--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ * Semantum Oy - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.layer0.adapter.impl;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.Collections;\r
+import java.util.Map;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
+import org.simantics.db.common.utils.Versions;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.adapter.StringModifier;\r
+import org.simantics.db.layer0.util.Layer0Utils;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.layer0.Layer0;\r
+\r
+/**\r
+ * Makes sure that two things apply for L0.HasName of any entity:\r
+ * <ol>\r
+ * <li>An entity must not have the same name as any of its\r
+ * L0.PartOf/L0.ConsistsOf related siblings</li>\r
+ * <li>An entity's name must not begin with one or more dots ('.'). Due to\r
+ * limitations imposed by the Variable specification no resources in the\r
+ * simantics database should be named beginning with one or more dots. '.' is\r
+ * variable browsing syntax for "parent" (see\r
+ * {@link Variable#browse(ReadGraph, String)}). This is comparable to file\r
+ * systems and the use of '.' and '..' therein.</li>\r
+ * </ol>\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public final class EntityNameModifier implements StringModifier {\r
+\r
+ private Resource entity;\r
+ private Resource property;\r
+\r
+ private boolean hasUri;\r
+ private Map<String, Resource> namesInUse = Collections.emptyMap();\r
+\r
+ private Layer0 L0;\r
+ \r
+ final private String initial;\r
+ final private String version;\r
+\r
+ public EntityNameModifier(ReadGraph graph, Resource entity, Resource property) throws DatabaseException {\r
+ this.entity = entity;\r
+ this.property = property;\r
+ initialize(graph);\r
+ this.initial = Versions.getBaseName(graph, entity);\r
+ this.version = Versions.getVersion(graph, entity);\r
+ }\r
+\r
+ @Override\r
+ public String getValue() {\r
+ return initial;\r
+ }\r
+ \r
+ private void initialize(ReadGraph graph) throws DatabaseException {\r
+ this.L0 = Layer0.getInstance(graph);\r
+ refreshUsedSiblingNames(graph);\r
+ if(Layer0Utils.isPublished(graph, entity)) throw new DatabaseException("Published resources cannot be renamed.");\r
+ if(Layer0Utils.isContainerPublished(graph, entity)) throw new DatabaseException("Cannot rename in a published shared library.");\r
+ }\r
+\r
+ private void refreshUsedSiblingNames(ReadGraph graph) throws DatabaseException {\r
+ String uri = graph.getPossibleURI(entity);\r
+ this.hasUri = uri != null;\r
+\r
+ Map<String, Resource> used = new THashMap<String, Resource>();\r
+ for (Resource partOf : graph.getObjects(entity, L0.PartOf)) {\r
+ Map<String, Resource> childMap = graph.syncRequest(new UnescapedChildMapOfResource(partOf));\r
+ used.putAll(childMap);\r
+ }\r
+ String originalName = graph.getPossibleValue(property, Bindings.STRING);\r
+// System.out.println("used names:" + used);\r
+// System.out.println("original name:" + originalName);\r
+ used.remove(originalName);\r
+\r
+ this.namesInUse = used;\r
+// System.out.println("final used names:" + used);\r
+ }\r
+\r
+ public String finalValue(String value) {\r
+ return version != null ? value + "@" + version : value;\r
+ }\r
+ \r
+ @Override\r
+ public String isValid(String value_) {\r
+ String value = finalValue(value_); \r
+ if (value.isEmpty())\r
+ return "Name is empty.";\r
+ if (namesInUse.containsKey(value))\r
+ return "Name is already used by a sibling.";\r
+ if (hasUri && value.startsWith("."))\r
+ return "Name of an entity with URI must not begin with a dot ('.')";\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ final public void modify(WriteGraph graph, String value_) throws DatabaseException {\r
+ String value = finalValue(value_); \r
+ graph.claimLiteral(entity, L0.HasName, L0.NameOf, value, Bindings.STRING);\r
+ }\r
+\r
+}\r