+package org.simantics.document.ui.graphfile;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.document.DocumentResource;\r
+import org.simantics.layer0.Layer0;\r
+/**\r
+ * Util class for managing document versions\r
+ * \r
+ * Document version history mode is searched with relations:\r
+ * 1. l0.PartOf\r
+ * 2. l0.IsOwnedBy\r
+ * 3. l0.IsDependencyOf \r
+ * \r
+ * If library is not found, history mode is assumed to be flat.\r
+ * \r
+ * In order to have working tree history, the library must contain proper configuration for relations:\r
+ * doc.HasLibraryRelation\r
+ * doc.HasVersionType\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class DocumentVersionUtils {\r
+\r
+ public enum VersionMode{FLAT,TREE};\r
+ \r
+ \r
+ /**\r
+ * Adds a new document version.\r
+ * \r
+ * Expects that newDocument is not part of document version chain, and oldDocument does not have newer version.\r
+ * \r
+ * @param graph\r
+ * @param oldDocument\r
+ * @param newDocument\r
+ * @param relation\r
+ * @throws DatabaseException\r
+ */\r
+ public static void createNewVersion(WriteGraph graph, Resource oldDocument, Resource newDocument, Resource relation) throws DatabaseException{\r
+ DocumentResource doc = DocumentResource.getInstance(graph);\r
+ if (graph.hasStatement(oldDocument, doc.HasNewerVersion))\r
+ throw new DatabaseException("Document " + NameUtils.getSafeName(graph, oldDocument) +" has already new version");\r
+ \r
+ Resource inverse = graph.getInverse(relation);\r
+ Resource lib = graph.getSingleObject(oldDocument, inverse);\r
+ String modeString = graph.getPossibleRelatedValue(lib, doc.HasVersionType);\r
+ VersionMode mode = VersionMode.FLAT;\r
+ if (modeString != null)\r
+ mode = VersionMode.valueOf(modeString);\r
+ \r
+ graph.claim(oldDocument, doc.HasNewerVersion, newDocument);\r
+ graph.claim(lib, relation, newDocument);\r
+ \r
+ if (mode == VersionMode.TREE) {\r
+ graph.deny(lib,relation,oldDocument);\r
+ graph.claim(newDocument,relation,oldDocument);\r
+ }\r
+ FileDocumentUtil.createUniqueName(graph, newDocument);\r
+ }\r
+ \r
+ /**\r
+ * Sets document version relationship between two documents. \r
+ * \r
+ * If the documents are already part of the same version chain this method does nothing.\r
+ * \r
+ * If documents are already set to some version chain with given relation, this method replaces the exiting links.\r
+ * \r
+ * @param graph\r
+ * @param document1\r
+ * @param document2\r
+ * @param versionRel\r
+ * @throws DatabaseException\r
+ */\r
+ public static void setVersion(WriteGraph graph, Resource document1, Resource document2, Resource versionRel) throws DatabaseException {\r
+ DocumentResource doc = DocumentResource.getInstance(graph);\r
+ // document type must match\r
+ if (!graph.getSingleType(document2, doc.Document).equals(graph.getSingleType(document1, doc.Document)))\r
+ return;\r
+ if (!versionRel.equals(doc.HasNewerVersion) && !(versionRel.equals(doc.HasOlderVersion)))\r
+ throw new IllegalArgumentException("Unknow version relation + " + graph.getPossibleURI(versionRel));\r
+ \r
+ Resource versionRelInv = graph.getInverse(versionRel);\r
+ // toSet must not be part of the document's version history\r
+ Resource r = document1;\r
+ while (r != null) {\r
+ if (r.equals(document2))\r
+ return;\r
+ r = graph.getPossibleObject(r, versionRel);\r
+ }\r
+ \r
+ r = document2;\r
+ while (r != null) {\r
+ if (r.equals(document1))\r
+ return;\r
+ r = graph.getPossibleObject(r, versionRel);\r
+ }\r
+ // At the moment document revision history is linear (no branching).\r
+ Resource document1Ver = graph.getPossibleObject(document1, versionRel);\r
+ if (document1Ver != null)\r
+ unsetVersion(graph, document1, document1Ver, versionRel);\r
+ Resource document2Ver = graph.getPossibleObject(document2, versionRelInv);\r
+ if (document2Ver != null)\r
+ unsetVersion(graph, document2, document2Ver, versionRelInv);\r
+ \r
+ graph.claim(document1, versionRel, document2);\r
+ \r
+ Resource lib = getLib(graph, document1);\r
+ if (lib != null) {\r
+ Resource relation = graph.getPossibleObject(lib, doc.HasLibraryRelation);\r
+ String type= graph.getPossibleRelatedValue(lib, doc.HasVersionType);\r
+ if ("TREE".equals(type) && relation != null) {\r
+ if (versionRel.equals(doc.HasOlderVersion)) {\r
+ graph.deny(document2, graph.getInverse(relation));\r
+ graph.claim(document1,relation,document2);\r
+ } else {\r
+ graph.deny(document1, graph.getInverse(relation));\r
+ graph.claim(document2,relation,document1);\r
+ }\r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Unlinks document version relationship between two documents. \r
+ * @param graph\r
+ * @param document1\r
+ * @param document2\r
+ * @param versionRel\r
+ * @throws DatabaseException\r
+ */\r
+ public static void unsetVersion(WriteGraph graph, Resource document1, Resource document2, Resource versionRel) throws DatabaseException {\r
+ DocumentResource doc = DocumentResource.getInstance(graph);\r
+ if (!versionRel.equals(doc.HasNewerVersion) && !(versionRel.equals(doc.HasOlderVersion)))\r
+ throw new IllegalArgumentException("Unknow version relation + " + graph.getPossibleURI(versionRel));\r
+ \r
+ graph.deny(document1, versionRel,document2);\r
+ Resource lib = getLib(graph, document1);\r
+ if (lib != null) {\r
+ Resource relation = graph.getPossibleObject(lib, doc.HasLibraryRelation);\r
+ String type= graph.getPossibleRelatedValue(lib, doc.HasVersionType);\r
+ if ("TREE".equals(type) && relation != null) {\r
+ if (versionRel.equals(doc.HasOlderVersion)) {\r
+ graph.deny(document1, relation);\r
+ graph.claim(lib,relation,document2);\r
+ FileDocumentUtil.createUniqueName(graph, document2);\r
+ } else {\r
+ graph.deny(document1, graph.getInverse(relation));\r
+ graph.claim(lib,relation,document1);\r
+ FileDocumentUtil.createUniqueName(graph, document1);\r
+ }\r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ private static Resource getLib(ReadGraph graph, Resource document) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ DocumentResource doc = DocumentResource.getInstance(graph);\r
+ Resource r = document;\r
+ while (true) {\r
+ Resource lib = graph.getPossibleObject(r, l0.PartOf);\r
+ if (lib == null)\r
+ lib = graph.getPossibleObject(r, l0.IsOwnedBy);\r
+ if (lib == null)\r
+ lib = graph.getPossibleObject(r, l0.IsDependencyOf);\r
+ if (lib == null)\r
+ return null;\r
+ if (!graph.isInstanceOf(lib, doc.Document))\r
+ return lib;\r
+ r = lib;\r
+ }\r
+ }\r
+}\r