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