-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
20412a7
commit f9b7362
Showing
5 changed files
with
432 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
219 changes: 219 additions & 0 deletions
219
...er-config/override/nypd-connector/src/main/java/com/i2group/nypd/ConnectorController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
/******************************************************************************** | ||
# * Licensed Materials - Property of IBM | ||
# * (C) Copyright IBM Corporation 2021. All Rights Reserved | ||
# * | ||
# * This program and the accompanying materials are made available under the | ||
# * terms of the Eclipse Public License 2.0 which is available at | ||
# * http://www.eclipse.org/legal/epl-2.0. | ||
# * | ||
# * US Government Users Restricted Rights - Use, duplication or | ||
# * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. | ||
# * | ||
# ********************************************************************************/ | ||
|
||
package com.i2group.nypd; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.i2group.nypd.rest.transport.ConnectorResponse; | ||
import com.i2group.nypd.rest.transport.ValidationResponse; | ||
import com.i2group.nypd.rest.transport.request.ConnectorRequest; | ||
import com.i2group.nypd.rest.transport.request.RequestCondition; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.core.io.Resource; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestHeader; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestMethod; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import javax.validation.Valid; | ||
|
||
import java.io.IOException; | ||
import java.util.Base64; | ||
import java.util.List; | ||
|
||
import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE; | ||
import static org.springframework.util.MimeTypeUtils.APPLICATION_XML_VALUE; | ||
|
||
/** Defines endpoints used by i2 Analyze to acquire data */ | ||
@RestController | ||
public class ConnectorController { | ||
|
||
private final ExternalConnectorDataService connectorDataService; | ||
@Value("classpath:global-config.json") | ||
private Resource globalConfigResource; | ||
|
||
@Value("classpath:analyst-config.json") | ||
private Resource analystConfigResource; | ||
|
||
@Value("classpath:other-config.json") | ||
private Resource otherConfigResource; | ||
|
||
@Value("classpath:nypd-complaint-data-schema.xml") | ||
private Resource schemaResource; | ||
@Value("classpath:nypd-complaint-data-schema-charting-schemes.xml") | ||
private Resource chartingSchemesResource; | ||
|
||
@Autowired | ||
private ObjectMapper objectMapper; | ||
|
||
/** | ||
* Creates an instance of the ExternalConnectorDataService used to complete acquires. | ||
* | ||
* @param connectorDataService The class containing operations which perform the operation defined | ||
* by the various services. | ||
*/ | ||
public ConnectorController(ExternalConnectorDataService connectorDataService) { | ||
this.connectorDataService = connectorDataService; | ||
} | ||
|
||
/** | ||
* Defines the /config endpoint which provides global connector configuration data. | ||
* | ||
* @return The global configuration. | ||
*/ | ||
@RequestMapping(method = RequestMethod.GET, value = "/config", produces = APPLICATION_JSON_VALUE) | ||
public Resource config() { | ||
return globalConfigResource; | ||
} | ||
|
||
/** | ||
* Defines the /userconfig endpoint, which provides user-specific connector configuration data. | ||
* | ||
* @return The user-specific configuration. | ||
*/ | ||
@RequestMapping(method = RequestMethod.GET, value = "/userconfig", produces = APPLICATION_JSON_VALUE) | ||
public Resource userConfig(@RequestHeader(value = "I2-Principal", required = false) String principalName, | ||
@RequestHeader(value = "I2-Display-Name", required = false) String displayName, | ||
@RequestHeader(value = "I2-User-Groups", required = false) String userGroups, | ||
@RequestHeader(value = "I2-Security-Permissions", required = false) String securityPermissions, | ||
@RequestHeader(value = "I2-Command-Access-Permissions", required = false) String cacPermissions) { | ||
|
||
final List<?> decodedGroups = decode(userGroups, List.class); | ||
if (decodedGroups != null && decodedGroups.contains("Analyst")) { | ||
System.out.println(principalName + " is an Analyst"); | ||
return analystConfigResource; | ||
} else { | ||
System.out.println(principalName + " is not an Analyst"); | ||
return otherConfigResource; | ||
} | ||
} | ||
|
||
private <T> T decode(String header, Class<T> type) { | ||
if (header == null) { | ||
return null; | ||
} | ||
final byte[] decoded = Base64.getDecoder().decode(header); | ||
try { | ||
return objectMapper.readValue(decoded, type); | ||
} catch (IOException e) { | ||
throw new IllegalArgumentException(e); | ||
} | ||
} | ||
|
||
/** | ||
* Defines the endpoint used to retrieve the connector schema. | ||
* | ||
* @return The connector schema. | ||
*/ | ||
@RequestMapping(method = RequestMethod.GET, value = "/schema", produces = APPLICATION_XML_VALUE) | ||
public Resource schema() { | ||
return schemaResource; | ||
} | ||
|
||
/** | ||
* Defines the endpoint used to retrieve the connector charting schemes. | ||
* | ||
* @return The connector charting schemes. | ||
*/ | ||
@RequestMapping(method = RequestMethod.GET, value = "/charting-schemes", | ||
produces = APPLICATION_XML_VALUE) | ||
public Resource chartingSchemes() { | ||
return chartingSchemesResource; | ||
} | ||
|
||
/** | ||
* Defines the /all endpoint which returns all entities and links. | ||
* | ||
* @return The response containing all entities and links. | ||
*/ | ||
@RequestMapping(method = RequestMethod.POST, value = "/all", consumes = APPLICATION_JSON_VALUE, | ||
produces = APPLICATION_JSON_VALUE) | ||
public ConnectorResponse allService() { | ||
return connectorDataService.retrieveAll(); | ||
} | ||
|
||
/** | ||
* Defines the /search endpoint which retrieves entities and links based on conditions. | ||
* | ||
* @param request The request containing the payload. | ||
* @return The resulting entities and links after a conditional search. | ||
*/ | ||
@RequestMapping(method = RequestMethod.POST, value = "/search", consumes = APPLICATION_JSON_VALUE, | ||
produces = APPLICATION_JSON_VALUE) | ||
public ConnectorResponse searchService(@Valid @RequestBody ConnectorRequest request) { | ||
return connectorDataService.search(request.payload.conditions); | ||
} | ||
|
||
/** | ||
* Defines the /search/validate endpoint which validates the condition inputs. | ||
* | ||
* @param request The request containing the payload. | ||
* @return A response containing an error message or nothing. | ||
*/ | ||
@RequestMapping(method = RequestMethod.POST, value = "/search/validate", | ||
consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) | ||
public ValidationResponse searchValidate(@Valid @RequestBody ConnectorRequest request) { | ||
final ValidationResponse validationResponse = new ValidationResponse(); | ||
final List<RequestCondition> conditions = request.payload.conditions; | ||
final boolean conditionPresent = conditions.stream() | ||
.anyMatch(condition -> condition.value != null); | ||
|
||
if (!conditionPresent) { | ||
validationResponse.errorMessage = "At least one search field should have a specified value."; | ||
} | ||
return validationResponse; | ||
} | ||
|
||
/** | ||
* Defines the /find-like-this-complaint endpoint which finds complaints similar to a selected | ||
* complaint. | ||
* | ||
* @param request The request containing the payload. | ||
* @return The entities found which are similar to the selected complaint. | ||
*/ | ||
@RequestMapping(method = RequestMethod.POST, value = "/find-like-this-complaint", | ||
consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) | ||
public ConnectorResponse findLikeThisComplaintService( | ||
@Valid @RequestBody ConnectorRequest request) { | ||
return connectorDataService.findLikeThisComplaint(request.payload.seeds); | ||
} | ||
|
||
/** | ||
* Defines the /expand endpoint which finds entities and links connected to selected entities. | ||
* | ||
* @param request The request containing the payload. | ||
* @return The resulting entities and links connected to the selected entities. | ||
*/ | ||
@RequestMapping(method = RequestMethod.POST, value = "/expand", consumes = APPLICATION_JSON_VALUE, | ||
produces = APPLICATION_JSON_VALUE) | ||
public ConnectorResponse expandService(@Valid @RequestBody ConnectorRequest request) { | ||
return connectorDataService.expand(request.payload.seeds); | ||
} | ||
|
||
/** | ||
* Defines the /expand-with-conditions endpoint which finds entities and links connected to | ||
* selected entities and also satisfies passed conditions. | ||
* | ||
* @param request The request containing the payload. | ||
* @return The resulting entities and links which meet the requirements. | ||
*/ | ||
@RequestMapping(method = RequestMethod.POST, value = "/expand-with-conditions", | ||
consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) | ||
public ConnectorResponse expandWithConditionsService( | ||
@Valid @RequestBody ConnectorRequest request) { | ||
return connectorDataService.expandWithConditions(request.payload); | ||
} | ||
} |
141 changes: 141 additions & 0 deletions
141
connector/user-config/override/nypd-connector/src/main/resources/analyst-config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
{ | ||
"defaultValues": { | ||
"timeZoneId": "Europe/London", | ||
"resultIdsPersistent": true | ||
}, | ||
"services": [ | ||
{ | ||
"id": "nypd-service", | ||
"name": "NYPD Connector: Get All", | ||
"description": "A service which retrieves all data", | ||
"clientConfigType": "NONE", | ||
"acquireUrl": "/all" | ||
}, | ||
{ | ||
"id": "nypd-search-service", | ||
"name": "NYPD Connector: Search", | ||
"description": "A service for conditional searches", | ||
"clientConfigType": "FORM", | ||
"clientConfigId": "searchForm", | ||
"acquireUrl": "/search", | ||
"validateUrl": "/search/validate" | ||
}, | ||
{ | ||
"id": "nypd-find-like-this-complaint-service", | ||
"name": "NYPD Connector: Find like this Complaint", | ||
"description": "A service which finds a similar complaint", | ||
"clientConfigType": "NONE", | ||
"acquireUrl": "/find-like-this-complaint", | ||
"seedConstraints": { | ||
"min": 1, | ||
"max": 1, | ||
"seedTypes": { | ||
"allowedTypes": "ENTITY", | ||
"itemTypes": [ | ||
{ | ||
"id": "ET1", | ||
"min": 1, | ||
"max": 1 | ||
} | ||
] | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "nypd-expand-service", | ||
"name": "NYPD Connector: Expand", | ||
"description": "A service which executes an Expand operation on a seed", | ||
"clientConfigType": "NONE", | ||
"acquireUrl": "/expand", | ||
"seedConstraints": { | ||
"min": 1, | ||
"max": 1, | ||
"seedTypes": { | ||
"allowedTypes": "ENTITY", | ||
"itemTypes": [ | ||
{ | ||
"id": "ET1" | ||
}, | ||
{ | ||
"id": "ET2" | ||
} | ||
] | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "nypd-expand-with-conditions", | ||
"name": "NYPD Connector: Expand with Conditions", | ||
"description": "A service which executes an Expand operation on a seed with conditions", | ||
"clientConfigType": "FORM", | ||
"clientConfigId": "searchForm", | ||
"acquireUrl": "/expand-with-conditions", | ||
"seedConstraints": { | ||
"min": 1, | ||
"max": 1, | ||
"seedTypes": { | ||
"allowedTypes": "ENTITY", | ||
"itemTypes": [ | ||
{ | ||
"id": "ET1" | ||
}, | ||
{ | ||
"id": "ET2" | ||
} | ||
] | ||
} | ||
} | ||
} | ||
], | ||
"clientConfigs": [ | ||
{ | ||
"id": "searchForm", | ||
"config": { | ||
"sections": [ | ||
{ | ||
"conditions": [ | ||
{ | ||
"id": "boro_nm", | ||
"label": "Borough Name", | ||
"logicalType": "SELECTED_FROM", | ||
"possibleValues": [ | ||
{ | ||
"value": "BROOKLYN" | ||
}, | ||
{ | ||
"value": "BRONX" | ||
}, | ||
{ | ||
"value": "MANHATTAN" | ||
}, | ||
{ | ||
"value": "QUEENS" | ||
}, | ||
{ | ||
"value": "STATEN ISLAND" | ||
} | ||
] | ||
}, | ||
{ | ||
"id": "law_cat_cd", | ||
"label": "Law Category", | ||
"logicalType": "SELECTED_FROM", | ||
"possibleValues": [ | ||
{ | ||
"value": "FELONY" | ||
}, | ||
{ | ||
"value": "MISDEMEANOR" | ||
}, | ||
{ | ||
"value": "VIOLATION" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
] | ||
} |
6 changes: 6 additions & 0 deletions
6
connector/user-config/override/nypd-connector/src/main/resources/global-config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"schemaShortName": "NYPD-Complaints", | ||
"schemaUrl": "/schema", | ||
"chartingSchemesUrl": "/charting-schemes", | ||
"userConfigUrl": "/userconfig" | ||
} |
Oops, something went wrong.