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.domainsupport;
016:
017: import java.util.ArrayList;
018: import java.util.Collection;
019: import java.util.HashSet;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Set;
023:
024: import javax.jmi.reflect.ConstraintViolationException;
025: import javax.jmi.reflect.RefObject;
026:
027: import com.metaboss.sdlctools.models.metabossmodel.ModelElementConstraint;
028: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.Structure;
029: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.Message;
030: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.Operation;
031: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.OperationInputField;
032: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.OperationOutputField;
033: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.OperationOutputMessage;
034: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.Service;
035: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.Servicemodule;
036: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.TransactionPolicyEnum;
037: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.AggregationTypeEnum;
038: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.AssociationRole;
039: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.AssociationRoleCardinalityEnum;
040: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Domain;
041: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Entity;
042: import com.metaboss.util.StringUtils;
043:
044: /** This class containse helper methods dealing with the Domain Support Servicemodule model element */
045: class TargetGetAllReferencedEntitiesOperationHelper {
046: private ModelAssistantImpl mModelAssistantImpl;
047:
048: TargetGetAllReferencedEntitiesOperationHelper(
049: ModelAssistantImpl pModelAssistantImpl) {
050: mModelAssistantImpl = pModelAssistantImpl;
051:
052: // Add entity Name attribute change listener
053: mModelAssistantImpl
054: .addAttributeChangeListener(
055: Entity.class,
056: "Name",
057: new ModelAssistantImpl.ModelElementAttributeChangeListener() {
058: public void onAttributeBeingUpdated(
059: RefObject pModelElementBeingUpdated,
060: String pAttributeName,
061: Object pOldValue, Object pNewValue) {
062: Entity lEntity = (Entity) pModelElementBeingUpdated;
063: Domain lDomain = lEntity.getDomain();
064: if (lDomain == null)
065: return; // Entity is not associated with domain
066: String lDomainName = lDomain.getName();
067: if (lDomainName == null)
068: return; // Domain does not have a name
069: com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.System lSystem = lDomain
070: .getSystem();
071: if (lSystem == null)
072: return; // Domain is not associated with system
073: Servicemodule lServicemodule = lSystem
074: .findServicemodule(StylesheetImpl
075: .getDomainSupportServicemoduleName(lDomainName));
076: if (lServicemodule == null)
077: return; // There is no support servicemodule yet
078: Service lDomainSupportService = lServicemodule
079: .findService(StylesheetImpl
080: .getDataManagementServiceName(lDomainName));
081: if (lDomainSupportService == null)
082: return; // There is no domain support service yet
083: // Iterate through references and ensure that the name change is accounted for
084: for (Iterator lEntityReferencesIterator = lEntity
085: .getCombinedReferences()
086: .iterator(); lEntityReferencesIterator
087: .hasNext();) {
088: AssociationRole lReference = (AssociationRole) lEntityReferencesIterator
089: .next();
090: String lReferencePluralName = lReference
091: .getPluralName();
092: if (lReferencePluralName == null)
093: continue; // Reference does not have a plural name yet
094: if (pNewValue == null) {
095: // Only old value is known - ensure that the element is deleted
096: ensureAbsent(
097: lDomainSupportService,
098: (String) pOldValue,
099: lReferencePluralName);
100: } else {
101: // New value is known - analyse the criteria and deal with the element accordingly
102: AssociationRole lOppositeRole = lReference
103: .getOppositeRole();
104: if (lOppositeRole != null
105: && lReference
106: .isPlural()
107: && lOppositeRole
108: .isPlural()
109: && AggregationTypeEnum.AGGREGATION
110: .equals(lOppositeRole
111: .getAggregationType())) {
112: // The element must be present - rename or create
113: if (pOldValue != null)
114: ensureRenamedPresent(
115: lDomainSupportService,
116: lReference,
117: (String) pOldValue,
118: (String) pNewValue,
119: lReferencePluralName,
120: lReferencePluralName);
121: else
122: ensurePresent(
123: lDomainSupportService,
124: lReference,
125: (String) pNewValue,
126: lReferencePluralName);
127: } else {
128: // The element must be absent - delete
129: ensureAbsent(
130: lDomainSupportService,
131: (String) pNewValue,
132: lReferencePluralName);
133: if (pOldValue != null)
134: ensureAbsent(
135: lDomainSupportService,
136: (String) pOldValue,
137: lReferencePluralName);
138: }
139: }
140: }
141: }
142: });
143:
144: // Add reference pluralName attribute change listener
145: mModelAssistantImpl
146: .addAttributeChangeListener(
147: AssociationRole.class,
148: "pluralName",
149: new ModelAssistantImpl.ModelElementAttributeChangeListener() {
150: public void onAttributeBeingUpdated(
151: RefObject pModelElementBeingUpdated,
152: String pAttributeName,
153: Object pOldValue, Object pNewValue) {
154: AssociationRole lReference = (AssociationRole) pModelElementBeingUpdated;
155: Entity lEntity = lReference
156: .getReferencingEntity();
157: if (lEntity == null)
158: return; // Attribute is not associated with entity
159: Domain lDomain = lEntity.getDomain();
160: if (lDomain == null)
161: return; // Entity is not associated with domain
162: String lDomainName = lDomain.getName();
163: if (lDomainName == null)
164: return; // Domain does not have a name
165: com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.System lSystem = lDomain
166: .getSystem();
167: if (lSystem == null)
168: return; // Domain is not associated with system
169: Servicemodule lServicemodule = lSystem
170: .findServicemodule(StylesheetImpl
171: .getDomainSupportServicemoduleName(lDomainName));
172: if (lServicemodule == null)
173: return; // There is no support servicemodule yet
174: Service lDomainSupportService = lServicemodule
175: .findService(StylesheetImpl
176: .getDataManagementServiceName(lDomainName));
177: if (lDomainSupportService == null)
178: return; // There is no domain support service yet
179: AssociationRole lOppositeRole = lReference
180: .getOppositeRole();
181: // Iterate through all entities containing this reference and ensure that the change is reflected
182: Set lAllEntitiesToConsider = new HashSet();
183: lAllEntitiesToConsider.add(lEntity);
184: lAllEntitiesToConsider.addAll(lEntity
185: .getCombinedSubtypes());
186: for (Iterator lEntityElementsIterator = lAllEntitiesToConsider
187: .iterator(); lEntityElementsIterator
188: .hasNext();) {
189: Entity lEntityElement = (Entity) lEntityElementsIterator
190: .next();
191: String lEntityName = lEntityElement
192: .getName();
193: if (lEntityName == null)
194: continue; // Entity does not have a name
195: if (pNewValue == null) {
196: // Only old value is known - ensure that the element is deleted
197: ensureAbsent(
198: lDomainSupportService,
199: lEntityName,
200: (String) pOldValue);
201: } else {
202: // New value is known - analyse the criteria and deal with the element accordingly
203: if (lOppositeRole != null
204: && lReference
205: .isPlural()
206: && lOppositeRole
207: .isPlural()
208: && AggregationTypeEnum.AGGREGATION
209: .equals(lOppositeRole
210: .getAggregationType())) {
211: // The element must be present - rename or create
212: if (pOldValue != null)
213: ensureRenamedPresent(
214: lDomainSupportService,
215: lReference,
216: lEntityName,
217: lEntityName,
218: (String) pOldValue,
219: (String) pNewValue);
220: else
221: ensurePresent(
222: lDomainSupportService,
223: lReference,
224: lEntityName,
225: (String) pNewValue);
226: } else {
227: // The element must be absent - delete
228: ensureAbsent(
229: lDomainSupportService,
230: lEntityName,
231: (String) pNewValue);
232: if (pOldValue != null)
233: ensureAbsent(
234: lDomainSupportService,
235: lEntityName,
236: (String) pOldValue);
237: }
238: }
239: }
240: }
241: });
242:
243: // Add reference cardinality attribute change listener
244: mModelAssistantImpl
245: .addAttributeChangeListener(
246: AssociationRole.class,
247: "cardinality",
248: new ModelAssistantImpl.ModelElementAttributeChangeListener() {
249: public void onAttributeBeingUpdated(
250: RefObject pModelElementBeingUpdated,
251: String pAttributeName,
252: Object pOldValue, Object pNewValue) {
253: AssociationRole lReference = (AssociationRole) pModelElementBeingUpdated;
254: String lReferencePluralName = lReference
255: .getPluralName();
256: if (lReferencePluralName == null)
257: return; // Role does not have a name
258: Entity lReferencingEntity = lReference
259: .getReferencingEntity();
260: if (lReferencingEntity == null)
261: return; // Attribute is not associated with entity
262: Domain lDomain = lReferencingEntity
263: .getDomain();
264: if (lDomain == null)
265: return; // Entity is not associated with domain
266: String lDomainName = lDomain.getName();
267: if (lDomainName == null)
268: return; // Domain does not have a name
269: com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.System lSystem = lDomain
270: .getSystem();
271: if (lSystem == null)
272: return; // Domain is not associated with system
273: Servicemodule lServicemodule = lSystem
274: .findServicemodule(StylesheetImpl
275: .getDomainSupportServicemoduleName(lDomainName));
276: if (lServicemodule == null)
277: return; // There is no support servicemodule yet
278: Service lDomainSupportService = lServicemodule
279: .findService(StylesheetImpl
280: .getDataManagementServiceName(lDomainName));
281: if (lDomainSupportService == null)
282: return; // There is no domain support service yet
283: AssociationRole lOppositeRole = lReference
284: .getOppositeRole();
285: // Iterate through all entities having this reference and ensure that the change is reflected
286: {
287: Set lAllEntitiesToConsider = new HashSet();
288: lAllEntitiesToConsider
289: .add(lReferencingEntity);
290: lAllEntitiesToConsider
291: .addAll(lReferencingEntity
292: .getCombinedSubtypes());
293: for (Iterator lEntityElementsIterator = lAllEntitiesToConsider
294: .iterator(); lEntityElementsIterator
295: .hasNext();) {
296: Entity lEntityElement = (Entity) lEntityElementsIterator
297: .next();
298: String lEntityName = lEntityElement
299: .getName();
300: if (lEntityName == null)
301: continue; // Entity does not have a name
302: if (lOppositeRole != null
303: && (AssociationRoleCardinalityEnum.ONE_TO_MANY
304: .equals(pNewValue) || AssociationRoleCardinalityEnum.ZERO_TO_MANY
305: .equals(pNewValue))
306: && // lReferenc.isPlural()
307: lOppositeRole
308: .isPlural()
309: && AggregationTypeEnum.AGGREGATION
310: .equals(lOppositeRole
311: .getAggregationType()))
312: ensurePresent(
313: lDomainSupportService,
314: lReference,
315: lEntityName,
316: lReferencePluralName);
317: else
318: ensureAbsent(
319: lDomainSupportService,
320: lEntityName,
321: lReferencePluralName);
322: }
323: }
324: // Look at the entity at the opposite side and ensure that the change is reflected
325: if (lOppositeRole != null) {
326: Entity lReferencedEntity = lReference
327: .getEntity();
328: String lReferencedEntityName = lReferencedEntity
329: .getName();
330: String lOppositeRolePluralName = lOppositeRole
331: .getName();
332: if (lReferencedEntityName != null) {
333: if ((AssociationRoleCardinalityEnum.ONE_TO_MANY
334: .equals(pNewValue) || AssociationRoleCardinalityEnum.ZERO_TO_MANY
335: .equals(pNewValue))
336: && // lReferenc.isPlural()
337: lOppositeRole
338: .isPlural()
339: && AggregationTypeEnum.AGGREGATION
340: .equals(lReference
341: .getAggregationType()))
342: ensurePresent(
343: lDomainSupportService,
344: lOppositeRole,
345: lReferencedEntityName,
346: lOppositeRolePluralName);
347: else
348: ensureAbsent(
349: lDomainSupportService,
350: lReferencedEntityName,
351: lOppositeRolePluralName);
352: }
353: }
354: }
355: });
356: }
357:
358: private static final String sOperationConstraintTextBase = "A Data Management Service must have Get All Referenced Entities operation for every many-to-many Association between Entities in the corresponding Domain.";
359: private static final String sReferencingEntityKeyInputFieldConstraintTextBase = "An Get All Referenced Entities Data Management Operation must have well formed Referencing Entity Key input parameter carrying referencing Entity identification information.";
360: private static final String sRetrievedEntityDetailsOutputFieldConstraintTextBase = "A Get All Referenced Entities Data Management Operation must have well formed Referenced Entities Details output parameter carrying the details of all retrieved Entities.";
361: private static final String sOperationInputConstraintTextBase = "A Get All Referenced Entities Data Management Operation must have well formed Input Constraints performing sanity check on the input data.";
362: private static final String sEntityNotFoundErrorOutputMessageConstraintTextBase = "A Get All Referenced Entities Data Management Operation must have well formed Entity Not Found output message, one for each reference, which is a part of the primary key of referencing Entity.";
363:
364: // This helper verifies constraints
365: void verifyConstraints(Collection pViolations,
366: Service pDataManagementService, AssociationRole pReference,
367: Collection pUnclaimedOperations) {
368: // Check if we have an operation and than just call ensurePresent
369: AssociationRole lOppositeReference = pReference
370: .getOppositeRole();
371: Entity lReferencingEntity = lOppositeReference.getEntity();
372: if (lReferencingEntity == null)
373: return; // Unable to rectify properly
374: String lReferencingEntityName = lReferencingEntity.getName();
375: if (lReferencingEntityName == null)
376: return; // Unable to rectify properly
377: String lReferencePluralName = pReference.getPluralName();
378: if (lReferencePluralName == null)
379: return; // Unable to rectify properly
380: // Work on the Key structure
381: String lOperationName = suggestOperationName(
382: lReferencingEntityName, lReferencePluralName);
383: Operation lOperation = pDataManagementService
384: .findOperation(lOperationName);
385: if (lOperation == null) {
386: if (AggregationTypeEnum.AGGREGATION
387: .equals(lOppositeReference.getAggregationType())
388: && pReference.isPlural()
389: && lOppositeReference.isPlural())
390: pViolations.add(new ConstraintViolationException(
391: pDataManagementService, pDataManagementService
392: .refMetaObject(),
393: sOperationConstraintTextBase + " The '"
394: + lOperationName
395: + "' Operation not found."));
396: return;
397: }
398: pUnclaimedOperations.remove(lOperation); // Claim the operation
399: if (AggregationTypeEnum.AGGREGATION.equals(lOppositeReference
400: .getAggregationType()) == false
401: || pReference.isPlural() == false
402: || lOppositeReference.isPlural() == false) {
403: pViolations.add(new ConstraintViolationException(
404: pDataManagementService, pDataManagementService
405: .refMetaObject(),
406: sOperationConstraintTextBase + " The '"
407: + lOperationName
408: + "' Operation unexpected."));
409: return;
410: }
411: // Input Fields - only verify that the ones that we need exist. The extra ones are allowed
412: {
413: String lOperationInputFieldName = StylesheetImpl
414: .getEntityKeyOperationInputParameterName(lReferencingEntityName);
415: OperationInputField lInputField = lOperation
416: .findInputField(lOperationInputFieldName);
417: if (lInputField != null) {
418: Structure lEntityKeyStructure = pDataManagementService
419: .getServicemodule() != null ? pDataManagementService
420: .getServicemodule()
421: .findStructure(
422: StylesheetImpl
423: .getEntityKeyStructureName(lReferencingEntityName))
424: : null;
425: if (lEntityKeyStructure != null
426: && lEntityKeyStructure.equals(lInputField
427: .getStructureType()) == false)
428: pViolations.add(new ConstraintViolationException(
429: lInputField, lInputField.refMetaObject(),
430: sReferencingEntityKeyInputFieldConstraintTextBase
431: + " The '"
432: + lOperationInputFieldName
433: + "' input field has wrong type."));
434: if (lInputField.isArray())
435: pViolations
436: .add(new ConstraintViolationException(
437: lInputField,
438: lInputField.refMetaObject(),
439: sReferencingEntityKeyInputFieldConstraintTextBase
440: + " The '"
441: + lOperationInputFieldName
442: + "' input field is an array, which is wrong."));
443: } else
444: pViolations.add(new ConstraintViolationException(
445: lOperation, lOperation.refMetaObject(),
446: sReferencingEntityKeyInputFieldConstraintTextBase
447: + " The '" + lOperationInputFieldName
448: + "' input field is missing."));
449: }
450: // Input constraints - only verify that the ones that we need exist. The extra ones are allowed
451: {
452: // Work on the entity key validation constraint.
453: {
454: String lEntityKeyInputFieldName = StylesheetImpl
455: .getEntityKeyOperationInputParameterName(lReferencingEntityName);
456: String lConstraintName = lEntityKeyInputFieldName
457: + "FieldPresenceConstraint";
458: ModelElementConstraint lModelElementConstraint = lOperation
459: .findInputConstraint(lConstraintName);
460: if (lModelElementConstraint == null)
461: pViolations
462: .add(new ConstraintViolationException(
463: lOperation,
464: lOperation.refMetaObject(),
465: sOperationInputConstraintTextBase
466: + " The '"
467: + lConstraintName
468: + "' Input Constraint is missing."));
469: }
470: }
471: // Output Fields - only verify that the ones that we need exist. The extra ones are allowed
472: {
473: String lOperationOutputFieldName = suggestReferenceDetailsOutputParameterName(lReferencePluralName);
474: OperationOutputField lOutputField = lOperation
475: .findOutputField(lOperationOutputFieldName);
476: if (lOutputField != null) {
477: Entity lReferencedEntity = pReference.getEntity();
478: if (lReferencedEntity != null) {
479: String lReferencedEntityName = lReferencedEntity
480: .getName();
481: if (lReferencedEntityName != null) {
482: Structure lEntityDetailsStructure = pDataManagementService
483: .getServicemodule() != null ? pDataManagementService
484: .getServicemodule()
485: .findStructure(
486: StylesheetImpl
487: .getEntityDetailsStructureName(lReferencedEntityName))
488: : null;
489: if (lEntityDetailsStructure != null
490: && lEntityDetailsStructure
491: .equals(lOutputField
492: .getStructureType()) == false)
493: pViolations
494: .add(new ConstraintViolationException(
495: lOutputField,
496: lOutputField
497: .refMetaObject(),
498: sRetrievedEntityDetailsOutputFieldConstraintTextBase
499: + " The '"
500: + lOperationOutputFieldName
501: + "' output field has wrong type."));
502: }
503: }
504: if (!lOutputField.isArray())
505: pViolations
506: .add(new ConstraintViolationException(
507: lOutputField,
508: lOutputField.refMetaObject(),
509: sRetrievedEntityDetailsOutputFieldConstraintTextBase
510: + " The '"
511: + lOperationOutputFieldName
512: + "' output field is not an array, which is wrong."));
513: } else
514: pViolations.add(new ConstraintViolationException(
515: lOperation, lOperation.refMetaObject(),
516: sRetrievedEntityDetailsOutputFieldConstraintTextBase
517: + " The '" + lOperationOutputFieldName
518: + "' output field is missing."));
519: }
520: // Output Messages - only verify that the ones that we need exist. The extra ones are allowed
521: {
522: // This method loads instances of the referencing entity and referenced entities
523: // all of them have a chance not to be found. We need to add relevant output mesages in the output specification
524: Set lEntitiesWhichMayBeNotFoundWhenInvokingOperation = new HashSet();
525: lEntitiesWhichMayBeNotFoundWhenInvokingOperation
526: .add(lReferencingEntity);
527: Util.collectEntitiesWhichMayBeNotFoundWhenLoadingInstance(
528: lReferencingEntity,
529: lEntitiesWhichMayBeNotFoundWhenInvokingOperation);
530:
531: for (Iterator lEntitiesWhichMayBeNotFoundWhenInvokingOperationIterator = lEntitiesWhichMayBeNotFoundWhenInvokingOperation
532: .iterator(); lEntitiesWhichMayBeNotFoundWhenInvokingOperationIterator
533: .hasNext();) {
534: Entity lEntityElement = (Entity) lEntitiesWhichMayBeNotFoundWhenInvokingOperationIterator
535: .next();
536: String lEntityElementName = lEntityElement.getName();
537: if (lEntityElementName == null)
538: continue;
539: String lOperationOutputMessageName = StylesheetImpl
540: .getEntityNotFoundOperationOutputMessageName(lEntityElementName);
541: OperationOutputMessage lOutputMessage = lOperation
542: .findOutputMessage(lOperationOutputMessageName);
543: if (lOutputMessage != null) {
544: Message lEntityNotFoundMessage = pDataManagementService
545: .getServicemodule() != null ? pDataManagementService
546: .getServicemodule()
547: .findMessage(
548: StylesheetImpl
549: .getEntityInstanceNotFoundMessageName(lEntityElementName))
550: : null;
551: if (lEntityNotFoundMessage != null
552: && lEntityNotFoundMessage
553: .equals(lOutputMessage
554: .getMessageType()) == false)
555: pViolations
556: .add(new ConstraintViolationException(
557: lOutputMessage,
558: lOutputMessage.refMetaObject(),
559: sEntityNotFoundErrorOutputMessageConstraintTextBase
560: + " The '"
561: + lOperationOutputMessageName
562: + "' output message has wrong type."));
563: if (lOutputMessage.isArray())
564: pViolations
565: .add(new ConstraintViolationException(
566: lOutputMessage,
567: lOutputMessage.refMetaObject(),
568: sEntityNotFoundErrorOutputMessageConstraintTextBase
569: + " The '"
570: + lOperationOutputMessageName
571: + "' output message is an array, which is wrong."));
572: } else
573: pViolations.add(new ConstraintViolationException(
574: lOperation, lOperation.refMetaObject(),
575: sEntityNotFoundErrorOutputMessageConstraintTextBase
576: + " The '"
577: + lOperationOutputMessageName
578: + "' output message is missing."));
579: }
580: }
581: }
582:
583: // This helper is doing everything necessary to rectify errors reported in verifyConstraints()
584: void rectifyModel(Service pDataManagementService,
585: AssociationRole pReference, Collection pUnclaimedOperations) {
586: // Check if we have an operation and than just call ensurePresent
587: AssociationRole lOppositeReference = pReference
588: .getOppositeRole();
589: Entity lReferencingEntity = lOppositeReference.getEntity();
590: if (lReferencingEntity == null)
591: return; // Unable to rectify properly
592: String lReferencingEntityName = lReferencingEntity.getName();
593: if (lReferencingEntityName == null)
594: return; // Unable to rectify properly
595: String lReferencePluralName = pReference.getPluralName();
596: if (lReferencePluralName == null)
597: return; // Unable to rectify properly
598: String lOperationName = suggestOperationName(
599: lReferencingEntityName, lReferencePluralName);
600: Operation lOperation = pDataManagementService
601: .findOperation(lOperationName);
602: if (lOperation != null)
603: pUnclaimedOperations.remove(lOperation); // Claim the operation
604: // We are after aggregation side of the many to many associations
605: if (AggregationTypeEnum.AGGREGATION.equals(lOppositeReference
606: .getAggregationType())
607: && pReference.isPlural()
608: && lOppositeReference.isPlural())
609: ensurePresent(pDataManagementService, pReference,
610: lReferencingEntityName, lReferencePluralName);
611: else
612: ensureAbsent(pDataManagementService,
613: lReferencingEntityName, lReferencePluralName);
614: }
615:
616: // This helper renames and ensures that the element is present
617: void ensureRenamedPresent(Service pDataManagementService,
618: AssociationRole pReference, String pOldEntityName,
619: String pNewEntityName, String pOldReferencePluralName,
620: String pNewReferencePluralName) {
621: // Note that this method only deals with renaming and than calls the ensure present method
622: String lOldOperationName = suggestOperationName(pOldEntityName,
623: pOldReferencePluralName);
624: Operation lOldOperation = pDataManagementService
625: .findOperation(lOldOperationName);
626: String lNewOperationName = suggestOperationName(pNewEntityName,
627: pNewReferencePluralName);
628: Operation lNewOperation = pDataManagementService
629: .findOperation(lNewOperationName);
630: // Be relaxed here - allow for all sorts of mishaps
631: if (lOldOperation != null) {
632: if (lNewOperation != null) {
633: // New and old structures are present - just delete the old one
634: lOldOperation.refDelete();
635: } else {
636: // Old structure is present - new one is not - rename
637: lOldOperation.setName(lNewOperationName);
638: }
639: }
640: // Call the ensure present bit
641: ensurePresent(pDataManagementService, pReference,
642: pNewEntityName, pNewReferencePluralName);
643: }
644:
645: // This helper makes sure that the version id attribute is present in the details structure
646: void ensurePresent(Service pDataManagementService,
647: AssociationRole pReference, String pReferencingEntityName,
648: String pReferencePluralName) {
649: AssociationRole lOppositeReference = pReference
650: .getOppositeRole();
651: Entity lReferencingEntity = lOppositeReference.getEntity();
652: // Work on the servicemodule
653: String lOperationName = suggestOperationName(
654: pReferencingEntityName, pReferencePluralName);
655: Operation lOperation = pDataManagementService
656: .findOperation(lOperationName);
657: if (lOperation == null) {
658: lOperation = mModelAssistantImpl.mOperationClass
659: .createOperation();
660: lOperation.setService(pDataManagementService);
661: lOperation.setName(lOperationName);
662: }
663: lOperation.setDescription(suggestOperationDescription(
664: pReferencingEntityName, pReferencePluralName));
665: lOperation
666: .setTransactionPolicy(TransactionPolicyEnum.SUPPORTED);
667: lOperation.setQuery(true);
668: // Input Fields
669: {
670: Collection lOperationInputFields = lOperation
671: .getInputFields();
672: List lUnprocessedInputFields = new ArrayList();
673: lUnprocessedInputFields.addAll(lOperationInputFields);
674: // Add entity key parameter
675: {
676: String lOperationInputFieldName = StylesheetImpl
677: .getEntityKeyOperationInputParameterName(pReferencingEntityName);
678: OperationInputField lInputField = lOperation
679: .findInputField(lOperationInputFieldName);
680: if (lInputField == null) {
681: lInputField = mModelAssistantImpl.mOperationInputFieldClass
682: .createOperationInputField();
683: lInputField.setName(lOperationInputFieldName);
684: lInputField.setOperation(lOperation);
685: } else {
686: lUnprocessedInputFields.remove(lInputField);
687: }
688: lInputField
689: .setDescription(suggestEntityKeyInputParameterDescription(pReferencingEntityName));
690: lInputField.setArray(false);
691: lInputField.setDataType(null);
692: Structure lEntityKeyStructure = pDataManagementService
693: .getServicemodule() != null ? pDataManagementService
694: .getServicemodule()
695: .findStructure(
696: StylesheetImpl
697: .getEntityKeyStructureName(pReferencingEntityName))
698: : null;
699: lInputField.setStructureType(lEntityKeyStructure);
700: }
701:
702: // Delete all input fields left
703: for (Iterator lUnprocessedInputFieldsIterator = lUnprocessedInputFields
704: .iterator(); lUnprocessedInputFieldsIterator
705: .hasNext();) {
706: OperationInputField lInputField = (OperationInputField) lUnprocessedInputFieldsIterator
707: .next();
708: if (!lInputField.isDerived())
709: lInputField.refDelete();
710: }
711: }
712: // Input constraints
713: {
714: // Copy aside the collection of the constraints, so we can delete the unused ones
715: Collection lUnclaimedConstraints = new ArrayList();
716: lUnclaimedConstraints.addAll(lOperation
717: .getInputConstraints());
718: // Work on the entity key validation constraint.
719: {
720: String lEntityKeyInputFieldName = StylesheetImpl
721: .getEntityKeyOperationInputParameterName(pReferencingEntityName);
722: String lEntityKeyOCLFieldName = lEntityKeyInputFieldName
723: .substring(0, 1).toLowerCase()
724: + lEntityKeyInputFieldName.substring(1);
725: String lConstraintName = lEntityKeyInputFieldName
726: + "FieldPresenceConstraint";
727: ModelElementConstraint lModelElementConstraint = lOperation
728: .findInputConstraint(lConstraintName);
729: if (lModelElementConstraint == null) {
730: lModelElementConstraint = mModelAssistantImpl.mModelElementConstraintClass
731: .createModelElementConstraint();
732: lModelElementConstraint.setName(lConstraintName);
733: lOperation.getInputConstraints().add(
734: lModelElementConstraint);
735: } else {
736: // Claim the field
737: lUnclaimedConstraints
738: .remove(lModelElementConstraint);
739: }
740: lModelElementConstraint
741: .setDescription("Verifies that the "
742: + lEntityKeyInputFieldName
743: + " input field is not empty in the operation input");
744: lModelElementConstraint.setDefaultErrorText("The '"
745: + lEntityKeyInputFieldName
746: + "' input field must not be empty.");
747: lModelElementConstraint.setOclExpression("not "
748: + lEntityKeyOCLFieldName + ".oclIsUndefined()");
749: }
750: // Remove unclaimed constraints
751: for (Iterator lUnclaimedConstraintsIterator = lUnclaimedConstraints
752: .iterator(); lUnclaimedConstraintsIterator
753: .hasNext();) {
754: ModelElementConstraint lUnclaimedConstraint = (ModelElementConstraint) lUnclaimedConstraintsIterator
755: .next();
756: if (!lUnclaimedConstraint.isDerived())
757: lUnclaimedConstraint.refDelete();
758: }
759: }
760: // Output Fields
761: {
762: Collection lOperationOutputFields = lOperation
763: .getOutputFields();
764: List lUnprocessedOutputFields = new ArrayList();
765: lUnprocessedOutputFields.addAll(lOperationOutputFields);
766:
767: // Add reference details parameter
768: {
769: String lOperationOutputFieldName = suggestReferenceDetailsOutputParameterName(pReferencePluralName);
770: OperationOutputField lOutputField = lOperation
771: .findOutputField(lOperationOutputFieldName);
772: if (lOutputField == null) {
773: lOutputField = mModelAssistantImpl.mOperationOutputFieldClass
774: .createOperationOutputField();
775: lOutputField.setName(lOperationOutputFieldName);
776: lOutputField.setOperation(lOperation);
777: } else {
778: lUnprocessedOutputFields.remove(lOutputField);
779: }
780: lOutputField
781: .setDescription(suggestReferenceDetailsOutputParameterDescription(
782: pReferencingEntityName,
783: pReferencePluralName));
784: lOutputField.setArray(true);
785: lOutputField.setDataType(null);
786:
787: Structure lEntityDetailsStructure = null;
788: Servicemodule lServicemodule = pDataManagementService
789: .getServicemodule();
790: if (lServicemodule != null) {
791: Entity lReferencedEntity = pReference.getEntity();
792: if (lReferencedEntity != null) {
793: String lReferencedEntityName = lReferencedEntity
794: .getName();
795: if (lReferencedEntityName != null)
796: lEntityDetailsStructure = lServicemodule
797: .findStructure(StylesheetImpl
798: .getEntityDetailsStructureName(lReferencedEntityName));
799: }
800: }
801: lOutputField.setStructureType(lEntityDetailsStructure);
802: }
803:
804: // Delete all output fields left
805: for (Iterator lUnprocessedOutputFieldsIterator = lUnprocessedOutputFields
806: .iterator(); lUnprocessedOutputFieldsIterator
807: .hasNext();) {
808: OperationOutputField lOutputField = (OperationOutputField) lUnprocessedOutputFieldsIterator
809: .next();
810: if (!lOutputField.isDerived())
811: lOutputField.refDelete();
812: }
813: }
814: // Output Messages
815: {
816: Collection lOperationOutputMessages = lOperation
817: .getOutputMessages();
818: List lUnprocessedOutputMessages = new ArrayList();
819: lUnprocessedOutputMessages.addAll(lOperationOutputMessages);
820:
821: // Output Messages - only verify that the ones that we need exist. The extra ones are allowed
822: {
823: // This method loads instances of the referencing entity and referenced entities
824: // all of them have a chance not to be found. We need to add relevant output mesages in the output specification
825: Set lEntitiesWhichMayBeNotFoundWhenInvokingOperation = new HashSet();
826: lEntitiesWhichMayBeNotFoundWhenInvokingOperation
827: .add(lReferencingEntity);
828: Util
829: .collectEntitiesWhichMayBeNotFoundWhenLoadingInstance(
830: lReferencingEntity,
831: lEntitiesWhichMayBeNotFoundWhenInvokingOperation);
832:
833: for (Iterator lEntitiesWhichMayBeNotFoundWhenInvokingOperationIterator = lEntitiesWhichMayBeNotFoundWhenInvokingOperation
834: .iterator(); lEntitiesWhichMayBeNotFoundWhenInvokingOperationIterator
835: .hasNext();) {
836: Entity lEntityElement = (Entity) lEntitiesWhichMayBeNotFoundWhenInvokingOperationIterator
837: .next();
838: // We need to use entity name parameter for the entity which is passed as a parameter.
839: String lEntityElementName = lEntityElement
840: .equals(lReferencingEntity) ? pReferencingEntityName
841: : lEntityElement.getName();
842: if (lEntityElementName == null)
843: continue;
844: String lOperationOutputMessageName = StylesheetImpl
845: .getEntityNotFoundOperationOutputMessageName(lEntityElementName);
846: OperationOutputMessage lOutputMessage = lOperation
847: .findOutputMessage(lOperationOutputMessageName);
848: if (lOutputMessage == null) {
849: lOutputMessage = mModelAssistantImpl.mOperationOutputMessageClass
850: .createOperationOutputMessage();
851: lOutputMessage
852: .setName(lOperationOutputMessageName);
853: lOutputMessage.setOperation(lOperation);
854: } else {
855: lUnprocessedOutputMessages
856: .remove(lOutputMessage);
857: }
858: lOutputMessage
859: .setDescription(StylesheetImpl
860: .getEntityNotFoundOperationOutputMessageDescription(lEntityElementName));
861: lOutputMessage.setArray(false);
862: Message lEntityNotFoundMessage = pDataManagementService
863: .getServicemodule() != null ? pDataManagementService
864: .getServicemodule()
865: .findMessage(
866: StylesheetImpl
867: .getEntityInstanceNotFoundMessageName(lEntityElementName))
868: : null;
869: lOutputMessage
870: .setMessageType(lEntityNotFoundMessage);
871: }
872: }
873: // Delete all output messages left
874: for (Iterator lUnprocessedOutputMessagesIterator = lUnprocessedOutputMessages
875: .iterator(); lUnprocessedOutputMessagesIterator
876: .hasNext();) {
877: OperationOutputMessage lOutputMessage = (OperationOutputMessage) lUnprocessedOutputMessagesIterator
878: .next();
879: if (!lOutputMessage.isDerived())
880: lOutputMessage.refDelete();
881: }
882: }
883: }
884:
885: // This helper makes sure that the version id attribute is absent in the details structure
886: void ensureAbsent(Service pDataManagementService,
887: String pEntityName, String pReferencePluralName) {
888: // Work on the details structure
889: Operation lOperation = pDataManagementService
890: .findOperation(suggestOperationName(pEntityName,
891: pReferencePluralName));
892: if (lOperation != null)
893: lOperation.refDelete();
894: }
895:
896: // Helper. Returns the message name
897: private static String suggestOperationName(String pEntityName,
898: String pReferencePluralName) {
899: // Use normalised name here
900: return "getAll"
901: + StringUtils.suggestName(pReferencePluralName, true,
902: false) + "For"
903: + StringUtils.suggestName(pEntityName, true, false);
904: }
905:
906: // Helper. Returns the message description
907: private static String suggestOperationDescription(
908: String pEntityName, String pReferencePluralName) {
909: // Use name 'as is' here
910: return "Returns all " + pReferencePluralName
911: + " associated with the specified " + pEntityName
912: + " instance.";
913: }
914:
915: // Helper. Returns the description
916: private static String suggestEntityKeyInputParameterDescription(
917: String pEntityName) {
918: // Use name 'as is' here
919: return "The unique key identifying the " + pEntityName
920: + " to be queried.";
921: }
922:
923: // Helper. Returns the name
924: private static String suggestReferenceDetailsOutputParameterName(
925: String pReferencePluralName) {
926: return StringUtils.suggestName(pReferencePluralName, true,
927: false);
928: }
929:
930: // Helper. Returns the description
931: private static String suggestReferenceDetailsOutputParameterDescription(
932: String pEntityName, String pReferencePluralName) {
933: // Use name 'as is' here
934: return "Details of all " + pReferencePluralName
935: + " associated with the given " + pEntityName;
936: }
937: }
|