Merge branch 'MIFOSX-1786' of git://github.com/binaryking/mifosx into binaryking-MIFOSX-1786

This commit is contained in:
Vishwas Babu A J
2015-01-13 11:10:16 -08:00
14 changed files with 2069 additions and 1895 deletions
+35 -29
View File
@@ -13936,6 +13936,7 @@ Request Body:
<li> events - array - Determines what events the hook is triggered for. <li> events - array - Determines what events the hook is triggered for.
</li> </li>
<li> config - hash - Required. Key/value pairs to provide settings for this hook. These settings vary between the templates.</li> <li> config - hash - Required. Key/value pairs to provide settings for this hook. These settings vary between the templates.</li>
<li> templateId - Optional. The UGD template ID associated with the same entity (client or loan).</li>
<ul></p> <ul></p>
</div> </div>
<div class="method-example"> <div class="method-example">
@@ -13950,6 +13951,7 @@ Request Body:
"name": "Web", "name": "Web",
"isActive": true, "isActive": true,
"displayName": "Kremlin", "displayName": "Kremlin",
"templateId": 1,
"events": [ "events": [
{ {
"actionName": "DISBURSE", "actionName": "DISBURSE",
@@ -13996,6 +13998,8 @@ GET https://DomainName/api/v1/hooks
"isActive": true, "isActive": true,
"createdAt": [2014, 9, 16], "createdAt": [2014, 9, 16],
"updatedAt": [2014, 9, 16], "updatedAt": [2014, 9, 16],
"templateId": 1,
"templateName": "My UGD",
"events": [ "events": [
{ {
"actionName": "DISBURSE", "actionName": "DISBURSE",
@@ -14043,6 +14047,8 @@ GET https://DomainName/api/v1/hooks/{hookId}
"isActive": true, "isActive": true,
"createdAt": [2014, 9, 16], "createdAt": [2014, 9, 16],
"updatedAt": [2014, 9, 16], "updatedAt": [2014, 9, 16],
"templateId": 1,
"templateName": "My UGD",
"events": [ "events": [
{ {
"actionName": "DISBURSE", "actionName": "DISBURSE",
@@ -33260,7 +33266,7 @@ No Request Body:
<p>User Generated Documents (and other types of templates) can aggregate data from several Mifos X back-end API calls via <b>mappers</b>. Mappers can even access non-Mifos X REST services from other servers. UGDs can render such data in tables, show images, etc. <i>TBD: Please have a look at some of the Example UGDs included in Mifos X (or <a href="https://mifosforge.jira.com/wiki/display/RES/UGD_FinalDoc">the Wiki page</a>, for now.).</i></p> <p>User Generated Documents (and other types of templates) can aggregate data from several Mifos X back-end API calls via <b>mappers</b>. Mappers can even access non-Mifos X REST services from other servers. UGDs can render such data in tables, show images, etc. <i>TBD: Please have a look at some of the Example UGDs included in Mifos X (or <a href="https://mifosforge.jira.com/wiki/display/RES/UGD_FinalDoc">the Wiki page</a>, for now.).</i></p>
<p>UGDs can be assigned to an entity like <b>client</b> or <b>loan</b> and be of a typ like <b>document</b>. The entity and type of a UGD is only there for the convenience of user agents (UIs), in order to know where to show UGDs for the user (i.e. which tab). The Template Engine back-end runner does not actually need this metadata.</p> <p>UGDs can be assigned to an entity like <b>client</b> or <b>loan</b> and be of a type like <b>Document</b> or <b>SMS</b>. The entity and type of a UGD is only there for the convenience of user agents (UIs), in order to know where to show UGDs for the user (i.e. which tab). The Template Engine back-end runner does not actually need this metadata.</p>
<table class=matrixHeading> <table class=matrixHeading>
<tr class="matrixHeadingBG"> <tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Field Descriptions</div></td> <td><div class="mifosXHeading2">Field Descriptions</div></td>
@@ -33277,8 +33283,8 @@ No Request Body:
</tr> </tr>
<tr> <tr>
<td class=fielddesc> <td class=fielddesc>
For now only the type document is supported. For now only the types Document and SMS are supported.
In a next version UGDs may be created for e-mails oder SMS. In a next version, UGDs may be created for e-mails as well.
</td> </td>
</tr> </tr>
<tr class=alt> <tr class=alt>
@@ -33357,14 +33363,14 @@ GET https://DomainName/api/v1/templates/template
{ {
"id": 1, "id": 1,
"name": "Test", "name": "Test",
"entity": "loan", "entity": 1,
"type": "Document", "type": 0,
"text": "This is a loan for {{loan.clientName}}", "text": "This is a loan for {{loan.clientName}}",
"mappers": [ "mappers": [
{ {
"mapperorder": 0, "mappersorder": 0,
"mapperkey": "loan", "mapperskey": "loan",
"mappervalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}", "mappersvalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}",
"id": 1 "id": 1
} }
] ]
@@ -33401,14 +33407,14 @@ Request Body:
{ {
"id": 1, "id": 1,
"name": "Test", "name": "Test",
"entity": "loan", "entity": 1,
"type": "Document", "type": 0,
"text": "This is a loan for {{loan.clientName}}", "text": "This is a loan for {{loan.clientName}}",
"mappers": [ "mappers": [
{ {
"mapperorder": 0, "mappersorder": 0,
"mapperkey": "loan", "mapperskey": "loan",
"mappervalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}", "mappersvalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}",
"id": 1 "id": 1
} }
] ]
@@ -33458,7 +33464,7 @@ Request Body:
<tr> <tr>
<td></td> <td></td>
<td></td> <td></td>
<td>SMS (not yet)</td> <td>SMS</td>
<td>2</td> <td>2</td>
</tr> </tr>
</table> </table>
@@ -33472,14 +33478,14 @@ GET https://DomainName/api/v1/templates
{ {
"id": 1, "id": 1,
"name": "Test", "name": "Test",
"entity": "loan", "entity": 1,
"type": "Document", "type": 0,
"text": "This is a loan for {{loan.clientName}}", "text": "This is a loan for {{loan.clientName}}",
"mappers": [ "mappers": [
{ {
"mapperorder": 0, "mappersorder": 0,
"mapperkey": "loan", "mapperskey": "loan",
"mappervalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}", "mappersvalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}",
"id": 1 "id": 1
} }
] ]
@@ -33505,14 +33511,14 @@ GET https://DomainName/api/v1/templates/{Id}
{ {
"id": 1, "id": 1,
"name": "Test", "name": "Test",
"entity": "loan", "entity": 1,
"type": "Document", "type": 0,
"text": "This is a loan for {{loan.clientName}}", "text": "This is a loan for {{loan.clientName}}",
"mappers": [ "mappers": [
{ {
"mapperorder": 0, "mappersorder": 0,
"mapperkey": "loan", "mapperskey": "loan",
"mappervalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}", "mappersvalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}",
"id": 1 "id": 1
} }
] ]
@@ -33538,14 +33544,14 @@ Request Body:
{ {
"id": 1, "id": 1,
"name": "Test", "name": "Test",
"entity": "loan", "entity": 1,
"type": "Document", "type": 0,
"text": "This is a loan for {{loan.clientName}}", "text": "This is a loan for {{loan.clientName}}",
"mappers": [ "mappers": [
{ {
"mapperorder": 0, "mappersorder": 0,
"mapperkey": "loan", "mapperskey": "loan",
"mappervalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}", "mappersvalue": "loans/{{loanId}}?associations=all&tenantIdentifier={{tenantIdentifier}}",
"id": 1 "id": 1
} }
] ]
@@ -45,12 +45,18 @@ public class HookApiConstants {
public static final String actionNameParamName = "actionName"; public static final String actionNameParamName = "actionName";
public static final String templateIdParamName = "templateId";
public static final String templateNameParamName = "templateName";
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>( public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(nameParamName, displayNameParamName, Arrays.asList(nameParamName, displayNameParamName,
isActiveParamName, configParamName, eventsParamName)); templateIdParamName, isActiveParamName, configParamName,
eventsParamName, templateNameParamName));
public static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>( public static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(nameParamName, displayNameParamName, Arrays.asList(nameParamName, displayNameParamName,
isActiveParamName, configParamName, eventsParamName)); templateIdParamName, isActiveParamName, configParamName,
eventsParamName, templateNameParamName));
} }
@@ -5,11 +5,11 @@
*/ */
package org.mifosplatform.infrastructure.hooks.data; package org.mifosplatform.infrastructure.hooks.data;
import org.joda.time.LocalDate;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import org.joda.time.LocalDate;
public class HookData implements Serializable { public class HookData implements Serializable {
private final Long id; private final Long id;
@@ -18,6 +18,8 @@ public class HookData implements Serializable {
private final Boolean isActive; private final Boolean isActive;
private final LocalDate createdAt; private final LocalDate createdAt;
private final LocalDate updatedAt; private final LocalDate updatedAt;
private final Long templateId;
private final String templateName;
// associations // associations
private final List<Event> events; private final List<Event> events;
@@ -30,15 +32,17 @@ public class HookData implements Serializable {
public static HookData instance(final Long id, final String name, public static HookData instance(final Long id, final String name,
final String displayName, final boolean isActive, final String displayName, final boolean isActive,
final LocalDate createdAt, final LocalDate updatedAt, final LocalDate createdAt, final LocalDate updatedAt,
final List<Event> registeredEvents, final List<Field> config) { final Long templateId, final List<Event> registeredEvents,
final List<Field> config, final String templateName) {
return new HookData(id, name, displayName, isActive, createdAt, return new HookData(id, name, displayName, isActive, createdAt,
updatedAt, registeredEvents, config, null, null); updatedAt, templateId, registeredEvents, config, templateName,
null, null);
} }
public static HookData template(final List<HookTemplateData> templates, public static HookData template(final List<HookTemplateData> templates,
final List<Grouping> groupings) { final List<Grouping> groupings) {
return new HookData(null, null, null, null, null, null, null, null, return new HookData(null, null, null, null, null, null, null, null,
templates, groupings); null, null, templates, groupings);
} }
public static HookData templateExisting(final HookData hookData, public static HookData templateExisting(final HookData hookData,
@@ -46,13 +50,15 @@ public class HookData implements Serializable {
final List<Grouping> groupings) { final List<Grouping> groupings) {
return new HookData(hookData.id, hookData.name, hookData.displayName, return new HookData(hookData.id, hookData.name, hookData.displayName,
hookData.isActive, hookData.createdAt, hookData.updatedAt, hookData.isActive, hookData.createdAt, hookData.updatedAt,
hookData.events, hookData.config, templates, groupings); hookData.templateId, hookData.events, hookData.config,
hookData.templateName, templates, groupings);
} }
private HookData(final Long id, final String name, private HookData(final Long id, final String name,
final String displayName, final Boolean isActive, final String displayName, final Boolean isActive,
final LocalDate createdAt, final LocalDate updatedAt, final LocalDate createdAt, final LocalDate updatedAt,
final List<Event> events, final List<Field> config, final Long templateId, final List<Event> events,
final List<Field> config, final String templateName,
final List<HookTemplateData> templates, final List<HookTemplateData> templates,
final List<Grouping> groupings) { final List<Grouping> groupings) {
this.id = id; this.id = id;
@@ -61,6 +67,8 @@ public class HookData implements Serializable {
this.isActive = isActive; this.isActive = isActive;
this.createdAt = createdAt; this.createdAt = createdAt;
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
this.templateId = templateId;
this.templateName = templateName;
// associations // associations
this.events = events; this.events = events;
@@ -5,34 +5,24 @@
*/ */
package org.mifosplatform.infrastructure.hooks.domain; package org.mifosplatform.infrastructure.hooks.domain;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.configParamName; import com.google.gson.JsonArray;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.displayNameParamName; import com.google.gson.JsonElement;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.eventsParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.isActiveParamName;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption; import org.hibernate.annotations.LazyCollectionOption;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import com.google.gson.JsonArray; import javax.persistence.*;
import com.google.gson.JsonElement; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.*;
@Entity @Entity
@Table(name = "m_hook") @Table(name = "m_hook")
@@ -56,25 +46,30 @@ public class Hook extends AbstractAuditableCustom<AppUser, Long> {
@JoinColumn(name = "template_id", referencedColumnName = "id", nullable = false) @JoinColumn(name = "template_id", referencedColumnName = "id", nullable = false)
private HookTemplate template; private HookTemplate template;
@ManyToOne(optional = true)
@JoinColumn(name = "ugd_template_id", referencedColumnName = "id", nullable = false)
private Template ugdTemplate;
protected Hook() { protected Hook() {
// //
} }
public static Hook fromJson(final JsonCommand command, public static Hook fromJson(final JsonCommand command,
final HookTemplate template, final Set<HookConfiguration> config, final HookTemplate template, final Set<HookConfiguration> config,
final Set<HookResource> events) { final Set<HookResource> events, final Template ugdTemplate) {
final String displayName = command final String displayName = command
.stringValueOfParameterNamed(displayNameParamName); .stringValueOfParameterNamed(displayNameParamName);
Boolean isActive = command Boolean isActive = command
.booleanObjectValueOfParameterNamed(isActiveParamName); .booleanObjectValueOfParameterNamed(isActiveParamName);
if (isActive == null) if (isActive == null)
isActive = false; isActive = false;
return new Hook(template, displayName, isActive, config, events); return new Hook(template, displayName, isActive, config, events,
ugdTemplate);
} }
private Hook(final HookTemplate template, final String displayName, private Hook(final HookTemplate template, final String displayName,
final Boolean isActive, final Set<HookConfiguration> config, final Boolean isActive, final Set<HookConfiguration> config,
final Set<HookResource> events) { final Set<HookResource> events, final Template ugdTemplate) {
this.template = template; this.template = template;
@@ -91,6 +86,7 @@ public class Hook extends AbstractAuditableCustom<AppUser, Long> {
this.events = associateEventsWithThisHook(events); this.events = associateEventsWithThisHook(events);
} }
this.ugdTemplate = ugdTemplate;
} }
private Set<HookConfiguration> associateConfigWithThisHook( private Set<HookConfiguration> associateConfigWithThisHook(
@@ -113,13 +109,21 @@ public class Hook extends AbstractAuditableCustom<AppUser, Long> {
return this.template; return this.template;
} }
public Template getUgdTemplate() {
return this.ugdTemplate;
}
public Long getUgdTemplateId() {
return this.ugdTemplate.getId();
}
public Set<HookConfiguration> getHookConfig() { public Set<HookConfiguration> getHookConfig() {
return this.config; return this.config;
} }
public Map<String, Object> update(final JsonCommand command) { public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(4); final Map<String, Object> actualChanges = new LinkedHashMap<>(5);
if (command.isChangeInStringParameterNamed(displayNameParamName, if (command.isChangeInStringParameterNamed(displayNameParamName,
this.name)) { this.name)) {
@@ -137,6 +141,13 @@ public class Hook extends AbstractAuditableCustom<AppUser, Long> {
this.isActive = newValue; this.isActive = newValue;
} }
if (command.isChangeInLongParameterNamed(templateIdParamName,
getUgdTemplateId())) {
final Long newValue = command
.longValueOfParameterNamed(templateIdParamName);
actualChanges.put(templateIdParamName, newValue);
}
// events // events
if (command.hasParameter(eventsParamName)) { if (command.hasParameter(eventsParamName)) {
final JsonArray jsonArray = command final JsonArray jsonArray = command
@@ -184,4 +195,8 @@ public class Hook extends AbstractAuditableCustom<AppUser, Long> {
return true; return true;
} }
public void updateUgdTemplate(final Template ugdTemplate) {
this.ugdTemplate = ugdTemplate;
}
} }
@@ -5,8 +5,6 @@
*/ */
package org.mifosplatform.infrastructure.hooks.listener; package org.mifosplatform.infrastructure.hooks.listener;
import java.util.List;
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant; import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil; import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
import org.mifosplatform.infrastructure.hooks.domain.Hook; import org.mifosplatform.infrastructure.hooks.domain.Hook;
@@ -20,6 +18,8 @@ import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
@Service @Service
public class MifosHookListener implements HookListener { public class MifosHookListener implements HookListener {
@@ -5,30 +5,43 @@
*/ */
package org.mifosplatform.infrastructure.hooks.processor; package org.mifosplatform.infrastructure.hooks.processor;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.apiKeyName; import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;
import org.mifosplatform.infrastructure.hooks.domain.Hook; import org.mifosplatform.infrastructure.hooks.domain.Hook;
import org.mifosplatform.infrastructure.hooks.domain.HookConfiguration; import org.mifosplatform.infrastructure.hooks.domain.HookConfiguration;
import org.mifosplatform.infrastructure.hooks.domain.HookConfigurationRepository; import org.mifosplatform.infrastructure.hooks.domain.HookConfigurationRepository;
import org.mifosplatform.infrastructure.hooks.processor.data.SmsProviderData; import org.mifosplatform.infrastructure.hooks.processor.data.SmsProviderData;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.template.service.TemplateMergeService;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import retrofit.Callback; import retrofit.Callback;
import com.google.gson.JsonObject; import java.io.IOException;
import com.google.gson.JsonParser; import java.util.HashMap;
import java.util.Map;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.apiKeyName;
@Service @Service
public class TwilioHookProcessor implements HookProcessor { public class TwilioHookProcessor implements HookProcessor {
private final HookConfigurationRepository hookConfigurationRepository; private final HookConfigurationRepository hookConfigurationRepository;
private final TemplateMergeService templateMergeService;
private final ClientRepository clientRepository;
@Autowired @Autowired
public TwilioHookProcessor( public TwilioHookProcessor(
final HookConfigurationRepository hookConfigurationRepository) { final HookConfigurationRepository hookConfigurationRepository,
final TemplateMergeService templateMergeService,
final ClientRepository clientRepository) {
this.hookConfigurationRepository = hookConfigurationRepository; this.hookConfigurationRepository = hookConfigurationRepository;
this.templateMergeService = templateMergeService;
this.clientRepository = clientRepository;
} }
@Override @Override
@@ -47,9 +60,9 @@ public class TwilioHookProcessor implements HookProcessor {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void sendRequest(final SmsProviderData smsProviderData, private void sendRequest(final SmsProviderData smsProviderData,
final String payload, final String entityName, final String payload, String entityName, String actionName,
final String actionName, final String tenantIdentifier, final String tenantIdentifier, final String authToken,
final String authToken, final Hook hook) { final Hook hook) {
final WebHookService service = ProcessorHelper final WebHookService service = ProcessorHelper
.createWebHookService(smsProviderData.getUrl()); .createWebHookService(smsProviderData.getUrl());
@@ -72,12 +85,51 @@ public class TwilioHookProcessor implements HookProcessor {
} }
if (apiKey != null && !apiKey.equals("")) { if (apiKey != null && !apiKey.equals("")) {
final JsonObject json = new JsonParser().parse(payload) JsonObject json = null;
.getAsJsonObject(); if (hook.getUgdTemplate() != null) {
entityName = "sms";
actionName = "send";
json = processUgdTemplate(payload, hook, authToken);
if (json == null) {
return;
}
} else {
json = new JsonParser().parse(payload).getAsJsonObject();
}
service.sendSmsBridgeRequest(entityName, actionName, service.sendSmsBridgeRequest(entityName, actionName,
tenantIdentifier, apiKey, json, callback); tenantIdentifier, apiKey, json, callback);
} }
} }
private JsonObject processUgdTemplate(final String payload,
final Hook hook, final String authToken) {
JsonObject json = null;
try {
@SuppressWarnings("unchecked")
final HashMap<String, Object> map = new ObjectMapper().readValue(
payload, HashMap.class);
map.put("BASE_URI", System.getProperty("baseUrl"));
if (map.containsKey("clientId")) {
final Long clientId = new Long(Integer.toString((int) map
.get("clientId")));
final Client client = this.clientRepository.findOne(clientId);
final String mobileNo = client.mobileNo();
if (mobileNo != null && !mobileNo.isEmpty()) {
this.templateMergeService.setAuthToken(authToken);
final String compiledMessage = this.templateMergeService
.compile(hook.getUgdTemplate(), map)
.replace("<p>", "").replace("</p>", "");
final Map<String, String> jsonMap = new HashMap<>();
jsonMap.put("mobileNo", mobileNo);
jsonMap.put("message", compiledMessage);
final String jsonString = new Gson().toJson(jsonMap);
json = new JsonParser().parse(jsonString).getAsJsonObject();
}
}
} catch (IOException e) {
}
return json;
}
} }
@@ -5,25 +5,20 @@
*/ */
package org.mifosplatform.infrastructure.hooks.serialization; package org.mifosplatform.infrastructure.hooks.serialization;
import java.lang.reflect.Type; import com.google.gson.JsonElement;
import java.util.ArrayList; import com.google.gson.reflect.TypeToken;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.data.ApiParameterError; import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.hooks.api.HookApiConstants;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.google.gson.JsonElement; import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken; import java.util.*;
@Component @Component
public class HookCommandFromApiJsonDeserializer { public class HookCommandFromApiJsonDeserializer {
@@ -32,7 +27,8 @@ public class HookCommandFromApiJsonDeserializer {
* The parameters supported for this command. * The parameters supported for this command.
*/ */
private final Set<String> supportedParameters = new HashSet<>( private final Set<String> supportedParameters = new HashSet<>(
Arrays.asList("name", "displayName", "isActive", "events", "config")); Arrays.asList("name", "displayName", "isActive", "events",
"config", "templateId"));
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
@Autowired @Autowired
@@ -62,6 +58,15 @@ public class HookCommandFromApiJsonDeserializer {
baseDataValidator.reset().parameter("name").value(name).notBlank() baseDataValidator.reset().parameter("name").value(name).notBlank()
.notExceedingLengthOf(100); .notExceedingLengthOf(100);
if (this.fromApiJsonHelper.parameterExists(
HookApiConstants.templateIdParamName, element)) {
final Long templateId = this.fromApiJsonHelper.extractLongNamed(
HookApiConstants.templateIdParamName, element);
baseDataValidator.reset()
.parameter(HookApiConstants.templateIdParamName)
.value(templateId).notNull().integerGreaterThanZero();
}
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
@@ -87,6 +92,15 @@ public class HookCommandFromApiJsonDeserializer {
.notExceedingLengthOf(100); .notExceedingLengthOf(100);
} }
if (this.fromApiJsonHelper.parameterExists(
HookApiConstants.templateIdParamName, element)) {
final Long templateId = this.fromApiJsonHelper.extractLongNamed(
HookApiConstants.templateIdParamName, element);
baseDataValidator.reset()
.parameter(HookApiConstants.templateIdParamName)
.value(templateId).notNull().integerGreaterThanZero();
}
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
@@ -5,20 +5,10 @@
*/ */
package org.mifosplatform.infrastructure.hooks.service; package org.mifosplatform.infrastructure.hooks.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.hooks.data.Event; import org.mifosplatform.infrastructure.hooks.data.*;
import org.mifosplatform.infrastructure.hooks.data.EventResultSetExtractor;
import org.mifosplatform.infrastructure.hooks.data.Field;
import org.mifosplatform.infrastructure.hooks.data.Grouping;
import org.mifosplatform.infrastructure.hooks.data.HookData;
import org.mifosplatform.infrastructure.hooks.data.HookTemplateData;
import org.mifosplatform.infrastructure.hooks.domain.Hook; import org.mifosplatform.infrastructure.hooks.domain.Hook;
import org.mifosplatform.infrastructure.hooks.domain.HookRepository; import org.mifosplatform.infrastructure.hooks.domain.HookRepository;
import org.mifosplatform.infrastructure.hooks.exception.HookNotFoundException; import org.mifosplatform.infrastructure.hooks.exception.HookNotFoundException;
@@ -30,6 +20,11 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
@Service @Service
public class HookReadPlatformServiceImpl implements HookReadPlatformService { public class HookReadPlatformServiceImpl implements HookReadPlatformService {
@@ -118,8 +113,10 @@ public class HookReadPlatformServiceImpl implements HookReadPlatformService {
} }
public String schema() { public String schema() {
return " h.id, s.name as name, h.name as display_name, h.is_active, h.created_date, h.lastmodified_date " return " h.id, s.name as name, h.name as display_name, h.is_active, h.created_date,"
+ " from m_hook h inner join m_hook_templates s on h.template_id = s.id "; + " h.lastmodified_date, h.ugd_template_id, tp.name as ugd_template_name, "
+ "h.ugd_template_id from m_hook h inner join m_hook_templates s on h.template_id = s.id"
+ " inner join m_template tp on h.ugd_template_id = tp.id";
} }
@Override @Override
@@ -135,11 +132,14 @@ public class HookReadPlatformServiceImpl implements HookReadPlatformService {
"created_date"); "created_date");
final LocalDate updatedAt = JdbcSupport.getLocalDate(rs, final LocalDate updatedAt = JdbcSupport.getLocalDate(rs,
"lastmodified_date"); "lastmodified_date");
final Long templateId = rs.getLong("ugd_template_id");
final String templateName = rs.getString("ugd_template_name");
final List<Event> registeredEvents = retrieveEvents(id); final List<Event> registeredEvents = retrieveEvents(id);
final List<Field> config = retrieveConfig(id); final List<Field> config = retrieveConfig(id);
return HookData.instance(id, name, displayname, isActive, return HookData.instance(id, name, displayname, isActive,
createdAt, updatedAt, registeredEvents, config); createdAt, updatedAt, templateId, registeredEvents, config,
templateName);
} }
private List<Event> retrieveEvents(final Long hookId) { private List<Event> retrieveEvents(final Long hookId) {
@@ -195,7 +195,8 @@ public class HookReadPlatformServiceImpl implements HookReadPlatformService {
} }
} }
private static final class TemplateMapper implements private static final class TemplateMapper
implements
RowMapper<HookTemplateData> { RowMapper<HookTemplateData> {
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
@@ -5,22 +5,8 @@
*/ */
package org.mifosplatform.infrastructure.hooks.service; package org.mifosplatform.infrastructure.hooks.service;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.actionNameParamName; import com.google.gson.JsonArray;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.configParamName; import com.google.gson.JsonObject;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.contentTypeName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.entityNameParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.eventsParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.nameParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.payloadURLName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.webTemplateName;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError; import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
@@ -29,37 +15,37 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.hooks.domain.Hook; import org.mifosplatform.infrastructure.hooks.domain.*;
import org.mifosplatform.infrastructure.hooks.domain.HookConfiguration;
import org.mifosplatform.infrastructure.hooks.domain.HookRepository;
import org.mifosplatform.infrastructure.hooks.domain.HookResource;
import org.mifosplatform.infrastructure.hooks.domain.HookTemplate;
import org.mifosplatform.infrastructure.hooks.domain.HookTemplateRepository;
import org.mifosplatform.infrastructure.hooks.domain.Schema;
import org.mifosplatform.infrastructure.hooks.exception.HookNotFoundException; import org.mifosplatform.infrastructure.hooks.exception.HookNotFoundException;
import org.mifosplatform.infrastructure.hooks.exception.HookTemplateNotFoundException; import org.mifosplatform.infrastructure.hooks.exception.HookTemplateNotFoundException;
import org.mifosplatform.infrastructure.hooks.processor.ProcessorHelper; import org.mifosplatform.infrastructure.hooks.processor.ProcessorHelper;
import org.mifosplatform.infrastructure.hooks.processor.WebHookService; import org.mifosplatform.infrastructure.hooks.processor.WebHookService;
import org.mifosplatform.infrastructure.hooks.serialization.HookCommandFromApiJsonDeserializer; import org.mifosplatform.infrastructure.hooks.serialization.HookCommandFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateRepository;
import org.mifosplatform.template.exception.TemplateNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import retrofit.RetrofitError; import retrofit.RetrofitError;
import com.google.gson.JsonArray; import java.util.*;
import com.google.gson.JsonObject; import java.util.Map.Entry;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.*;
@Service @Service
public class HookWritePlatformServiceJpaRepositoryImpl implements public class HookWritePlatformServiceJpaRepositoryImpl
implements
HookWritePlatformService { HookWritePlatformService {
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final HookRepository hookRepository; private final HookRepository hookRepository;
private final HookTemplateRepository hookTemplateRepository; private final HookTemplateRepository hookTemplateRepository;
private final TemplateRepository ugdTemplateRepository;
private final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
@@ -68,11 +54,13 @@ public class HookWritePlatformServiceJpaRepositoryImpl implements
final PlatformSecurityContext context, final PlatformSecurityContext context,
final HookRepository hookRepository, final HookRepository hookRepository,
final HookTemplateRepository hookTemplateRepository, final HookTemplateRepository hookTemplateRepository,
final TemplateRepository ugdTemplateRepository,
final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer, final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final FromJsonHelper fromApiJsonHelper) { final FromJsonHelper fromApiJsonHelper) {
this.context = context; this.context = context;
this.hookRepository = hookRepository; this.hookRepository = hookRepository;
this.hookTemplateRepository = hookTemplateRepository; this.hookTemplateRepository = hookTemplateRepository;
this.ugdTemplateRepository = ugdTemplateRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.fromApiJsonHelper = fromApiJsonHelper; this.fromApiJsonHelper = fromApiJsonHelper;
} }
@@ -95,8 +83,17 @@ public class HookWritePlatformServiceJpaRepositoryImpl implements
final JsonArray events = command final JsonArray events = command
.arrayOfParameterNamed(eventsParamName); .arrayOfParameterNamed(eventsParamName);
final Set<HookResource> allEvents = assembleSetOfEvents(events); final Set<HookResource> allEvents = assembleSetOfEvents(events);
Template ugdTemplate = null;
if (command.hasParameter(templateIdParamName)) {
final Long ugdTemplateId = command
.longValueOfParameterNamed(templateIdParamName);
ugdTemplate = this.ugdTemplateRepository.findOne(ugdTemplateId);
if (ugdTemplate == null) {
throw new TemplateNotFoundException(ugdTemplateId);
}
}
final Hook hook = Hook.fromJson(command, template, config, final Hook hook = Hook.fromJson(command, template, config,
allEvents); allEvents, ugdTemplate);
validateHookRules(template, config, allEvents); validateHookRules(template, config, allEvents);
@@ -128,6 +125,18 @@ public class HookWritePlatformServiceJpaRepositoryImpl implements
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
if (changes.containsKey(templateIdParamName)) {
final Long ugdTemplateId = command
.longValueOfParameterNamed(templateIdParamName);
final Template ugdTemplate = this.ugdTemplateRepository
.findOne(ugdTemplateId);
if (ugdTemplate == null) {
changes.remove(templateIdParamName);
throw new TemplateNotFoundException(ugdTemplateId);
}
hook.updateUgdTemplate(ugdTemplate);
}
if (changes.containsKey(eventsParamName)) { if (changes.containsKey(eventsParamName)) {
final Set<HookResource> events = assembleSetOfEvents(command final Set<HookResource> events = assembleSetOfEvents(command
.arrayOfParameterNamed(eventsParamName)); .arrayOfParameterNamed(eventsParamName));
@@ -311,7 +320,9 @@ public class HookWritePlatformServiceJpaRepositoryImpl implements
if (!found) { if (!found) {
final String errorMessage = "required.config.field." final String errorMessage = "required.config.field."
+ "not.provided"; + "not.provided";
baseDataValidator.reset().value(field.getFieldName()) baseDataValidator
.reset()
.value(field.getFieldName())
.failWithCodeNoParameterAddedToErrorCode( .failWithCodeNoParameterAddedToErrorCode(
errorMessage); errorMessage);
} }
@@ -49,7 +49,8 @@ public class Template extends AbstractPersistable<Long> {
@OneToMany(targetEntity = TemplateMapper.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(targetEntity = TemplateMapper.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<TemplateMapper> mappers; private List<TemplateMapper> mappers;
public Template(final String name, final String text, final TemplateEntity entity, final TemplateType type, public Template(final String name, final String text,
final TemplateEntity entity, final TemplateType type,
final List<TemplateMapper> mappers) { final List<TemplateMapper> mappers) {
this.name = StringUtils.defaultIfEmpty(name, null); this.name = StringUtils.defaultIfEmpty(name, null);
this.entity = entity; this.entity = entity;
@@ -65,16 +66,29 @@ public class Template extends AbstractPersistable<Long> {
public static Template fromJson(final JsonCommand command) { public static Template fromJson(final JsonCommand command) {
final String name = command.stringValueOfParameterNamed("name"); final String name = command.stringValueOfParameterNamed("name");
final String text = command.stringValueOfParameterNamed("text"); final String text = command.stringValueOfParameterNamed("text");
final TemplateEntity entity = TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed("entity")]; final TemplateEntity entity = TemplateEntity.values()[command
final TemplateType type = TemplateType.values()[command.integerValueSansLocaleOfParameterNamed("type")]; .integerValueSansLocaleOfParameterNamed("entity")];
final int templateTypeId = command
.integerValueSansLocaleOfParameterNamed("type");
TemplateType type = null;
switch (templateTypeId) {
case 0 :
type = TemplateType.DOCUMENT;
break;
case 2 :
type = TemplateType.SMS;
break;
}
final JsonArray array = command.arrayOfParameterNamed("mappers"); final JsonArray array = command.arrayOfParameterNamed("mappers");
final List<TemplateMapper> mappersList = new ArrayList<>(); final List<TemplateMapper> mappersList = new ArrayList<>();
for (final JsonElement element : array) { for (final JsonElement element : array) {
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject() mappersList.add(new TemplateMapper(element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString())); .get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject()
.get("mappersvalue").getAsString()));
} }
return new Template(name, text, entity, type, mappersList); return new Template(name, text, entity, type, mappersList);
@@ -13,11 +13,11 @@ import com.google.gson.annotations.SerializedName;
public enum TemplateType { public enum TemplateType {
@SerializedName("Document") @SerializedName("Document")
DOCUMENT(0, "Document"); DOCUMENT(0, "Document"), @SerializedName("SMS")
SMS(2, "SMS");
/** /**
* @SerializedName("E-Mail") EMAIL(1, "E-Mail"), * @SerializedName("E-Mail") EMAIL(1, "E-Mail")
* @SerializedName("SMS") SMS(2, "SMS");
*/ */
private int id; private int id;
private String name; private String name;
@@ -44,7 +44,9 @@ public class JpaTemplateDomainService implements TemplateDomainService {
@Override @Override
public Template findOneById(final Long id) { public Template findOneById(final Long id) {
final Template template = this.templateRepository.findOne(id); final Template template = this.templateRepository.findOne(id);
if (template == null) { throw new TemplateNotFoundException(id); } if (template == null) {
throw new TemplateNotFoundException(id);
}
return template; return template;
} }
@@ -58,12 +60,14 @@ public class JpaTemplateDomainService implements TemplateDomainService {
final Template template = Template.fromJson(command); final Template template = Template.fromJson(command);
this.templateRepository.saveAndFlush(template); this.templateRepository.saveAndFlush(template);
return new CommandProcessingResultBuilder().withEntityId(template.getId()).build(); return new CommandProcessingResultBuilder().withEntityId(
template.getId()).build();
} }
@Transactional @Transactional
@Override @Override
public CommandProcessingResult updateTemplate(final Long templateId, final JsonCommand command) { public CommandProcessingResult updateTemplate(final Long templateId,
final JsonCommand command) {
// FIXME - no validation here of the data in the command object, is // FIXME - no validation here of the data in the command object, is
// name, text populated etc // name, text populated etc
// FIXME - handle cases where data integrity constraints are fired from // FIXME - handle cases where data integrity constraints are fired from
@@ -72,20 +76,36 @@ public class JpaTemplateDomainService implements TemplateDomainService {
final Template template = findOneById(templateId); final Template template = findOneById(templateId);
template.setName(command.stringValueOfParameterNamed(PROPERTY_NAME)); template.setName(command.stringValueOfParameterNamed(PROPERTY_NAME));
template.setText(command.stringValueOfParameterNamed(PROPERTY_TEXT)); template.setText(command.stringValueOfParameterNamed(PROPERTY_TEXT));
template.setEntity(TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_ENTITY)]); template.setEntity(TemplateEntity.values()[command
template.setType(TemplateType.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_TYPE)]); .integerValueSansLocaleOfParameterNamed(PROPERTY_ENTITY)]);
final int templateTypeId = command
.integerValueSansLocaleOfParameterNamed(PROPERTY_TYPE);
TemplateType type = null;
switch (templateTypeId) {
case 0 :
type = TemplateType.DOCUMENT;
break;
case 2 :
type = TemplateType.SMS;
break;
}
template.setType(type);
final JsonArray array = command.arrayOfParameterNamed("mappers"); final JsonArray array = command.arrayOfParameterNamed("mappers");
final List<TemplateMapper> mappersList = new ArrayList<>(); final List<TemplateMapper> mappersList = new ArrayList<>();
for (final JsonElement element : array) { for (final JsonElement element : array) {
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject() mappersList.add(new TemplateMapper(element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString())); .get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject()
.get("mappersvalue").getAsString()));
} }
template.setMappers(mappersList); template.setMappers(mappersList);
this.templateRepository.saveAndFlush(template); this.templateRepository.saveAndFlush(template);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(template.getId()).build(); return new CommandProcessingResultBuilder()
.withCommandId(command.commandId())
.withEntityId(template.getId()).build();
} }
@Transactional @Transactional
@@ -95,7 +115,8 @@ public class JpaTemplateDomainService implements TemplateDomainService {
this.templateRepository.delete(template); this.templateRepository.delete(template);
return new CommandProcessingResultBuilder().withEntityId(templateId).build(); return new CommandProcessingResultBuilder().withEntityId(templateId)
.build();
} }
@Transactional @Transactional
@@ -105,7 +126,8 @@ public class JpaTemplateDomainService implements TemplateDomainService {
} }
@Override @Override
public List<Template> getAllByEntityAndType(final TemplateEntity entity, final TemplateType type) { public List<Template> getAllByEntityAndType(final TemplateEntity entity,
final TemplateType type) {
return this.templateRepository.findByEntityAndType(entity, type); return this.templateRepository.findByEntityAndType(entity, type);
} }
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectMapper;
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
import org.mifosplatform.template.domain.Template; import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateFunctions; import org.mifosplatform.template.domain.TemplateFunctions;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@@ -37,21 +38,30 @@ public class TemplateMergeService {
// private final FromJsonHelper fromApiJsonHelper; // private final FromJsonHelper fromApiJsonHelper;
private Map<String, Object> scopes; private Map<String, Object> scopes;
private String authToken;
// @Autowired // @Autowired
// public TemplateMergeService(final FromJsonHelper fromApiJsonHelper) { // public TemplateMergeService(final FromJsonHelper fromApiJsonHelper) {
// this.fromApiJsonHelper = fromApiJsonHelper; // this.fromApiJsonHelper = fromApiJsonHelper;
// } // }
public String compile(final Template template, final Map<String, Object> scopes) throws MalformedURLException, IOException { public void setAuthToken(final String authToken) {
this.authToken = authToken;
}
public String compile(final Template template,
final Map<String, Object> scopes) throws MalformedURLException,
IOException {
this.scopes = scopes; this.scopes = scopes;
this.scopes.put("static", new TemplateFunctions()); this.scopes.put("static", new TemplateFunctions());
final MustacheFactory mf = new DefaultMustacheFactory(); final MustacheFactory mf = new DefaultMustacheFactory();
final Mustache mustache = mf.compile(new StringReader(template.getText()), template.getName()); final Mustache mustache = mf.compile(
new StringReader(template.getText()), template.getName());
final Map<String, Object> mappers = getCompiledMapFromMappers(template.getMappersAsMap()); final Map<String, Object> mappers = getCompiledMapFromMappers(template
.getMappersAsMap());
this.scopes.putAll(mappers); this.scopes.putAll(mappers);
final StringWriter stringWriter = new StringWriter(); final StringWriter stringWriter = new StringWriter();
@@ -60,14 +70,16 @@ public class TemplateMergeService {
return stringWriter.toString(); return stringWriter.toString();
} }
private Map<String, Object> getCompiledMapFromMappers(final Map<String, String> data) { private Map<String, Object> getCompiledMapFromMappers(
final Map<String, String> data) {
final MustacheFactory mf = new DefaultMustacheFactory(); final MustacheFactory mf = new DefaultMustacheFactory();
if (data != null) { if (data != null) {
for (final Map.Entry<String, String> entry : data.entrySet()) { for (final Map.Entry<String, String> entry : data.entrySet()) {
final Mustache mappersMustache = mf.compile(new StringReader(entry.getValue()), ""); final Mustache mappersMustache = mf.compile(new StringReader(
entry.getValue()), "");
final StringWriter stringWriter = new StringWriter(); final StringWriter stringWriter = new StringWriter();
mappersMustache.execute(stringWriter, this.scopes); mappersMustache.execute(stringWriter, this.scopes);
@@ -88,11 +100,13 @@ public class TemplateMergeService {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Map<String, Object> getMapFromUrl(final String url) throws MalformedURLException, IOException { private Map<String, Object> getMapFromUrl(final String url)
throws MalformedURLException, IOException {
final HttpURLConnection connection = getConnection(url); final HttpURLConnection connection = getConnection(url);
final String response = getStringFromInputStream(connection.getInputStream()); final String response = getStringFromInputStream(connection
.getInputStream());
HashMap<String, Object> result = new HashMap<>(); HashMap<String, Object> result = new HashMap<>();
if (connection.getContentType().equals("text/plain")) { if (connection.getContentType().equals("text/plain")) {
result.put("src", response); result.put("src", response);
@@ -104,20 +118,29 @@ public class TemplateMergeService {
private HttpURLConnection getConnection(final String url) { private HttpURLConnection getConnection(final String url) {
final String name = SecurityContextHolder.getContext().getAuthentication().getName(); if (this.authToken == null) {
final String password = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString(); final String name = SecurityContextHolder.getContext()
.getAuthentication().getName();
final String password = SecurityContextHolder.getContext()
.getAuthentication().getCredentials().toString();
Authenticator.setDefault(new Authenticator() { Authenticator.setDefault(new Authenticator() {
@Override @Override
protected PasswordAuthentication getPasswordAuthentication() { protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(name, password.toCharArray()); return new PasswordAuthentication(name, password
.toCharArray());
} }
}); });
}
HttpURLConnection connection = null; HttpURLConnection connection = null;
try { try {
connection = (HttpURLConnection) new URL(url).openConnection(); connection = (HttpURLConnection) new URL(url).openConnection();
if (this.authToken != null) {
connection.setRequestProperty("Authorization", "Basic "
+ this.authToken);
}
TrustModifier.relaxHostChecking(connection); TrustModifier.relaxHostChecking(connection);
connection.setDoInput(true); connection.setDoInput(true);
@@ -0,0 +1,2 @@
ALTER TABLE `m_hook` ADD COLUMN `ugd_template_id` bigint(20) NOT NULL;
ALTER TABLE `m_hook` ADD CONSTRAINT `fk_ugd_template_id` FOREIGN KEY (`ugd_template_id`) REFERENCES `m_template` (`id`);