001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.metaboss.sdlctools.models.modelassistant.metabossmodel.implicittypes;
016:
017: import java.util.Collection;
018: import java.util.Comparator;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Set;
022: import java.util.TreeSet;
023:
024: import javax.jmi.reflect.ConstraintViolationException;
025:
026: import com.metaboss.sdlctools.models.ModelRepositoryException;
027: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.DataType;
028: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.Namespace;
029: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.Property;
030: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.PropertyDescriptor;
031: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.TypeTemplate;
032: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Entity;
033: import com.metaboss.sdlctools.models.metabossmodel.statemachinemodel.State;
034: import com.metaboss.sdlctools.models.metabossmodel.statemachinemodel.StateMachine;
035: import com.metaboss.sdlctools.models.metabossmodel.statemachinemodel.StateType;
036: import com.metaboss.sdlctools.models.metabossmodel.statemachinemodel.Transition;
037:
038: /** This class holds details about Entity State DataType
039: * being processed. Used internally in the Assistant impl */
040: class EntityStateDataTypeHelper {
041: // Utility comparator, which is used to sort properties in order of deletion
042: // The problem is that when parent property is deleted - the child property is deleted too, so
043: // when we iterate through unused properties and issue refDelete() - we may hit already deleted property.
044: // This comparator sorts the properties in the reverse string sort order of the keys,
045: // which ensures that properties are sorted in the right order for deletion (child properties before parent ones)
046: private static Comparator sPropertiesToDeleteComparator = new Comparator() {
047: public int compare(Object o1, Object o2) {
048: return ((Property) o2).getKey().compareTo(
049: ((Property) o1).getKey());
050: }
051: };
052:
053: private ModelAssistantImpl mModelAssistantImpl;
054: private Set mUnusedProperties = new TreeSet(
055: sPropertiesToDeleteComparator);
056: private DataType mEntityStateDataType = null;
057: private TypeTemplate mEntityStateFieldTypeTemplate = null;
058: private PropertyDescriptor mStatePropertyDescriptor = null;
059: private PropertyDescriptor mStateNamePropertyDescriptor = null;
060: private PropertyDescriptor mStateDescriptionPropertyDescriptor = null;
061: private PropertyDescriptor mStateTypePropertyDescriptor = null;
062: private PropertyDescriptor mStateTransitionPropertyDescriptor = null;
063: private PropertyDescriptor mStateTransitionDestinationStateNamePropertyDescriptor = null;
064: private PropertyDescriptor mStateTransitionDescriptionPropertyDescriptor = null;
065:
066: // This helper is looking at the conditions and ensuring the inegrity of the data type
067: // it will create the missing data type and delete exta one if necessary
068: static void verifyEntityStateDataTypeIntegrity(
069: Collection pViolations,
070: ModelAssistantImpl pModelAssistantImpl, Entity lEntity,
071: List pUnprocessedDataTypes, HelperContext pHelperContext) {
072: Namespace lDomainNamespace = pHelperContext
073: .getDomainNamespace();
074: if (lDomainNamespace == null)
075: return;
076: TypeTemplate lDesiredTypeTemplate = pHelperContext
077: .getEntityStateFieldTypeTemplate();
078:
079: StateMachine lStateMachine = lEntity.getStateMachine();
080: if (lStateMachine != null) {
081: String lExpectedDataTypeName = StylesheetImpl
082: .getEntityStateDataTypeName(lEntity.getName());
083: DataType lDataTypeInNamespace = lDomainNamespace
084: .findDataType(lExpectedDataTypeName);
085: if (lDataTypeInNamespace != null) {
086: // Remove this data type from the list of unprocessed ones
087: if (pUnprocessedDataTypes != null)
088: pUnprocessedDataTypes.remove(lDataTypeInNamespace);
089: // Verify that the entity is actually pointing to this data type
090: DataType lDataTypeInEntity = lEntity.getStateDataType();
091: if (lDataTypeInEntity == null)
092: pViolations
093: .add(new ConstraintViolationException(
094: lEntity,
095: lEntity.refMetaObject(),
096: "Entity does not have associated State DataType. Entity with StateMachine must always be associated with the Entity State DataType."));
097: else if (lDataTypeInEntity.equals(lDataTypeInNamespace) == false)
098: pViolations
099: .add(new ConstraintViolationException(
100: lEntity, lEntity.refMetaObject(),
101: "Entity is associated with wrong State DataType. Expecting '"
102: + lDataTypeInNamespace
103: .getRef()
104: + "' found '"
105: + lDataTypeInEntity
106: .getRef() + "'."));
107:
108: // Verify that this data type is based on prescribed template
109: TypeTemplate lActualTypeTemplate = lDataTypeInNamespace
110: .getTypetemplate();
111: if (lActualTypeTemplate == null)
112: pViolations
113: .add(new ConstraintViolationException(
114: lDataTypeInNamespace,
115: lDataTypeInNamespace
116: .refMetaObject(),
117: "DataType does not use typetemplate. An Entity State data type must always use the "
118: + lDesiredTypeTemplate
119: .getRef()
120: + " typetemplate."));
121: else if (lActualTypeTemplate
122: .equals(lDesiredTypeTemplate) == false)
123: pViolations
124: .add(new ConstraintViolationException(
125: lDataTypeInNamespace,
126: lDataTypeInNamespace
127: .refMetaObject(),
128: "DataType uses wrong template. Expecting '"
129: + lDesiredTypeTemplate
130: .getName()
131: + "' found '"
132: + lActualTypeTemplate
133: .getName()
134: + "'. An Entity State data type must always use the "
135: + lDesiredTypeTemplate
136: .getRef()
137: + " typetemplate."));
138:
139: // Now work on all properties
140: EntityStateDataTypeHelper lDataTypeHelper = new EntityStateDataTypeHelper(
141: pModelAssistantImpl, lDataTypeInNamespace);
142: lDataTypeHelper.markPropertiesAsUnused();
143: // Check individual states
144: for (Iterator lStatesIterator = lStateMachine
145: .getStates().iterator(); lStatesIterator
146: .hasNext();) {
147: State lState = (State) lStatesIterator.next();
148: lDataTypeHelper.verifyStateExists(pViolations,
149: lState.getName(), lState.getDescription(),
150: lState.getType().toString());
151: // Iterate through transitions
152: for (Iterator lOutgoingTransitionsIterator = lState
153: .getOutgoingTranstions().iterator(); lOutgoingTransitionsIterator
154: .hasNext();) {
155: Transition lStateTransition = (Transition) lOutgoingTransitionsIterator
156: .next();
157: lDataTypeHelper.verifyTransitionExists(
158: pViolations, lState.getName(),
159: lStateTransition.getEndState()
160: .getName(), lStateTransition
161: .getDescription());
162: }
163: }
164: lDataTypeHelper.verifyUnusedProperties(pViolations);
165: } else
166: pViolations
167: .add(new ConstraintViolationException(
168: lDomainNamespace,
169: lDomainNamespace.refMetaObject(),
170: "DataType not found. System namespace for Domain must contain an Entity State data type for every entity in the domain which has state machine defined. Entity '"
171: + lEntity.getName()
172: + "' does not have corresponding '"
173: + lExpectedDataTypeName
174: + "' data type."));
175: }
176: }
177:
178: // This helper is looking at the conditions and ensuring the inegrity of the data type
179: // it will create the missing data type and delete exta one if necessary
180: static void ensureEntityStateDataTypeIntegrity(
181: ModelAssistantImpl pModelAssistantImpl, Entity pEntity,
182: List pUnprocessedDataTypes, HelperContext pHelperContext)
183: throws ModelRepositoryException {
184: // Create data type if necessary
185: StateMachine lStateMachine = pEntity.getStateMachine();
186: if (lStateMachine != null) {
187: // Ensure that data type exists
188: ensureEntityStateDataTypeExists(pModelAssistantImpl,
189: pEntity, pUnprocessedDataTypes, pHelperContext);
190: // Now work on all properties
191: EntityStateDataTypeHelper lDataTypeHelper = new EntityStateDataTypeHelper(
192: pModelAssistantImpl, pEntity.getStateDataType());
193: // Work on properties
194: lDataTypeHelper.markPropertiesAsUnused();
195: for (Iterator lStatesIterator = lStateMachine.getStates()
196: .iterator(); lStatesIterator.hasNext();) {
197: State lState = (State) lStatesIterator.next();
198: lDataTypeHelper.ensureStateExists(lState.getName(),
199: lState.getDescription(), lState.getType());
200: // Iterate through transitions
201: for (Iterator lOutgoingTransitionsIterator = lState
202: .getOutgoingTranstions().iterator(); lOutgoingTransitionsIterator
203: .hasNext();) {
204: Transition lStateTransition = (Transition) lOutgoingTransitionsIterator
205: .next();
206: lDataTypeHelper.ensureTransitionExists(lState
207: .getName(), lStateTransition.getEndState()
208: .getName(), lStateTransition
209: .getDescription());
210: }
211: }
212: // Delete all still unused properties
213: lDataTypeHelper.deleteUnusedProperties();
214: } else
215: ensureEntityStateDataTypeAbsent(pEntity,
216: pUnprocessedDataTypes, pHelperContext);
217: }
218:
219: // This helper is looking after creation of absent entity state data type
220: // It returns the newly created or found Data Type or null if it can not be created
221: // The namespaces are optional parameters - if they are null - they will be discovered inside this method
222: // and if they are unobtainable - this method will fail to work and return null. This is provided to save some time
223: // during batch operations
224: static DataType ensureEntityStateDataTypeExists(
225: ModelAssistantImpl pModelAssistantImpl, Entity pEntity,
226: List pUnprocessedDataTypes, HelperContext pHelperContext) {
227: Namespace lDomainNamespace = pHelperContext
228: .getDomainNamespace();
229: if (lDomainNamespace == null)
230: return null;
231:
232: String lEntityStateDataTypeName = StylesheetImpl
233: .getEntityStateDataTypeName(pEntity.getName());
234: DataType lEntityStateDataType = lDomainNamespace
235: .findDataType(lEntityStateDataTypeName);
236: TypeTemplate lStateTypeTemplate = pHelperContext
237: .getEntityStateFieldTypeTemplate();
238: if (lEntityStateDataType == null) {
239: lEntityStateDataType = pModelAssistantImpl.mDataTypeClass
240: .createDataType();
241: lEntityStateDataType.setName(lEntityStateDataTypeName);
242: lDomainNamespace.getDataTypes().add(lEntityStateDataType);
243: } else {
244: if (pUnprocessedDataTypes != null)
245: pUnprocessedDataTypes.remove(lEntityStateDataType);
246: }
247: // Because the data type is located by name - it is possible that in fact it does not have
248: // features set up as we would like them to be. We need just to override them
249: lEntityStateDataType.setDescription(StylesheetImpl
250: .getEntityStateDataTypeDescription(pEntity.getName()));
251: lEntityStateDataType.setTypetemplate(lStateTypeTemplate);
252: pEntity.setStateDataType(lEntityStateDataType);
253: EntityStateDataTypeHelper lDataTypeHelper = new EntityStateDataTypeHelper(
254: pModelAssistantImpl, lEntityStateDataType);
255: // Here we would need to work on mandatory properties, but this type has none
256: return lEntityStateDataType;
257: }
258:
259: // This helper is looking after creation of absent ordering instruction data type
260: // The namespace is optional parameters - if it is null it will be discovered inside this method
261: // and if it is unobtainable - this method will fail to work and return false. This is provided to save some time
262: // during batch operations
263: static boolean ensureEntityStateDataTypeAbsent(Entity pEntity,
264: List pUnprocessedDataTypes, HelperContext pHelperContext) {
265: Namespace lDomainNamespace = pHelperContext
266: .getDomainNamespace();
267: if (lDomainNamespace == null)
268: return false;
269: String lEntityStateDataTypeName = StylesheetImpl
270: .getEntityStateDataTypeName(pEntity.getName());
271: DataType lEntityStateDataType = lDomainNamespace
272: .findDataType(lEntityStateDataTypeName);
273: if (lEntityStateDataType != null) {
274: if (pUnprocessedDataTypes != null)
275: pUnprocessedDataTypes.remove(lEntityStateDataType);
276: lEntityStateDataType.refDelete();
277: }
278: // Just in case - set the datatype to null
279: pEntity.setStateDataType(null);
280: return true; // Done
281: }
282:
283: public EntityStateDataTypeHelper(
284: ModelAssistantImpl pModelAssistantImpl,
285: DataType pEntityStateDataType) {
286: mModelAssistantImpl = pModelAssistantImpl;
287: mEntityStateDataType = pEntityStateDataType;
288: mEntityStateFieldTypeTemplate = mEntityStateDataType
289: .getTypetemplate();
290: mStatePropertyDescriptor = mEntityStateFieldTypeTemplate
291: .getPropertyDescriptor("State");
292: mStateNamePropertyDescriptor = mStatePropertyDescriptor
293: .getPropertyDescriptor("Name");
294: mStateDescriptionPropertyDescriptor = mStatePropertyDescriptor
295: .getPropertyDescriptor("Description");
296: mStateTypePropertyDescriptor = mStatePropertyDescriptor
297: .getPropertyDescriptor("Type");
298: mStateTransitionPropertyDescriptor = mStatePropertyDescriptor
299: .getPropertyDescriptor("Transition");
300: mStateTransitionDestinationStateNamePropertyDescriptor = mStateTransitionPropertyDescriptor
301: .getPropertyDescriptor("DestinationStateName");
302: mStateTransitionDescriptionPropertyDescriptor = mStateTransitionPropertyDescriptor
303: .getPropertyDescriptor("Description");
304: }
305:
306: // Marks all optional properties as unused.
307: // Every subsequent property action will remove from this list a property, which is not unused one
308: void markPropertiesAsUnused() {
309: // Put all properties to unused apart from mandatory ones
310: for (Iterator lPropertiesIterator = mEntityStateDataType
311: .getCombinedTypetemplateProperties().iterator(); lPropertiesIterator
312: .hasNext();) {
313: Property lProperty = (Property) lPropertiesIterator.next();
314: // Here we could filter out mandatory properties, so they never ever get into the unused
315: // set. This would ensure that they never deleted. This data type has not got
316: // any mandatory properties - so all properties will go into the unused set
317: mUnusedProperties.add(lProperty);
318: }
319: }
320:
321: // Deletes all properties in unused set at the moment. Normally
322: // we start with marking all properties as unused, than going though all property manipulations
323: // and than calling this method to delete all whjat is left
324: void deleteUnusedProperties() {
325: for (Iterator lUnprocessedPropertiesIterator = mUnusedProperties
326: .iterator(); lUnprocessedPropertiesIterator.hasNext();) {
327: Property lProperty = (Property) lUnprocessedPropertiesIterator
328: .next();
329: lProperty.refDelete();
330: }
331: }
332:
333: // Deletes all properties in unused set at the moment. Normally
334: // we start with marking all properties as unused, than going though all property manipulations
335: // and than calling this method to delete all whjat is left
336: private void verifyUnusedProperties(Collection pViolations) {
337: for (Iterator lUnprocessedPropertiesIterator = mUnusedProperties
338: .iterator(); lUnprocessedPropertiesIterator.hasNext();) {
339: Property lProperty = (Property) lUnprocessedPropertiesIterator
340: .next();
341: pViolations
342: .add(new ConstraintViolationException(
343: mEntityStateDataType,
344: mEntityStateDataType.refMetaObject(),
345: "DataType Property '"
346: + lProperty.getKey()
347: + "' appears to be not required. All properties in the Entity State Data Type must be derived from the Entity State Machine."));
348: }
349: }
350:
351: // Makes sure that the stae exists and its properties are set to given values
352: public void ensureStateExists(String pStateName,
353: String pStateDescription, StateType pStateType) {
354: // Work on state properties
355: Property lStateProperty = null;
356: Property lStateNameProperty = null;
357: Property lStateDescriptionProperty = null;
358: Property lStateTypeProperty = null;
359: Collection lAllStateNames = mEntityStateDataType
360: .getTypetemplatePropertiesByDescriptor(mStateNamePropertyDescriptor);
361: for (Iterator lPropertiesIterator = lAllStateNames.iterator(); lPropertiesIterator
362: .hasNext();) {
363: Property lProperty = (Property) lPropertiesIterator.next();
364: String lValue = lProperty.getValue();
365: if (lValue != null && lValue.equals(pStateName)) {
366: // If name found - it means state is already declared.
367: // If name is not found - we have to create a state
368: lStateNameProperty = lProperty;
369: lStateProperty = lStateNameProperty.getParentProperty();
370: // Find description and type properties
371: for (Iterator lSubPropertiesIterator = lStateProperty
372: .getSubProperties().iterator(); (lStateDescriptionProperty == null || lStateTypeProperty == null)
373: && lSubPropertiesIterator.hasNext();) {
374: Property lSubProperty = (Property) lSubPropertiesIterator
375: .next();
376: if (lSubProperty.getDescriptor().equals(
377: mStateDescriptionPropertyDescriptor))
378: lStateDescriptionProperty = lSubProperty;
379: else if (lSubProperty.getDescriptor().equals(
380: mStateTypePropertyDescriptor))
381: lStateTypeProperty = lSubProperty;
382: }
383: break;
384: }
385: }
386: if (lStateProperty == null) {
387: // Find out the next available array index
388: int lNextAvailableArrayIndex = mEntityStateDataType
389: .getTypetemplatePropertiesByDescriptor(
390: mStatePropertyDescriptor).size() + 1;
391: lStateProperty = mStatePropertyDescriptor.createProperty(
392: null, new Integer(lNextAvailableArrayIndex));
393: mEntityStateDataType.getTypetemplateProperties().add(
394: lStateProperty);
395: } else {
396: mUnusedProperties.remove(lStateProperty);
397: }
398:
399: if (lStateNameProperty == null) {
400: lStateNameProperty = mStateNamePropertyDescriptor
401: .createProperty(pStateName, null);
402: lStateProperty.getSubProperties().add(lStateNameProperty);
403: } else {
404: // No point updating the name it must be the same because we have found the whole thing by state name
405: mUnusedProperties.remove(lStateNameProperty);
406: }
407:
408: if (lStateDescriptionProperty == null) {
409: lStateDescriptionProperty = mStateDescriptionPropertyDescriptor
410: .createProperty(
411: pStateDescription != null ? pStateDescription
412: : "", null);
413: lStateProperty.getSubProperties().add(
414: lStateDescriptionProperty);
415: } else {
416: // Update description
417: lStateDescriptionProperty
418: .setValue(pStateDescription != null ? pStateDescription
419: : "");
420: mUnusedProperties.remove(lStateDescriptionProperty);
421: }
422:
423: if (lStateTypeProperty == null) {
424: lStateTypeProperty = mStateTypePropertyDescriptor
425: .createProperty(pStateType != null ? pStateType
426: .toString() : "", null);
427: lStateProperty.getSubProperties().add(lStateTypeProperty);
428: } else {
429: // Update type
430: lStateTypeProperty.setValue(pStateType != null ? pStateType
431: .toString() : "");
432: mUnusedProperties.remove(lStateTypeProperty);
433: }
434: }
435:
436: // Makes sure that the state related properties exist and its properties are set to given values
437: private void verifyStateExists(Collection pViolations,
438: String pStateName, String pStateDescription,
439: String pStateType) {
440: // Work on state properties
441: Property lStateProperty = null;
442: Property lStateNameProperty = null;
443: Property lStateDescriptionProperty = null;
444: Property lStateTypeProperty = null;
445: Collection lAllStateNames = mEntityStateDataType
446: .getTypetemplatePropertiesByDescriptor(mStateNamePropertyDescriptor);
447: for (Iterator lPropertiesIterator = lAllStateNames.iterator(); lPropertiesIterator
448: .hasNext();) {
449: Property lProperty = (Property) lPropertiesIterator.next();
450: String lValue = lProperty.getValue();
451: if (lValue != null && lValue.equals(pStateName)) {
452: // If name found - it means state is already declared.
453: // If name is not found - we have to create a state
454: lStateNameProperty = lProperty;
455: lStateProperty = lStateNameProperty.getParentProperty();
456: // Find description and type properties
457: for (Iterator lSubPropertiesIterator = lStateProperty
458: .getSubProperties().iterator(); (lStateDescriptionProperty == null || lStateTypeProperty == null)
459: && lSubPropertiesIterator.hasNext();) {
460: Property lSubProperty = (Property) lSubPropertiesIterator
461: .next();
462: if (lSubProperty.getDescriptor().equals(
463: mStateDescriptionPropertyDescriptor))
464: lStateDescriptionProperty = lSubProperty;
465: else if (lSubProperty.getDescriptor().equals(
466: mStateTypePropertyDescriptor))
467: lStateTypeProperty = lSubProperty;
468: }
469: break;
470: }
471: }
472:
473: // Because we have found all properties by this one we need to display generic error message and
474: // not check constraints any further because there will be nothing to check
475: if (lStateNameProperty == null) {
476: pViolations
477: .add(new ConstraintViolationException(
478: mEntityStateDataType,
479: mEntityStateDataType.refMetaObject(),
480: "DataType property is missing. Can not find State Property corresponding to the '"
481: + pStateName
482: + "' state. Entity State data type must have State property for each and every state."));
483: return; // Nothing more to say
484: } else {
485: // No point validating the name because we have found the whole thing by state name
486: mUnusedProperties.remove(lStateNameProperty);
487: }
488:
489: // Again - if this property is missing we should not check constraints any further because there will be nothing to check
490: if (lStateProperty == null) {
491: pViolations
492: .add(new ConstraintViolationException(
493: mEntityStateDataType,
494: mEntityStateDataType.refMetaObject(),
495: "DataType property is missing. Can not find State Property corresponding to the '"
496: + pStateName
497: + "' state. Entity State data type must have State property for each and every state."));
498: return; // Nothing more to say
499: } else {
500: mUnusedProperties.remove(lStateProperty);
501: }
502:
503: if (lStateDescriptionProperty == null) {
504: pViolations
505: .add(new ConstraintViolationException(
506: mEntityStateDataType,
507: mEntityStateDataType.refMetaObject(),
508: "DataType property is missing. Can not find State Description Property corresponding to the '"
509: + pStateName
510: + "' state. Entity State data type must have State Description property for each and every state."));
511: } else {
512: // Do not worry about description mismatch
513: mUnusedProperties.remove(lStateDescriptionProperty);
514: }
515:
516: if (lStateTypeProperty == null) {
517: pViolations
518: .add(new ConstraintViolationException(
519: mEntityStateDataType,
520: mEntityStateDataType.refMetaObject(),
521: "DataType property is missing. Can not find State Type Property corresponding to the '"
522: + pStateName
523: + "' state. Entity State data type must have State Type property for each and every state."));
524: } else {
525: // Do not worry about description mismatch
526: mUnusedProperties.remove(lStateTypeProperty);
527: if (!pStateType.equals(lStateTypeProperty.getValue()))
528: pViolations
529: .add(new ConstraintViolationException(
530: mEntityStateDataType,
531: mEntityStateDataType.refMetaObject(),
532: "DataType property has wrong value. Expecting State Type '"
533: + pStateType
534: + "' found '"
535: + lStateTypeProperty.getValue()
536: + "'. Entity State Type property value must match actual State Type."));
537: }
538: }
539:
540: public void ensureStateAbsent(String pStateName) {
541: // Work on ascending and descending categories
542: Property lStateProperty = null;
543: Collection lAllStateNames = mEntityStateDataType
544: .getTypetemplatePropertiesByDescriptor(mStateNamePropertyDescriptor);
545: for (Iterator lPropertiesIterator = lAllStateNames.iterator(); lPropertiesIterator
546: .hasNext();) {
547: Property lProperty = (Property) lPropertiesIterator.next();
548: String lValue = lProperty.getValue();
549: if (lValue != null && lValue.equals(pStateName)) {
550: // If name found - it means category is declared.
551: lStateProperty = lProperty.getParentProperty();
552: break;
553: }
554: }
555: if (lStateProperty != null) {
556: mUnusedProperties.remove(lStateProperty);
557: mUnusedProperties.removeAll(lStateProperty
558: .getCombinedProperties());
559: lStateProperty.refDelete();
560: }
561: }
562:
563: /** Ensures that transition exists. Source state must exist already */
564: public void ensureTransitionExists(String pSourceStateName,
565: String pDestinationStateName, String pTransitionDescription)
566: throws ModelRepositoryException {
567: // First obtain source state
568: Property lSourceStateProperty = null;
569: Collection lAllStateNames = mEntityStateDataType
570: .getTypetemplatePropertiesByDescriptor(mStateNamePropertyDescriptor);
571: for (Iterator lPropertiesIterator = lAllStateNames.iterator(); lPropertiesIterator
572: .hasNext();) {
573: Property lProperty = (Property) lPropertiesIterator.next();
574: String lValue = lProperty.getValue();
575: if (lValue != null && lValue.equals(pSourceStateName)) {
576: // If name found - it means category is declared.
577: lSourceStateProperty = lProperty.getParentProperty();
578: break;
579: }
580: }
581: if (lSourceStateProperty == null)
582: throw new ModelRepositoryException(
583: "Transition Source state '"
584: + pSourceStateName
585: + "' property does not exist. Unabe to work on Transition.");
586: // Work on transition properties
587: Property lTransitionProperty = null;
588: Property lTransitionDestinationStateNameProperty = null;
589: Property lTransitionDescriptionProperty = null;
590: Collection lAllDestinationStateNames = lSourceStateProperty
591: .getPropertiesByDescriptor(mStateTransitionDestinationStateNamePropertyDescriptor);
592: for (Iterator lPropertiesIterator = lAllDestinationStateNames
593: .iterator(); lPropertiesIterator.hasNext();) {
594: Property lProperty = (Property) lPropertiesIterator.next();
595: String lValue = lProperty.getValue();
596: if (lValue != null && lValue.equals(pDestinationStateName)) {
597: // If name found - it means transition is already declared.
598: // If name is not found - we have to create a transition
599: lTransitionDestinationStateNameProperty = lProperty;
600: lTransitionProperty = lTransitionDestinationStateNameProperty
601: .getParentProperty();
602: // Find description and type properties
603: for (Iterator lSubPropertiesIterator = lTransitionProperty
604: .getSubProperties().iterator(); lTransitionDescriptionProperty == null
605: && lSubPropertiesIterator.hasNext();) {
606: Property lSubProperty = (Property) lSubPropertiesIterator
607: .next();
608: if (lSubProperty
609: .getDescriptor()
610: .equals(
611: mStateTransitionDescriptionPropertyDescriptor))
612: lTransitionDescriptionProperty = lSubProperty;
613: }
614: break;
615: }
616: }
617: if (lTransitionProperty == null) {
618: lTransitionProperty = mStateTransitionPropertyDescriptor
619: .createProperty(
620: null,
621: new Integer(
622: lSourceStateProperty
623: .getPropertiesByDescriptor(
624: mStateTransitionPropertyDescriptor)
625: .size() + 1));
626: lSourceStateProperty.getSubProperties().add(
627: lTransitionProperty);
628: } else {
629: mUnusedProperties.remove(lTransitionProperty);
630: }
631:
632: if (lTransitionDestinationStateNameProperty == null) {
633: lTransitionDestinationStateNameProperty = mStateTransitionDestinationStateNamePropertyDescriptor
634: .createProperty(pDestinationStateName, null);
635: lTransitionProperty.getSubProperties().add(
636: lTransitionDestinationStateNameProperty);
637: } else {
638: mUnusedProperties
639: .remove(lTransitionDestinationStateNameProperty);
640: }
641:
642: if (lTransitionDescriptionProperty == null) {
643: lTransitionDescriptionProperty = mStateTransitionDescriptionPropertyDescriptor
644: .createProperty(pTransitionDescription, null);
645: lTransitionProperty.getSubProperties().add(
646: lTransitionDescriptionProperty);
647: } else {
648: mUnusedProperties.remove(lTransitionDescriptionProperty);
649: }
650: }
651:
652: // Makes sure that the transition related property exists and its properties are set to given values
653: void verifyTransitionExists(Collection pViolations,
654: String pSourceStateName, String pDestinationStateName,
655: String pTransitionDescription) {
656: // First obtain source state
657: Property lSourceStateProperty = null;
658: Collection lAllStateNames = mEntityStateDataType
659: .getTypetemplatePropertiesByDescriptor(mStateNamePropertyDescriptor);
660: for (Iterator lPropertiesIterator = lAllStateNames.iterator(); lPropertiesIterator
661: .hasNext();) {
662: Property lProperty = (Property) lPropertiesIterator.next();
663: String lValue = lProperty.getValue();
664: if (lValue != null && lValue.equals(pSourceStateName)) {
665: // If name found - it means state is declared.
666: lSourceStateProperty = lProperty.getParentProperty();
667: break;
668: }
669: }
670: if (lSourceStateProperty == null)
671: return; // No source stae property found - so we can not really validate the transiton
672: // Work on transition properties
673: Property lTransitionProperty = null;
674: Property lTransitionDestinationStateNameProperty = null;
675: Property lTransitionDescriptionProperty = null;
676: Collection lAllDestinationStateNames = lSourceStateProperty
677: .getPropertiesByDescriptor(mStateTransitionDestinationStateNamePropertyDescriptor);
678: for (Iterator lPropertiesIterator = lAllDestinationStateNames
679: .iterator(); lPropertiesIterator.hasNext();) {
680: Property lProperty = (Property) lPropertiesIterator.next();
681: String lValue = lProperty.getValue();
682: if (lValue != null && lValue.equals(pDestinationStateName)) {
683: // If name found - it means transition is already declared.
684: // If name is not found - we have to create a transition
685: lTransitionDestinationStateNameProperty = lProperty;
686: lTransitionProperty = lTransitionDestinationStateNameProperty
687: .getParentProperty();
688: // Find description and type properties
689: for (Iterator lSubPropertiesIterator = lTransitionProperty
690: .getSubProperties().iterator(); lTransitionDescriptionProperty == null
691: && lSubPropertiesIterator.hasNext();) {
692: Property lSubProperty = (Property) lSubPropertiesIterator
693: .next();
694: if (lSubProperty
695: .getDescriptor()
696: .equals(
697: mStateTransitionDescriptionPropertyDescriptor))
698: lTransitionDescriptionProperty = lSubProperty;
699: }
700: break;
701: }
702: }
703:
704: if (lTransitionDestinationStateNameProperty == null) {
705: pViolations
706: .add(new ConstraintViolationException(
707: mEntityStateDataType,
708: mEntityStateDataType.refMetaObject(),
709: "DataType property is missing. Can not find State Transition Property corresponding to the transition from '"
710: + pSourceStateName
711: + "' to '"
712: + pDestinationStateName
713: + "'. Entity State data type must have Transition property for each and every state transition."));
714: return; // Nothing more to say
715: } else {
716: mUnusedProperties
717: .remove(lTransitionDestinationStateNameProperty);
718: }
719:
720: if (lTransitionProperty == null) {
721: pViolations
722: .add(new ConstraintViolationException(
723: mEntityStateDataType,
724: mEntityStateDataType.refMetaObject(),
725: "DataType property is missing. Can not find State Transition Property corresponding to the transition from '"
726: + pSourceStateName
727: + "' to '"
728: + pDestinationStateName
729: + "'. Entity State data type must have Transition property for each and every state transition."));
730: return; // Nothing more to say
731: } else {
732: mUnusedProperties.remove(lTransitionProperty);
733: }
734:
735: if (lTransitionDescriptionProperty == null) {
736: pViolations
737: .add(new ConstraintViolationException(
738: mEntityStateDataType,
739: mEntityStateDataType.refMetaObject(),
740: "DataType property is missing. Can not find State Transition Description Property corresponding to the transition from '"
741: + pSourceStateName
742: + "' to '"
743: + pDestinationStateName
744: + "'. Entity State data type must have State Transition Description property for each and every state transition."));
745: } else {
746: mUnusedProperties.remove(lTransitionDescriptionProperty);
747: }
748: }
749:
750: public void ensureTransitionAbsent(String pSourceStateName,
751: String pDestinationStateName) {
752: // First obtain source state
753: Property lSourceStateProperty = null;
754: Collection lAllStateNames = mEntityStateDataType
755: .getTypetemplatePropertiesByDescriptor(mStateNamePropertyDescriptor);
756: for (Iterator lPropertiesIterator = lAllStateNames.iterator(); lPropertiesIterator
757: .hasNext();) {
758: Property lProperty = (Property) lPropertiesIterator.next();
759: String lValue = lProperty.getValue();
760: if (lValue != null && lValue.equals(pSourceStateName)) {
761: // If name found - it means category is declared.
762: lSourceStateProperty = lProperty.getParentProperty();
763: break;
764: }
765: }
766: if (lSourceStateProperty == null)
767: return; // Source state property is not here. Transition is definitely absent
768: // Work on transition properties
769: Property lTransitionProperty = null;
770: Collection lAllDestinationStateNames = lSourceStateProperty
771: .getPropertiesByDescriptor(mStateTransitionDestinationStateNamePropertyDescriptor);
772: for (Iterator lPropertiesIterator = lAllDestinationStateNames
773: .iterator(); lPropertiesIterator.hasNext();) {
774: Property lProperty = (Property) lPropertiesIterator.next();
775: String lValue = lProperty.getValue();
776: if (lValue != null && lValue.equals(pDestinationStateName)) {
777: // If name found - it means transition is declared.
778: lTransitionProperty = lProperty.getParentProperty();
779: break;
780: }
781: }
782: if (lTransitionProperty != null) {
783: mUnusedProperties.remove(lTransitionProperty);
784: mUnusedProperties.removeAll(lTransitionProperty
785: .getCombinedProperties());
786: lTransitionProperty.refDelete();
787: }
788: }
789: }
|