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 @Autowired
private PortfolioCommandsReadPlatformService commandSourceReadPlatformService; private PortfolioCommandsReadPlatformService commandSourceReadPlatformService;
@Autowired @Autowired
private PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; private PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired @Autowired
private OfficeReadPlatformService officeReadPlatformService; private OfficeReadPlatformService officeReadPlatformService;
@Autowired @Autowired
private PortfolioApiDataConversionService apiDataConversionService; private PortfolioApiDataConversionService apiDataConversionService;
@Autowired @Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService; private PortfolioApiJsonSerializerService apiJsonSerializerService;
@Autowired @Autowired
private PlatformSecurityContext context; private PlatformSecurityContext context;
@GET @GET
@Consumes({MediaType.APPLICATION_JSON}) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({MediaType.APPLICATION_JSON}) @Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllIndividualClients(@Context final UriInfo uriInfo, public String retrieveAllIndividualClients(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("sqlSearch") final String sqlSearch, @QueryParam("officeId") final Integer officeId, @QueryParam("externalId") final String externalId,
@QueryParam("officeId") final Integer officeId, @QueryParam("displayName") final String displayName, @QueryParam("firstName") final String firstName,
@QueryParam("externalId") final String externalId, @QueryParam("lastName") final String lastName, @QueryParam("underHierarchy") final String hierarchy) {
@QueryParam("displayName") final String displayName,
@QueryParam("firstName") final String firstName,
@QueryParam("lastName") final String lastName,
@QueryParam("underHierarchy") final String hierarchy) {
context.authenticatedUser().validateHasReadPermission("CLIENT");
final String extraCriteria = getClientCriteria(sqlSearch, officeId, externalId, displayName, firstName, lastName, hierarchy);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final Collection<ClientData> clients = this.clientReadPlatformService.retrieveAllIndividualClients(extraCriteria);
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clients);
}
private String getClientCriteria(String sqlSearch, Integer officeId,
String externalId, String displayName, String firstName,
String lastName, String hierarchy) {
String extraCriteria = "";
if (sqlSearch != null) {
extraCriteria = " and (" + sqlSearch + ")";
}
if (officeId != null) {
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)) {
extraCriteria = extraCriteria.substring(4);
}
logger.info("extraCriteria; " + extraCriteria);
return extraCriteria;
}
@GET
@Path("{clientId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveClient(
@PathParam("clientId") final Long clientId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENT");
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);
}
private ClientData handleMakerCheckerRequest(final Long clientId, final Long makerCheckerId, ClientData clientData) {
final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
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) { context.authenticatedUser().validateHasReadPermission("CLIENT");
Collection<ClientData> dataChanges = new ArrayList<ClientData>();
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
@Path("template")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String newClientDetails(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENT");
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
@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
@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);
return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
@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, "{}");
return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
@GET
@Path("{clientId}/loans")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveClientAccount(@PathParam("clientId") final Long clientId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission("CLIENT");
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("pendingApprovalLoans", "awaitingDisbursalLoans", "openLoans", "closedLoans",
"anyLoanCount", "pendingApprovalLoanCount", "awaitingDisbursalLoanCount", "activeLoanCount", "closedLoanCount",
"pendingApprovalDespositAccountsCount", "pendingApprovalDespositAccounts", "approvedDespositAccountsCount", "approvedDespositAccounts",
"withdrawnByClientDespositAccountsCount","withdrawnByClientDespositAccounts","closedDepositAccountsCount","closedDepositAccounts",
"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
@Path("{clientId}/notes")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveAllClientNotes(@PathParam("clientId") final Long clientId, @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()); final String extraCriteria = getClientCriteria(sqlSearch, officeId, externalId, displayName, firstName, lastName, hierarchy);
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters); final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
} final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final Collection<ClientData> clients = this.clientReadPlatformService.retrieveAllIndividualClients(extraCriteria);
Collection<NoteData> notes = this.clientReadPlatformService.retrieveAllClientNotes(clientId);
return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clients);
return this.apiJsonSerializerService.serializeNoteDataToJson(prettyPrint, responseParameters, notes); }
}
private String getClientCriteria(String sqlSearch, Integer officeId, String externalId, String displayName, String firstName,
@POST String lastName, String hierarchy) {
@Path("{clientId}/notes")
@Consumes({MediaType.APPLICATION_JSON}) String extraCriteria = "";
@Produces({MediaType.APPLICATION_JSON})
public Response addNewClientNote(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { if (sqlSearch != null) {
extraCriteria = " and (" + sqlSearch + ")";
NoteCommand command = this.apiDataConversionService.convertJsonToNoteCommand(null, clientId, jsonRequestBody); }
EntityIdentifier identifier = this.clientWritePlatformService.addClientNote(command); if (officeId != null) {
extraCriteria += " and office_id = " + officeId;
return Response.ok().entity(identifier).build(); }
}
if (externalId != null) {
@GET extraCriteria += " and external_id like " + ApiParameterHelper.sqlEncodeString(externalId);
@Path("{clientId}/notes/{noteId}") }
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON}) if (displayName != null) {
public String retrieveClientNote( extraCriteria += " and concat(ifnull(firstname, ''), if(firstname > '',' ', '') , ifnull(lastname, '')) like "
@PathParam("clientId") final Long clientId, + ApiParameterHelper.sqlEncodeString(displayName);
@PathParam("noteId") final Long noteId, }
@Context final UriInfo uriInfo) {
if (firstName != null) {
context.authenticatedUser().validateHasReadPermission("CLIENTNOTE"); extraCriteria += " and firstname like " + ApiParameterHelper.sqlEncodeString(firstName);
}
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "clientId", "loanId", "loanTransactionId", "noteType", "note", "createdById", "createdByUsername", if (lastName != null) {
"createdOn", "updatedById", "updatedByUsername", "updatedOn") extraCriteria += " and lastname like " + ApiParameterHelper.sqlEncodeString(lastName);
); }
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (hierarchy != null) {
if (responseParameters.isEmpty()) { extraCriteria += " and o.hierarchy like " + ApiParameterHelper.sqlEncodeString(hierarchy + "%");
responseParameters.addAll(typicalResponseParameters); }
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); if (StringUtils.isNotBlank(extraCriteria)) {
extraCriteria = extraCriteria.substring(4);
NoteData note = this.clientReadPlatformService.retrieveClientNote(clientId, noteId); }
return this.apiJsonSerializerService.serializeNoteDataToJson(prettyPrint, responseParameters, note); logger.info("extraCriteria; " + extraCriteria);
}
return extraCriteria;
@PUT }
@Path("{clientId}/notes/{noteId}")
@Consumes({MediaType.APPLICATION_JSON}) @GET
@Produces({MediaType.APPLICATION_JSON}) @Path("{clientId}")
public Response updateClientNote( @Consumes({ MediaType.APPLICATION_JSON })
@PathParam("clientId") final Long clientId, @Produces({ MediaType.APPLICATION_JSON })
@PathParam("noteId") final Long noteId, final String jsonRequestBody) { public String retrieveClient(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
NoteCommand command = this.apiDataConversionService.convertJsonToNoteCommand(noteId, clientId, jsonRequestBody); context.authenticatedUser().validateHasReadPermission("CLIENT");
EntityIdentifier identifier = this.clientWritePlatformService.updateNote(command); final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
return Response.ok().entity(identifier).build(); final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
} final Long makerCheckerId = ApiParameterHelper.makerCheckerId(uriInfo.getQueryParameters());
/** ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId);
* Upload images through multi-part form upload if (template) {
*/ final List<OfficeLookup> allowedOffices = new ArrayList<OfficeLookup>(officeReadPlatformService.retrieveAllOfficesForLookup());
@POST clientData = ClientData.templateOnTop(clientData, allowedOffices);
@Path("{clientId}/image") }
@Consumes({ MediaType.MULTIPART_FORM_DATA }) if (makerCheckerId != null) {
@Produces({ MediaType.APPLICATION_JSON }) clientData = handleMakerCheckerRequest(clientId, makerCheckerId, clientData);
public Response addNewClientImage( }
@PathParam("clientId") final Long clientId,
@HeaderParam("Content-Length") Long fileSize, boolean retrieveChanges = true;
@FormDataParam("file") InputStream inputStream, if (retrieveChanges) {
@FormDataParam("file") FormDataContentDisposition fileDetails, final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
@FormDataParam("file") FormDataBodyPart bodyPart) { clientData = ClientData.integrateChanges(clientData, clientData.currentChange(), dataChanges);
}
//TODO: vishwas might need more advances validation (like reading magic number) for handling malicious clients return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
//and clients not setting mime type }
FileUtils.validateClientImageNotEmpty(fileDetails.getFileName());
FileUtils.validateImageMimeType(bodyPart.getMediaType().toString()); private ClientData handleMakerCheckerRequest(final Long clientId, final Long makerCheckerId, ClientData clientData) {
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, final CommandSourceData entry = this.commandSourceReadPlatformService.retrieveById(makerCheckerId);
fileDetails.getFileName(), final ClientData currentChange = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId, entry.json());
ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
final Collection<ClientData> dataChanges = retrieveAllUnprocessedDataChanges(clientId);
logger.debug(bodyPart.getMediaType().toString()); clientData = ClientData.integrateChanges(clientData, currentChange, dataChanges);
return clientData;
EntityIdentifier entityIdentifier = this.clientWritePlatformService }
.saveOrUpdateClientImage(clientId, fileDetails.getFileName(),
inputStream); private Collection<ClientData> retrieveAllUnprocessedDataChanges(final Long clientId) {
Collection<ClientData> dataChanges = new ArrayList<ClientData>();
return Response.ok().entity(entityIdentifier).build();
} boolean retrieveChanges = true;
if (retrieveChanges) {
Collection<CommandSourceData> unprocessedChanges = this.commandSourceReadPlatformService.retrieveUnprocessChangesByResourceId(
/** "clients", clientId);
* Upload image as a Data URL (essentially a base64 encoded stream) for (CommandSourceData commandSourceData : unprocessedChanges) {
*/ ClientData change = this.apiDataConversionService.convertInternalJsonFormatToClientDataChange(clientId,
@POST commandSourceData.json());
@Path("{clientId}/image") dataChanges.add(change);
@Consumes({ MediaType.APPLICATION_JSON }) }
@Produces({ MediaType.APPLICATION_JSON }) }
public Response addNewClientImage(
@PathParam("clientId") final Long clientId, if (dataChanges.isEmpty()) {
final String jsonRequestBody) { dataChanges = null;
}
Base64EncodedImage base64EncodedImage = FileUtils
.extractImageFromDataURL(jsonRequestBody); return dataChanges;
}
EntityIdentifier entityIdentifier = this.clientWritePlatformService
.saveOrUpdateClientImage(clientId, base64EncodedImage); @GET
@Path("template")
return Response.ok().entity(entityIdentifier).build(); @Consumes({ MediaType.APPLICATION_JSON })
} @Produces({ MediaType.APPLICATION_JSON })
public String newClientDetails(@Context final UriInfo uriInfo) {
/**
* Returns a base 64 encoded client image context.authenticatedUser().validateHasReadPermission("CLIENT");
*/
@GET final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
@Path("{clientId}/image") final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
@Consumes({MediaType.APPLICATION_JSON}) final Long makerCheckerId = ApiParameterHelper.makerCheckerId(uriInfo.getQueryParameters());
@Produces({MediaType.APPLICATION_JSON})
public Response retrieveClientImage( ClientData clientData = this.clientReadPlatformService.retrieveNewClientDetails();
@PathParam("clientId") final Long clientId) { if (makerCheckerId != null) {
clientData = handleMakerCheckerRequest(null, makerCheckerId, clientData);
context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE"); }
final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); return this.apiJsonSerializerService.serializeClientDataToJson(prettyPrint, responseParameters, clientData);
}
if (clientData.imageKeyDoesNotExist()) {
throw new ImageNotFoundException("clients", clientId); @POST
} @Consumes({ MediaType.APPLICATION_JSON })
return Response.ok().entity(Base64.encodeFromFile(clientData.imageKey())).build(); @Produces({ MediaType.APPLICATION_JSON })
} public String createClient(final String jsonRequestBody) {
/** final EntityIdentifier result = this.commandsSourceWritePlatformService
* This method is added only for consistency with other URL patterns .logCommandSource("CREATE", "clients", null, jsonRequestBody);
* and for maintaining consistency of usage of the HTTP "verb"
* at the client side return this.apiJsonSerializerService.serializeEntityIdentifier(result);
*/ }
@PUT
@Path("{clientId}/image") @PUT
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Path("{clientId}")
@Produces({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
public Response updateClientImage( @Produces({ MediaType.APPLICATION_JSON })
@PathParam("clientId") final Long clientId, public String updateClient(@PathParam("clientId") final Long clientId, final String jsonRequestBody) {
@HeaderParam("Content-Length") Long fileSize,
@FormDataParam("file") InputStream inputStream, final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "clients", clientId,
@FormDataParam("file") FormDataContentDisposition fileDetails, jsonRequestBody);
@FormDataParam("file") FormDataBodyPart bodyPart) {
return addNewClientImage(clientId, fileSize, inputStream, fileDetails, return this.apiJsonSerializerService.serializeEntityIdentifier(result);
bodyPart); }
}
@DELETE
@DELETE @Path("{clientId}")
@Path("{clientId}/image") @Consumes({ MediaType.APPLICATION_JSON })
@Consumes({MediaType.APPLICATION_JSON}) @Produces({ MediaType.APPLICATION_JSON })
@Produces({MediaType.APPLICATION_JSON}) public String deleteClient(@PathParam("clientId") final Long clientId) {
public Response deleteClientImage(@PathParam("clientId") final Long clientId) {
this.clientWritePlatformService.deleteClientImage(clientId); final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("DELETE", "clients", clientId, "{}");
return Response.ok(new EntityIdentifier(clientId)).build();
} return this.apiJsonSerializerService.serializeEntityIdentifier(result);
}
/** @GET
* This method is added only for consistency with other URL patterns @Path("{clientId}/loans")
* and for maintaining consistency of usage of the HTTP "verb" @Consumes({ MediaType.APPLICATION_JSON })
* at the client side @Produces({ MediaType.APPLICATION_JSON })
* public String retrieveClientAccount(@PathParam("clientId") final Long clientId, @Context final UriInfo uriInfo) {
* Upload image as a Data URL (essentially a base64 encoded stream)
*/ context.authenticatedUser().validateHasReadPermission("CLIENT");
@PUT
@Path("{clientId}/image") Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("pendingApprovalLoans", "awaitingDisbursalLoans",
@Consumes({ MediaType.APPLICATION_JSON }) "openLoans", "closedLoans", "anyLoanCount", "pendingApprovalLoanCount", "awaitingDisbursalLoanCount", "activeLoanCount",
@Produces({ MediaType.APPLICATION_JSON }) "closedLoanCount", "pendingApprovalDespositAccountsCount", "pendingApprovalDespositAccounts",
public Response updateClientImage( "approvedDespositAccountsCount", "approvedDespositAccounts", "withdrawnByClientDespositAccountsCount",
@PathParam("clientId") final Long clientId, "withdrawnByClientDespositAccounts", "closedDepositAccountsCount", "closedDepositAccounts", "rejectedDepositAccountsCount",
final String jsonRequestBody) { "rejectedDepositAccounts", "preclosedDepositAccountsCount", "preclosedDepositAccounts"));
return addNewClientImage(clientId, jsonRequestBody);
} 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
@Path("{clientId}/notes")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllClientNotes(@PathParam("clientId") final Long clientId, @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());
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;
@@ -53,6 +54,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 RoleCommand command = this.apiDataConversionService.convertJsonToRoleCommand(null, jsonRequestBody); final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("CREATE", "roles", null, apiRequestBodyAsJson);
final Long roleId = this.roleWritePlatformService.createRole(command); return this.apiJsonSerializerService.serializeEntityIdentifier(result);
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( public ClientCommand(final Set<String> modifiedParameters, final Long id, final String externalId, final String firstname,
final Set<String> modifiedParameters, final String lastname, final String clientOrBusinessName, final Long officeId, final LocalDate joiningDate,
final Long id, final boolean makerCheckerApproval) {
final String externalId, this.parametersPassedInRequest = modifiedParameters;
final String firstname, this.id = id;
final String lastname, this.externalId = externalId;
final String clientOrBusinessName, this.firstname = firstname;
final Long officeId, this.lastname = lastname;
final LocalDate joiningDate, this.clientOrBusinessName = clientOrBusinessName;
final boolean makerCheckerApproval) { this.officeId = officeId;
this.parametersPassedInRequest = modifiedParameters; this.joiningDate = joiningDate;
this.id = id; this.makerCheckerApproval = makerCheckerApproval;
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 Long getId() {
return id; return id;
} }
public String getExternalId() { public String getExternalId() {
return externalId; return externalId;
} }
public String getFirstname() { public String getFirstname() {
return firstname; return firstname;
} }
public String getLastname() { public String getLastname() {
return lastname; return lastname;
} }
public String getClientOrBusinessName() { public String getClientOrBusinessName() {
return clientOrBusinessName; return clientOrBusinessName;
} }
public Long getOfficeId() { public Long getOfficeId() {
return officeId; return officeId;
} }
public LocalDate getJoiningDate() { public LocalDate getJoiningDate() {
return joiningDate; return joiningDate;
} }
public boolean isFirstnameChanged() { public boolean isFirstnameChanged() {
return this.parametersPassedInRequest.contains("firstname"); return this.parametersPassedInRequest.contains("firstname");
} }
public boolean isLastnameChanged() { public boolean isLastnameChanged() {
return this.parametersPassedInRequest.contains("lastname"); return this.parametersPassedInRequest.contains("lastname");
} }
public boolean isClientOrBusinessNameChanged() { public boolean isClientOrBusinessNameChanged() {
return this.parametersPassedInRequest.contains("clientOrBusinessName"); return this.parametersPassedInRequest.contains("clientOrBusinessName");
} }
public boolean isExternalIdChanged() { public boolean isExternalIdChanged() {
return this.parametersPassedInRequest.contains("externalId"); return this.parametersPassedInRequest.contains("externalId");
} }
public boolean isJoiningDateChanged() { public boolean isJoiningDateChanged() {
return this.parametersPassedInRequest.contains("joiningDate"); return this.parametersPassedInRequest.contains("joiningDate");
} }
public boolean isOfficeChanged() { public boolean isOfficeChanged() {
return this.parametersPassedInRequest.contains("officeId"); return this.parametersPassedInRequest.contains("officeId");
} }
public boolean isApprovedByChecker() { public boolean isApprovedByChecker() {
return this.makerCheckerApproval; 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);
String serializeGuarantorDataToJson(boolean prettyPrint,Set<String> responseParameters, GuarantorData guarantorData);
// TODO - KW - might devide serialize up into portfolio and account to
// 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);
}
}
@@ -28,521 +28,423 @@ import com.google.gson.JsonPrimitive;
*/ */
public class JsonParserHelper { public class JsonParserHelper {
public Boolean extractBooleanNamed(final String parameterName, final JsonElement element, final Set<String> requestParamatersDetected) { public Boolean extractBooleanNamed(final String parameterName, final JsonElement element, final Set<String> requestParamatersDetected) {
Boolean value = null; Boolean value = 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) && object.get(parameterName).isJsonPrimitive()) {
requestParamatersDetected.add(parameterName); requestParamatersDetected.add(parameterName);
JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive(); JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
value = primitive.getAsBoolean(); value = primitive.getAsBoolean();
} }
} }
return value; return value;
} }
public Long extractLongNamed(final String parameterName, public Long extractLongNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) {
final JsonElement element, final Set<String> parametersPassedInRequest) { Long longValue = 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) parametersPassedInRequest.add(parameterName);
&& object.get(parameterName).isJsonPrimitive()) { JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
parametersPassedInRequest.add(parameterName); final String stringValue = primitive.getAsString();
JsonPrimitive primitive = object.get(parameterName) if (StringUtils.isNotBlank(stringValue)) {
.getAsJsonPrimitive(); longValue = Long.valueOf(stringValue);
final String stringValue = primitive.getAsString(); }
if (StringUtils.isNotBlank(stringValue)) { }
longValue = Long.valueOf(stringValue); }
} return longValue;
} }
}
return longValue; public String extractStringNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) {
} String stringValue = null;
if (element.isJsonObject()) {
public String extractStringNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) { JsonObject object = element.getAsJsonObject();
String stringValue = null; if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
if (element.isJsonObject()) { parametersPassedInRequest.add(parameterName);
JsonObject object = element.getAsJsonObject(); final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) { final String valueAsString = primitive.getAsString();
parametersPassedInRequest.add(parameterName); if (StringUtils.isNotBlank(valueAsString)) {
final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive(); stringValue = valueAsString;
final String valueAsString = primitive.getAsString(); }
if (StringUtils.isNotBlank(valueAsString)) { }
stringValue = valueAsString; }
} return stringValue;
} }
}
return stringValue; public BigDecimal extractBigDecimalNamed(final String parameterName, final JsonElement element, final Set<String> modifiedParameters) {
} BigDecimal value = null;
if (element.isJsonObject()) {
public BigDecimal extractBigDecimalNamed( final JsonObject object = element.getAsJsonObject();
final String parameterName, final Locale locale = extractLocaleValue(object);
final JsonElement element, value = extractBigDecimalNamed(parameterName, object, locale, modifiedParameters);
final Set<String> modifiedParameters) { }
BigDecimal value = null; return value;
if (element.isJsonObject()) { }
final JsonObject object = element.getAsJsonObject();
final Locale locale = extractLocaleValue(object); public BigDecimal extractBigDecimalNamed(final String parameterName, final JsonObject element, final Locale locale,
value = extractBigDecimalNamed(parameterName, object, locale, modifiedParameters); final Set<String> modifiedParameters) {
} BigDecimal value = null;
return value; if (element.isJsonObject()) {
} JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
public BigDecimal extractBigDecimalNamed( modifiedParameters.add(parameterName);
final String parameterName, JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
final JsonObject element, String valueAsString = primitive.getAsString();
final Locale locale, if (StringUtils.isNotBlank(valueAsString)) {
final Set<String> modifiedParameters) { value = convertFrom(valueAsString, parameterName, locale);
BigDecimal value = null; }
if (element.isJsonObject()) { }
JsonObject object = element.getAsJsonObject(); }
if (object.has(parameterName) return value;
&& object.get(parameterName).isJsonPrimitive()) { }
modifiedParameters.add(parameterName);
JsonPrimitive primitive = object.get(parameterName) public Integer extractIntegerNamed(final String parameterName, final JsonElement element, final Set<String> modifiedParameters) {
.getAsJsonPrimitive(); Integer value = null;
String valueAsString = primitive.getAsString(); if (element.isJsonObject()) {
if (StringUtils.isNotBlank(valueAsString)) { final JsonObject object = element.getAsJsonObject();
value = convertFrom(valueAsString, parameterName, locale); final Locale locale = extractLocaleValue(object);
} value = extractIntegerNamed(parameterName, object, locale, modifiedParameters);
} }
} return value;
return value; }
}
public Integer extractIntegerNamed(final String parameterName, final JsonElement element, final Locale locale,
public Integer extractIntegerNamed( final Set<String> modifiedParameters) {
final String parameterName, Integer value = null;
final JsonElement element, if (element.isJsonObject()) {
final Set<String> modifiedParameters) { final JsonObject object = element.getAsJsonObject();
Integer value = null; if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
if (element.isJsonObject()) { modifiedParameters.add(parameterName);
final JsonObject object = element.getAsJsonObject(); JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
final Locale locale = extractLocaleValue(object); String valueAsString = primitive.getAsString();
value = extractIntegerNamed(parameterName, object, locale, modifiedParameters); if (StringUtils.isNotBlank(valueAsString)) {
} value = convertToInteger(valueAsString, parameterName, locale);
return value; }
} }
}
public Integer extractIntegerNamed( return value;
final String parameterName, }
final JsonElement element,
final Locale locale, public String extractDateFormatParameter(final JsonObject element) {
final Set<String> modifiedParameters) { String value = null;
Integer value = null; if (element.isJsonObject()) {
if (element.isJsonObject()) { JsonObject object = element.getAsJsonObject();
final JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) { final String dateFormatParameter = "dateFormat";
modifiedParameters.add(parameterName); if (object.has(dateFormatParameter) && object.get(dateFormatParameter).isJsonPrimitive()) {
JsonPrimitive primitive = object.get(parameterName) final JsonPrimitive primitive = object.get(dateFormatParameter).getAsJsonPrimitive();
.getAsJsonPrimitive(); value = primitive.getAsString();
String valueAsString = primitive.getAsString(); }
if (StringUtils.isNotBlank(valueAsString)) { }
value = convertToInteger(valueAsString, parameterName, locale); return value;
} }
}
} public Locale extractLocaleParameter(final JsonObject element) {
return value; Locale clientApplicationLocale = null;
} if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
public String extractDateFormatParameter(final JsonObject element) {
String value = null; String locale = null;
if (element.isJsonObject()) { final String localeParameter = "locale";
JsonObject object = element.getAsJsonObject(); if (object.has(localeParameter) && object.get(localeParameter).isJsonPrimitive()) {
final JsonPrimitive primitive = object.get(localeParameter).getAsJsonPrimitive();
final String dateFormatParameter = "dateFormat"; locale = primitive.getAsString();
if (object.has(dateFormatParameter) clientApplicationLocale = localeFromString(locale);
&& object.get(dateFormatParameter).isJsonPrimitive()) { }
final JsonPrimitive primitive = object.get(dateFormatParameter).getAsJsonPrimitive(); }
value = primitive.getAsString(); return clientApplicationLocale;
} }
}
return value; /**
} * Used with the local date is in array format
*/
public Locale extractLocaleParameter(final JsonObject element) { public LocalDate extractLocalDateAsArrayNamed(final String parameterName, final JsonElement element,
Locale clientApplicationLocale = null; final Set<String> parametersPassedInCommand) {
if (element.isJsonObject()) { LocalDate value = null;
JsonObject object = element.getAsJsonObject(); if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
String locale = null;
final String localeParameter = "locale"; if (object.has(parameterName) && object.get(parameterName).isJsonArray()) {
if (object.has(localeParameter)
&& object.get(localeParameter).isJsonPrimitive()) { parametersPassedInCommand.add(parameterName);
final JsonPrimitive primitive = object.get(localeParameter).getAsJsonPrimitive();
locale = primitive.getAsString(); final JsonArray dateArray = object.get(parameterName).getAsJsonArray();
clientApplicationLocale = localeFromString(locale);
} Integer year = dateArray.get(0).getAsInt();
} Integer month = dateArray.get(1).getAsInt();
return clientApplicationLocale; Integer day = dateArray.get(2).getAsInt();
}
value = new LocalDate().withYearOfEra(year).withMonthOfYear(month).withDayOfMonth(day);
/** }
* Used with the local date is in array format
*/ }
public LocalDate extractLocalDateAsArrayNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInCommand) { return value;
LocalDate value = null; }
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject(); public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element,
final Set<String> parametersPassedInCommand) {
if (object.has(parameterName) && object.get(parameterName).isJsonArray()) {
LocalDate value = null;
parametersPassedInCommand.add(parameterName);
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
final JsonArray dateArray = object.get(parameterName).getAsJsonArray();
final String dateFormat = extractDateFormatParameter(object);
Integer year = dateArray.get(0).getAsInt(); final Locale clientApplicationLocale = extractLocaleParameter(object);
Integer month = dateArray.get(1).getAsInt(); value = extractLocalDateNamed(parameterName, object, dateFormat, clientApplicationLocale, parametersPassedInCommand);
Integer day = dateArray.get(2).getAsInt(); }
return value;
value = new LocalDate().withYearOfEra(year).withMonthOfYear(month).withDayOfMonth(day); }
}
public LocalDate extractLocalDateNamed(final String parameterName, final JsonObject element, final String dateFormat,
} final Locale clientApplicationLocale, final Set<String> parametersPassedInCommand) {
return value; LocalDate value = null;
} if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
public LocalDate extractLocalDateNamed(
final String parameterName, if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
final JsonElement element,
final Set<String> parametersPassedInCommand) { parametersPassedInCommand.add(parameterName);
LocalDate value = null; final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
final String valueAsString = primitive.getAsString();
if (element.isJsonObject()) { if (StringUtils.isNotBlank(valueAsString)) {
JsonObject object = element.getAsJsonObject(); value = convertFrom(valueAsString, parameterName, dateFormat, clientApplicationLocale);
}
final String dateFormat = extractDateFormatParameter(object); }
final Locale clientApplicationLocale = extractLocaleParameter(object);
value = extractLocalDateNamed(parameterName, object, dateFormat, clientApplicationLocale, parametersPassedInCommand); }
} return value;
return value; }
}
public LocalDate convertFrom(final String dateAsString, final String parameterName, final String dateFormat,
public LocalDate extractLocalDateNamed( final Locale clientApplicationLocale) {
final String parameterName,
final JsonObject element, if (StringUtils.isBlank(dateFormat) || clientApplicationLocale == null) {
final String dateFormat,
final Locale clientApplicationLocale, List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final Set<String> parametersPassedInCommand) { if (StringUtils.isBlank(dateFormat)) {
LocalDate value = null; String defaultMessage = new StringBuilder("The parameter '" + parameterName
if (element.isJsonObject()) { + "' requires a 'dateFormat' parameter to be passed with it.").toString();
JsonObject object = element.getAsJsonObject(); ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.dateFormat.parameter", defaultMessage,
parameterName);
if (object.has(parameterName) dataValidationErrors.add(error);
&& object.get(parameterName).isJsonPrimitive()) { }
if (clientApplicationLocale == null) {
parametersPassedInCommand.add(parameterName); String defaultMessage = new StringBuilder("The parameter '" + parameterName
+ "' requires a 'locale' parameter to be passed with it.").toString();
final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive(); ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage,
final String valueAsString = primitive.getAsString(); parameterName);
if (StringUtils.isNotBlank(valueAsString)) { dataValidationErrors.add(error);
value = convertFrom(valueAsString, parameterName, dateFormat, clientApplicationLocale); }
} throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
} dataValidationErrors);
}
}
return value; LocalDate eventLocalDate = null;
} if (StringUtils.isNotBlank(dateAsString)) {
try {
public LocalDate convertFrom(final String dateAsString, // Locale locale = LocaleContextHolder.getLocale();
final String parameterName, final String dateFormat, eventLocalDate = DateTimeFormat.forPattern(dateFormat).withLocale(clientApplicationLocale)
final Locale clientApplicationLocale) { .parseLocalDate(dateAsString.toLowerCase(clientApplicationLocale));
} catch (IllegalArgumentException e) {
if (StringUtils.isBlank(dateFormat) || clientApplicationLocale == null) { List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.date.format", "The parameter "
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); + parameterName + " is invalid based on the dateFormat: '" + dateFormat + "' and locale: '"
if (StringUtils.isBlank(dateFormat)) { + clientApplicationLocale + "' provided:", parameterName, dateAsString, dateFormat);
String defaultMessage = new StringBuilder( dataValidationErrors.add(error);
"The parameter '"
+ parameterName throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
+ "' requires a 'dateFormat' parameter to be passed with it.") dataValidationErrors);
.toString(); }
ApiParameterError error = ApiParameterError.parameterError( }
"validation.msg.missing.dateFormat.parameter",
defaultMessage, parameterName); return eventLocalDate;
dataValidationErrors.add(error); }
}
if (clientApplicationLocale == null) { public Integer convertToInteger(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) {
String defaultMessage = new StringBuilder(
"The parameter '" if (clientApplicationLocale == null) {
+ parameterName
+ "' requires a 'locale' parameter to be passed with it.") List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
.toString(); String defaultMessage = new StringBuilder("The parameter '" + parameterName
ApiParameterError error = ApiParameterError.parameterError( + "' requires a 'locale' parameter to be passed with it.").toString();
"validation.msg.missing.locale.parameter", ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage,
defaultMessage, parameterName); parameterName);
dataValidationErrors.add(error); 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); }
}
try {
LocalDate eventLocalDate = null; Integer number = null;
if (StringUtils.isNotBlank(dateAsString)) {
try { if (StringUtils.isNotBlank(numericalValueFormatted)) {
// Locale locale = LocaleContextHolder.getLocale();
eventLocalDate = DateTimeFormat String source = numericalValueFormatted.trim();
.forPattern(dateFormat)
.withLocale(clientApplicationLocale) NumberFormat format = NumberFormat.getInstance(clientApplicationLocale);
.parseLocalDate( DecimalFormat df = (DecimalFormat) format;
dateAsString DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
.toLowerCase(clientApplicationLocale)); df.setParseBigDecimal(true);
} catch (IllegalArgumentException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); // http://bugs.sun.com/view_bug.do?bug_id=4510618
ApiParameterError error = ApiParameterError.parameterError( char groupingSeparator = symbols.getGroupingSeparator();
"validation.msg.invalid.date.format", "The parameter " if (groupingSeparator == '\u00a0') {
+ parameterName source = source.replaceAll(" ", Character.toString('\u00a0'));
+ " is invalid based on the dateFormat: '" }
+ dateFormat + "' and locale: '"
+ clientApplicationLocale + "' provided:", Number parsedNumber = df.parse(source);
parameterName, dateAsString, dateFormat);
dataValidationErrors.add(error); double parsedNumberDouble = parsedNumber.doubleValue();
int parsedNumberInteger = parsedNumber.intValue();
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist", if (source.contains(Character.toString(symbols.getDecimalSeparator()))) { throw new ParseException(source, 0); }
"Validation errors exist.", dataValidationErrors);
} if (!Double.valueOf(parsedNumberDouble).equals(Double.valueOf(Integer.valueOf(parsedNumberInteger)))) { throw new ParseException(
} source, 0); }
return eventLocalDate; number = parsedNumber.intValue();
} }
public Integer convertToInteger(final String numericalValueFormatted, return number;
final String parameterName, final Locale clientApplicationLocale) { } catch (ParseException e) {
if (clientApplicationLocale == null) { List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.integer.format", "The parameter "
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); + parameterName + " has value: " + numericalValueFormatted + " which is invalid integer value for provided locale of ["
String defaultMessage = new StringBuilder("The parameter '" + clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
+ parameterName dataValidationErrors.add(error);
+ "' requires a 'locale' parameter to be passed with it.")
.toString(); throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
ApiParameterError error = ApiParameterError.parameterError( dataValidationErrors);
"validation.msg.missing.locale.parameter", defaultMessage, }
parameterName); }
dataValidationErrors.add(error);
public BigDecimal convertFrom(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) {
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist", if (clientApplicationLocale == null) {
"Validation errors exist.", dataValidationErrors);
} List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
String defaultMessage = new StringBuilder("The parameter '" + parameterName
try { + "' requires a 'locale' parameter to be passed with it.").toString();
Integer number = null; ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage,
parameterName);
if (StringUtils.isNotBlank(numericalValueFormatted)) { dataValidationErrors.add(error);
String source = numericalValueFormatted.trim(); throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
dataValidationErrors);
NumberFormat format = NumberFormat }
.getInstance(clientApplicationLocale);
DecimalFormat df = (DecimalFormat) format; try {
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); BigDecimal number = null;
df.setParseBigDecimal(true);
if (StringUtils.isNotBlank(numericalValueFormatted)) {
// http://bugs.sun.com/view_bug.do?bug_id=4510618
char groupingSeparator = symbols.getGroupingSeparator(); String source = numericalValueFormatted.trim();
if (groupingSeparator == '\u00a0') {
source = source.replaceAll(" ", NumberFormat format = NumberFormat.getNumberInstance(clientApplicationLocale);
Character.toString('\u00a0')); DecimalFormat df = (DecimalFormat) format;
} DecimalFormatSymbols symbols = df.getDecimalFormatSymbols();
// http://bugs.sun.com/view_bug.do?bug_id=4510618
Number parsedNumber = df.parse(source); char groupingSeparator = symbols.getGroupingSeparator();
if (groupingSeparator == '\u00a0') {
double parsedNumberDouble = parsedNumber.doubleValue(); source = source.replaceAll(" ", Character.toString('\u00a0'));
int parsedNumberInteger = parsedNumber.intValue(); }
if (source.contains(Character.toString(symbols NumberFormatter numberFormatter = new NumberFormatter();
.getDecimalSeparator()))) { Number parsedNumber = numberFormatter.parse(source, clientApplicationLocale);
throw new ParseException(source, 0); number = BigDecimal.valueOf(Double.valueOf(parsedNumber.doubleValue()));
} }
if (!Double.valueOf(parsedNumberDouble).equals( return number;
Double.valueOf(Integer.valueOf(parsedNumberInteger)))) { } catch (ParseException e) {
throw new ParseException(source, 0);
} List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.decimal.format", "The parameter "
number = parsedNumber.intValue(); + parameterName + " has value: " + numericalValueFormatted + " which is invalid decimal value for provided locale of ["
} + clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale);
dataValidationErrors.add(error);
return number;
} catch (ParseException e) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
dataValidationErrors);
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); }
ApiParameterError error = ApiParameterError }
.parameterError(
"validation.msg.invalid.integer.format", private Locale localeFromString(final String localeAsString) {
"The parameter "
+ parameterName if (StringUtils.isBlank(localeAsString)) {
+ " has value: " List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
+ numericalValueFormatted ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format",
+ " which is invalid integer value for provided locale of [" "The parameter locale is invalid. It cannot be blank.", "locale");
+ clientApplicationLocale.toString() + "].", dataValidationErrors.add(error);
parameterName, numericalValueFormatted,
clientApplicationLocale); throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
dataValidationErrors.add(error); dataValidationErrors);
}
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist", String languageCode = "";
"Validation errors exist.", dataValidationErrors); String courntryCode = "";
} String variantCode = "";
}
String[] localeParts = localeAsString.split("_");
public BigDecimal convertFrom(final String numericalValueFormatted,
final String parameterName, final Locale clientApplicationLocale) { if (localeParts != null && localeParts.length == 1) {
languageCode = localeParts[0];
if (clientApplicationLocale == null) { }
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); if (localeParts != null && localeParts.length == 2) {
String defaultMessage = new StringBuilder("The parameter '" languageCode = localeParts[0];
+ parameterName courntryCode = localeParts[1];
+ "' requires a 'locale' parameter to be passed with it.") }
.toString();
ApiParameterError error = ApiParameterError.parameterError( if (localeParts != null && localeParts.length == 3) {
"validation.msg.missing.locale.parameter", defaultMessage, languageCode = localeParts[0];
parameterName); courntryCode = localeParts[1];
dataValidationErrors.add(error); variantCode = localeParts[2];
}
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist", return localeFrom(languageCode, courntryCode, variantCode);
"Validation errors exist.", dataValidationErrors); }
}
private Locale localeFrom(final String languageCode, final String courntryCode, final String variantCode) {
try {
BigDecimal number = null; List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (StringUtils.isNotBlank(numericalValueFormatted)) { List<String> allowedLanguages = Arrays.asList(Locale.getISOLanguages());
if (!allowedLanguages.contains(languageCode.toLowerCase())) {
String source = numericalValueFormatted.trim(); ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format",
"The parameter locale has an invalid language value " + languageCode + " .", "locale", languageCode);
NumberFormat format = NumberFormat dataValidationErrors.add(error);
.getNumberInstance(clientApplicationLocale); }
DecimalFormat df = (DecimalFormat) format;
DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); if (StringUtils.isNotBlank(courntryCode.toUpperCase())) {
// http://bugs.sun.com/view_bug.do?bug_id=4510618 List<String> allowedCountries = Arrays.asList(Locale.getISOCountries());
char groupingSeparator = symbols.getGroupingSeparator(); if (!allowedCountries.contains(courntryCode)) {
if (groupingSeparator == '\u00a0') { ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format",
source = source.replaceAll(" ", "The parameter locale has an invalid country value " + courntryCode + " .", "locale", courntryCode);
Character.toString('\u00a0')); dataValidationErrors.add(error);
} }
}
NumberFormatter numberFormatter = new NumberFormatter();
Number parsedNumber = numberFormatter.parse(source, if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
clientApplicationLocale); "Validation errors exist.", dataValidationErrors); }
number = BigDecimal.valueOf(Double.valueOf(parsedNumber
.doubleValue())); return new Locale(languageCode.toLowerCase(), courntryCode.toUpperCase(), variantCode);
} }
return number; private Locale extractLocaleValue(final JsonObject object) {
} catch (ParseException e) { Locale clientApplicationLocale = null;
String locale = null;
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); if (object.has("locale") && object.get("locale").isJsonPrimitive()) {
ApiParameterError error = ApiParameterError JsonPrimitive primitive = object.get("locale").getAsJsonPrimitive();
.parameterError( locale = primitive.getAsString();
"validation.msg.invalid.decimal.format", clientApplicationLocale = localeFromString(locale);
"The parameter " }
+ parameterName return clientApplicationLocale;
+ " has value: " }
+ numericalValueFormatted
+ " which is invalid decimal value for provided locale of ["
+ clientApplicationLocale.toString() + "].",
parameterName, numericalValueFormatted,
clientApplicationLocale);
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
private Locale localeFromString(final String localeAsString) {
if (StringUtils.isBlank(localeAsString)) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.invalid.locale.format",
"The parameter locale is invalid. It cannot be blank.",
"locale");
dataValidationErrors.add(error);
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,26 +12,25 @@ 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) @Column(name = "code", nullable = false, length = 100)
private final String code; private final String code;
@Column(name = "default_name", nullable = false, length=100) @Column(name = "default_name", nullable = false, length = 100)
private final String defaultName; private final String defaultName;
@Column(name = "default_description", nullable = false, length=500) @Column(name = "default_description", nullable = false, length = 500)
private final String defaultDescription; 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;
@@ -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 @Autowired
public RoleWritePlatformServiceJpaRepositoryImpl( public RoleWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final RoleRepository roleRepository,
final PlatformSecurityContext context, final PermissionRepository permissionRepository) {
final RoleRepository roleRepository, this.context = context;
final PermissionRepository permissionRepository) { this.roleRepository = roleRepository;
this.context = context; this.permissionRepository = permissionRepository;
this.roleRepository = roleRepository; }
this.permissionRepository = permissionRepository;
}
@Transactional @Transactional
@Override @Override
public Long createRole(final RoleCommand command) { public Long createRole(final RoleCommand command) {
context.authenticatedUser(); context.authenticatedUser();
RoleCommandValidator validator = new RoleCommandValidator(command); RoleCommandValidator validator = new RoleCommandValidator(command);
validator.validateForCreate(); validator.validateForCreate();
Role entity = new Role(command.getName(), command.getDescription()); Role entity = new Role(command.getName(), command.getDescription());
this.roleRepository.save(entity); this.roleRepository.save(entity);
return entity.getId(); if (this.makerCheckerEnabledForTask && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); }
}
@Transactional return entity.getId();
@Override }
public Long updateRole(RoleCommand command) {
context.authenticatedUser(); @Transactional
@Override
public Long updateRole(RoleCommand command) {
RoleCommandValidator validator = new RoleCommandValidator(command); context.authenticatedUser();
validator.validateForUpdate();
Role role = this.roleRepository.findOne(command.getId()); RoleCommandValidator validator = new RoleCommandValidator(command);
if (role == null) { validator.validateForUpdate();
throw new RoleNotFoundException(command.getId());
}
role.update(command);
this.roleRepository.save(role); Role role = this.roleRepository.findOne(command.getId());
if (role == null) { throw new RoleNotFoundException(command.getId()); }
role.update(command);
return role.getId(); this.roleRepository.save(role);
}
@Transactional if (this.makerCheckerEnabledForTask && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); }
@Override
public Long updateRolePermissions(final RolePermissionCommand command) {
context.authenticatedUser();
final Role role = this.roleRepository.findOne(command.getRoleId()); return role.getId();
if (role == null) { }
throw new RoleNotFoundException(command.getRoleId());
}
Collection<Permission> allPermissions = this.permissionRepository @Transactional
.findAll(); @Override
public Long updateRolePermissions(final RolePermissionCommand command) {
context.authenticatedUser();
Map<String, Boolean> commandPermissions = command.getPermissions(); final Role role = this.roleRepository.findOne(command.getRoleId());
for (String permissionCode : commandPermissions.keySet()) { if (role == null) { throw new RoleNotFoundException(command.getRoleId()); }
Boolean selected = commandPermissions.get(permissionCode);
Permission permission = getPermissionByCode(allPermissions, Collection<Permission> allPermissions = this.permissionRepository.findAll();
permissionCode);
if (role.getPermissions().contains(permission)) { Map<String, Boolean> commandPermissions = command.getPermissions();
if (!(selected)) { for (String permissionCode : commandPermissions.keySet()) {
role.getPermissions().remove(permission); Boolean selected = commandPermissions.get(permissionCode);
}
} else { final Permission permission = findPermissionByCode(allPermissions, permissionCode);
if (selected) {
role.getPermissions().add(permission);
}
} if (role.getPermissions().contains(permission)) {
} if (!(selected)) {
role.getPermissions().remove(permission);
}
} else {
if (selected) {
role.getPermissions().add(permission);
}
}
}
this.roleRepository.save(role); this.roleRepository.save(role);
return role.getId(); return role.getId();
} }
private Permission getPermissionByCode( private Permission findPermissionByCode(Collection<Permission> allPermissions, String permissionCode) {
Collection<Permission> allPermissions, String permissionCode) {
if (allPermissions != null) { if (allPermissions != null) {
for (Permission permission : allPermissions) { for (Permission permission : allPermissions) {
if (permission.code().equals(permissionCode)) return permission; if (permission.hasCode(permissionCode)) {return permission;}
}
}
} throw new PermissionNotFoundException(permissionCode);
} }
throw new PermissionNotFoundException(permissionCode);
}
} }