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.metabossmodel.datadictionarymodel.DataType;
027: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.Namespace;
028: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.Property;
029: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.TypeTemplate;
030: import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Entity;
031:
032: /** This class holds details about Entity InstanceId DataType
033: * being processed. Used internally in the Assistant impl */
034: class EntityInstanceIdDataTypeHelper {
035: // Utility comparator, which is used to sort properties in order of deletion
036: // The problem is that when parent property is deleted - the child property is deleted too, so
037: // when we iterate through unused properties and issue refDelete() - we may hit already deleted property.
038: // This comparator sorts the properties in the reverse string sort order of the keys,
039: // which ensures that properties are sorted in the right order for deletion (child properties before parent ones)
040: private static Comparator sPropertiesToDeleteComparator = new Comparator() {
041: public int compare(Object o1, Object o2) {
042: return ((Property) o2).getKey().compareTo(
043: ((Property) o1).getKey());
044: }
045: };
046:
047: private ModelAssistantImpl mModelAssistantImpl;
048: private Set mUnusedProperties = new TreeSet(
049: sPropertiesToDeleteComparator);
050: private DataType mEntityInstanceIdDataType = null;
051: private TypeTemplate mEntityInstanceIdFieldTypeTemplate = null;
052:
053: // This helper is looking at the conditions and ensuring the inegrity of the data type
054: // it will create the missing data type and delete exta one if necessary
055: static void verifyEntityInstanceIdDataTypeIntegrity(
056: Collection pViolations,
057: ModelAssistantImpl pModelAssistantImpl, Entity pEntity,
058: List pUnprocessedDataTypes, HelperContext pHelperContext) {
059: Namespace lDomainNamespace = pHelperContext
060: .getDomainNamespace();
061: if (lDomainNamespace == null)
062: return;
063: TypeTemplate lDesiredTypeTemplate = pHelperContext
064: .getEntityInstanceIdFieldTypeTemplate();
065: if (lDesiredTypeTemplate == null)
066: return;
067: // Each entity must have instance id data type, so integrity issue is simple - instance id is always there
068: String lExpectedDataTypeName = StylesheetImpl
069: .getEntityInstanceIdDataTypeName(pEntity.getName());
070: DataType lInstanceIdDataTypeInNamespace = lDomainNamespace
071: .findDataType(lExpectedDataTypeName);
072: if (lInstanceIdDataTypeInNamespace != null) {
073: // Remove this data type from the list of unprocessed ones
074: if (pUnprocessedDataTypes != null)
075: pUnprocessedDataTypes
076: .remove(lInstanceIdDataTypeInNamespace);
077: // Verify that this data type is what the entity is pointing to
078: DataType lInstanceIdDataTypeInEntity = pEntity
079: .getInstanceIdDataType();
080: if (lInstanceIdDataTypeInEntity == null
081: || lInstanceIdDataTypeInEntity
082: .equals(lInstanceIdDataTypeInNamespace) == false)
083: pViolations
084: .add(new ConstraintViolationException(
085: pEntity,
086: pEntity.refMetaObject(),
087: "Entity must always be associated with the dedicated Entity Instance Id data type residing in System namespace."));
088:
089: // Verify that this data type is based on prescribed template
090: TypeTemplate lActualTypeTemplate = lInstanceIdDataTypeInNamespace
091: .getTypetemplate();
092: if (lActualTypeTemplate == null
093: || lActualTypeTemplate.equals(lDesiredTypeTemplate) == false)
094: pViolations
095: .add(new ConstraintViolationException(
096: lInstanceIdDataTypeInNamespace,
097: lInstanceIdDataTypeInNamespace
098: .refMetaObject(),
099: "The Entity Instance Id data type must be based on a "
100: + lDesiredTypeTemplate
101: .getName()
102: + " typetemplate. The '"
103: + lInstanceIdDataTypeInNamespace
104: .getName()
105: + "' data type is not based on this template."));
106: } else
107: pViolations
108: .add(new ConstraintViolationException(
109: lDomainNamespace,
110: lDomainNamespace.refMetaObject(),
111: "System namespace for Domain must contain an Entity Instance Id data type for every entity in the domain. Entity '"
112: + pEntity.getName()
113: + "' does not have corresponding '"
114: + lExpectedDataTypeName
115: + "' data type."));
116: }
117:
118: // This helper is looking at the conditions and ensuring the inegrity of the data type
119: // it will create the missing data type and delete exta one if necessary
120: static void ensureEntityInstanceIdDataTypeIntegrity(
121: ModelAssistantImpl pModelAssistantImpl, Entity pEntity,
122: List pUnprocessedDataTypes, HelperContext pHelperContext) {
123: // Each entity must have one, so integrity issue is simple - instance id is always there
124: ensureEntityInstanceIdDataTypeExists(pModelAssistantImpl,
125: pEntity, pUnprocessedDataTypes, pHelperContext);
126: // Now work on all properties
127: EntityInstanceIdDataTypeHelper lDataTypeHelper = new EntityInstanceIdDataTypeHelper(
128: pModelAssistantImpl, pEntity.getInstanceIdDataType());
129: // Work on properties
130: lDataTypeHelper.markPropertiesAsUnused();
131: // Delete all still unused properties
132: lDataTypeHelper.deleteUnusedProperties();
133: }
134:
135: // This helper is looking after creation of absent entity state data type
136: // It returns the newly created or found Data Type or null if it can not be created
137: // The namespaces are optional parameters - if they are null - they will be discovered inside this method
138: // and if they are unobtainable - this method will fail to work and return null. This is provided to save some time
139: // during batch operations
140: static DataType ensureEntityInstanceIdDataTypeExists(
141: ModelAssistantImpl pModelAssistantImpl, Entity pEntity,
142: List pUnprocessedDataTypes, HelperContext pHelperContext) {
143: Namespace lDomainNamespace = pHelperContext
144: .getDomainNamespace();
145: if (lDomainNamespace == null)
146: return null;
147: String lEntityInstanceIdDataTypeName = StylesheetImpl
148: .getEntityInstanceIdDataTypeName(pEntity.getName());
149: DataType lEntityInstanceIdDataType = lDomainNamespace
150: .findDataType(lEntityInstanceIdDataTypeName);
151: TypeTemplate lEntityInstanceIdDataTypeTypeTemplate = pHelperContext
152: .getEntityInstanceIdFieldTypeTemplate();
153: if (lEntityInstanceIdDataTypeTypeTemplate == null)
154: return null;
155: if (lEntityInstanceIdDataType == null) {
156: lEntityInstanceIdDataType = pModelAssistantImpl.mDataTypeClass
157: .createDataType();
158: lEntityInstanceIdDataType
159: .setName(lEntityInstanceIdDataTypeName);
160: lDomainNamespace.getDataTypes().add(
161: lEntityInstanceIdDataType);
162: } else {
163: if (pUnprocessedDataTypes != null)
164: pUnprocessedDataTypes.remove(lEntityInstanceIdDataType);
165: }
166: // Because the data type is located by name - it is possible that in fact it does not have
167: // features set up as we would like them to be. We need just to override them
168: lEntityInstanceIdDataType.setDescription(StylesheetImpl
169: .getEntityInstanceIdDataTypeDescription(pEntity
170: .getName()));
171: lEntityInstanceIdDataType
172: .setTypetemplate(lEntityInstanceIdDataTypeTypeTemplate);
173: pEntity.setInstanceIdDataType(lEntityInstanceIdDataType);
174: // Here we would need to work on mandatory properties, but this type has none
175: return lEntityInstanceIdDataType;
176: }
177:
178: // This helper is looking after creation of absent data type
179: // The namespace is optional parameters - if it is null it will be discovered inside this method
180: // and if it is unobtainable - this method will fail to work and return false. This is provided to save some time
181: // during batch operations
182: static boolean ensureEntityInstanceIdDataTypeAbsent(Entity pEntity,
183: List pUnprocessedDataTypes, HelperContext pHelperContext) {
184: Namespace lDomainNamespace = pHelperContext
185: .getDomainNamespace();
186: if (lDomainNamespace == null)
187: return false;
188: String lEntityInstanceIdDataTypeName = StylesheetImpl
189: .getEntityInstanceIdDataTypeName(pEntity.getName());
190: DataType lEntityInstanceIdDataType = lDomainNamespace
191: .findDataType(lEntityInstanceIdDataTypeName);
192: if (lEntityInstanceIdDataType != null) {
193: if (pUnprocessedDataTypes != null)
194: pUnprocessedDataTypes.remove(lEntityInstanceIdDataType);
195: lEntityInstanceIdDataType.refDelete();
196: }
197: // Just in case - set the datatype to null
198: pEntity.setInstanceIdDataType(null);
199: return true; // Done
200: }
201:
202: public EntityInstanceIdDataTypeHelper(
203: ModelAssistantImpl pModelAssistantImpl,
204: DataType pEntityInstanceIdDataType) {
205: mModelAssistantImpl = pModelAssistantImpl;
206: mEntityInstanceIdDataType = pEntityInstanceIdDataType;
207: mEntityInstanceIdFieldTypeTemplate = mEntityInstanceIdDataType
208: .getTypetemplate();
209: }
210:
211: // Marks all optional properties as unused.
212: // Every subsequent property action will remove from this list a property, which is not unused one
213: void markPropertiesAsUnused() {
214: // Put all properties to unused apart from mandatory ones
215: for (Iterator lPropertiesIterator = mEntityInstanceIdDataType
216: .getCombinedTypetemplateProperties().iterator(); lPropertiesIterator
217: .hasNext();) {
218: Property lProperty = (Property) lPropertiesIterator.next();
219: // Here we could filter out mandatory properties, so they never ever get into the unused
220: // set. This would ensure that they never deleted. This data type has not got
221: // any mandatory properties - so all properties will go into the unused set
222: mUnusedProperties.add(lProperty);
223: }
224: }
225:
226: // Deletes all properties in unused set at the moment. Normally
227: // we start with marking all properties as unused, than going though all property manipulations
228: // and than calling this method to delete all whjat is left
229: void deleteUnusedProperties() {
230: for (Iterator lUnprocessedPropertiesIterator = mUnusedProperties
231: .iterator(); lUnprocessedPropertiesIterator.hasNext();) {
232: Property lProperty = (Property) lUnprocessedPropertiesIterator
233: .next();
234: lProperty.refDelete();
235: }
236: }
237: }
|