Commit d3bb1794 by Eli Ben Baruch

mde - phase 2 - full support of ge parking and traffic. generalization of dynamic variables

parent dcc59bb1
Showing with 3238 additions and 563 deletions
......@@ -13,7 +13,7 @@ repositories {
}
dependencies {
compile 'com.flipkart.zjsonpatch:zjsonpatch:0.2.1'
// compile 'com.flipkart.zjsonpatch:zjsonpatch:0.2.1'
// compile group:'com.ipgallery.common', name:'microservice', version:'1.2.0'
compile group:'com.ipgallery.common', name:'microservice', version:'1.3.2'
compile group:'com.ipgallery.common', name:'itc', version:'1.0.0'
......@@ -21,34 +21,29 @@ dependencies {
compile 'io.swagger:swagger-annotations:1.5.7'
compile 'org.slf4j:slf4j-simple:1.7.19'
compile 'com.javadocmd:simplelatlng:1.3.1'
compile group: 'org.json', name: 'json', version: '20160212'
// https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api
compile group: 'javax.websocket', name: 'javax.websocket-api', version: '1.1'
compile 'com.neovisionaries:nv-websocket-client:1.30'
compile 'org.java-websocket:Java-WebSocket:1.3.0'
// compile 'com.google.oauth-client:google-oauth-client:1.22.0'
// compile 'com.google.api.client:google-api-client-json:1.2.3-alpha'
// compile 'com.google.http-client:google-http-client-jackson:1.15.0-rc'
///json-patch start
compile 'com.google.guava:guava:1.18.0'
compile 'com.github.fge:json-patch:1.9'
compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.0'
///json-patch end
// <dependency>
// <groupId>com.google.api.client</groupId>
//<artifactId>google-api-client</artifactId>
// <version>1.4.1-beta</version>
//</dependency>
testCompile 'junit:junit:4.12'
// testCompile 'com.neovisionaries:nv-websocket-client:1.30'
testCompile fileTree(dir: '../ds/lib/external/sap', include: '*.jar')
testCompile 'junit:junit:4.12'
// testCompile fileTree(dir: '../ds/lib/external/sap', include: '*.jar')
testCompile 'org.java-websocket:Java-WebSocket:1.3.0'
testCompile 'com.google.oauth-client:google-oauth-client:1.22.0'
testCompile 'com.google.api.client:google-api-client-json:1.2.3-alpha'
// testCompile 'com.google.api.client:google-api-client-zjsonpatch:1.2.3-alpha'
testCompile 'com.google.http-client:google-http-client-jackson:1.15.0-rc'
testCompile 'com.google.api.client:google-api-client:1.4.1-beta'
}
jar {
......
......@@ -7,9 +7,6 @@
"headers": [{
"name": "predix-zone-id",
"value": "c54e3e63-8dc6-425e-a533-64e061f64023"
}, {
"name": "Authorization",
"value": "bearer $token"
}]
},
"authentication": {
......@@ -34,11 +31,10 @@
}, {
"name": "q",
"value": "location-type:PARKING_SPOT"
},
{
"name": "size",
"value": "30"
}],
}, {
"name": "size",
"value": "30"
}],
"headers": [],
"content": null
}
......@@ -56,22 +52,29 @@
"metaDataActionClass": "logic.adapter.action.JsonConvertAction",
"params": {
"intermediateOperations": [{
"metaDataOperationClass": "logic.adapter.HttpAdapter.model.MapJsonToStringOperation",
"operationParams": {
"action": {
"metaDataActionClass": "logic.adapter.action.ExtractValueAction",
"params": {
"path": "/_links/self/href",
"valueType": "STRING"
}
}
}
}, {
"metaDataOperationClass": "logic.adapter.HttpAdapter.model.MapStringToJsonOperation",
"operationParams": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.SimpleHttpAction",
"params": {
"variables": {
"id": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.ExtractSubStringAction",
"extract": {
"path": "/_links/self/href",
"valueType": "STRING"
},
"subString": {
"from": {
"str": "/",
"location": "LAST",
"index": null
},
"to": null
}
}
}},
"id": "getLocationDetails",
"httpMethod": "GET",
"path": "locations/$id",
......@@ -79,8 +82,7 @@
"headers": [],
"content": null
}
},
"id": "lastToken"
}
}
}, {
"metaDataOperationClass": "logic.adapter.HttpAdapter.model.MapJsonToJsonOperation",
......@@ -88,6 +90,25 @@
"action": {
"metaDataActionClass": "logic.adapter.action.JsonPatchAction",
"params": {
"variables": {
"mdeKey": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.ExtractSubStringAction",
"extract": {
"path": "/_embedded/assets/0/_links/self/href",
"valueType": "STRING"
},
"subString": {
"from": {
"str": "/",
"location": "LAST",
"index": null
},
"to": null
}
}
}
},
"fileInput": null,
"filePatch": "parkingSpotJsonPatch.json"
}
......@@ -98,10 +119,7 @@
}
}]
},
"onError": {
"actionsInput": "CONTENT",
"actions": []
}
"onError": null
}
}, {
"action": {
......@@ -125,47 +143,58 @@
"actions": []
}
}
},
{
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.SimpleHttpAction",
"params": {
"id": "subscribe",
"httpMethod": "GET",
"path": "assets/$mdeKey/live-events",
"queryParams": [{
"name": "event-types",
"value": "PKIN,PKOUT"
}, {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.SimpleHttpAction",
"params": {
"id": "subscribe",
"httpMethod": "GET",
"path": "assets/$mdeKey/live-events",
"queryParams": [{
"name": "event-types",
"value": "PKIN,PKOUT"
}],
"headers": [],
"content": null
}
},
"onResponse": {
"onSuccess": {
"actionsInput": "CONTENT",
"actions": [{
"metaDataActionClass": "logic.adapter.HttpAdapter.action.WebSocketAction",
"params": {
"variables": {
"webSocket": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.ExtractSubStringAction",
"extract": {
"path": "/url",
"valueType": "STRING"
},
"subString": {
"from": null,
"to": null
}
}
}
},
"headers": [{
"name": "predix-zone-id",
"value": "c54e3e63-8dc6-425e-a533-64e061f64023"
}],
"webSocket": "$webSocket",
"mdeKey": "$mdeKey",
"uid": "$uid"
}
],
"headers": [],
"content": null
}
}]
},
"onResponse": {
"onSuccess": {
"actionsInput": "CONTENT",
"actions": [{
"metaDataActionClass": "logic.adapter.action.ExtractValueAction",
"params": {
"path": "/url",
"valueType": "STRING"
}
},
{
"metaDataActionClass": "logic.adapter.HttpAdapter.action.WebSocketAction",
"params": {
"headers":[{
"name": "predix-zone-id",
"value": "c54e3e63-8dc6-425e-a533-64e061f64023"
}]
}
}]
},
"onError": {
"actionsInput": "CONTENT",
"actions": []
}
"onError": {
"actionsInput": "CONTENT",
"actions": []
}
}]
}
}
]
}
\ No newline at end of file
......@@ -7,9 +7,6 @@
"headers": [{
"name": "predix-zone-id",
"value": "b6fc22b6-ad71-423e-867b-a1b197f6cfc2"
}, {
"name": "Authorization",
"value": "bearer $token"
}]
},
"authentication": {
......@@ -26,14 +23,19 @@
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.SimpleHttpAction",
"params": {
"id": "subscribe",
"id": "GetAllTrafficLanes",
"httpMethod": "GET",
"path": "assets/$mdeKey/live-events",
"path": "locations/search",
"queryParams": [{
"name": "event-types",
"value": "TFEVT"
}
],
"name": "bbox",
"value": "32.123:-117,32.723179:-117.172655"
}, {
"name": "q",
"value": "location-type:TRAFFIC_LANE"
}, {
"name": "size",
"value": "30"
}],
"headers": [],
"content": null
}
......@@ -44,19 +46,157 @@
"actions": [{
"metaDataActionClass": "logic.adapter.action.ExtractValueAction",
"params": {
"path": "/url",
"valueType": "STRING"
"path": "/_embedded/locations",
"valueType": "ARRAY-NODE"
}
}, {
"metaDataActionClass": "logic.adapter.action.JsonConvertAction",
"params": {
"intermediateOperations": [{
"metaDataOperationClass": "logic.adapter.HttpAdapter.model.MapStringToJsonOperation",
"operationParams": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.SimpleHttpAction",
"params": {
"variables": {
"id": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.ExtractSubStringAction",
"extract": {
"path": "/_links/self/href",
"valueType": "STRING"
},
"subString": {
"from": {
"str": "/",
"location": "LAST",
"index": null
},
"to": null
}
}
}},
"id": "getLocationDetails",
"httpMethod": "GET",
"path": "locations/$id",
"queryParams": null,
"headers": [],
"content": null
}
}
}
},
{
"metaDataOperationClass": "logic.adapter.HttpAdapter.model.MapJsonToJsonOperation",
"operationParams": {
"action": {
"metaDataActionClass": "logic.adapter.action.JsonPatchAction",
"params": {
"variables": {
"mdeKey": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.ExtractSubStringAction",
"extract": {
"path": "/_embedded/assets/0/_links/self/href",
"valueType": "STRING"
},
"subString": {
"from": {
"str": "/",
"location": "LAST",
"index": null
},
"to": null
}
}
}
},
"fileInput": null,
"filePatch": "trafficLaneJsonPatch.json"
}
}
}
}],
"terminateOperation": null
}
}]
},
"onError": null
}
}, {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.SimpleHttpAction",
"params": {
"id": "getLocationDetails",
"httpMethod": "GET",
"path": "locations/$id",
"queryParams": [],
"headers": [],
"content": null
}
},
"onResponse": {
"onSuccess": {
"actionsInput": "CONTENT",
"actions": []
},
"onError": {
"actionsInput": "CONTENT",
"actions": []
}
}
},
{
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.SimpleHttpAction",
"params": {
"id": "subscribe",
"httpMethod": "GET",
"path": "assets/$mdeKey/live-events",
"queryParams": [
{
"name": "event-types",
"value": "TFEVT"
}
},
],
"headers": [],
"content": null
}
},
"onResponse": {
"onSuccess": {
"actionsInput": "CONTENT",
"actions": [
{
"metaDataActionClass": "logic.adapter.HttpAdapter.action.WebSocketAction",
"params": {
"headers":[{
"name": "predix-zone-id",
"value": "b6fc22b6-ad71-423e-867b-a1b197f6cfc2"
}]
"variables": {
"webSocket": {
"action": {
"metaDataActionClass": "logic.adapter.HttpAdapter.action.ExtractSubStringAction",
"extract": {
"path": "/url",
"valueType": "STRING"
},
"subString": {
"from": null,
"to": null
}
}
}
},
"headers": [
{
"name": "predix-zone-id",
"value": "c54e3e63-8dc6-425e-a533-64e061f64023"
}
],
"webSocket": "$webSocket",
"mdeKey": "$mdeKey",
"uid": "$uid"
}
}]
}
]
},
"onError": {
"actionsInput": "CONTENT",
......@@ -64,5 +204,6 @@
}
}
}
]
]
}
\ No newline at end of file
{
"apiList": [
{
"apiIn": "spots",
"apiIn": { "name": "spots", "paramsTypes": null},
"method": "GET",
"actions": [{
"adapterId": "adapter.ge.parking",
......@@ -9,7 +9,7 @@
}]
},
{
"apiIn": "resources/devices/$id",
"apiIn": {"name": "resources/devices/$id", "paramsTypes": ["DIGITS"]},
"method": "GET",
"actions": [{
"adapterId": "adapter.ge.parking",
......@@ -17,7 +17,7 @@
}]
},
{
"apiIn": "subscribe/$mde-id/$uid",
"apiIn": {"name": "subscribe/$mdeKey/$uid", "paramsTypes": ["DIGITS","NO_CHECK"]},
"method": "POST",
"actions": [{
"adapterId": "adapter.ge.parking",
......
{
"apiList": [
{
"apiIn": "subscribe/$mde-id/$uid",
"apiIn": {"name": "subscribe/$mdeKey/$uid", "paramsTypes": ["DIGITS","NO_CHECK"]},
"method": "POST",
"actions": [{
"adapterId": "adapter.ge.traffic",
"apiOut": "subscribe"
}]
},
{
"apiIn": { "name": "traffic-lanes", "paramsTypes": null},
"method": "GET",
"actions": [{
"adapterId": "adapter.ge.traffic",
"apiOut": "GetAllTrafficLanes"
}]
}
]
}
[
{ "op": "remove", "path": "/city"},
{ "op": "remove", "path": "/state"},
{ "op": "remove", "path": "/country"},
{ "op": "remove", "path": "/zipcode"},
{ "op": "remove", "path": "/_links"},
{ "op": "remove", "path": "/location-type"},
{ "op": "remove", "path": "/address"},
{ "op": "remove", "path": "/_embedded"},
{ "op": "remove", "path": "/analytic-category"},
{ "op": "add", "path": "/properties", "value": { "vehicleType": null, "measures": null, "timestamp": 0, "mde-key": "$mdeKey"}}
]
\ No newline at end of file
......@@ -9,4 +9,6 @@ mde:
- "50040:50040"
extra_hosts:
- "transportation:172.16.1.151"
- "parking:172.16.1.244"
\ No newline at end of file
- "parking:172.16.1.56"
# volumes:
# - "/opt/mcz/user_images:/opt/mcz/user_images"
\ No newline at end of file
......@@ -3,13 +3,28 @@ package defs;
import com.fasterxml.jackson.databind.JsonNode;
import util.Utils;
import java.util.regex.Pattern;
/**
* Created by eli on 6/26/16.
*/
public class Constants {
public static final String ADAPTERS_PATH = "adapters.json";
public static final String SERVICES_PATH = "services.json";
public static final String CONFIG_LOCATION = "/opt/mcx/config/";
public final static String ADAPTERS_PATH = "adapters.json";
public final static String SERVICES_PATH = "services.json";
public final static String CONFIG_LOCATION = "/opt/mcx/config/";
private final static String regexQueryParamValue = "^\\$[a-zA-Z]{1,15}\\.[a-zA-Z]{1,15}$";
public final static Pattern patternFullMatchValue = Pattern.compile(regexQueryParamValue);
private final static String regexPathParamValue = "^\\$[a-zA-Z]{1,15}\\.[a-zA-Z]{1,15}$";
public final static Pattern patternPathParamValue = Pattern.compile(regexPathParamValue);
private final static String regexPathKeyWord= "^\\$[a-zA-Z0-9]{1,15}\\.[a-zA-Z]{1,15}$";
public final static Pattern patternPathKeyWord = Pattern.compile(regexPathKeyWord);
private final static String regex = "\\$[a-zA-Z0-9]{1,15}";
public final static Pattern compiledRegEx = Pattern.compile(regex);
private final static String regexWord = "^\\$[a-zA-Z0-9]{1,15}$";
public final static Pattern compiledRegExWord = Pattern.compile(regexWord);
private final static String regexDigits = "^[0-9]{1,15}$";
public final static Pattern compiledRegexDigits = Pattern.compile(regexDigits);
}
package defs;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.regex.Pattern;
import static defs.Constants.compiledRegexDigits;
/**
* Created by eli on 7/5/16.
*/
......@@ -32,6 +40,45 @@ public class Enums {
}
public enum ePreDefinedRegexTypes{
STRING_EQUALS("NORMAL",null),
REGEX_NO_CHECK("NO_CHECK",null),
REGEX_DIGITS("DIGITS",compiledRegexDigits);
private final String name;
private final Pattern rexEx;
public Pattern getPattern() {
return rexEx;
}
private ePreDefinedRegexTypes(String name,Pattern rexEx) {
this.name = name;
this.rexEx=rexEx;
}
@JsonValue
public String toString() {
return name;
}
@JsonCreator
public static ePreDefinedRegexTypes forValue(String name){
ePreDefinedRegexTypes[] types = ePreDefinedRegexTypes.values();
for (ePreDefinedRegexTypes type : types)
{
if (type.toString().equals(name))
return type;
}
return null;
}
}
public enum eKeyWord{
QUERY("query"),
HEADER("header");
......@@ -58,4 +105,40 @@ public class Enums {
}
}
public enum eSubStringLocation{
@JsonProperty("FIRST")
FIRST("FIRST"),
@JsonProperty("LAST")
LAST("LAST"),
@JsonProperty("XXX_th")
XXX_th("XXX_th"),
@JsonProperty("INDEX")
INDEX("INDEX");
private final String name;
private eSubStringLocation(String name) {
this.name = name;
}
public String getName() {
return name;
}
@JsonCreator
public static eSubStringLocation resolveName(String name){
eSubStringLocation[] keys = eSubStringLocation.values();
for (eSubStringLocation eName : keys)
{
if (eName.getName().equals(name))
return eName;
}
return null;
}
}
}
package defs;
/**
* Created by eli on 12/14/16.
*/
public class KeyIndexParam {
private String key;
private int index;
public KeyIndexParam(String key, int index) {
this.key = key;
this.index = index;
}
public String getKey() {
return key;
}
public int getIndex() {
return index;
}
}
......@@ -34,14 +34,28 @@ public class MdeHandler extends BaseHandler {
@Override
public void init() {
this.mdeManager = new MdeManager(logger);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
this.mdeManager = new MdeManager(logger);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
this.rcc = new RedisCacheClient(this.getConfigValueAsString("redis.host","localhost"));
}
@Override
public void doCreate(RequestContext requestContext) {
JsonNode content = (JsonNode)readObjectFromRequest(requestContext,JsonNode.class);
BaseRestResponse brr = mdeManager.doCreate(requestContext,content);
BaseRestResponse brr;
brr = validityCheck(requestContext);
if (brr.success) {
brr = mdeManager.doCreate(requestContext, content);
}
writeObjectToResponse(requestContext, brr);
}
......@@ -51,27 +65,43 @@ public class MdeHandler extends BaseHandler {
// GET ../mde/{tenantId}/{serviceId}/{apiId}
// example: GET ../mde/chicago/transportation/routes?key=gT2nciTKwRv6Jy5njqm8fe7LW
//change to!!!!!: // example: GET ../mde/chicago.transportation/routes?key=gT2nciTKwRv6Jy5njqm8fe7LW
BaseRestResponse brr = mdeManager.doRead(requestContext);
BaseRestResponse brr;
brr = validityCheck(requestContext);
if (brr.success) {
brr = mdeManager.doRead(requestContext);
}
writeObjectToResponse(requestContext, brr);
}
@Override
public void doUpdate(RequestContext requestContext) {
BaseRestResponse brr = mdeManager.doUpdate(requestContext);
BaseRestResponse brr;
brr = validityCheck(requestContext);
if (brr.success) {
brr = mdeManager.doUpdate(requestContext);
}
writeObjectToResponse(requestContext, brr);
}
@Override
public void doDelete(RequestContext requestContext) {
BaseRestResponse brr = mdeManager.doDelete(requestContext);
BaseRestResponse brr;
brr = validityCheck(requestContext);
if (brr.success) {
brr = mdeManager.doDelete(requestContext);
}
writeObjectToResponse(requestContext, brr);
}
private SimpleRestResponse errorResponse(String error) {
private BaseRestResponse validityCheck(RequestContext requestContext) {
String[] params=requestContext.params;
if (params.length>=3)
return new BaseRestResponse(true,null);
else{
return new BaseRestResponse(false,"missing url parameters. after base url at least "+params.length+ " parameters must be populated");
}
SimpleRestResponse resp = new SimpleRestResponse();
resp.error = error;
return resp;
}
}
......@@ -57,25 +57,7 @@ public class HttpAdapter extends BaseAdapter<HttpFlow, RequestParams, SimpleHttp
httpClient = new SimpleHttpClient();
httpClient.Initialize(100);
List<NameValueParam> headers= new ArrayList<>();
NameValueParam header = new NameValueParam();
if (this.adapterId.equals("adapter.ge.parking")) {
//parking
header.setName("predix-zone-id");
header.setValue("c54e3e63-8dc6-425e-a533-64e061f64023");
headers.add(header);
}
//traffic
else if (this.adapterId.equals("adapter.ge.traffic")){
header.setName("predix-zone-id");
header.setValue("b6fc22b6-ad71-423e-867b-a1b197f6cfc2");
headers.add(header);
}
this.webSocketManager = new WebSocketManager(authClient,headers,adapterId);
this.webSocketManager = new WebSocketManager(authClient,config.getConfigHttpRequestParams().getHeaders(),adapterId);
this.setModelReferences();
......@@ -89,6 +71,7 @@ public class HttpAdapter extends BaseAdapter<HttpFlow, RequestParams, SimpleHttp
HttpAdapterConfig config = (HttpAdapterConfig) getModel().getConfig();
OnHttpResponse onHttpResponse;
SimpleHttpAction httpAction;
List<BaseAction> actions;
// ActionsList actionsListOnSuccess, actionsListOnError;
HttpContentActions actionsListOnSuccess, actionsListOnError;
......@@ -102,30 +85,30 @@ public class HttpAdapter extends BaseAdapter<HttpFlow, RequestParams, SimpleHttp
onHttpResponse = (OnHttpResponse) httpFlow.getOnResponse();
if (onHttpResponse != null) {
actionsListOnSuccess = onHttpResponse.getOnSuccess();
List<BaseAction> actions = actionsListOnSuccess.getActions();
for (BaseAction action :
actions) {
if (myTypeOf(action).equals("WebSocketAction")) {
httpFlow.addWebSocketAction((WebSocketAction) action);
((WebSocketAction)action).setWebSocetManager(webSocketManager);
}
else if (myTypeOf(action).equals("SimpleHttpAction")) {
action.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
httpFlow.addHttpAction((SimpleHttpAction) action);
}
else if (myTypeOf(action).equals("JsonConvertAction")) {
List<IntermediateOperation> interOperations = ((JsonConvertAction) action).getParams().getIntermediateOperations();
for (IntermediateOperation operation :
interOperations) {
if (myTypeOf(operation.getOperationParams()).contains("Map")) {
BaseAction action1 = ((MapOperationParams) operation.getOperationParams()).getAction();
if (myTypeOf(action1).equals("SimpleHttpAction")) {
httpFlow.addHttpAction((SimpleHttpAction) action1);
action1.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
if (actionsListOnSuccess!=null) {
actions = actionsListOnSuccess.getActions();
for (BaseAction action :
actions) {
if (myTypeOf(action).equals("WebSocketAction")) {
httpFlow.addWebSocketAction((WebSocketAction) action);
((WebSocketAction) action).setWebSocetManager(webSocketManager);
} else if (myTypeOf(action).equals("SimpleHttpAction")) {
action.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
httpFlow.addHttpAction((SimpleHttpAction) action);
} else if (myTypeOf(action).equals("JsonConvertAction")) {
List<IntermediateOperation> interOperations = ((JsonConvertAction) action).getParams().getIntermediateOperations();
for (IntermediateOperation operation :
interOperations) {
if (myTypeOf(operation).contains("Map")) {
BaseAction action1 = ((MapOperationParams) operation.getOperationParams()).getAction();
if (myTypeOf(action1).equals("SimpleHttpAction")) {
httpFlow.addHttpAction((SimpleHttpAction) action1);
action1.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
}
}
}
}
......@@ -133,30 +116,31 @@ public class HttpAdapter extends BaseAdapter<HttpFlow, RequestParams, SimpleHttp
}
actionsListOnError = onHttpResponse.getOnError();
actions = actionsListOnError.getActions();
for (BaseAction act : actions) {
if (myTypeOf(act).equals("WebSocketAction")) {
httpFlow.addWebSocketAction((WebSocketAction) act);
((WebSocketAction)act).setWebSocetManager(webSocketManager);
}
if (myTypeOf(act).equals("SimpleHttpAction")) {
httpFlow.addHttpAction((SimpleHttpAction) act);
act.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
}
else if (myTypeOf(act).equals("JsonConvertAction")) {
List<IntermediateOperation> interOperations = ((JsonConvertAction) act).getParams().getIntermediateOperations();
for (IntermediateOperation operation :
interOperations) {
if (myTypeOf(operation.getOperationParams()).contains("Map")) {
BaseAction action1 = ((MapOperationParams) operation.getOperationParams()).getAction();
if (myTypeOf(action1).equals("SimpleHttpAction")) {
httpFlow.addHttpAction((SimpleHttpAction) action1);
action1.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
if (actionsListOnError != null) {
actions = actionsListOnError.getActions();
for (BaseAction act : actions) {
if (myTypeOf(act).equals("WebSocketAction")) {
httpFlow.addWebSocketAction((WebSocketAction) act);
((WebSocketAction) act).setWebSocetManager(webSocketManager);
}
if (myTypeOf(act).equals("SimpleHttpAction")) {
httpFlow.addHttpAction((SimpleHttpAction) act);
act.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
} else if (myTypeOf(act).equals("JsonConvertAction")) {
List<IntermediateOperation> interOperations = ((JsonConvertAction) act).getParams().getIntermediateOperations();
for (IntermediateOperation operation :
interOperations) {
if (myTypeOf(operation).contains("Map")) {
BaseAction action1 = ((MapOperationParams) operation.getOperationParams()).getAction();
if (myTypeOf(action1).equals("SimpleHttpAction")) {
httpFlow.addHttpAction((SimpleHttpAction) action1);
action1.setAdapterReferences(config.getConfigHttpRequestParams(),
httpClient,
authClient);
}
}
}
}
......@@ -205,6 +189,7 @@ public class HttpAdapter extends BaseAdapter<HttpFlow, RequestParams, SimpleHttp
HttpFlow flow = this.getModel().getFlow(flowId);
if (flow!=null){
//set run time RequestParams to all action of types SimpleHttpAction and WebSocketAction
flow.setRunTimeHttpRequest(input);
try {
resp = flow.execute(input);
......
package logic.adapter.HttpAdapter;
import logic.adapter.HttpAdapter.model.NameValueParam;
import microservice.defs.Enums;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Map;
......@@ -7,6 +10,17 @@ import java.util.Map;
* Created by eli on 11/29/16.
*/
public class RequestParams {
private String[] params = null;
private Map<String, String> variablesValues =null;
private Map<String, Deque<String>> queryParameters = null;
private Enums.EnumCrudMethod enumCrudMethod;
private Map<String, String> headersMap = null;
private String content;
public String[] getParams() {
return params;
}
......@@ -40,11 +54,13 @@ public class RequestParams {
this.content = content;
}
private String[] params = null;
private Map<String, Deque<String>> queryParameters = null;
private Enums.EnumCrudMethod enumCrudMethod;
private Map<String, String> headersMap = null;
private String content;
public Map<String, String> getVariablesValues() {
return variablesValues;
}
public void setVariablesValues(Map<String, String> variablesValues) {
this.variablesValues = variablesValues;
}
public RequestParams() {}
public String getQueryParameter(String paramName) {
......
package logic.adapter.HttpAdapter.action;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import logic.adapter.action.BaseAction;
import logic.adapter.action.ExtractValueAction;
import logic.adapter.action.SubStringAction;
import logic.adapter.model.ExtractValueActionParams;
import logic.adapter.model.SubStringActionParams;
import java.util.function.Function;
/**
* Created by eli on 12/18/16.
*/
public class ExtractSubStringAction implements Function<JsonNode,String>{
private ExtractValueAction extractValueAction;
private SubStringAction subStringAction;
@JsonCreator
public ExtractSubStringAction(@JsonProperty("extract") ExtractValueActionParams extractValueActionParams,
@JsonProperty("subString") SubStringActionParams subStringActionParams) {
this.extractValueAction = new ExtractValueAction(extractValueActionParams);
this.subStringAction = new SubStringAction(subStringActionParams);
}
/**
* Applies this function to the given argument.
*
* @param jsonNode the function argument
* @return the function result
*/
@Override
public String apply(JsonNode jsonNode) {
JsonNode retNode;
String retStr=null;
try {
retNode = extractValueAction.apply(jsonNode);
retStr = subStringAction.apply(retNode);
} catch (Exception e) {
e.printStackTrace();
}
return retStr;
}
}
......@@ -3,16 +3,12 @@ package logic.adapter.HttpAdapter.action;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import common.JsonHandler;
import http.simpleHttpClient.SimpleHttpRequest;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.adapter.HttpAdapter.HttpAdapter;
import logic.adapter.HttpAdapter.RequestParams;
import logic.adapter.action.ActionsList;
import logic.adapter.action.BaseAction;
import util.Utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
......@@ -99,21 +95,24 @@ public class HttpContentActions {//extends ActionsList<SimpleHttpResponse> {
}
public void setRunTimeHttpRequest(RequestParams inRequestParams) {
this.runTimeHttpRequest = inRequestParams;
}
private RequestParams runTimeHttpRequest;
// public void setRunTimeHttpRequest(RequestParams inRequestParams) {
// this.runTimeHttpRequest = inRequestParams;
// }
//
// private RequestParams runTimeHttpRequest;
// @Override
public SimpleHttpResponse executeActions(SimpleHttpResponse input) throws Exception {
String content = input.getContent();
JsonNode node = (JsonNode)Utils.readObjectFromString1(content, JsonNode.class);
List<BaseAction> actions=getActions();
SimpleHttpResponse resp;
for (BaseAction action : actions)
{
if (action.getType().equals(SimpleHttpAction.TYPE)) {
SimpleHttpResponse resp = (SimpleHttpResponse) action.apply(runTimeHttpRequest);
//SimpleHttpResponse resp = (SimpleHttpResponse) action.apply(runTimeHttpRequest);
((SimpleHttpAction)action).computeVariables(node);
resp = (SimpleHttpResponse) action.apply(null);
if (resp.getStatusCode()!= 200)
{
return new SimpleHttpResponse(500,"failed onSuccess.executeActions.httpAction with error:" +resp.getStatusCode() );
......@@ -123,10 +122,12 @@ public class HttpContentActions {//extends ActionsList<SimpleHttpResponse> {
}
//assumed that after extractValueAction
else if (HttpAdapter.myTypeOf(action).equals("WebSocketAction")){
Map<String,String > runTimeParams = new HashMap<>();
if (node!=null && node.isTextual()) runTimeParams.put("webSocket", node.asText());
action.setRunTimeParameters(runTimeParams);
SimpleHttpResponse resp = (SimpleHttpResponse) action.apply(runTimeHttpRequest);
// Map<String,String > runTimeParams = new HashMap<>();
// if (node!=null && node.isTextual()) runTimeParams.put("webSocket", node.asText());
// action.setRunTimeVariables(runTimeParams);
// SimpleHttpResponse resp = (SimpleHttpResponse) action.apply(runTimeHttpRequest);
((WebSocketAction)action).computeVariables(node);
resp = (SimpleHttpResponse) action.apply(null);
}
else //JsonNodeAction.class
......
......@@ -2,21 +2,16 @@ package logic.adapter.HttpAdapter.action;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import http.simpleHttpClient.SimpleHttpClient;
import com.fasterxml.jackson.databind.JsonNode;
import http.simpleHttpClient.SimpleHttpRequest;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.adapter.HttpAdapter.ErrorLoginException;
import logic.adapter.HttpAdapter.OAuth2Client;
import logic.adapter.HttpAdapter.RequestParams;
import logic.adapter.HttpAdapter.model.ConfigHttpRequestParams;
import logic.adapter.HttpAdapter.model.HttpRequestActionParams;
import logic.adapter.HttpAdapter.model.NameValueParam;
import logic.adapter.action.BaseAction;
import util.HttpRequestResolver;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.List;
/**
* Created by eli on 11/17/16.
......@@ -72,7 +67,6 @@ public class SimpleHttpAction extends BaseAction<HttpRequestActionParams ,Reques
RequestParams inRequestParams = (requestParams!=null)?requestParams:getRunTimeInput();
//if authentication not needed or token already exist
httpRequest = buildHttpRequest(inRequestParams);
try {
resp = httpClient.processRequest(httpRequest);
......@@ -100,16 +94,20 @@ public class SimpleHttpAction extends BaseAction<HttpRequestActionParams ,Reques
private SimpleHttpRequest buildHttpRequest(RequestParams inRequestParams) {
protected SimpleHttpRequest buildHttpRequest(RequestParams inRequestParams) {
SimpleHttpRequest request = new HttpRequestResolver().createResolvedRequest(inRequestParams,
adapterHttpParams,
getParams(),
((oauth2Client != null)?oauth2Client.getToken():null),
getRunTimeParameters());
getRunTimeVariables());
return request;
}
public void computeVariables(JsonNode node) throws Exception {
setRunTimeVariables(getParams().computeVariables(node));
}
}
......@@ -3,6 +3,7 @@ package logic.adapter.HttpAdapter.action;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.neovisionaries.ws.client.WebSocketException;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.adapter.HttpAdapter.ErrorLoginException;
......@@ -61,9 +62,8 @@ public class WebSocketAction extends BaseAction<WebSocketActionParams ,RequestPa
public SimpleHttpResponse apply(RequestParams requestParams) {
OnEventDetails details=null;
RequestParams inRequestParams = (requestParams!=null)?requestParams:getRunTimeInput();
String[] params = inRequestParams.getParams();
String mdeKey = params[3];//id
String uid = params[4];//uid
String mdeKey=null;
String uid=null;
String httpPayload = inRequestParams.getContent();
try {
details = (OnEventDetails) Utils.readObjectFromString1(httpPayload, OnEventDetails.class);
......@@ -72,7 +72,7 @@ public class WebSocketAction extends BaseAction<WebSocketActionParams ,RequestPa
return new SimpleHttpResponse(500, "Failed to read Request payload OnEventDetails");
}
Map<String, String> runTimeParameters = getRunTimeParameters();
Map<String, String> runTimeParameters = getRunTimeVariables();
String webSocket=null;
if (runTimeParameters.containsKey("webSocket")){
webSocket = runTimeParameters.get("webSocket");
......@@ -81,6 +81,9 @@ public class WebSocketAction extends BaseAction<WebSocketActionParams ,RequestPa
return new SimpleHttpResponse(500, "Failed to extract web socket url");
try {
mdeKey=getParams().getResolvedMdeKey(inRequestParams.getVariablesValues());
uid=getParams().getResolvedUid(inRequestParams.getVariablesValues());
webSocket=getParams().getResolvedWebSocket(getRunTimeVariables());
webSocketManager.connect(mdeKey,uid,webSocket,details);
} catch (UnsupportedEncodingException e) {
return new SimpleHttpResponse(500, "failed to connect to webSocket with error: "+e);
......@@ -107,18 +110,10 @@ public class WebSocketAction extends BaseAction<WebSocketActionParams ,RequestPa
this.webSocketManager = webSocetManager;
}
public void computeVariables(JsonNode node) throws Exception {
setRunTimeVariables(getParams().computeVariables(node));
}
// private SimpleHttpRequest buildHttpRequest(RequestParams inRequestParams) {
//
//
// SimpleHttpRequest request = new HttpRequestResolver().createResolvedRequest(inRequestParams,
// adapterHttpParams,
// getParams(),
// ((oauth2Client != null)?oauth2Client.getToken():null),
// getRunTimeParameters());
//
// return request;
// }
}
......
package logic.adapter.HttpAdapter.action;
import com.fasterxml.jackson.annotation.JsonProperty;
import logic.adapter.HttpAdapter.model.ComputeVariable;
import logic.adapter.HttpAdapter.model.NameValueParam;
import logic.adapter.model.BaseActionParams;
import logic.adapter.model.DynamicVariablesParams;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by eli on 12/4/16.
*/
public class WebSocketActionParams extends BaseActionParams{
public class WebSocketActionParams extends DynamicVariablesParams{
@JsonProperty("headers")
private List<NameValueParam> headers = new ArrayList<>();
private List<NameValueParam> headers;
@JsonProperty("webSocket")
private String webSocket;
@JsonProperty("mdeKey")
private String mdeKey;
@JsonProperty("uid")
private String uid;
// "webSocket": "$webSocket"
// "mdeKey": "$mdeKey",
// "uid": "$uid"
public WebSocketActionParams(@JsonProperty("variables") Map<String, ComputeVariable> mapVariableToValueComputation,
@JsonProperty("headers") List<NameValueParam> headers,
@JsonProperty("webSocket") String webSocket,
@JsonProperty("mdeKey") String mdeKey,
@JsonProperty("uid") String uid) {
super(mapVariableToValueComputation);
this.headers=headers;
this.webSocket=webSocket;
this.mdeKey=mdeKey;
this.uid=uid;
}
@Override
......@@ -26,4 +51,28 @@ public class WebSocketActionParams extends BaseActionParams{
public boolean isValid() {
return true;
}
public String getResolvedMdeKey(Map<String, String> variablesValues) {
return resolve(this.mdeKey,variablesValues);
}
private String resolve(String key, Map<String, String> variablesValues) {
String resolved=null;
String realKey=null;
if (key!=null && key.startsWith("$")){
realKey = key.substring(1);
resolved = variablesValues.get(realKey);
}
else if (key!=null)
resolved=key;
return resolved;
}
public String getResolvedUid(Map<String, String> variablesValues) {
return resolve(this.uid,variablesValues);
}
public String getResolvedWebSocket(Map<String, String> variablesValues) {
return resolve(this.webSocket,variablesValues);
}
}
package logic.adapter.HttpAdapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import logic.adapter.HttpAdapter.action.ExtractSubStringAction;
import logic.adapter.action.BaseAction;
import logic.adapter.action.ExtractValueAction;
import logic.adapter.action.SubStringAction;
import logic.adapter.model.BaseActionParams;
import java.util.List;
import static util.Utils.myTypeOf;
/**
* Created by eli on 12/11/16.
*/
public class ComputeVariable{
public ExtractSubStringAction getAction() {
return action;
}
@JsonProperty("action")
private ExtractSubStringAction action;
@JsonCreator
public ComputeVariable(@JsonProperty("action") ExtractSubStringAction action) {
this.action = action;
}
@JsonIgnore
private String actionRunTimeResult;
public String execute(JsonNode node) throws Exception {
return action.apply(node);
}
}
package logic.adapter.HttpAdapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
......@@ -27,6 +28,15 @@ public class ConfigHttpRequestParams implements ModelValidator {
@JsonProperty("headers")
private List<NameValueParam> headers = new ArrayList<>();
@JsonCreator
public ConfigHttpRequestParams(@JsonProperty("baseUrl") String baseUrl,
@JsonProperty("basePath") String basePath,
@JsonProperty("headers") ArrayList<NameValueParam> headers) {
this.baseUrl = baseUrl;
this.basePath = basePath;
this.headers = headers;
}
/**
*
......
......@@ -4,9 +4,11 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import logic.adapter.model.BaseActionParams;
import logic.adapter.model.DynamicVariablesParams;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by eli on 11/17/16.
......@@ -19,7 +21,7 @@ import java.util.List;
"headers",
"content"
})
public class HttpRequestActionParams extends BaseActionParams {
public class HttpRequestActionParams extends DynamicVariablesParams {
@JsonProperty("id")
private String id;
......@@ -34,7 +36,8 @@ public class HttpRequestActionParams extends BaseActionParams {
@JsonProperty("content")
private Object content;
public HttpRequestActionParams() {
public HttpRequestActionParams(@JsonProperty("variables") Map<String, ComputeVariable> variablesToCompute) {
super(variablesToCompute);
}
......
package logic.adapter.HttpAdapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import http.simpleHttpClient.SimpleHttpClient;
import logic.adapter.HttpAdapter.OAuth2Client;
import logic.adapter.action.BaseAction;
import java.util.HashMap;
import java.util.function.Function;
/**
......@@ -11,7 +15,8 @@ import java.util.function.Function;
public abstract class IntermediateOperation<TypeParams extends BaseOperationParams, TypeFunc>
extends Operation<TypeParams> {
public IntermediateOperation(TypeParams operationParams) {
public IntermediateOperation( TypeParams operationParams) {
super(operationParams);
this.func=buildFunc();
}
......@@ -27,6 +32,8 @@ public abstract class IntermediateOperation<TypeParams extends BaseOperationPara
OAuth2Client oAuth2Client){
getOperationParams().setAdapterReferences(configHttpRequestParams,httpClient,oAuth2Client );
}
private TypeFunc func;
......
package logic.adapter.HttpAdapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import logic.adapter.action.BaseAction;
import util.Utils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
......@@ -9,7 +18,12 @@ import java.util.stream.Stream;
public abstract class MapIntermediateOperation<TypeIn, TypeOut> extends IntermediateOperation<MapOperationParams, Function<TypeIn,TypeOut>>
{
public static final String TYPE = "MapIntermediateOperation";
public MapIntermediateOperation(MapOperationParams operationParams) {
@JsonCreator
public MapIntermediateOperation(@JsonProperty("operationParams") MapOperationParams operationParams)
{
super(operationParams);
}
@Override
......
......@@ -6,11 +6,14 @@ import com.fasterxml.jackson.databind.JsonNode;
import common.JsonHandler;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.adapter.HttpAdapter.action.SimpleHttpAction;
import logic.adapter.action.BaseAction;
import logic.adapter.action.JsonNodeAction;
import util.Utils;
import java.util.Map;
import java.util.function.Function;
import static util.Utils.myTypeOf;
/**
* Created by eli on 11/22/16.
*/
......@@ -25,19 +28,22 @@ public class MapJsonToJsonOperation extends MapIntermediateOperation<JsonNode, J
protected Function<JsonNode, JsonNode> buildFunc() {
Function<JsonNode,JsonNode> ret = (node) -> {
SimpleHttpResponse resp;
String content;
try {
int end_index = getOperationParams().getAction().toString().indexOf('@');
String type=getOperationParams().getAction().toString().substring(0,end_index);
int startIndex = type.lastIndexOf(".");
startIndex++;
type = type.substring(startIndex,end_index);
String type=myTypeOf(getOperationParams().getAction());
if (type.equals("SimpleHttpAction")) {
SimpleHttpAction httpAction = (SimpleHttpAction)getOperationParams().getAction();
//assumed that the action holds its input already, and use it
resp = httpAction.apply(null);
httpAction.computeVariables(node);
resp = ((SimpleHttpAction)httpAction).apply(null);
if (resp.getStatusCode()!=200)
throw new Exception("MapJsonToJsonOperation: http action failed with status code: "+resp.getStatusCode()+" errorMsg: "+ resp.getContent() );
return JsonHandler.getJsonNodeFromObject(resp.getContent());
else{
content=resp.getContent();
System.out.println("MapJsonToJsonOperation params="+ getOperationParams().toString()+" convert node= "+node.toString()+" to convertedNode= "+content);
return JsonHandler.getJsonNodeFromObject(content);
}
}
//assumed JsonNodeAction.class
//else if(getOperationParams().getAction().getClass().isInstance(JsonNodeAction.class)) {
......
......@@ -4,11 +4,11 @@ package logic.adapter.HttpAdapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import common.JsonHandler;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.adapter.HttpAdapter.action.SimpleHttpAction;
import logic.adapter.action.JsonNodeAction;
import java.util.Map;
import java.util.function.Function;
/**
......@@ -18,7 +18,7 @@ import java.util.function.Function;
public class MapJsonToStringOperation extends MapIntermediateOperation<JsonNode, JsonNode> {
@JsonCreator
public MapJsonToStringOperation(@JsonProperty("operationParams") MapOperationParams operationParams) {
public MapJsonToStringOperation(@JsonProperty("operationParams") MapOperationParams operationParams){
super(operationParams);
}
......@@ -26,12 +26,15 @@ public class MapJsonToStringOperation extends MapIntermediateOperation<JsonNode
protected Function<JsonNode, JsonNode> buildFunc() {
Function<JsonNode,JsonNode> ret = (node) -> {
SimpleHttpResponse resp;
JsonNode retNode;
try {
//in this case assumed that the action get and return JsonNode!!!!! no else section
if(!getOperationParams().getAction().getClass().isInstance(SimpleHttpAction.class)) {
JsonNodeAction JsonAction = (JsonNodeAction)getOperationParams().getAction();
JsonNode transformedNode = (JsonNode)JsonAction.apply(node);
return transformedNode;
retNode = (JsonNode)JsonAction.apply(node);
System.out.println("MapJsonToStringOperation ,params="+ getOperationParams().toString()+"convert from node= [" +node.toString()+"] to convertedNode= ["+ retNode.toString()+"]");
return retNode;
}
} catch (Exception e) {
e.printStackTrace();
......
......@@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.*;
import http.simpleHttpClient.SimpleHttpClient;
import logic.adapter.HttpAdapter.OAuth2Client;
import logic.adapter.action.BaseAction;
import logic.adapter.model.BaseActionParams;
import microservice.params.CommandParamsBuilder;
import java.util.HashMap;
import java.util.Map;
......@@ -22,20 +22,26 @@ public class MapOperationParams extends BaseOperationParams{
public BaseAction getAction() {
return action;
}
private BaseAction action;
private BaseAction action;
@JsonIgnore
private Map<String, String> additionalProperties = new HashMap<String, String>();
@JsonAnyGetter
public Map<String, String> getAdditionalProperties() {
return this.additionalProperties;
public String toString(){
String str="action="+action.toString();
return str;
}
@JsonAnySetter
public void setAdditionalProperty(String name, String value) {
this.additionalProperties.put(name, value);
}
// @JsonIgnore
// private Map<String, String> additionalProperties = new HashMap<String, String>();
// @JsonAnyGetter
// public Map<String, String> getAdditionalProperties() {
// return this.additionalProperties;
// }
//
// @JsonAnySetter
// public void setAdditionalProperty(String name, String value) {
// this.additionalProperties.put(name, value);
// }
......
......@@ -6,9 +6,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import common.JsonHandler;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.adapter.HttpAdapter.action.SimpleHttpAction;
import logic.adapter.action.JsonNodeAction;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
......@@ -18,38 +16,30 @@ import java.util.function.Function;
public class MapStringToJsonOperation extends MapIntermediateOperation<JsonNode, JsonNode> {
@JsonCreator
public MapStringToJsonOperation(@JsonProperty("operationParams") MapOperationParams operationParams) {
public MapStringToJsonOperation(@JsonProperty("operationParams") MapOperationParams operationParams){
super(operationParams);
}
@Override
protected Function<JsonNode, JsonNode> buildFunc() {
Function<JsonNode,JsonNode> ret = (str) -> {
Function<JsonNode,JsonNode> ret = (node) -> {
SimpleHttpResponse resp;
String last;
String content;
try {
//currently support only httpAction
if (getOperationParams().getAction().getType().equals(SimpleHttpAction.TYPE)) {
SimpleHttpAction httpAction = (SimpleHttpAction)getOperationParams().getAction();
Map<String,String> parameters = getOperationParams().getAdditionalProperties();
Map<String,String> convertedParameters = new HashMap<>();
for (Map.Entry<String,String> parameter:
parameters.entrySet()) {
if (parameter.getValue().equals("lastToken")) {
String str1 = str.asText();
last = str1.substring(str1.lastIndexOf('/') + 1);
convertedParameters.put(parameter.getKey(), last);
}
else
convertedParameters.put(parameter.getKey(), parameter.getValue());
}
httpAction.setRunTimeParameters(convertedParameters);
//assumed that the action holds its input already, and use it
httpAction.computeVariables(node);
resp = httpAction.apply(null);
if (resp.getStatusCode()!=200)
throw new Exception("MapJsonToJsonOperation: http action failed with status code: "+resp.getStatusCode()+" errorMsg: "+ resp.getContent() );
content=resp.getContent();
System.out.println("MapStringToJsonOperation params="+ getOperationParams().toString()+" convert node= "+node.toString()+" to convertedNode= "+content.toString());
return JsonHandler.getJsonNodeFromString(resp.getContent());
}
......@@ -63,4 +53,6 @@ public class MapStringToJsonOperation extends MapIntermediateOperation<JsonNode,
}
}
......@@ -3,11 +3,21 @@ package logic.adapter.HttpAdapter.model;
/**
* Created by eli on 6/27/16.
*/
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
public class NameValueParam {
private String name;
private String value;
@JsonCreator
public NameValueParam(@JsonProperty("name") String name,
@JsonProperty("value") String value) {
this.name = name;
this.value = value;
}
@JsonIgnore
public String toString(){
return new String(name+"="+value);
......
package logic.adapter.HttpAdapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import logic.adapter.action.BaseAction;
import logic.adapter.action.StringAction;
import java.util.HashMap;
/**
* Created by eli on 11/22/16.
*/
@JsonTypeInfo(use= JsonTypeInfo.Id.CLASS, include= JsonTypeInfo.As.PROPERTY, property="metaDataOperationClass")
public abstract class Operation<T extends BaseOperationParams> {
public Operation(T operationParams) {
public Operation(@JsonProperty("operationParams") T operationParams) {
this.operationParams = operationParams;
}
......@@ -17,5 +24,4 @@ public abstract class Operation<T extends BaseOperationParams> {
private T operationParams;
}
......@@ -2,6 +2,7 @@ package logic.adapter.action;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.JsonNode;
import http.simpleHttpClient.SimpleHttpClient;
import logic.adapter.HttpAdapter.OAuth2Client;
import logic.adapter.HttpAdapter.model.ConfigHttpRequestParams;
......@@ -9,7 +10,6 @@ import logic.adapter.model.BaseActionParams;
import logic.adapter.model.ModelValidator;
import java.util.Map;
import java.util.function.Function;
/**
* Created by eli on 11/17/16.
......@@ -20,11 +20,11 @@ public abstract class BaseAction<T extends BaseActionParams, TypeIn, TypeOut> im
@JsonProperty
T params;
public Map<String, String> getRunTimeParameters() {
return runTimeParameters;
public Map<String, String> getRunTimeVariables() {
return runTimeVariables;
}
private Map<String, String> runTimeParameters;
private Map<String, String> runTimeVariables;
public BaseAction(T params) {
this.params = params;
......@@ -46,10 +46,10 @@ public abstract class BaseAction<T extends BaseActionParams, TypeIn, TypeOut> im
}
abstract public String getType();
public abstract void build();
public abstract void build() throws Exception;
public void setRunTimeParameters(Map<String, String> convertedParameters) {
this.runTimeParameters = convertedParameters;
public void setRunTimeVariables(Map<String, String> convertedParameters) {
this.runTimeVariables = convertedParameters;
}
......@@ -77,4 +77,7 @@ public abstract class BaseAction<T extends BaseActionParams, TypeIn, TypeOut> im
this.httpClient = httpClient;
this.oauth2Client = oauth2Client;
}
}
......@@ -33,6 +33,9 @@ public class ExtractValueAction extends JsonNodeAction<ExtractValueActionParams>
public JsonNode apply(JsonNode jsonNode) throws Exception {
Enums.eNodeType eType = getParams().getValueType();
JsonNode transformedNode = jsonNode.at(pathPointer);
if (transformedNode.isMissingNode() )
System.out.println("ExtractValueAction didn't match "+pathPointer.toString()+ "for node: "+ jsonNode.toString());
switch (eType){
case ARRAY_NODE:
if (!transformedNode.isArray())
......
......@@ -3,7 +3,6 @@ package logic.adapter.action;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import logic.adapter.HttpAdapter.model.*;
import logic.adapter.model.JsonConvertActionParams;
import logic.adapter.model.TerminateOperation;
......@@ -12,10 +11,11 @@ import util.ArrayNodeCollector;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static util.Utils.myTypeOf;
/**
* Created by eli on 11/21/16.
......@@ -60,12 +60,7 @@ public class JsonConvertAction extends JsonNodeAction<JsonConvertActionParams>
List<IntermediateOperation> operations = params.getIntermediateOperations();
for (IntermediateOperation operation : operations) {
int end_index = operation.toString().indexOf('@');
String type=operation.toString().substring(0,end_index);
int startIndex = type.lastIndexOf(".");
startIndex++;
type = type.substring(startIndex,end_index);
String type=myTypeOf(operation);
if (type.equals("MapJsonToJsonOperation")){
Function<JsonNode,JsonNode> func = ((MapJsonToJsonOperation)operation).getFunc();
streamOfJsonNodes=streamOfJsonNodes.map(func);
......
......@@ -2,27 +2,37 @@ package logic.adapter.action;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
import com.flipkart.zjsonpatch.JsonPatch;
import logic.adapter.model.JsonPatchActionParams;
import util.Utils;
import util.zjsonpatch.ZJsonPatch;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import static defs.Constants.CONFIG_LOCATION;
import static defs.Constants.compiledRegEx;
/**
* Created by eli on 12/1/16.
*/
public class JsonPatchAction extends JsonNodeAction<JsonPatchActionParams>{
//***DEMO***/
private JsonNode jsonPatch;
private String strJsonPatch;
//this map holds for each key(i.e $id) its (start,end) indexes
//in order to be replaced in run time more effectively
private List<KeyPointer> variablesLocations = new ArrayList<>();
//***DEMO***/
@JsonCreator
public JsonPatchAction(@JsonProperty("params") JsonPatchActionParams params) {
super(params);
try {
this.build();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
......@@ -31,61 +41,90 @@ public class JsonPatchAction extends JsonNodeAction<JsonPatchActionParams>{
}
@Override
public void build() {
public void build() throws Exception {
String jsonPatchfile = getParams().getFileJsonPatch();
try {
jsonPatch = Utils.readJsonNodeFromFile(CONFIG_LOCATION + jsonPatchfile);
strJsonPatch = jsonPatch.toString();
// String result=target;
Matcher matcher = compiledRegEx.matcher(strJsonPatch);
int start, end;
String key;
while (matcher.find()) {
start = matcher.start();
end = matcher.end();
//if matched not last portion of the string
key= strJsonPatch.substring(start+1,end);
KeyPointer strIndexes = new KeyPointer(key,start,end);
variablesLocations.add(strIndexes);
}
//by now strJsonPatch holds the String of JsonPatch, and variablesLocations holds the list of
//key->locations the can be run on run time at o(n) and replaced with the real time values
}
catch(Exception e){
throw new Exception("failed to build JsonPathAction: error reading file: "+ ((jsonPatchfile!=null)?jsonPatchfile:"null")+" Exception: "+e);
}
}
@Override
public JsonNode apply(JsonNode jsonNode) throws Exception {
JsonNode jsonInput;
JsonPatchActionParams params = getParams();
String JsonPatchFile = params.getFileJsonPatch();
JsonNode jsonPatch;
////if DEMO *******/
if (params.getFileJsonPatch().equals("parkingSpotJsonPatch.json") ){
JsonPointer demo = JsonPointer.compile("/_embedded/assets/0/_links/self/href");
JsonNode transformedNode = jsonNode.at(demo);
String str1 = transformedNode.asText();
String lastAssetIdToken = str1.substring(str1.lastIndexOf('/') + 1);
jsonPatch = Utils.readJsonNodeFromFile(CONFIG_LOCATION + JsonPatchFile);
////*******for DEMO start*******/
String json = jsonPatch.toString();
json = json.replaceFirst("\\$mdeKey", lastAssetIdToken);
jsonPatch = Utils.getJsonNodeFromString(json);
JsonNode currentJsonPatch;
if (variablesLocations.size()>0){
String strTransformedJsonPatch = replaceKeysWithValues(jsonNode);
currentJsonPatch = Utils.getJsonNodeFromString(strTransformedJsonPatch);
}
//jsonPatch is static without dynamic variables and we can use it as is without replacements
else{
currentJsonPatch=jsonPatch;
}
else////not Demo
jsonPatch = Utils.readJsonNodeFromFile(CONFIG_LOCATION + JsonPatchFile);
if (params.getFileJsonInput() == null)
jsonInput=jsonNode;
else
jsonInput=Utils.readJsonNodeFromFile(CONFIG_LOCATION+JsonPatchFile);
if (jsonPatch!=null && !jsonPatch.isNull() && jsonInput!=null && !jsonInput.isNull()){
return JsonPatch.apply(jsonPatch, jsonInput);
if (currentJsonPatch!=null && !currentJsonPatch.isNull() && jsonNode!=null && !jsonNode.isNull()){
return ZJsonPatch.apply(currentJsonPatch, jsonNode);
}
else
return null;
}
private String replaceKeysWithValues(JsonNode jsonNode) throws Exception {
StringBuilder strBuilder = new StringBuilder();
String strKey=null;
// Map<String, String> runTimeParameters = getRunTimeVariables();
Map<String, String> runTimeParameters = getParams().computeVariables(jsonNode);
String subString;
int currentLocation=0;
for (KeyPointer key: variablesLocations){
strKey=key.getKey();
if (runTimeParameters.containsKey(strKey))
{
subString = strJsonPatch.substring(currentLocation,key.getStart());
strBuilder.append(subString);
strBuilder.append(runTimeParameters.get(strKey));
currentLocation=key.getEnd();
}
else
System.out.println("replacekeysWithValues run time error, missing key: "+ ((strKey!=null)? strKey: "null"));
}
//insert the last substring from last replacement to the end
if (currentLocation>0){
subString = strJsonPatch.substring(currentLocation);
strBuilder.append(subString);
}
return strBuilder.toString();
}
private JsonNode jsonPatchApply(String jsonPatchfile, String jsonInputfile ) throws IOException {
JsonNode jsonPatch = Utils.readJsonNodeFromFile(jsonPatchfile);
JsonNode jsonInput = Utils.readJsonNodeFromFile(jsonInputfile);
if (jsonPatch!=null && !jsonPatch.isNull() && jsonInput!=null && !jsonInput.isNull()){
return JsonPatch.apply(jsonPatch, jsonInput);
return ZJsonPatch.apply(jsonPatch, jsonInput);
}
return null;
}
......
package logic.adapter.action;
/**
* Created by eli on 12/12/16.
*/
public class KeyPointer {
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
private int start;
private int end;
public String getKey() {
return key;
}
private String key;
public KeyPointer(String key, int start, int end) {
this.start = start;
this.end = end;
this.key=key;
}
}
package logic.adapter.action;
import com.fasterxml.jackson.databind.JsonNode;
import logic.adapter.model.BaseActionParams;
/**
* Created by eli on 12/8/16.
*/
public abstract class StringAction<T extends BaseActionParams> extends BaseAction<T, JsonNode, String> {
public StringAction(T params) {
super(params);
}
}
package logic.adapter.action;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import defs.Enums;
import logic.adapter.model.SubStringActionParams;
import logic.adapter.model.WithinStringPointer;
/**
* Created by eli on 12/8/16.
*/
public class SubStringAction extends StringAction<SubStringActionParams> {
@JsonCreator
public SubStringAction(@JsonProperty("params") SubStringActionParams params) {
super(params);
}
@Override
public String getType() {
return null;
}
@Override
public void build() {
}
@Override
public String apply(JsonNode jsonNode) throws Exception {
String retStr;
SubStringActionParams params = getParams();
WithinStringPointer from = params.getFrom();
WithinStringPointer to = params.getTo();
if (jsonNode!=null && jsonNode.isMissingNode())
throw new Exception("SubStringAction expect none missing node input. [from: "
+((from!=null)?from.toString():"null")+"], [to="+((to!=null)?to.toString():"null")+"]");
if (!jsonNode.isTextual())
throw new Exception("SubStringAction expect textual JsonNode");
retStr=subStringOf(jsonNode.asText(), from, to);
if (retStr==null)
throw new Exception("SubStringAction failed, check your configuration");
return retStr;
}
private String subStringOf(String str, WithinStringPointer from, WithinStringPointer to) {
int fromIndex, toIndex;
String retString=null;
if (from != null) {
fromIndex = indexOf(str, from);
if (fromIndex != -1) {
retString = str.substring(fromIndex);
//if to==null return substring from "fromIndex" till end of the string
if (to != null)
{
toIndex = indexOf(str, to);
if (toIndex != -1)
retString = retString.substring(fromIndex, toIndex);
}
}
}
else
retString=str;
return retString;
}
//find the index of "pointer" in the string. in case that pointer include prefix to look for
//the returned index points to the index right after the given prefix
private int indexOf(String string,WithinStringPointer pointer) {
int index=-1;
if (pointer == null) return -1;
String token = pointer.getPrefix();
Enums.eSubStringLocation type = pointer.geteLocationType();
switch(type){
case FIRST:
index = string.indexOf(token);
break;
case LAST:
index = string.lastIndexOf(token);
break;
case XXX_th:
int count = pointer.getIndex();
index=0;
while (count>0){
index=string.indexOf(token,index);
if (index==-1)
break;
else
count--;
}
if (index==0) index--;
break;
case INDEX:
index=pointer.getIndex();
break;
}
if (type!= Enums.eSubStringLocation.INDEX&& index!=-1)
index+=token.length();
return index;
}
}
package logic.adapter.model;
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.annotation.JsonIgnore;
//import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.*;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.adapter.HttpAdapter.RequestParams;
import logic.adapter.HttpAdapter.action.OnHttpResponse;
import logic.adapter.HttpAdapter.action.SimpleHttpAction;
import logic.adapter.HttpAdapter.model.HttpFlow;
import logic.adapter.HttpAdapter.model.HttpRequestActionParams;
import logic.adapter.HttpAdapter.model.OnResponse;
import logic.adapter.action.BaseAction;
import java.util.ArrayList;
/**
* Created by eli on 11/16/16.
*/
//@JsonTypeInfo(
// use = JsonTypeInfo.Id.CLASS,
// include = JsonTypeInfo.As.PROPERTY,
// property = "metaDataClassFlow")
//@JsonSubTypes({
// @JsonSubTypes.Type(value = HttpFlow.class)
//})
//HttpRequestActionParams, RequestParams,SimpleHttpResponse
public abstract class BaseFlow implements ModelValidator{
@JsonProperty("action")
......@@ -93,6 +48,7 @@ public abstract class BaseFlow implements ModelValidator{
return null;
}
public SimpleHttpResponse execute(RequestParams input) throws Exception {
// action.getRunTimeVariables();
SimpleHttpResponse actionResp = action.apply(input);
try {
return onResponse.execute(actionResp);
......
package logic.adapter.model;
import com.fasterxml.jackson.databind.JsonNode;
import logic.adapter.HttpAdapter.model.ComputeVariable;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Created by eli on 12/15/16.
*/
public abstract class DynamicVariablesParams extends BaseActionParams{
private Map<String, ComputeVariable> mapVariableToValueComputation;
public DynamicVariablesParams(Map<String, ComputeVariable> mapVariableToValueComputation) {
this.mapVariableToValueComputation = mapVariableToValueComputation;
}
public Map<String, ComputeVariable> getMapVariableToValueComputation() {
return mapVariableToValueComputation;
}
public Map<String, String> computeVariables(JsonNode node) throws Exception {
HashMap<String, String> map = new HashMap<>();
for (Map.Entry<String,ComputeVariable> entry : mapVariableToValueComputation.entrySet()){
String str=entry.getValue().execute(node);
if (str!=null)
map.put(entry.getKey(),str);
}
return map;
}
}
package logic.adapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Created by eli on 12/18/16.
*/
public class ExtractSubStringParams extends BaseActionParams{
private ExtractValueActionParams extractParams;
private SubStringActionParams subStringParams;
@JsonCreator
public ExtractSubStringParams(@JsonProperty("extract") ExtractValueActionParams extractParams,
@JsonProperty("subString") SubStringActionParams subStringParams) {
this.extractParams = extractParams;
this.subStringParams = subStringParams;
}
@Override
public String getId() {
return null;
}
@Override
public boolean isValid() {
return false;
}
}
......@@ -31,8 +31,8 @@ public class JsonConvertActionParams extends BaseActionParams {
@JsonCreator
public JsonConvertActionParams(@JsonProperty("intermediateOperations") List<IntermediateOperation> intermediateOperations,
@JsonProperty("terminateOperation") TerminateOperation terminateOperation) {
this.terminateOperation = terminateOperation;
this.intermediateOperations = intermediateOperations;
this.terminateOperation = terminateOperation;
}
@Override
......
......@@ -6,7 +6,7 @@
//import com.fasterxml.jackson.annotation.JsonProperty;
//import com.fasterxml.jackson.core.JsonPointer;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.google.api.client.json.Json;
//import com.google.api.client.zjsonpatch.Json;
//
///**
// * Created by eli on 11/15/16.
......
......@@ -2,11 +2,14 @@ package logic.adapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import logic.adapter.HttpAdapter.model.ComputeVariable;
import java.util.Map;
/**
* Created by eli on 12/1/16.
*/
public class JsonPatchActionParams extends BaseActionParams{
public class JsonPatchActionParams extends DynamicVariablesParams{
@JsonProperty("fileInput")
private String fileJsonInput;
......@@ -14,7 +17,8 @@ public class JsonPatchActionParams extends BaseActionParams{
private String fileJsonPatch;
@JsonCreator
public JsonPatchActionParams(@JsonProperty("fileInput") String fileJsonInput, @JsonProperty("filePatch") String fileJsonPatch) {
public JsonPatchActionParams(@JsonProperty("variables") Map<String, ComputeVariable> variableMap, @JsonProperty("fileInput") String fileJsonInput, @JsonProperty("filePatch") String fileJsonPatch) {
super(variableMap);
this.fileJsonInput = fileJsonInput;
this.fileJsonPatch = fileJsonPatch;
}
......
package logic.adapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Created by eli on 12/8/16.
*/
public class SubStringActionParams extends BaseActionParams{
@JsonProperty("from")
private WithinStringPointer from;
@JsonProperty("to")
private WithinStringPointer to;
@JsonCreator
public SubStringActionParams(@JsonProperty("from") WithinStringPointer from,
@JsonProperty("to") WithinStringPointer to) {
this.from = from;
this.to = to;
}
public WithinStringPointer getFrom() { return this.from;}
public WithinStringPointer getTo() { return this.to;}
@Override
public String getId() {
return null;
}
@Override
public boolean isValid() {
return ((from!=null && from.isValid()) && ((to== null) || to.isValid()));
}
}
package logic.adapter.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import defs.Enums;
/**
* Created by eli on 12/8/16.
*/
public class WithinStringPointer implements ModelValidator{
private static final int MAX_INDEX_VALUE = 200;
@JsonProperty("str")
private String prefix;
@JsonProperty("location")
private Enums.eSubStringLocation eLocationType;
@JsonProperty("index")
private String strIndex;
private int index;
@JsonCreator
public WithinStringPointer(@JsonProperty("str") String prefix,
@JsonProperty("location") Enums.eSubStringLocation eLocationType,
@JsonProperty("index") String strIndex) {
this.prefix = prefix;
this.eLocationType = eLocationType;
this.strIndex = strIndex;
}
@JsonGetter("str")
public String getPrefix() {
return prefix;
}
@JsonGetter("location")
public String geteLocation() {
return eLocationType.getName();
}
@JsonGetter("index")
public String getStrIndex() {
return strIndex;
}
@JsonIgnore
public int getIndex(){
return index;
}
@JsonIgnore
public Enums.eSubStringLocation geteLocationType() {
return eLocationType;
}
@Override
public boolean isValid() {
//for index "state" prefix must be null
boolean ret = true;
switch (eLocationType){
case FIRST:
case LAST:
if (strIndex!=null)
ret=false;
break;
case INDEX:
//XXX-th is the state that the index indicate which appearance of the prefix to look for.
// (i.e: 1-th, 2-th, 3-th etc.)
case XXX_th:
try {
this.index = Integer.valueOf(strIndex);
ret = ( index>0 && index < MAX_INDEX_VALUE);
}
catch (NumberFormatException e){
ret = false;
}
break;
}
return ret;
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("prefix=").append((prefix!=null)?prefix:"null");
sb.append(", locationType=").append(eLocationType.getName());
sb.append(", index=").append((strIndex!=null)?strIndex:"null");
return sb.toString();
}
}
package logic.adapter.normalizer;
import com.fasterxml.jackson.databind.JsonNode;
import com.flipkart.zjsonpatch.JsonPatch;
//import com.google.api.client.json.Json;
//import com.flipkart.zjsonpatch.ZJsonPatch;
//import com.google.api.client.zjsonpatch.Json;
import defs.Constants;
import org.apache.commons.lang.text.StrTokenizer;
import util.Utils;
import common.JsonHandler;
import java.io.File;
import static util.Utils.readJsonNodeFromFile;
import util.zjsonpatch.ZJsonPatch;
/**
* Created by eli on 7/13/16.
......@@ -26,7 +22,7 @@ public class JsonConverterNormalizer implements INormalizer {
JsonNode fileJsonNode = format.get("jsonPatchfile");
if (fileJsonNode != null && !fileJsonNode.isNull()) {
JsonNode jsonPatch = Utils.readJsonNodeFromFile(JSON_PATCH_LOCATION + fileJsonNode.asText());
JsonNode jsonTarget = JsonPatch.apply(jsonPatch, jsonNodeToNormalize);
JsonNode jsonTarget = ZJsonPatch.apply(jsonPatch, jsonNodeToNormalize);
strToNormalize = JsonHandler.getObjectAsJsonString(jsonTarget);
}}
catch (Exception e){
......
package logic.adapter.normalizer;
//import org.json.XML
import com.fasterxml.jackson.databind.JsonNode;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
/**
* Created by eli on 7/11/16.
*/
public class Xml2jsonNormalizer implements INormalizer {
/**
* convert xml data string to Json string
* @param data - xml string to convert
* @return
*/
/**
* convert xml data string to Json string
* @param strToNormalize - xml string to convert
* @param format format may hold format data that needed for the normalizer for the activate
* currently, this normalizer doesn't need any data
* @return normalized String, null on failure
*/
@Override
public String activate(String strToNormalize, JsonNode format) {
JSONObject jsonObject;
String retString=null;
try {
jsonObject=XML.toJSONObject(strToNormalize);
retString=jsonObject.toString();
}
catch(JSONException | NullPointerException e){
e.printStackTrace();
}
return retString;
}
}
//package logic.adapter.normalizer;
//
////import org.zjsonpatch.XML
//
//import com.fasterxml.jackson.databind.JsonNode;
//import org.json.JSONException;
//import org.json.JSONObject;
//import org.json.XML;
//
///**
// * Created by eli on 7/11/16.
// */
//public class Xml2jsonNormalizer implements INormalizer {
//
// /**
// * convert xml data string to Json string
// * @param data - xml string to convert
// * @return
// */
// /**
// * convert xml data string to Json string
// * @param strToNormalize - xml string to convert
// * @param format format may hold format data that needed for the normalizer for the activate
// * currently, this normalizer doesn't need any data
// * @return normalized String, null on failure
// */
// @Override
// public String activate(String strToNormalize, JsonNode format) {
// JSONObject jsonObject;
// String retString=null;
// try {
// jsonObject=XML.toJSONObject(strToNormalize);
// retString=jsonObject.toString();
// }
// catch(JSONException | NullPointerException e){
// e.printStackTrace();
// }
//
// return retString;
// }
//
//}
......@@ -25,7 +25,7 @@ public class AdaptersRepository {
this.logger = logger;
adapterList = new HashMap<>();
}
public void load() {//have to throw exception
public void load() throws Exception {//have to throw exception
ArrayNode adaptersArray;
JsonNode jsonNode=null;
try {
......@@ -41,7 +41,7 @@ public class AdaptersRepository {
}
}
private void loadAdapters(ArrayNode adaptersArray) {
private void loadAdapters(ArrayNode adaptersArray) throws Exception {
if ( adaptersArray!= null && !adaptersArray.isNull() && adaptersArray.isArray()) {
for (int i = 0; i < adaptersArray.size(); i++) {
JsonNode jsonAdapter = adaptersArray.get(i);
......@@ -61,14 +61,15 @@ public class AdaptersRepository {
logger.error(Thread.currentThread().getStackTrace()[1].getMethodName()+" Failed to load adapters");
}
private void addHttpAdapter(String adapterId) {
private void addHttpAdapter(String adapterId) throws Exception {
HttpAdapter httpAdapter;
try {
httpAdapter = new HttpAdapter(logger, adapterId);
adapterList.put(adapterId, httpAdapter);
} catch (Exception e) {
e.printStackTrace();
logger.error("failed to load adapter: " + adapterId+ ", Exception:" + e.toString());
throw new Exception("failed to load adapter: " + adapterId+ ", Exception:" + e);
}
}
......
package logic.service.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import static defs.Constants.compiledRegEx;
import static defs.Constants.compiledRegExWord;
/**
* Created by eli on 7/18/16.
*/
public class Api {
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
@JsonProperty("method")
private String method;
@JsonProperty("apiIn")
private String apiIn;
private ApiInRegEx apiIn;
@JsonProperty("actions")
private List<Action> actions = new ArrayList<>();
@JsonIgnore
public Map<String, Integer> getMapKeyToParamIndex() {
return apiIn.getMapKeyToParamIndex();
}
/**
*
* @return
* The apiIn
*/
@JsonProperty("apiIn")
public String getApiIn() {
public ApiInRegEx getApiIn() {
return apiIn;
}
/**
*
* @param apiIn
* The apiIn
*/
@JsonProperty("apiIn")
public void setApiIn(String apiIn) {
public void setApiIn(ApiInRegEx apiIn) {
this.apiIn = apiIn;
}
private boolean isUserKey(String param) {
Matcher matcher = compiledRegExWord.matcher(param);
return (matcher.find());
}
/**
*
......@@ -57,7 +64,6 @@ public class Api {
public List<Action> getActions() {
return actions;
}
/**
*
* @param actions
......@@ -67,6 +73,16 @@ public class Api {
public void setActions(List<Action> actions) {
this.actions = actions;
}
public boolean isMatched(String[] apiId) {
boolean ret;
ret = apiIn.isMatch(apiId);
return ret;
}
public void setOffSet(int offSet) {
apiIn.setOffSet(offSet);
}
}
package logic.service.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import defs.Enums;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import static defs.Constants.compiledRegExWord;
import static defs.Enums.ePreDefinedRegexTypes.REGEX_DIGITS;
import static defs.Enums.ePreDefinedRegexTypes.STRING_EQUALS;
/**
* Created by eli on 12/20/16.
*/
public class ApiInRegEx {
@JsonProperty("name")
private String name;
@JsonProperty("paramsTypes")
private List<Enums.ePreDefinedRegexTypes> listOfParamsTypes;
@JsonCreator
public ApiInRegEx(@JsonProperty("name") String name, @JsonProperty("paramsTypes") List<Enums.ePreDefinedRegexTypes> listOfParamsTypes) {
this.name = name;
this.listOfParamsTypes = listOfParamsTypes;
try {
this.build();
} catch (Exception e) {
e.printStackTrace();
}
}
@JsonIgnore
private ArrayList<ParamType> listOfBuildedParams;
@JsonIgnore
private Map<String, Integer> mapKeyToParamIndex=new HashMap<>();
@JsonIgnore
public Map<String, Integer> getMapKeyToParamIndex() {
return mapKeyToParamIndex;
}
@JsonIgnore
public boolean isMatch(String[] apiId){
if(apiId==null || apiId.length!=listOfBuildedParams.size())
return false;
else{
for (int i = 0; i< apiId.length; i++){
if (!listOfBuildedParams.get(i).isMatch(apiId[i]))
return false;
}
}
return true;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("API:[name=").append((name!=null)?name:"null").append(", paramsType=");
sb.append((listOfParamsTypes!=null)?listOfParamsTypes.toString():"null").append("]");
return sb.toString();
}
private void build() throws Exception {
Enums.ePreDefinedRegexTypes currType=null;
int currIndex=0;
listOfBuildedParams = new ArrayList<>(5);
String[] params=name.split("/");
if (listOfParamsTypes!=null && listOfParamsTypes.size()>currIndex)
currType=listOfParamsTypes.get(currIndex++);
for (String param :
params) {
if ( !param.startsWith("$")){
ParamType paramType = new ParamType(param, STRING_EQUALS);
listOfBuildedParams.add(paramType);
}
else
{
if (isValidKeyPattern(param) && currType!=null){
ParamType paramType = new ParamType(param.substring(1), currType);
listOfBuildedParams.add(paramType);
if (listOfParamsTypes!=null && listOfParamsTypes.size()>currIndex)
currType=listOfParamsTypes.get(currIndex++);
}
else if(currType==null){
String error="ApiInRegEx "+this.toString()+" FAILED TO BUILD, reason: paramsTypes length mismatch";
System.out.println(error);
throw new Exception(error);
}
else{//not valid key pattern
String error="ApiInRegEx "+this.toString()+" FAILED TO BUILD, reason: key pattern is not valid";
System.out.println(error);
throw new Exception(error);
}
}
}
if (listOfBuildedParams.size()>0){
mapKeyToParamIndex=listOfBuildedParams.stream().
filter((param)-> param.getType()!=STRING_EQUALS).
collect(Collectors.toMap(param->param.getName(),param->listOfBuildedParams.indexOf(param)));
}
}
private boolean isValidKeyPattern(String param) {
Matcher matcher = compiledRegExWord.matcher(param);
return (matcher.find());
}
public void setOffSet(int offSet) {
for (Map.Entry<String, Integer> entry: mapKeyToParamIndex.entrySet()) {
mapKeyToParamIndex.replace(entry.getKey(), entry.getValue() + offSet);
}
}
private class ParamType {
private String name;
private Enums.ePreDefinedRegexTypes type;
public String getName() {
return name;
}
public Enums.ePreDefinedRegexTypes getType() {
return type;
}
public ParamType(String name, Enums.ePreDefinedRegexTypes type) {
this.name = name;
this.type = type;
}
public boolean isMatch(String param){
boolean ret=false;
switch (type){
case STRING_EQUALS:
ret = name.equals(param);
break;
case REGEX_NO_CHECK:
ret = true;
break;
case REGEX_DIGITS:
Matcher matcher = REGEX_DIGITS.getPattern().matcher(param);
ret = matcher.find();
break;
}
return ret;
}
}
}
......@@ -36,11 +36,18 @@ public class Service {
this.apiList = apiList;
}
public Api getApi(String apiId){
public Api matchApi(String[] apiId){
for (Api api : apiList) {
if (api.getApiIn().startsWith(apiId))
if (api.isMatched(apiId))
return api;
}
return null;
}
public void setOffSet(int offSet) {
for (Api api :
apiList) {
api.setOffSet(offSet);
}
}
}
......@@ -4,8 +4,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import common.JsonHandler;
import defs.Constants;
import logic.adapter.BaseAdapter;
import logic.adapter.HttpAdapter.HttpAdapter;
import logic.service.model.Api;
import logic.service.model.Service;
import microservice.io.iface.ILogger;
......@@ -66,6 +64,9 @@ public class ServicesRepository {
e.printStackTrace();
}
Service service = (Service)JsonHandler.getNodeAsObject(serviceNode,Service.class);
String[] split = serviceId.split("\\.");
int offSet = split.length;
service.setOffSet(offSet);
if (serviceList.putIfAbsent(serviceId,service) != null)
logger.debug("service " +serviceId + " was loaded successfully");
}
......@@ -76,10 +77,10 @@ public class ServicesRepository {
public Api getApi(String serviceId, String apiId) {
public Api getApi(String serviceId, String[] apiIdAsParams) {
Service service = serviceList.get(serviceId);
if (service!=null){
return service.getApi(apiId);
return service.matchApi(apiIdAsParams);
}
else
return null;
......
package logic.webSocket;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
import com.flipkart.zjsonpatch.JsonPatch;
import com.google.api.client.json.Json;
//import com.flipkart.zjsonpatch.ZJsonPatch;
import com.google.api.client.util.DateTime;
import com.neovisionaries.ws.client.*;
import defs.Constants;
import http.simpleHttpClient.SimpleHttpClient;
import http.simpleHttpClient.SimpleHttpRequest;
import http.simpleHttpClient.SimpleHttpResponse;
import logic.MdeManager;
import logic.adapter.action.JsonPatchAction;
import logic.adapter.model.ExtractValueActionParams;
import microservice.io.iface.ILogger;
import util.Utils;
import util.zjsonpatch.ZJsonPatch;
import java.io.IOException;
import java.io.InterruptedIOException;
......@@ -356,7 +351,7 @@ public class WebSocketEventListener implements WebSocketListener {
jsonPatchStr = jsonPatchStr.replaceFirst("\\$uid", details.getAppKey());
try {
JsonNode newJsonPatch = Utils.getJsonNodeFromString(jsonPatchStr);
jsonEvent = JsonPatch.apply(newJsonPatch, jsonEvent);
jsonEvent = ZJsonPatch.apply(newJsonPatch, jsonEvent);
this.sendHttpPost(details.getCallBackUrl(), jsonEvent);
} catch (IOException e) {
logging(connectionId+ " #1 sendEvent failed to send event error: "+e, eTraceLevel.eERROR, false);
......
......@@ -29,13 +29,10 @@ public class WebSocketManager {
this.defaultHeaders = defaultHeaders;
this.auth2Client = oAuth2Client;
}
public boolean isConnected( String connectionId, String uid){
StringBuilder sb = new StringBuilder();
sb.append(connectionId).append(":").append(uid);
String key = sb.toString();
if (webSocketConnections.containsKey(connectionId)){
WebSocketConnection connection = webSocketConnections.get(connectionId);
if (connection!=null ){
......
......@@ -17,6 +17,8 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static defs.Constants.*;
import static defs.Constants.compiledRegEx;
import static defs.Enums.eKeyWord;
......@@ -26,12 +28,12 @@ import static defs.Enums.eKeyWord;
public class HttpRequestResolver {
//this regexQueryParamValue means string starting with '$' followed with word (1-15 chars length) followed by period, ending with
//another word (1-15 chars)
private final static String regexQueryParamValue = "^\\$[a-zA-Z]{1,15}\\.[a-zA-Z]{1,15}$";
private final static Pattern patternFullMatchValue = Pattern.compile(regexQueryParamValue);
private final static String regexPathParamValue = "^\\$[a-zA-Z]{1,15}\\.[a-zA-Z]{1,15}$";
private final static Pattern patternPathParamValue = Pattern.compile(regexPathParamValue);
private final static String regexPathKeyWord= "^\\$[a-zA-Z0-9]{1,15}\\.[a-zA-Z]{1,15}$";
private final static Pattern patternPathKeyWord = Pattern.compile(regexPathKeyWord);
// private final static String regexQueryParamValue = "^\\$[a-zA-Z]{1,15}\\.[a-zA-Z]{1,15}$";
// private final static Pattern patternFullMatchValue = Pattern.compile(regexQueryParamValue);
// private final static String regexPathParamValue = "^\\$[a-zA-Z]{1,15}\\.[a-zA-Z]{1,15}$";
// private final static Pattern patternPathParamValue = Pattern.compile(regexPathParamValue);
// private final static String regexPathKeyWord= "^\\$[a-zA-Z0-9]{1,15}\\.[a-zA-Z]{1,15}$";
// private final static Pattern patternPathKeyWord = Pattern.compile(regexPathKeyWord);
// private final String tokenAccess;
//
// private RequestContext srcRequest;
......@@ -108,24 +110,16 @@ public class HttpRequestResolver {
{
name = header.getName();
value = header.getValue();
value = value.replaceFirst("\\$token",tokenAccess);
request.addHeader(name,value);
}
Map<String, String> variables;
path = dstRequestParamsPattern.getPath();
Enums.EnumCrudMethod enumCrudMethod = srcRequest.getEnumCrudMethod();
if (enumCrudMethod == Enums.EnumCrudMethod.E_CREATE){
if (dstRequestParamsPattern.getId().equals("subscribe")) {
variables = new HashMap<>();
String[] params = srcRequest.getParams();
if (params.length>3) {
variables.put("mdeKey", (srcRequest.getParams())[3]);
path = replaceMatchedKeysByItsValues(path, variables);
}
}
if (tokenAccess!=null) {
request.addHeader("Authorization", "Bearer " + tokenAccess);
}
else
path = dstRequestParamsPattern.getPath();
if (srcRequest.getVariablesValues()!=null && srcRequest.getVariablesValues().size()>0)
path = replaceMatchedKeysByItsValues(path, srcRequest.getVariablesValues());
if (runTimeVariables!=null && runTimeVariables.size()>0)
path = replaceMatchedKeysByItsValues(path, runTimeVariables);
request.setPath(path);
......@@ -144,8 +138,8 @@ public class HttpRequestResolver {
{
if (keyVals== null) return target;
final String regex = "\\$[a-zA-Z0-9]{1,15}";
final Pattern compiledRegEx = Pattern.compile(regex);
// /*final String*/ regex = "\\$[a-zA-Z0-9]{1,15}";
// /*final Pattern*/ compiledRegEx = Pattern.compile(regex);
String result=target;
Matcher matcher = compiledRegEx.matcher(target);
......
......@@ -12,6 +12,16 @@ public class Utils {
public static final ObjectMapper SORTED_MAPPER = new ObjectMapper();
public static String myTypeOf(Object obj){
int end_index = obj.toString().indexOf('@');
String type=obj.toString().substring(0,end_index);
int startIndex = type.lastIndexOf(".");
startIndex++;
return type.substring(startIndex,end_index);
}
public static Object readObjectFromString1(String jsonStr, Class<?> ObjClass) throws IOException {
Object obj = null;
......@@ -47,6 +57,8 @@ public class Utils {
return objectReader.readValue(jsonNode);
} catch (Exception var4) {
var4.printStackTrace();
// com.fasterxml.jackson.databind.JsonMappingException: Could not find creator property with name 'operationParams' (in class logic.adapter.HttpAdapter.model.IntermediateOperation)
// at [Source: N/A; line: -1, column: -1] (through reference chain: logic.adapter.model.AdapterModel["flows"]->java.util.ArrayList[0]->java.util.ArrayList[1])
}
}
else
......
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.annotation.JsonProperty;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.node.ArrayNode;
//import com.fasterxml.jackson.databind.node.ObjectNode;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//import com.github.fge.jackson.jsonpointer.ReferenceToken;
//import com.github.fge.jackson.jsonpointer.TokenResolver;
//import com.google.common.collect.Iterables;
//
//
///**
// * JSON Patch {@code add} operation
// *
// * <p>For this operation, {@code path} is the JSON Pointer where the value
// * should be added, and {@code value} is the value to add.</p>
// *
// * <p>Note that if the target value pointed to by {@code path} already exists,
// * it is replaced. In this case, {@code add} is equivalent to {@code replace}.
// * </p>
// *
// * <p>Note also that a value will be created at the target path <b>if and only
// * if</b> the immediate parent of that value exists (and is of the correct
// * type).</p>
// *
// * <p>Finally, if the last reference token of the JSON Pointer is {@code -} and
// * the immediate parent is an array, the given value is added at the end of the
// * array. For instance, applying:</p>
// *
// * <pre>
// * { "op": "add", "path": "/-", "value": 3 }
// * </pre>
// *
// * <p>to:</p>
// *
// * <pre>
// * [ 1, 2 ]
// * </pre>
// *
// * <p>will give:</p>
// *
// * <pre>
// * [ 1, 2, 3 ]
// * </pre>
// */
//public final class AddOperation
// extends PathValueOperation
//{
// private static final ReferenceToken LAST_ARRAY_ELEMENT
// = ReferenceToken.fromRaw("-");
//
// @JsonCreator
// public AddOperation(@JsonProperty("path") final JsonPointer path,
// @JsonProperty("value") final JsonNode value)
// {
// super("add", path, value);
// }
//
// @Override
// public JsonNode apply(final JsonNode node)
// throws JsonPatchException
// {
// if (path.isEmpty())
// return value;
//
// /*
// * Check the parent node: it must exist and be a container (ie an array
// * or an object) for the add operation to work.
// */
// final JsonNode parentNode = path.parent().path(node);
// if (parentNode.isMissingNode())
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.noSuchParent"));
// if (!parentNode.isContainerNode())
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.parentNotContainer"));
// return parentNode.isArray()
// ? addToArray(path, node)
// : addToObject(path, node);
// }
//
// private JsonNode addToArray(final JsonPointer path, final JsonNode node)
// throws JsonPatchException
// {
// final JsonNode ret = node.deepCopy();
// final ArrayNode target = (ArrayNode) path.parent().get(ret);
// final TokenResolver<JsonNode> token = Iterables.getLast(path);
//
// if (token.getToken().equals(LAST_ARRAY_ELEMENT)) {
// target.add(value);
// return ret;
// }
//
// final int size = target.size();
// final int index;
// try {
// index = Integer.parseInt(token.toString());
// } catch (NumberFormatException ignored) {
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.notAnIndex"));
// }
//
// if (index < 0 || index > size)
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.noSuchIndex"));
//
// target.insert(index, value);
// return ret;
// }
//
// private JsonNode addToObject(final JsonPointer path, final JsonNode node)
// {
// final JsonNode ret = node.deepCopy();
// final ObjectNode target = (ObjectNode) path.parent().get(ret);
// target.put(Iterables.getLast(path).getToken().getRaw(), value);
// return ret;
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.annotation.JsonProperty;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//
///**
// * JSON Patch {@code copy} operation
// *
// * <p>For this operation, {@code from} is the JSON Pointer of the value to copy,
// * and {@code path} is the destination where the value should be copied.</p>
// *
// * <p>As for {@code add}:</p>
// *
// * <ul>
// * <li>the value at the destination path is either created or replaced;</li>
// * <li>it is created only if the immediate parent exists;</li>
// * <li>{@code -} appends at the end of an array.</li>
// * </ul>
// *
// * <p>It is an error if {@code from} fails to resolve to a JSON value.</p>
// */
//public final class CopyOperation
// extends DualPathOperation
//{
// @JsonCreator
// public CopyOperation(@JsonProperty("from") final JsonPointer from,
// @JsonProperty("path") final JsonPointer path)
// {
// super("copy", from, path);
// }
//
// @Override
// public JsonNode apply(final JsonNode node)
// throws JsonPatchException
// {
// final JsonNode dupData = from.path(node).deepCopy();
// if (dupData.isMissingNode())
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.noSuchPath"));
// return new AddOperation(path, dupData).apply(node);
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.core.JsonGenerator;
//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.SerializerProvider;
//import com.fasterxml.jackson.databind.annotation.JsonSerialize;
//import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
//import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//
//import java.io.IOException;
//
///**
// * Base class for JSON Patch operations taking two JSON Pointers as arguments
// */
//public abstract class DualPathOperation
// extends JsonPatchOperation
//{
// @JsonSerialize(using = ToStringSerializer.class)
// protected final JsonPointer from;
//
// /**
// * Protected constructor
// *
// * @param op operation name
// * @param from source path
// * @param path destination path
// */
// protected DualPathOperation(final String op, final JsonPointer from,
// final JsonPointer path)
// {
// super(op, path);
// this.from = from;
// }
//
// @Override
// public final void serialize(final JsonGenerator jgen,
// final SerializerProvider provider)
// throws IOException, JsonProcessingException
// {
// jgen.writeStartObject();
// jgen.writeStringField("op", op);
// jgen.writeStringField("path", path.toString());
// jgen.writeStringField("from", from.toString());
// jgen.writeEndObject();
// }
//
// @Override
// public final void serializeWithType(final JsonGenerator jgen,
// final SerializerProvider provider, final TypeSerializer typeSer)
// throws IOException, JsonProcessingException
// {
// serialize(jgen, provider);
// }
//
// @Override
// public final String toString()
// {
// return "op: " + op + "; from: \"" + from + "\"; path: \"" + path + '"';
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.core.JsonGenerator;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.JsonSerializable;
//import com.fasterxml.jackson.databind.SerializerProvider;
//import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
//import com.github.fge.jackson.JacksonUtils;
//import com.github.fge.msgsimple.bundle.MessageBundle;
//import com.github.fge.msgsimple.load.MessageBundles;
//import com.google.common.collect.ImmutableList;
//
//import java.io.IOException;
//import java.util.List;
//
///**
// * Implementation of JSON Patch
// *
// * <p><a href="http://tools.ietf.org/html/draft-ietf-appsawg-json-patch-10">JSON
// * Patch</a>, as its name implies, is an IETF draft describing a mechanism to
// * apply a patch to any JSON value. This implementation covers all operations
// * according to the specification; however, there are some subtle differences
// * with regards to some operations which are covered in these operations'
// * respective documentation.</p>
// *
// * <p>An example of a JSON Patch is as follows:</p>
// *
// * <pre>
// * [
// * {
// * "op": "add",
// * "path": "/-",
// * "value": {
// * "productId": 19,
// * "name": "Duvel",
// * "type": "beer"
// * }
// * }
// * ]
// * </pre>
// *
// * <p>This patch contains a single operation which adds an item at the end of
// * an array. A JSON Patch can contain more than one operation; in this case, all
// * operations are applied to the input JSON value in their order of appearance,
// * until all operations are applied or an error condition is encountered.</p>
// *
// * <p>The main point where this implementation differs from the specification
// * is initial JSON parsing. The draft says:</p>
// *
// * <pre>
// * Operation objects MUST have exactly one "op" member
// * </pre>
// *
// * <p>and:</p>
// *
// * <pre>
// * Additionally, operation objects MUST have exactly one "path" member.
// * </pre>
// *
// * <p>However, obeying these to the letter forces constraints on the JSON
// * <b>parser</b>. Here, these constraints are not enforced, which means:</p>
// *
// * <pre>
// * [ { "op": "add", "op": "remove", "path": "/x" } ]
// * </pre>
// *
// * <p>is parsed (as a {@code remove} operation, since it appears last).</p>
// *
// * <p><b>IMPORTANT NOTE:</b> the JSON Patch is supposed to be VALID when the
// * constructor for this class ({@link JsonPatch#fromJson(JsonNode)} is used.</p>
// */
//public final class JsonPatch
// implements JsonSerializable
//{
// private static final MessageBundle BUNDLE
// = MessageBundles.getBundle(JsonPatchMessages.class);
//
// /**
// * List of operations
// */
// private final List<JsonPatchOperation> operations;
//
// /**
// * Constructor
// *
// * <p>Normally, you should never have to use it.</p>
// *
// * @param operations the list of operations for this patch
// * @see JsonPatchOperation
// */
// @JsonCreator
// public JsonPatch(final List<JsonPatchOperation> operations)
// {
// this.operations = ImmutableList.copyOf(operations);
// }
//
// /**
// * Static factory method to build a JSON Patch out of a JSON representation
// *
// * @param node the JSON representation of the generated JSON Patch
// * @return a JSON Patch
// * @throws IOException input is not a valid JSON patch
// * @throws NullPointerException input is null
// */
// public static JsonPatch fromJson(final JsonNode node)
// throws IOException
// {
// BUNDLE.checkNotNull(node, "jsonPatch.nullInput");
// return JacksonUtils.getReader().withType(JsonPatch.class)
// .readValue(node);
// }
//
// /**
// * Apply this patch to a JSON value
// *
// * @param node the value to apply the patch to
// * @return the patched JSON value
// * @throws JsonPatchException failed to apply patch
// * @throws NullPointerException input is null
// */
// public JsonNode apply(final JsonNode node)
// throws JsonPatchException
// {
// BUNDLE.checkNotNull(node, "jsonPatch.nullInput");
// JsonNode ret = node;
// for (final JsonPatchOperation operation: operations)
// ret = operation.apply(ret);
//
// return ret;
// }
//
// @Override
// public String toString()
// {
// return operations.toString();
// }
//
// @Override
// public void serialize(final JsonGenerator jgen,
// final SerializerProvider provider)
// throws IOException
// {
// jgen.writeStartArray();
// for (final JsonPatchOperation op: operations)
// op.serialize(jgen, provider);
// jgen.writeEndArray();
// }
//
// @Override
// public void serializeWithType(final JsonGenerator jgen,
// final SerializerProvider provider, final TypeSerializer typeSer)
// throws IOException
// {
// serialize(jgen, provider);
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//public final class JsonPatchException
// extends Exception
//{
// public JsonPatchException(final String message)
// {
// super(message);
// }
//
// public JsonPatchException(final String message, final Throwable cause)
// {
// super(message, cause);
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.github.fge.msgsimple.bundle.MessageBundle;
//import com.github.fge.msgsimple.bundle.PropertiesBundle;
//import com.github.fge.msgsimple.load.MessageBundleLoader;
//
//public final class JsonPatchMessages
// implements MessageBundleLoader
//{
// @Override
// public MessageBundle getBundle()
// {
// return PropertiesBundle.forPath("/com/github/fge/jsonpatch/messages");
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
//import com.fasterxml.jackson.annotation.JsonSubTypes;
//import com.fasterxml.jackson.annotation.JsonTypeInfo;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.JsonSerializable;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//import com.github.fge.msgsimple.bundle.MessageBundle;
//import com.github.fge.msgsimple.load.MessageBundles;
//
//import static com.fasterxml.jackson.annotation.JsonSubTypes.Type;
//import static com.fasterxml.jackson.annotation.JsonTypeInfo.As;
//import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
//
//@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "op")
//
//@JsonSubTypes({
// @Type(name = "add", value = AddOperation.class),
// @Type(name = "copy", value = CopyOperation.class),
// @Type(name = "move", value = MoveOperation.class),
// @Type(name = "remove", value = RemoveOperation.class),
// @Type(name = "replace", value = ReplaceOperation.class),
// @Type(name = "test", value = TestOperation.class)
//})
//
///**
// * Base abstract class for one patch operation
// *
// * <p>Two more abstract classes extend this one according to the arguments of
// * the operation:</p>
// *
// * <ul>
// * <li>{@link DualPathOperation} for operations taking a second pointer as
// * an argument ({@code copy} and {@code move});</li>
// * <li>{@link PathValueOperation} for operations taking a value as an
// * argument ({@code add}, {@code replace} and {@code test}).</li>
// * </ul>
// */
//@JsonIgnoreProperties(ignoreUnknown = true)
//public abstract class JsonPatchOperation
// implements JsonSerializable
//{
// protected static final MessageBundle BUNDLE
// = MessageBundles.getBundle(JsonPatchMessages.class);
//
// protected final String op;
//
// /*
// * Note: no need for a custom deserializer, Jackson will try and find a
// * constructor with a single string argument and use it.
// *
// * However, we need to serialize using .toString().
// */
// protected final JsonPointer path;
//
// /**
// * Constructor
// *
// * @param op the operation name
// * @param path the JSON Pointer for this operation
// */
// protected JsonPatchOperation(final String op, final JsonPointer path)
// {
// this.op = op;
// this.path = path;
// }
//
// /**
// * Apply this operation to a JSON value
// *
// * @param node the value to patch
// * @return the patched value
// * @throws JsonPatchException operation failed to apply to this value
// */
// public abstract JsonNode apply(final JsonNode node)
// throws JsonPatchException;
//
// @Override
// public abstract String toString();
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.annotation.JsonProperty;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//
///**
// * JSON Patch {@code move} operation
// *
// * <p>For this operation, {@code from} points to the value to move, and {@code
// * path} points to the new location of the moved value.</p>
// *
// * <p>As for {@code add}:</p>
// *
// * <ul>
// * <li>the value at the destination path is either created or replaced;</li>
// * <li>it is created only if the immediate parent exists;</li>
// * <li>{@code -} appends at the end of an array.</li>
// * </ul>
// *
// * <p>It is an error condition if {@code from} does not point to a JSON value.
// * </p>
// *
// * <p>The specification adds another rule that the {@code from} path must not be
// * an immediate parent of {@code path}. Unfortunately, that doesn't really work.
// * Consider this patch:</p>
// *
// * <pre>
// * { "op": "move", "from": "/0", "path": "/0/x" }
// * </pre>
// *
// * <p>Even though {@code /0} is an immediate parent of {@code /0/x}, when this
// * patch is applied to:</p>
// *
// * <pre>
// * [ "victim", {} ]
// * </pre>
// *
// * <p>it actually succeeds and results in the patched value:</p>
// *
// * <pre>
// * [ { "x": "victim" } ]
// * </pre>
// */
//public final class MoveOperation
// extends DualPathOperation
//{
// @JsonCreator
// public MoveOperation(@JsonProperty("from") final JsonPointer from,
// @JsonProperty("path") final JsonPointer path)
// {
// super("move", from, path);
// }
//
// @Override
// public JsonNode apply(final JsonNode node)
// throws JsonPatchException
// {
// if (from.equals(path))
// return node.deepCopy();
// final JsonNode movedNode = from.path(node);
// if (movedNode.isMissingNode())
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.noSuchPath"));
// final JsonPatchOperation remove = new RemoveOperation(from);
// final JsonPatchOperation add = new AddOperation(path, movedNode);
// return add.apply(remove.apply(node));
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.core.JsonGenerator;
//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.SerializerProvider;
//import com.fasterxml.jackson.databind.annotation.JsonSerialize;
//import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//
//import java.io.IOException;
//
///**
// * Base class for patch operations taking a value in addition to a path
// */
//public abstract class PathValueOperation
// extends JsonPatchOperation
//{
// @JsonSerialize
// protected final JsonNode value;
//
// /**
// * Protected constructor
// *
// * @param op operation name
// * @param path affected path
// * @param value JSON value
// */
// protected PathValueOperation(final String op, final JsonPointer path,
// final JsonNode value)
// {
// super(op, path);
// this.value = value.deepCopy();
// }
//
// @Override
// public final void serialize(final JsonGenerator jgen,
// final SerializerProvider provider)
// throws IOException, JsonProcessingException
// {
// jgen.writeStartObject();
// jgen.writeStringField("op", op);
// jgen.writeStringField("path", path.toString());
// jgen.writeFieldName("value");
// jgen.writeTree(value);
// jgen.writeEndObject();
// }
//
// @Override
// public final void serializeWithType(final JsonGenerator jgen,
// final SerializerProvider provider, final TypeSerializer typeSer)
// throws IOException, JsonProcessingException
// {
// serialize(jgen, provider);
// }
//
// @Override
// public final String toString()
// {
// return "op: " + op + "; path: \"" + path + "\"; value: " + value;
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.annotation.JsonProperty;
//import com.fasterxml.jackson.core.JsonGenerator;
//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.SerializerProvider;
//import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
//import com.fasterxml.jackson.databind.node.ArrayNode;
//import com.fasterxml.jackson.databind.node.MissingNode;
//import com.fasterxml.jackson.databind.node.ObjectNode;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//import com.google.common.collect.Iterables;
//
//import java.io.IOException;
//
///**
// * JSON Path {@code remove} operation
// *
// * <p>This operation only takes one pointer ({@code path}) as an argument. It
// * is an error condition if no JSON value exists at that pointer.</p>
// */
//public final class RemoveOperation
// extends JsonPatchOperation
//{
// @JsonCreator
// public RemoveOperation(@JsonProperty("path") final JsonPointer path)
// {
// super("remove", path);
// }
//
// @Override
// public JsonNode apply(final JsonNode node)
// throws JsonPatchException
// {
// if (path.isEmpty())
// return MissingNode.getInstance();
// if (path.path(node).isMissingNode())
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.noSuchPath"));
// final JsonNode ret = node.deepCopy();
// final JsonNode parentNode = path.parent().get(ret);
// final String raw = Iterables.getLast(path).getToken().getRaw();
// if (parentNode.isObject())
// ((ObjectNode) parentNode).remove(raw);
// else
// ((ArrayNode) parentNode).remove(Integer.parseInt(raw));
// return ret;
// }
//
// @Override
// public void serialize(final JsonGenerator jgen,
// final SerializerProvider provider)
// throws IOException, JsonProcessingException
// {
// jgen.writeStartObject();
// jgen.writeStringField("op", "remove");
// jgen.writeStringField("path", path.toString());
// jgen.writeEndObject();
// }
//
// @Override
// public void serializeWithType(final JsonGenerator jgen,
// final SerializerProvider provider, final TypeSerializer typeSer)
// throws IOException, JsonProcessingException
// {
// serialize(jgen, provider);
// }
//
// @Override
// public String toString()
// {
// return "op: " + op + "; path: \"" + path + '"';
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.annotation.JsonProperty;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.fasterxml.jackson.databind.node.ArrayNode;
//import com.fasterxml.jackson.databind.node.ObjectNode;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//import com.google.common.collect.Iterables;
//
///**
// * JSON Patch {@code replace} operation
// *
// * <p>For this operation, {@code path} points to the value to replace, and
// * {@code value} is the replacement value.</p>
// *
// * <p>It is an error condition if {@code path} does not point to an actual JSON
// * value.</p>
// */
//public final class ReplaceOperation
// extends PathValueOperation
//{
// @JsonCreator
// public ReplaceOperation(@JsonProperty("path") final JsonPointer path,
// @JsonProperty("value") final JsonNode value)
// {
// super("replace", path, value);
// }
//
// @Override
// public JsonNode apply(final JsonNode node)
// throws JsonPatchException
// {
// /*
// * FIXME cannot quite be replaced by a remove + add because of arrays.
// * For instance:
// *
// * { "op": "replace", "path": "/0", "value": 1 }
// *
// * with
// *
// * [ "x" ]
// *
// * If remove is done first, the array is empty and add rightly complains
// * that there is no such index in the array.
// */
// if (path.path(node).isMissingNode())
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.noSuchPath"));
// final JsonNode replacement = value.deepCopy();
// if (path.isEmpty())
// return replacement;
// final JsonNode ret = node.deepCopy();
// final JsonNode parent = path.parent().get(ret);
// final String rawToken = Iterables.getLast(path).getToken().getRaw();
// if (parent.isObject())
// ((ObjectNode) parent).put(rawToken, replacement);
// else
// ((ArrayNode) parent).set(Integer.parseInt(rawToken), replacement);
// return ret;
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch;
//
//import com.fasterxml.jackson.annotation.JsonCreator;
//import com.fasterxml.jackson.annotation.JsonProperty;
//import com.fasterxml.jackson.databind.JsonNode;
//import com.github.fge.jackson.JsonNumEquals;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//import com.google.common.base.Equivalence;
//
///**
// * JSON Patch {@code test} operation
// *
// * <p>The two arguments for this operation are the pointer containing the value
// * to test ({@code path}) and the value to test equality against ({@code
// * value}).</p>
// *
// * <p>It is an error if no value exists at the given path.</p>
// *
// * <p>Also note that equality as defined by JSON Patch is exactly the same as it
// * is defined by JSON Schema itself. As such, this operation reuses {@link
// * JsonNumEquals} for testing equality.</p>
// */
//public final class TestOperation
// extends PathValueOperation
//{
// private static final Equivalence<JsonNode> EQUIVALENCE
// = JsonNumEquals.getInstance();
//
// @JsonCreator
// public TestOperation(@JsonProperty("path") final JsonPointer path,
// @JsonProperty("value") final JsonNode value)
// {
// super("test", path, value);
// }
//
// @Override
// public JsonNode apply(final JsonNode node)
// throws JsonPatchException
// {
// final JsonNode tested = path.path(node);
// if (tested.isMissingNode())
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.noSuchPath"));
// if (!EQUIVALENCE.equivalent(tested, value))
// throw new JsonPatchException(BUNDLE.getMessage(
// "jsonPatch.valueTestFailure"));
// return node.deepCopy();
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch.diff;
//
//import com.fasterxml.jackson.databind.JsonNode;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//import com.github.fge.jsonpatch.*;
//
//final class DiffOperation
//{
// private final Type type;
// /* An op's "from", if any */
// private final JsonPointer from;
// /* Value displaced by this operation, if any */
// private final JsonNode oldValue;
// /* An op's "path", if any */
// private final JsonPointer path;
// /* An op's "value", if any */
// private final JsonNode value;
//
// static DiffOperation add(final JsonPointer path,
// final JsonNode value)
// {
// return new DiffOperation(Type.ADD, null, null, path, value);
// }
//
// static DiffOperation copy(final JsonPointer from,
// final JsonPointer path, final JsonNode value)
// {
// return new DiffOperation(Type.COPY, from, null, path,
// value);
// }
//
// static DiffOperation move(final JsonPointer from,
// final JsonNode oldValue, final JsonPointer path,
// final JsonNode value)
// {
// return new DiffOperation(Type.MOVE, from, oldValue, path,
// value);
// }
//
// static DiffOperation remove(final JsonPointer from,
// final JsonNode oldValue)
// {
// return new DiffOperation(Type.REMOVE, from, oldValue, null, null);
// }
//
// static DiffOperation replace(final JsonPointer from,
// final JsonNode oldValue, final JsonNode value)
// {
// return new DiffOperation(Type.REPLACE, from, oldValue, null,
// value);
// }
//
// private DiffOperation(final Type type, final JsonPointer from,
// final JsonNode oldValue, final JsonPointer path,
// final JsonNode value)
// {
// this.type = type;
// this.from = from;
// this.oldValue = oldValue;
// this.path = path;
// this.value = value;
// }
//
// Type getType()
// {
// return type;
// }
//
// JsonPointer getFrom()
// {
// return from;
// }
//
// JsonNode getOldValue()
// {
// return oldValue;
// }
//
// JsonPointer getPath()
// {
// return path;
// }
//
// JsonNode getValue()
// {
// return value;
// }
//
// JsonPatchOperation asJsonPatchOperation()
// {
// return type.toOperation(this);
// }
//
// enum Type {
// ADD
// {
// @Override
// JsonPatchOperation toOperation(final DiffOperation op)
// {
// return new AddOperation(op.path, op.value);
// }
// },
// COPY
// {
// @Override
// JsonPatchOperation toOperation(final DiffOperation op)
// {
// return new CopyOperation(op.from, op.path);
// }
// },
// MOVE
// {
// @Override
// JsonPatchOperation toOperation(final DiffOperation op)
// {
// return new MoveOperation(op.from, op.path);
// }
// },
// REMOVE
// {
// @Override
// JsonPatchOperation toOperation(final DiffOperation op)
// {
// return new RemoveOperation(op.from);
// }
// },
// REPLACE
// {
// @Override
// JsonPatchOperation toOperation(final DiffOperation op)
// {
// return new ReplaceOperation(op.from, op.value);
// }
// },
// ;
//
// abstract JsonPatchOperation toOperation(final DiffOperation op);
// }
//}
///*
// * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com)
// *
// * This software is dual-licensed under:
// *
// * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
// * later version;
// * - the Apache Software License (ASL) version 2.0.
// *
// * The text of this file and of both licenses is available at the root of this
// * project or, if you have the jar distribution, in directory META-INF/, under
// * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
// *
// * Direct link to the sources:
// *
// * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
// * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
// */
//
//package util.fgeJsonPatch.diff;
//
//import com.fasterxml.jackson.databind.JsonNode;
//import com.github.fge.jackson.JsonNumEquals;
//import com.github.fge.jackson.jsonpointer.JsonPointer;
//import com.github.fge.jsonpatch.JsonPatch;
//import com.github.fge.jsonpatch.JsonPatchOperation;
//import com.google.common.base.Equivalence;
//import com.google.common.base.Predicate;
//import com.google.common.collect.ImmutableMap;
//import com.google.common.collect.Lists;
//
//import javax.annotation.Nullable;
//import java.util.List;
//import java.util.Map;
//
//// TODO: cleanup
//final class DiffProcessor
//{
// private static final Equivalence<JsonNode> EQUIVALENCE
// = JsonNumEquals.getInstance();
//
// private final Map<JsonPointer, JsonNode> unchanged;
//
// private final List<DiffOperation> diffs = Lists.newArrayList();
//
// DiffProcessor(final Map<JsonPointer, JsonNode> unchanged)
// {
// this.unchanged = ImmutableMap.copyOf(unchanged);
// }
//
// void valueReplaced(final JsonPointer pointer, final JsonNode oldValue,
// final JsonNode newValue)
// {
// diffs.add(DiffOperation.replace(pointer, oldValue, newValue));
// }
//
// void valueRemoved(final JsonPointer pointer, final JsonNode value)
// {
// diffs.add(DiffOperation.remove(pointer, value));
// }
//
// void valueAdded(final JsonPointer pointer, final JsonNode value)
// {
// final int removalIndex = findPreviouslyRemoved(value);
// if (removalIndex != -1) {
// final DiffOperation removed = diffs.get(removalIndex);
// diffs.remove(removalIndex);
// diffs.add(DiffOperation.move(removed.getFrom(),
// value, pointer, value));
// return;
// }
// final JsonPointer ptr = findUnchangedValue(value);
// final DiffOperation op = ptr != null
// ? DiffOperation.copy(ptr, pointer, value)
// : DiffOperation.add(pointer, value);
//
// diffs.add(op);
// }
//
// JsonPatch getPatch()
// {
// final List<JsonPatchOperation> list = Lists.newArrayList();
//
// for (final DiffOperation op: diffs)
// list.add(op.asJsonPatchOperation());
//
// return new JsonPatch(list);
// }
//
// @Nullable
// private JsonPointer findUnchangedValue(final JsonNode value)
// {
// final Predicate<JsonNode> predicate = EQUIVALENCE.equivalentTo(value);
// for (final Map.Entry<JsonPointer, JsonNode> entry: unchanged.entrySet())
// if (predicate.apply(entry.getValue()))
// return entry.getKey();
// return null;
// }
//
// private int findPreviouslyRemoved(final JsonNode value)
// {
// final Predicate<JsonNode> predicate = EQUIVALENCE.equivalentTo(value);
//
// DiffOperation op;
//
// for (int i = 0; i < diffs.size(); i++) {
// op = diffs.get(i);
// if (op.getType() == DiffOperation.Type.REMOVE
// && predicate.apply(op.getOldValue()))
// return i;
// }
// return -1;
// }
//}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment