package org.ff4j.neo4j.store; /* * #%L * ff4j-store-neo4j * %% * Copyright (C) 2013 - 2016 FF4J * %% * 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. * #L% */ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.ff4j.exception.PropertyAlreadyExistException; import org.ff4j.neo4j.FF4jNeo4jLabels; import org.ff4j.neo4j.mapper.Neo4jMapper; import org.ff4j.property.Property; import org.ff4j.property.store.AbstractPropertyStore; import org.ff4j.property.store.PropertyStore; import org.ff4j.utils.Util; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Result; import org.neo4j.graphdb.Transaction; import static org.ff4j.neo4j.FF4jNeo4jConstants.*; /** *Implementation of {@link PropertyStore} to work with Neo4J. * * @author Cedrick Lunven (@clunven)</a> */ public class PropertyStoreNeo4j extends AbstractPropertyStore { /** Persistent storage. */ private GraphDatabaseService graphDb; /** * Default to create instances. */ public PropertyStoreNeo4j() {} /** * Initialization of store. */ public PropertyStoreNeo4j(GraphDatabaseService myDb) { this.graphDb = myDb; } /** {@inheritDoc} */ public boolean existProperty(String name) { Util.assertHasLength(name); Map < String, Object > queryParameters = new HashMap<>(); queryParameters.put("name", name); Result result = graphDb.execute(QUERY_CYPHER_EXISTS_PROPERTY, queryParameters); Object count = null; if (result.hasNext()) { count = result.next().get(QUERY_CYPHER_ALIAS); } return (null != count) && (((long) count) > 0); } /** {@inheritDoc} */ public <T> void createProperty(Property<T> ap) { Util.assertNotNull(ap); Util.assertHasLength(ap.getName()); if (existProperty(ap.getName())) { throw new PropertyAlreadyExistException(ap.getName()); } StringBuilder cypherCreate = new StringBuilder(); cypherCreate.append("CREATE (p:" + FF4jNeo4jLabels.FF4J_PROPERTY + " { name :'"); cypherCreate.append(ap.getName()); cypherCreate.append("', type:'"); cypherCreate.append(ap.getType()); cypherCreate.append("', value:'"); cypherCreate.append(ap.getValue()); cypherCreate.append("', fixedValues:["); if (ap.getFixedValues() != null && !ap.getFixedValues().isEmpty()) { boolean first = true; for (Object fix : ap.getFixedValues()) { if (!first) { cypherCreate.append(","); } cypherCreate.append("'" + fix.toString() + "'"); first = false; } } cypherCreate.append("]"); if (ap.getDescription() != null && ap.getDescription().length() > 0) { cypherCreate.append(", description:'"); cypherCreate.append(ap.getDescription()); cypherCreate.append("'"); } cypherCreate.append("});"); Transaction tx = graphDb.beginTx(); graphDb.execute(cypherCreate.toString()); tx.success(); } /** {@inheritDoc} */ public Property<?> readProperty(String name) { assertPropertyExist(name); Property<?> pro; Transaction tx = graphDb.beginTx(); Map<String, Object> queryParameters = new HashMap<>(); queryParameters.put("name", name); Result result = graphDb.execute(QUERY_CYPHER_READ_PROPERTY, queryParameters); // Property must exist (existProperty executed before) : no JNPE here nor hasNext() tested Node node = (Node) result.next().get("p"); pro = Neo4jMapper.fromNode2Property(node); tx.success(); return pro; } /** {@inheritDoc} */ public void updateProperty(String name, String newValue) { assertPropertyExist(name); // Check new value validity readProperty(name).fromString(newValue); Transaction tx = graphDb.beginTx(); Map<String, Object> queryParameters = new HashMap<>(); queryParameters.put("name", name); queryParameters.put("value", newValue); graphDb.execute(QUERY_CYPHER_UPDATE_PROPERTYVALUE, queryParameters); tx.success(); } /** {@inheritDoc} */ public <T> void updateProperty(Property<T> prop) { Util.assertNotNull(prop); // Delete deleteProperty(prop.getName()); // Create createProperty(prop); } /** {@inheritDoc} */ public void deleteProperty(String name) { assertPropertyExist(name); Map<String, Object> paramUID = new HashMap<>(); paramUID.put("name", name); Transaction tx = graphDb.beginTx(); // Delete feature graphDb.execute(QUERY_CYPHER_DELETE_PROPERTY, paramUID); tx.success(); } /** {@inheritDoc} */ public Map<String, Property<?>> readAllProperties() { Map<String, Property<?>> allProperties = new HashMap<>(); Transaction tx = graphDb.beginTx(); // Node with relationships Result result = graphDb.execute(QUERY_CYPHER_READ_ALLPROPERTIES); while (result.hasNext()) { Node node = (Node) result.next().get("p"); Property<?> current = Neo4jMapper.fromNode2Property(node); allProperties.put(current.getName(), current); } tx.success(); return allProperties; } /** {@inheritDoc} */ public Set<String> listPropertyNames() { Result result = graphDb.execute(QUERY_READ_PROPERTYNAMES); Set < String > response = new HashSet<>(); while (result.hasNext()) { response.add((String) result.next().get("NAME")); } return response; } /** {@inheritDoc} */ public void clear() { Transaction tx = graphDb.beginTx(); graphDb.execute(QUERY_CYPHER_DELETE_ALLPROPERTY); tx.success(); } /** * Getter accessor for attribute 'graphDb'. * * @return * current value of 'graphDb' */ public GraphDatabaseService getGraphDb() { return graphDb; } /** * Setter accessor for attribute 'graphDb'. * @param graphDb * new value for 'graphDb ' */ public void setGraphDb(GraphDatabaseService graphDb) { this.graphDb = graphDb; } /** {@inheritDoc} */ @Override public void createSchema() { // TODO Auto-generated method stub } }