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