MIFOSX-117: integrate andreas work on UGD.

This commit is contained in:
Keith Woodlock
2013-09-21 13:28:59 +01:00
parent 01368e59b2
commit c607c9bba5
33 changed files with 1602 additions and 24 deletions
+1
View File
@@ -20,3 +20,4 @@ rebel.xml
*.DS_Store
*.ini
*~
.metadata
@@ -0,0 +1,34 @@
DROP TABLE IF EXISTS `m_template`;
CREATE TABLE `m_template` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`text` longtext COLLATE utf8_unicode_ci NOT NULL,
`entity` int(11) DEFAULT NULL,
`type` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unq_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `m_templatemappers`;
CREATE TABLE `m_templatemappers` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`mapperkey` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`mapperorder` int(11) DEFAULT NULL,
`mappervalue` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `m_template_m_templatemappers`;
CREATE TABLE `m_template_m_templatemappers` (
`m_template_id` bigint(20) NOT NULL,
`mappers_id` bigint(20) NOT NULL,
UNIQUE KEY `mappers_id` (`mappers_id`),
KEY (`mappers_id`),
KEY (`m_template_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
VALUES ('organistion', 'DELETE_TEMPLATE', 'TEMPLATE', 'DELETE', 0),
('organistion', 'CREATE_TEMPLATE', 'TEMPLATE', 'CREATE', 0),
('organistion', 'UPDATE_TEMPLATE', 'TEMPLATE', 'UPDATE', 0),
('organistion', 'READ_TEMPLATE', 'TEMPLATE', 'READ', 0);
+3 -2
View File
@@ -99,6 +99,7 @@ dependencies {
[group: 'org.springframework', name: 'spring-core', version: springVersion],
[group: 'org.springframework', name: 'spring-aspects', version: springVersion],
[group: 'org.springframework', name: 'spring-web', version: springVersion],
[group: 'org.springframework', name: 'spring-test', version: springVersion],
[group: 'org.springframework.security', name: 'spring-security-core', version: springSecurityVersion],
[group: 'org.springframework.security', name: 'spring-security-web', version: springSecurityVersion],
[group: 'org.springframework.security', name: 'spring-security-config', version: springSecurityVersion],
@@ -162,8 +163,8 @@ dependencies {
[group: 'com.googlecode.flyway', name: 'flyway-maven-plugin', version: '2.1.1'],
[group: 'org.quartz-scheduler', name: 'quartz', version: '2.1.7'],
[group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.2.1'],
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2']
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2'],
[group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.8.12']
)
testCompile 'junit:junit:4.10',
@@ -0,0 +1,64 @@
package org.mifosplatform.integrationtests;
import java.util.ArrayList;
import java.util.HashMap;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mifosplatform.integrationtests.common.Utils;
import com.google.gson.Gson;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
public class TemplateIntegrationTest {
private final String GET_TEMPLATES_URL = "/mifosng-provider/api/v1/templates?tenantIdentifier=default";
private final String GET_TEMPLATE_ID_URL = "/mifosng-provider/api/v1/templates/%s?tenantIdentifier=default";
private final String RESPONSE_ATTRIBUTE_NAME = "name";
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
@Before
public void setup() {
Utils.initializeRESTAssured();
requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
}
@Test
public void test() {
HashMap<String, String> metadata = new HashMap<String, String>();
metadata.put("user", "resource_url");
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("name", "foo");
map.put("text", "Hello {{template}}");
map.put("mappers", metadata);
ArrayList<?> get = Utils.performServerGet(requestSpec, responseSpec, GET_TEMPLATES_URL, "");
int entriesBeforeTest = get.size();
Integer id = Utils.performServerPost(requestSpec, responseSpec, GET_TEMPLATES_URL, new Gson().toJson(map), "resourceId");
String templateUrlForId = String.format(GET_TEMPLATE_ID_URL, id);
String getrequest2 = Utils.performServerGet(requestSpec, responseSpec, templateUrlForId, RESPONSE_ATTRIBUTE_NAME);
Assert.assertTrue(getrequest2.equals("foo"));
Utils.performServerDelete(requestSpec, responseSpec, templateUrlForId, "");
get = Utils.performServerGet(requestSpec, responseSpec, GET_TEMPLATES_URL, "");
int entriesAfterTest = get.size();
Assert.assertEquals(entriesBeforeTest, entriesAfterTest);
}
}
@@ -26,6 +26,7 @@ public class CommandWrapper {
private final String supportedEntityType;
private final Long supportedEntityId;
private final Long productId;
private Long templateId;
public static CommandWrapper wrap(final String actionName, final String entityName, final Long resourceId, final Long subresourceId) {
return new CommandWrapper(null, actionName, entityName, resourceId, subresourceId, null, null);
@@ -56,13 +57,12 @@ public class CommandWrapper {
this.json = null;
this.transactionId = null;
this.productId = productId;
}
public CommandWrapper(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
final String actionName, final String entityName, final Long entityId, final Long subentityId, final Long codeId,
final String supportedEntityType, final Long supportedEntityId, final String href, final String json,
final String transactionId, final Long productId) {
final String transactionId, final Long productId, final Long templateId) {
this.commandId = null;
this.officeId = officeId;
this.groupId = groupId;
@@ -81,6 +81,7 @@ public class CommandWrapper {
this.json = json;
this.transactionId = transactionId;
this.productId = productId;
this.templateId = templateId;
}
public Long commandId() {
@@ -142,6 +143,10 @@ public class CommandWrapper {
public String getTransactionId() {
return this.transactionId;
}
public Long getTemplateId() {
return this.templateId;
}
public String getEntityName() {
return this.entityName;
@@ -320,6 +325,10 @@ public class CommandWrapper {
public boolean isCollateralResource() {
return this.entityName.equalsIgnoreCase("COLLATERAL");
}
public boolean isTemplateRessource() {
return this.entityName.equalsIgnoreCase("Template");
}
public boolean isApproveLoanApplication() {
return this.actionName.equalsIgnoreCase("APPROVE") && this.entityName.equalsIgnoreCase("LOAN");
@@ -26,11 +26,12 @@ public class CommandWrapperBuilder {
private String supportedEntityType;
private Long supportedEntityId;
private Long productId;
private Long templateId;
public CommandWrapper build() {
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName,
this.entityName, this.entityId, this.subentityId, this.codeId, this.supportedEntityType, this.supportedEntityId, this.href,
this.json, this.transactionId, this.productId);
this.json, this.transactionId, this.productId, this.templateId);
}
public CommandWrapperBuilder withLoanId(final Long withLoanId) {
@@ -1305,6 +1306,33 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder createTemplate() {
this.actionName = "CREATE";
this.entityName = "TEMPLATE";
this.entityId = null;
this.templateId = null;
this.href = "/templates";
return this;
}
public CommandWrapperBuilder updateTemplate(final Long templateId) {
this.actionName = "UPDATE";
this.entityName = "TEMPLATE";
this.entityId = templateId;
this.templateId = templateId;
this.href = "/templates/" + templateId;
return this;
}
public CommandWrapperBuilder deleteTemplate(final Long templateId) {
this.actionName = "DELETE";
this.entityName = "TEMPLATE";
this.entityId = templateId;
this.templateId = templateId;
this.href = "/templates/" + templateId;
return this;
}
public CommandWrapperBuilder assignClientStaff(final Long clientId) {
this.actionName = "ASSIGNSTAFF";
this.entityName = "CLIENT";
@@ -144,7 +144,6 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isClientIdentifierResource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createClientIdentifierCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
@@ -501,15 +500,12 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isCollectionSheetResource()) {
if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isReportResource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createReportCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
@@ -519,9 +515,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isAccountingRuleResource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createAccountingRuleCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
@@ -531,7 +525,6 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isXBRLMappingResource()) {
if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateTaxonomyMappingCommandHandler", NewCommandSourceHandler.class);
@@ -539,7 +532,6 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isHolidayResource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createHolidayCommandHandler", NewCommandSourceHandler.class);
}
@@ -577,6 +569,29 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isTemplateRessource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createTemplateCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateTemplateCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDelete()) {
handler = this.applicationContext.getBean("deleteTemplateCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isTemplateRessource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createTemplateCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateTemplateCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDelete()) {
handler = this.applicationContext.getBean("deleteTemplateCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else {
throw new UnsupportedCommandException(wrapper.commandName());
@@ -584,4 +599,4 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
return handler;
}
}
}
@@ -10,6 +10,7 @@ import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.ObjectUtils;
@@ -23,6 +24,7 @@ import org.mifosplatform.infrastructure.security.service.PlatformPasswordEncoder
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Immutable representation of a command.
@@ -314,6 +316,12 @@ public final class JsonCommand {
return this.fromApiJsonHelper.extractStringNamed(parameterName, this.parsedCommand);
}
public Map<String, String> mapValueOfParameterNamed(final String json) {
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
final Map<String, String> value = this.fromApiJsonHelper.extractDataMap(typeOfMap, json);
return value;
}
public boolean isChangeInBigDecimalParameterNamedDefaultingZeroToNull(final String parameterName, final BigDecimal existingValue) {
boolean isChanged = false;
if (parameterExists(parameterName)) {
@@ -0,0 +1,206 @@
package org.mifosplatform.template.api;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.codehaus.jackson.map.ObjectMapper;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.template.data.TemplateData;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateEntity;
import org.mifosplatform.template.domain.TemplateType;
import org.mifosplatform.template.service.TemplateDomainService;
import org.mifosplatform.template.service.TemplateMergeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/templates")
@Component
@Scope("singleton")
public class TemplatesApiResource {
private final Set<String> RESPONSE_TEMPLATES_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id"));
private final Set<String> RESPONSE_TEMPLATE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "entities", "types", "template"));
private final String RESOURCEN_NAME_FOR_PERMISSION = "template";
private final PlatformSecurityContext context;
private final DefaultToApiJsonSerializer<Template> toApiJsonSerializer;
private final DefaultToApiJsonSerializer<TemplateData> templateDataApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final TemplateDomainService templateService;
private final TemplateMergeService templateMergeService;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public TemplatesApiResource(final PlatformSecurityContext context, final DefaultToApiJsonSerializer<Template> toApiJsonSerializer,
final DefaultToApiJsonSerializer<TemplateData> templateDataApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final TemplateDomainService templateService, final TemplateMergeService templateMergeService,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.toApiJsonSerializer = toApiJsonSerializer;
this.templateDataApiJsonSerializer = templateDataApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.templateService = templateService;
this.templateMergeService = templateMergeService;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String getTemplates(@DefaultValue("-1") @QueryParam("typeId") final int typeId,
@DefaultValue("-1") @QueryParam("entityId") final int entityId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
List<Template> templates = new ArrayList<Template>();
if (typeId != -1 && entityId != -1) {
templates = this.templateService.getAllByEntityAndType(TemplateEntity.values()[entityId], TemplateType.values()[typeId]);
} else {
templates = this.templateService.getAll();
}
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, templates, this.RESPONSE_TEMPLATES_DATA_PARAMETERS);
}
@GET
@Path("template")
@Produces({ MediaType.APPLICATION_JSON })
public String getTemplatesByTemplate(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
final TemplateData templateData = TemplateData.template();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.templateDataApiJsonSerializer.serialize(settings, templateData, this.RESPONSE_TEMPLATES_DATA_PARAMETERS);
}
@GET
@Path("{templateId}")
@Produces({ MediaType.APPLICATION_JSON })
public String getTemplate(@PathParam("templateId") final Long templateId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
final Template template = this.templateService.getById(templateId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, template, this.RESPONSE_TEMPLATES_DATA_PARAMETERS);
}
@GET
@Path("{templateId}/template")
@Produces({ MediaType.APPLICATION_JSON })
public String getTemplateByTemplate(@PathParam("templateId") final Long templateId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.RESOURCEN_NAME_FOR_PERMISSION);
final TemplateData template = TemplateData.template(this.templateService.getById(templateId));
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
System.out.println("QUERY_PARAMETER: " + uriInfo.getQueryParameters());
System.out.println("SETTINGS: " + settings);
System.out.println("FOO: " + this.templateDataApiJsonSerializer.serialize(settings, template, this.RESPONSE_TEMPLATE_DATA_PARAMETERS));
return this.templateDataApiJsonSerializer.serialize(settings, template, this.RESPONSE_TEMPLATE_DATA_PARAMETERS);
}
@PUT
@Path("{templateId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String saveTemplate(@PathParam("templateId") final Long templateId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateTemplate(templateId).withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@DELETE
@Path("{templateId}")
@Produces({ MediaType.APPLICATION_JSON })
public String deleteTemplate(@PathParam("templateId") final Long templateId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteTemplate(templateId).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createTemplate(final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createTemplate().withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@POST
@Path("{templateId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.TEXT_HTML })
public String mergeTemplate(@PathParam("templateId") final Long templateId, @Context final UriInfo uriInfo,
final String apiRequestBodyAsJson) throws MalformedURLException, IOException {
final Template template = this.templateService.getById(templateId);
@SuppressWarnings("unchecked")
final
HashMap<String, Object> result = new ObjectMapper().readValue(apiRequestBodyAsJson, HashMap.class);
final MultivaluedMap<String, String> parameters = uriInfo.getQueryParameters();
final Map<String, Object> parametersMap = new HashMap<String, Object>();
for (final Map.Entry<String, List<String>> entry : parameters.entrySet()) {
if (entry.getValue().size() == 1) {
parametersMap.put(entry.getKey(), entry.getValue().get(0));
} else {
parametersMap.put(entry.getKey(), entry.getValue());
}
}
parametersMap.put("BASE_URI", uriInfo.getBaseUri());
parametersMap.putAll(result);
return this.templateMergeService.compile(template, parametersMap);
}
}
@@ -0,0 +1,56 @@
package org.mifosplatform.template.data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateEntity;
import org.mifosplatform.template.domain.TemplateType;
public class TemplateData {
@SuppressWarnings("unused")
private final List<Map<String, Object>> entities;
@SuppressWarnings("unused")
private final List<Map<String, Object>> types;
@SuppressWarnings("unused")
private final Template template;
private TemplateData(final Template template) {
this.template = template;
this.entities = getEntites();
this.types = getTypes();
}
public static TemplateData template(final Template template) {
return new TemplateData(template);
}
public static TemplateData template() {
return new TemplateData(null);
}
private List<Map<String, Object>> getEntites() {
final List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
for (final TemplateEntity e : TemplateEntity.values()) {
final Map<String, Object> m = new HashMap<String, Object>();
m.put("id", e.getId());
m.put("name", e.getName());
l.add(m);
}
return l;
}
private List<Map<String, Object>> getTypes() {
final List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
for (final TemplateType e : TemplateType.values()) {
final Map<String, Object> m = new HashMap<String, Object>();
m.put("id", e.getId());
m.put("name", e.getName());
l.add(m);
}
return l;
}
}
@@ -0,0 +1,119 @@
package org.mifosplatform.template.domain;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.springframework.data.jpa.domain.AbstractPersistable;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@Entity
@Table(name = "m_template", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
public class Template extends AbstractPersistable<Long> {
@Column(name = "name", nullable = false, unique = true)
private String name;
@Enumerated
@JsonSerialize(using = TemplateEntitySerializer.class)
private TemplateEntity entity;
@Enumerated
@JsonSerialize(using = TemplateTypeSerializer.class)
private TemplateType type;
@Column(name = "text", columnDefinition = "longtext", nullable = false)
private String text;
@OrderBy(value = "mapperorder")
@OneToMany(targetEntity = TemplateMapper.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<TemplateMapper> mappers;
public Template(final String name, final String text, final TemplateEntity entity, final TemplateType type, final List<TemplateMapper> mappers) {
this.name = name;
this.entity = entity;
this.type = type;
this.text = text;
this.mappers = mappers;
}
protected Template() {}
public static Template fromJson(final JsonCommand command) {
System.out.println("COMMAND: " + command);
final String name = command.stringValueOfParameterNamed("name");
final String text = command.stringValueOfParameterNamed("text");
final TemplateEntity entity = TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed("entity")];
final TemplateType type = TemplateType.values()[command.integerValueSansLocaleOfParameterNamed("type")];
final JsonArray array = command.arrayOfParameterNamed("mappers");
final List<TemplateMapper> mappersList = new ArrayList<TemplateMapper>();
for (final JsonElement element : array) {
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString()));
}
return new Template(name, text, entity, type, mappersList);
}
public LinkedHashMap<String, String> getMappersAsMap() {
final LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
for (final TemplateMapper mapper : getMappers()) {
map.put(mapper.getMapperkey(), mapper.getMappervalue());
}
return map;
}
public List<TemplateMapper> getMappers() {
return this.mappers;
}
public void setMappers(final List<TemplateMapper> mappers) {
this.mappers = mappers;
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
public TemplateEntity getEntity() {
return this.entity;
}
public void setEntity(final TemplateEntity entity) {
this.entity = entity;
}
public TemplateType getType() {
return this.type;
}
public void setType(final TemplateType type) {
this.type = type;
}
public String getText() {
return this.text;
}
public void setText(final String text) {
this.text = text;
}
}
@@ -0,0 +1,37 @@
package org.mifosplatform.template.domain;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import com.google.gson.annotations.SerializedName;
@JsonSerialize(using = TemplateEntitySerializer.class)
public enum TemplateEntity {
@SerializedName("client")
CLIENT(0, "client"), @SerializedName("loan")
LOAN(1, "loan");
private int id;
private String name;
private TemplateEntity(final int id, final String name) {
this.id = id;
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
public int getId() {
return this.id;
}
public void setId(final int id) {
this.id = id;
}
}
@@ -0,0 +1,23 @@
package org.mifosplatform.template.domain;
import java.io.IOException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class TemplateEntitySerializer extends JsonSerializer<TemplateEntity> {
@Override
public void serialize(final TemplateEntity value, final JsonGenerator generator, @SuppressWarnings("unused") final SerializerProvider provider)
throws IOException, JsonProcessingException {
generator.writeStartObject();
generator.writeFieldName("id");
generator.writeNumber(value.getId());
generator.writeFieldName("name");
generator.writeString(value.getName());
generator.writeEndObject();
}
}
@@ -0,0 +1,15 @@
package org.mifosplatform.template.domain;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TemplateFunctions {
public static String now() {
final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm");
final Date date = new Date();
return dateFormat.format(date);
}
}
@@ -0,0 +1,54 @@
package org.mifosplatform.template.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_templatemappers")
public class TemplateMapper extends AbstractPersistable<Long> {
@Column(name = "mapperorder")
private int mapperorder;
@Column(name = "mapperkey")
private String mapperkey;
@Column(name = "mappervalue")
private String mappervalue;
protected TemplateMapper() {}
public TemplateMapper(final int mapperorder, final String mapperkey, final String mappervalue) {
this.mapperorder = mapperorder;
this.mapperkey = mapperkey;
this.mappervalue = mappervalue;
}
public String getMapperkey() {
return this.mapperkey;
}
public int getMapperorder() {
return this.mapperorder;
}
public void setMapperorder(final int mapperorder) {
this.mapperorder = mapperorder;
}
public void setMapperkey(final String mapperkey) {
this.mapperkey = mapperkey;
}
public String getMappervalue() {
return this.mappervalue;
}
public void setMappervalue(final String mappervalue) {
this.mappervalue = mappervalue;
}
}
@@ -0,0 +1,10 @@
package org.mifosplatform.template.domain;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TemplateRepository extends JpaRepository<Template, Long> {
List<Template> findByEntityAndType(TemplateEntity entity, TemplateType type);
}
@@ -0,0 +1,40 @@
package org.mifosplatform.template.domain;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import com.google.gson.annotations.SerializedName;
@JsonSerialize(using = TemplateTypeSerializer.class)
public enum TemplateType {
@SerializedName("Document")
DOCUMENT(0, "Document");
/**
* @SerializedName("E-Mail") EMAIL(1, "E-Mail"),
* @SerializedName("SMS") SMS(2, "SMS");
*/
private int id;
private String name;
private TemplateType(final int id, final String name) {
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public void setId(final int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
}
@@ -0,0 +1,23 @@
package org.mifosplatform.template.domain;
import java.io.IOException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class TemplateTypeSerializer extends JsonSerializer<TemplateType> {
@Override
public void serialize(final TemplateType value, final JsonGenerator generator, @SuppressWarnings("unused") final SerializerProvider provider)
throws IOException, JsonProcessingException {
generator.writeStartObject();
generator.writeFieldName("id");
generator.writeNumber(value.getId());
generator.writeFieldName("name");
generator.writeString(value.getName());
generator.writeEndObject();
}
}
@@ -0,0 +1,10 @@
package org.mifosplatform.template.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
public class TemplateNotFoundException extends AbstractPlatformResourceNotFoundException {
public TemplateNotFoundException(final Long id) {
super("error.msg.template.id.invalid", "Template with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,28 @@
package org.mifosplatform.template.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.template.service.TemplateDomainService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CreateTemplateCommandHandler implements NewCommandSourceHandler {
private final TemplateDomainService templateService;
@Autowired
public CreateTemplateCommandHandler(final TemplateDomainService templateService) {
this.templateService = templateService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.templateService.createTemplate(command);
}
}
@@ -0,0 +1,28 @@
package org.mifosplatform.template.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.template.service.TemplateDomainService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class DeleteTemplateCommandHandler implements NewCommandSourceHandler {
private final TemplateDomainService templateService;
@Autowired
public DeleteTemplateCommandHandler(final TemplateDomainService templateService) {
this.templateService = templateService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.templateService.removeTemplate(command.entityId());
}
}
@@ -0,0 +1,28 @@
package org.mifosplatform.template.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.template.service.TemplateDomainService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UpdateTemplateCommandHandler implements NewCommandSourceHandler {
private final TemplateDomainService templateService;
@Autowired
public UpdateTemplateCommandHandler(final TemplateDomainService templateService) {
this.templateService = templateService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.templateService.updateTemplate(command.entityId(), command);
}
}
@@ -0,0 +1,98 @@
package org.mifosplatform.template.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateEntity;
import org.mifosplatform.template.domain.TemplateMapper;
import org.mifosplatform.template.domain.TemplateRepository;
import org.mifosplatform.template.domain.TemplateType;
import org.mifosplatform.template.exception.TemplateNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@Service
public class JpaTemplateDomainService implements TemplateDomainService {
private static final String PROPERTY_NAME = "name";
private static final String PROPERTY_TEXT = "text";
private static final String PROPERTY_MAPPERS = "mappers";
private static final String PROPERTY_ENTITY = "entity";
private static final String PROPERTY_TYPE = "type";
@Autowired
private TemplateRepository templateRepository;
@Override
public List<Template> getAll() {
return this.templateRepository.findAll();
}
@Override
public Template getById(final Long id) {
final Template template = this.templateRepository.findOne(id);
if (template == null) { throw new TemplateNotFoundException(id); }
return template;
}
@Transactional
@Override
public CommandProcessingResult createTemplate(final JsonCommand command) {
final Template template = Template.fromJson(command);
this.templateRepository.saveAndFlush(template);
return new CommandProcessingResultBuilder().withEntityId(template.getId()).build();
}
@Transactional
@Override
public CommandProcessingResult updateTemplate(final Long templateId, final JsonCommand command) {
final Template template = getById(templateId);
System.out.println("COMM: " + command);
template.setName(command.stringValueOfParameterNamed(PROPERTY_NAME));
template.setText(command.stringValueOfParameterNamed(PROPERTY_TEXT));
template.setEntity(TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_ENTITY)]);
template.setType(TemplateType.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_TYPE)]);
final JsonArray array = command.arrayOfParameterNamed("mappers");
final List<TemplateMapper> mappersList = new ArrayList<TemplateMapper>();
for (final JsonElement element : array) {
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString()));
}
template.setMappers(mappersList);
this.templateRepository.saveAndFlush(template);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(template.getId()).build();
}
@Transactional
@Override
public CommandProcessingResult removeTemplate(final Long templateId) {
final Template template = getById(templateId);
this.templateRepository.delete(template);
return new CommandProcessingResultBuilder().withEntityId(templateId).build();
}
@Override
public Template updateTemplate(final Template template) {
return this.templateRepository.saveAndFlush(template);
}
@Override
public List<Template> getAllByEntityAndType(final TemplateEntity entity, final TemplateType type) {
return this.templateRepository.findByEntityAndType(entity, type);
}
}
@@ -0,0 +1,26 @@
package org.mifosplatform.template.service;
import java.util.List;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateEntity;
import org.mifosplatform.template.domain.TemplateType;
public interface TemplateDomainService {
List<Template> getAll();
List<Template> getAllByEntityAndType(TemplateEntity entity, TemplateType type);
Template getById(Long id);
Template updateTemplate(Template template);
CommandProcessingResult createTemplate(final JsonCommand command);
CommandProcessingResult updateTemplate(final Long templateId, final JsonCommand command);
CommandProcessingResult removeTemplate(final Long templateId);
}
@@ -0,0 +1,166 @@
package org.mifosplatform.template.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.map.ObjectMapper;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateFunctions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
@Service
public class TemplateMergeService {
private final FromJsonHelper fromApiJsonHelper;
private Map<String, Object> scopes;
@Autowired
public TemplateMergeService(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public String compile(final Template template, final Map<String, Object> scopes) throws MalformedURLException, IOException {
this.scopes = scopes;
this.scopes.put("static", new TemplateFunctions());
final MustacheFactory mf = new DefaultMustacheFactory();
final Mustache mustache = mf.compile(new StringReader(template.getText()), template.getName());
final Map<String, Object> mappers = getCompiledMapFromMappers(template.getMappersAsMap());
this.scopes.putAll(mappers);
final StringWriter stringWriter = new StringWriter();
mustache.execute(stringWriter, this.scopes);
return stringWriter.toString();
}
private Map<String, Object> getCompiledMapFromMappers(final Map<String, String> data) {
final MustacheFactory mf = new DefaultMustacheFactory();
if (data != null) {
for (final Map.Entry<String, String> entry : data.entrySet()) {
final Mustache mappersMustache = mf.compile(new StringReader(entry.getValue()), "");
final StringWriter stringWriter = new StringWriter();
mappersMustache.execute(stringWriter, this.scopes);
String url = stringWriter.toString();
if (!url.startsWith("http")) {
url = this.scopes.get("BASE_URI") + url;
}
System.out.println("URL: " + url);
try {
this.scopes.put(entry.getKey(), getMapFromUrl(url));
} catch (final MalformedURLException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
return this.scopes;
}
@SuppressWarnings("unchecked")
private Map<String, Object> getMapFromUrl(final String url) throws MalformedURLException, IOException {
final HttpURLConnection connection = getConnection(url);
final String response = getStringFromInputStream(connection.getInputStream());
HashMap<String, Object> result = new HashMap<String, Object>();
System.out.println("CONTENT_TYPE" + connection.getContentType());
if (connection.getContentType().equals("text/plain")) {
result.put("src", response);
} else {
result = new ObjectMapper().readValue(response, HashMap.class);
}
return result;
}
private HttpURLConnection getConnection(final String url) {
final String name = SecurityContextHolder.getContext().getAuthentication().getName();
final String password = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(name, password.toCharArray());
}
});
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
TrustModifier.relaxHostChecking(connection);
connection.setDoInput(true);
} catch (final MalformedURLException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
} catch (final KeyManagementException e) {
e.printStackTrace();
} catch (final NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (final KeyStoreException e) {
e.printStackTrace();
}
return connection;
}
private static String getStringFromInputStream(final InputStream is) {
BufferedReader br = null;
final StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (final IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
@@ -0,0 +1,70 @@
package org.mifosplatform.template.service;
import java.net.HttpURLConnection;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
@SuppressWarnings("unused")
public class TrustModifier {
private static final TrustingHostnameVerifier TRUSTING_HOSTNAME_VERIFIER = new TrustingHostnameVerifier();
private static SSLSocketFactory factory;
/**
* Call this with any HttpURLConnection, and it will modify the trust
* settings if it is an HTTPS connection.
*/
public static void relaxHostChecking(final HttpURLConnection conn) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
if (conn instanceof HttpsURLConnection) {
final HttpsURLConnection httpsConnection = (HttpsURLConnection) conn;
final SSLSocketFactory factory = prepFactory(httpsConnection);
httpsConnection.setSSLSocketFactory(factory);
httpsConnection.setHostnameVerifier(TRUSTING_HOSTNAME_VERIFIER);
}
}
static synchronized SSLSocketFactory prepFactory(final HttpsURLConnection httpsConnection) throws NoSuchAlgorithmException,
KeyStoreException, KeyManagementException {
if (factory == null) {
final SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[] { new AlwaysTrustManager() }, null);
factory = ctx.getSocketFactory();
}
return factory;
}
private static final class TrustingHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(final String hostname, final SSLSession session) {
return true;
}
}
private static class AlwaysTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {}
@Override
public void checkServerTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}
@@ -14,10 +14,8 @@
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
<!-- <property name="hibernate.hbm2ddl.auto" value="update"/> -->
<property name="hibernate.jdbc.batch_size" value="100" />
<property name="hibernate.order_inserts" value="true" />
<!-- <property name = "hibernate.show_sql" value = "true" /> -->
</properties>
</persistence-unit>
</persistence>
@@ -36,7 +36,10 @@
org.mifosplatform.portfolio.savingsaccount.*,
org.mifosplatform.portfolio.*,
org.mifosplatform.useradministration.*,
org.mifosplatform.mix.*">
org.mifosplatform.mix.*,
org.mifosplatform.template.*,
org.mifosplatform.template.service.*,
org.mifosplatform.useradministration.*">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
</context:component-scan>
@@ -51,6 +54,7 @@
<jpa:repositories base-package="org.mifosplatform.portfolio.*" />
<jpa:repositories base-package="org.mifosplatform.mix.domain" />
<jpa:repositories base-package="org.mifosplatform.scheduledjobs.domain" />
<jpa:repositories base-package="org.mifosplatform.template.domain" />
<import resource="infrastructure.xml" />
@@ -29,12 +29,6 @@
<beans:property name="realmName" value="Mifos Platform API" />
</beans:bean>
<!--
<beans:bean id="basicAuthenticationProcessingFilter" class="org.mifosplatform.infrastructure.security.filter.TenantAwareBasicAuthenticationFilter" depends-on="cacheManager">
<beans:constructor-arg ref="authenticationManager" />
<beans:constructor-arg ref="basicAuthenticationEntryPoint" />
</beans:bean>
-->
<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
<beans:constructor-arg value="256"/>
</beans:bean>
@@ -49,7 +43,7 @@
<beans:property name="saltSource" ref="saltSource" />
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-manager alias="authenticationManager" erase-credentials="false">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
</beans:beans>
@@ -0,0 +1,93 @@
package org.mifosplatform.common;
import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.path.json.JsonPath.from;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import org.apache.commons.lang.StringUtils;
import org.apache.http.conn.HttpHostConnectException;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.path.json.JsonPath;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Random;
@SuppressWarnings("unchecked")
public class Utils {
private static final String LOGIN_URL = "/mifosng-provider/api/v1/authentication?username=mifos&password=password&tenantIdentifier=default";
public static void initializeRESTAssured() {
RestAssured.baseURI ="https://localhost";
RestAssured.port = 8443;
RestAssured.keystore("../keystore.jks", "openmf");
}
public static String loginIntoServerAndGetBase64EncodedAuthenticationKey() {
try {
System.out.println("-----------------------------------LOGIN-----------------------------------------");
String json = RestAssured.post(LOGIN_URL).asString();
assertThat("Failed to login into mifosx platform", StringUtils.isBlank(json), is(false));
return JsonPath.with(json).get("base64EncodedAuthenticationKey");
}
catch (Exception e) {
if (e instanceof HttpHostConnectException) {
HttpHostConnectException hh = (HttpHostConnectException) e;
fail("Failed to connect to mifosx platform:"+hh.getMessage());
}
throw new RuntimeException(e);
}
}
public static <T> T performServerGet(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
final String getURL, final String jsonAttributeToGetBack) {
String json = given().spec(requestSpec)
.expect().spec(responseSpec).log().ifError()
.when().get(getURL).andReturn().asString();
return (T) from(json).get(jsonAttributeToGetBack);
}
public static <T> T performServerPost(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
final String postURL, final String jsonBodyToSend, final String jsonAttributeToGetBack) {
String json = given().spec(requestSpec).body(jsonBodyToSend)
.expect().spec(responseSpec).log().ifError()
.when().post(postURL)
.andReturn().asString();
return (T) from(json).get(jsonAttributeToGetBack);
}
public static String convertDateToURLFormat(String dateToBeConvert){
SimpleDateFormat oldFormat = new SimpleDateFormat("dd MMMMMM yyyy");
SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd");
String reformattedStr="";
try {
reformattedStr = newFormat.format(oldFormat.parse(dateToBeConvert));
} catch (ParseException e) {
e.printStackTrace();
}
return reformattedStr;
}
public static String randomStringGenerator(final String prefix, final int len, final String sourceSetString) {
int lengthOfSource = sourceSetString.length();
Random rnd = new Random();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append((sourceSetString).charAt(rnd.nextInt(lengthOfSource)));
return (prefix + (sb.toString()));
}
public static String randomStringGenerator(final String prefix, final int len) {
return randomStringGenerator(prefix, len, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
}
@@ -0,0 +1,78 @@
package org.mifosplatform.template;
import static org.junit.Assert.assertEquals;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import org.joda.time.LocalDate;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.loanaccount.LoanScheduleTestDataHelper;
import org.mifosplatform.portfolio.loanaccount.MonetaryCurrencyBuilder;
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.service.TemplateMergeService;
public class TemplateMergeServiceTest {
private Template template;
private final static String TEST_FILE = "src/test/resources/template.mustache";
private static TemplateMergeService tms;
@BeforeClass
public static void init() {
tms = new TemplateMergeService(new FromJsonHelper());
}
@Test
public void compileHelloTemplate() throws Exception {
String name = "TemplateName";
String text = "Hello Test for Template {{template.name}}!";
template = new Template(name, text, null, null, null);
HashMap<String, Object> scopes = new HashMap<String, Object>();
scopes.put("template", template);
String output ="";
output = tms.compile(template, scopes);
assertEquals("Hello Test for Template TemplateName!", output);
}
//TODO:ASSERT!!
@Test
public void compileLoanSummary() throws IOException{
LocalDate july2nd = new LocalDate(2012, 7, 2);
MonetaryCurrency usDollars = new MonetaryCurrencyBuilder().withCode("USD").withDigitsAfterDecimal(2).build();
List<LoanRepaymentScheduleInstallment> installments
= LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars);
File file = new File(TEST_FILE);
DataInputStream dis = new DataInputStream(new FileInputStream(file));
byte[] bytes = new byte[(int) file.length()];
dis.readFully(bytes);
String content = new String(bytes, "UTF-8");
template = new Template("TemplateName", content, null, null, null);
HashMap<String, Object> scopes = new HashMap<String, Object>();
scopes.put("installments", installments);
String output = tms.compile(template, scopes);
dis.close();
System.out.println(output);
dis.close();
}
}
@@ -0,0 +1,82 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<tx:annotation-driven />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mifosplatform-tenants"
p:username="root"
p:password="mysql" />
<bean id="hibernateExceptionTranslator" class="org.springframework.orm.hibernate4.HibernateExceptionTranslator" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="dataSource" ref="tenantDataSourceJndi"/>
<property name="packagesToScan">
<list>
<value>org.mifosplatform.template</value>
<value>org.mifosplatform.commands.domain</value>
<value>org.mifosplatform.useradministration.domain</value>
<value>org.mifosplatform.organisation.office.domain</value>
<value>org.mifosplatform.organisation.staff.domain</value>
<value>org.mifosplatform.infrastructure.core.serialization</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<context:component-scan base-package="org.mifosplatform.accounting.*,
org.mifosplatform.commands.handler.*,
org.mifosplatform.commands.service.*,
org.mifosplatform.commands.*,
org.mifosplatform.audit.*,
org.mifosplatform.infrastructure.*,
org.mifosplatform.scheduledjobs.*,
org.mifosplatform.organisation.*,
org.mifosplatform.portfolio.loanaccount.*,
org.mifosplatform.portfolio.savingsaccount.*,
org.mifosplatform.portfolio.*,
org.mifosplatform.template.*,
org.mifosplatform.template.service.*,
org.mifosplatform.useradministration.*" >
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
</context:component-scan>
<jpa:repositories base-package="org.mifosplatform.commands.domain" />
<jpa:repositories base-package="org.mifosplatform.infrastructure.*.domain" />
<jpa:repositories base-package="org.mifosplatform.accounting.*.domain" />
<jpa:repositories base-package="org.mifosplatform.useradministration.domain" />
<jpa:repositories base-package="org.mifosplatform.organisation.*.domain" />
<jpa:repositories base-package="org.mifosplatform.portfolio.*" />
<jpa:repositories base-package="org.mifosplatform.template.domain" />
<jee:jndi-lookup jndi-name="java:comp/env/jdbc/mifosplatform-tenants" id="tenantDataSourceJndi" />
</beans>
@@ -0,0 +1,132 @@
<h1><span style="font-size:20px"><strong><span style="color:#0000CD">Sample Loan Summary &amp; Repayment Schedule&nbsp;</span></strong></span></h1>
<h2><span style="font-size:16px"><span style="color:#0000CD">TABLE 1. LOAN SUMMARY</span>&nbsp;</span></h2>
<table align="left" border="1" cellpadding="3" cellspacing="0" style="width:650px">
<tbody>
<tr>
<td>Loan size and currency</td>
<td>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</td>
<td>Total no. of installments&nbsp;</td>
<td>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</td>
</tr>
<tr>
<td>Interest rate&nbsp;</td>
<td>&nbsp;</td>
<td>Installment&nbsp;frequency</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Commission fee</td>
<td>&nbsp;</td>
<td>Disbursement date&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Other fees</td>
<td>&nbsp;</td>
<td>Mandatory savings</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Purpose of loan</td>
<td>&nbsp;</td>
<td>Maturity date&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Grace period (if applies)</td>
<td>&nbsp;</td>
<td>Type of guarantee</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Penalty for late payment</td>
<td>&nbsp;</td>
<td>Maturity of the loan (in months)&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Penalty for pre-payment</td>
<td>&nbsp;</td>
<td>Total cost of loan (principle + int.+ fees)&nbsp;</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><span style="font-size:16px"><span style="color:#0000CD">TABLE 2. REPAYMENT SCHEDULE&nbsp;</span></span></h2>
<table border="1" cellpadding="3" cellspacing="0" style="width:600px">
<tbody>
<tr>
<td>Date</td>
<td>Disbursement&nbsp;Amount</td>
<td>
<p>Principle Repayment</p>
</td>
<td>&nbsp;Interest&nbsp;Repayment</td>
<td>Commission&nbsp;Payment</td>
<td>Fees</td>
<td>Tax Payment</td>
<td>Total&nbsp;Repayment</td>
<td>Total Balance&nbsp;Outstanding</td>
</tr>
{{#installments}}
<tr>
<td>{{dueDate}}</td>
<td>{{installmentNumber}}</td>
<td>{{fromDate}}</td>
<td>{{principal}}</td>
<td>&nbsp;</td>
<td>{{feeChargesCharged}}</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
{{/installments}}
<tr>
<td>Total</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Client&nbsp;Signature&nbsp;___________________________________________________________________&nbsp;</p>
<p>Credit Officer Signature _____________________________________________________________&nbsp;</p>
<p>Branch&nbsp;Director&nbsp;Signature&nbsp;___________________________________________________________&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size:12px"><strong>Please contact the<span style="color:#FF0000"> Macro</span><span style="color:#0000CD">Dreams</span> Customer Service Line if you have questions or complaints about our products,&nbsp;</strong></span></p>
<p><span style="font-size:12px"><strong>services, or staff: 555-555-5555. Open Monday to Saturday 7:00-20:00. All calls are free.&nbsp;</strong></span></p>