1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management in
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.modeling.userComponent;
14 import gnu.trove.map.hash.THashMap;
18 import org.simantics.databoard.Bindings;
19 import org.simantics.databoard.Datatypes;
20 import org.simantics.databoard.adapter.AdaptException;
21 import org.simantics.databoard.binding.Binding;
22 import org.simantics.databoard.binding.error.BindingException;
23 import org.simantics.databoard.parser.repository.DataTypeSyntaxError;
24 import org.simantics.databoard.parser.repository.DataValueRepository;
25 import org.simantics.databoard.type.Datatype;
26 import org.simantics.databoard.type.NumberType;
27 import org.simantics.db.ReadGraph;
28 import org.simantics.db.Resource;
29 import org.simantics.db.Statement;
30 import org.simantics.db.WriteGraph;
31 import org.simantics.db.common.CommentMetadata;
32 import org.simantics.db.common.request.UnaryRead;
33 import org.simantics.db.common.utils.NameUtils;
34 import org.simantics.db.exception.DatabaseException;
35 import org.simantics.db.exception.ServiceException;
36 import org.simantics.db.layer0.request.ModelInstances;
37 import org.simantics.db.layer0.util.Layer0Utils;
38 import org.simantics.layer0.Layer0;
39 import org.simantics.modeling.ModelingResources;
40 import org.simantics.modeling.NewSymbol;
41 import org.simantics.operation.Layer0X;
42 import org.simantics.scl.runtime.tuple.Tuple;
43 import org.simantics.scl.runtime.tuple.Tuple3;
44 import org.simantics.selectionview.SelectionViewResources;
45 import org.simantics.structural.stubs.StructuralResource2;
46 import org.simantics.structural2.utils.StructuralUtils;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 public class ComponentTypeCommands {
52 private static final Logger LOGGER = LoggerFactory.getLogger(ComponentTypeCommands.class);
54 public static void applyCode(WriteGraph g, Resource componentType, String code) throws DatabaseException {
55 StructuralResource2 STR = StructuralResource2.getInstance(g);
56 g.claimLiteral(componentType, STR.ProceduralComponentType_code, code, Bindings.STRING);
59 public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource cp) throws DatabaseException {
60 return StructuralUtils.createConnectionPoint(g, componentType, cp);
63 public static Resource createMonitorPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException {
65 Layer0 L0 = Layer0.getInstance(g);
66 StructuralResource2 STR = StructuralResource2.getInstance(g);
67 ModelingResources MOD = ModelingResources.getInstance(g);
69 Resource monitorType = g.getPossibleObject(componentType, STR.ComponentType_HasDefaultMonitorValueType);
70 if(monitorType == null) monitorType = MOD.MonitorValue;
72 Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty");
73 g.claim(relation, L0.HasRange, monitorType);
75 Resource assertion = g.newResource();
76 g.claim(componentType, L0.Asserts, assertion);
77 g.claim(assertion, L0.InstanceOf, L0.Assertion);
78 g.claim(assertion, L0.HasPredicate, relation);
80 Resource value = g.newResource();
81 g.claim(value, L0.InstanceOf, monitorType);
82 g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING);
83 g.claimLiteral(value, L0.SCLValue_expression, L0.String, "", Bindings.STRING);
84 g.claim(assertion, L0.HasObject, value);
90 public static Resource createPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException {
92 Layer0 L0 = Layer0.getInstance(g);
94 Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty");
96 Resource assertion = g.newResource();
97 g.claim(componentType, L0.Asserts, assertion);
98 g.claim(assertion, L0.InstanceOf, L0.Assertion);
99 g.claim(assertion, L0.HasPredicate, relation);
101 Resource value = g.newResource();
102 g.claim(value, L0.InstanceOf, L0.Literal);
103 g.claimLiteral(value, L0.HasDataType, L0.DataType, Datatypes.DOUBLE, Bindings.getBindingUnchecked(Datatype.class));
104 g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING);
105 g.claimValue(value, 0.0, Bindings.DOUBLE);
106 g.claim(assertion, L0.HasObject, value);
112 public static Resource createPropertyWithDefaultsBase(WriteGraph g, Resource componentType, String defaultName) throws DatabaseException {
114 Layer0 L0 = Layer0.getInstance(g);
115 StructuralResource2 STR = StructuralResource2.getInstance(g);
116 ModelingResources MOD = ModelingResources.getInstance(g);
118 String name = NameUtils.findFreshEscapedName(g, defaultName, componentType);
120 Resource relation = g.newResource();
121 g.claim(relation, L0.SubrelationOf, null, L0.HasProperty);
122 boolean hadProperty = false;
123 for(Resource type : g.getObjects(componentType, STR.ComponentType_HasDefaultPropertyRelationType)) {
124 if(g.isInheritedFrom(type, STR.Property)) hadProperty = true;
125 g.claim(relation, L0.InstanceOf, type);
128 g.claim(relation, L0.InstanceOf, STR.Property);
130 g.claimLiteral(relation, L0.HasName, name);
131 g.claim(componentType, L0.ConsistsOf, L0.PartOf, relation);
132 g.claim(relation, L0.HasDomain, L0.DomainOf, componentType);
134 Resource invRelation = g.newResource();
135 g.claim(invRelation, L0.SubrelationOf, null, L0.PropertyOf);
136 g.claim(relation, L0.ConsistsOf, L0.PartOf, invRelation);
137 g.claimLiteral(invRelation, L0.HasName, "Inverse");
138 g.claim(relation, L0.InverseOf, invRelation);
140 g.claimLiteral(relation, L0.RequiresValueType, "Double");
142 SelectionViewResources SEL = SelectionViewResources.getInstance(g);
143 Resource category = g.getPossibleObject(relation, SEL.HasStandardPropertyInfo);
144 if(category == null) {
145 g.claim(relation, SEL.HasStandardPropertyInfo, MOD.UserDefinedPropertyInfo);
147 if(!g.isInstanceOf(relation, SEL.GenericParameterType))
148 g.claim(relation, L0.InstanceOf, SEL.GenericParameterType);
150 CommentMetadata cm = g.getMetadata(CommentMetadata.class);
151 g.addMetadata(cm.add("Created new property " + name + " for " + g.getRelatedValue2(componentType, L0.HasName, Bindings.STRING) + " " + componentType.toString()));
156 public static Resource createProperty(WriteGraph graph, Resource componentType, String name, String type, String unit, String range, String label, String description) throws DatabaseException {
158 Resource property = createPropertyWithDefaults(graph, componentType);
159 rename(graph, property, name);
160 setRequiredType(graph, componentType, property, type);
161 convertDefaultValue(graph, componentType, property, type);
162 //setDefaultValue(graph, type, relation, valueText)
163 if (!type.equals("String")) {
164 setUnit(graph, componentType, property, unit);
165 setRange(graph, componentType, property, range);
167 setLabel(graph, property, label);
168 setDescription(graph, property, description);
173 public static void removeProperty(WriteGraph g, Resource componentType, Resource property) throws DatabaseException {
174 Layer0 L0 = Layer0.getInstance(g);
175 for(Resource assertion : g.getObjects(property, L0.HasPredicateInverse))
179 String name = g.getPossibleRelatedValue2(componentType, L0.HasName);
181 CommentMetadata cm = g.getMetadata(CommentMetadata.class);
182 g.addMetadata(cm.add("Removed property " + property + " from component/annotation " + name + ", resource "+ componentType));
185 public static void rename(WriteGraph g, Resource resource, String newName) throws DatabaseException {
186 Layer0 L0 = Layer0.getInstance(g);
188 String prevName = g.getPossibleRelatedValue2(resource, L0.HasName);
189 g.claimLiteral(resource, L0.HasName, newName);
191 CommentMetadata cm = g.getMetadata(CommentMetadata.class);
192 g.addMetadata(cm.add("Renamed component/annotation type from " + prevName + " to " + newName + ", resource " + resource ));
195 public static void setRequiredType(WriteGraph g, Resource property,
196 String requiredType) throws DatabaseException {
197 setRequiredType(g, null, property, requiredType);
200 public static void setRequiredType(WriteGraph g, Resource componentType, Resource property,
201 String requiredType) throws DatabaseException {
202 Layer0 L0 = Layer0.getInstance(g);
203 g.claimLiteral(property, L0.RequiresValueType, requiredType);
205 if (componentType != null) {
206 StructuralResource2 STR = StructuralResource2.getInstance(g);
207 for (Resource assertedValue : g.getAssertedObjects(componentType, property)) {
208 if (g.isInstanceOf(assertedValue, STR.MonitorValue)) {
209 g.claimLiteral(assertedValue, L0.HasValueType, requiredType);
214 CommentMetadata cm = g.getMetadata(CommentMetadata.class);
215 g.addMetadata(cm.add("Set required type "+ requiredType + " for component/annotation " + property));
218 public static void editType(WriteGraph graph, Resource componentType, Resource property, boolean convertDefaultValue, String newValue) throws DatabaseException {
219 ComponentTypeCommands.setRequiredType(graph, componentType, property, newValue);
220 if (convertDefaultValue) {
221 ComponentTypeCommands.convertDefaultValue(graph, componentType, property, newValue);
222 Map<String, Resource> instances = graph.sync(new ModelInstances(componentType, componentType));
223 for(Resource instance : instances.values()) {
224 ComponentTypeCommands.convertInstantiatedValue(graph, instance, property, newValue);
229 static class AssertionMap extends UnaryRead<Resource, Map<Resource,Resource>> {
230 public AssertionMap(Resource parameter) {
235 public Map<Resource, Resource> perform(ReadGraph graph)
236 throws DatabaseException {
237 THashMap<Resource,Resource> result = new THashMap<Resource, Resource>();
238 Layer0 L0 = Layer0.getInstance(graph);
239 for(Resource assertion : graph.getObjects(parameter, L0.Asserts))
240 result.put(graph.getSingleObject(assertion, L0.HasPredicate),
241 graph.getSingleObject(assertion, L0.HasObject));
246 public static Resource getAssertedObject(ReadGraph g, Resource type, Resource relation) throws DatabaseException {
247 return g.syncRequest(new AssertionMap(type)).get(relation);
250 public static void setMonitorExpression(WriteGraph g, Resource type, Resource relation,
251 String valueText) throws DatabaseException {
253 Resource object = getAssertedObject(g, type, relation);
255 LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) +
256 " in " + NameUtils.getSafeName(g, type) + ".");
259 Layer0 L0 = Layer0.getInstance(g);
260 g.claimLiteral(object, L0.SCLValue_expression, valueText, Bindings.STRING);
264 public static void setDefaultValue(WriteGraph g, Resource type, Resource relation,
265 String valueText) throws DatabaseException {
267 Resource object = getAssertedObject(g, type, relation);
269 LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) +
270 " in " + NameUtils.getSafeName(g, type) + ".");
274 if(valueText.length() > 0 && valueText.charAt(0) == '=') {
276 String expression = valueText.substring(1);
277 Layer0 L0 = Layer0.getInstance(g);
278 ModelingResources MOD = ModelingResources.getInstance(g);
279 if(!g.isInstanceOf(object, MOD.SCLValue)) {
280 Resource assertion = g.getSingleObject(object, L0.HasObjectInverse);
281 g.deny(assertion, L0.HasObject, object);
282 object = g.newResource();
283 g.claim(object, L0.InstanceOf, MOD.SCLValue);
284 g.claim(assertion, L0.HasObject, object);
286 g.claimLiteral(object, L0.SCLValue_expression, L0.String, expression, Bindings.STRING);
287 Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new expression '" + expression + "'");
291 Layer0 L0 = Layer0.getInstance(g);
292 ModelingResources MOD = ModelingResources.getInstance(g);
293 if(g.isInstanceOf(object, MOD.SCLValue)) {
294 Resource assertion = g.getSingleObject(object, L0.HasObjectInverse);
295 g.deny(assertion, L0.HasObject, object);
296 object = g.newResource();
297 String sclType = g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING);
298 Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(sclType);
299 g.claim(object, L0.InstanceOf, L0.Literal);
300 Binding ntb = Bindings.getBindingUnchecked(Datatype.class);
301 g.claimLiteral(object, L0.HasDataType, L0.DataType, newDatatype, ntb);
302 g.claim(assertion, L0.HasObject, object);
305 Datatype dt = g.getDataType(object);
306 Binding binding = Bindings.getBinding(dt);
309 value = binding.parseValue(valueText, new DataValueRepository());
310 g.claimValue(object, value, binding);
311 Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new value " + value.toString());
312 } catch (DataTypeSyntaxError e) {
314 } catch (BindingException e) {
323 * @param graph graph write transaction handle
324 * @param type component type to edit
325 * @param relation component type property relation to edit
326 * @param unit <code>null</code> to remove unit description
327 * @throws DatabaseException
329 public static void setUnit(WriteGraph graph, Resource type, Resource relation, String unit) throws DatabaseException {
330 Resource object = getAssertedObject(graph, type, relation);
331 if (object == null) {
332 LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) +
333 " in " + NameUtils.getSafeName(graph, type) + ".");
337 Datatype dt = graph.getDataType(object);
338 if (dt instanceof NumberType) {
339 NumberType nt = (NumberType) dt;
340 Binding ntb = Bindings.getBindingUnchecked(Datatype.class);
343 Layer0 L0 = Layer0.getInstance(graph);
344 Layer0X L0X = Layer0X.getInstance(graph);
346 String oldUnit = graph.getPossibleRelatedValue2(relation, L0X.HasUnit, Bindings.STRING);
348 graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, ntb);
349 graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, ntb);
350 graph.claimLiteral(relation, L0X.HasUnit, unit, Bindings.STRING);
352 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
353 graph.addMetadata(cm.add("Setted unit from " + oldUnit + " to " + unit + " for component/annotation " + type));
358 * @param graph graph write transaction handle
359 * @param type component type to modify
360 * @param relation property relation of a component type
361 * @param newRange new range definition or <code>null</code> to remove range restriction
362 * @throws DatabaseException
364 public static void setRange(WriteGraph graph, Resource type, Resource relation, String newRange) throws DatabaseException {
365 Resource object = getAssertedObject(graph, type, relation);
366 if (object == null) {
367 LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) +
368 " in " + NameUtils.getSafeName(graph, type) + ".");
372 Datatype dt = graph.getDataType(object);
373 if (dt instanceof NumberType) {
374 NumberType nt = (NumberType) dt;
375 Binding ntb = Bindings.getBindingUnchecked(Datatype.class);
376 nt.setRange(newRange);
378 Layer0 L0 = Layer0.getInstance(graph);
379 Layer0X L0X = Layer0X.getInstance(graph);
381 graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, ntb);
382 graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, ntb);
384 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
385 graph.addMetadata(cm.add("Setted range " + newRange + " for component/annotation " + type));
389 public static Tuple getDatatypeValueAndBinding(ReadGraph g, Resource object, String newSCLType) throws DatabaseException {
391 Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(newSCLType);
392 if(newDatatype == null) {
393 LOGGER.warn("Couldn't convert default value to <" + newSCLType + ">.");
396 Binding newBinding = Bindings.getBinding(newDatatype);
398 Datatype oldDatatype = g.getDataType(object);
399 Binding oldBinding = Bindings.getBinding(oldDatatype);
401 Object oldValue = g.getValue(object, oldBinding);
404 newValue = Bindings.adapt(oldValue, oldBinding, newBinding);
405 } catch (AdaptException e) {
407 newValue = newBinding.createDefault();
408 } catch (BindingException e1) {
409 e1.printStackTrace();
414 return new Tuple3(newDatatype, newValue, newBinding);
418 public static void convertDefaultValue(WriteGraph g,
419 Resource type, Resource relation, String newSCLType) throws DatabaseException {
420 Resource object = getAssertedObject(g, type, relation);
422 LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) +
423 " in " + NameUtils.getSafeName(g, type) + ".");
427 Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType);
431 Layer0 L0 = Layer0.getInstance(g);
432 g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class));
433 g.claimLiteral(object, L0.HasValueType, g.<String>getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING);
434 g.claimValue(object, tuple.get(1), (Binding)tuple.get(2));
438 public static void convertInstantiatedValue(WriteGraph g, Resource instance, Resource relation, String newSCLType)
439 throws DatabaseException {
441 Statement stm = g.getPossibleStatement(instance, relation);
442 if(stm != null && !stm.isAsserted(instance)) {
444 Resource object = stm.getObject();
446 // We can only convert literals
447 Layer0 L0 = Layer0.getInstance(g);
448 if(!g.isInstanceOf(object, L0.Literal)) return;
450 Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType);
452 g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class));
453 g.claimLiteral(object, L0.HasValueType, g.<String>getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING);
454 g.claimValue(object, tuple.get(1), (Binding)tuple.get(2));
461 * @param graph graph write transaction handle
462 * @param relation component type property relation to edit
463 * @param newDescription new label or <code>null</code> to remove label
464 * @throws DatabaseException
466 public static void setLabel(WriteGraph graph, Resource relation, String newLabel) throws DatabaseException {
467 setProperty(graph, relation, Layer0.getInstance(graph).HasLabel, newLabel);
469 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
470 graph.addMetadata(cm.add("Setted label " + newLabel + " for component/annotation " + relation));
474 * @param graph graph write transaction handle
475 * @param relation component type property relation to edit
476 * @param newDescription new description or <code>null</code> if new description
477 * @throws DatabaseException
479 public static void setDescription(WriteGraph graph, Resource relation, String newDescription) throws DatabaseException {
480 setProperty(graph, relation, Layer0.getInstance(graph).HasDescription, newDescription);
481 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
482 graph.addMetadata(cm.add("Setted description " + newDescription + " for component/annotation " + relation));
486 * @param graph graph write transaction handle
487 * @param relation component type property relation to edit
488 * @param newValue new property value or <code>null</code> to remove property
489 * @throws DatabaseException
491 public static void setProperty(WriteGraph graph, Resource relation, Resource property, String newValue) throws DatabaseException {
492 if (newValue != null) {
493 graph.claimLiteral(relation, property, newValue, Bindings.STRING);
495 graph.denyValue(relation, property);
501 * @param componentType
502 * @return the created symbol
504 public static Resource createSymbol(WriteGraph graph, Resource componentType) throws DatabaseException {
505 return NewSymbol.createSymbol(graph, componentType);
509 * Converts to a <code>camelCase</code> name to a more user-readable
510 * <code>Camel Case</code> label.
515 * "fooBarBazBAR" => "Foo Bar Baz BAR"
516 * " fooBarBazBAR" => " Foo Bar Baz BAR"
517 * "_fooBarBazBAR" => "_Foo Bar Baz BAR"
518 * "_FooBarBazBAR" => "_Foo Bar Baz BAR"
519 * " _ fooBarBazBAR" => " _ Foo Bar Baz BAR"
522 * @param str camelCase SCL identifier name
523 * @return labelified Camel Case string
525 public static String camelCaseNameToLabel(String str) {
526 int len = str.length();
527 StringBuilder sb = new StringBuilder(len*2);
529 boolean wasLastUpper = false;
530 boolean isFirstEncounteredLetter = true;
532 for (int i = 0; i < len; ++i) {
533 char ch = str.charAt(i);
535 boolean space = Character.isWhitespace(ch);
541 boolean isUpperCaseLetter = Character.isUpperCase(ch);
542 boolean isLetterOrDigit = Character.isLetterOrDigit(ch);
543 if (!isFirstEncounteredLetter && isUpperCaseLetter && !wasLastUpper && isLetterOrDigit) {
547 if (isLetterOrDigit && isFirstEncounteredLetter)
548 sb.append(Character.toUpperCase(ch));
551 if (isFirstEncounteredLetter)
552 isFirstEncounteredLetter = !isLetterOrDigit;
554 wasLastUpper = isUpperCaseLetter;
556 return sb.toString();
559 public static void saveProceduralCodeWithUC(WriteGraph graph, Resource componentType, String newText) throws DatabaseException {
560 StructuralResource2 STR = StructuralResource2.getInstance(graph);
561 Resource code = graph.getPossibleObject(componentType, STR.ProceduralComponentType_code);
562 saveProceduralCode(graph, code, newText);
565 public static void saveProceduralCode(WriteGraph graph, Resource resource, String newText) throws ServiceException {
566 graph.claimValue(resource, newText, Bindings.STRING);
567 Layer0Utils.addCommentMetadata(graph, "Saved Procedural Component Type SCL Code");