X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2FuserComponent%2FComponentTypeCommands.java;h=74ae599e3797f6a06d9c07f2c9ed6bc7d4789843;hp=fdd2649b0f925210b6a18f50973554365430155a;hb=4e402f51b0e34d40c3f9d33a4bec7feffeb8d339;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/userComponent/ComponentTypeCommands.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/userComponent/ComponentTypeCommands.java index fdd2649b0..74ae599e3 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/userComponent/ComponentTypeCommands.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/userComponent/ComponentTypeCommands.java @@ -1,565 +1,573 @@ -/******************************************************************************* - * Copyright (c) 2012 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.modeling.userComponent; - -import gnu.trove.map.hash.THashMap; - -import java.util.Map; - -import org.simantics.databoard.Bindings; -import org.simantics.databoard.Datatypes; -import org.simantics.databoard.adapter.AdaptException; -import org.simantics.databoard.binding.Binding; -import org.simantics.databoard.binding.error.BindingException; -import org.simantics.databoard.parser.repository.DataTypeSyntaxError; -import org.simantics.databoard.parser.repository.DataValueRepository; -import org.simantics.databoard.type.Datatype; -import org.simantics.databoard.type.NumberType; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.Statement; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.CommentMetadata; -import org.simantics.db.common.request.UnaryRead; -import org.simantics.db.common.utils.NameUtils; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.exception.ServiceException; -import org.simantics.db.layer0.request.ModelInstances; -import org.simantics.db.layer0.util.Layer0Utils; -import org.simantics.layer0.Layer0; -import org.simantics.modeling.ModelingResources; -import org.simantics.modeling.NewSymbol; -import org.simantics.operation.Layer0X; -import org.simantics.scl.runtime.tuple.Tuple; -import org.simantics.scl.runtime.tuple.Tuple3; -import org.simantics.selectionview.SelectionViewResources; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.structural2.utils.StructuralUtils; - -public class ComponentTypeCommands { - - public static void applyCode(WriteGraph g, Resource componentType, String code) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(g); - g.claimLiteral(componentType, STR.ProceduralComponentType_code, code, Bindings.STRING); - } - - public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource cp) throws DatabaseException { - return StructuralUtils.createConnectionPoint(g, componentType, cp); - } - - public static Resource createMonitorPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(g); - StructuralResource2 STR = StructuralResource2.getInstance(g); - ModelingResources MOD = ModelingResources.getInstance(g); - - Resource monitorType = g.getPossibleObject(componentType, STR.ComponentType_HasDefaultMonitorValueType); - if(monitorType == null) monitorType = MOD.MonitorValue; - - Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty"); - g.claim(relation, L0.HasRange, monitorType); - - Resource assertion = g.newResource(); - g.claim(componentType, L0.Asserts, assertion); - g.claim(assertion, L0.InstanceOf, L0.Assertion); - g.claim(assertion, L0.HasPredicate, relation); - - Resource value = g.newResource(); - g.claim(value, L0.InstanceOf, monitorType); - g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING); - g.claimLiteral(value, L0.SCLValue_expression, L0.String, "", Bindings.STRING); - g.claim(assertion, L0.HasObject, value); - - return relation; - - } - - public static Resource createPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException { - g.markUndoPoint(); - Layer0 L0 = Layer0.getInstance(g); - - Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty"); - - Resource assertion = g.newResource(); - g.claim(componentType, L0.Asserts, assertion); - g.claim(assertion, L0.InstanceOf, L0.Assertion); - g.claim(assertion, L0.HasPredicate, relation); - - Resource value = g.newResource(); - g.claim(value, L0.InstanceOf, L0.Literal); - g.claimLiteral(value, L0.HasDataType, L0.DataType, Datatypes.DOUBLE, Bindings.getBindingUnchecked(Datatype.class)); - g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING); - g.claimValue(value, 0.0, Bindings.DOUBLE); - g.claim(assertion, L0.HasObject, value); - - return relation; - - } - - public static Resource createPropertyWithDefaultsBase(WriteGraph g, Resource componentType, String defaultName) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(g); - StructuralResource2 STR = StructuralResource2.getInstance(g); - ModelingResources MOD = ModelingResources.getInstance(g); - - String name = NameUtils.findFreshEscapedName(g, defaultName, componentType); - - Resource relation = g.newResource(); - g.claim(relation, L0.SubrelationOf, null, L0.HasProperty); - boolean hadProperty = false; - for(Resource type : g.getObjects(componentType, STR.ComponentType_HasDefaultPropertyRelationType)) { - if(g.isInheritedFrom(type, STR.Property)) hadProperty = true; - g.claim(relation, L0.InstanceOf, type); - } - if(!hadProperty) - g.claim(relation, L0.InstanceOf, STR.Property); - - g.claimLiteral(relation, L0.HasName, name); - g.claim(componentType, L0.ConsistsOf, L0.PartOf, relation); - g.claim(relation, L0.HasDomain, L0.DomainOf, componentType); - - Resource invRelation = g.newResource(); - g.claim(invRelation, L0.SubrelationOf, null, L0.PropertyOf); - g.claim(relation, L0.ConsistsOf, L0.PartOf, invRelation); - g.claimLiteral(invRelation, L0.HasName, "Inverse"); - g.claim(relation, L0.InverseOf, invRelation); - - g.claimLiteral(relation, L0.RequiresValueType, "Double"); - - SelectionViewResources SEL = SelectionViewResources.getInstance(g); - Resource category = g.getPossibleObject(relation, SEL.HasStandardPropertyInfo); - if(category == null) { - g.claim(relation, SEL.HasStandardPropertyInfo, MOD.UserDefinedPropertyInfo); - } - if(!g.isInstanceOf(relation, SEL.GenericParameterType)) - g.claim(relation, L0.InstanceOf, SEL.GenericParameterType); - - CommentMetadata cm = g.getMetadata(CommentMetadata.class); - g.addMetadata(cm.add("Created new property " + name + " for " + g.getRelatedValue2(componentType, L0.HasName, Bindings.STRING) + " " + componentType.toString())); - - return relation; - } - - public static Resource createProperty(WriteGraph graph, Resource componentType, String name, String type, String unit, String range, String label, String description) throws DatabaseException { - - Resource property = createPropertyWithDefaults(graph, componentType); - rename(graph, property, name); - setRequiredType(graph, componentType, property, type); - convertDefaultValue(graph, componentType, property, type); - //setDefaultValue(graph, type, relation, valueText) - if (!type.equals("String")) { - setUnit(graph, componentType, property, unit); - setRange(graph, componentType, property, range); - } - setLabel(graph, property, label); - setDescription(graph, property, description); - - return property; - } - - public static void removeProperty(WriteGraph g, Resource componentType, Resource property) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(g); - for(Resource assertion : g.getObjects(property, L0.HasPredicateInverse)) - g.deny(assertion); - g.deny(property); - - String name = g.getPossibleRelatedValue2(componentType, L0.HasName); - - CommentMetadata cm = g.getMetadata(CommentMetadata.class); - g.addMetadata(cm.add("Removed property " + property + " from component/annotation " + name + ", resource "+ componentType)); - } - - public static void rename(WriteGraph g, Resource resource, String newName) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(g); - - String prevName = g.getPossibleRelatedValue2(resource, L0.HasName); - g.claimLiteral(resource, L0.HasName, newName); - - CommentMetadata cm = g.getMetadata(CommentMetadata.class); - g.addMetadata(cm.add("Renamed component/annotation type from " + prevName + " to " + newName + ", resource " + resource )); - } - - public static void setRequiredType(WriteGraph g, Resource property, - String requiredType) throws DatabaseException { - setRequiredType(g, null, property, requiredType); - } - - public static void setRequiredType(WriteGraph g, Resource componentType, Resource property, - String requiredType) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(g); - g.claimLiteral(property, L0.RequiresValueType, requiredType); - - if (componentType != null) { - StructuralResource2 STR = StructuralResource2.getInstance(g); - for (Resource assertedValue : g.getAssertedObjects(componentType, property)) { - if (g.isInstanceOf(assertedValue, STR.MonitorValue)) { - g.claimLiteral(assertedValue, L0.HasValueType, requiredType); - } - } - } - - CommentMetadata cm = g.getMetadata(CommentMetadata.class); - g.addMetadata(cm.add("Set required type "+ requiredType + " for component/annotation " + property)); - } - - public static void editType(WriteGraph graph, Resource componentType, Resource property, boolean convertDefaultValue, String newValue) throws DatabaseException { - ComponentTypeCommands.setRequiredType(graph, componentType, property, newValue); - if (convertDefaultValue) { - ComponentTypeCommands.convertDefaultValue(graph, componentType, property, newValue); - Map instances = graph.sync(new ModelInstances(componentType, componentType)); - for(Resource instance : instances.values()) { - ComponentTypeCommands.convertInstantiatedValue(graph, instance, property, newValue); - } - } - } - - static class AssertionMap extends UnaryRead> { - public AssertionMap(Resource parameter) { - super(parameter); - } - - @Override - public Map perform(ReadGraph graph) - throws DatabaseException { - THashMap result = new THashMap(); - Layer0 L0 = Layer0.getInstance(graph); - for(Resource assertion : graph.getObjects(parameter, L0.Asserts)) - result.put(graph.getSingleObject(assertion, L0.HasPredicate), - graph.getSingleObject(assertion, L0.HasObject)); - return result; - } - } - - public static Resource getAssertedObject(ReadGraph g, Resource type, Resource relation) throws DatabaseException { - return g.syncRequest(new AssertionMap(type)).get(relation); - } - - public static void setMonitorExpression(WriteGraph g, Resource type, Resource relation, - String valueText) throws DatabaseException { - - Resource object = getAssertedObject(g, type, relation); - if(object == null) { - System.err.println("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + - " in " + NameUtils.getSafeName(g, type) + "."); - return; - } - Layer0 L0 = Layer0.getInstance(g); - g.claimLiteral(object, L0.SCLValue_expression, valueText, Bindings.STRING); - - } - - public static void setDefaultValue(WriteGraph g, Resource type, Resource relation, - String valueText) throws DatabaseException { - - Resource object = getAssertedObject(g, type, relation); - if(object == null) { - System.err.println("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + - " in " + NameUtils.getSafeName(g, type) + "."); - return; - } - - if(valueText.length() > 0 && valueText.charAt(0) == '=') { - - String expression = valueText.substring(1); - Layer0 L0 = Layer0.getInstance(g); - ModelingResources MOD = ModelingResources.getInstance(g); - if(!g.isInstanceOf(object, MOD.SCLValue)) { - Resource assertion = g.getSingleObject(object, L0.HasObjectInverse); - g.deny(assertion, L0.HasObject, object); - object = g.newResource(); - g.claim(object, L0.InstanceOf, MOD.SCLValue); - g.claim(assertion, L0.HasObject, object); - } - g.claimLiteral(object, L0.SCLValue_expression, L0.String, expression, Bindings.STRING); - Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new expression '" + expression + "'"); - - } else { - - Layer0 L0 = Layer0.getInstance(g); - ModelingResources MOD = ModelingResources.getInstance(g); - if(g.isInstanceOf(object, MOD.SCLValue)) { - Resource assertion = g.getSingleObject(object, L0.HasObjectInverse); - g.deny(assertion, L0.HasObject, object); - object = g.newResource(); - String sclType = g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING); - Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(sclType); - g.claim(object, L0.InstanceOf, L0.Literal); - Binding ntb = Bindings.getBindingUnchecked(Datatype.class); - g.claimLiteral(object, L0.HasDataType, L0.DataType, newDatatype, ntb); - g.claim(assertion, L0.HasObject, object); - } - - Datatype dt = g.getDataType(object); - Binding binding = Bindings.getBinding(dt); - Object value; - try { - value = binding.parseValue(valueText, new DataValueRepository()); - g.claimValue(object, value, binding); - Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new value " + value.toString()); - } catch (DataTypeSyntaxError e) { - e.printStackTrace(); - } catch (BindingException e) { - e.printStackTrace(); - } - - } - - } - - /** - * @param graph graph write transaction handle - * @param type component type to edit - * @param relation component type property relation to edit - * @param unit null to remove unit description - * @throws DatabaseException - */ - public static void setUnit(WriteGraph graph, Resource type, Resource relation, String unit) throws DatabaseException { - Resource object = getAssertedObject(graph, type, relation); - if (object == null) { - System.err.println("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) + - " in " + NameUtils.getSafeName(graph, type) + "."); - return; - } - - Datatype dt = graph.getDataType(object); - if (dt instanceof NumberType) { - NumberType nt = (NumberType) dt; - Binding ntb = Bindings.getBindingUnchecked(Datatype.class); - nt.setUnit(unit); - - Layer0 L0 = Layer0.getInstance(graph); - Layer0X L0X = Layer0X.getInstance(graph); - - String oldUnit = graph.getPossibleRelatedValue2(relation, L0X.HasUnit, Bindings.STRING); - - graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, ntb); - graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, ntb); - graph.claimLiteral(relation, L0X.HasUnit, unit, Bindings.STRING); - - CommentMetadata cm = graph.getMetadata(CommentMetadata.class); - graph.addMetadata(cm.add("Setted unit from " + oldUnit + " to " + unit + " for component/annotation " + type)); - } - } - - /** - * @param graph graph write transaction handle - * @param type component type to modify - * @param relation property relation of a component type - * @param newRange new range definition or null to remove range restriction - * @throws DatabaseException - */ - public static void setRange(WriteGraph graph, Resource type, Resource relation, String newRange) throws DatabaseException { - Resource object = getAssertedObject(graph, type, relation); - if (object == null) { - System.err.println("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) + - " in " + NameUtils.getSafeName(graph, type) + "."); - return; - } - - Datatype dt = graph.getDataType(object); - if (dt instanceof NumberType) { - NumberType nt = (NumberType) dt; - Binding ntb = Bindings.getBindingUnchecked(Datatype.class); - nt.setRange(newRange); - - Layer0 L0 = Layer0.getInstance(graph); - Layer0X L0X = Layer0X.getInstance(graph); - - graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, ntb); - graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, ntb); - - CommentMetadata cm = graph.getMetadata(CommentMetadata.class); - graph.addMetadata(cm.add("Setted range " + newRange + " for component/annotation " + type)); - } - } - - public static Tuple getDatatypeValueAndBinding(ReadGraph g, Resource object, String newSCLType) throws DatabaseException { - - Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(newSCLType); - if(newDatatype == null) { - System.err.println("Couldn't convert default value to <" + newSCLType + ">."); - return null; - } - Binding newBinding = Bindings.getBinding(newDatatype); - - Datatype oldDatatype = g.getDataType(object); - Binding oldBinding = Bindings.getBinding(oldDatatype); - - Object oldValue = g.getValue(object, oldBinding); - Object newValue; - try { - newValue = Bindings.adapt(oldValue, oldBinding, newBinding); - } catch (AdaptException e) { - try { - newValue = newBinding.createDefault(); - } catch (BindingException e1) { - e1.printStackTrace(); - return null; - } - } - - return new Tuple3(newDatatype, newValue, newBinding); - - } - - public static void convertDefaultValue(WriteGraph g, - Resource type, Resource relation, String newSCLType) throws DatabaseException { - Resource object = getAssertedObject(g, type, relation); - if(object == null) { - System.err.println("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + - " in " + NameUtils.getSafeName(g, type) + "."); - return; - } - - Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType); - if (tuple == null) - return; - - Layer0 L0 = Layer0.getInstance(g); - g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class)); - g.claimLiteral(object, L0.HasValueType, g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING); - g.claimValue(object, tuple.get(1), (Binding)tuple.get(2)); - - } - - public static void convertInstantiatedValue(WriteGraph g, Resource instance, Resource relation, String newSCLType) - throws DatabaseException { - - Statement stm = g.getPossibleStatement(instance, relation); - if(stm != null && !stm.isAsserted(instance)) { - - Resource object = stm.getObject(); - - // We can only convert literals - Layer0 L0 = Layer0.getInstance(g); - if(!g.isInstanceOf(object, L0.Literal)) return; - - Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType); - - g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class)); - g.claimLiteral(object, L0.HasValueType, g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING); - g.claimValue(object, tuple.get(1), (Binding)tuple.get(2)); - - } - - } - - /** - * @param graph graph write transaction handle - * @param relation component type property relation to edit - * @param newDescription new label or null to remove label - * @throws DatabaseException - */ - public static void setLabel(WriteGraph graph, Resource relation, String newLabel) throws DatabaseException { - setProperty(graph, relation, Layer0.getInstance(graph).HasLabel, newLabel); - - CommentMetadata cm = graph.getMetadata(CommentMetadata.class); - graph.addMetadata(cm.add("Setted label " + newLabel + " for component/annotation " + relation)); - } - - /** - * @param graph graph write transaction handle - * @param relation component type property relation to edit - * @param newDescription new description or null if new description - * @throws DatabaseException - */ - public static void setDescription(WriteGraph graph, Resource relation, String newDescription) throws DatabaseException { - setProperty(graph, relation, Layer0.getInstance(graph).HasDescription, newDescription); - CommentMetadata cm = graph.getMetadata(CommentMetadata.class); - graph.addMetadata(cm.add("Setted description " + newDescription + " for component/annotation " + relation)); - } - - /** - * @param graph graph write transaction handle - * @param relation component type property relation to edit - * @param newValue new property value or null to remove property - * @throws DatabaseException - */ - public static void setProperty(WriteGraph graph, Resource relation, Resource property, String newValue) throws DatabaseException { - if (newValue != null) { - graph.claimLiteral(relation, property, newValue, Bindings.STRING); - } else { - graph.denyValue(relation, property); - } - } - - /** - * @param graph - * @param componentType - * @return the created symbol - */ - public static Resource createSymbol(WriteGraph graph, Resource componentType) throws DatabaseException { - return NewSymbol.createSymbol(graph, componentType); - } - - /** - * Converts to a camelCase name to a more user-readable - * Camel Case label. - * - *

- * Examples - *

-     * "fooBarBazBAR" => "Foo Bar Baz BAR"
-     * " fooBarBazBAR" => " Foo Bar Baz BAR"
-     * "_fooBarBazBAR" => "_Foo Bar Baz BAR"
-     * "_FooBarBazBAR" => "_Foo Bar Baz BAR"
-     * " _ fooBarBazBAR" => " _ Foo Bar Baz BAR"
-     * 
- * - * @param str camelCase SCL identifier name - * @return labelified Camel Case string - */ - public static String camelCaseNameToLabel(String str) { - int len = str.length(); - StringBuilder sb = new StringBuilder(len*2); - - boolean wasLastUpper = false; - boolean isFirstEncounteredLetter = true; - - for (int i = 0; i < len; ++i) { - char ch = str.charAt(i); - - boolean space = Character.isWhitespace(ch); - if (space) { - sb.append(ch); - continue; - } - - boolean isUpperCaseLetter = Character.isUpperCase(ch); - boolean isLetterOrDigit = Character.isLetterOrDigit(ch); - if (!isFirstEncounteredLetter && isUpperCaseLetter && !wasLastUpper && isLetterOrDigit) { - sb.append(' '); - sb.append(ch); - } else { - if (isLetterOrDigit && isFirstEncounteredLetter) - sb.append(Character.toUpperCase(ch)); - else - sb.append(ch); - if (isFirstEncounteredLetter) - isFirstEncounteredLetter = !isLetterOrDigit; - } - wasLastUpper = isUpperCaseLetter; - } - return sb.toString(); - } - - public static void saveProceduralCodeWithUC(WriteGraph graph, Resource componentType, String newText) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource code = graph.getPossibleObject(componentType, STR.ProceduralComponentType_code); - saveProceduralCode(graph, code, newText); - } - - public static void saveProceduralCode(WriteGraph graph, Resource resource, String newText) throws ServiceException { - graph.claimValue(resource, newText, Bindings.STRING); - Layer0Utils.addCommentMetadata(graph, "Saved Procedural Component Type SCL Code"); - } -} +/******************************************************************************* + * Copyright (c) 2012 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.modeling.userComponent; + +import java.util.Map; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.Datatypes; +import org.simantics.databoard.adapter.AdaptException; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.parser.repository.DataTypeSyntaxError; +import org.simantics.databoard.parser.repository.DataValueRepository; +import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.type.NumberType; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.CommentMetadata; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.ServiceException; +import org.simantics.db.layer0.request.ModelInstances; +import org.simantics.db.layer0.util.Layer0Utils; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.NewSymbol; +import org.simantics.operation.Layer0X; +import org.simantics.scl.runtime.tuple.Tuple; +import org.simantics.scl.runtime.tuple.Tuple3; +import org.simantics.selectionview.SelectionViewResources; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.structural2.utils.StructuralUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gnu.trove.map.hash.THashMap; + +public class ComponentTypeCommands { + + private static final Logger LOGGER = LoggerFactory.getLogger(ComponentTypeCommands.class); + + public static void applyCode(WriteGraph g, Resource componentType, String code) throws DatabaseException { + StructuralResource2 STR = StructuralResource2.getInstance(g); + g.claimLiteral(componentType, STR.ProceduralComponentType_code, code, Bindings.STRING); + } + + public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource cp) throws DatabaseException { + return StructuralUtils.createConnectionPoint(g, componentType, cp); + } + + public static Resource createMonitorPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(g); + StructuralResource2 STR = StructuralResource2.getInstance(g); + ModelingResources MOD = ModelingResources.getInstance(g); + + Resource monitorType = g.getPossibleObject(componentType, STR.ComponentType_HasDefaultMonitorValueType); + if(monitorType == null) monitorType = MOD.MonitorValue; + + Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty"); + g.claim(relation, L0.HasRange, monitorType); + + Resource assertion = g.newResource(); + g.claim(componentType, L0.Asserts, assertion); + g.claim(assertion, L0.InstanceOf, L0.Assertion); + g.claim(assertion, L0.HasPredicate, relation); + + Resource value = g.newResource(); + g.claim(value, L0.InstanceOf, monitorType); + g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING); + g.claimLiteral(value, L0.SCLValue_expression, L0.String, "", Bindings.STRING); + g.claim(assertion, L0.HasObject, value); + + return relation; + + } + + public static Resource createPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException { + g.markUndoPoint(); + Layer0 L0 = Layer0.getInstance(g); + + Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty"); + + Resource assertion = g.newResource(); + g.claim(componentType, L0.Asserts, assertion); + g.claim(assertion, L0.InstanceOf, L0.Assertion); + g.claim(assertion, L0.HasPredicate, relation); + + Resource value = g.newResource(); + g.claim(value, L0.InstanceOf, L0.Literal); + g.claimLiteral(value, L0.HasDataType, L0.DataType, Datatypes.DOUBLE, Bindings.getBindingUnchecked(Datatype.class)); + g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING); + g.claimValue(value, 0.0, Bindings.DOUBLE); + g.claim(assertion, L0.HasObject, value); + + return relation; + + } + + public static Resource createPropertyWithDefaultsBase(WriteGraph g, Resource componentType, String defaultName) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(g); + StructuralResource2 STR = StructuralResource2.getInstance(g); + ModelingResources MOD = ModelingResources.getInstance(g); + + String name = NameUtils.findFreshEscapedName(g, defaultName, componentType); + + Resource relation = g.newResource(); + g.claim(relation, L0.SubrelationOf, null, L0.HasProperty); + boolean hadProperty = false; + for(Resource type : g.getObjects(componentType, STR.ComponentType_HasDefaultPropertyRelationType)) { + if(g.isInheritedFrom(type, STR.Property)) hadProperty = true; + g.claim(relation, L0.InstanceOf, type); + } + if(!hadProperty) + g.claim(relation, L0.InstanceOf, STR.Property); + + g.claimLiteral(relation, L0.HasName, name); + g.claim(componentType, L0.ConsistsOf, L0.PartOf, relation); + g.claim(relation, L0.HasDomain, L0.DomainOf, componentType); + + Resource invRelation = g.newResource(); + g.claim(invRelation, L0.SubrelationOf, null, L0.PropertyOf); + g.claim(relation, L0.ConsistsOf, L0.PartOf, invRelation); + g.claimLiteral(invRelation, L0.HasName, "Inverse"); + g.claim(relation, L0.InverseOf, invRelation); + + g.claimLiteral(relation, L0.RequiresValueType, "Double"); + + SelectionViewResources SEL = SelectionViewResources.getInstance(g); + Resource category = g.getPossibleObject(relation, SEL.HasStandardPropertyInfo); + if(category == null) { + g.claim(relation, SEL.HasStandardPropertyInfo, MOD.UserDefinedPropertyInfo); + } + if(!g.isInstanceOf(relation, SEL.GenericParameterType)) + g.claim(relation, L0.InstanceOf, SEL.GenericParameterType); + + CommentMetadata cm = g.getMetadata(CommentMetadata.class); + g.addMetadata(cm.add("Created new property " + name + " for " + g.getRelatedValue2(componentType, L0.HasName, Bindings.STRING) + " " + componentType.toString())); + + return relation; + } + + public static Resource createProperty(WriteGraph graph, Resource componentType, String name, String type, String unit, String range, String label, String description) throws DatabaseException { + + Resource property = createPropertyWithDefaults(graph, componentType); + rename(graph, property, name); + setRequiredType(graph, componentType, property, type); + convertDefaultValue(graph, componentType, property, type); + //setDefaultValue(graph, type, relation, valueText) + if (!type.equals("String")) { + setUnit(graph, componentType, property, unit); + setRange(graph, componentType, property, range); + } + setLabel(graph, property, label); + setDescription(graph, property, description); + + return property; + } + + public static void removeProperty(WriteGraph g, Resource componentType, Resource property) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(g); + for(Resource assertion : g.getObjects(property, L0.HasPredicateInverse)) + g.deny(assertion); + g.deny(property); + + String name = g.getPossibleRelatedValue2(componentType, L0.HasName); + + CommentMetadata cm = g.getMetadata(CommentMetadata.class); + g.addMetadata(cm.add("Removed property " + property + " from component/annotation " + name + ", resource "+ componentType)); + } + + public static void rename(WriteGraph g, Resource resource, String newName) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(g); + + String prevName = g.getPossibleRelatedValue2(resource, L0.HasName); + g.claimLiteral(resource, L0.HasName, newName); + + CommentMetadata cm = g.getMetadata(CommentMetadata.class); + g.addMetadata(cm.add("Renamed component/annotation type from " + prevName + " to " + newName + ", resource " + resource )); + } + + public static void setRequiredType(WriteGraph g, Resource property, + String requiredType) throws DatabaseException { + setRequiredType(g, null, property, requiredType); + } + + public static void setRequiredType(WriteGraph g, Resource componentType, Resource property, + String requiredType) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(g); + g.claimLiteral(property, L0.RequiresValueType, requiredType); + + if (componentType != null) { + StructuralResource2 STR = StructuralResource2.getInstance(g); + for (Resource assertedValue : g.getAssertedObjects(componentType, property)) { + if (g.isInstanceOf(assertedValue, STR.MonitorValue)) { + g.claimLiteral(assertedValue, L0.HasValueType, requiredType); + } + } + } + + CommentMetadata cm = g.getMetadata(CommentMetadata.class); + g.addMetadata(cm.add("Set required type "+ requiredType + " for component/annotation " + property)); + } + + public static void editType(WriteGraph graph, Resource componentType, Resource property, boolean convertDefaultValue, String newValue) throws DatabaseException { + ComponentTypeCommands.setRequiredType(graph, componentType, property, newValue); + if (convertDefaultValue) { + ComponentTypeCommands.convertDefaultValue(graph, componentType, property, newValue); + Map instances = graph.sync(new ModelInstances(componentType, componentType)); + for(Resource instance : instances.values()) { + ComponentTypeCommands.convertInstantiatedValue(graph, instance, property, newValue); + } + } + } + + static class AssertionMap extends UnaryRead> { + public AssertionMap(Resource parameter) { + super(parameter); + } + + @Override + public Map perform(ReadGraph graph) + throws DatabaseException { + THashMap result = new THashMap(); + Layer0 L0 = Layer0.getInstance(graph); + for(Resource assertion : graph.getObjects(parameter, L0.Asserts)) + result.put(graph.getSingleObject(assertion, L0.HasPredicate), + graph.getSingleObject(assertion, L0.HasObject)); + return result; + } + } + + public static Resource getAssertedObject(ReadGraph g, Resource type, Resource relation) throws DatabaseException { + return g.syncRequest(new AssertionMap(type)).get(relation); + } + + public static void setMonitorExpression(WriteGraph g, Resource type, Resource relation, + String valueText) throws DatabaseException { + + Resource object = getAssertedObject(g, type, relation); + if(object == null) { + LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + + " in " + NameUtils.getSafeName(g, type) + "."); + return; + } + Layer0 L0 = Layer0.getInstance(g); + g.claimLiteral(object, L0.SCLValue_expression, valueText, Bindings.STRING); + + } + + public static void setDefaultValue(WriteGraph g, Resource type, Resource relation, + String valueText) throws DatabaseException { + + Resource object = getAssertedObject(g, type, relation); + if(object == null) { + LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + + " in " + NameUtils.getSafeName(g, type) + "."); + return; + } + + if(valueText.length() > 0 && valueText.charAt(0) == '=') { + + String expression = valueText.substring(1); + Layer0 L0 = Layer0.getInstance(g); + ModelingResources MOD = ModelingResources.getInstance(g); + if(!g.isInstanceOf(object, MOD.SCLValue)) { + Resource assertion = g.getSingleObject(object, L0.HasObjectInverse); + g.deny(assertion, L0.HasObject, object); + object = g.newResource(); + g.claim(object, L0.InstanceOf, MOD.SCLValue); + g.claim(assertion, L0.HasObject, object); + } + g.claimLiteral(object, L0.SCLValue_expression, L0.String, expression, Bindings.STRING); + Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new expression '" + expression + "'"); + + } else { + + Layer0 L0 = Layer0.getInstance(g); + ModelingResources MOD = ModelingResources.getInstance(g); + if(g.isInstanceOf(object, MOD.SCLValue)) { + Resource assertion = g.getSingleObject(object, L0.HasObjectInverse); + g.deny(assertion, L0.HasObject, object); + object = g.newResource(); + String sclType = g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING); + Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(sclType); + g.claim(object, L0.InstanceOf, L0.Literal); + Binding ntb = Bindings.getBindingUnchecked(Datatype.class); + g.claimLiteral(object, L0.HasDataType, L0.DataType, newDatatype, ntb); + g.claim(assertion, L0.HasObject, object); + } + + Datatype dt = g.getDataType(object); + Binding binding = Bindings.getBinding(dt); + Object value; + try { + value = binding.parseValue(valueText, new DataValueRepository()); + g.claimValue(object, value, binding); + Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new value " + value.toString()); + } catch (DataTypeSyntaxError e) { + e.printStackTrace(); + } catch (BindingException e) { + e.printStackTrace(); + } + + } + + } + + /** + * @param graph graph write transaction handle + * @param type component type to edit + * @param relation component type property relation to edit + * @param unit null to remove unit description + * @throws DatabaseException + */ + public static void setUnit(WriteGraph graph, Resource type, Resource relation, String unit) throws DatabaseException { + Resource object = getAssertedObject(graph, type, relation); + if (object == null) { + LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) + + " in " + NameUtils.getSafeName(graph, type) + "."); + return; + } + + Layer0 L0 = Layer0.getInstance(graph); + Layer0X L0X = Layer0X.getInstance(graph); + boolean hasRequiresDataType = graph.hasStatement(relation, L0X.RequiresDataType); + if (hasRequiresDataType) { + Datatype dt = graph.getDataType(object); + if (dt instanceof NumberType) { + NumberType nt = (NumberType) Bindings.DATATYPE.cloneUnchecked(dt); + nt.setUnit(unit); + graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, Bindings.DATATYPE); + graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, Bindings.DATATYPE); + } + } + + String oldUnit = graph.getPossibleRelatedValue2(relation, L0X.HasUnit, Bindings.STRING); + if (unit != null) { + graph.claimLiteral(relation, L0X.HasUnit, L0.String, unit, Bindings.STRING); + } else { + graph.denyValue(relation, L0X.HasUnit); + } + + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add("Set unit from " + oldUnit + " to " + unit + " for component/annotation " + type + " property " + relation)); + } + + /** + * @param graph graph write transaction handle + * @param type component type to modify + * @param relation property relation of a component type + * @param newRange new range definition or null to remove range restriction + * @throws DatabaseException + */ + public static void setRange(WriteGraph graph, Resource type, Resource relation, String newRange) throws DatabaseException { + Resource object = getAssertedObject(graph, type, relation); + if (object == null) { + LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) + + " in " + NameUtils.getSafeName(graph, type) + "."); + return; + } + + Datatype dt = graph.getDataType(object); + if (dt instanceof NumberType) { + NumberType nt = (NumberType) dt; + Binding ntb = Bindings.getBindingUnchecked(Datatype.class); + nt.setRange(newRange); + + Layer0 L0 = Layer0.getInstance(graph); + Layer0X L0X = Layer0X.getInstance(graph); + + graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, ntb); + graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, ntb); + + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add("Setted range " + newRange + " for component/annotation " + type)); + } + } + + public static Tuple getDatatypeValueAndBinding(ReadGraph g, Resource object, String newSCLType) throws DatabaseException { + + Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(newSCLType); + if(newDatatype == null) { + LOGGER.warn("Couldn't convert default value to <" + newSCLType + ">."); + return null; + } + Binding newBinding = Bindings.getBinding(newDatatype); + + Datatype oldDatatype = g.getDataType(object); + Binding oldBinding = Bindings.getBinding(oldDatatype); + + Object oldValue = g.getValue(object, oldBinding); + Object newValue; + try { + newValue = Bindings.adapt(oldValue, oldBinding, newBinding); + } catch (AdaptException e) { + try { + newValue = newBinding.createDefault(); + } catch (BindingException e1) { + e1.printStackTrace(); + return null; + } + } + + return new Tuple3(newDatatype, newValue, newBinding); + + } + + public static void convertDefaultValue(WriteGraph g, + Resource type, Resource relation, String newSCLType) throws DatabaseException { + Resource object = getAssertedObject(g, type, relation); + if(object == null) { + LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + + " in " + NameUtils.getSafeName(g, type) + "."); + return; + } + + Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType); + if (tuple == null) + return; + + Layer0 L0 = Layer0.getInstance(g); + g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class)); + g.claimLiteral(object, L0.HasValueType, g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING); + g.claimValue(object, tuple.get(1), (Binding)tuple.get(2)); + + } + + public static void convertInstantiatedValue(WriteGraph g, Resource instance, Resource relation, String newSCLType) + throws DatabaseException { + + Statement stm = g.getPossibleStatement(instance, relation); + if(stm != null && !stm.isAsserted(instance)) { + + Resource object = stm.getObject(); + + // We can only convert literals + Layer0 L0 = Layer0.getInstance(g); + if(!g.isInstanceOf(object, L0.Literal)) return; + + Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType); + + g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class)); + g.claimLiteral(object, L0.HasValueType, g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING); + g.claimValue(object, tuple.get(1), (Binding)tuple.get(2)); + + } + + } + + /** + * @param graph graph write transaction handle + * @param relation component type property relation to edit + * @param newDescription new label or null to remove label + * @throws DatabaseException + */ + public static void setLabel(WriteGraph graph, Resource relation, String newLabel) throws DatabaseException { + setProperty(graph, relation, Layer0.getInstance(graph).HasLabel, newLabel); + + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add("Setted label " + newLabel + " for component/annotation " + relation)); + } + + /** + * @param graph graph write transaction handle + * @param relation component type property relation to edit + * @param newDescription new description or null if new description + * @throws DatabaseException + */ + public static void setDescription(WriteGraph graph, Resource relation, String newDescription) throws DatabaseException { + setProperty(graph, relation, Layer0.getInstance(graph).HasDescription, newDescription); + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add("Setted description " + newDescription + " for component/annotation " + relation)); + } + + /** + * @param graph graph write transaction handle + * @param relation component type property relation to edit + * @param newValue new property value or null to remove property + * @throws DatabaseException + */ + public static void setProperty(WriteGraph graph, Resource relation, Resource property, String newValue) throws DatabaseException { + if (newValue != null) { + graph.claimLiteral(relation, property, newValue, Bindings.STRING); + } else { + graph.denyValue(relation, property); + } + } + + /** + * @param graph + * @param componentType + * @return the created symbol + */ + public static Resource createSymbol(WriteGraph graph, Resource componentType) throws DatabaseException { + return NewSymbol.createSymbol(graph, componentType); + } + + /** + * Converts to a camelCase name to a more user-readable + * Camel Case label. + * + *

+ * Examples + *

+     * "fooBarBazBAR" => "Foo Bar Baz BAR"
+     * " fooBarBazBAR" => " Foo Bar Baz BAR"
+     * "_fooBarBazBAR" => "_Foo Bar Baz BAR"
+     * "_FooBarBazBAR" => "_Foo Bar Baz BAR"
+     * " _ fooBarBazBAR" => " _ Foo Bar Baz BAR"
+     * 
+ * + * @param str camelCase SCL identifier name + * @return labelified Camel Case string + */ + public static String camelCaseNameToLabel(String str) { + int len = str.length(); + StringBuilder sb = new StringBuilder(len*2); + + boolean wasLastUpper = false; + boolean isFirstEncounteredLetter = true; + + for (int i = 0; i < len; ++i) { + char ch = str.charAt(i); + + boolean space = Character.isWhitespace(ch); + if (space) { + sb.append(ch); + continue; + } + + boolean isUpperCaseLetter = Character.isUpperCase(ch); + boolean isLetterOrDigit = Character.isLetterOrDigit(ch); + if (!isFirstEncounteredLetter && isUpperCaseLetter && !wasLastUpper && isLetterOrDigit) { + sb.append(' '); + sb.append(ch); + } else { + if (isLetterOrDigit && isFirstEncounteredLetter) + sb.append(Character.toUpperCase(ch)); + else + sb.append(ch); + if (isFirstEncounteredLetter) + isFirstEncounteredLetter = !isLetterOrDigit; + } + wasLastUpper = isUpperCaseLetter; + } + return sb.toString(); + } + + public static void saveProceduralCodeWithUC(WriteGraph graph, Resource componentType, String newText) throws DatabaseException { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource code = graph.getPossibleObject(componentType, STR.ProceduralComponentType_code); + saveProceduralCode(graph, code, newText); + } + + public static void saveProceduralCode(WriteGraph graph, Resource resource, String newText) throws ServiceException { + graph.claimValue(resource, newText, Bindings.STRING); + Layer0Utils.addCommentMetadata(graph, "Saved Procedural Component Type SCL Code"); + } +}