Package org.springframework.data.neo4j.fieldaccess

Source Code of org.springframework.data.neo4j.fieldaccess.QueryFieldAccessorFactory$QueryFieldAccessor

/**
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.data.neo4j.fieldaccess;

import org.neo4j.graphdb.Node;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.mapping.MappingPolicy;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.query.CypherQueryEngine;
import org.springframework.data.util.TypeInformation;

import java.util.HashMap;
import java.util.Map;

import static org.springframework.data.neo4j.support.DoReturn.doReturn;

public class QueryFieldAccessorFactory implements FieldAccessorFactory {
    private final Neo4jTemplate template;

    public QueryFieldAccessorFactory(Neo4jTemplate template) {
        this.template = template;
    }

    @Override
    public boolean accept(final Neo4jPersistentProperty property) {
        return property.hasQuery();
    }


    @Override
    public FieldAccessor forField(final Neo4jPersistentProperty property) {
        return new QueryFieldAccessor(property, template);
    }

  /**
   * @author Michael Hunger
   * @since 12.09.2010
   */
  public static class QueryFieldAccessor implements FieldAccessor {
      protected final Neo4jPersistentProperty property;
        private final Neo4jTemplate template;
        private final String query;
      private Class<?> target;
        protected String[] annotationParams;
        private boolean iterableResult;
        private final CypherQueryEngine queryEngine;

        public QueryFieldAccessor(final Neo4jPersistentProperty property, Neo4jTemplate template) {
          this.property = property;
            this.template = template;
            final Query query = property.findAnnotation(Query.class);
            this.annotationParams = query.params();
            if ((this.annotationParams.length % 2) != 0) {
                throw new IllegalArgumentException("Number of parameters has to be even to construct a parameter map");
            }
            this.query = property.getQuery();
            this.iterableResult = Iterable.class.isAssignableFrom(property.getType());
            this.target = resolveTarget(query,property);
            queryEngine = this.template.queryEngineFor();
        }

        private Class<?> resolveTarget(Query query, Neo4jPersistentProperty property) {
            if (!query.elementClass().equals(Object.class)) return query.elementClass();
            return property.getTypeInformation().getActualType().getType();
        }

        @Override
      public boolean isWriteable(Object entity) {
          return false;
      }

      @Override
      public Object setValue(final Object entity, final Object newVal, MappingPolicy mappingPolicy) {
          throw new InvalidDataAccessApiUsageException("Cannot set readonly query field " + property);
      }

      @Override
      public Object getValue(final Object entity, MappingPolicy mappingPolicy) {
            return doReturn(executeQuery(entity, this.query, createPlaceholderParams(entity),mappingPolicy));
      }

        private Object executeQuery(Object entity, String queryString, Map<String, Object> params, MappingPolicy mappingPolicy) {
            final TypeInformation<?> typeInformation = property.getTypeInformation();
            final TypeInformation<?> actualType = typeInformation.getActualType();
            final Class<?> targetType = actualType.getType();
            final Result<Map<String, Object>> result = queryEngine.query(queryString, params).with(mappingPolicy);
            if (actualType.isMap()) {
                return result;
            }

            if (typeInformation.isCollectionLike()) {
                Class<? extends Iterable> collectionType = (Class<? extends Iterable>) typeInformation.getType();
                return result.to(targetType).as(collectionType);
            }
            return result.to(targetType).singleOrNull();
        }

        private Map<String, Object> createPlaceholderParams(Object entity) {
            Map<String,Object> params=new HashMap<String, Object>();
            final Node startNode = template.<Node>getPersistentState(entity);
            params.put("self", startNode.getId());
            if (annotationParams.length==0) return params;
            for (int i = 0; i < annotationParams.length; i+=2) {
                params.put(annotationParams[i],annotationParams[i+1]);
            }
            return params;
        }

    @Override
    public Object getDefaultValue() {
      return null;
    }
    }
}
TOP

Related Classes of org.springframework.data.neo4j.fieldaccess.QueryFieldAccessorFactory$QueryFieldAccessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.