package xdi2.messaging.container.impl.graph; import java.io.IOException; import java.util.Iterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import xdi2.core.ContextNode; import xdi2.core.Graph; import xdi2.core.features.equivalence.Equivalence; import xdi2.core.features.nodetypes.XdiAbstractContext; import xdi2.core.features.nodetypes.XdiContext; import xdi2.core.features.nodetypes.XdiPeerRoot; import xdi2.core.syntax.XDIAddress; import xdi2.core.syntax.XDIArc; import xdi2.core.syntax.XDIStatement; import xdi2.core.util.GraphUtil; import xdi2.core.util.iterators.MappingIterator; import xdi2.messaging.MessageEnvelope; import xdi2.messaging.container.AddressHandler; import xdi2.messaging.container.MessagingContainer; import xdi2.messaging.container.Prototype; import xdi2.messaging.container.StatementHandler; import xdi2.messaging.container.exceptions.Xdi2MessagingException; import xdi2.messaging.container.execution.ExecutionContext; import xdi2.messaging.container.execution.ExecutionResult; import xdi2.messaging.container.impl.AbstractMessagingContainer; /** * An XDI messaging container backed by some implementation of the Graph interface. * * @author markus */ public class GraphMessagingContainer extends AbstractMessagingContainer implements Prototype<GraphMessagingContainer> { private static final Logger log = LoggerFactory.getLogger(GraphMessagingContainer.class); private Graph graph; private GraphContextHandler graphContextHandler; public GraphMessagingContainer(Graph graph) { super(); this.graph = graph; this.graphContextHandler = new GraphContextHandler(graph); } public GraphMessagingContainer() { super(); this.graph = null; this.graphContextHandler = null; } @Override public void init() throws Exception { super.init(); } @Override public void shutdown() throws Exception { super.shutdown(); this.graph.close(); } @Override public XDIArc getOwnerPeerRootXDIArc() { return GraphUtil.getOwnerPeerRootXDIArc(this.getGraph()); } @Override public XDIAddress getOwnerXDIAddress() { return GraphUtil.getOwnerXDIAddress(this.getGraph()); } @Override public void setOwnerPeerRootXDIArc(XDIArc ownerPeerRootXDIArc) { GraphUtil.setOwnerPeerRootXDIArc(this.getGraph(), ownerPeerRootXDIArc); } @Override public void setOwnerXDIAddress(XDIAddress ownerXDIAddress) { GraphUtil.setOwnerXDIAddress(this.getGraph(), ownerXDIAddress); } @Override public boolean ownsPeerRootXDIArc(XDIArc peerRootXDIArc) { return GraphUtil.ownsPeerRootXDIArc(this.getGraph(), peerRootXDIArc); } @Override public boolean before(MessageEnvelope messageEnvelope, ExecutionContext executionContext, ExecutionResult executionResult) throws Xdi2MessagingException { this.graph.beginTransaction(); return super.before(messageEnvelope, executionContext, executionResult); } @Override public void after(MessageEnvelope messageEnvelope, ExecutionContext executionContext, ExecutionResult executionResult) throws Xdi2MessagingException { this.graph.commitTransaction(); super.after(messageEnvelope, executionContext, executionResult); } @Override public void exception(MessageEnvelope messageEnvelope, ExecutionContext executionContext, ExecutionResult executionResult, Xdi2MessagingException ex) throws Xdi2MessagingException { super.exception(messageEnvelope, executionContext, executionResult, ex); this.graph.rollbackTransaction(); } @Override public AddressHandler getAddressHandler(XDIAddress XDIaddress) throws Xdi2MessagingException { return this.graphContextHandler; } @Override public StatementHandler getStatementHandler(XDIStatement statement) throws Xdi2MessagingException { return this.graphContextHandler; } /* * Prototype */ @Override public GraphMessagingContainer instanceFor(PrototypingContext prototypingContext) throws Xdi2MessagingException { // create new messaging container MessagingContainer messagingContainer = new GraphMessagingContainer(); // instantiate new graph Graph graph; try { String identifier = XdiPeerRoot.createPeerRootXDIArc(prototypingContext.getOwnerXDIAddress()).toString(); graph = this.getGraph().getGraphFactory().openGraph(identifier); if (log.isDebugEnabled()) log.debug("Opened graph " + graph.getClass().getCanonicalName() + " for " + identifier); } catch (IOException ex) { throw new Xdi2MessagingException("Cannot open graph: " + ex.getMessage(), ex, null); } ((GraphMessagingContainer) messagingContainer).setGraph(graph); // done return (GraphMessagingContainer) messagingContainer; } /* * Convenience methods */ public static ContextNode getContextNode(Graph graph, XDIAddress XDIaddress) { ContextNode contextNode = graph.getRootContextNode(); for (XDIArc XDIarc : XDIaddress.getXDIArcs()) { contextNode = contextNode.getContextNode(XDIarc); if (contextNode == null) return null; while (true) { ContextNode referenceContextNode = Equivalence.getReferenceContextNode(contextNode); if (referenceContextNode != null) { contextNode = referenceContextNode; continue; } ContextNode replacementContextNode = Equivalence.getReplacementContextNode(contextNode); if (replacementContextNode != null) { contextNode = replacementContextNode; continue; } break; } } return contextNode; } @SuppressWarnings("unchecked") public static <T extends XdiContext<T>> XdiContext<T> getXdiContext(Graph graph, XDIAddress XDIaddress) { ContextNode contextNode = getContextNode(graph, XDIaddress); if (contextNode == null) return null; return (XdiContext<T>) XdiAbstractContext.fromContextNode(contextNode); } public static class MappingXDIAddressContextNodeIterator extends MappingIterator<XDIAddress, ContextNode> { private Graph graph; public MappingXDIAddressContextNodeIterator(Graph graph, Iterator<XDIAddress> XDIaddresses) { super(XDIaddresses); this.graph = graph; } @Override public ContextNode map(XDIAddress XDIaddress) { return GraphMessagingContainer.getContextNode(this.graph, XDIaddress); } } public static class MappingXDIAddressXdiContextIterator<T extends XdiContext<T>> extends MappingIterator<XDIAddress, XdiContext<T>> { private Graph graph; public MappingXDIAddressXdiContextIterator(Graph graph, Iterator<XDIAddress> XDIaddresses) { super(XDIaddresses); this.graph = graph; } @Override public XdiContext<T> map(XDIAddress XDIaddress) { return GraphMessagingContainer.getXdiContext(this.graph, XDIaddress); } } /* * Getters and setters */ public Graph getGraph() { return this.graph; } public void setGraph(Graph graph) { this.graph = graph; this.graphContextHandler = new GraphContextHandler(graph); } }