From d606d319fa24d5035c90e86469ea5466533a119a Mon Sep 17 00:00:00 2001 From: Michael Hunger Date: Thu, 31 Mar 2011 14:08:26 +0200 Subject: [PATCH] GraphDatabase for RestGraphDatabase --- .../java/org/neo4j/kernel/RestConfig.java | 131 ++++++++++++++++++ .../data/graph/core/Property.java | 48 +++++++ .../support/DelegatingGraphDatabase.java | 110 +++++++++++++++ .../neo4j/support/LocalGraphDatabase.java | 83 ----------- 4 files changed, 289 insertions(+), 83 deletions(-) create mode 100644 spring-data-neo4j-rest/src/main/java/org/neo4j/kernel/RestConfig.java create mode 100644 spring-data-neo4j/src/main/java/org/springframework/data/graph/core/Property.java create mode 100644 spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java delete mode 100644 spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/LocalGraphDatabase.java diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/kernel/RestConfig.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/kernel/RestConfig.java new file mode 100644 index 000000000..e8008799a --- /dev/null +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/kernel/RestConfig.java @@ -0,0 +1,131 @@ +package org.neo4j.kernel; + +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.kernel.impl.core.*; +import org.neo4j.kernel.impl.nioneo.store.FileSystemAbstraction; +import org.neo4j.kernel.impl.nioneo.store.StoreId; +import org.neo4j.kernel.impl.transaction.LockManager; +import org.neo4j.kernel.impl.transaction.TxModule; +import org.neo4j.kernel.impl.transaction.xaframework.LogBufferFactory; +import org.neo4j.kernel.impl.transaction.xaframework.TxIdGenerator; +import org.neo4j.rest.graphdb.RestGraphDatabase; + +import javax.transaction.*; +import javax.transaction.xa.XAResource; +import java.util.Collections; +import java.util.Map; + +/** +* @author mh +* @since 23.02.11 +*/ +public class RestConfig extends Config { + public RestConfig(GraphDatabaseService graphDb, String storeDir, StoreId storeId, + Map inputParams, KernelPanicEventGenerator kpe, + TxModule txModule, LockManager lockManager, LockReleaser lockReleaser, + IdGeneratorFactory idGeneratorFactory, + TxEventSyncHookFactory txSyncHookFactory, RelationshipTypeCreator relTypeCreator, + TxIdGenerator txIdGenerator, LastCommittedTxIdSetter lastCommittedTxIdSetter, + FileSystemAbstraction fileSystem, LogBufferFactory logBufferFactory) { + super(graphDb, storeDir, storeId, + inputParams, kpe, txModule, lockManager, lockReleaser, idGeneratorFactory, txSyncHookFactory, relTypeCreator, txIdGenerator, lastCommittedTxIdSetter, fileSystem, logBufferFactory); + } + + public RestConfig(RestGraphDatabase restGraphDatabase) { + super(restGraphDatabase, restGraphDatabase.getStoreDir(), null, + Collections.emptyMap(),null, + new TxModule(true,null){ + @Override + public TransactionManager getTxManager() { + return new NullTransactionManager(); + } + }, + null,null, + null,null,null,null,null, + null,null); + } + + private static class NullTransactionManager implements TransactionManager { + private static final Transaction NULL_JAVA_TRANSACTION = new Transaction() { + @Override + public void commit() throws HeuristicMixedException, HeuristicRollbackException, RollbackException, SecurityException, SystemException { + + } + + @Override + public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException { + return false; + } + + @Override + public boolean enlistResource(XAResource xaResource) throws IllegalStateException, RollbackException, SystemException { + return false; + } + + @Override + public int getStatus() throws SystemException { + return Status.STATUS_NO_TRANSACTION; + } + + @Override + public void registerSynchronization(Synchronization synchronization) throws IllegalStateException, RollbackException, SystemException { + + } + + @Override + public void rollback() throws IllegalStateException, SystemException { + + } + + @Override + public void setRollbackOnly() throws IllegalStateException, SystemException { + + } + }; + + @Override + public void begin() throws NotSupportedException, SystemException { + + } + + @Override + public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException { + + } + + @Override + public int getStatus() throws SystemException { + return 0; + } + + @Override + public Transaction getTransaction() throws SystemException { + return NULL_JAVA_TRANSACTION; + } + + @Override + public void resume(Transaction transaction) throws IllegalStateException, InvalidTransactionException, SystemException { + + } + + @Override + public void rollback() throws IllegalStateException, SecurityException, SystemException { + + } + + @Override + public void setRollbackOnly() throws IllegalStateException, SystemException { + + } + + @Override + public void setTransactionTimeout(int i) throws SystemException { + + } + + @Override + public Transaction suspend() throws SystemException { + return NULL_JAVA_TRANSACTION; + } + } +} \ No newline at end of file diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/Property.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/Property.java new file mode 100644 index 000000000..06f0de6af --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/Property.java @@ -0,0 +1,48 @@ +package org.springframework.data.graph.core; + +import java.util.Map; + +/** + * @author mh + * @since 31.03.11 + */ +public class Property { + public final String name; + public final Object value; + + public Property(String name, Object value) { + this.name = name; + this.value = value; + } + + public static Property _(String name, Object value) { + return new Property(name, value); + } + + public static Property[] _(String name1, Object value1, String name2, Object value2) { + return new Property[]{new Property(name1, value1), new Property(name2, value2)}; + } + + public static Property[] _(String name1, Object value1, String name2, Object value2, String name3, Object value3) { + return new Property[]{new Property(name1, value1), new Property(name2, value2), new Property(name3, value3)}; + } + + public static Property[] _(Object... nameValuePairs) { + if (nameValuePairs.length % 2 != 0) + throw new IllegalArgumentException("there must be an even number of name value pairs"); + Property[] result = new Property[nameValuePairs.length / 2]; + for (int i = 0; i < result.length; i++) { + result[i] = new Property(nameValuePairs[i * 2].toString(), nameValuePairs[i * 2 + 1]); + } + return result; + } + + public static Property[] _(Map properties) { + Property[] result = new Property[properties.size()]; + int i = 0; + for (Map.Entry entry : properties.entrySet()) { + result[i++] = new Property(entry.getKey(), entry.getValue()); + } + return result; + } +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java new file mode 100644 index 000000000..e2d9a4e4d --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/DelegatingGraphDatabase.java @@ -0,0 +1,110 @@ +package org.springframework.data.graph.neo4j.support; + +import org.neo4j.graphdb.*; +import org.neo4j.graphdb.index.Index; +import org.neo4j.graphdb.index.IndexManager; +import org.neo4j.graphdb.traversal.TraversalDescription; +import org.neo4j.index.impl.lucene.LuceneIndexImplementation; +import org.neo4j.kernel.AbstractGraphDatabase; +import org.neo4j.kernel.Traversal; +import org.springframework.data.graph.core.GraphDatabase; +import org.springframework.data.graph.core.NodeBacked; +import org.springframework.data.graph.core.Property; +import org.springframework.data.graph.core.RelationshipBacked; + +import java.util.Map; + +/** + * @author mh + * @since 29.03.11 + */ +public class DelegatingGraphDatabase implements GraphDatabase { + + protected AbstractGraphDatabase delegate; + + public DelegatingGraphDatabase(final AbstractGraphDatabase delegate) { + this.delegate = delegate; + } + + @Override + public Node getReferenceNode() { + return delegate.getReferenceNode(); + } + + @Override + public Node getNodeById(long id) { + return delegate.getNodeById(id); + } + + @Override + public Node createNode(Property... props) { + return setProperties(delegate.createNode(), props); + } + + private T setProperties(T element, Property[] props) { + if (props==null || props.length==0) return element; + for (Property prop : props) { + element.setProperty(prop.name, prop.value); + } + return element; + } + + @Override + public Relationship getRelationshipById(long id) { + return delegate.getRelationshipById(id); + } + + @Override + public Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Property... props) { + return setProperties(startNode.createRelationshipTo(endNode,type),props); + } + + @Override + public Index getIndex(String indexName) { + IndexManager indexManager = delegate.index(); + if (indexManager.existsForNodes(indexName)) return (Index) indexManager.forNodes(indexName); + if (indexManager.existsForRelationships(indexName)) return (Index) indexManager.forRelationships(indexName); + throw new IllegalArgumentException("Index "+indexName+" does not exist."); + } + + // TODO handle existing indexes + @Override + public Index createIndex(Class type, String indexName, boolean fullText) { + IndexManager indexManager = delegate.index(); + if (isNode(type)) { + if (indexManager.existsForNodes(indexName)) + return (Index) checkAndGetExistingIndex(indexName, fullText, indexManager.forNodes(indexName)); + return (Index) indexManager.forNodes(indexName, indexConfigFor(fullText)); + } else { + if (indexManager.existsForRelationships(indexName)) + return (Index) checkAndGetExistingIndex(indexName, fullText, indexManager.forRelationships(indexName)); + return (Index) indexManager.forRelationships(indexName, indexConfigFor(fullText)); + } + } + + public boolean isNode(Class type) { + if (type.equals(Node.class)) return true; + if (type.equals(Relationship.class)) return false; + throw new IllegalArgumentException("Unknown Graph Primitive, neither Node nor Relationship"+type); + } + + private Index checkAndGetExistingIndex(final String indexName, boolean fullText, final Index index) { + Map existingConfig = delegate.index().getConfiguration(index); + Map config = indexConfigFor(fullText); + if (config.equals(existingConfig)) return index; + throw new IllegalArgumentException("Setup for index "+indexName+" does not match "+(fullText ? "fulltext":"exact")); + } + + private Map indexConfigFor(boolean fullText) { + return fullText ? LuceneIndexImplementation.FULLTEXT_CONFIG : LuceneIndexImplementation.EXACT_CONFIG; + } + + @Override + public TraversalDescription createTraversalDescription() { + return Traversal.description(); + } + + public void shutdown() { + delegate.shutdown(); + } +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/LocalGraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/LocalGraphDatabase.java deleted file mode 100644 index c61af0fa1..000000000 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/LocalGraphDatabase.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.springframework.data.graph.neo4j.support; - -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.PropertyContainer; -import org.neo4j.graphdb.Relationship; -import org.neo4j.graphdb.RelationshipType; -import org.neo4j.graphdb.index.Index; -import org.neo4j.graphdb.index.IndexManager; -import org.neo4j.graphdb.traversal.TraversalDescription; -import org.neo4j.index.impl.lucene.LuceneIndexImplementation; -import org.neo4j.kernel.EmbeddedGraphDatabase; -import org.neo4j.kernel.Traversal; -import org.springframework.data.graph.core.GraphDatabase; -import org.springframework.data.graph.core.NodeBacked; -import org.springframework.data.graph.core.RelationshipBacked; - -import java.io.File; -import java.util.Map; - -/** - * @author mh - * @since 29.03.11 - */ -public class LocalGraphDatabase implements GraphDatabase { - - protected EmbeddedGraphDatabase delegate; - - public LocalGraphDatabase(File file) { - delegate = new EmbeddedGraphDatabase(file.getAbsolutePath()); - } - - @Override - public Node getReferenceNode() { - return delegate.getReferenceNode(); - } - - @Override - public Node getNode(long id) { - return delegate.getNodeById(id); - } - - @Override - public Node createNode(Map props, String... indexFields) { - return null; - } - - @Override - public Relationship getRelationship(long id) { - return delegate.getRelationshipById(id); - } - - @Override - public Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map props, String... indexFields) { - return null; - } - - @Override - public Index getIndex(String indexName) { - IndexManager indexManager = delegate.index(); - if (indexManager.existsForNodes(indexName)) return (Index) indexManager.forNodes(indexName); - if (indexManager.existsForRelationships(indexName)) return (Index) indexManager.forRelationships(indexName); - throw new IllegalArgumentException("Index "+indexName+" does not exist."); - } - - // TODO handle existing indexes - @Override - public Index createIndex(Class type, String indexName, boolean fullText) { - IndexManager indexManager = delegate.index(); - Map config = fullText ? LuceneIndexImplementation.FULLTEXT_CONFIG : LuceneIndexImplementation.EXACT_CONFIG; - if (NodeBacked.class.isAssignableFrom(type)) return (Index) indexManager.forNodes(indexName, config); - if (RelationshipBacked.class.isAssignableFrom(type)) return (Index) indexManager.forRelationships(indexName, config); - throw new IllegalArgumentException("Wrong index type supplied "+type); - } - - @Override - public TraversalDescription createTraversalDescription() { - return Traversal.description(); - } - - public void shutdown() { - delegate.shutdown(); - } -}