test_class.declarator: pairService
test_class.modifier: @Autowired
  	private
test_class.original_string: @Autowired
  	private PairService pairService;
test_class.type: PairService
test_class.var_name: pairService
test_class.declarator: rateService
test_class.modifier: @Autowired
  	private
test_class.original_string: @Autowired
  	private RateService rateService;
test_class.type: RateService
test_class.var_name: rateService
test_class.declarator: lookupService
test_class.modifier: @MockBean
  	private
test_class.original_string: @MockBean
  	private LookupService lookupService;
test_class.type: LookupService
test_class.var_name: lookupService
test_class.declarator: rateProviderService
test_class.modifier: @MockBean
  	private
test_class.original_string: @MockBean
  	private RateProviderService rateProviderService;
test_class.type: RateProviderService
test_class.var_name: rateProviderService
test_class.declarator: adminService
test_class.modifier: @Autowired
  	private
test_class.original_string: @Autowired
  	private AdminService adminService;
test_class.type: AdminService
test_class.var_name: adminService
test_class.declarator: hRateRepo
test_class.modifier: @Autowired
  	private
test_class.original_string: @Autowired
  	private HistoricalRateRepository hRateRepo;
test_class.type: HistoricalRateRepository
test_class.var_name: hRateRepo
test_class.declarator: hrp
test_class.modifier: @Mock
  	private
test_class.original_string: @Mock
  	private HistoricalRateProvider hrp;
test_class.type: HistoricalRateProvider
test_class.var_name: hrp
test_class.declarator: lrp
test_class.modifier: @Mock
  	private
test_class.original_string: @Mock
  	private LatestRateProvider lrp;
test_class.type: LatestRateProvider
test_class.var_name: lrp
test_class.file: trading-common/src/test/java/fr/ymanvieu/trading/common/admin/AdminServiceTest.java
test_class.identifier: AdminServiceTest
test_case.body: @Sql("/sql/insert_data.sql")
  	@Test
  	public void testAdd_alreadyExistsAsCurrency() throws Exception {
  		// given
  		String symbol = "EURUSD=X";
  		String name = "EUR/USD";
  		String provider = "Provider";
  		
  		when(lookupService.getDetails(symbol, provider)).thenReturn(new LookupDetails(symbol, name, "EUR", "USD", "CY", provider));
  		
  		// when
  		assertThatThrownBy(() -> adminService.add(symbol, provider))
  		.isInstanceOf(AdminException.class)
  		.hasMessage("admin.error.currency-already-exists: [EUR]");
  	}
test_case.class_method_signature: AdminServiceTest.testAdd_alreadyExistsAsCurrency()
test_case.full_signature: @Sql("/sql/insert_data.sql") @Test public void testAdd_alreadyExistsAsCurrency()
test_case.identifier: testAdd_alreadyExistsAsCurrency
test_case.invocations: thenReturn when getDetails hasMessage isInstanceOf assertThatThrownBy add
test_case.modifiers: @Sql("/sql/insert_data.sql") @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void testAdd_alreadyExistsAsCurrency()
focal_class.declarator: symbolService
focal_class.modifier: @Autowired
  	private
focal_class.original_string: @Autowired
  	private SymbolService symbolService;
focal_class.type: SymbolService
focal_class.var_name: symbolService
focal_class.declarator: pairService
focal_class.modifier: @Autowired
  	private
focal_class.original_string: @Autowired
  	private PairService pairService;
focal_class.type: PairService
focal_class.var_name: pairService
focal_class.declarator: rateService
focal_class.modifier: @Autowired
  	private
focal_class.original_string: @Autowired
  	private RateService rateService;
focal_class.type: RateService
focal_class.var_name: rateService
focal_class.declarator: rateProviderService
focal_class.modifier: @Autowired
  	private
focal_class.original_string: @Autowired
  	private RateProviderService rateProviderService;
focal_class.type: RateProviderService
focal_class.var_name: rateProviderService
focal_class.declarator: lookupService
focal_class.modifier: @Autowired
  	private
focal_class.original_string: @Autowired
  	private LookupService lookupService;
focal_class.type: LookupService
focal_class.var_name: lookupService
focal_class.file: trading-common/src/main/java/fr/ymanvieu/trading/common/admin/AdminService.java
focal_class.identifier: AdminService
focal_class.class_method_signature: AdminService.add(String code, String provider)
focal_class.full_signature: public SymbolInfo add(String code, String provider)
focal_class.identifier: add
focal_class.modifiers: public
focal_class.parameters: (String code, String provider)
focal_class.return: SymbolInfo
focal_class.signature: SymbolInfo add(String code, String provider)
focal_class.class_method_signature: AdminService.delete(String code, String provider)
focal_class.full_signature: public void delete(String code, String provider)
focal_class.identifier: delete
focal_class.modifiers: public
focal_class.parameters: (String code, String provider)
focal_class.return: void
focal_class.signature: void delete(String code, String provider)
focal_class.class_method_signature: AdminService.search(String symbolOrName)
focal_class.full_signature: public SearchResult search(String symbolOrName)
focal_class.identifier: search
focal_class.modifiers: public
focal_class.parameters: (String symbolOrName)
focal_class.return: SearchResult
focal_class.signature: SearchResult search(String symbolOrName)
focal_class.class_method_signature: AdminService.removeDuplicates(List<LookupInfo> availableSymbols, List<UpdatedPair> existingSymbols)
focal_class.full_signature: private void removeDuplicates(List<LookupInfo> availableSymbols, List<UpdatedPair> existingSymbols)
focal_class.identifier: removeDuplicates
focal_class.modifiers: private
focal_class.parameters: (List<LookupInfo> availableSymbols, List<UpdatedPair> existingSymbols)
focal_class.return: void
focal_class.signature: void removeDuplicates(List<LookupInfo> availableSymbols, List<UpdatedPair> existingSymbols)
focal_method.body: public SymbolInfo add(String code, String provider) throws IOException {
  		Stopwatch sw = Stopwatch.createStarted();
  
  		Pair pair = pairService.getForCodeAndProvider(code, provider);
  
  		if (pair != null) {
  			throw PairException.alreadyExists(pair.getSymbol(), provider);
  		}
  
  		LookupDetails details = lookupService.getDetails(code, provider);
  
  		String source = details.getSource();
  		String currency = details.getCurrency();
  		String name = details.getName();
  		String exchange = details.getExchange();
  
  		// check if currency exists
  		if (!symbolService.getForCodeWithNoCurrency(currency).isPresent()) {
  			throw PairException.currencyNotFound(currency);
  		}
  
  		Optional<Symbol> sourceSymbol = symbolService.getForCode(source);
  
  		if(sourceSymbol.isPresent()) {
  			if(sourceSymbol.get().getCurrency() == null) {
  				throw AdminException.currencyAlreadyExists(source);
  			}
  		} else {
  			symbolService.addSymbol(source, name, null, currency);
  		}
  
  		pair = pairService.create(code, name, source, currency, exchange, provider);
  
  		final LatestRateProvider rProvider = rateProviderService.getLatestProvider(ProviderType.STOCK);
  
  		Quote latestQuote = rProvider.getLatestRate(code);
  
  		if (latestQuote == null) {
  			throw SymbolException.UNAVAILABLE(code);
  		}
  
  		// TODO immutability ! copy data
  		latestQuote.setCode(source);
  		latestQuote.setCurrency(currency);
  
  		List<Quote> historicalQuotes = new ArrayList<>();
  
  		final HistoricalRateProvider hRProvider = rateProviderService.getHistoricalProvider(ProviderType.STOCK);
  
  		try {
  			historicalQuotes.addAll(hRProvider.getHistoricalRates(code));
  		} catch (IOException | RuntimeException e) {
  			// generally, if provider cannot get historical data, it throws exception
  			log.warn("Cannot get historical data for: {} (provider: {})", code, provider);
  		}
  
  		for (Quote q : historicalQuotes) {
  			q.setCode(source);
  			q.setCurrency(currency);
  		}
  
  		historicalQuotes.removeIf(q -> q.getTime().compareTo(latestQuote.getTime()) == 0);
  		
  		historicalQuotes.add(latestQuote);
  
  		rateService.addHistoricalRates(historicalQuotes);
  		rateService.addLatestRate(latestQuote);
  
  		log.info("{} created in: {}", pair, sw);
  
  		return new SymbolInfo(pair.getSymbol(), pair.getName(), !historicalQuotes.isEmpty(), latestQuote);
  	}
focal_method.class_method_signature: AdminService.add(String code, String provider)
focal_method.full_signature: public SymbolInfo add(String code, String provider)
focal_method.identifier: add
focal_method.invocations: createStarted getForCodeAndProvider alreadyExists getSymbol getDetails getSource getCurrency getName getExchange isPresent getForCodeWithNoCurrency currencyNotFound getForCode isPresent getCurrency get currencyAlreadyExists addSymbol create getLatestProvider getLatestRate UNAVAILABLE setCode setCurrency getHistoricalProvider addAll getHistoricalRates warn setCode setCurrency removeIf compareTo getTime getTime add addHistoricalRates addLatestRate info getSymbol getName isEmpty
focal_method.modifiers: public
focal_method.parameters: (String code, String provider)
focal_method.return: SymbolInfo
focal_method.signature: SymbolInfo add(String code, String provider)