]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.common/src/org/simantics/db/common/utils/NameUtils.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / utils / NameUtils.java
diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/NameUtils.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/NameUtils.java
new file mode 100644 (file)
index 0000000..424e76f
--- /dev/null
@@ -0,0 +1,533 @@
+/*******************************************************************************\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.db.common.utils;\r
+\r
+import java.nio.CharBuffer;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+import java.util.Comparator;\r
+import java.util.Formatter;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Locale;\r
+import java.util.Set;\r
+import java.util.TreeSet;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.util.binary.RandomAccessBinary;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.exception.BindingException;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+\r
+public final class NameUtils {\r
+\r
+       public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource propertyToList, Set<String> result, MapList<String,String> reservation) throws DatabaseException {\r
+               \r
+               if (proposition == null)\r
+                       throw new NullPointerException("null proposition");\r
+               if (propertyToList == null)\r
+                       throw new NullPointerException("null property to list");\r
+               if (result == null)\r
+                       result = new HashSet<String>();\r
+               \r
+               if (reservation != null) {\r
+                       String possibleURI = g.getPossibleURI(container);\r
+                       if(possibleURI != null) {\r
+                               result.addAll(reservation.getValuesUnsafe(possibleURI));\r
+                       }\r
+               }\r
+               \r
+               for (Resource r : g.getObjects(container, consistRelation)) {\r
+                       String name = g.getPossibleRelatedValue(r, propertyToList);\r
+                       if (name != null && name.startsWith(proposition))\r
+                               result.add(Versions.getBaseName(name));\r
+               }\r
+               \r
+               return result;\r
+               \r
+       }\r
+\r
+       public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource propertyToList, Set<String> result) throws DatabaseException {\r
+               return findReservedNames(g, proposition, container, consistRelation, propertyToList, result, null);\r
+       }\r
+\r
+       public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation, Set<String> result) throws DatabaseException {\r
+               Layer0 L0 = Layer0.getInstance(g);\r
+               return findReservedNames(g, proposition, container, consistRelation, L0.HasName, result);\r
+       }\r
+\r
+       public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation) throws DatabaseException {\r
+               Set<String> result = new HashSet<String>();\r
+               findReservedNames(g, proposition, container, consistRelation, result);\r
+               return result;\r
+       }\r
+\r
+       public static String findFreshName(ReadGraph g, String proposition, Resource container) throws DatabaseException {\r
+               Layer0 b = Layer0.getInstance(g);\r
+               return findFreshName(g, proposition, container, b.ConsistsOf);\r
+       }\r
+\r
+       public static String findFreshLabel(ReadGraph g, String proposition, Resource container) throws DatabaseException {\r
+               Layer0 L0 = Layer0.getInstance(g);\r
+               return _findFreshName(g, proposition, container, L0.ConsistsOf, L0.HasLabel, " ");\r
+       }\r
+\r
+       public static String findFreshEscapedName(ReadGraph g, String proposition, Resource container) throws DatabaseException {\r
+               Layer0 b = Layer0.getInstance(g);\r
+               return findFreshEscapedName(g, proposition, container, b.ConsistsOf);\r
+       }\r
+\r
+       public static final Comparator<Object> STRING_CHARBUFFER_COMPARATOR = new Comparator<Object>(){\r
+               @Override\r
+               public int compare(Object o1, Object o2) {\r
+                       String s1 = null;\r
+                       String s2 = null;\r
+                       if (o1 instanceof String)\r
+                               s1 = (String) o1;\r
+                       if (o2 instanceof String)\r
+                               s2 = (String) o2;\r
+                       if (s1 != null && s2 != null)\r
+                               return s1.compareTo((String) o2);\r
+\r
+                       if (s1 == null && s2 == null)\r
+                               return 0;\r
+\r
+                       if (s1 == null && (o1 instanceof CharBuffer))\r
+                               return -compare(s2, (CharBuffer) o1);\r
+                       if (s2 == null && (o2 instanceof CharBuffer))\r
+                               return compare(s1, (CharBuffer) o2);\r
+\r
+                       return 0;\r
+               }\r
+               int compare(String s, CharBuffer buf) {\r
+                       int len1 = s.length();\r
+                       int len2 = buf.position();\r
+                       int n = Math.min(len1, len2);\r
+                       int k = 0;\r
+                       while (k < n) {\r
+                               char c1 = s.charAt(k);\r
+                               char c2 = buf.get(k);\r
+                               if (c1 != c2) {\r
+                                       return c1 - c2;\r
+                               }\r
+                               k++;\r
+                       }\r
+                       return len1 - len2;\r
+               }\r
+       };\r
+\r
+       public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation) throws DatabaseException {\r
+               return _findFreshName(g, proposition, container, consistRelation, " ");\r
+       }\r
+\r
+       public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, String nameFormat) throws DatabaseException {\r
+               return findFreshName(g, proposition, container, consistRelation, Layer0.getInstance(g).HasName, nameFormat);\r
+       }\r
+\r
+       public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource nameProperty, String nameFormat) throws DatabaseException {\r
+               Set<String> reservedNames = new TreeSet<String>(STRING_CHARBUFFER_COMPARATOR);\r
+               findReservedNames(g, proposition, container, consistRelation, nameProperty, reservedNames);\r
+               return findFreshNameFormatted(proposition, reservedNames, nameFormat);\r
+       }\r
+\r
+       public static String findFreshEscapedName(ReadGraph g, String proposition, Resource container, Resource consistRelation) throws DatabaseException {\r
+               return _findFreshName(g, proposition, container, consistRelation, "_");\r
+       }\r
+       \r
+       /**\r
+        * Find a fresh name using the specified name proposition among an\r
+        * externally specified set of names using suffix numbers.\r
+        * \r
+        * @param g\r
+        * @param proposition\r
+        * @param reservedNames\r
+        * @param numberSeparator\r
+        * @return\r
+        * @throws DatabaseException\r
+        */\r
+       public static String findFreshName(ReadGraph g, String proposition, Set<String> reservedNames, String numberSeparator) throws DatabaseException {\r
+               // Trying to optimize away unnecessary allocation of new String instances\r
+               // when looking for fresh names for objects.\r
+               if (!reservedNames.contains(proposition))\r
+                       return proposition;\r
+\r
+               // Need to make sure that the set is using the correct comparator.\r
+               Set<String> used = new TreeSet<String>(STRING_CHARBUFFER_COMPARATOR);\r
+               used.addAll(reservedNames);\r
+               return findFreshNameNumbered(proposition, used, numberSeparator);\r
+       }\r
+\r
+       public static String findFreshInstanceName(ReadGraph g, Resource type, Resource container) throws DatabaseException {\r
+               String typeName = g.getPossibleRelatedValue(type, Layer0.getInstance(g).HasName);\r
+               if (typeName == null)\r
+                       typeName = "Entity";\r
+               return findFreshName(g, typeName, container);\r
+       }\r
+\r
+       public static String findFreshInstanceName(ReadGraph g, Resource type, Resource container, Resource relation) throws DatabaseException {\r
+               String typeName = g.getPossibleRelatedValue(type, Layer0.getInstance(g).HasName);\r
+               if (typeName == null)\r
+                       typeName = "Entity";\r
+               return findFreshName(g, typeName, container, relation);\r
+       }\r
+\r
+       private static String _findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, String numberSeparator) throws DatabaseException {\r
+               return _findFreshName(g, proposition, container, consistRelation, Layer0.getInstance(g).HasName, numberSeparator);\r
+       }\r
+\r
+       private static String _findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource nameProperty, String numberSeparator) throws DatabaseException {\r
+               return findFreshName(g, proposition, container, consistRelation, nameProperty, numberSeparator, null);\r
+       }\r
+       \r
+       public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource nameProperty, String numberSeparator, MapList<String, String> reservation) throws DatabaseException {\r
+               Set<String> reservedNames = new TreeSet<String>(STRING_CHARBUFFER_COMPARATOR);\r
+               findReservedNames(g, proposition, container, consistRelation, nameProperty, reservedNames, reservation);\r
+               return findFreshNameNumbered(proposition, reservedNames, numberSeparator);\r
+       }\r
+\r
+       public static String findFreshNameNumbered(String proposition, Set<String> reservedNames, String numberSeparator) {\r
+               // Trying to optimize away unnecessary allocation of new String instances\r
+               // when looking for fresh names for objects.\r
+               if (!reservedNames.contains(proposition))\r
+                       return proposition;\r
+\r
+               CharBuffer cb = CharBuffer.allocate(proposition.length() + 10);\r
+               cb.append(proposition);\r
+               cb.append(numberSeparator);\r
+               cb.mark();\r
+               int i = reservedNames.size() + 1;\r
+               while (true) {\r
+                       cb.reset();\r
+                       cb.append(String.valueOf(i));\r
+                       if (!reservedNames.contains(cb)) {\r
+                               // Construct a String from the CharBuffer\r
+                               cb.limit(cb.position());\r
+                               cb.rewind();\r
+                               return cb.toString();\r
+                       }\r
+                       ++i;\r
+               }\r
+       }\r
+\r
+       public static String findFreshNameFormatted(String proposition, Set<String> reservedNames, String nameFormat) {\r
+               if (!reservedNames.contains(proposition))\r
+                       return proposition;\r
+\r
+               // Trying to optimize away unnecessary allocation of new String instances\r
+               // when looking for fresh names for objects.\r
+               CharBuffer cb = CharBuffer.allocate(proposition.length() + 10);\r
+               cb.mark();\r
+\r
+               @SuppressWarnings("resource")\r
+               Formatter formatter = new Formatter(cb, Locale.US);\r
+\r
+               int i = reservedNames.size() + 1;\r
+               for (;; ++i) {\r
+                       cb.reset();\r
+                       formatter.format(nameFormat, proposition, i);\r
+                       if (!reservedNames.contains(cb)) {\r
+                               // Construct a String from the CharBuffer\r
+                               cb.limit(cb.position());\r
+                               cb.rewind();\r
+                               String result = cb.toString();\r
+                               return result;\r
+                       }\r
+               }\r
+       }\r
+\r
+       public static String getSafeName(ReadGraph graph, Resource resource, boolean id) throws ValidationException, ServiceException {\r
+\r
+               if(id && resource != null) {\r
+                       return getSafeName(graph, resource) + ":$" + resource.getResourceId();\r
+               } else {\r
+                       return getSafeName(graph, resource);\r
+               }\r
+\r
+       }\r
+\r
+       public static String getSafeName(ReadGraph graph, Collection<Resource> rs) throws ValidationException, ServiceException {\r
+\r
+               StringBuilder b = new StringBuilder();\r
+               b.append("{");\r
+               for(Resource r : rs) {\r
+                       b.append(getSafeName(graph, r));\r
+                       b.append(",");\r
+               }\r
+               b.append("}");\r
+               return b.toString();\r
+\r
+       }\r
+\r
+       public static String getSafeLabel(ReadGraph graph, Resource resource) throws ValidationException, ServiceException {\r
+               return getSafeNameInternal(graph, resource, true);\r
+       }\r
+\r
+       public static String getSafeName(ReadGraph graph, Resource resource) throws ValidationException, ServiceException {\r
+               return getSafeNameInternal(graph, resource, false);\r
+       }\r
+\r
+       private static Object truncate(Object array) {\r
+               if(array instanceof byte[]) {\r
+                       byte[] bytes = (byte[])array;\r
+                       if(bytes.length > 100)\r
+                               return Arrays.copyOfRange(bytes, 0, 100);\r
+               }\r
+               return array;\r
+       }\r
+\r
+       public static String getURIOrSafeNameInternal(ReadGraph graph, Resource resource) throws ValidationException, ServiceException {\r
+               return getURIOrSafeNameInternal(graph, resource, false);\r
+       }\r
+\r
+       public static String getURIOrSafeNameInternal(ReadGraph graph, Resource resource, boolean tryLabel) throws ValidationException, ServiceException {\r
+               if (resource == null) return "null";\r
+               String uri = graph.getPossibleURI(resource);\r
+               if(uri != null) return uri;\r
+               else return getSafeNameInternal(graph, resource, tryLabel);\r
+       }\r
+\r
+       public static long getPossibleValueSize(ReadGraph graph, Resource resource) {\r
+               try {\r
+                       if(graph.hasValue(resource)) {\r
+                               RandomAccessBinary rab = graph.getRandomAccessBinary(resource);\r
+                               return rab.length();\r
+                       }\r
+               }catch (Exception e) {\r
+\r
+               }\r
+               return 0;\r
+       }\r
+\r
+       private static String getSafeNameInternal(ReadGraph graph, Resource resource, boolean tryLabel) throws ValidationException, ServiceException {\r
+               if(resource == null) return "null";\r
+               Layer0 b = Layer0.getInstance(graph);\r
+               if (graph.isInstanceOf(resource, b.Variant)) {\r
+                       try {\r
+                               Variant v = graph.getPossibleValue(resource, Bindings.VARIANT);\r
+                               return v.toString();\r
+                       } catch (BindingException e) {\r
+                       }\r
+               }\r
+               List<String> names = new ArrayList<String>(1);\r
+               if (tryLabel) {\r
+                       for(Resource nameResource : graph.getObjects(resource, b.HasLabel)) {\r
+                               if(graph.isInstanceOf(nameResource, b.Literal)) {\r
+                                       Object value = graph.getPossibleValue(nameResource);\r
+                                       if(value != null) {\r
+                                               String s = Literals.literalToString(value);\r
+                                               if (!s.isEmpty())\r
+                                                       names.add(s);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               if (names.isEmpty()) {\r
+                       for(Resource nameResource : graph.getObjects(resource, b.HasName)) {\r
+                               Object value = graph.getPossibleValue(nameResource);\r
+                               if(value != null) {\r
+                                       names.add(Literals.literalToString(value));\r
+                               }\r
+                       }\r
+               }\r
+               if(!names.isEmpty()) {\r
+                       if(names.size() == 1)\r
+                               return names.get(0);\r
+                       else {\r
+                               StringBuilder bb = new StringBuilder();\r
+                               bb.append('[');\r
+                               for(int i=0;i<names.size();++i) {\r
+                                       if(i>0)\r
+                                               bb.append(", ");\r
+                                       bb.append(names.get(i));\r
+                               }\r
+                               bb.append(']');\r
+                               return bb.toString();\r
+                       }\r
+               }\r
+               StringBuilder bb = new StringBuilder();\r
+               long valueSize = getPossibleValueSize(graph, resource);\r
+               //System.err.println("valueSize=" + valueSize);\r
+               if(valueSize > 0) {\r
+                       if(valueSize < 1e6) {\r
+                               Object val = graph.getPossibleValue(resource);\r
+                               if(val != null) {\r
+                                       val = truncate(val);\r
+                                       if(val instanceof double[])\r
+                                               bb.append(Arrays.toString((double[])val));\r
+                                       else if(val instanceof float[])\r
+                                               bb.append(Arrays.toString((float[])val));\r
+                                       else if(val instanceof int[])\r
+                                               bb.append(Arrays.toString((int[])val));\r
+                                       else if(val instanceof boolean[])\r
+                                               bb.append(Arrays.toString((boolean[])val));\r
+                                       else if(val instanceof long[])\r
+                                               bb.append(Arrays.toString((long[])val));\r
+                                       else if(val instanceof byte[])\r
+                                               bb.append(Arrays.toString((byte[])val));\r
+                                       else if(val instanceof String[])\r
+                                               bb.append(Arrays.toString((String[])val));\r
+                                       else\r
+                                               bb.append(val);\r
+                               } else {\r
+                                       bb.append('$').append(resource.getResourceId());\r
+                               }\r
+                       } else {\r
+                               bb.append('$').append(resource.getResourceId());\r
+                               bb.append("[" + valueSize + " bytes of value]");\r
+                       }\r
+               } else {\r
+                       bb.append('$').append(resource.getResourceId());\r
+               }\r
+               boolean ok = false;\r
+               for(Resource r : graph.getObjects(resource, b.InstanceOf)) {\r
+                       if(!r.equals(resource))\r
+                               bb.append(" : (" + getSafeName(graph, r) + ")");\r
+                       ok = true;\r
+               }\r
+               if(!ok) {\r
+                       for(Resource r : graph.getObjects(resource, b.Inherits)) {\r
+                               bb.append(" <T (" + getSafeName(graph, r) + ")");\r
+                               ok = true;\r
+                       }\r
+                       if(!ok) {\r
+                               for(Resource r : graph.getObjects(resource, b.SubrelationOf)) {\r
+                                       bb.append(" <R (" + getSafeName(graph, r) + ")");\r
+                                       ok = true;\r
+                               }\r
+                       }\r
+               }\r
+               return bb.toString();\r
+       }\r
+\r
+       public static String toString(ReadGraph graph, Statement stm) throws DatabaseException {\r
+               return getSafeName(graph, stm.getSubject()) + ", " +\r
+                               getSafeName(graph, stm.getPredicate()) + ", " +\r
+                               getSafeName(graph, stm.getObject());\r
+       }\r
+\r
+       public static String toString(ReadGraph graph, Statement stm, boolean ids) throws DatabaseException {\r
+               return getSafeName(graph, stm.getSubject(), ids) + ", " +\r
+                               getSafeName(graph, stm.getPredicate(), ids) + ", " +\r
+                               getSafeName(graph, stm.getObject(), ids);\r
+       }\r
+\r
+       public static String toIdString(ReadGraph graph, Statement stm) throws DatabaseException {\r
+               return stm.getSubject() + ", " + stm.getPredicate() + ", " + stm.getObject();\r
+       }\r
+\r
+       /**\r
+        * Convert a collection of resources into a String in the same manner as\r
+        * {@link Arrays#toString(Object[])} does but by consulting\r
+        * {@link #getSafeName(ReadGraph, Resource)} for each resource.\r
+        * \r
+        * @param g database accessor\r
+        * @param c the collection of resources to translate to named strings\r
+        * @return string representation of the resource collection\r
+        * @throws DatabaseException\r
+        */\r
+       public static String toString(ReadGraph g, Collection<Resource> c) throws DatabaseException {\r
+               return toString(g, c, false);\r
+       }\r
+\r
+       /**\r
+        * Convert a collection of resources into a String in the same manner as\r
+        * {@link Arrays#toString(Object[])} does but by consulting\r
+        * {@link #getSafeName(ReadGraph, Resource)} for each resource.\r
+        * \r
+        * @param g database accessor\r
+        * @param c the collection of resources to translate to named strings\r
+        * @param ids <code>true</code> to print the ID of each resource after its\r
+        *        name separated by ':'\r
+        * @return string representation of the resource collection\r
+        * @throws DatabaseException\r
+        */\r
+       public static String toString(ReadGraph g, Collection<Resource> c, boolean ids) throws DatabaseException {\r
+               StringBuilder sb = new StringBuilder();\r
+               sb.append('[');\r
+               boolean first = true;\r
+               for (Resource r : c) {\r
+                       if (!first)\r
+                               sb.append(", ");\r
+                       first = false;\r
+                       sb.append(getSafeName(g, r, ids));\r
+               }\r
+               return sb.append(']').toString();\r
+       }\r
+\r
+       /**\r
+        * @param graph\r
+        * @param r\r
+        * @return\r
+        * @throws DatabaseException\r
+        */\r
+       public static String resourcePath(ReadGraph graph, Resource r) throws DatabaseException {\r
+               return resourcePath0(graph, r, new StringBuilder(80)).toString();\r
+       }\r
+\r
+       /**\r
+        * @param graph\r
+        * @param r\r
+        * @return\r
+        * @throws DatabaseException\r
+        */\r
+       private static StringBuilder resourcePath0(ReadGraph graph, Resource r, StringBuilder result) throws DatabaseException {\r
+               String uri = graph.getPossibleURI(r);\r
+               if (uri != null)\r
+                       return result.append(uri);\r
+               Resource owner = null;\r
+               try {\r
+                       owner = CommonDBUtils.getPossibleOwner(graph, r);\r
+                       if (owner == null)\r
+                               return result.append(NameUtils.getSafeName(graph, r));\r
+               } catch (DatabaseException e) {\r
+                       // Owner resource not found by CommonDBUtils.getPossibleOwner.\r
+                       return result.append(NameUtils.getSafeName(graph, r));\r
+               }\r
+               // See if there's a statement between r and owner.\r
+               Layer0 L0 = Layer0.getInstance(graph);\r
+               for (Statement stm : graph.getStatements(owner, L0.IsWeaklyRelatedTo)) {\r
+                       if (stm.getObject().equals(r)) {\r
+                               Resource predicate = stm.getPredicate();\r
+                               if (predicate.equals(L0.ConsistsOf)) {\r
+                                       return resourcePath0(graph, owner, result)\r
+                                                       .append(" / ")\r
+                                                       .append(NameUtils.getSafeName(graph, r));\r
+                               } else if (graph.isSubrelationOf(predicate, L0.HasProperty)) {\r
+                                       return resourcePath0(graph, owner, result)\r
+                                                       .append(" #(")\r
+                                                       .append(NameUtils.getSafeName(graph, predicate, true))\r
+                                                       .append(") ")\r
+                                                       .append(NameUtils.getSafeName(graph, r));\r
+                               } else {\r
+                                       return resourcePath0(graph, owner, result)\r
+                                                       .append(" -(")\r
+                                                       .append(NameUtils.getSafeName(graph, predicate, true))\r
+                                                       .append(")-> ")\r
+                                                       .append(NameUtils.getSafeName(graph, r));\r
+                               }\r
+                       }\r
+               }\r
+               return resourcePath0(graph, owner, result)\r
+                               .append(" ... ")\r
+                               .append(NameUtils.getSafeName(graph, r));\r
+       }\r
+\r
+}\r