]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/userComponent/ComponentTypeCommands.java
ea4de26b22da5fe935c6153093ed476304278954
[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.Map;
15
16 import org.simantics.databoard.Bindings;
17 import org.simantics.databoard.Datatypes;
18 import org.simantics.databoard.adapter.AdaptException;
19 import org.simantics.databoard.binding.Binding;
20 import org.simantics.databoard.binding.error.BindingException;
21 import org.simantics.databoard.parser.repository.DataTypeSyntaxError;
22 import org.simantics.databoard.parser.repository.DataValueRepository;
23 import org.simantics.databoard.type.Datatype;
24 import org.simantics.databoard.type.NumberType;
25 import org.simantics.db.ReadGraph;
26 import org.simantics.db.Resource;
27 import org.simantics.db.Statement;
28 import org.simantics.db.WriteGraph;
29 import org.simantics.db.common.CommentMetadata;
30 import org.simantics.db.common.request.UnaryRead;
31 import org.simantics.db.common.utils.NameUtils;
32 import org.simantics.db.exception.DatabaseException;
33 import org.simantics.db.exception.ServiceException;
34 import org.simantics.db.layer0.request.ModelInstances;
35 import org.simantics.db.layer0.util.Layer0Utils;
36 import org.simantics.layer0.Layer0;
37 import org.simantics.modeling.ModelingResources;
38 import org.simantics.modeling.NewSymbol;
39 import org.simantics.operation.Layer0X;
40 import org.simantics.scl.runtime.tuple.Tuple;
41 import org.simantics.scl.runtime.tuple.Tuple3;
42 import org.simantics.selectionview.SelectionViewResources;
43 import org.simantics.structural.stubs.StructuralResource2;
44 import org.simantics.structural2.utils.StructuralUtils;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import gnu.trove.map.hash.THashMap;
49
50 public class ComponentTypeCommands {
51
52     private static final Logger LOGGER = LoggerFactory.getLogger(ComponentTypeCommands.class);
53
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);
57     }
58
59     public static Resource createConnectionPoint(WriteGraph g, Resource componentType, Resource cp) throws DatabaseException {
60         return StructuralUtils.createConnectionPoint(g, componentType, cp);
61     }
62
63     public static Resource createMonitorPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException {
64
65         Layer0 L0 = Layer0.getInstance(g);
66         StructuralResource2 STR = StructuralResource2.getInstance(g);
67         ModelingResources MOD = ModelingResources.getInstance(g);
68
69         Resource monitorType = g.getPossibleObject(componentType, STR.ComponentType_HasDefaultMonitorValueType);
70         if(monitorType == null) monitorType = MOD.MonitorValue;
71
72         Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty");
73         g.claim(relation, L0.HasRange, monitorType);
74
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);
79         
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);
85         
86         return relation;
87         
88     }
89
90     public static Resource createPropertyWithDefaults(WriteGraph g, Resource componentType) throws DatabaseException {
91         g.markUndoPoint();
92         Layer0 L0 = Layer0.getInstance(g);
93
94         Resource relation = createPropertyWithDefaultsBase(g, componentType, "newProperty");
95
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);
100         
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);
107         
108         return relation;
109         
110     }
111
112     public static Resource createPropertyWithDefaultsBase(WriteGraph g, Resource componentType, String defaultName) throws DatabaseException {
113
114         Layer0 L0 = Layer0.getInstance(g);
115         StructuralResource2 STR = StructuralResource2.getInstance(g);
116         ModelingResources MOD = ModelingResources.getInstance(g);
117
118         String name = NameUtils.findFreshEscapedName(g, defaultName, componentType);
119
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);
126         }
127         if(!hadProperty)
128                 g.claim(relation, L0.InstanceOf, STR.Property);
129         
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);
133
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);
139
140         g.claimLiteral(relation, L0.RequiresValueType, "Double");
141
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);
146         }
147         if(!g.isInstanceOf(relation, SEL.GenericParameterType))
148                 g.claim(relation, L0.InstanceOf, SEL.GenericParameterType);
149         
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()));
152
153         return relation;
154     }
155     
156     public static Resource createProperty(WriteGraph graph, Resource componentType, String name, String type, String unit, String range, String label, String description) throws DatabaseException {
157         
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);        
166         }
167         setLabel(graph, property, label);
168         setDescription(graph, property, description);
169         
170         return property;
171     }
172
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))
176             g.deny(assertion);
177         g.deny(property);
178         
179         String name = g.getPossibleRelatedValue2(componentType, L0.HasName);
180         
181         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
182         g.addMetadata(cm.add("Removed property " + property + " from component/annotation " + name + ", resource "+ componentType));
183     }
184
185     public static void rename(WriteGraph g, Resource resource, String newName) throws DatabaseException {
186         Layer0 L0 = Layer0.getInstance(g);
187         
188         String prevName = g.getPossibleRelatedValue2(resource, L0.HasName);
189         g.claimLiteral(resource, L0.HasName, newName);
190         
191         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
192         g.addMetadata(cm.add("Renamed component/annotation type from " + prevName + " to " + newName + ", resource " + resource  ));
193     }
194
195     public static void setRequiredType(WriteGraph g, Resource property,
196             String requiredType) throws DatabaseException {
197         setRequiredType(g, null, property, requiredType);
198     }
199
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);
204
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);
210                 }
211             }
212         }
213
214         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
215         g.addMetadata(cm.add("Set required type "+ requiredType + " for component/annotation " + property));
216     }
217     
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);
225             }
226         }
227     }
228
229     static class AssertionMap extends UnaryRead<Resource, Map<Resource,Resource>> {
230         public AssertionMap(Resource parameter) {
231             super(parameter);
232         }
233
234         @Override
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));
242             return result;
243         }
244     }
245
246     public static Resource getAssertedObject(ReadGraph g, Resource type, Resource relation) throws DatabaseException {
247         return g.syncRequest(new AssertionMap(type)).get(relation);
248     }
249
250     public static void setMonitorExpression(WriteGraph g, Resource type, Resource relation,
251             String valueText) throws DatabaseException {
252
253         Resource object = getAssertedObject(g, type, relation);
254         if(object == null) {
255             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + 
256                     " in " + NameUtils.getSafeName(g, type) + ".");
257             return;
258         }
259         Layer0 L0 = Layer0.getInstance(g);
260         g.claimLiteral(object, L0.SCLValue_expression, valueText, Bindings.STRING);
261         
262     }
263
264     public static void setDefaultValue(WriteGraph g, Resource type, Resource relation,
265             String valueText) throws DatabaseException {
266
267         Resource object = getAssertedObject(g, type, relation);
268         if(object == null) {
269             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + 
270                     " in " + NameUtils.getSafeName(g, type) + ".");
271             return;
272         }
273         
274         if(valueText.length() > 0 && valueText.charAt(0) == '=') {
275                 
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);
285                 }
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 + "'");
288             
289         } else {
290                 
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);
303                 }
304                 
305                 Datatype dt = g.getDataType(object);
306                 Binding binding = Bindings.getBinding(dt);
307                 Object value;
308                 try {
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) {
313                         e.printStackTrace();
314                 } catch (BindingException e) {
315                         e.printStackTrace();
316                 }
317                 
318         }
319
320     }
321
322     /**
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
328      */
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) + ".");
334             return;
335         }
336
337         Layer0X L0X = Layer0X.getInstance(graph);
338         boolean hasRequiresDataType = graph.hasStatement(relation, L0X.RequiresDataType);
339         if (hasRequiresDataType) {
340             Datatype dt = graph.getDataType(object);
341             if (dt instanceof NumberType) {
342                 Layer0 L0 = Layer0.getInstance(graph);
343                 NumberType nt = (NumberType) Bindings.DATATYPE.cloneUnchecked(dt);
344                 nt.setUnit(unit);
345                 graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, Bindings.DATATYPE);
346                 graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, Bindings.DATATYPE);
347             }
348         }
349
350         String oldUnit = graph.getPossibleRelatedValue2(relation, L0X.HasUnit, Bindings.STRING);
351         graph.claimLiteral(relation, L0X.HasUnit, unit, Bindings.STRING);
352
353         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
354         graph.addMetadata(cm.add("Set unit from " + oldUnit + " to " + unit + " for component/annotation " + type + " property " + relation));
355     }
356
357     /**
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 
363      */
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) + ".");
369             return;
370         }
371
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);
377
378             Layer0 L0 = Layer0.getInstance(graph);
379             Layer0X L0X = Layer0X.getInstance(graph);
380
381             graph.claimLiteral(object, L0.HasDataType, L0.DataType, nt, ntb);
382             graph.claimLiteral(relation, L0X.RequiresDataType, L0.DataType, nt, ntb);
383             
384             CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
385             graph.addMetadata(cm.add("Setted range " + newRange + " for component/annotation " + type));
386         }
387     }
388
389     public static Tuple getDatatypeValueAndBinding(ReadGraph g, Resource object, String newSCLType) throws DatabaseException {
390
391         Datatype newDatatype = TypeConversion.convertSCLTypeToDatatype(newSCLType);
392         if(newDatatype == null) {
393             LOGGER.warn("Couldn't convert default value to <" + newSCLType + ">.");
394             return null;
395         }
396         Binding newBinding = Bindings.getBinding(newDatatype);
397
398         Datatype oldDatatype = g.getDataType(object);
399         Binding oldBinding = Bindings.getBinding(oldDatatype);
400
401         Object oldValue = g.getValue(object, oldBinding);
402         Object newValue;
403         try {
404             newValue = Bindings.adapt(oldValue, oldBinding, newBinding);
405         } catch (AdaptException e) {
406             try {
407                 newValue = newBinding.createDefault();
408             } catch (BindingException e1) {
409                 e1.printStackTrace();
410                 return null;
411             }
412         }
413
414         return new Tuple3(newDatatype, newValue, newBinding);
415
416     }
417
418     public static void convertDefaultValue(WriteGraph g,
419             Resource type, Resource relation, String newSCLType) throws DatabaseException {
420         Resource object = getAssertedObject(g, type, relation);
421         if(object == null) {
422             LOGGER.warn("Didn't find assertion for " + NameUtils.getSafeName(g, relation) + 
423                     " in " + NameUtils.getSafeName(g, type) + ".");
424             return;
425         }
426
427         Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType);
428         if (tuple == null)
429             return;
430
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));
435
436     }
437
438     public static void convertInstantiatedValue(WriteGraph g, Resource instance, Resource relation, String newSCLType)
439             throws DatabaseException {
440
441         Statement stm = g.getPossibleStatement(instance, relation);
442         if(stm != null && !stm.isAsserted(instance)) {
443
444             Resource object = stm.getObject();
445
446             // We can only convert literals
447             Layer0 L0 = Layer0.getInstance(g);
448             if(!g.isInstanceOf(object, L0.Literal)) return;
449
450             Tuple tuple = getDatatypeValueAndBinding(g, object, newSCLType);
451
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));
455
456         }
457
458     }
459
460     /**
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 
465      */
466     public static void setLabel(WriteGraph graph, Resource relation, String newLabel) throws DatabaseException {
467         setProperty(graph, relation, Layer0.getInstance(graph).HasLabel, newLabel);
468         
469         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
470         graph.addMetadata(cm.add("Setted label " + newLabel + " for component/annotation " + relation));
471     }
472
473     /**
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 
478      */
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));
483     }
484
485     /**
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 
490      */
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);
494         } else {
495             graph.denyValue(relation, property);
496         }
497     }
498
499     /**
500      * @param graph
501      * @param componentType
502      * @return the created symbol
503      */
504     public static Resource createSymbol(WriteGraph graph, Resource componentType) throws DatabaseException {
505         return NewSymbol.createSymbol(graph, componentType);
506     }
507
508     /**
509      * Converts to a <code>camelCase</code> name to a more user-readable
510      * <code>Camel Case</code> label.
511      * 
512      * <p>
513      * Examples
514      * <pre>
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"
520      * </pre>
521      * 
522      * @param str camelCase SCL identifier name
523      * @return labelified Camel Case string
524      */
525     public static String camelCaseNameToLabel(String str) {
526         int len = str.length();
527         StringBuilder sb = new StringBuilder(len*2);
528
529         boolean wasLastUpper = false;
530         boolean isFirstEncounteredLetter = true;
531
532         for (int i = 0; i < len; ++i) {
533             char ch = str.charAt(i);
534
535             boolean space = Character.isWhitespace(ch);
536             if (space) {
537                 sb.append(ch);
538                 continue;
539             }
540
541             boolean isUpperCaseLetter = Character.isUpperCase(ch);
542             boolean isLetterOrDigit = Character.isLetterOrDigit(ch);
543             if (!isFirstEncounteredLetter && isUpperCaseLetter && !wasLastUpper && isLetterOrDigit) {
544                 sb.append(' ');
545                 sb.append(ch);
546             } else {
547                 if (isLetterOrDigit && isFirstEncounteredLetter)
548                     sb.append(Character.toUpperCase(ch));
549                 else
550                     sb.append(ch);
551                 if (isFirstEncounteredLetter)
552                     isFirstEncounteredLetter = !isLetterOrDigit;
553             }
554             wasLastUpper = isUpperCaseLetter;
555         }
556         return sb.toString();
557     }
558
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);
563     }
564     
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");
568     }
569 }