use of org.structr.common.error.TypeToken in project structr by structr.
the class TypeAndValueDeserializationStrategy method deserialize.
@Override
public T deserialize(final SecurityContext securityContext, Class<T> type, S source, final Object context) throws FrameworkException {
final App app = StructrApp.getInstance(securityContext);
Result<T> result = Result.EMPTY_RESULT;
// default to UUID
if (propertyKey == null) {
propertyKey = GraphObject.id;
}
// create and fill input map with source object
Map<String, Object> sourceMap = new LinkedHashMap<>();
sourceMap.put(propertyKey.jsonName(), source);
// try to convert input type to java type in order to create object correctly
PropertyMap convertedSourceMap = PropertyMap.inputTypeToJavaType(securityContext, type, sourceMap);
Object convertedSource = convertedSourceMap.get(propertyKey);
if (convertedSource != null) {
// FIXME: use uuid only here?
if (convertedSource instanceof Map) {
Object value = ((Map<String, Object>) convertedSource).get(propertyKey.jsonName());
if (value != null) {
result = app.nodeQuery(type).and(propertyKey, value.toString()).getResult();
}
} else if (convertedSource instanceof GraphObject) {
final GraphObject obj = (GraphObject) convertedSource;
result = app.nodeQuery(type).and(propertyKey, obj.getProperty(propertyKey)).getResult();
} else {
result = app.nodeQuery(type).and(propertyKey, convertedSource).getResult();
}
}
// just check for existance
int resultCount = result.size();
switch(resultCount) {
case 0:
if ((convertedSource != null) && createIfNotExisting) {
// create node and return it
T newNode = app.create(type);
if (newNode != null) {
newNode.setProperty(propertyKey, convertedSource);
return newNode;
}
} else {
logger.warn("Unable to create node of type {} for property {}", new Object[] { type.getSimpleName(), propertyKey.jsonName() });
}
break;
case 1:
T obj = result.get(0);
// if(!type.getSimpleName().equals(node.getType())) {
if (!type.isAssignableFrom(obj.getClass())) {
throw new FrameworkException(422, "Node type mismatch", new TypeToken(obj.getClass(), propertyKey, type.getSimpleName()));
}
if (!convertedSourceMap.isEmpty()) {
// set properties on related node?
setProperties(securityContext, obj, convertedSourceMap);
}
return obj;
}
if (convertedSource != null) {
PropertyMap attributes = new PropertyMap();
attributes.put(propertyKey, convertedSource);
attributes.put(AbstractNode.type, type.getSimpleName());
throw new FrameworkException(404, "No node found for given properties", new PropertiesNotFoundToken(type.getSimpleName(), null, attributes));
}
return null;
}
use of org.structr.common.error.TypeToken in project structr by structr.
the class IdDeserializationStrategy method deserialize.
@Override
public T deserialize(final SecurityContext securityContext, final Class<T> type, final S source, final Object context) throws FrameworkException {
final App app = StructrApp.getInstance(securityContext);
if (source != null) {
if (source instanceof Map) {
final Map<String, Object> properties = (Map<String, Object>) source;
Class<T> actualType = type;
if (actualType != null && actualType.isInterface()) {
// (creation wouldn't work otherwise anyway)
if (properties.containsKey(NodeInterface.type.jsonName())) {
final String typeFromInput = properties.get(NodeInterface.type.jsonName()).toString();
actualType = StructrApp.getConfiguration().getNodeEntityClass(typeFromInput);
// reset type on failed check
if (actualType == null) {
actualType = type;
}
}
}
final PropertyMap convertedProperties = PropertyMap.inputTypeToJavaType(securityContext, actualType, properties);
final Set<PropertyKey> allProperties = StructrApp.getConfiguration().getPropertySet(type, "all");
final Map<String, Object> foreignProps = new HashMap<>();
T relatedNode = null;
// If property map contains the uuid, search only for uuid
if (convertedProperties.containsKey(GraphObject.id)) {
relatedNode = (T) app.getNodeById(convertedProperties.get(GraphObject.id));
if (relatedNode != null) {
if (!SearchCommand.isTypeAssignableFromOtherType(type, relatedNode.getClass())) {
throw new FrameworkException(422, "Node type mismatch", new TypeToken(type.getSimpleName(), null, type.getSimpleName()));
}
for (final PropertyKey key : convertedProperties.keySet()) {
if (!key.isUnique() && !key.isCompound() && !isIdentifying(actualType, key) && !allProperties.contains(key)) {
// store "foreign" properties (those that are to be set on the newly created relationship
foreignProps.put(key.jsonName(), properties.get(key.jsonName()));
}
}
// node found, remove UUID
convertedProperties.remove(GraphObject.id);
}
} else {
final PropertyMap uniqueKeyValues = new PropertyMap();
for (final PropertyKey key : convertedProperties.keySet()) {
if (key.isUnique() || key.isCompound() || isIdentifying(actualType, key)) {
uniqueKeyValues.put(key, convertedProperties.get(key));
} else if (!allProperties.contains(key)) {
// store "foreign" properties (those that are to be set on the newly created relationship
foreignProps.put(key.jsonName(), properties.get(key.jsonName()));
}
}
// (this is quite similar to the Cypher MERGE command),
if (!uniqueKeyValues.isEmpty()) {
final List<T> possibleResults = app.nodeQuery(type).and(uniqueKeyValues).getAsList();
final int num = possibleResults.size();
switch(num) {
case 0:
// not found => will be created
break;
case 1:
relatedNode = possibleResults.get(0);
break;
default:
// more than one => not unique??
throw new FrameworkException(422, concat("Unable to resolve related node of type ", type.getSimpleName(), ", ambiguous result: found ", num, " nodes for the given property set."));
}
} else {
// throw exception here?
}
}
if (relatedNode == null) {
// no related node found, should we create one?
if (relationProperty != null) {
final Relation relation = relationProperty.getRelation();
if (relationProperty.doAutocreate()) {
return app.create(type, convertedProperties);
} else {
throw new FrameworkException(422, concat("Cannot create ", relation.getOtherType(type).getSimpleName(), ": no matching ", type.getSimpleName(), " found for the given property set ", convertedProperties, " and autoCreate has a value of ", relationProperty.getAutocreateFlagName()));
}
}
// FIXME: when can the relationProperty be null at all?
throw new FrameworkException(500, concat("Unable to resolve related node of type ", type.getSimpleName(), ", no relation defined."));
} else {
// set properties on related node?
if (!convertedProperties.isEmpty()) {
setProperties(securityContext, relatedNode, convertedProperties);
}
if (foreignProps.isEmpty()) {
return relatedNode;
} else {
return (T) new EntityAndPropertiesContainer(relatedNode, foreignProps);
}
}
} else if (type.isAssignableFrom(source.getClass())) {
return (T) source;
} else {
// interpret source as a raw ID string and fetch entity
final GraphObject obj = app.getNodeById(source.toString());
if (obj != null && !type.isAssignableFrom(obj.getClass())) {
throw new FrameworkException(422, "Node type mismatch", new TypeToken(obj.getClass().getSimpleName(), null, type.getSimpleName()));
}
return (T) obj;
}
}
return null;
}
Aggregations