Changed the management of instance property to properly support Map,

List and Set
This commit is contained in:
Luca Frosini 2021-10-26 20:49:58 +02:00
parent 2578a7cecb
commit b025d08099
6 changed files with 277 additions and 88 deletions

View File

@ -876,7 +876,7 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
return null;
}
public static Object getObjectFromElement(JsonNode value)
public static Object getObjectFromJsonNode(JsonNode value)
throws UnsupportedDataTypeException, ResourceRegistryException {
JsonNodeType jsonNodeType = value.getNodeType();
@ -885,23 +885,8 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
return PropertyElementManagement.getPropertyDocument(value);
case ARRAY:
List<Object> list = new ArrayList<Object>();
Iterator<JsonNode> arrayElement = value.elements();
while(arrayElement.hasNext()) {
JsonNode arrayNode = arrayElement.next();
Object objectNode = getObjectFromElement(arrayNode);
if(objectNode != null) {
list.add(objectNode);
}
}
return list;
break;
/*
* List/Set support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354
*
throw new UnsupportedDataTypeException(
"List/Set support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354");
*/
case BINARY:
break;
@ -940,10 +925,10 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
return null;
}
public Map<String,Object> getPropertyMap(JsonNode jsonNode, Set<String> ignoreKeys,
public Map<String,JsonNode> getPropertyMap(JsonNode jsonNode, Set<String> ignoreKeys,
Set<String> ignoreStartWith) throws JsonProcessingException, IOException {
Map<String,Object> map = new HashMap<>();
Map<String, JsonNode> map = new HashMap<>();
if(ignoreKeys == null) {
ignoreKeys = new HashSet<>();
@ -971,15 +956,7 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
}
JsonNode value = entry.getValue();
Object object = null;
try {
object = getObjectFromElement(value);
if(object != null) {
map.put(key, object);
}
} catch(ResourceRegistryException e) {
logger.warn("An invalidy property has been provided. It will be ignored.");
}
map.put(key, value);
}
@ -991,7 +968,7 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
Set<String> oldKeys = element.getPropertyNames();
Map<String,Object> properties;
Map<String,JsonNode> properties;
try {
properties = getPropertyMap(jsonNode, ignoreKeys, ignoreStartWithKeys);
} catch(IOException e) {
@ -1000,33 +977,88 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
oldKeys.removeAll(properties.keySet());
getOClass();
for(String key : properties.keySet()) {
try {
Object object = properties.get(key);
JsonNode value = properties.get(key);
boolean set = false;
OProperty oProperty = oClass.getProperty(key);
if(object instanceof ODocument) {
ODocument oDocument = (ODocument) object;
element.setProperty(key, oDocument, OType.EMBEDDED);
set = true;
}
/*
* List/Set support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354
*/
if(object instanceof Set) {
element.setProperty(key, object, OType.EMBEDDEDSET);
set = true;
}
if(object instanceof List) {
element.setProperty(key, object, OType.EMBEDDEDLIST);
set = true;
}
if(!set) {
element.setProperty(key, object);
if(oProperty==null) {
Object object = getObjectFromJsonNode(value);
if(object != null) {
if(object instanceof ODocument) {
element.setProperty(key, object, OType.EMBEDDED);
}else {
element.setProperty(key, object);
}
}
}else {
switch (oProperty.getType()) {
case EMBEDDED:
ODocument oDocument = PropertyElementManagement.getPropertyDocument(value);
element.setProperty(key, oDocument, OType.EMBEDDED);
break;
case EMBEDDEDLIST:
List<Object> list = new ArrayList<Object>();
Iterator<JsonNode> arrayElement = value.elements();
while(arrayElement.hasNext()) {
JsonNode elementOfArray = arrayElement.next();
Object object = null;
if(oProperty.getLinkedType()!=null) {
object = getObjectFromJsonNode(elementOfArray);
}else {
object = PropertyElementManagement.getPropertyDocument(elementOfArray);
}
list.add(object);
}
element.setProperty(key, list, OType.EMBEDDEDLIST);
break;
case EMBEDDEDSET:
Set<Object> set = new HashSet<Object>();
Iterator<JsonNode> setElement = value.elements();
while(setElement.hasNext()) {
JsonNode elementOfSet = setElement.next();
Object object = null;
if(oProperty.getLinkedType()!=null) {
object = getObjectFromJsonNode(elementOfSet);
}else {
object = PropertyElementManagement.getPropertyDocument(elementOfSet);
}
set.add(object);
}
element.setProperty(key, set, OType.EMBEDDEDSET);
break;
case EMBEDDEDMAP:
Map<String, Object> map = new HashMap<>();
Iterator<String> fieldNames = value.fieldNames();
while(fieldNames.hasNext()) {
String fieldKey = fieldNames.next();
Object object = null;
if(oProperty.getLinkedType()!=null) {
object = getObjectFromJsonNode(value.get(fieldKey));
}else {
object = PropertyElementManagement.getPropertyDocument(value.get(fieldKey));
}
map.put(fieldKey, object);
}
element.setProperty(key, map, OType.EMBEDDEDMAP);
break;
default:
Object object = getObjectFromJsonNode(value);
if(object != null) {
element.setProperty(key, object);
}
break;
}
}
} catch(Exception e) {
@ -1035,6 +1067,7 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
logger.error(error);
throw new ResourceRegistryException(error, e);
}
}
OUTER_FOR: for(String key : oldKeys) {
@ -1118,16 +1151,26 @@ public abstract class ElementManagement<El extends OElement, T extends Type> {
ArrayNode arrayNode = objectMapper.createArrayNode();
for(Object o : collection) {
Object obj = getPropertyForJson("PLACEHOLDER", o);
JsonNode obj = getPropertyForJson("PLACEHOLDER", o);
if(obj!=null) {
arrayNode.add((JsonNode) obj);
arrayNode.add(obj);
}
}
return arrayNode;
}
if(object instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) object;
ObjectNode objectNode = objectMapper.createObjectNode();
for(String k : map.keySet()) {
JsonNode obj = getPropertyForJson("PLACEHOLDER", map.get(k));
objectNode.set(k, obj);
}
return objectNode;
}
return new TextNode(object.toString());
} catch(Exception e) {

View File

@ -51,6 +51,10 @@ public class PropertyElementManagement {
public static ODocument getPropertyDocument(JsonNode jsonNode) throws ResourceRegistryException {
ODocument oDocument = null;
if(jsonNode.isNull()) {
return null;
}
if(jsonNode.has(Element.CLASS_PROPERTY)) {
// Complex type
String type = ElementManagement.getClassProperty(jsonNode);

View File

@ -46,6 +46,7 @@ public class JsonQuery {
protected ObjectMapper objectMapper;
protected JsonNode jsonQuery;
protected JsonQueryERElement entryPoint;
protected ODatabaseDocument oDatabaseDocument;
public JsonQuery() {
this.objectMapper = new ObjectMapper();
@ -105,7 +106,7 @@ public class JsonQuery {
public String query() throws InvalidQueryException, ResourceRegistryException {
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
ODatabaseDocument oDatabaseDocument = null;
oDatabaseDocument = null;
try {
Integer limit = AccessPath.UNBOUNDED;

View File

@ -7,7 +7,6 @@ import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.contexts.reference.entities.Context;
import org.gcube.informationsystem.queries.templates.reference.entities.QueryTemplate;
import org.gcube.informationsystem.resourceregistry.api.exceptions.AlreadyPresentException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
@ -16,21 +15,25 @@ import org.gcube.informationsystem.resourceregistry.api.exceptions.queries.Inval
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaViolationException;
import org.gcube.informationsystem.resourceregistry.contexts.security.QueryTemplatesSecurityContext;
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility;
import org.gcube.informationsystem.resourceregistry.instances.base.entities.EntityElementManagement;
import org.gcube.informationsystem.resourceregistry.queries.json.JsonQuery;
import org.gcube.informationsystem.resourceregistry.utils.Utility;
import org.gcube.informationsystem.types.reference.entities.EntityType;
import org.gcube.informationsystem.utils.ElementMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.record.OVertex;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.executor.OResult;
import com.orientechnologies.orient.core.sql.executor.OResultSet;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class QueryTemplateManagement extends EntityElementManagement<Context, EntityType> {
public class QueryTemplateManagement extends EntityElementManagement<QueryTemplate, EntityType> {
private static Logger logger = LoggerFactory.getLogger(QueryTemplateManagement.class);
@ -52,18 +55,36 @@ public class QueryTemplateManagement extends EntityElementManagement<Context, En
getOClass();
}
public void setName(String name) {
protected void checkNameMatch() throws ResourceRegistryException {
if(jsonNode!=null && name!=null) {
String jsonName = jsonNode.get(QueryTemplate.NAME_PROPERTY).asText();
if(name.compareTo(jsonName)!=0) {
String error = String.format(
"Name provided in json (%s) differs from the one (%s) used to identify the %s instance",
jsonName, name, typeName);
throw new ResourceRegistryException(error);
}
}
}
public void setName(String name) throws ResourceRegistryException {
this.name = name;
checkNameMatch();
}
protected void checkJsonNode() throws ResourceRegistryException {
super.checkJsonNode();
checkNameMatch();
}
public String getName() {
if (name == null) {
if (element == null) {
if (jsonNode != null) {
name = jsonNode.get(Context.NAME_PROPERTY).asText();
name = jsonNode.get(QueryTemplate.NAME_PROPERTY).asText();
}
} else {
name = element.getProperty(Context.NAME_PROPERTY);
name = element.getProperty(QueryTemplate.NAME_PROPERTY);
}
}
return name;
@ -83,7 +104,7 @@ public class QueryTemplateManagement extends EntityElementManagement<Context, En
return queryTemplate;
}
protected void checkIfNameAlreadyExists() throws AlreadyPresentException {
protected StringBuffer getSelectQuery() {
StringBuffer select = new StringBuffer();
select.append("SELECT FROM ");
select.append(QueryTemplate.NAME);
@ -93,6 +114,11 @@ public class QueryTemplateManagement extends EntityElementManagement<Context, En
select.append("\"");
select.append(getName());
select.append("\"");
return select;
}
protected void checkIfNameAlreadyExists() throws AlreadyPresentException {
StringBuffer select = getSelectQuery();
StringBuffer errorMessage = new StringBuffer();
errorMessage.append("A ");
@ -110,8 +136,47 @@ public class QueryTemplateManagement extends EntityElementManagement<Context, En
}
}
protected void tryTemplate() throws InvalidQueryException {
protected void tryTemplate() throws Exception {
QueryTemplate queryTemplate = ElementMapper.unmarshal(QueryTemplate.class, jsonNode.toString());
JsonNode jsonQueryNode = queryTemplate.getJsonQuery();
JsonQuery jsonQuery = new JsonQuery();
jsonQuery.setJsonQuery(jsonQueryNode);
try {
jsonQuery.query();
}catch (ResourceRegistryException e) {
throw e;
}catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
@Override
public OVertex retrieveElement() throws NotFoundException, ResourceRegistryException {
try {
StringBuffer select = getSelectQuery();
OResultSet resultSet = oDatabaseDocument.query(select.toString(), new HashMap<>());
if(resultSet == null || !resultSet.hasNext()) {
throw new NotFoundException("Error retrieving " + QueryTemplate.NAME + " with name " + getName());
}
OResult oResult = resultSet.next();
OVertex queryTemplate = ElementManagementUtility.getElementFromOptional(oResult.getVertex());
logger.trace("{} representing vertex is {}", QueryTemplate.NAME, Utility.toJsonString(queryTemplate, true));
if(resultSet.hasNext()) {
throw new NotFoundException("Found more than one " + QueryTemplate.NAME + " with name " + name + ". This should not occur, please contact the administrator");
}
return queryTemplate;
} catch(NotFoundException e) {
throw getSpecificNotFoundException(e);
} catch(ResourceRegistryException e) {
throw e;
} catch(Exception e) {
throw new ResourceRegistryException(e);
}
}
@Override
@ -198,17 +263,27 @@ public class QueryTemplateManagement extends EntityElementManagement<Context, En
}
public void setParams(JsonNode params) throws ResourceRegistryException {
// TODO checks here
this.params = params;
}
/**
* Run the query after having replaced query parameter with the provided values
* @return
* @throws Exception
*/
public String run() {
// TODO Auto-generated method stub
return null;
public String run() throws ResourceRegistryException {
try {
String read = read();
QueryTemplate queryTemplate = ElementMapper.unmarshal(QueryTemplate.class, read);
JsonNode jsonNode = queryTemplate.getJsonQuery(params);
JsonQuery jsonQuery = new JsonQuery();
jsonQuery.setJsonQuery(jsonNode);
return jsonQuery.query();
} catch (ResourceRegistryException e) {
throw e;
} catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
public void sanityCheck() throws SchemaViolationException, ResourceRegistryException {

View File

@ -9,6 +9,7 @@ import org.gcube.informationsystem.queries.templates.impl.entities.QueryTemplate
import org.gcube.informationsystem.queries.templates.impl.properties.TemplateVariableImpl;
import org.gcube.informationsystem.queries.templates.reference.entities.QueryTemplate;
import org.gcube.informationsystem.queries.templates.reference.properties.TemplateVariable;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.queries.JsonQueryTest;
import org.gcube.informationsystem.utils.ElementMapper;
import org.junit.Test;
@ -27,11 +28,11 @@ public class QueryTemplateManagementTest {
}
@Test
public void testCreate() throws Exception {
public void completeTest() throws Exception {
File queryTemplatesDirectory = getQueryTemplatesDirectory();
File jsonQueryTemaplateFile = new File(queryTemplatesDirectory, "queryTemplate" + 1 + ".json");
File jsonQueryTemplateFile = new File(queryTemplatesDirectory, "queryTemplate" + 1 + ".json");
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(jsonQueryTemaplateFile);
JsonNode jsonNode = objectMapper.readTree(jsonQueryTemplateFile);
String name = "Test";
@ -56,31 +57,73 @@ public class QueryTemplateManagementTest {
groupTemplateVariable.setName("$group");
groupTemplateVariable.setDescription("SoftwareFacet group");
groupTemplateVariable.setDefaultValue("information-system");
queryTemplate.addTemplateVariable(nameTemplateVariable);
queryTemplate.addTemplateVariable(groupTemplateVariable);
String json = ElementMapper.marshal(queryTemplate);
logger.info("Going to create {}: {}", QueryTemplate.NAME, json);
QueryTemplate gotQueryTemplate = ElementMapper.unmarshal(QueryTemplate.class, json);
logger.info("Going to create {} - {}", QueryTemplate.NAME, ElementMapper.marshal(gotQueryTemplate));
JsonNode gotTemplate = gotQueryTemplate.getTemplate();
logger.info("{}", gotTemplate.toString());
logger.info("Template is {}", gotTemplate.toString());
// QueryTemplateManagement queryTemplateManagement = new QueryTemplateManagement();
// queryTemplateManagement.setName("Test");
// queryTemplateManagement.setJson(json);
// String created = queryTemplateManagement.create();
// logger.debug(created);
}
@Test
public void testUpdate() {
}
@Test
public void testDelete() {
logger.info("Query template is {}.\nQuery with default values is {}", gotTemplate.toString(), queryTemplate.getJsonQuery().toString());
QueryTemplateManagement queryTemplateManagement = new QueryTemplateManagement();
queryTemplateManagement.setName(name);
queryTemplateManagement.setJson(json);
try {
String created = queryTemplateManagement.create();
logger.info("Created {} is {}", QueryTemplate.NAME, created);
queryTemplateManagement = new QueryTemplateManagement();
queryTemplateManagement.setName("Test");
String read = queryTemplateManagement.read();
QueryTemplate readQueryTemplate = ElementMapper.unmarshal(QueryTemplate.class, read);
logger.info("Read {} is {}", QueryTemplate.NAME, ElementMapper.marshal(readQueryTemplate));
gotTemplate = readQueryTemplate.getTemplate();
logger.info("Read Template is {}", gotTemplate.toString());
try {
readQueryTemplate.setName("AnotheName");
queryTemplateManagement = new QueryTemplateManagement();
queryTemplateManagement.setName(name);
queryTemplateManagement.setJson(ElementMapper.marshal(readQueryTemplate));
queryTemplateManagement.update();
throw new Exception("It should not be possibile to update the " + QueryTemplate.NAME + " with json name different from the name used to identify the instance");
}catch (ResourceRegistryException e) {
// OK
logger.debug("{}", e);
}
// Restoring correct name
readQueryTemplate.setName(name);
jsonQueryTemplateFile = new File(queryTemplatesDirectory, "queryTemplate" + 1 + "-bis.json");
jsonNode = objectMapper.readTree(jsonQueryTemplateFile);
readQueryTemplate.setTemplate(jsonNode);
queryTemplateManagement = new QueryTemplateManagement();
queryTemplateManagement.setName(name);
queryTemplateManagement.setJson(ElementMapper.marshal(readQueryTemplate));
String updatedString = queryTemplateManagement.update();
QueryTemplate updatedQueryTemplate = ElementMapper.unmarshal(QueryTemplate.class, updatedString);
logger.info("Updated {} is {}", QueryTemplate.NAME, ElementMapper.marshal(updatedQueryTemplate));
gotTemplate = updatedQueryTemplate.getTemplate();
logger.info("Updated Template is {}", gotTemplate.toString());
queryTemplateManagement = new QueryTemplateManagement();
queryTemplateManagement.setName(name);
// TODO Set Values
queryTemplateManagement.run();
}finally {
queryTemplateManagement.delete();
}
}
}

View File

@ -0,0 +1,23 @@
{
"@class": "EService",
"consistsOf": [
{
"@class": "ConsistsOf",
"propagationConstraint" : {
"add": "propagate"
},
"target": {
"@class": "StateFacet",
"value": "$state"
}
},
{
"@class": "IsIdentifiedBy",
"target": {
"@class": "SoftwareFacet",
"group": "$group",
"name": "$name"
}
}
]
}