]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.project/src/org/simantics/project/management/GraphBundle.java
Include acorn db in db.client feature and make it the default db driver
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / GraphBundle.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.project.management;\r
13 \r
14 import java.util.regex.Matcher;\r
15 import java.util.regex.Pattern;\r
16 \r
17 import org.simantics.databoard.Bindings;\r
18 import org.simantics.databoard.binding.Binding;\r
19 import org.simantics.databoard.binding.error.BindingException;\r
20 import org.simantics.databoard.binding.error.RuntimeBindingException;\r
21 import org.simantics.db.ReadGraph;\r
22 import org.simantics.db.RequestProcessor;\r
23 import org.simantics.db.Resource;\r
24 import org.simantics.db.common.request.ResourceRead;\r
25 import org.simantics.db.common.utils.Transaction;\r
26 import org.simantics.db.exception.DatabaseException;\r
27 import org.simantics.graph.representation.TransferableGraph1;\r
28 import org.simantics.layer0.DatabaseManagementResource;\r
29 \r
30 /**\r
31  * GraphBundle represents a bundle graph that may exist in memory \r
32  * in a OSGi Bundle Context, a P2 Bundle Pool, or in Simantics Database.\r
33  * \r
34  * The string representation of the version is in the following format: \r
35  *   <id>/<major.minor.micro(.qualifier)>\r
36  * \r
37  * Here is what is said about osgi version numbers:\r
38  * \r
39  *  Major - Differences in the major part indicate significant differences \r
40  *          such that backward compability is not guaranteed.\r
41  *          \r
42  *  Minor - Changes in the minor part indicate that the newer version of the\r
43  *          entity is backward compatible with the older version, but it \r
44  *          includes additional functionality and/or API.\r
45  *     \r
46  *  Service - The service part indicates the presence of bug fixes and minor\r
47  *          implementation (i.e., hidden) changes over previous versions.\r
48  *  \r
49  *  Qualifier - The qualifier is not interpreted by the system. Qualifiers are\r
50  *           compared using standard string comparison. Qualifier is determined\r
51  *           at build time by builder. It may be millisecond time or version \r
52  *           control revision number. The value is monotonically increasing. \r
53  *           \r
54  *   \r
55  * The class is hash-equals-comparable.\r
56  *\r
57  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
58  */\r
59 public class GraphBundle implements Comparable<GraphBundle> {\r
60 \r
61         /** Versioned Id pattern */     \r
62         static String ID_PATTERN_STRING =                "[a-zA-Z_0-9\\-]+(?:\\.[a-zA-Z_0-9\\-]+)*";\r
63         static String VERSION_PATTERN_STRING =           "(\\d+).(\\d+).(\\d+).([a-zA-Z_0-9\\-]+)";\r
64         static Pattern ID_PATTERN = Pattern.compile(ID_PATTERN_STRING);\r
65         static Pattern VERSION_PATTERN = Pattern.compile(VERSION_PATTERN_STRING);\r
66         static Pattern VERSIONED_ID_PATTERN = Pattern.compile("(" + ID_PATTERN_STRING + ")/" + VERSION_PATTERN_STRING + "");\r
67                 \r
68         /** User-friendly name */\r
69         String name;\r
70         \r
71         /** Actual graph */\r
72         TransferableGraph1 graph;\r
73         \r
74         /** GraphBundle resource in database */ \r
75         Resource resource;\r
76         \r
77         /** Graph hash code */\r
78         int hashcode;\r
79         \r
80         /** Id */\r
81         String id;\r
82         \r
83         // Version\r
84         int major, minor, service;\r
85         \r
86         // Optional qualifier\r
87         String qualifier;\r
88         \r
89         /** Database install Info, optional */\r
90         long[] resourceArray;\r
91 \r
92         /** Should this ontology be installed immutable **/\r
93         boolean immutable = true;\r
94 \r
95         GraphBundle() {}\r
96         \r
97         public GraphBundle(String name, TransferableGraph1 data, String versionedId) \r
98         throws RuntimeBindingException {                \r
99                 try {                   \r
100                         // Assert version id is correct\r
101                         Matcher m = VERSIONED_ID_PATTERN.matcher(versionedId); \r
102                         if (!m.matches()) {\r
103                                 throw new IllegalArgumentException("Illegal VersionId \""+versionedId+"\", <id>/<major.minor.micro.qualifier> is expected.");\r
104                         }\r
105                         \r
106                         Binding binding = Bindings.getBindingUnchecked( TransferableGraph1.class );             \r
107                         \r
108                         this.name = name;\r
109                         this.graph = data;              \r
110                         this.hashcode = data != null ? binding.hashValue( data ) : 0;\r
111                         this.id = m.group(1);\r
112                         this.major = Integer.valueOf( m.group(2) );\r
113                         this.minor = Integer.valueOf( m.group(3) );\r
114                         if (m.group(4) != null) {\r
115                                 this.service = Integer.valueOf( m.group(4) );\r
116                         }\r
117                         this.qualifier = m.group(5);\r
118                 } catch (BindingException e) {\r
119                         // Unexpected\r
120                         throw new RuntimeBindingException(e);\r
121                 }                       \r
122         }\r
123         \r
124         public GraphBundle(String name, TransferableGraph1 data, String id, String version) \r
125         throws RuntimeBindingException {                \r
126                 Matcher m = ID_PATTERN.matcher(id);\r
127                 if (!m.matches()) \r
128                         throw new IllegalArgumentException("Illegal Id, got \""+id+"\"");\r
129                 m = VERSION_PATTERN.matcher(version);\r
130                 if (!m.matches()) \r
131                         throw new IllegalArgumentException("Illegal Version, got \""+id+"\", <id>/<major.minor.micro.qualifier> is expected.");\r
132                 try {                   \r
133                         Binding binding = Bindings.getBindingUnchecked( TransferableGraph1.class );             \r
134                         this.name = name;\r
135                         this.graph = data;              \r
136                         this.hashcode = binding.hashValue( data );\r
137                         this.id = id;\r
138                         this.major = Integer.valueOf( m.group(1) );\r
139                         this.minor = Integer.valueOf( m.group(2) );\r
140                         this.service = Integer.valueOf( m.group(3) );\r
141                         if (m.group(4) != null) {\r
142                                 this.qualifier = m.group(4);\r
143                         }\r
144                 } catch (BindingException e) {\r
145                         // Unexpected\r
146                         throw new RuntimeBindingException(e);\r
147                 }\r
148         }\r
149         \r
150         public String getName() {\r
151                 return name;\r
152         }\r
153 \r
154         @Override\r
155         public int compareTo(GraphBundle o) {\r
156             int cur = id.compareTo(o.id);\r
157             if(cur != 0)\r
158                 return cur;\r
159             \r
160             cur = major - o.major;\r
161             if(cur != 0)\r
162             return cur;\r
163             \r
164             cur = minor - o.minor;\r
165         if(cur != 0)\r
166             return cur;\r
167         \r
168         cur = service - o.service;        \r
169         return cur;\r
170         }\r
171         \r
172         /**\r
173          * This method excepts {@link Transaction#readGraph()} to return a non-null\r
174          * value, i.e. a database transaction must be in progress that has been\r
175          * started with\r
176          * {@link Transaction#startTransaction(RequestProcessor, boolean)}.\r
177          * \r
178          * @return\r
179          * @see #getGraph(RequestProcessor)\r
180          */\r
181         public TransferableGraph1 getGraph() {\r
182                 if (graph == null) {\r
183                         ReadGraph g = Transaction.readGraph();\r
184                         if (g == null)\r
185                             throw new IllegalStateException("No read transaction available");\r
186                         try {\r
187                                 Binding tg_binding = Bindings.getBindingUnchecked( TransferableGraph1.class );\r
188                                 DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
189                                 graph = g.getRelatedValue(resource, DatabaseManagement.HasFile, tg_binding); \r
190                         } catch (DatabaseException e) {\r
191                                 e.printStackTrace();\r
192                         }\r
193                 }\r
194                 return graph;\r
195         }\r
196 \r
197         public TransferableGraph1 getGraph(RequestProcessor processor) {\r
198                 if (graph == null) {\r
199                         try {\r
200                                 graph = processor.syncRequest(new ResourceRead<TransferableGraph1>(resource) {\r
201                                         @Override\r
202                                         public TransferableGraph1 perform(ReadGraph graph) throws DatabaseException {\r
203                                                 Binding tg_binding = Bindings.getBindingUnchecked( TransferableGraph1.class );\r
204                                                 DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(graph);\r
205                                                 return graph.getRelatedValue(resource, DatabaseManagement.HasFile, tg_binding); \r
206                                         }\r
207                                 });\r
208                         } catch (DatabaseException e) {\r
209                                 e.printStackTrace();\r
210                         }\r
211                 }\r
212                 return graph;\r
213         }\r
214         \r
215         public int getHashcode() {\r
216                 return hashcode;\r
217         }\r
218         \r
219         @Override\r
220         public int hashCode() {\r
221                 return 31*id.hashCode() + 7*major + 3*minor + 11*service + (qualifier!=null?13*qualifier.hashCode():0) + hashcode;\r
222         }\r
223         \r
224         @Override\r
225         public boolean equals(Object obj) {\r
226                 if (obj instanceof GraphBundle == false) return false;\r
227                 GraphBundle other = (GraphBundle) obj;\r
228                 if (other.hashcode != hashcode) return false;\r
229                 if (!other.id.equals(id)) return false;\r
230                 if (other.major != major) return false;\r
231                 if (other.minor != minor) return false;\r
232                 if (other.service != service) return false;\r
233                 if (!objectEquals(other.qualifier, qualifier )) return false;\r
234                 return true;\r
235         }       \r
236         \r
237     static boolean objectEquals(Object o1, Object o2) {\r
238         if (o1 == o2) return true;\r
239         if (o1 == null && o2 == null) return true;\r
240         if (o1 == null || o2 == null) return false;\r
241         return o1.equals(o2);\r
242     }   \r
243     \r
244     public boolean getImmutable() {\r
245         return immutable;\r
246     }\r
247         \r
248         public String getId() {\r
249                 return id;\r
250         }\r
251         \r
252         public int getMajor() {\r
253                 return major;\r
254         }\r
255         \r
256         public int getMinor() {\r
257                 return minor;\r
258         }\r
259         \r
260         public int getService() {\r
261                 return service;\r
262         }\r
263         \r
264         public String getQualifier() {\r
265                 return qualifier;\r
266         }\r
267 \r
268         public String getVersionedId() {\r
269                 return id+"/"+major+"."+minor+"."+service+"."+qualifier;\r
270         }\r
271         \r
272         @Override\r
273         public String toString() {\r
274                 return name+", "+id+"/"+getVersionedId()+", hash="+hashcode;\r
275         }\r
276 \r
277         public long[] getResourceArray() {\r
278                 return resourceArray;\r
279         }\r
280 \r
281         public void setResourceArray(long[] resourceArray) {\r
282                 this.resourceArray = resourceArray;\r
283         }\r
284         \r
285         public static void main(String[] args) {\r
286                 Matcher m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1.1.qualifier");\r
287                 if (m.matches()) {\r
288                         System.out.println( m.groupCount() );\r
289                 }\r
290                 \r
291                 m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1.1");\r
292                 if (m.matches()) {\r
293                         System.out.println( m.groupCount() );\r
294                 }\r
295                 \r
296                 m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1.1.200810101010");\r
297                 if (m.matches()) {\r
298                         System.out.println( m.groupCount() );\r
299                 }\r
300                 \r
301                 m = VERSIONED_ID_PATTERN.matcher("org.simantics.layer0/1.1");\r
302                 if (m.matches()) {\r
303                         System.out.println( m.groupCount() );\r
304                 }\r
305                 \r
306         }\r
307         \r
308 }\r
309 \r