This is an automated email from the ASF dual-hosted git repository. awasum pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract-cn-reporting.git
commit bf26ed8722e81f105fee93d24d9b80f16460d8f6 Author: mgeiss <[email protected]> AuthorDate: Fri Jun 30 22:51:43 2017 +0200 added first report defition --- .../AbstractReportingSpecificationTest.java | 117 ++++++++++++++++++++ .../TestCustomerListReportSpecification.java | 27 ++--- component-test/src/main/resources/logback-test.xml | 37 +------ .../reporting/service/ReportingConfiguration.java | 5 +- .../provider/ReportSpecificationProvider.java | 95 ++++++++++++++++ .../CustomerListReportSpecification.java | 120 +++++++++++++++++++++ .../service/rest/ReportingRestController.java | 92 ++++++++++++++-- .../service/spi/DisplayableFieldBuilder.java | 49 +++++++++ .../service/spi/QueryParameterBuilder.java | 71 ++++++++++++ .../ReportingService.java => spi/Report.java} | 29 +++-- .../ReportSpecification.java} | 23 ++-- 11 files changed, 580 insertions(+), 85 deletions(-) diff --git a/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java new file mode 100644 index 0000000..47fc8a7 --- /dev/null +++ b/component-test/src/main/java/io/mifos/reporting/AbstractReportingSpecificationTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2017 The Mifos Initiative. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.mifos.reporting; + +import io.mifos.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule; +import io.mifos.core.api.context.AutoUserContext; +import io.mifos.core.lang.ApplicationName; +import io.mifos.core.test.env.TestEnvironment; +import io.mifos.core.test.fixture.TenantDataStoreContextTestRule; +import io.mifos.core.test.fixture.cassandra.CassandraInitializer; +import io.mifos.core.test.fixture.mariadb.MariaDBInitializer; +import io.mifos.reporting.api.v1.client.ReportManager; +import io.mifos.reporting.service.ReportingConfiguration; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.cloud.netflix.ribbon.RibbonClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; + +import java.security.interfaces.RSAPrivateKey; + +@RunWith(SpringRunner.class) +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, + classes = {AbstractReportingSpecificationTest.TestConfiguration.class} +) +public class AbstractReportingSpecificationTest { + private static final String APP_NAME = "reporting-v1"; + public static final String LOGGER_NAME = "test-logger"; + + @Configuration + @EnableFeignClients(basePackages = {"io.mifos.reporting.api.v1.client"}) + @RibbonClient(name = APP_NAME) + @Import({ReportingConfiguration.class}) + public static class TestConfiguration { + public TestConfiguration() { + super(); + } + + @Bean(name = LOGGER_NAME) + public Logger logger() { + return LoggerFactory.getLogger(LOGGER_NAME); + } + } + + static final String TEST_USER = "homer"; + + private final static TestEnvironment testEnvironment = new TestEnvironment(APP_NAME); + private final static CassandraInitializer cassandraInitializer = new CassandraInitializer(); + private final static MariaDBInitializer mariaDBInitializer = new MariaDBInitializer(); + final static TenantDataStoreContextTestRule tenantDataStoreContext = TenantDataStoreContextTestRule.forRandomTenantName(cassandraInitializer, mariaDBInitializer); + + @ClassRule + public static TestRule orderClassRules = RuleChain + .outerRule(testEnvironment) + .around(cassandraInitializer) + .around(mariaDBInitializer) + .around(tenantDataStoreContext); + + @Rule + public final TenantApplicationSecurityEnvironmentTestRule tenantApplicationSecurityEnvironment + = new TenantApplicationSecurityEnvironmentTestRule(testEnvironment, this::waitForInitialize); + + private AutoUserContext userContext; + + @Autowired + ReportManager testSubject; + + @Autowired + private ApplicationName applicationName; + + @Autowired + @Qualifier(LOGGER_NAME) + Logger logger; + + @Before + public void prepTest() { + userContext = tenantApplicationSecurityEnvironment.createAutoUserContext(TEST_USER); + final RSAPrivateKey tenantPrivateKey = tenantApplicationSecurityEnvironment.getSystemSecurityEnvironment().tenantPrivateKey(); + logger.info("tenantPrivateKey = {}", tenantPrivateKey); + } + + @After + public void cleanTest() { + userContext.close(); + } + + boolean waitForInitialize() { + return true; + } +} diff --git a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java b/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java similarity index 50% copy from service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java copy to component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java index 620dff3..dfabeaf 100644 --- a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java +++ b/component-test/src/main/java/io/mifos/reporting/TestCustomerListReportSpecification.java @@ -13,22 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.mifos.reporting.service.internal.service; +package io.mifos.reporting; -import io.mifos.reporting.service.ServiceConstants; -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; +import io.mifos.reporting.api.v1.domain.ReportDefinition; +import org.junit.Assert; +import org.junit.Test; -@Service -public class ReportingService { +import java.util.List; - private final Logger logger; +public class TestCustomerListReportSpecification extends AbstractReportingSpecificationTest { - @Autowired - public ReportingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) { + public TestCustomerListReportSpecification() { super(); - this.logger = logger; + } + + @Test + public void shouldReturnReportDefinition() { + final List<ReportDefinition> reportDefinitions = super.testSubject.fetchReportDefinitions("Customer"); + Assert.assertTrue( + reportDefinitions.stream().anyMatch(reportDefinition -> reportDefinition.getIdentifier().equals("Listing")) + ); } } diff --git a/component-test/src/main/resources/logback-test.xml b/component-test/src/main/resources/logback-test.xml index 2473b99..735b8e5 100644 --- a/component-test/src/main/resources/logback-test.xml +++ b/component-test/src/main/resources/logback-test.xml @@ -16,44 +16,17 @@ --> <configuration> - <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <file>logs/reporting.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/archive/reporting.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>7</maxHistory> - <totalSizeCap>2GB</totalSizeCap> - </rollingPolicy> - <encoder> - <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> - <logger name="com" level="INFO"> - <appender-ref ref="STDOUT" /> - </logger> - - <logger name="ch" level="INFO"> - <appender-ref ref="STDOUT" /> - </logger> - - <logger name="org" level="INFO"> - <appender-ref ref="STDOUT" /> - </logger> - - <logger name="io" level="DEBUG"> - <appender-ref ref="STDOUT" /> - </logger> - - <logger name="net" level="INFO"> - <appender-ref ref="STDOUT" /> - </logger> + <logger name="org" level="ERROR"/> + <logger name="com" level="OFF"/> + <logger name="ch" level="OFF"/> - <root level="WARN"> - <appender-ref ref="FILE"/> + <root level="DEBUG"> + <appender-ref ref="STDOUT"/> </root> </configuration> \ No newline at end of file diff --git a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java index 58dd263..f0ab979 100644 --- a/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java +++ b/service/src/main/java/io/mifos/reporting/service/ReportingConfiguration.java @@ -42,9 +42,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter @EnableServiceException @ComponentScan({ "io.mifos.reporting.service.rest", - "io.mifos.reporting.service.internal.service", - "io.mifos.reporting.service.repository", - "io.mifos.reporting.service.internal.provider" + "io.mifos.reporting.service.internal", + "io.mifos.reporting.service.repository" }) @EnableJpaRepositories({ "io.mifos.reporting.service.repository" diff --git a/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java new file mode 100644 index 0000000..7ef4871 --- /dev/null +++ b/service/src/main/java/io/mifos/reporting/service/internal/provider/ReportSpecificationProvider.java @@ -0,0 +1,95 @@ +/* + * Copyright 2017 The Mifos Initiative. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.mifos.reporting.service.internal.provider; + +import io.mifos.reporting.api.v1.domain.ReportDefinition; +import io.mifos.reporting.service.ServiceConstants; +import io.mifos.reporting.service.spi.Report; +import io.mifos.reporting.service.spi.ReportSpecification; +import org.slf4j.Logger; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) +public class ReportSpecificationProvider implements ApplicationContextAware { + + private final Logger logger; + private final HashMap<String, ReportSpecification> reportSpecificationCache = new HashMap<>(); + private final HashMap<String, List<ReportDefinition>> reportCategoryCache = new HashMap<>(); + + private ApplicationContext applicationContext; + + @Autowired + public ReportSpecificationProvider(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) { + super(); + this.logger = logger; + } + + @Override + public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + this.initialize(); + } + + public List<String> getAvailableCategories() { + return new ArrayList<>(this.reportCategoryCache.keySet()); + } + + public List<ReportDefinition> getAvailableReports(final String category) { + this.logger.debug("Looking up report definitions for category {}.", category); + return this.reportCategoryCache.getOrDefault(category, Collections.emptyList()); + } + + public Optional<ReportSpecification> getReportSpecification(final String category, final String identifier) { + final String keyForReportSpecificationCache = this.buildKeyForSpecificationCache(category, identifier); + this.logger.debug("Looking up report specification for {}.", keyForReportSpecificationCache); + return Optional.ofNullable(this.reportSpecificationCache.get(keyForReportSpecificationCache)); + } + + private void initialize() { + final Map<String, Object> beansWithAnnotation = this.applicationContext.getBeansWithAnnotation(Report.class); + + beansWithAnnotation.values().forEach(bean -> { + final ReportSpecification reportSpecification = ReportSpecification.class.cast(bean); + final Report report = reportSpecification.getClass().getAnnotation(Report.class); + final String keyForReportSpecificationCache = + this.buildKeyForSpecificationCache(report.category(), report.identifier()); + this.logger.debug("Adding report specification for {}", keyForReportSpecificationCache); + + this.reportCategoryCache.computeIfAbsent(report.category(), (key) -> new ArrayList<>()); + this.reportCategoryCache.get(report.category()).add(reportSpecification.getReportDefinition()); + this.reportSpecificationCache.put(keyForReportSpecificationCache, reportSpecification); + }); + } + + private String buildKeyForSpecificationCache(final String category, final String identifier) { + return category + "~" + identifier; + } +} diff --git a/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java new file mode 100644 index 0000000..b166b53 --- /dev/null +++ b/service/src/main/java/io/mifos/reporting/service/internal/specification/CustomerListReportSpecification.java @@ -0,0 +1,120 @@ +/* + * Copyright 2017 The Mifos Initiative. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.mifos.reporting.service.internal.specification; + +import io.mifos.reporting.api.v1.domain.DisplayableField; +import io.mifos.reporting.api.v1.domain.QueryParameter; +import io.mifos.reporting.api.v1.domain.ReportDefinition; +import io.mifos.reporting.api.v1.domain.ReportPage; +import io.mifos.reporting.api.v1.domain.ReportRequest; +import io.mifos.reporting.api.v1.domain.Type; +import io.mifos.reporting.service.ServiceConstants; +import io.mifos.reporting.service.spi.DisplayableFieldBuilder; +import io.mifos.reporting.service.spi.QueryParameterBuilder; +import io.mifos.reporting.service.spi.Report; +import io.mifos.reporting.service.spi.ReportSpecification; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +@Report(category = "Customer", identifier = "Listing") +public class CustomerListReportSpecification implements ReportSpecification { + + private final Logger logger; + private final HashMap<String, String> columnMapping = new HashMap<>(); + + @Autowired + public CustomerListReportSpecification(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) { + super(); + this.logger = logger; + this.initializeMapping(); + } + + @Override + public ReportDefinition getReportDefinition() { + final ReportDefinition reportDefinition = new ReportDefinition(); + reportDefinition.setIdentifier("Listing"); + reportDefinition.setName("Customer Listing"); + reportDefinition.setDescription("List of all customers."); + reportDefinition.setQueryParameters(this.buildQueryParameters()); + reportDefinition.setDisplayableFields(this.buildDisplayableFields()); + return reportDefinition; + } + + @Override + public ReportPage generateReport(final ReportRequest reportRequest) { + return null; + } + + @Override + public void validate(final ReportRequest reportRequest) throws IllegalArgumentException { + final ArrayList<String> unknownFields = new ArrayList<>(); + reportRequest.getQueryParameters().forEach(queryParameter -> { + if (!this.columnMapping.keySet().contains(queryParameter.getName())) { + unknownFields.add(queryParameter.getName()); + } + }); + + reportRequest.getDisplayableFields().forEach(displayableField -> { + if (!this.columnMapping.keySet().contains(displayableField.getName())) { + unknownFields.add(displayableField.getName()); + } + }); + + if (!unknownFields.isEmpty()) { + throw new IllegalArgumentException( + "Unspecified fields requested: " + unknownFields.stream().collect(Collectors.joining(", ")) + ); + } + } + + private void initializeMapping() { + this.columnMapping.put("Date Range", "createdBy"); + this.columnMapping.put("State", "currentState"); + this.columnMapping.put("Customer", "identifier"); + this.columnMapping.put("Account number", "identifier"); + this.columnMapping.put("First name", "givenName"); + this.columnMapping.put("Middle Name", "middleName"); + this.columnMapping.put("Last Name", "surname"); + this.columnMapping.put("Balance", "balance"); + this.columnMapping.put("Address", "address"); + } + + private List<QueryParameter> buildQueryParameters() { + return Arrays.asList( + QueryParameterBuilder.create("Date range", Type.DATE).operator(QueryParameter.Operator.BETWEEN).build(), + QueryParameterBuilder.create("State", Type.TEXT).operator(QueryParameter.Operator.IN).build() + ); + } + + private List<DisplayableField> buildDisplayableFields() { + return Arrays.asList( + DisplayableFieldBuilder.create("Customer", Type.TEXT).mandatory().build(), + DisplayableFieldBuilder.create("First name", Type.TEXT).build(), + DisplayableFieldBuilder.create("Middle name", Type.TEXT).build(), + DisplayableFieldBuilder.create("Last name", Type.TEXT).build(), + DisplayableFieldBuilder.create("Account number", Type.TEXT).mandatory().build(), + DisplayableFieldBuilder.create("Balance", Type.NUMBER).build(), + DisplayableFieldBuilder.create("Address", Type.TEXT).build() + ); + } +} diff --git a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java index d639ae7..16307c5 100644 --- a/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java +++ b/service/src/main/java/io/mifos/reporting/service/rest/ReportingRestController.java @@ -17,15 +17,28 @@ package io.mifos.reporting.service.rest; import io.mifos.anubis.annotation.AcceptedTokenType; import io.mifos.anubis.annotation.Permittable; -import io.mifos.core.command.gateway.CommandGateway; +import io.mifos.core.lang.ServiceException; +import io.mifos.reporting.api.v1.domain.ReportDefinition; +import io.mifos.reporting.api.v1.domain.ReportPage; +import io.mifos.reporting.api.v1.domain.ReportRequest; import io.mifos.reporting.service.ServiceConstants; -import io.mifos.reporting.service.internal.service.ReportingService; +import io.mifos.reporting.service.internal.provider.ReportSpecificationProvider; +import io.mifos.reporting.service.spi.ReportSpecification; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Optional; @SuppressWarnings("unused") @RestController @@ -33,16 +46,77 @@ import org.springframework.web.bind.annotation.*; public class ReportingRestController { private final Logger logger; - private final CommandGateway commandGateway; - private final ReportingService reportingService; + private final ReportSpecificationProvider reportSpecificationProvider; @Autowired public ReportingRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger, - final CommandGateway commandGateway, - final ReportingService reportingService) { + final ReportSpecificationProvider reportSpecificationProvider) { super(); this.logger = logger; - this.commandGateway = commandGateway; - this.reportingService = reportingService; + this.reportSpecificationProvider = reportSpecificationProvider; + } + + @Permittable(value = AcceptedTokenType.SYSTEM) + @RequestMapping( + value = "/initialize", + method = RequestMethod.POST, + consumes = MediaType.ALL_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE + ) + public + @ResponseBody + ResponseEntity<Void> initialize() { + return ResponseEntity.accepted().build(); + } + + @RequestMapping( + value = "/categories", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.ALL_VALUE + ) + public + ResponseEntity<List<String>> fetchCategories() { + return ResponseEntity.ok(this.reportSpecificationProvider.getAvailableCategories()); + } + + @RequestMapping( + value = "categories/{category}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.ALL_VALUE) + public + ResponseEntity<List<ReportDefinition>> fetchReportDefinitions(@PathVariable("category") final String category) { + return ResponseEntity.ok(this.reportSpecificationProvider.getAvailableReports(category)); + } + + @RequestMapping( + value = "/categories/{category}/reports/{identifier}", + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) + public + ResponseEntity<ReportPage> generateReport(@PathVariable("category") final String category, + @PathVariable("identifier") final String identifier, + @RequestBody final ReportRequest reportRequest, + @RequestParam(value = "pageIndex", required = false) final Integer pageIndex, + @RequestParam(value = "size", required = false) final Integer size) { + + final Optional<ReportSpecification> optionalReportSpecification = + this.reportSpecificationProvider.getReportSpecification(category, identifier); + if (optionalReportSpecification.isPresent()) { + final ReportSpecification reportSpecification = optionalReportSpecification.get(); + + try { + reportSpecification.validate(reportRequest); + } catch (final IllegalArgumentException iaex) { + throw ServiceException.badRequest(iaex.getMessage()); + } + + return ResponseEntity.ok(reportSpecification.generateReport(reportRequest)); + } else { + throw ServiceException.notFound("Report {0} not found.", identifier); + } } } diff --git a/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java new file mode 100644 index 0000000..987ad9b --- /dev/null +++ b/service/src/main/java/io/mifos/reporting/service/spi/DisplayableFieldBuilder.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017 The Mifos Initiative. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.mifos.reporting.service.spi; + +import io.mifos.reporting.api.v1.domain.DisplayableField; +import io.mifos.reporting.api.v1.domain.Type; + +public class DisplayableFieldBuilder { + + private String name; + private Type type; + private Boolean mandatory; + + private DisplayableFieldBuilder(final String name, final Type type) { + super(); + this.name = name; + this.type = type; + } + + public static DisplayableFieldBuilder create(final String name, final Type type) { + return new DisplayableFieldBuilder(name, type); + } + + public DisplayableFieldBuilder mandatory() { + this.mandatory = Boolean.TRUE; + return this; + } + + public DisplayableField build() { + final DisplayableField displayableField = new DisplayableField(); + displayableField.setName(this.name); + displayableField.setType(this.type); + displayableField.setMandatory(this.mandatory != null ? this.mandatory : Boolean.FALSE); + return displayableField; + } +} diff --git a/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java b/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java new file mode 100644 index 0000000..00251f3 --- /dev/null +++ b/service/src/main/java/io/mifos/reporting/service/spi/QueryParameterBuilder.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017 The Mifos Initiative. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.mifos.reporting.service.spi; + +import io.mifos.reporting.api.v1.domain.AutoCompleteResource; +import io.mifos.reporting.api.v1.domain.QueryParameter; +import io.mifos.reporting.api.v1.domain.Type; + +import java.util.Arrays; + +public class QueryParameterBuilder { + + private String name; + private Type type; + private QueryParameter.Operator operator; + private Boolean mandatory; + private AutoCompleteResource autoCompleteResource; + + private QueryParameter queryParameter; + + private QueryParameterBuilder(final String name, final Type type) { + super(); + this.name = name; + this.type = type; + } + + public static QueryParameterBuilder create(final String name, final Type type) { + return new QueryParameterBuilder(name, type); + } + + public QueryParameterBuilder operator(final QueryParameter.Operator operator) { + this.operator = operator; + return this; + } + + public QueryParameterBuilder mandatory() { + this.mandatory = Boolean.TRUE; + return this; + } + + public QueryParameterBuilder autoComplete(final String path, final String... terms) { + final AutoCompleteResource autoCompleteResource = new AutoCompleteResource(); + autoCompleteResource.setPath(path); + autoCompleteResource.setTerms(Arrays.asList(terms)); + this.autoCompleteResource = autoCompleteResource; + return this; + } + + public QueryParameter build() { + final QueryParameter queryParameter = new QueryParameter(); + queryParameter.setName(this.name); + queryParameter.setType(this.type); + queryParameter.setOperator(this.operator != null ? this.operator : QueryParameter.Operator.EQUALS); + queryParameter.setMandatory(this.mandatory != null ? this.mandatory : Boolean.FALSE); + queryParameter.setAutoCompleteResource(this.autoCompleteResource); + return queryParameter; + } +} diff --git a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java b/service/src/main/java/io/mifos/reporting/service/spi/Report.java similarity index 53% copy from service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java copy to service/src/main/java/io/mifos/reporting/service/spi/Report.java index 620dff3..ec40ec8 100644 --- a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java +++ b/service/src/main/java/io/mifos/reporting/service/spi/Report.java @@ -13,22 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.mifos.reporting.service.internal.service; +package io.mifos.reporting.service.spi; -import io.mifos.reporting.service.ServiceConstants; -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; +import org.springframework.stereotype.Component; -@Service -public class ReportingService { +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; - private final Logger logger; - - @Autowired - public ReportingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) { - super(); - this.logger = logger; - } +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +@Component +public @interface Report { + String category(); + String identifier(); } diff --git a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java similarity index 53% rename from service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java rename to service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java index 620dff3..3502b94 100644 --- a/service/src/main/java/io/mifos/reporting/service/internal/service/ReportingService.java +++ b/service/src/main/java/io/mifos/reporting/service/spi/ReportSpecification.java @@ -13,22 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.mifos.reporting.service.internal.service; +package io.mifos.reporting.service.spi; -import io.mifos.reporting.service.ServiceConstants; -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; +import io.mifos.reporting.api.v1.domain.ReportDefinition; +import io.mifos.reporting.api.v1.domain.ReportPage; +import io.mifos.reporting.api.v1.domain.ReportRequest; -@Service -public class ReportingService { +public interface ReportSpecification { - private final Logger logger; + ReportDefinition getReportDefinition(); - @Autowired - public ReportingService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) { - super(); - this.logger = logger; - } + ReportPage generateReport(final ReportRequest reportRequest); + + void validate(final ReportRequest reportRequest) throws IllegalArgumentException; }
