MIFOSX-97: process role commands through command_source table.

This commit is contained in:
Keith Woodlock
2012-11-22 14:51:53 +00:00
parent 85de5e92c2
commit 79ff5a7511
17 changed files with 1162 additions and 1054 deletions
@@ -60,436 +60,402 @@ import com.sun.jersey.multipart.FormDataParam;
@Scope("singleton") @Scope("singleton")
public class ClientsApiResource { public class ClientsApiResource {
private final static Logger logger = LoggerFactory.getLogger(ClientsApiResource.class); private final static Logger logger = LoggerFactory.getLogger(ClientsApiResource.class);
@Autowired @Autowired
private ClientReadPlatformService clientReadPlatformService; private ClientReadPlatformService clientReadPlatformService;
@Autowired @Autowired
private ClientWritePlatformService clientWritePlatformService; private ClientWritePlatformService clientWritePlatformService;
@Autowired
private PortfolioCommandsReadPlatformService commandSourceReadPlatformService;
@Autowired
private PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired @Autowired
private OfficeReadPlatformService officeReadPlatformService; private PortfolioCommandsReadPlatformService commandSourceReadPlatformService;
@Autowired
private PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
private OfficeReadPlatformService officeReadPlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
@Autowired @Autowired
private PlatformSecurityContext context; private PlatformSecurityContext context;
@GET
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveAllIndividualClients(@Context final UriInfo uriInfo,
@QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("officeId") final Integer officeId,
@QueryParam("externalId") final String externalId,
@QueryParam("displayName") final String displayName,
@QueryParam("firstName") final String firstName,
@QueryParam("lastName") final String lastName,
@QueryParam("underHierarchy") final String hierarchy) {
context.authenticatedUser().validateHasReadPermission("CLIENT"); @GET
@Consumes({ MediaType.APPLICATION_JSON })
final String extraCriteria = getClientCriteria(sqlSearch, officeId, externalId, displayName, firstName, lastName, hierarchy); @Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllIndividualClients(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); @QueryParam("officeId") final Integer officeId, @QueryParam("externalId") final String externalId,
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); @QueryParam("displayName") final String displayName, @QueryParam("firstName") final String firstName,
@QueryParam("lastName") final String lastName, @QueryParam("underHierarchy") final String hierarchy) {
final Collection<ClientData> clients = this.clientReadPlatformService.retrieveAllIndividualClients(extraCriteria); context.authenticatedUser().validateHasReadPermission("CLIENT");
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clients);
}
private String getClientCriteria(String sqlSearch, Integer officeId, final String extraCriteria = getClientCriteria(sqlSearch, officeId, externalId, displayName, firstName, lastName, hierarchy);
String externalId, String displayName, String firstName,
String lastName, String hierarchy) {
String extraCriteria = ""; final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
if (sqlSearch != null) { final Collection<ClientData> clients = this.clientReadPlatformService.retrieveAllIndividualClients(extraCriteria);
extraCriteria = " and (" + sqlSearch + ")";
}
if (officeId != null) { return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clients);
extraCriteria += " and office_id = " + officeId; }
}
if (externalId != null) {
extraCriteria += " and external_id like " + ApiParameterHelper.sqlEncodeString(externalId);
}
if (displayName != null) {
extraCriteria += " and concat(ifnull(firstname, ''), if(firstname > '',' ', '') , ifnull(lastname, '')) like "
+ ApiParameterHelper.sqlEncodeString(displayName);
}
if (firstName != null) {
extraCriteria += " and firstname like " + ApiParameterHelper.sqlEncodeString(firstName);
}
if (lastName != null) {
extraCriteria += " and lastname like " + ApiParameterHelper.sqlEncodeString(lastName);
}
if (hierarchy != null) {
extraCriteria += " and o.hierarchy like " + ApiParameterHelper.sqlEncodeString(hierarchy+"%");
}
if (StringUtils.isNotBlank(extraCriteria)) { private String getClientCriteria(String sqlSearch, Integer officeId, String externalId, String displayName, String firstName,
extraCriteria = extraCriteria.substring(4); String lastName, String hierarchy) {
}
logger.info("extraCriteria; " + extraCriteria); String extraCriteria = "";
return extraCriteria; if (sqlSearch != null) {
} extraCriteria = " and (" + sqlSearch + ")";
}
@GET if (officeId != null) {
@Path("{clientId}") extraCriteria += " and office_id = " + officeId;
@Consumes({MediaType.APPLICATION_JSON}) }
@Produces({MediaType.APPLICATION_JSON})
public String retrieveClient(
@PathParam("clientId") final Long clientId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENT"); if (externalId != null) {
extraCriteria += " and external_id like " + ApiParameterHelper.sqlEncodeString(externalId);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); }
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
final Long makerCheckerId = ApiParameterHelper.makerCheckerId(uriInfo.getQueryParameters());
ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId);
if (template) {
final List<OfficeLookup> allowedOffices = new ArrayList<OfficeLookup>(officeReadPlatformService.retrieveAllOfficesForLookup());
clientData = ClientData.templateOnTop(clientData, allowedOffices);
}
if (makerCheckerId != null) {
clientData = handleMakerCheckerRequest(clientId, makerCheckerId, clientData);
}
boolean retrieveChanges = true;
if (retrieveChanges) {
final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
clientData = ClientData.integrateChanges(clientData, clientData.currentChange(), dataChanges);
}
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData); if (displayName != null) {
} extraCriteria += " and concat(ifnull(firstname, ''), if(firstname > '',' ', '') , ifnull(lastname, '')) like "
+ ApiParameterHelper.sqlEncodeString(displayName);
}
private ClientData handleMakerCheckerRequest(final Long clientId, final Long makerCheckerId, ClientData clientData) { if (firstName != null) {
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId); extraCriteria += " and firstname like " + ApiParameterHelper.sqlEncodeString(firstName);
final ClientData currentChange = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, entry.json()); }
final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
clientData = ClientData.integrateChanges(clientData, currentChange, dataChanges);
return clientData;
}
private Collection<ClientData> retrieveAllUnprocessedDataChanges(final Long clientId) { if (lastName != null) {
Collection<ClientData> dataChanges = new ArrayList<ClientData>(); extraCriteria += " and lastname like " + ApiParameterHelper.sqlEncodeString(lastName);
}
boolean retrieveChanges = true;
if (retrieveChanges) {
Collection<CommandSourceData> unprocessedChanges = this.commandSourceReadPlatformService.retrieveUnprocessChangesByResourceId("clients", clientId);
for (CommandSourceData commandSourceData : unprocessedChanges) {
ClientData change = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, commandSourceData.json());
dataChanges.add(change);
}
}
if (dataChanges.isEmpty()) {
dataChanges = null;
}
return dataChanges;
}
@GET if (hierarchy != null) {
@Path("template") extraCriteria += " and o.hierarchy like " + ApiParameterHelper.sqlEncodeString(hierarchy + "%");
@Consumes({MediaType.APPLICATION_JSON}) }
@Produces({MediaType.APPLICATION_JSON})
public String newClientDetails(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENT"); if (StringUtils.isNotBlank(extraCriteria)) {
extraCriteria = extraCriteria.substring(4);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); }
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final Long makerCheckerId = ApiParameterHelper.makerCheckerId(uriInfo.getQueryParameters());
ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails();
if (makerCheckerId != null) {
clientData = handleMakerCheckerRequest(null, makerCheckerId, clientData);
}
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
}
@POST logger.info("extraCriteria; " + extraCriteria);
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String createClient(final String jsonRequestBody) {
final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("CREATE", "clients", null, jsonRequestBody);
return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
@PUT return extraCriteria;
@Path("{clientId}") }
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String updateClient(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "clients", clientId, jsonRequestBody); @GET
@Path("{clientId}")
return this.apiJsonSerializerService.serializeEntityIdentifier(result); @Consumes({ MediaType.APPLICATION_JSON })
} @Produces({ MediaType.APPLICATION_JSON })
public String retrieveClient(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
@DELETE
@Path("{clientId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String deleteClient(@PathParam("clientId") final Long clientId) {
final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("DELETE", "clients", clientId, "{}"); context.authenticatedUser().validateHasReadPermission("CLIENT");
return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
@GET final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
@Path("{clientId}/loans") final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
@Consumes({MediaType.APPLICATION_JSON}) final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
@Produces({MediaType.APPLICATION_JSON}) final Long makerCheckerId = ApiParameterHelper.makerCheckerId(uriInfo.getQueryParameters());
public String retrieveClientAccount(@PathParam("clientId") final Long clientId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENT"); ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId);
if (template) {
Set<String> typicalResponseParameters = new HashSet<String>( final List<OfficeLookup> allowedOffices = new ArrayList<OfficeLookup>(officeReadPlatformService.retrieveAllOfficesForLookup());
Arrays.asList("pendingApprovalLoans", "awaitingDisbursalLoans", "openLoans", "closedLoans", clientData = ClientData.templateOnTop(clientData, allowedOffices);
"anyLoanCount", "pendingApprovalLoanCount", "awaitingDisbursalLoanCount", "activeLoanCount", "closedLoanCount", }
"pendingApprovalDespositAccountsCount", "pendingApprovalDespositAccounts", "approvedDespositAccountsCount", "approvedDespositAccounts", if (makerCheckerId != null) {
"withdrawnByClientDespositAccountsCount","withdrawnByClientDespositAccounts","closedDepositAccountsCount","closedDepositAccounts", clientData = handleMakerCheckerRequest(clientId, makerCheckerId, clientData);
"rejectedDepositAccountsCount","rejectedDepositAccounts","preclosedDepositAccountsCount","preclosedDepositAccounts") }
);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
ClientAccountSummaryCollectionData clientAccount = this.clientReadPlatformService.retrieveClientAccountDetails(clientId);
return this.apiJsonSerializerService.serializeClientAccountSummaryCollectionDataToJson(prettyPrint, responseParameters, clientAccount);
}
@GET boolean retrieveChanges = true;
@Path("{clientId}/notes") if (retrieveChanges) {
@Consumes({MediaType.APPLICATION_JSON}) final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
@Produces({MediaType.APPLICATION_JSON}) clientData = ClientData.integrateChanges(clientData, clientData.currentChange(), dataChanges);
public String retrieveAllClientNotes(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) { }
context.authenticatedUser().validateHasReadPermission("CLIENTNOTE"); return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
}
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "clientId", "loanId", "loanTransactionId", "noteType", "note", "createdById", "createdByUsername",
"createdOn", "updatedById", "updatedByUsername", "updatedOn")
);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
Collection<NoteData> notes = this.clientReadPlatformService.retrieveAllClientNotes(clientId);
return this.apiJsonSerializerService.serializeNoteDataToJson(prettyPrint, responseParameters, notes);
}
@POST private ClientData handleMakerCheckerRequest(final Long clientId, final Long makerCheckerId, ClientData clientData) {
@Path("{clientId}/notes") final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
@Consumes({MediaType.APPLICATION_JSON}) final ClientData currentChange = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, entry.json());
@Produces({MediaType.APPLICATION_JSON})
public Response addNewClientNote(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
NoteCommand command = this.apiDataConversionService.convertJsonToNoteCommand(null, clientId, jsonRequestBody); final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
clientData = ClientData.integrateChanges(clientData, currentChange, dataChanges);
EntityIdentifier identifier = this.clientWritePlatformService.addClientNote(command); return clientData;
}
return Response.ok().entity(identifier).build(); private Collection<ClientData> retrieveAllUnprocessedDataChanges(final Long clientId) {
} Collection<ClientData> dataChanges = new ArrayList<ClientData>();
@GET boolean retrieveChanges = true;
@Path("{clientId}/notes/{noteId}") if (retrieveChanges) {
@Consumes({MediaType.APPLICATION_JSON}) Collection<CommandSourceData> unprocessedChanges = this.commandSourceReadPlatformService.retrieveUnprocessChangesByResourceId(
@Produces({MediaType.APPLICATION_JSON}) "clients", clientId);
public String retrieveClientNote( for (CommandSourceData commandSourceData : unprocessedChanges) {
@PathParam("clientId") final Long clientId, ClientData change = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId,
@PathParam("noteId") final Long noteId, commandSourceData.json());
@Context final UriInfo uriInfo) { dataChanges.add(change);
}
}
context.authenticatedUser().validateHasReadPermission("CLIENTNOTE"); if (dataChanges.isEmpty()) {
dataChanges = null;
Set<String> typicalResponseParameters = new HashSet<String>( }
Arrays.asList("id", "clientId", "loanId", "loanTransactionId", "noteType", "note", "createdById", "createdByUsername",
"createdOn", "updatedById", "updatedByUsername", "updatedOn")
);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
NoteData note = this.clientReadPlatformService.retrieveClientNote(clientId, noteId);
return this.apiJsonSerializerService.serializeNoteDataToJson(prettyPrint, responseParameters, note);
}
@PUT return dataChanges;
@Path("{clientId}/notes/{noteId}") }
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response updateClientNote(
@PathParam("clientId") final Long clientId,
@PathParam("noteId") final Long noteId, final String jsonRequestBody) {
NoteCommand command = this.apiDataConversionService.convertJsonToNoteCommand(noteId, clientId, jsonRequestBody); @GET
@Path("template")
EntityIdentifier identifier = this.clientWritePlatformService.updateNote(command); @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String newClientDetails(@Context final UriInfo uriInfo) {
return Response.ok().entity(identifier).build(); context.authenticatedUser().validateHasReadPermission("CLIENT");
}
/**
* Upload images through multi-part form upload
*/
@POST
@Path("{clientId}/image")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Produces({ MediaType.APPLICATION_JSON })
public Response addNewClientImage(
@PathParam("clientId") final Long clientId,
@HeaderParam("Content-Length") Long fileSize,
@FormDataParam("file") InputStream inputStream,
@FormDataParam("file") FormDataContentDisposition fileDetails,
@FormDataParam("file") FormDataBodyPart bodyPart) {
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
//TODO: vishwas might need more advances validation (like reading magic number) for handling malicious clients final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
//and clients not setting mime type final Long makerCheckerId = ApiParameterHelper.makerCheckerId(uriInfo.getQueryParameters());
FileUtils.validateClientImageNotEmpty(fileDetails.getFileName());
FileUtils.validateImageMimeType(bodyPart.getMediaType().toString());
FileUtils.validateFileSizeWithinPermissibleRange(fileSize,
fileDetails.getFileName(),
ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
logger.debug(bodyPart.getMediaType().toString());
EntityIdentifier entityIdentifier = this.clientWritePlatformService ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails();
.saveOrUpdateClientImage(clientId, fileDetails.getFileName(), if (makerCheckerId != null) {
inputStream); clientData = handleMakerCheckerRequest(null, makerCheckerId, clientData);
}
return Response.ok().entity(entityIdentifier).build(); return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
} }
/** @POST
* Upload image as a Data URL (essentially a base64 encoded stream) @Consumes({ MediaType.APPLICATION_JSON })
*/ @Produces({ MediaType.APPLICATION_JSON })
@POST public String createClient(final String jsonRequestBody) {
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addNewClientImage(
@PathParam("clientId") final Long clientId,
final String jsonRequestBody) {
Base64EncodedImage base64EncodedImage = FileUtils final EntityIdentifier result = this.commandsSourceWritePlatformService
.extractImageFromDataURL(jsonRequestBody); .logCommandSource("CREATE", "clients", null, jsonRequestBody);
EntityIdentifier entityIdentifier = this.clientWritePlatformService return this.apiJsonSerializerService.serializeEntityIdentifier(result);
.saveOrUpdateClientImage(clientId, base64EncodedImage); }
return Response.ok().entity(entityIdentifier).build(); @PUT
} @Path("{clientId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateClient(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
/** final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "clients", clientId,
* Returns a base 64 encoded client image jsonRequestBody);
*/
@GET
@Path("{clientId}/image")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response retrieveClientImage(
@PathParam("clientId") final Long clientId) {
context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE"); return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId);
if (clientData.imageKeyDoesNotExist()) { @DELETE
throw new ImageNotFoundException("clients", clientId); @Path("{clientId}")
} @Consumes({ MediaType.APPLICATION_JSON })
return Response.ok().entity(Base64.encodeFromFile(clientData.imageKey())).build(); @Produces({ MediaType.APPLICATION_JSON })
} public String deleteClient(@PathParam("clientId") final Long clientId) {
/** final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("DELETE", "clients", clientId, "{}");
* This method is added only for consistency with other URL patterns
* and for maintaining consistency of usage of the HTTP "verb" return this.apiJsonSerializerService.serializeEntityIdentifier(result);
* at the client side }
*/
@PUT @GET
@Path("{clientId}/image") @Path("{clientId}/loans")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public Response updateClientImage( public String retrieveClientAccount(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
@PathParam("clientId") final Long clientId,
@HeaderParam("Content-Length") Long fileSize, context.authenticatedUser().validateHasReadPermission("CLIENT");
@FormDataParam("file") InputStream inputStream,
@FormDataParam("file") FormDataContentDisposition fileDetails, Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("pendingApprovalLoans", "awaitingDisbursalLoans",
@FormDataParam("file") FormDataBodyPart bodyPart) { "openLoans", "closedLoans", "anyLoanCount", "pendingApprovalLoanCount", "awaitingDisbursalLoanCount", "activeLoanCount",
return addNewClientImage(clientId, fileSize, inputStream, fileDetails, "closedLoanCount", "pendingApprovalDespositAccountsCount", "pendingApprovalDespositAccounts",
bodyPart); "approvedDespositAccountsCount", "approvedDespositAccounts", "withdrawnByClientDespositAccountsCount",
} "withdrawnByClientDespositAccounts", "closedDepositAccountsCount", "closedDepositAccounts", "rejectedDepositAccountsCount",
"rejectedDepositAccounts", "preclosedDepositAccountsCount", "preclosedDepositAccounts"));
@DELETE
@Path("{clientId}/image") Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
@Consumes({MediaType.APPLICATION_JSON}) if (responseParameters.isEmpty()) {
@Produces({MediaType.APPLICATION_JSON}) responseParameters.addAll(typicalResponseParameters);
public Response deleteClientImage(@PathParam("clientId") final Long clientId) { }
this.clientWritePlatformService.deleteClientImage(clientId); boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
return Response.ok(new EntityIdentifier(clientId)).build();
} ClientAccountSummaryCollectionData clientAccount = this.clientReadPlatformService.retrieveClientAccountDetails(clientId);
return this.apiJsonSerializerService.serializeClientAccountSummaryCollectionDataToJson(prettyPrint, responseParameters,
/** clientAccount);
* This method is added only for consistency with other URL patterns }
* and for maintaining consistency of usage of the HTTP "verb"
* at the client side @GET
* @Path("{clientId}/notes")
* Upload image as a Data URL (essentially a base64 encoded stream) @Consumes({ MediaType.APPLICATION_JSON })
*/ @Produces({ MediaType.APPLICATION_JSON })
@PUT public String retrieveAllClientNotes(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON }) context.authenticatedUser().validateHasReadPermission("CLIENTNOTE");
@Produces({ MediaType.APPLICATION_JSON })
public Response updateClientImage( Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "clientId", "loanId", "loanTransactionId",
@PathParam("clientId") final Long clientId, "noteType", "note", "createdById", "createdByUsername", "createdOn", "updatedById", "updatedByUsername", "updatedOn"));
final String jsonRequestBody) {
return addNewClientImage(clientId, jsonRequestBody); Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
} if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
Collection<NoteData> notes = this.clientReadPlatformService.retrieveAllClientNotes(clientId);
return this.apiJsonSerializerService.serializeNoteDataToJson(prettyPrint, responseParameters, notes);
}
@POST
@Path("{clientId}/notes")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addNewClientNote(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
NoteCommand command = this.apiDataConversionService.convertJsonToNoteCommand(null, clientId, jsonRequestBody);
EntityIdentifier identifier = this.clientWritePlatformService.addClientNote(command);
return Response.ok().entity(identifier).build();
}
@GET
@Path("{clientId}/notes/{noteId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENTNOTE");
Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "clientId", "loanId", "loanTransactionId",
"noteType", "note", "createdById", "createdByUsername", "createdOn", "updatedById", "updatedByUsername", "updatedOn"));
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
NoteData note = this.clientReadPlatformService.retrieveClientNote(clientId, noteId);
return this.apiJsonSerializerService.serializeNoteDataToJson(prettyPrint, responseParameters, note);
}
@PUT
@Path("{clientId}/notes/{noteId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateClientNote(@PathParam("clientId") final Long clientId, @PathParam("noteId") final Long noteId,
final String jsonRequestBody) {
NoteCommand command = this.apiDataConversionService.convertJsonToNoteCommand(noteId, clientId, jsonRequestBody);
EntityIdentifier identifier = this.clientWritePlatformService.updateNote(command);
return Response.ok().entity(identifier).build();
}
/**
* Upload images through multi-part form upload
*/
@POST
@Path("{clientId}/image")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Produces({ MediaType.APPLICATION_JSON })
public Response addNewClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") Long fileSize,
@FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetails,
@FormDataParam("file") FormDataBodyPart bodyPart) {
// TODO: vishwas might need more advances validation (like reading magic
// number) for handling malicious clients
// and clients not setting mime type
FileUtils.validateClientImageNotEmpty(fileDetails.getFileName());
FileUtils.validateImageMimeType(bodyPart.getMediaType().toString());
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, fileDetails.getFileName(), ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
logger.debug(bodyPart.getMediaType().toString());
EntityIdentifier entityIdentifier = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, fileDetails.getFileName(),
inputStream);
return Response.ok().entity(entityIdentifier).build();
}
/**
* Upload image as a Data URL (essentially a base64 encoded stream)
*/
@POST
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addNewClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
Base64EncodedImage base64EncodedImage = FileUtils.extractImageFromDataURL(jsonRequestBody);
EntityIdentifier entityIdentifier = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, base64EncodedImage);
return Response.ok().entity(entityIdentifier).build();
}
/**
* Returns a base 64 encoded client image
*/
@GET
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response retrieveClientImage(@PathParam("clientId") final Long clientId) {
context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE");
final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId);
if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); }
return Response.ok().entity(Base64.encodeFromFile(clientData.imageKey())).build();
}
/**
* This method is added only for consistency with other URL patterns and for
* maintaining consistency of usage of the HTTP "verb" at the client side
*/
@PUT
@Path("{clientId}/image")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") Long fileSize,
@FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetails,
@FormDataParam("file") FormDataBodyPart bodyPart) {
return addNewClientImage(clientId, fileSize, inputStream, fileDetails, bodyPart);
}
@DELETE
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response deleteClientImage(@PathParam("clientId") final Long clientId) {
this.clientWritePlatformService.deleteClientImage(clientId);
return Response.ok(new EntityIdentifier(clientId)).build();
}
/**
* This method is added only for consistency with other URL patterns and for
* maintaining consistency of usage of the HTTP "verb" at the client side
*
* Upload image as a Data URL (essentially a base64 encoded stream)
*/
@PUT
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
return addNewClientImage(clientId, jsonRequestBody);
}
} }
@@ -25,6 +25,7 @@ import org.mifosng.platform.api.data.RolePermissionsData;
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService; import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService; import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
import org.mifosng.platform.infrastructure.api.ApiParameterHelper; import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
import org.mifosng.platform.makerchecker.service.PortfolioCommandSourceWritePlatformService;
import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.service.PermissionReadPlatformService; import org.mifosng.platform.user.service.PermissionReadPlatformService;
import org.mifosng.platform.user.service.RoleReadPlatformService; import org.mifosng.platform.user.service.RoleReadPlatformService;
@@ -52,6 +53,9 @@ public class RolesApiResource {
@Autowired @Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService; private PortfolioApiJsonSerializerService apiJsonSerializerService;
@Autowired
private PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired @Autowired
private PlatformSecurityContext context; private PlatformSecurityContext context;
@@ -77,7 +81,7 @@ public class RolesApiResource {
@Path("template") @Path("template")
@Consumes({MediaType.APPLICATION_JSON}) @Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON})
public String retrieveNewRoleDetails(@Context final UriInfo uriInfo) { public String retrieveRoleTemplate(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
@@ -94,13 +98,11 @@ public class RolesApiResource {
@POST @POST
@Consumes({MediaType.APPLICATION_JSON}) @Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON})
public String createRole(final String jsonRequestBody) { public String createRole(final String apiRequestBodyAsJson) {
final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("CREATE", "roles", null, apiRequestBodyAsJson);
final RoleCommand command = this.apiDataConversionService.convertJsonToRoleCommand(null, jsonRequestBody); return this.apiJsonSerializerService.serializeEntityIdentifier(result);
final Long roleId = this.roleWritePlatformService.createRole(command);
return this.apiJsonSerializerService.serializeEntityIdentifier(new EntityIdentifier(roleId));
} }
// TODO - General thing to fix about REST API is if use partial response // TODO - General thing to fix about REST API is if use partial response
@@ -140,7 +142,7 @@ public class RolesApiResource {
@Produces({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON})
public String updateRole(@PathParam("roleId") final Long roleId, final String jsonRequestBody) { public String updateRole(@PathParam("roleId") final Long roleId, final String jsonRequestBody) {
final RoleCommand command = this.apiDataConversionService.convertJsonToRoleCommand(roleId, jsonRequestBody); final RoleCommand command = this.apiDataConversionService.convertApiRequestJsonToRoleCommand(roleId, jsonRequestBody);
this.roleWritePlatformService.updateRole(command); this.roleWritePlatformService.updateRole(command);
@@ -9,92 +9,85 @@ import org.joda.time.LocalDate;
*/ */
public class ClientCommand { public class ClientCommand {
private final String externalId; private final String externalId;
private final String firstname; private final String firstname;
private final String lastname; private final String lastname;
private final String clientOrBusinessName; private final String clientOrBusinessName;
private final Long officeId; private final Long officeId;
private final LocalDate joiningDate; private final LocalDate joiningDate;
// made transient as dont want them to be serialized/converted to JSON // made transient as dont want them to be serialized/converted to JSON
private final transient Long id; private final transient Long id;
private final transient boolean makerCheckerApproval; private final transient boolean makerCheckerApproval;
private final transient Set<String> parametersPassedInRequest; private final transient Set<String> parametersPassedInRequest;
public ClientCommand(
final Set<String> modifiedParameters,
final Long id,
final String externalId,
final String firstname,
final String lastname,
final String clientOrBusinessName,
final Long officeId,
final LocalDate joiningDate,
final boolean makerCheckerApproval) {
this.parametersPassedInRequest = modifiedParameters;
this.id = id;
this.externalId = externalId;
this.firstname = firstname;
this.lastname = lastname;
this.clientOrBusinessName = clientOrBusinessName;
this.officeId = officeId;
this.joiningDate = joiningDate;
this.makerCheckerApproval = makerCheckerApproval;
}
public Long getId() { public ClientCommand(final Set<String> modifiedParameters, final Long id, final String externalId, final String firstname,
return id; final String lastname, final String clientOrBusinessName, final Long officeId, final LocalDate joiningDate,
} final boolean makerCheckerApproval) {
this.parametersPassedInRequest = modifiedParameters;
this.id = id;
this.externalId = externalId;
this.firstname = firstname;
this.lastname = lastname;
this.clientOrBusinessName = clientOrBusinessName;
this.officeId = officeId;
this.joiningDate = joiningDate;
this.makerCheckerApproval = makerCheckerApproval;
}
public String getExternalId() { public Long getId() {
return externalId; return id;
} }
public String getFirstname() { public String getExternalId() {
return firstname; return externalId;
} }
public String getLastname() { public String getFirstname() {
return lastname; return firstname;
} }
public String getClientOrBusinessName() { public String getLastname() {
return clientOrBusinessName; return lastname;
} }
public Long getOfficeId() { public String getClientOrBusinessName() {
return officeId; return clientOrBusinessName;
} }
public LocalDate getJoiningDate() { public Long getOfficeId() {
return joiningDate; return officeId;
} }
public boolean isFirstnameChanged() {
return this.parametersPassedInRequest.contains("firstname");
}
public boolean isLastnameChanged() {
return this.parametersPassedInRequest.contains("lastname");
}
public boolean isClientOrBusinessNameChanged() {
return this.parametersPassedInRequest.contains("clientOrBusinessName");
}
public boolean isExternalIdChanged() {
return this.parametersPassedInRequest.contains("externalId");
}
public boolean isJoiningDateChanged() {
return this.parametersPassedInRequest.contains("joiningDate");
}
public boolean isOfficeChanged() {
return this.parametersPassedInRequest.contains("officeId");
}
public boolean isApprovedByChecker() { public LocalDate getJoiningDate() {
return this.makerCheckerApproval; return joiningDate;
} }
public boolean isFirstnameChanged() {
return this.parametersPassedInRequest.contains("firstname");
}
public boolean isLastnameChanged() {
return this.parametersPassedInRequest.contains("lastname");
}
public boolean isClientOrBusinessNameChanged() {
return this.parametersPassedInRequest.contains("clientOrBusinessName");
}
public boolean isExternalIdChanged() {
return this.parametersPassedInRequest.contains("externalId");
}
public boolean isJoiningDateChanged() {
return this.parametersPassedInRequest.contains("joiningDate");
}
public boolean isOfficeChanged() {
return this.parametersPassedInRequest.contains("officeId");
}
public boolean isApprovedByChecker() {
return this.makerCheckerApproval;
}
} }
@@ -4,17 +4,26 @@ import java.util.Set;
/** /**
* Immutable command for creating or updating details of a role. * Immutable command for creating or updating details of a role.
*
* <p>Fields that are transient are intended not to be serialized into JSON.</p>
*/ */
public class RoleCommand { public class RoleCommand {
private final Long id; private final transient Long id;
private final String name; private final String name;
private final String description; private final String description;
private final Set<String> modifiedParameters; private final transient boolean makerCheckerApproval;
private final transient Set<String> modifiedParameters;
public RoleCommand(Set<String> modifiedParameters, final Long id, final String name, final String description) { public RoleCommand(
final Set<String> modifiedParameters,
final boolean makerCheckerApproval,
final Long id,
final String name,
final String description) {
this.modifiedParameters = modifiedParameters; this.modifiedParameters = modifiedParameters;
this.makerCheckerApproval = makerCheckerApproval;
this.id = id; this.id = id;
this.name = name; this.name = name;
this.description = description; this.description = description;
@@ -39,4 +48,8 @@ public class RoleCommand {
public boolean isDescriptionChanged() { public boolean isDescriptionChanged() {
return this.modifiedParameters.contains("description"); return this.modifiedParameters.contains("description");
} }
public boolean isApprovedByChecker() {
return this.makerCheckerApproval;
}
} }
@@ -40,7 +40,7 @@ public interface PortfolioApiDataConversionService {
OfficeCommand convertJsonToOfficeCommand(Long resourceIdentifier, String json); OfficeCommand convertJsonToOfficeCommand(Long resourceIdentifier, String json);
RoleCommand convertJsonToRoleCommand(Long resourceIdentifier, String json); RoleCommand convertApiRequestJsonToRoleCommand(Long resourceIdentifier, String json);
RolePermissionCommand convertJsonToRolePermissionCommand(Long roleId, String jsonRequestBody); RolePermissionCommand convertJsonToRolePermissionCommand(Long roleId, String jsonRequestBody);
@@ -53,6 +53,7 @@ import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.infrastructure.api.JsonParserHelper; import org.mifosng.platform.infrastructure.api.JsonParserHelper;
import org.mifosng.platform.infrastructure.errorhandling.InvalidJsonException; import org.mifosng.platform.infrastructure.errorhandling.InvalidJsonException;
import org.mifosng.platform.infrastructure.errorhandling.UnsupportedParameterException; import org.mifosng.platform.infrastructure.errorhandling.UnsupportedParameterException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.number.NumberFormatter; import org.springframework.format.number.NumberFormatter;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -66,9 +67,20 @@ import com.google.gson.reflect.TypeToken;
@Service @Service
public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataConversionService { public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataConversionService {
/**
* Used in places where the support json of the api request is not any
* different to that of the json of a serialized command object.
*/
private final PortfolioCommandDeserializerService portfolioCommandDeserializerService;
/**
* Google-gson class for converting to and from json.
*/
private final Gson gsonConverter; private final Gson gsonConverter;
public PortfolioApiDataConversionServiceImpl() { @Autowired
public PortfolioApiDataConversionServiceImpl(final PortfolioCommandDeserializerService portfolioCommandDeserializerService) {
this.portfolioCommandDeserializerService = portfolioCommandDeserializerService;
gsonConverter = new Gson(); gsonConverter = new Gson();
} }
@@ -229,22 +241,20 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
} }
@Override @Override
public RoleCommand convertJsonToRoleCommand(final Long resourceIdentifier, final String json) { public RoleCommand convertApiRequestJsonToRoleCommand(final Long resourceIdentifier, final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType(); final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap); final Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
Set<String> supportedParams = new HashSet<String>(Arrays.asList("name", "description", "permissions")); final Set<String> supportedParams = new HashSet<String>(Arrays.asList("id", "name", "description"));
checkForUnsupportedParameters(requestMap, supportedParams); checkForUnsupportedParameters(requestMap, supportedParams);
Set<String> modifiedParameters = new HashSet<String>(); // no difference between the api json and internal command
// representation of json so reuse this code to de-serialize into
String name = extractStringParameter("name", requestMap, modifiedParameters); // command object
String description = extractStringParameter("description", requestMap, modifiedParameters); return this.portfolioCommandDeserializerService.deserializeRoleCommand(resourceIdentifier, json, false);
return new RoleCommand(modifiedParameters, resourceIdentifier, name, description);
} }
@Override @Override
@@ -13,6 +13,7 @@ import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData;
import org.mifosng.platform.api.data.ClientData; import org.mifosng.platform.api.data.ClientData;
import org.mifosng.platform.api.data.ClientIdentifierData; import org.mifosng.platform.api.data.ClientIdentifierData;
import org.mifosng.platform.api.data.CodeData; import org.mifosng.platform.api.data.CodeData;
import org.mifosng.platform.api.data.CommandSourceData;
import org.mifosng.platform.api.data.ConfigurationData; import org.mifosng.platform.api.data.ConfigurationData;
import org.mifosng.platform.api.data.DatatableData; import org.mifosng.platform.api.data.DatatableData;
import org.mifosng.platform.api.data.DepositAccountData; import org.mifosng.platform.api.data.DepositAccountData;
@@ -30,7 +31,6 @@ import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.LoanReassignmentData; import org.mifosng.platform.api.data.LoanReassignmentData;
import org.mifosng.platform.api.data.LoanScheduleData; import org.mifosng.platform.api.data.LoanScheduleData;
import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.api.data.CommandSourceData;
import org.mifosng.platform.api.data.NoteData; import org.mifosng.platform.api.data.NoteData;
import org.mifosng.platform.api.data.OfficeData; import org.mifosng.platform.api.data.OfficeData;
import org.mifosng.platform.api.data.OfficeTransactionData; import org.mifosng.platform.api.data.OfficeTransactionData;
@@ -157,9 +157,9 @@ public interface PortfolioApiJsonSerializerService {
String serializeSavingAccountsDataToJson(boolean prettyPrint, Set<String> responseParameters, Collection<SavingAccountData> accounts); String serializeSavingAccountsDataToJson(boolean prettyPrint, Set<String> responseParameters, Collection<SavingAccountData> accounts);
// TODO - KW - might devide serialize up into portfolio and account to reduce interface String serializeGuarantorDataToJson(boolean prettyPrint, Set<String> responseParameters, GuarantorData guarantorData);
String serializeChartOfAccountDataToJson(boolean prettyPrint, Set<String> responseParameters, ChartOfAccountsData chartOfAccounts);
// TODO - KW - might devide serialize up into portfolio and account to
String serializeGuarantorDataToJson(boolean prettyPrint,Set<String> responseParameters, GuarantorData guarantorData); // reduce interface
String serializeChartOfAccountDataToJson(boolean prettyPrint, Set<String> responseParameters, ChartOfAccountsData chartOfAccounts);
} }
@@ -0,0 +1,42 @@
package org.mifosng.platform.api.infrastructure;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.RoleCommand;
import org.mifosng.platform.infrastructure.api.JsonParserHelper;
import org.mifosng.platform.infrastructure.errorhandling.InvalidJsonException;
import org.springframework.stereotype.Service;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
/**
* Implementation of {@link PortfolioCommandDeserializerService} that de-serializes
* JSON of commands into Java object representation using google-gson.
*/
@Service
public class PortfolioCommandDeerializerServiceGoogleGson implements PortfolioCommandDeserializerService {
private final JsonParser parser;
public PortfolioCommandDeerializerServiceGoogleGson() {
parser = new JsonParser();
}
@Override
public RoleCommand deserializeRoleCommand(final Long roleId, final String commandAsJson, final boolean makerCheckerApproval) {
if (StringUtils.isBlank(commandAsJson)) { throw new InvalidJsonException(); }
final JsonParserHelper helper = new JsonParserHelper();
final JsonElement element = parser.parse(commandAsJson);
final Set<String> parametersPassedInRequest = new HashSet<String>();
final String name = helper.extractStringNamed("name", element, parametersPassedInRequest);
final String description = helper.extractStringNamed("description", element, parametersPassedInRequest);
return new RoleCommand(parametersPassedInRequest, makerCheckerApproval, roleId, name, description);
}
}
@@ -0,0 +1,18 @@
package org.mifosng.platform.api.infrastructure;
import org.mifosng.platform.api.commands.RoleCommand;
/**
* Service for de-serializing JSON for a command into the platforms internal
* Java object representation of the command.
*
* <p>
* Known implementations:
* </p>
*
* @see PortfolioCommandDeerializerServiceGoogleGson
*/
public interface PortfolioCommandDeserializerService {
RoleCommand deserializeRoleCommand(Long roleId, String commandAsJson, boolean makerCheckerApproval);
}
@@ -0,0 +1,14 @@
package org.mifosng.platform.api.infrastructure;
import org.mifosng.platform.api.commands.RoleCommand;
/**
* Service for serializing commands into another format.
*
* <p>Known implementations:</p>
* @see PortfolioCommandSerializerServiceJson
*/
public interface PortfolioCommandSerializerService {
String serializeRoleCommandToJson(RoleCommand command);
}
@@ -0,0 +1,32 @@
package org.mifosng.platform.api.infrastructure;
import java.util.HashSet;
import org.mifosng.platform.api.commands.RoleCommand;
import org.mifosng.platform.infrastructure.api.GoogleGsonSerializerHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gson.Gson;
/**
* Implementation of {@link PortfolioCommandSerializerService} that serializes
* the commands into JSON using google-gson.
*/
@Service
public class PortfolioCommandSerializerServiceJson implements PortfolioCommandSerializerService {
private final GoogleGsonSerializerHelper helper;
@Autowired
public PortfolioCommandSerializerServiceJson(final GoogleGsonSerializerHelper helper) {
this.helper = helper;
}
@Override
public String serializeRoleCommandToJson(final RoleCommand command) {
final Gson gsonDeserializer = helper.createGsonBuilderWithParameterExclusionSerializationStrategy(new HashSet<String>(), false,
new HashSet<String>());
return helper.serializedJsonFrom(gsonDeserializer, command);
}
}
@@ -27,522 +27,424 @@ import com.google.gson.JsonPrimitive;
* Helper class to extract values of json named attributes. * Helper class to extract values of json named attributes.
*/ */
public class JsonParserHelper { public class JsonParserHelper {
public Boolean extractBooleanNamed(final String parameterName, final JsonElement element, final Set<String> requestParamatersDetected) {
Boolean value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
requestParamatersDetected.add(parameterName);
JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
value = primitive.getAsBoolean();
}
}
return value;
}
public Long extractLongNamed(final String parameterName, public Boolean extractBooleanNamed(final String parameterName, final JsonElement element, final Set<String> requestParamatersDetected) {
final JsonElement element, final Set<String> parametersPassedInRequest) { Boolean value = null;
Long longValue = null; if (element.isJsonObject()) {
if (element.isJsonObject()) { JsonObject object = element.getAsJsonObject();
JsonObject object = element.getAsJsonObject(); if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
if (object.has(parameterName) requestParamatersDetected.add(parameterName);
&& object.get(parameterName).isJsonPrimitive()) {
parametersPassedInRequest.add(parameterName);
JsonPrimitive primitive = object.get(parameterName)
.getAsJsonPrimitive();
final String stringValue = primitive.getAsString();
if (StringUtils.isNotBlank(stringValue)) {
longValue = Long.valueOf(stringValue);
}
}
}
return longValue;
}
public String extractStringNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) { JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
String stringValue = null; value = primitive.getAsBoolean();
if (element.isJsonObject()) { }
JsonObject object = element.getAsJsonObject(); }
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) { return value;
parametersPassedInRequest.add(parameterName); }
final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
final String valueAsString = primitive.getAsString();
if (StringUtils.isNotBlank(valueAsString)) {
stringValue = valueAsString;
}
}
}
return stringValue;
}
public BigDecimal extractBigDecimalNamed( public Long extractLongNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) {
final String parameterName, Long longValue = null;
final JsonElement element, if (element.isJsonObject()) {
final Set<String> modifiedParameters) { JsonObject object = element.getAsJsonObject();
BigDecimal value = null; if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
if (element.isJsonObject()) { parametersPassedInRequest.add(parameterName);
final JsonObject object = element.getAsJsonObject(); JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
final Locale locale = extractLocaleValue(object); final String stringValue = primitive.getAsString();
value = extractBigDecimalNamed(parameterName, object, locale, modifiedParameters); if (StringUtils.isNotBlank(stringValue)) {
} longValue = Long.valueOf(stringValue);
return value; }
} }
}
public BigDecimal extractBigDecimalNamed( return longValue;
final String parameterName, }
final JsonObject element,
final Locale locale,
final Set<String> modifiedParameters) {
BigDecimal value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has(parameterName)
&& object.get(parameterName).isJsonPrimitive()) {
modifiedParameters.add(parameterName);
JsonPrimitive primitive = object.get(parameterName)
.getAsJsonPrimitive();
String valueAsString = primitive.getAsString();
if (StringUtils.isNotBlank(valueAsString)) {
value = convertFrom(valueAsString, parameterName, locale);
}
}
}
return value;
}
public Integer extractIntegerNamed( public String extractStringNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) {
final String parameterName, String stringValue = null;
final JsonElement element, if (element.isJsonObject()) {
final Set<String> modifiedParameters) { JsonObject object = element.getAsJsonObject();
Integer value = null; if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
if (element.isJsonObject()) { parametersPassedInRequest.add(parameterName);
final JsonObject object = element.getAsJsonObject(); final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
final Locale locale = extractLocaleValue(object); final String valueAsString = primitive.getAsString();
value = extractIntegerNamed(parameterName, object, locale, modifiedParameters); if (StringUtils.isNotBlank(valueAsString)) {
} stringValue = valueAsString;
return value; }
} }
}
public Integer extractIntegerNamed( return stringValue;
final String parameterName, }
final JsonElement element,
final Locale locale,
final Set<String> modifiedParameters) {
Integer value = null;
if (element.isJsonObject()) {
final JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
modifiedParameters.add(parameterName);
JsonPrimitive primitive = object.get(parameterName)
.getAsJsonPrimitive();
String valueAsString = primitive.getAsString();
if (StringUtils.isNotBlank(valueAsString)) {
value = convertToInteger(valueAsString, parameterName, locale);
}
}
}
return value;
}
public String extractDateFormatParameter(final JsonObject element) {
String value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
final String dateFormatParameter = "dateFormat"; public BigDecimal extractBigDecimalNamed(final String parameterName, final JsonElement element, final Set<String> modifiedParameters) {
if (object.has(dateFormatParameter) BigDecimal value = null;
&& object.get(dateFormatParameter).isJsonPrimitive()) { if (element.isJsonObject()) {
final JsonPrimitive primitive = object.get(dateFormatParameter).getAsJsonPrimitive(); final JsonObject object = element.getAsJsonObject();
value = primitive.getAsString(); final Locale locale = extractLocaleValue(object);
} value = extractBigDecimalNamed(parameterName, object, locale, modifiedParameters);
} }
return value; return value;
} }
public Locale extractLocaleParameter(final JsonObject element) {
Locale clientApplicationLocale = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
String locale = null;
final String localeParameter = "locale";
if (object.has(localeParameter)
&& object.get(localeParameter).isJsonPrimitive()) {
final JsonPrimitive primitive = object.get(localeParameter).getAsJsonPrimitive();
locale = primitive.getAsString();
clientApplicationLocale = localeFromString(locale);
}
}
return clientApplicationLocale;
}
/**
* Used with the local date is in array format
*/
public LocalDate extractLocalDateAsArrayNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInCommand) {
LocalDate value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonArray()) { public BigDecimal extractBigDecimalNamed(final String parameterName, final JsonObject element, final Locale locale,
final Set<String> modifiedParameters) {
parametersPassedInCommand.add(parameterName); BigDecimal value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
modifiedParameters.add(parameterName);
JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
String valueAsString = primitive.getAsString();
if (StringUtils.isNotBlank(valueAsString)) {
value = convertFrom(valueAsString, parameterName, locale);
}
}
}
return value;
}
public Integer extractIntegerNamed(final String parameterName, final JsonElement element, final Set<String> modifiedParameters) {
final JsonArray dateArray = object.get(parameterName).getAsJsonArray(); Integer value = null;
if (element.isJsonObject()) {
Integer year = dateArray.get(0).getAsInt(); final JsonObject object = element.getAsJsonObject();
Integer month = dateArray.get(1).getAsInt(); final Locale locale = extractLocaleValue(object);
Integer day = dateArray.get(2).getAsInt(); value = extractIntegerNamed(parameterName, object, locale, modifiedParameters);
}
value = new LocalDate().withYearOfEra(year).withMonthOfYear(month).withDayOfMonth(day); return value;
} }
} public Integer extractIntegerNamed(final String parameterName, final JsonElement element, final Locale locale,
return value; final Set<String> modifiedParameters) {
} Integer value = null;
if (element.isJsonObject()) {
final JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
modifiedParameters.add(parameterName);
JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
String valueAsString = primitive.getAsString();
if (StringUtils.isNotBlank(valueAsString)) {
value = convertToInteger(valueAsString, parameterName, locale);
}
}
}
return value;
}
public LocalDate extractLocalDateNamed( public String extractDateFormatParameter(final JsonObject element) {
final String parameterName, String value = null;
final JsonElement element, if (element.isJsonObject()) {
final Set<String> parametersPassedInCommand) { JsonObject object = element.getAsJsonObject();
LocalDate value = null; final String dateFormatParameter = "dateFormat";
if (object.has(dateFormatParameter) && object.get(dateFormatParameter).isJsonPrimitive()) {
if (element.isJsonObject()) { final JsonPrimitive primitive = object.get(dateFormatParameter).getAsJsonPrimitive();
JsonObject object = element.getAsJsonObject(); value = primitive.getAsString();
}
}
return value;
}
final String dateFormat = extractDateFormatParameter(object); public Locale extractLocaleParameter(final JsonObject element) {
final Locale clientApplicationLocale = extractLocaleParameter(object); Locale clientApplicationLocale = null;
value = extractLocalDateNamed(parameterName, object, dateFormat, clientApplicationLocale, parametersPassedInCommand); if (element.isJsonObject()) {
} JsonObject object = element.getAsJsonObject();
return value;
}
public LocalDate extractLocalDateNamed(
final String parameterName,
final JsonObject element,
final String dateFormat,
final Locale clientApplicationLocale,
final Set<String> parametersPassedInCommand) {
LocalDate value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) String locale = null;
&& object.get(parameterName).isJsonPrimitive()) { final String localeParameter = "locale";
if (object.has(localeParameter) && object.get(localeParameter).isJsonPrimitive()) {
parametersPassedInCommand.add(parameterName); final JsonPrimitive primitive = object.get(localeParameter).getAsJsonPrimitive();
locale = primitive.getAsString();
final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive(); clientApplicationLocale = localeFromString(locale);
final String valueAsString = primitive.getAsString(); }
if (StringUtils.isNotBlank(valueAsString)) { }
value = convertFrom(valueAsString, parameterName, dateFormat, clientApplicationLocale); return clientApplicationLocale;
} }
}
} /**
return value; * Used with the local date is in array format
} */
public LocalDate extractLocalDateAsArrayNamed(final String parameterName, final JsonElement element,
final Set<String> parametersPassedInCommand) {
LocalDate value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
public LocalDate convertFrom(final String dateAsString, if (object.has(parameterName) && object.get(parameterName).isJsonArray()) {
final String parameterName, final String dateFormat,
final Locale clientApplicationLocale) {
if (StringUtils.isBlank(dateFormat) || clientApplicationLocale == null) { parametersPassedInCommand.add(parameterName);
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); final JsonArray dateArray = object.get(parameterName).getAsJsonArray();
if (StringUtils.isBlank(dateFormat)) {
String defaultMessage = new StringBuilder(
"The parameter '"
+ parameterName
+ "' requires a 'dateFormat' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.dateFormat.parameter",
defaultMessage, parameterName);
dataValidationErrors.add(error);
}
if (clientApplicationLocale == null) {
String defaultMessage = new StringBuilder(
"The parameter '"
+ parameterName
+ "' requires a 'locale' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.locale.parameter",
defaultMessage, parameterName);
dataValidationErrors.add(error);
}
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
LocalDate eventLocalDate = null; Integer year = dateArray.get(0).getAsInt();
if (StringUtils.isNotBlank(dateAsString)) { Integer month = dateArray.get(1).getAsInt();
try { Integer day = dateArray.get(2).getAsInt();
// Locale locale = LocaleContextHolder.getLocale();
eventLocalDate = DateTimeFormat
.forPattern(dateFormat)
.withLocale(clientApplicationLocale)
.parseLocalDate(
dateAsString
.toLowerCase(clientApplicationLocale));
} catch (IllegalArgumentException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.invalid.date.format", "The parameter "
+ parameterName
+ " is invalid based on the dateFormat: '"
+ dateFormat + "' and locale: '"
+ clientApplicationLocale + "' provided:",
parameterName, dateAsString, dateFormat);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException( value = new LocalDate().withYearOfEra(year).withMonthOfYear(month).withDayOfMonth(day);
"validation.msg.validation.errors.exist", }
"Validation errors exist.", dataValidationErrors);
}
}
return eventLocalDate; }
} return value;
}
public Integer convertToInteger(final String numericalValueFormatted, public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element,
final String parameterName, final Locale clientApplicationLocale) { final Set<String> parametersPassedInCommand) {
if (clientApplicationLocale == null) { LocalDate value = null;
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); if (element.isJsonObject()) {
String defaultMessage = new StringBuilder("The parameter '" JsonObject object = element.getAsJsonObject();
+ parameterName
+ "' requires a 'locale' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException( final String dateFormat = extractDateFormatParameter(object);
"validation.msg.validation.errors.exist", final Locale clientApplicationLocale = extractLocaleParameter(object);
"Validation errors exist.", dataValidationErrors); value = extractLocalDateNamed(parameterName, object, dateFormat, clientApplicationLocale, parametersPassedInCommand);
} }
return value;
}
try { public LocalDate extractLocalDateNamed(final String parameterName, final JsonObject element, final String dateFormat,
Integer number = null; final Locale clientApplicationLocale, final Set<String> parametersPassedInCommand) {
LocalDate value = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (StringUtils.isNotBlank(numericalValueFormatted)) { if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
String source = numericalValueFormatted.trim(); parametersPassedInCommand.add(parameterName);
NumberFormat format = NumberFormat final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
.getInstance(clientApplicationLocale); final String valueAsString = primitive.getAsString();
DecimalFormat df = (DecimalFormat) format; if (StringUtils.isNotBlank(valueAsString)) {
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); value = convertFrom(valueAsString, parameterName, dateFormat, clientApplicationLocale);
df.setParseBigDecimal(true); }
}
// http://bugs.sun.com/view_bug.do?bug_id=4510618 }
char groupingSeparator = symbols.getGroupingSeparator(); return value;
if (groupingSeparator == '\u00a0') { }
source = source.replaceAll(" ",
Character.toString('\u00a0'));
}
Number parsedNumber = df.parse(source); public LocalDate convertFrom(final String dateAsString, final String parameterName, final String dateFormat,
final Locale clientApplicationLocale) {
double parsedNumberDouble = parsedNumber.doubleValue(); if (StringUtils.isBlank(dateFormat) || clientApplicationLocale == null) {
int parsedNumberInteger = parsedNumber.intValue();
if (source.contains(Character.toString(symbols List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
.getDecimalSeparator()))) { if (StringUtils.isBlank(dateFormat)) {
throw new ParseException(source, 0); String defaultMessage = new StringBuilder("The parameter '" + parameterName
} + "' requires a 'dateFormat' parameter to be passed with it.").toString();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.dateFormat.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
}
if (clientApplicationLocale == null) {
String defaultMessage = new StringBuilder("The parameter '" + parameterName
+ "' requires a 'locale' parameter to be passed with it.").toString();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
}
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
dataValidationErrors);
}
if (!Double.valueOf(parsedNumberDouble).equals( LocalDate eventLocalDate = null;
Double.valueOf(Integer.valueOf(parsedNumberInteger)))) { if (StringUtils.isNotBlank(dateAsString)) {
throw new ParseException(source, 0); try {
} // Locale locale = LocaleContextHolder.getLocale();
eventLocalDate = DateTimeFormat.forPattern(dateFormat).withLocale(clientApplicationLocale)
.parseLocalDate(dateAsString.toLowerCase(clientApplicationLocale));
} catch (IllegalArgumentException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.date.format", "The parameter "
+ parameterName + " is invalid based on the dateFormat: '" + dateFormat + "' and locale: '"
+ clientApplicationLocale + "' provided:", parameterName, dateAsString, dateFormat);
dataValidationErrors.add(error);
number = parsedNumber.intValue(); throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
} dataValidationErrors);
}
}
return number; return eventLocalDate;
} catch (ParseException e) { }
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); public Integer convertToInteger(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) {
ApiParameterError error = ApiParameterError
.parameterError(
"validation.msg.invalid.integer.format",
"The parameter "
+ parameterName
+ " has value: "
+ numericalValueFormatted
+ " which is invalid integer value for provided locale of ["
+ clientApplicationLocale.toString() + "].",
parameterName, numericalValueFormatted,
clientApplicationLocale);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException( if (clientApplicationLocale == null) {
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
public BigDecimal convertFrom(final String numericalValueFormatted, List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final String parameterName, final Locale clientApplicationLocale) { String defaultMessage = new StringBuilder("The parameter '" + parameterName
+ "' requires a 'locale' parameter to be passed with it.").toString();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
if (clientApplicationLocale == null) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
dataValidationErrors);
}
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); try {
String defaultMessage = new StringBuilder("The parameter '" Integer number = null;
+ parameterName
+ "' requires a 'locale' parameter to be passed with it.")
.toString();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException( if (StringUtils.isNotBlank(numericalValueFormatted)) {
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
try { String source = numericalValueFormatted.trim();
BigDecimal number = null;
if (StringUtils.isNotBlank(numericalValueFormatted)) { NumberFormat format = NumberFormat.getInstance(clientApplicationLocale);
DecimalFormat df = (DecimalFormat) format;
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
df.setParseBigDecimal(true);
String source = numericalValueFormatted.trim(); // http://bugs.sun.com/view_bug.do?bug_id=4510618
char groupingSeparator = symbols.getGroupingSeparator();
if (groupingSeparator == '\u00a0') {
source = source.replaceAll(" ", Character.toString('\u00a0'));
}
NumberFormat format = NumberFormat Number parsedNumber = df.parse(source);
.getNumberInstance(clientApplicationLocale);
DecimalFormat df = (DecimalFormat) format;
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
// http://bugs.sun.com/view_bug.do?bug_id=4510618
char groupingSeparator = symbols.getGroupingSeparator();
if (groupingSeparator == '\u00a0') {
source = source.replaceAll(" ",
Character.toString('\u00a0'));
}
NumberFormatter numberFormatter = new NumberFormatter(); double parsedNumberDouble = parsedNumber.doubleValue();
Number parsedNumber = numberFormatter.parse(source, int parsedNumberInteger = parsedNumber.intValue();
clientApplicationLocale);
number = BigDecimal.valueOf(Double.valueOf(parsedNumber
.doubleValue()));
}
return number; if (source.contains(Character.toString(symbols.getDecimalSeparator()))) { throw new ParseException(source, 0); }
} catch (ParseException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); if (!Double.valueOf(parsedNumberDouble).equals(Double.valueOf(Integer.valueOf(parsedNumberInteger)))) { throw new ParseException(
ApiParameterError error = ApiParameterError source, 0); }
.parameterError(
"validation.msg.invalid.decimal.format",
"The parameter "
+ parameterName
+ " has value: "
+ numericalValueFormatted
+ " which is invalid decimal value for provided locale of ["
+ clientApplicationLocale.toString() + "].",
parameterName, numericalValueFormatted,
clientApplicationLocale);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException( number = parsedNumber.intValue();
"validation.msg.validation.errors.exist", }
"Validation errors exist.", dataValidationErrors);
}
}
private Locale localeFromString(final String localeAsString) { return number;
} catch (ParseException e) {
if (StringUtils.isBlank(localeAsString)) { List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer.format", "The parameter "
ApiParameterError error = ApiParameterError.parameterError( + parameterName + " has value: " + numericalValueFormatted + " which is invalid integer value for provided locale of ["
"validation.msg.invalid.locale.format", + clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
"The parameter locale is invalid. It cannot be blank.", dataValidationErrors.add(error);
"locale");
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException( throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
"validation.msg.validation.errors.exist", dataValidationErrors);
"Validation errors exist.", dataValidationErrors); }
} }
String languageCode = ""; public BigDecimal convertFrom(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) {
String courntryCode = "";
String variantCode = "";
String[] localeParts = localeAsString.split("_"); if (clientApplicationLocale == null) {
if (localeParts != null && localeParts.length == 1) { List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
languageCode = localeParts[0]; String defaultMessage = new StringBuilder("The parameter '" + parameterName
} + "' requires a 'locale' parameter to be passed with it.").toString();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
dataValidationErrors.add(error);
if (localeParts != null && localeParts.length == 2) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
languageCode = localeParts[0]; dataValidationErrors);
courntryCode = localeParts[1]; }
}
if (localeParts != null && localeParts.length == 3) { try {
languageCode = localeParts[0]; BigDecimal number = null;
courntryCode = localeParts[1];
variantCode = localeParts[2];
}
return localeFrom(languageCode, courntryCode, variantCode); if (StringUtils.isNotBlank(numericalValueFormatted)) {
}
private Locale localeFrom(final String languageCode, String source = numericalValueFormatted.trim();
final String courntryCode, final String variantCode) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); NumberFormat format = NumberFormat.getNumberInstance(clientApplicationLocale);
DecimalFormat df = (DecimalFormat) format;
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
// http://bugs.sun.com/view_bug.do?bug_id=4510618
char groupingSeparator = symbols.getGroupingSeparator();
if (groupingSeparator == '\u00a0') {
source = source.replaceAll(" ", Character.toString('\u00a0'));
}
List<String> allowedLanguages = Arrays.asList(Locale.getISOLanguages()); NumberFormatter numberFormatter = new NumberFormatter();
if (!allowedLanguages.contains(languageCode.toLowerCase())) { Number parsedNumber = numberFormatter.parse(source, clientApplicationLocale);
ApiParameterError error = ApiParameterError.parameterError( number = BigDecimal.valueOf(Double.valueOf(parsedNumber.doubleValue()));
"validation.msg.invalid.locale.format", }
"The parameter locale has an invalid language value "
+ languageCode + " .", "locale", languageCode);
dataValidationErrors.add(error);
}
if (StringUtils.isNotBlank(courntryCode.toUpperCase())) { return number;
List<String> allowedCountries = Arrays.asList(Locale } catch (ParseException e) {
.getISOCountries());
if (!allowedCountries.contains(courntryCode)) {
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.invalid.locale.format",
"The parameter locale has an invalid country value "
+ courntryCode + " .", "locale", courntryCode);
dataValidationErrors.add(error);
}
}
if (!dataValidationErrors.isEmpty()) { List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
throw new PlatformApiDataValidationException( ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.decimal.format", "The parameter "
"validation.msg.validation.errors.exist", + parameterName + " has value: " + numericalValueFormatted + " which is invalid decimal value for provided locale of ["
"Validation errors exist.", dataValidationErrors); + clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
} dataValidationErrors.add(error);
return new Locale(languageCode.toLowerCase(), throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
courntryCode.toUpperCase(), variantCode); dataValidationErrors);
} }
}
private Locale extractLocaleValue(final JsonObject object) { private Locale localeFromString(final String localeAsString) {
Locale clientApplicationLocale = null;
String locale = null; if (StringUtils.isBlank(localeAsString)) {
if (object.has("locale") && object.get("locale").isJsonPrimitive()) { List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
JsonPrimitive primitive = object.get("locale").getAsJsonPrimitive(); ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format",
locale = primitive.getAsString(); "The parameter locale is invalid. It cannot be blank.", "locale");
clientApplicationLocale = localeFromString(locale); dataValidationErrors.add(error);
}
return clientApplicationLocale; throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
} dataValidationErrors);
}
String languageCode = "";
String courntryCode = "";
String variantCode = "";
String[] localeParts = localeAsString.split("_");
if (localeParts != null && localeParts.length == 1) {
languageCode = localeParts[0];
}
if (localeParts != null && localeParts.length == 2) {
languageCode = localeParts[0];
courntryCode = localeParts[1];
}
if (localeParts != null && localeParts.length == 3) {
languageCode = localeParts[0];
courntryCode = localeParts[1];
variantCode = localeParts[2];
}
return localeFrom(languageCode, courntryCode, variantCode);
}
private Locale localeFrom(final String languageCode, final String courntryCode, final String variantCode) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
List<String> allowedLanguages = Arrays.asList(Locale.getISOLanguages());
if (!allowedLanguages.contains(languageCode.toLowerCase())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format",
"The parameter locale has an invalid language value " + languageCode + " .", "locale", languageCode);
dataValidationErrors.add(error);
}
if (StringUtils.isNotBlank(courntryCode.toUpperCase())) {
List<String> allowedCountries = Arrays.asList(Locale.getISOCountries());
if (!allowedCountries.contains(courntryCode)) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format",
"The parameter locale has an invalid country value " + courntryCode + " .", "locale", courntryCode);
dataValidationErrors.add(error);
}
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
return new Locale(languageCode.toLowerCase(), courntryCode.toUpperCase(), variantCode);
}
private Locale extractLocaleValue(final JsonObject object) {
Locale clientApplicationLocale = null;
String locale = null;
if (object.has("locale") && object.get("locale").isJsonPrimitive()) {
JsonPrimitive primitive = object.get("locale").getAsJsonPrimitive();
locale = primitive.getAsString();
clientApplicationLocale = localeFromString(locale);
}
return clientApplicationLocale;
}
} }
@@ -108,10 +108,6 @@ public class CommandSource extends AbstractPersistable<Long> {
return this.apiOperation; return this.apiOperation;
} }
public boolean isClientResource() {
return this.resource.equalsIgnoreCase("CLIENTS");
}
public boolean isCreate() { public boolean isCreate() {
return this.apiOperation.equalsIgnoreCase("CREATE"); return this.apiOperation.equalsIgnoreCase("CREATE");
} }
@@ -123,4 +119,12 @@ public class CommandSource extends AbstractPersistable<Long> {
public boolean isDelete() { public boolean isDelete() {
return this.apiOperation.equalsIgnoreCase("DELETE") && this.resourceId != null; return this.apiOperation.equalsIgnoreCase("DELETE") && this.resourceId != null;
} }
public boolean isClientResource() {
return this.resource.equalsIgnoreCase("CLIENTS");
}
public boolean isRoleResource() {
return this.resource.equalsIgnoreCase("ROLES");
}
} }
@@ -14,11 +14,15 @@ public class CommandSourceHandlerDelegator {
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final ClientCommandHandler clientCommandHandler; private final ClientCommandHandler clientCommandHandler;
private final RoleCommandHandler roleCommandHandler;
@Autowired @Autowired
public CommandSourceHandlerDelegator(final PlatformSecurityContext context, final ClientCommandHandler clientCommandHandler) { public CommandSourceHandlerDelegator(final PlatformSecurityContext context,
final ClientCommandHandler clientCommandHandler,
final RoleCommandHandler roleCommandHandler) {
this.context = context; this.context = context;
this.clientCommandHandler = clientCommandHandler; this.clientCommandHandler = clientCommandHandler;
this.roleCommandHandler = roleCommandHandler;
} }
public CommandSource handle(final CommandSource commandSource, final String apiRequestBodyInJson) { public CommandSource handle(final CommandSource commandSource, final String apiRequestBodyInJson) {
@@ -27,6 +31,8 @@ public class CommandSourceHandlerDelegator {
CommandSource commandSourceResult = null; CommandSource commandSourceResult = null;
if (commandSource.isClientResource()) { if (commandSource.isClientResource()) {
commandSourceResult = clientCommandHandler.handle(commandSource, apiRequestBodyInJson); commandSourceResult = clientCommandHandler.handle(commandSource, apiRequestBodyInJson);
} else if (commandSource.isRoleResource()) {
commandSourceResult = roleCommandHandler.handle(commandSource, apiRequestBodyInJson);
} else { } else {
throw new UnsupportedCommandException(commandSource.commandName()); throw new UnsupportedCommandException(commandSource.commandName());
} }
@@ -39,6 +45,8 @@ public class CommandSourceHandlerDelegator {
CommandSource commandSourceResult = null; CommandSource commandSourceResult = null;
if (commandSource.isClientResource()) { if (commandSource.isClientResource()) {
commandSourceResult = clientCommandHandler.handle(commandSource); commandSourceResult = clientCommandHandler.handle(commandSource);
} else if (commandSource.isRoleResource()) {
commandSourceResult = roleCommandHandler.handle(commandSource);
} else { } else {
throw new UnsupportedCommandException(commandSource.commandName()); throw new UnsupportedCommandException(commandSource.commandName());
} }
@@ -0,0 +1,110 @@
package org.mifosng.platform.makerchecker.service;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.RoleCommand;
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
import org.mifosng.platform.api.infrastructure.PortfolioCommandDeserializerService;
import org.mifosng.platform.api.infrastructure.PortfolioCommandSerializerService;
import org.mifosng.platform.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
import org.mifosng.platform.infrastructure.errorhandling.UnsupportedCommandException;
import org.mifosng.platform.makerchecker.domain.CommandSource;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.service.RoleWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RoleCommandHandler implements CommandSourceHandler {
private final PlatformSecurityContext context;
private final ChangeDetectionService changeDetectionService;
private final PortfolioApiDataConversionService apiDataConversionService;
private final PortfolioCommandSerializerService commandSerializerService;
private final PortfolioCommandDeserializerService commandDeserializerService;
private final RoleWritePlatformService writePlatformService;
@Autowired
public RoleCommandHandler(final PlatformSecurityContext context, final ChangeDetectionService changeDetectionService,
final PortfolioApiDataConversionService apiDataConversionService,
final PortfolioCommandSerializerService commandSerializerService,
final PortfolioCommandDeserializerService commandDeserializerService,
final RoleWritePlatformService writePlatformService) {
this.context = context;
this.changeDetectionService = changeDetectionService;
this.apiDataConversionService = apiDataConversionService;
this.commandSerializerService = commandSerializerService;
this.commandDeserializerService = commandDeserializerService;
this.writePlatformService = writePlatformService;
}
/*
* Used when users with 'create' capability create a command. If 'maker-checker' is not
* enabled for this specific command then the 'creator' is also marked 'as the checker' and command
* automatically is processed and changes state of system.
*/
public CommandSource handle(final CommandSource commandSource, final String apiRequestBodyInJson) {
final AppUser maker = context.authenticatedUser();
final LocalDate asToday = new LocalDate();
CommandSource commandSourceResult = commandSource.copy();
final Long resourceId = commandSource.resourceId();
Long newResourceId = null;
final RoleCommand command = this.apiDataConversionService.convertApiRequestJsonToRoleCommand(resourceId, apiRequestBodyInJson);
final String commandSerializedAsJson = this.commandSerializerService.serializeRoleCommandToJson(command);
commandSourceResult.updateJsonTo(commandSerializedAsJson);
if (commandSource.isCreate()) {
try {
newResourceId = this.writePlatformService.createRole(command);
commandSourceResult.markAsChecked(maker, asToday);
commandSourceResult.updateResourceId(newResourceId);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
}
} else if (commandSource.isUpdate()) {
try {
final String jsonOfChangesOnly = this.changeDetectionService.detectChangesOnUpdate(commandSource.resourceName(), commandSource.resourceId(), commandSerializedAsJson);
commandSourceResult.updateJsonTo(jsonOfChangesOnly);
final RoleCommand changesOnly = this.commandDeserializerService.deserializeRoleCommand(resourceId, jsonOfChangesOnly, false);
newResourceId = this.writePlatformService.updateRole(changesOnly);
commandSourceResult.markAsChecked(maker, asToday);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
// swallow this rollback transaction by design
}
} else if (commandSource.isDelete()) {
throw new UnsupportedCommandException(commandSource.commandName());
}
return commandSourceResult;
}
/*
* Used when users with 'checker' capability approve a command.
*/
public CommandSource handle(final CommandSource commandSourceResult) {
Long resourceId = null;
if (commandSourceResult.isRoleResource()) {
final RoleCommand command = this.commandDeserializerService.deserializeRoleCommand(resourceId, commandSourceResult.json(), true);
if (commandSourceResult.isCreate()) {
resourceId = this.writePlatformService.createRole(command);
} else if (commandSourceResult.isUpdate()) {
resourceId = this.writePlatformService.updateRole(command);
} else if (commandSourceResult.isDelete()) {
throw new UnsupportedCommandException(commandSourceResult.commandName());
}
}
commandSourceResult.updateResourceId(resourceId);
return commandSourceResult;
}
}
@@ -12,27 +12,26 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
public class Permission extends AbstractPersistable<Long> { public class Permission extends AbstractPersistable<Long> {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Column(name = "grouping", nullable = false, length=45) @Column(name = "grouping", nullable = false, length = 45)
private final String grouping; private final String grouping;
@Column(name = "code", nullable = false, length=100)
private final String code;
@Column(name = "default_name", nullable = false, length=100) @Column(name = "code", nullable = false, length = 100)
private final String defaultName; private final String code;
@Column(name = "default_description", nullable = false, length=500) @Column(name = "default_name", nullable = false, length = 100)
private final String defaultDescription; private final String defaultName;
@Column(name = "default_description", nullable = false, length = 500)
private final String defaultDescription;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Column(name = "entity_name", nullable = true, length=100) @Column(name = "entity_name", nullable = true, length = 100)
private final String entityName; private final String entityName;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Column(name = "action_name", nullable = true, length=100) @Column(name = "action_name", nullable = true, length = 100)
private final String actionName; private final String actionName;
protected Permission() { protected Permission() {
this.grouping = null; this.grouping = null;
this.code = null; this.code = null;
@@ -42,15 +41,15 @@ public class Permission extends AbstractPersistable<Long> {
this.actionName = null; this.actionName = null;
} }
public boolean hasCode(String checkCode) { public boolean hasCode(final String checkCode) {
return this.code.equalsIgnoreCase(checkCode); return this.code.equalsIgnoreCase(checkCode);
} }
public String code() { public String code() {
return this.code; return this.code;
} }
public PermissionData toData() { public PermissionData toData() {
return new PermissionData(this.getId(), this.defaultName, this.defaultDescription, this.code); return new PermissionData(this.getId(), this.defaultName, this.defaultDescription, this.code);
} }
} }
@@ -5,6 +5,7 @@ import java.util.Map;
import org.mifosng.platform.accounting.api.commands.RolePermissionCommand; import org.mifosng.platform.accounting.api.commands.RolePermissionCommand;
import org.mifosng.platform.api.commands.RoleCommand; import org.mifosng.platform.api.commands.RoleCommand;
import org.mifosng.platform.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
import org.mifosng.platform.exceptions.PermissionNotFoundException; import org.mifosng.platform.exceptions.PermissionNotFoundException;
import org.mifosng.platform.exceptions.RoleNotFoundException; import org.mifosng.platform.exceptions.RoleNotFoundException;
import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.security.PlatformSecurityContext;
@@ -17,108 +18,102 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class RoleWritePlatformServiceJpaRepositoryImpl implements public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatformService {
RoleWritePlatformService {
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final RoleRepository roleRepository; private final RoleRepository roleRepository;
private final PermissionRepository permissionRepository;
private final PermissionRepository permissionRepository; // FIXME - kw - this value is hardcoded for now but will be retrieved from
// configuration
private boolean makerCheckerEnabledForTask = false;
@Autowired
public RoleWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final RoleRepository roleRepository,
final PermissionRepository permissionRepository) {
this.context = context;
this.roleRepository = roleRepository;
this.permissionRepository = permissionRepository;
}
@Autowired @Transactional
public RoleWritePlatformServiceJpaRepositoryImpl( @Override
final PlatformSecurityContext context, public Long createRole(final RoleCommand command) {
final RoleRepository roleRepository,
final PermissionRepository permissionRepository) {
this.context = context;
this.roleRepository = roleRepository;
this.permissionRepository = permissionRepository;
}
@Transactional context.authenticatedUser();
@Override
public Long createRole(final RoleCommand command) {
context.authenticatedUser(); RoleCommandValidator validator = new RoleCommandValidator(command);
validator.validateForCreate();
RoleCommandValidator validator = new RoleCommandValidator(command); Role entity = new Role(command.getName(), command.getDescription());
validator.validateForCreate();
Role entity = new Role(command.getName(), command.getDescription()); this.roleRepository.save(entity);
if (this.makerCheckerEnabledForTask && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); }
this.roleRepository.save(entity); return entity.getId();
}
return entity.getId(); @Transactional
} @Override
public Long updateRole(RoleCommand command) {
@Transactional context.authenticatedUser();
@Override
public Long updateRole(RoleCommand command) {
context.authenticatedUser(); RoleCommandValidator validator = new RoleCommandValidator(command);
validator.validateForUpdate();
RoleCommandValidator validator = new RoleCommandValidator(command); Role role = this.roleRepository.findOne(command.getId());
validator.validateForUpdate(); if (role == null) { throw new RoleNotFoundException(command.getId()); }
role.update(command);
Role role = this.roleRepository.findOne(command.getId()); this.roleRepository.save(role);
if (role == null) {
throw new RoleNotFoundException(command.getId()); if (this.makerCheckerEnabledForTask && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); }
}
role.update(command);
this.roleRepository.save(role); return role.getId();
}
return role.getId(); @Transactional
} @Override
public Long updateRolePermissions(final RolePermissionCommand command) {
context.authenticatedUser();
@Transactional final Role role = this.roleRepository.findOne(command.getRoleId());
@Override if (role == null) { throw new RoleNotFoundException(command.getRoleId()); }
public Long updateRolePermissions(final RolePermissionCommand command) {
context.authenticatedUser();
final Role role = this.roleRepository.findOne(command.getRoleId()); Collection<Permission> allPermissions = this.permissionRepository.findAll();
if (role == null) {
throw new RoleNotFoundException(command.getRoleId());
}
Collection<Permission> allPermissions = this.permissionRepository Map<String, Boolean> commandPermissions = command.getPermissions();
.findAll(); for (String permissionCode : commandPermissions.keySet()) {
Boolean selected = commandPermissions.get(permissionCode);
Map<String, Boolean> commandPermissions = command.getPermissions(); final Permission permission = findPermissionByCode(allPermissions, permissionCode);
for (String permissionCode : commandPermissions.keySet()) {
Boolean selected = commandPermissions.get(permissionCode);
Permission permission = getPermissionByCode(allPermissions, if (role.getPermissions().contains(permission)) {
permissionCode); if (!(selected)) {
role.getPermissions().remove(permission);
}
} else {
if (selected) {
role.getPermissions().add(permission);
}
}
}
if (role.getPermissions().contains(permission)) { this.roleRepository.save(role);
if (!(selected)) {
role.getPermissions().remove(permission);
}
} else { return role.getId();
if (selected) { }
role.getPermissions().add(permission);
}
} private Permission findPermissionByCode(Collection<Permission> allPermissions, String permissionCode) {
}
this.roleRepository.save(role); if (allPermissions != null) {
for (Permission permission : allPermissions) {
if (permission.hasCode(permissionCode)) {return permission;}
}
}
return role.getId(); throw new PermissionNotFoundException(permissionCode);
} }
private Permission getPermissionByCode(
Collection<Permission> allPermissions, String permissionCode) {
if (allPermissions != null) {
for (Permission permission : allPermissions) {
if (permission.code().equals(permissionCode)) return permission;
}
}
throw new PermissionNotFoundException(permissionCode);
}
} }