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.impl.metabossmodel.enterprisemodel.systemimplementationmodel;
016:
017: import java.util.ArrayList;
018: import java.util.Collection;
019: import java.util.Collections;
020: import java.util.HashSet;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Set;
025: import java.util.TreeMap;
026:
027: import org.netbeans.mdr.storagemodel.StorableObject;
028:
029: import com.metaboss.sdlctools.models.impl.metabossmodel.ModelElementImpl;
030: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.AssociationRole;
031: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Domain;
032: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Entity;
033: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Report;
034:
035: public abstract class DomainImpl extends ModelElementImpl implements
036: Domain {
037: // Required constructor
038: protected DomainImpl(StorableObject storable) {
039: super (storable);
040: }
041:
042: /**
043: * @param pEntityName
044: * @return requested Entity or throws exception if none found
045: */
046: public Entity getEntity(String pEntityName) {
047: Entity lFoundEntity = findEntity(pEntityName);
048: // Throw exception if nothing found
049: if (lFoundEntity == null)
050: throw new IllegalArgumentException(
051: "Unable to locate Entity named '" + pEntityName
052: + "' in Domain. DomainRef: " + getRef());
053: return lFoundEntity;
054: }
055:
056: /**
057: * @param pEntityName
058: * @return requested Entity or null if none found
059: */
060: public Entity findEntity(String pEntityName) {
061: Collection lEntities = getEntities();
062: if (!lEntities.isEmpty()) {
063: for (Iterator lEntitiesIterator = lEntities.iterator(); lEntitiesIterator
064: .hasNext();) {
065: Entity lEntity = (Entity) lEntitiesIterator.next();
066: if (lEntity.getName().equals(pEntityName))
067: return lEntity;
068: }
069: }
070: return null;
071: }
072:
073: /** Returns list of all entities in order of population dependency.
074: * From the population point of view, one entity absolutely
075: * depends on the other when it has mandatory reference (one and only one) to the other entity.
076: * Somewhat weaker dependency is when entity has a nonmandatory reference. Preferrably
077: * entities are orders in a way where earlier entity does not depend on the latter ones at all,
078: * however since entities may have circular non mandatory references some times this will not be true */
079: public List getEntitiesInPopulationOrder() {
080: TreeMap lAllEntitiesMap = new TreeMap();
081: for (Iterator lEntitiesIter = getEntities().iterator(); lEntitiesIter
082: .hasNext();) {
083: Entity lEntity = (Entity) lEntitiesIter.next();
084: lAllEntitiesMap.put(lEntity.getName(), lEntity);
085: }
086: List lEntitiesOrderOfDependency = new ArrayList();
087:
088: while (lAllEntitiesMap.size() > 0) {
089: Entity lPerfectCandidate = null;
090: Entity lImperfectCandidate = null;
091: int lImperfectCandidateUncopiedReferencesCount = Integer.MAX_VALUE;
092:
093: // Iterate through the list of remaining entities trying to find perfect candidate
094: // but also keeing an eye on the possible unperfect one. The entity with lesser number uncopied references wins.
095: for (Iterator lEntitiesIter = lAllEntitiesMap.entrySet()
096: .iterator(); lEntitiesIter.hasNext();) {
097: Map.Entry lEntityEntry = (Map.Entry) lEntitiesIter
098: .next();
099: Entity lEntity = (Entity) lEntityEntry.getValue();
100: // First ensure that the supertype of this entity have been moved already or it does not have one
101: Entity lSupertypeEntity = lEntity.getSupertype();
102: if (lAllEntitiesMap.containsValue(lSupertypeEntity))
103: continue; // Supertype entity is still not moved
104: // Work on references. Note that we only need to work on our references, not at the supertypes
105: // as all of the supertype references are automatically checked by checking the supertype first
106: Collection lReferences = lEntity.getReferences();
107: if (!lReferences.isEmpty()) {
108: // Check for uncopied mandatory references
109: // Calculate the number of copied and uncopied references
110: int lUncopiedReferencesCount = 0;
111: boolean lFoundMandatoryReference = false;
112: for (Iterator lReferencesIterator = lReferences
113: .iterator(); lReferencesIterator.hasNext();) {
114: AssociationRole lReference = (AssociationRole) lReferencesIterator
115: .next();
116: boolean lStillNotCopied = lAllEntitiesMap
117: .containsValue(lReference.getEntity());
118: if (lStillNotCopied) {
119: lFoundMandatoryReference = lReference
120: .isSingular()
121: && lReference.isMandatory();
122: if (lFoundMandatoryReference == true)
123: break; // All bets are off - found singular mandatory uncopied
124: lUncopiedReferencesCount++;
125: }
126: }
127: if (lFoundMandatoryReference == true)
128: continue; // We have found singular mandatory reference which is not moved yet - we can not move this entity in any case
129: // This entity does not have absolutely must have reference, but it does have some others.
130: if (lUncopiedReferencesCount > 0) {
131: // See if this is less unperfect
132: if (lImperfectCandidateUncopiedReferencesCount > lUncopiedReferencesCount) {
133: lImperfectCandidateUncopiedReferencesCount = lUncopiedReferencesCount;
134: lImperfectCandidate = lEntity;
135: }
136: continue; // There is an uncopied reference
137: }
138: }
139: // If we have reached this point - it means that the entity can be copied
140: lPerfectCandidate = lEntity;
141: break;
142: }
143: // By now we should have found either perfect or imperfect candidate.
144: if (lPerfectCandidate != null) {
145: lEntitiesOrderOfDependency.add(lPerfectCandidate);
146: lAllEntitiesMap.remove(lPerfectCandidate.getName());
147: } else if (lImperfectCandidate != null) {
148: lEntitiesOrderOfDependency.add(lImperfectCandidate);
149: lAllEntitiesMap.remove(lImperfectCandidate.getName());
150: } else {
151: // Build the exception message
152: StringBuffer lExceptionTextStringBuffer = new StringBuffer(
153: "Unable to achieve progress with ordering of entities. It appears that the domain is not implementable. ");
154: lExceptionTextStringBuffer.append("DomainRef: ");
155: lExceptionTextStringBuffer.append(getRef());
156: lExceptionTextStringBuffer
157: .append(" Conflicting Entities: ");
158: for (Iterator lConflictingEntitiesNamesIterator = lAllEntitiesMap
159: .keySet().iterator(); lConflictingEntitiesNamesIterator
160: .hasNext();) {
161: lExceptionTextStringBuffer.append("'");
162: lExceptionTextStringBuffer
163: .append(lConflictingEntitiesNamesIterator
164: .next());
165: lExceptionTextStringBuffer.append("'");
166: if (lConflictingEntitiesNamesIterator.hasNext())
167: lExceptionTextStringBuffer.append(", ");
168: }
169: throw new RuntimeException(lExceptionTextStringBuffer
170: .toString());
171: }
172: }
173: return Collections.unmodifiableList(lEntitiesOrderOfDependency);
174: }
175:
176: // Returns list of DataTypes, Structures and Messages used in the Domain. This includes owned and referenced elements
177: public Collection getCombinedTypes() {
178: Set lCombinedTypes = new HashSet();
179: // Interrogate the entities
180: for (Iterator lEntitiesIterator = getEntities().iterator(); lEntitiesIterator
181: .hasNext();) {
182: Entity lEntity = (Entity) lEntitiesIterator.next();
183: lCombinedTypes.addAll(lEntity.getCombinedTypes());
184: }
185: // Interrogate the reports
186: for (Iterator lReportsIterator = getReports().iterator(); lReportsIterator
187: .hasNext();) {
188: Report lReport = (Report) lReportsIterator.next();
189: lCombinedTypes.addAll(lReport.getCombinedTypes());
190: }
191: return java.util.Collections
192: .unmodifiableCollection(lCombinedTypes);
193: }
194: }
|