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