]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/userComponent/ComponentTypeCommands.java
Merge branch 'bug-623' into release/1.43.0.1
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / userComponent / ComponentTypeCommands.java
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management in
3  * Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.userComponent;
13
14 import java.util.Collections;
15 import java.util.Map;
16
17 import org.simantics.databoard.Bindings;
18 import org.simantics.databoard.Datatypes;
19 import org.simantics.databoard.adapter.AdaptException;
20 import org.simantics.databoard.binding.Binding;
21 import org.simantics.databoard.binding.error.BindingException;
22 import org.simantics.databoard.parser.repository.DataTypeSyntaxError;
23 import org.simantics.databoard.parser.repository.DataValueRepository;
24 import org.simantics.databoard.type.Datatype;
25 import org.simantics.databoard.type.NumberType;
26 import org.simantics.db.ReadGraph;
27 import org.simantics.db.Resource;
28 import org.simantics.db.Statement;
29 import org.simantics.db.WriteGraph;
30 import org.simantics.db.common.CommentMetadata;
31 import org.simantics.db.common.request.EnumerationMap;
32 import org.simantics.db.common.request.IsEnumeratedValue;
33 import org.simantics.db.common.request.UnaryRead;
34 import org.simantics.db.common.utils.NameUtils;
35 import org.simantics.db.exception.DatabaseException;
36 import org.simantics.db.exception.ServiceException;
37 import org.simantics.db.layer0.QueryIndexUtils;
38 import org.simantics.db.layer0.util.Layer0Utils;
39 import org.simantics.layer0.Layer0;
40 import org.simantics.modeling.ModelingResources;
41 import org.simantics.modeling.NewSymbol;
42 import org.simantics.operation.Layer0X;
43 import org.simantics.scl.runtime.tuple.Tuple;
44 import org.simantics.scl.runtime.tuple.Tuple3;
45 import org.simantics.selectionview.SelectionViewResources;
46 import org.simantics.structural.stubs.StructuralResource2;
47 import org.simantics.structural2.utils.StructuralUtils;
48 import org.simantics.utils.strings.AlphanumComparator;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import gnu.trove.map.hash.THashMap;
53
54 public class ComponentTypeCommands {
55
56     private static final Logger LOGGER = LoggerFactory.getLogger(ComponentTypeCommands.class);
57
58     public static void applyCode(WriteGraph g, Resource componentType, String code) throws DatabaseException {
59         StructuralResource2 STR = StructuralResource2.getInstance(g);
60         g.claimLiteral(componentType, STR.ProceduralComponentType_code, code, Bindings.STRING);
61     }
62
63     public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource cp) throws DatabaseException {
64         return StructuralUtils.createConnectionPoint(g, componentType, cp);
65     }
66
67     public static Resource createMonitorPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException {
68
69         Layer0 L0 = Layer0.getInstance(g);
70         StructuralResource2 STR = StructuralResource2.getInstance(g);
71         ModelingResources MOD = ModelingResources.getInstance(g);
72
73         Resource monitorType = g.getPossibleObject(componentType, STR.ComponentType_HasDefaultMonitorValueType);
74         if(monitorType == null) monitorType = MOD.MonitorValue;
75
76         Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty");
77         g.claim(relation, L0.HasRange, monitorType);
78
79         Resource assertion = g.newResource();
80         g.claim(componentType, L0.Asserts, assertion);
81         g.claim(assertion, L0.InstanceOf, L0.Assertion);
82         g.claim(assertion, L0.HasPredicate, relation);
83         
84         Resource value = g.newResource();
85         g.claim(value, L0.InstanceOf, monitorType);
86         g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING);
87         g.claimLiteral(value, L0.SCLValue_expression, L0.String, "", Bindings.STRING);
88         g.claim(assertion, L0.HasObject, value);
89         
90         return relation;
91         
92     }
93
94     public static Resource createPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException {
95         g.markUndoPoint();
96         Layer0 L0 = Layer0.getInstance(g);
97
98         Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty");
99
100         Resource assertion = g.newResource();
101         g.claim(componentType, L0.Asserts, assertion);
102         g.claim(assertion, L0.InstanceOf, L0.Assertion);
103         g.claim(assertion, L0.HasPredicate, relation);
104         
105         Resource value = g.newResource();
106         g.claim(value, L0.InstanceOf, L0.Literal);
107         g.claimLiteral(value, L0.HasDataType, L0.DataType, Datatypes.DOUBLE, Bindings.getBindingUnchecked(Datatype.class));
108         g.claimLiteral(value, L0.HasValueType, L0.String, "Double", Bindings.STRING);
109         g.claimValue(value, 0.0, Bindings.DOUBLE);
110         g.claim(assertion, L0.HasObject, value);
111         
112         return relation;
113         
114     }
115
116     public static Resource createPropertyWithDefaultsBase(WriteGraph g, Resource componentType, String defaultName) throws DatabaseException {
117
118         Layer0 L0 = Layer0.getInstance(g);
119         StructuralResource2 STR = StructuralResource2.getInstance(g);
120         ModelingResources MOD = ModelingResources.getInstance(g);
121
122         String name = NameUtils.findFreshEscapedName(g, defaultName, componentType);
123
124         Resource relation = g.newResource();
125         g.claim(relation, L0.SubrelationOf, null, L0.HasProperty);
126         boolean hadProperty = false;
127         for(Resource type : g.getObjects(componentType, STR.ComponentType_HasDefaultPropertyRelationType)) {
128                 if(g.isInheritedFrom(type, STR.Property)) hadProperty = true;
129             g.claim(relation, L0.InstanceOf, type);
130         }
131         if(!hadProperty)
132                 g.claim(relation, L0.InstanceOf, STR.Property);
133         
134         g.claimLiteral(relation, L0.HasName, name);
135         g.claim(componentType, L0.ConsistsOf, L0.PartOf, relation);
136         g.claim(relation, L0.HasDomain, L0.DomainOf, componentType);
137
138         Resource invRelation = g.newResource();
139         g.claim(invRelation, L0.SubrelationOf, null, L0.PropertyOf);
140         g.claim(relation, L0.ConsistsOf, L0.PartOf, invRelation);
141         g.claimLiteral(invRelation, L0.HasName, "Inverse");
142         g.claim(relation, L0.InverseOf, invRelation);
143
144         g.claimLiteral(relation, L0.RequiresValueType, "Double");
145
146         SelectionViewResources SEL = SelectionViewResources.getInstance(g);
147         Resource category = g.getPossibleObject(relation, SEL.HasStandardPropertyInfo);
148         if(category == null) {
149                 g.claim(relation, SEL.HasStandardPropertyInfo, MOD.UserDefinedPropertyInfo);
150         }
151         if(!g.isInstanceOf(relation, SEL.GenericParameterType))
152                 g.claim(relation, L0.InstanceOf, SEL.GenericParameterType);
153         
154         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
155         g.addMetadata(cm.add("Created new property " + name + " for " + g.getRelatedValue2(componentType, L0.HasName, Bindings.STRING) + " " + componentType.toString()));
156
157         return relation;
158     }
159     
160     public static Resource createProperty(WriteGraph graph, Resource componentType, String name, String type, String unit, String range, String label, String description) throws DatabaseException {
161         
162         Resource property = createPropertyWithDefaults(graph, componentType);
163         rename(graph, property, name);
164         setRequiredType(graph, componentType, property, type);
165         convertDefaultValue(graph, componentType, property, type);
166         //setDefaultValue(graph, type, relation, valueText)
167         if (!type.equals("String")) {
168                 setUnit(graph, componentType, property, unit);
169                 setRange(graph, componentType, property, range);        
170         }
171         setLabel(graph, property, label);
172         setDescription(graph, property, description);
173         
174         return property;
175     }
176
177     public static void removeProperty(WriteGraph g, Resource componentType, Resource property) throws DatabaseException {
178         Layer0 L0 = Layer0.getInstance(g);
179         for(Resource assertion : g.getObjects(property, L0.HasPredicateInverse))
180             g.deny(assertion);
181         g.deny(property);
182         
183         String name = g.getPossibleRelatedValue2(componentType, L0.HasName);
184         
185         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
186         g.addMetadata(cm.add("Removed property " + property + " from component/annotation " + name + ", resource "+ componentType));
187     }
188
189     public static void rename(WriteGraph g, Resource resource, String newName) throws DatabaseException {
190         Layer0 L0 = Layer0.getInstance(g);
191         
192         String prevName = g.getPossibleRelatedValue2(resource, L0.HasName);
193         g.claimLiteral(resource, L0.HasName, newName);
194         
195         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
196         g.addMetadata(cm.add("Renamed component/annotation type from " + prevName + " to " + newName + ", resource " + resource  ));
197     }
198
199     public static void setRequiredType(WriteGraph g, Resource property,
200             String requiredType) throws DatabaseException {
201         setRequiredType(g, null, property, requiredType);
202     }
203
204     public static void setRequiredType(WriteGraph g, Resource componentType, Resource property,
205             String requiredType) throws DatabaseException {
206         setRequiredType(g, componentType, property, requiredType, null);
207     }
208
209     public static void setRequiredType(WriteGraph g, Resource componentType, Resource property,
210             String requiredType, Resource possibleType) throws DatabaseException {
211         Layer0 L0 = Layer0.getInstance(g);
212         ModelingResources MOD = ModelingResources.getInstance(g);
213         g.claimLiteral(property, L0.RequiresValueType, requiredType);
214
215         if (componentType != null) {
216             StructuralResource2 STR = StructuralResource2.getInstance(g);
217             for (Resource assertedValue : g.getAssertedObjects(componentType, property)) {
218                 if (g.isInstanceOf(assertedValue, STR.MonitorValue)) {
219                     g.claimLiteral(assertedValue, L0.HasValueType, requiredType);
220                 }
221             }
222         }
223
224         // We assert the range of the property only if we are given a dedicated graph value type
225         if(g.hasStatement(property, L0.HasRange))
226             g.deny(property, L0.HasRange);
227
228         if(possibleType != null) {
229             // We have a dedicated graph type for this SCL value type
230             if(g.hasStatement(possibleType, L0.Enumeration)) {
231                 // This value type is an enumeration - let's constrain the range of this predicate to match the enumeration type only
232                 g.claim(property, L0.HasRange, possibleType);
233             } else if (g.isInheritedFrom(possibleType, MOD.MonitorValue)) {
234                 // Support derived properties
235                 g.claim(property, L0.HasRange, possibleType);
236             }
237         }
238
239         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
240         g.addMetadata(cm.add("Set required type "+ requiredType + " for component/annotation " + property));
241     }
242     
243     public static void editType(WriteGraph graph, Resource componentType, Resource property, boolean convertDefaultValue, String newValue) throws DatabaseException {
244         editType(graph, componentType, property, convertDefaultValue, newValue, null);
245     }
246
247     public static void editType(WriteGraph graph, Resource componentType, Resource property, boolean convertDefaultValue, String newValue, Resource possibleType) throws DatabaseException {
248         ComponentTypeCommands.setRequiredType(graph, componentType, property, newValue, possibleType);
249         if (convertDefaultValue) {
250             ComponentTypeCommands.convertDefaultValue(graph, componentType, property, newValue, possibleType);
251             for (Resource indexRoot : Layer0Utils.listIndexRoots(graph)) {
252                 for(Resource instance : QueryIndexUtils.searchByTypeShallow(graph, indexRoot, componentType)) {
253                     ComponentTypeCommands.convertInstantiatedValue(graph, instance, property, newValue, componentType);
254                 }
255             }
256         }
257     }
258
259     static class AssertionMap extends UnaryRead<Resource, Map<Resource,Resource>> {
260         public AssertionMap(Resource parameter) {
261             super(parameter);
262         }
263
264         @Override
265         public Map<Resource, Resource> perform(ReadGraph graph)
266                 throws DatabaseException {
267             THashMap<Resource,Resource> result = new THashMap<Resource, Resource>();
268             Layer0 L0 = Layer0.getInstance(graph);
269             for(Resource assertion : graph.getObjects(parameter, L0.Asserts))
270                 result.put(graph.getSingleObject(assertion, L0.HasPredicate), 
271                         graph.getSingleObject(assertion, L0.HasObject));
272             return result;
273         }
274     }
275
276     public static Resource getAssertedObject(ReadGraph g, Resource type, Resource relation) throws DatabaseException {
277         return g.syncRequest(new AssertionMap(type)).get(relation);
278     }
279
280     public static void setMonitorExpression(WriteGraph g, Resource type, Resource relation,
281             String valueText) throws DatabaseException {
282
283         Resource object = getAssertedObject(g, type, relation);
284         if(object == null) {
285             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + 
286                     " in " + NameUtils.getSafeName(g, type) + ".");
287             return;
288         }
289         Layer0 L0 = Layer0.getInstance(g);
290         g.claimLiteral(object, L0.SCLValue_expression, valueText, Bindings.STRING);
291         
292     }
293
294     public static void setDefaultValue(WriteGraph g, Resource type, Resource relation,
295             String valueText) throws DatabaseException {
296
297         Resource object = getAssertedObject(g, type, relation);
298         if(object == null) {
299             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + 
300                     " in " + NameUtils.getSafeName(g, type) + ".");
301             return;
302         }
303
304         Layer0 L0 = Layer0.getInstance(g);
305         Resource range = g.getPossibleObject(relation, L0.HasRange);
306         if (range != null) {
307             if(g.hasStatement(range, L0.Enumeration)) {
308                 Map<String,Resource> values = g.syncRequest(new EnumerationMap(range));
309                 Resource value = values.get(valueText);
310                 if (value != null) {
311                     for(Resource assertion : g.getObjects(type, L0.Asserts)) {
312                         Resource p = g.getSingleObject(assertion, L0.HasPredicate);
313                         if (p.equals(relation)) {
314                             g.deny(assertion, L0.HasObject, object);
315                             g.claim(assertion, L0.HasObject, value);
316                         }
317                     }
318                 }
319                 return;
320             }
321         }
322         
323         if(valueText.length() > 0 && valueText.charAt(0) == '=') {
324                 
325                 String expression = valueText.substring(1);
326                 ModelingResources MOD = ModelingResources.getInstance(g);
327                 if(!g.isInstanceOf(object, MOD.SCLValue)) {
328                         Resource assertion = g.getSingleObject(object, L0.HasObjectInverse);
329                         g.deny(assertion, L0.HasObject, object);
330                         object = g.newResource();
331                         g.claim(object, L0.InstanceOf, MOD.SCLValue);
332                         g.claim(assertion, L0.HasObject, object);
333                 }
334                 g.claimLiteral(object, L0.SCLValue_expression, L0.String, expression, Bindings.STRING);
335             Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new expression '" + expression + "'");
336             
337         } else {
338                 
339                 ModelingResources MOD = ModelingResources.getInstance(g);
340                 if(g.isInstanceOf(object, MOD.SCLValue)) {
341                         Resource assertion = g.getSingleObject(object, L0.HasObjectInverse);
342                         g.deny(assertion, L0.HasObject, object);
343                         object = g.newResource();
344                         String sclType = g.getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING);
345                 Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(sclType);
346                         g.claim(object, L0.InstanceOf, L0.Literal);
347                 Binding ntb = Bindings.getBindingUnchecked(Datatype.class);
348                 g.claimLiteral(object, L0.HasDataType, L0.DataType, newDatatype, ntb);
349                         g.claim(assertion, L0.HasObject, object);
350                 }
351                 
352                 Datatype dt = g.getDataType(object);
353                 Binding binding = Bindings.getBinding(dt);
354                 Object value;
355                 try {
356                         value = binding.parseValue(valueText, new DataValueRepository());
357                         g.claimValue(object, value, binding);
358                         Layer0Utils.addCommentMetadata(g, "Modified " + g.getRelatedValue2(relation, Layer0.getInstance(g).HasName, Bindings.STRING) + " with new value " + value.toString());
359                 } catch (DataTypeSyntaxError e) {
360                         e.printStackTrace();
361                 } catch (BindingException e) {
362                         e.printStackTrace();
363                 }
364                 
365         }
366
367     }
368
369     /**
370      * @param graph graph write transaction handle
371      * @param type component type to edit
372      * @param relation component type property relation to edit
373      * @param unit <code>null</code> to remove unit description
374      * @throws DatabaseException
375      */
376     public static void setUnit(WriteGraph graph, Resource type, Resource relation, String unit) throws DatabaseException {
377         Resource object = getAssertedObject(graph, type, relation);
378         if (object == null) {
379             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) + 
380                     " in " + NameUtils.getSafeName(graph, type) + ".");
381             return;
382         }
383
384         Layer0 L0 = Layer0.getInstance(graph);
385         Layer0X L0X = Layer0X.getInstance(graph);
386         boolean hasRequiresDataType = graph.hasStatement(relation, L0X.RequiresDataType);
387         if (hasRequiresDataType) {
388             Datatype dt = graph.getDataType(object);
389             if (dt instanceof NumberType) {
390                 NumberType nt = (NumberType) Bindings.DATATYPE.cloneUnchecked(dt);
391                 nt.setUnit(unit);
392                 graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, Bindings.DATATYPE);
393                 graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, Bindings.DATATYPE);
394             }
395         }
396
397         String oldUnit = graph.getPossibleRelatedValue2(relation, L0X.HasUnit, Bindings.STRING);
398         if (unit != null) {
399             graph.claimLiteral(relation, L0X.HasUnit, L0.String, unit, Bindings.STRING);
400         } else {
401             graph.denyValue(relation, L0X.HasUnit);
402         }
403
404         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
405         graph.addMetadata(cm.add("Set unit from " + oldUnit + " to " + unit + " for component/annotation " + type + " property " + relation));
406     }
407
408     /**
409      * @param graph graph write transaction handle
410      * @param type component type to modify
411      * @param relation property relation of a component type
412      * @param newRange new range definition or <code>null</code> to remove range restriction
413      * @throws DatabaseException 
414      */
415     public static void setRange(WriteGraph graph, Resource type, Resource relation, String newRange) throws DatabaseException {
416         Resource object = getAssertedObject(graph, type, relation);
417         if (object == null) {
418             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(graph, relation) + 
419                     " in " + NameUtils.getSafeName(graph, type) + ".");
420             return;
421         }
422
423         Datatype dt = graph.getDataType(object);
424         if (dt instanceof NumberType) {
425             NumberType nt = (NumberType) dt;
426             Binding ntb = Bindings.getBindingUnchecked(Datatype.class);
427             nt.setRange(newRange);
428
429             Layer0 L0 = Layer0.getInstance(graph);
430             Layer0X L0X = Layer0X.getInstance(graph);
431
432             graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, ntb);
433             graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, ntb);
434             
435             CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
436             graph.addMetadata(cm.add("Setted range " + newRange + " for component/annotation " + type));
437         }
438     }
439
440     public static Tuple getDatatypeValueAndBinding(ReadGraph g, Resource object, String newSCLType) throws DatabaseException {
441
442         Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(newSCLType);
443         if(newDatatype == null) {
444             LOGGER.warn("Couldn't convert default value to <" + newSCLType + ">.");
445             return null;
446         }
447         Binding newBinding = Bindings.getBinding(newDatatype);
448
449         Datatype oldDatatype = g.getDataType(object);
450         Binding oldBinding = Bindings.getBinding(oldDatatype);
451
452         Object oldValue = g.getValue(object, oldBinding);
453         Object newValue;
454         try {
455             newValue = Bindings.adapt(oldValue, oldBinding, newBinding);
456         } catch (AdaptException e) {
457             try {
458                 newValue = newBinding.createDefault();
459             } catch (BindingException e1) {
460                 e1.printStackTrace();
461                 return null;
462             }
463         }
464
465         return new Tuple3(newDatatype, newValue, newBinding);
466
467     }
468
469     public static void convertDefaultValue(WriteGraph g,
470             Resource type, Resource relation, String newSCLType) throws DatabaseException {
471         convertDefaultValue(g, type, relation, newSCLType, null);
472     }
473
474     private static Resource findAssertionWithPO(ReadGraph graph, Resource possibleType, Resource predicate, Resource object) throws DatabaseException {
475             Layer0 L0 = Layer0.getInstance(graph);
476         for(Resource assertion : graph.getObjects(possibleType, L0.Asserts)) {
477             Resource p = graph.getSingleObject(assertion, L0.HasPredicate);
478             Resource o = graph.getSingleObject(assertion, L0.HasObject);
479             if(predicate.equals(p) && object.equals(o))
480                 return assertion;
481         }
482         return null;
483     }
484
485     public static void convertDefaultValue(WriteGraph g,
486             Resource type, Resource relation, String newSCLType, Resource possibleType) throws DatabaseException {
487         Resource object = getAssertedObject(g, type, relation);
488         if(object == null) {
489             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + 
490                     " in " + NameUtils.getSafeName(g, type) + ".");
491             return;
492         }
493
494         Layer0 L0 = Layer0.getInstance(g);
495         if(possibleType != null) {
496             if(g.hasStatement(possibleType, L0.Enumeration)) {
497                 if(!g.isInstanceOf(object, possibleType)) {
498                     Map<String, Resource> enumMap = g.syncRequest(new EnumerationMap(possibleType));
499                     String firstKey = Collections.min(enumMap.keySet(), AlphanumComparator.COMPARATOR);
500                     Resource defaultValue = enumMap.get(firstKey);
501
502                     if (defaultValue != null) {
503                         Resource assertion = findAssertionWithPO(g, type, relation, object);
504                         if(assertion != null) {
505                             g.deny(assertion, L0.HasObject);
506                             g.claim(assertion, L0.HasObject, defaultValue);
507                             return;
508                         } else {
509                             Layer0Utils.assert_(g, type, relation, defaultValue);
510                             return;
511                         }
512                     }
513                 } else {
514                         return;
515                 }
516             }
517         }
518
519         Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType);
520         if (tuple == null)
521             return;
522
523         if(g.sync(new IsEnumeratedValue(object))) {
524             Resource assertion = findAssertionWithPO(g, type, relation, object);
525             object = g.newResource();
526             g.claim(object, L0.InstanceOf, L0.Literal);
527             if(assertion != null) {
528                 g.deny(assertion, L0.HasObject);
529                 g.claim(assertion, L0.HasObject, object);
530             }
531         }
532
533         g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class));
534         g.claimLiteral(object, L0.HasValueType, g.<String>getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING);
535         g.claimValue(object, tuple.get(1), (Binding)tuple.get(2));
536
537     }
538
539     public static void convertInstantiatedValue(WriteGraph g, Resource instance, Resource relation, String newSCLType) throws DatabaseException {
540         convertInstantiatedValue(g, instance, relation, newSCLType, null);
541     }
542
543     public static void convertInstantiatedValue(WriteGraph g, Resource instance, Resource relation, String newSCLType, Resource possibleType)
544             throws DatabaseException {
545
546         Statement stm = g.getPossibleStatement(instance, relation);
547         if(stm != null && !stm.isAsserted(instance)) {
548
549             Layer0 L0 = Layer0.getInstance(g);
550             Resource object = stm.getObject();
551
552             if(g.sync(new IsEnumeratedValue(object))) {
553                 if(!g.isInstanceOf(object, possibleType)) {
554                     g.deny(instance, relation);
555                 }
556                 return;
557             }
558
559             // We can only convert literals
560             if(!g.isInstanceOf(object, L0.Literal)) return;
561
562             Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType);
563
564             g.claimLiteral(object, L0.HasDataType, L0.DataType, tuple.get(0), Bindings.getBindingUnchecked(Datatype.class));
565             g.claimLiteral(object, L0.HasValueType, g.<String>getRelatedValue(relation, L0.RequiresValueType, Bindings.STRING), Bindings.STRING);
566             g.claimValue(object, tuple.get(1), (Binding)tuple.get(2));
567
568         }
569
570     }
571
572     /**
573      * @param graph graph write transaction handle
574      * @param relation component type property relation to edit
575      * @param newDescription new label or <code>null</code> to remove label
576      * @throws DatabaseException 
577      */
578     public static void setLabel(WriteGraph graph, Resource relation, String newLabel) throws DatabaseException {
579         setProperty(graph, relation, Layer0.getInstance(graph).HasLabel, newLabel);
580         
581         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
582         graph.addMetadata(cm.add("Setted label " + newLabel + " for component/annotation " + relation));
583     }
584
585     /**
586      * @param graph graph write transaction handle
587      * @param relation component type property relation to edit
588      * @param newDescription new description or <code>null</code> if new description
589      * @throws DatabaseException 
590      */
591     public static void setDescription(WriteGraph graph, Resource relation, String newDescription) throws DatabaseException {
592         setProperty(graph, relation, Layer0.getInstance(graph).HasDescription, newDescription);        
593         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
594         graph.addMetadata(cm.add("Setted description " + newDescription + " for component/annotation " + relation));
595     }
596
597     /**
598      * @param graph graph write transaction handle
599      * @param relation component type property relation to edit
600      * @param newValue new property value or <code>null</code> to remove property
601      * @throws DatabaseException 
602      */
603     public static void setProperty(WriteGraph graph, Resource relation, Resource property, String newValue) throws DatabaseException {
604         if (newValue != null) {
605             graph.claimLiteral(relation, property, newValue, Bindings.STRING);
606         } else {
607             graph.denyValue(relation, property);
608         }
609     }
610
611     /**
612      * @param graph
613      * @param componentType
614      * @return the created symbol
615      */
616     public static Resource createSymbol(WriteGraph graph, Resource componentType) throws DatabaseException {
617         return NewSymbol.createSymbol(graph, componentType);
618     }
619
620     /**
621      * Converts to a <code>camelCase</code> name to a more user-readable
622      * <code>Camel Case</code> label.
623      * 
624      * <p>
625      * Examples
626      * <pre>
627      * "fooBarBazBAR" => "Foo Bar Baz BAR"
628      * " fooBarBazBAR" => " Foo Bar Baz BAR"
629      * "_fooBarBazBAR" => "_Foo Bar Baz BAR"
630      * "_FooBarBazBAR" => "_Foo Bar Baz BAR"
631      * " _ fooBarBazBAR" => " _ Foo Bar Baz BAR"
632      * </pre>
633      * 
634      * @param str camelCase SCL identifier name
635      * @return labelified Camel Case string
636      */
637     public static String camelCaseNameToLabel(String str) {
638         int len = str.length();
639         StringBuilder sb = new StringBuilder(len*2);
640
641         boolean wasLastUpper = false;
642         boolean isFirstEncounteredLetter = true;
643
644         for (int i = 0; i < len; ++i) {
645             char ch = str.charAt(i);
646
647             boolean space = Character.isWhitespace(ch);
648             if (space) {
649                 sb.append(ch);
650                 continue;
651             }
652
653             boolean isUpperCaseLetter = Character.isUpperCase(ch);
654             boolean isLetterOrDigit = Character.isLetterOrDigit(ch);
655             if (!isFirstEncounteredLetter && isUpperCaseLetter && !wasLastUpper && isLetterOrDigit) {
656                 sb.append(' ');
657                 sb.append(ch);
658             } else {
659                 if (isLetterOrDigit && isFirstEncounteredLetter)
660                     sb.append(Character.toUpperCase(ch));
661                 else
662                     sb.append(ch);
663                 if (isFirstEncounteredLetter)
664                     isFirstEncounteredLetter = !isLetterOrDigit;
665             }
666             wasLastUpper = isUpperCaseLetter;
667         }
668         return sb.toString();
669     }
670
671     public static void saveProceduralCodeWithUC(WriteGraph graph, Resource componentType, String newText) throws DatabaseException {
672         StructuralResource2 STR = StructuralResource2.getInstance(graph);
673         Resource code = graph.getPossibleObject(componentType, STR.ProceduralComponentType_code);
674         saveProceduralCode(graph, code, newText);
675     }
676     
677     public static void saveProceduralCode(WriteGraph graph, Resource resource, String newText) throws ServiceException {
678         graph.claimValue(resource, newText, Bindings.STRING);
679         Layer0Utils.addCommentMetadata(graph, "Saved Procedural Component Type SCL Code");
680     }
681 }