]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.project/src/org/simantics/project/management/GraphBundle.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / GraphBundle.java
diff --git a/bundles/org.simantics.project/src/org/simantics/project/management/GraphBundle.java b/bundles/org.simantics.project/src/org/simantics/project/management/GraphBundle.java
new file mode 100644 (file)
index 0000000..c428b7f
--- /dev/null
@@ -0,0 +1,309 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.project.management;\r
+\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.binding.error.RuntimeBindingException;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ResourceRead;\r
+import org.simantics.db.common.utils.Transaction;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.graph.representation.TransferableGraph1;\r
+import org.simantics.layer0.DatabaseManagementResource;\r
+\r
+/**\r
+ * GraphBundle represents a bundle graph that may exist in memory \r
+ * in a OSGi Bundle Context, a P2 Bundle Pool, or in Simantics Database.\r
+ * \r
+ * The string representation of the version is in the following format: \r
+ *   <id>/<major.minor.micro(.qualifier)>\r
+ * \r
+ * Here is what is said about osgi version numbers:\r
+ * \r
+ *  Major - Differences in the major part indicate significant differences \r
+ *          such that backward compability is not guaranteed.\r
+ *          \r
+ *  Minor - Changes in the minor part indicate that the newer version of the\r
+ *          entity is backward compatible with the older version, but it \r
+ *          includes additional functionality and/or API.\r
+ *     \r
+ *  Service - The service part indicates the presence of bug fixes and minor\r
+ *          implementation (i.e., hidden) changes over previous versions.\r
+ *  \r
+ *  Qualifier - The qualifier is not interpreted by the system. Qualifiers are\r
+ *           compared using standard string comparison. Qualifier is determined\r
+ *           at build time by builder. It may be millisecond time or version \r
+ *           control revision number. The value is monotonically increasing. \r
+ *           \r
+ *   \r
+ * The class is hash-equals-comparable.\r
+ *\r
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
+ */\r
+public class GraphBundle implements Comparable<GraphBundle> {\r
+\r
+       /** Versioned Id pattern */     \r
+       static String ID_PATTERN_STRING =                "[a-zA-Z_0-9\\-]+(?:\\.[a-zA-Z_0-9\\-]+)*";\r
+       static String VERSION_PATTERN_STRING =           "(\\d+).(\\d+).(\\d+).([a-zA-Z_0-9\\-]+)";\r
+       static Pattern ID_PATTERN = Pattern.compile(ID_PATTERN_STRING);\r
+       static Pattern VERSION_PATTERN = Pattern.compile(VERSION_PATTERN_STRING);\r
+       static Pattern VERSIONED_ID_PATTERN = Pattern.compile("(" + ID_PATTERN_STRING + ")/" + VERSION_PATTERN_STRING + "");\r
+               \r
+       /** User-friendly name */\r
+       String name;\r
+       \r
+       /** Actual graph */\r
+       TransferableGraph1 graph;\r
+       \r
+       /** GraphBundle resource in database */ \r
+       Resource resource;\r
+       \r
+       /** Graph hash code */\r
+       int hashcode;\r
+       \r
+       /** Id */\r
+       String id;\r
+       \r
+       // Version\r
+       int major, minor, service;\r
+       \r
+       // Optional qualifier\r
+       String qualifier;\r
+       \r
+       /** Database install Info, optional */\r
+       long[] resourceArray;\r
+\r
+       /** Should this ontology be installed immutable **/\r
+       boolean immutable = true;\r
+\r
+       GraphBundle() {}\r
+       \r
+       public GraphBundle(String name, TransferableGraph1 data, String versionedId) \r
+       throws RuntimeBindingException {                \r
+               try {                   \r
+                       // Assert version id is correct\r
+                       Matcher m = VERSIONED_ID_PATTERN.matcher(versionedId); \r
+                       if (!m.matches()) {\r
+                               throw new IllegalArgumentException("Illegal VersionId \""+versionedId+"\", <id>/<major.minor.micro.qualifier> is expected.");\r
+                       }\r
+                       \r
+                       Binding binding = Bindings.getBindingUnchecked( TransferableGraph1.class );             \r
+                       \r
+                       this.name = name;\r
+                       this.graph = data;              \r
+                       this.hashcode = data != null ? binding.hashValue( data ) : 0;\r
+                       this.id = m.group(1);\r
+                       this.major = Integer.valueOf( m.group(2) );\r
+                       this.minor = Integer.valueOf( m.group(3) );\r
+                       if (m.group(4) != null) {\r
+                               this.service = Integer.valueOf( m.group(4) );\r
+                       }\r
+                       this.qualifier = m.group(5);\r
+               } catch (BindingException e) {\r
+                       // Unexpected\r
+                       throw new RuntimeBindingException(e);\r
+               }                       \r
+       }\r
+       \r
+       public GraphBundle(String name, TransferableGraph1 data, String id, String version) \r
+       throws RuntimeBindingException {                \r
+               Matcher m = ID_PATTERN.matcher(id);\r
+               if (!m.matches()) \r
+                       throw new IllegalArgumentException("Illegal Id, got \""+id+"\"");\r
+               m = VERSION_PATTERN.matcher(version);\r
+               if (!m.matches()) \r
+                       throw new IllegalArgumentException("Illegal Version, got \""+id+"\", <id>/<major.minor.micro.qualifier> is expected.");\r
+               try {                   \r
+                       Binding binding = Bindings.getBindingUnchecked( TransferableGraph1.class );             \r
+                       this.name = name;\r
+                       this.graph = data;              \r
+                       this.hashcode = binding.hashValue( data );\r
+                       this.id = id;\r
+                       this.major = Integer.valueOf( m.group(1) );\r
+                       this.minor = Integer.valueOf( m.group(2) );\r
+                       this.service = Integer.valueOf( m.group(3) );\r
+                       if (m.group(4) != null) {\r
+                               this.qualifier = m.group(4);\r
+                       }\r
+               } catch (BindingException e) {\r
+                       // Unexpected\r
+                       throw new RuntimeBindingException(e);\r
+               }\r
+       }\r
+       \r
+       public String getName() {\r
+               return name;\r
+       }\r
+\r
+       @Override\r
+       public int compareTo(GraphBundle o) {\r
+           int cur = id.compareTo(o.id);\r
+           if(cur != 0)\r
+               return cur;\r
+           \r
+           cur = major - o.major;\r
+           if(cur != 0)\r
+            return cur;\r
+           \r
+           cur = minor - o.minor;\r
+        if(cur != 0)\r
+            return cur;\r
+        \r
+        cur = service - o.service;        \r
+        return cur;\r
+       }\r
+       \r
+       /**\r
+        * This method excepts {@link Transaction#readGraph()} to return a non-null\r
+        * value, i.e. a database transaction must be in progress that has been\r
+        * started with\r
+        * {@link Transaction#startTransaction(RequestProcessor, boolean)}.\r
+        * \r
+        * @return\r
+        * @see #getGraph(RequestProcessor)\r
+        */\r
+       public TransferableGraph1 getGraph() {\r
+               if (graph == null) {\r
+                       ReadGraph g = Transaction.readGraph();\r
+                       if (g == null)\r
+                           throw new IllegalStateException("No read transaction available");\r
+                       try {\r
+                               Binding tg_binding = Bindings.getBindingUnchecked( TransferableGraph1.class );\r
+                               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
+                               graph = g.getRelatedValue(resource, DatabaseManagement.HasFile, tg_binding); \r
+                       } catch (DatabaseException e) {\r
+                               e.printStackTrace();\r
+                       }\r
+               }\r
+               return graph;\r
+       }\r
+\r
+       public TransferableGraph1 getGraph(RequestProcessor processor) {\r
+               if (graph == null) {\r
+                       try {\r
+                               graph = processor.syncRequest(new ResourceRead<TransferableGraph1>(resource) {\r
+                                       @Override\r
+                                       public TransferableGraph1 perform(ReadGraph graph) throws DatabaseException {\r
+                                               Binding tg_binding = Bindings.getBindingUnchecked( TransferableGraph1.class );\r
+                                               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(graph);\r
+                                               return graph.getRelatedValue(resource, DatabaseManagement.HasFile, tg_binding); \r
+                                       }\r
+                               });\r
+                       } catch (DatabaseException e) {\r
+                               e.printStackTrace();\r
+                       }\r
+               }\r
+               return graph;\r
+       }\r
+       \r
+       public int getHashcode() {\r
+               return hashcode;\r
+       }\r
+       \r
+       @Override\r
+       public int hashCode() {\r
+               return 31*id.hashCode() + 7*major + 3*minor + 11*service + (qualifier!=null?13*qualifier.hashCode():0) + hashcode;\r
+       }\r
+       \r
+       @Override\r
+       public boolean equals(Object obj) {\r
+               if (obj instanceof GraphBundle == false) return false;\r
+               GraphBundle other = (GraphBundle) obj;\r
+               if (other.hashcode != hashcode) return false;\r
+               if (!other.id.equals(id)) return false;\r
+               if (other.major != major) return false;\r
+               if (other.minor != minor) return false;\r
+               if (other.service != service) return false;\r
+               if (!objectEquals(other.qualifier, qualifier )) return false;\r
+               return true;\r
+       }       \r
+       \r
+    static boolean objectEquals(Object o1, Object o2) {\r
+        if (o1 == o2) return true;\r
+        if (o1 == null && o2 == null) return true;\r
+        if (o1 == null || o2 == null) return false;\r
+        return o1.equals(o2);\r
+    }  \r
+    \r
+    public boolean getImmutable() {\r
+       return immutable;\r
+    }\r
+       \r
+       public String getId() {\r
+               return id;\r
+       }\r
+       \r
+       public int getMajor() {\r
+               return major;\r
+       }\r
+       \r
+       public int getMinor() {\r
+               return minor;\r
+       }\r
+       \r
+       public int getService() {\r
+               return service;\r
+       }\r
+       \r
+       public String getQualifier() {\r
+               return qualifier;\r
+       }\r
+\r
+       public String getVersionedId() {\r
+               return id+"/"+major+"."+minor+"."+service+"."+qualifier;\r
+       }\r
+       \r
+       @Override\r
+       public String toString() {\r
+               return name+", "+id+"/"+getVersionedId()+", hash="+hashcode;\r
+       }\r
+\r
+       public long[] getResourceArray() {\r
+               return resourceArray;\r
+       }\r
+\r
+       public void setResourceArray(long[] resourceArray) {\r
+               this.resourceArray = resourceArray;\r
+       }\r
+       \r
+       public static void main(String[] args) {\r
+               Matcher m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1.1.qualifier");\r
+               if (m.matches()) {\r
+                       System.out.println( m.groupCount() );\r
+               }\r
+               \r
+               m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1.1");\r
+               if (m.matches()) {\r
+                       System.out.println( m.groupCount() );\r
+               }\r
+               \r
+               m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1.1.200810101010");\r
+               if (m.matches()) {\r
+                       System.out.println( m.groupCount() );\r
+               }\r
+               \r
+               m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1");\r
+               if (m.matches()) {\r
+                       System.out.println( m.groupCount() );\r
+               }\r
+               \r
+       }\r
+       \r
+}\r
+\r