1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.common.utils;
14 import java.nio.CharBuffer;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collection;
18 import java.util.Comparator;
19 import java.util.Formatter;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Locale;
24 import java.util.TreeSet;
26 import org.simantics.databoard.Bindings;
27 import org.simantics.databoard.binding.mutable.Variant;
28 import org.simantics.databoard.util.binary.RandomAccessBinary;
29 import org.simantics.db.ReadGraph;
30 import org.simantics.db.Resource;
31 import org.simantics.db.Statement;
32 import org.simantics.db.exception.BindingException;
33 import org.simantics.db.exception.DatabaseException;
34 import org.simantics.db.exception.ServiceException;
35 import org.simantics.db.exception.ValidationException;
36 import org.simantics.layer0.Layer0;
37 import org.simantics.utils.datastructures.MapList;
40 public final class NameUtils {
42 public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource propertyToList, Set<String> result, MapList<String,String> reservation) throws DatabaseException {
44 if (proposition == null)
45 throw new NullPointerException("null proposition");
46 if (propertyToList == null)
47 throw new NullPointerException("null property to list");
49 result = new HashSet<String>();
51 if (reservation != null) {
52 String possibleURI = g.getPossibleURI(container);
53 if(possibleURI != null) {
54 result.addAll(reservation.getValuesUnsafe(possibleURI));
58 for (Resource r : g.getObjects(container, consistRelation)) {
59 String name = g.getPossibleRelatedValue(r, propertyToList);
60 if (name != null && name.startsWith(proposition))
61 result.add(Versions.getBaseName(name));
68 public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource propertyToList, Set<String> result) throws DatabaseException {
69 return findReservedNames(g, proposition, container, consistRelation, propertyToList, result, null);
72 public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation, Set<String> result) throws DatabaseException {
73 Layer0 L0 = Layer0.getInstance(g);
74 return findReservedNames(g, proposition, container, consistRelation, L0.HasName, result);
77 public static Set<String> findReservedNames(ReadGraph g, String proposition, Resource container, Resource consistRelation) throws DatabaseException {
78 Set<String> result = new HashSet<String>();
79 findReservedNames(g, proposition, container, consistRelation, result);
83 public static String findFreshName(ReadGraph g, String proposition, Resource container) throws DatabaseException {
84 Layer0 b = Layer0.getInstance(g);
85 return findFreshName(g, proposition, container, b.ConsistsOf);
88 public static String findFreshLabel(ReadGraph g, String proposition, Resource container) throws DatabaseException {
89 Layer0 L0 = Layer0.getInstance(g);
90 return _findFreshName(g, proposition, container, L0.ConsistsOf, L0.HasLabel, " ");
93 public static String findFreshEscapedName(ReadGraph g, String proposition, Resource container) throws DatabaseException {
94 Layer0 b = Layer0.getInstance(g);
95 return findFreshEscapedName(g, proposition, container, b.ConsistsOf);
98 public static final Comparator<Object> STRING_CHARBUFFER_COMPARATOR = new Comparator<Object>(){
100 public int compare(Object o1, Object o2) {
103 if (o1 instanceof String)
105 if (o2 instanceof String)
107 if (s1 != null && s2 != null)
108 return s1.compareTo((String) o2);
110 if (s1 == null && s2 == null)
113 if (s1 == null && (o1 instanceof CharBuffer))
114 return -compare(s2, (CharBuffer) o1);
115 if (s2 == null && (o2 instanceof CharBuffer))
116 return compare(s1, (CharBuffer) o2);
120 int compare(String s, CharBuffer buf) {
121 int len1 = s.length();
122 int len2 = buf.position();
123 int n = Math.min(len1, len2);
126 char c1 = s.charAt(k);
127 char c2 = buf.get(k);
137 public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation) throws DatabaseException {
138 return _findFreshName(g, proposition, container, consistRelation, " ");
141 public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, String nameFormat) throws DatabaseException {
142 return findFreshName(g, proposition, container, consistRelation, Layer0.getInstance(g).HasName, nameFormat);
145 public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource nameProperty, String nameFormat) throws DatabaseException {
146 Set<String> reservedNames = new TreeSet<String>(STRING_CHARBUFFER_COMPARATOR);
147 findReservedNames(g, proposition, container, consistRelation, nameProperty, reservedNames);
148 return findFreshNameFormatted(proposition, reservedNames, nameFormat);
151 public static String findFreshEscapedName(ReadGraph g, String proposition, Resource container, Resource consistRelation) throws DatabaseException {
152 return _findFreshName(g, proposition, container, consistRelation, "_");
156 * Find a fresh name using the specified name proposition among an
157 * externally specified set of names using suffix numbers.
161 * @param reservedNames
162 * @param numberSeparator
164 * @throws DatabaseException
166 public static String findFreshName(ReadGraph g, String proposition, Set<String> reservedNames, String numberSeparator) throws DatabaseException {
167 // Trying to optimize away unnecessary allocation of new String instances
168 // when looking for fresh names for objects.
169 if (!reservedNames.contains(proposition))
172 // Need to make sure that the set is using the correct comparator.
173 Set<String> used = new TreeSet<String>(STRING_CHARBUFFER_COMPARATOR);
174 used.addAll(reservedNames);
175 return findFreshNameNumbered(proposition, used, numberSeparator);
178 public static String findFreshInstanceName(ReadGraph g, Resource type, Resource container) throws DatabaseException {
179 String typeName = g.getPossibleRelatedValue(type, Layer0.getInstance(g).HasName);
180 if (typeName == null)
182 return findFreshName(g, typeName, container);
185 public static String findFreshInstanceName(ReadGraph g, Resource type, Resource container, Resource relation) throws DatabaseException {
186 String typeName = g.getPossibleRelatedValue(type, Layer0.getInstance(g).HasName);
187 if (typeName == null)
189 return findFreshName(g, typeName, container, relation);
192 private static String _findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, String numberSeparator) throws DatabaseException {
193 return _findFreshName(g, proposition, container, consistRelation, Layer0.getInstance(g).HasName, numberSeparator);
196 private static String _findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource nameProperty, String numberSeparator) throws DatabaseException {
197 return findFreshName(g, proposition, container, consistRelation, nameProperty, numberSeparator, null);
200 public static String findFreshName(ReadGraph g, String proposition, Resource container, Resource consistRelation, Resource nameProperty, String numberSeparator, MapList<String, String> reservation) throws DatabaseException {
201 Set<String> reservedNames = new TreeSet<String>(STRING_CHARBUFFER_COMPARATOR);
202 findReservedNames(g, proposition, container, consistRelation, nameProperty, reservedNames, reservation);
203 return findFreshNameNumbered(proposition, reservedNames, numberSeparator);
206 public static String findFreshNameNumbered(String proposition, Set<String> reservedNames, String numberSeparator) {
207 // Trying to optimize away unnecessary allocation of new String instances
208 // when looking for fresh names for objects.
209 if (!reservedNames.contains(proposition))
212 CharBuffer cb = CharBuffer.allocate(proposition.length() + 10);
213 cb.append(proposition);
214 cb.append(numberSeparator);
216 int i = reservedNames.size() + 1;
219 cb.append(String.valueOf(i));
220 if (!reservedNames.contains(cb)) {
221 // Construct a String from the CharBuffer
222 cb.limit(cb.position());
224 return cb.toString();
230 public static String findFreshNameFormatted(String proposition, Set<String> reservedNames, String nameFormat) {
231 if (!reservedNames.contains(proposition))
234 // Trying to optimize away unnecessary allocation of new String instances
235 // when looking for fresh names for objects.
236 CharBuffer cb = CharBuffer.allocate(proposition.length() + 10);
239 @SuppressWarnings("resource")
240 Formatter formatter = new Formatter(cb, Locale.US);
242 int i = reservedNames.size() + 1;
245 formatter.format(nameFormat, proposition, i);
246 if (!reservedNames.contains(cb)) {
247 // Construct a String from the CharBuffer
248 cb.limit(cb.position());
250 String result = cb.toString();
256 public static String getSafeName(ReadGraph graph, Resource resource, boolean id) throws ValidationException, ServiceException {
258 if(id && resource != null) {
259 return getSafeName(graph, resource) + ":$" + resource.getResourceId();
261 return getSafeName(graph, resource);
266 public static String getSafeName(ReadGraph graph, Collection<Resource> rs) throws ValidationException, ServiceException {
268 StringBuilder b = new StringBuilder();
270 for(Resource r : rs) {
271 b.append(getSafeName(graph, r));
279 public static String getSafeLabel(ReadGraph graph, Resource resource) throws ValidationException, ServiceException {
280 return getSafeNameInternal(graph, resource, true);
283 public static String getSafeName(ReadGraph graph, Resource resource) throws ValidationException, ServiceException {
284 return getSafeNameInternal(graph, resource, false);
287 private static Object truncate(Object array) {
288 if(array instanceof byte[]) {
289 byte[] bytes = (byte[])array;
290 if(bytes.length > 100)
291 return Arrays.copyOfRange(bytes, 0, 100);
296 public static String getURIOrSafeNameInternal(ReadGraph graph, Resource resource) throws ValidationException, ServiceException {
297 return getURIOrSafeNameInternal(graph, resource, false);
300 public static String getURIOrSafeNameInternal(ReadGraph graph, Resource resource, boolean tryLabel) throws ValidationException, ServiceException {
301 if (resource == null) return "null";
302 String uri = graph.getPossibleURI(resource);
303 if(uri != null) return uri;
304 else return getSafeNameInternal(graph, resource, tryLabel);
307 public static long getPossibleValueSize(ReadGraph graph, Resource resource) {
309 if(graph.hasValue(resource)) {
310 RandomAccessBinary rab = graph.getRandomAccessBinary(resource);
313 }catch (Exception e) {
319 private static String getSafeNameInternal(ReadGraph graph, Resource resource, boolean tryLabel) throws ValidationException, ServiceException {
320 if(resource == null) return "null";
321 Layer0 b = Layer0.getInstance(graph);
322 if (graph.isInstanceOf(resource, b.Variant)) {
324 Variant v = graph.getPossibleValue(resource, Bindings.VARIANT);
326 } catch (BindingException e) {
329 List<String> names = new ArrayList<String>(1);
331 for(Resource nameResource : graph.getObjects(resource, b.HasLabel)) {
332 if(graph.isInstanceOf(nameResource, b.Literal)) {
333 Object value = graph.getPossibleValue(nameResource);
335 String s = Literals.literalToString(value);
342 if (names.isEmpty()) {
343 for(Resource nameResource : graph.getObjects(resource, b.HasName)) {
344 Object value = graph.getPossibleValue(nameResource);
346 names.add(Literals.literalToString(value));
350 if(!names.isEmpty()) {
351 if(names.size() == 1)
354 StringBuilder bb = new StringBuilder();
356 for(int i=0;i<names.size();++i) {
359 bb.append(names.get(i));
362 return bb.toString();
365 StringBuilder bb = new StringBuilder();
366 long valueSize = getPossibleValueSize(graph, resource);
367 //System.err.println("valueSize=" + valueSize);
369 if(valueSize < 1e6) {
370 Object val = graph.getPossibleValue(resource);
373 if(val instanceof double[])
374 bb.append(Arrays.toString((double[])val));
375 else if(val instanceof float[])
376 bb.append(Arrays.toString((float[])val));
377 else if(val instanceof int[])
378 bb.append(Arrays.toString((int[])val));
379 else if(val instanceof boolean[])
380 bb.append(Arrays.toString((boolean[])val));
381 else if(val instanceof long[])
382 bb.append(Arrays.toString((long[])val));
383 else if(val instanceof byte[])
384 bb.append(Arrays.toString((byte[])val));
385 else if(val instanceof String[])
386 bb.append(Arrays.toString((String[])val));
390 bb.append('$').append(resource.getResourceId());
393 bb.append('$').append(resource.getResourceId());
394 bb.append("[" + valueSize + " bytes of value]");
397 bb.append('$').append(resource.getResourceId());
400 for(Resource r : graph.getObjects(resource, b.InstanceOf)) {
401 if(!r.equals(resource))
402 bb.append(" : (" + getSafeName(graph, r) + ")");
406 for(Resource r : graph.getObjects(resource, b.Inherits)) {
407 bb.append(" <T (" + getSafeName(graph, r) + ")");
411 for(Resource r : graph.getObjects(resource, b.SubrelationOf)) {
412 bb.append(" <R (" + getSafeName(graph, r) + ")");
417 return bb.toString();
420 public static String toString(ReadGraph graph, Statement stm) throws DatabaseException {
421 return getSafeName(graph, stm.getSubject()) + ", " +
422 getSafeName(graph, stm.getPredicate()) + ", " +
423 getSafeName(graph, stm.getObject());
426 public static String toString(ReadGraph graph, Statement stm, boolean ids) throws DatabaseException {
427 return getSafeName(graph, stm.getSubject(), ids) + ", " +
428 getSafeName(graph, stm.getPredicate(), ids) + ", " +
429 getSafeName(graph, stm.getObject(), ids);
432 public static String toIdString(ReadGraph graph, Statement stm) throws DatabaseException {
433 return stm.getSubject() + ", " + stm.getPredicate() + ", " + stm.getObject();
437 * Convert a collection of resources into a String in the same manner as
438 * {@link Arrays#toString(Object[])} does but by consulting
439 * {@link #getSafeName(ReadGraph, Resource)} for each resource.
441 * @param g database accessor
442 * @param c the collection of resources to translate to named strings
443 * @return string representation of the resource collection
444 * @throws DatabaseException
446 public static String toString(ReadGraph g, Collection<Resource> c) throws DatabaseException {
447 return toString(g, c, false);
451 * Convert a collection of resources into a String in the same manner as
452 * {@link Arrays#toString(Object[])} does but by consulting
453 * {@link #getSafeName(ReadGraph, Resource)} for each resource.
455 * @param g database accessor
456 * @param c the collection of resources to translate to named strings
457 * @param ids <code>true</code> to print the ID of each resource after its
458 * name separated by ':'
459 * @return string representation of the resource collection
460 * @throws DatabaseException
462 public static String toString(ReadGraph g, Collection<Resource> c, boolean ids) throws DatabaseException {
463 StringBuilder sb = new StringBuilder();
465 boolean first = true;
466 for (Resource r : c) {
470 sb.append(getSafeName(g, r, ids));
472 return sb.append(']').toString();
479 * @throws DatabaseException
481 public static String resourcePath(ReadGraph graph, Resource r) throws DatabaseException {
482 return resourcePath0(graph, r, new StringBuilder(80)).toString();
489 * @throws DatabaseException
491 private static StringBuilder resourcePath0(ReadGraph graph, Resource r, StringBuilder result) throws DatabaseException {
492 String uri = graph.getPossibleURI(r);
494 return result.append(uri);
495 Resource owner = null;
497 owner = CommonDBUtils.getPossibleOwner(graph, r);
499 return result.append(NameUtils.getSafeName(graph, r));
500 } catch (DatabaseException e) {
501 // Owner resource not found by CommonDBUtils.getPossibleOwner.
502 return result.append(NameUtils.getSafeName(graph, r));
504 // See if there's a statement between r and owner.
505 Layer0 L0 = Layer0.getInstance(graph);
506 for (Statement stm : graph.getStatements(owner, L0.IsWeaklyRelatedTo)) {
507 if (stm.getObject().equals(r)) {
508 Resource predicate = stm.getPredicate();
509 if (predicate.equals(L0.ConsistsOf)) {
510 return resourcePath0(graph, owner, result)
512 .append(NameUtils.getSafeName(graph, r));
513 } else if (graph.isSubrelationOf(predicate, L0.HasProperty)) {
514 return resourcePath0(graph, owner, result)
516 .append(NameUtils.getSafeName(graph, predicate, true))
518 .append(NameUtils.getSafeName(graph, r));
520 return resourcePath0(graph, owner, result)
522 .append(NameUtils.getSafeName(graph, predicate, true))
524 .append(NameUtils.getSafeName(graph, r));
528 return resourcePath0(graph, owner, result)
530 .append(NameUtils.getSafeName(graph, r));