Search in sources :

Example 1 with TypeToken

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;
}
Also used : StructrApp(org.structr.core.app.StructrApp) App(org.structr.core.app.App) FrameworkException(org.structr.common.error.FrameworkException) PropertiesNotFoundToken(org.structr.common.error.PropertiesNotFoundToken) PropertyMap(org.structr.core.property.PropertyMap) TypeToken(org.structr.common.error.TypeToken) PropertyMap(org.structr.core.property.PropertyMap)

Example 2 with TypeToken

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;
}
Also used : StructrApp(org.structr.core.app.StructrApp) App(org.structr.core.app.App) FrameworkException(org.structr.common.error.FrameworkException) HashMap(java.util.HashMap) GraphObject(org.structr.core.GraphObject) EntityAndPropertiesContainer(org.structr.common.EntityAndPropertiesContainer) Relation(org.structr.core.entity.Relation) PropertyMap(org.structr.core.property.PropertyMap) TypeToken(org.structr.common.error.TypeToken) GraphObject(org.structr.core.GraphObject) HashMap(java.util.HashMap) PropertyMap(org.structr.core.property.PropertyMap) Map(java.util.Map) PropertyKey(org.structr.core.property.PropertyKey)

Aggregations

FrameworkException (org.structr.common.error.FrameworkException)2 TypeToken (org.structr.common.error.TypeToken)2 App (org.structr.core.app.App)2 StructrApp (org.structr.core.app.StructrApp)2 PropertyMap (org.structr.core.property.PropertyMap)2 HashMap (java.util.HashMap)1 Map (java.util.Map)1 EntityAndPropertiesContainer (org.structr.common.EntityAndPropertiesContainer)1 PropertiesNotFoundToken (org.structr.common.error.PropertiesNotFoundToken)1 GraphObject (org.structr.core.GraphObject)1 Relation (org.structr.core.entity.Relation)1 PropertyKey (org.structr.core.property.PropertyKey)1