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;
016:
017: import java.io.PrintWriter;
018: import java.io.StringWriter;
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import javax.jmi.reflect.ConstraintViolationException;
025: import javax.jmi.reflect.RefObject;
026: import javax.naming.Context;
027: import javax.naming.InitialContext;
028: import javax.naming.NamingException;
029:
030: import org.omg.uml.foundation.core.Comment;
031: import org.omg.uml.foundation.core.Namespace;
032:
033: import com.metaboss.sdlctools.models.ModelRepository;
034: import com.metaboss.sdlctools.models.ModelRepositoryException;
035: import com.metaboss.sdlctools.models.ModelRepositoryInternalException;
036: import com.metaboss.sdlctools.models.ModelRepositoryNotFoundException;
037: import com.metaboss.sdlctools.models.ModelValidationException;
038: import com.metaboss.sdlctools.models.metabossmodel.ModelElement;
039: import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.DataType;
040: import com.metaboss.sdlctools.models.metabossmodel.statemachinemodel.State;
041: import com.metaboss.sdlctools.models.metabossmodel.statemachinemodel.StateMachine;
042:
043: /** This is a utility class which contains generic UML utility methods */
044: public final class UMLUtils {
045: private static ModelRepository sModelRepository = null;
046: private static Object sModelRepositoryCreationSemaphore = new Object();
047:
048: // Hide default constructor - this is just a toolbox, which can not be created
049: private UMLUtils() {
050: }
051:
052: /** Creates UML Comment out of ModelElement description and attaches it to the target model element*/
053: public static void copyComment(
054: com.metaboss.sdlctools.models.metabossmodel.ModelElement pSourceModelElement,
055: org.omg.uml.foundation.core.ModelElement pTargetModelElement) {
056: String lDescription = pSourceModelElement.getDescription();
057: if (lDescription != null && lDescription.length() > 0)
058: copyComment(lDescription, pTargetModelElement);
059: }
060:
061: /** Creates UML Comment out of ModelElement description and attaches it to the target model element*/
062: public static void copyComment(String pCommentText,
063: org.omg.uml.foundation.core.ModelElement pTargetModelElement) {
064: if (pCommentText != null && pCommentText.length() > 0) {
065: Comment lComment = ((org.omg.uml.UmlPackage) pTargetModelElement
066: .refOutermostPackage()).getCore().getComment()
067: .createComment();
068: lComment.setBody(pCommentText);
069: lComment
070: .setVisibility(org.omg.uml.foundation.datatypes.VisibilityKindEnum.VK_PUBLIC);
071: // Find closest namespace where to put this comment.
072: // Find it by moving up the containment chain and try to find the namespace this way
073: Namespace lCommentNamespace = null;
074: for (RefObject lProspectiveNamespace = pTargetModelElement; lCommentNamespace == null
075: && lProspectiveNamespace != null; lProspectiveNamespace = (RefObject) lProspectiveNamespace
076: .refImmediateComposite()) {
077: if (lProspectiveNamespace instanceof Namespace)
078: lCommentNamespace = (Namespace) lProspectiveNamespace;
079: }
080: // As the last resort we will put the comment in the target component's namespace
081: if (lCommentNamespace == null)
082: lCommentNamespace = pTargetModelElement.getNamespace();
083: // Set the namespace if we have found one
084: if (lCommentNamespace != null)
085: lComment.setNamespace(lCommentNamespace);
086: pTargetModelElement.getComment().add(lComment);
087: }
088: }
089:
090: /** Creates UML Comment out of ModelElement description and attaches it to the target model element*/
091: public static void copyComment(
092: org.omg.uml.foundation.core.ModelElement pSourceModelElement,
093: com.metaboss.sdlctools.models.metabossmodel.ModelElement pTargetModelElement) {
094: Collection lComments = pSourceModelElement.getComment();
095: if (!lComments.isEmpty()) {
096: StringWriter lStringWriter = new StringWriter();
097: PrintWriter lPrintWriter = new PrintWriter(lStringWriter);
098: // Ensure that commentas are separated by linebreaks, but do not put the
099: // linebreak in if there is only one comment.
100: boolean lNeedLineBreak = false;
101: for (Iterator lCommentsIterator = lComments.iterator(); lCommentsIterator
102: .hasNext();) {
103: if (lNeedLineBreak)
104: lPrintWriter.println();
105: else
106: lNeedLineBreak = true;
107: Comment lComment = (Comment) lCommentsIterator.next();
108: lPrintWriter.print(lComment.getBody());
109: }
110: lPrintWriter.flush();
111: pTargetModelElement
112: .setDescription(lStringWriter.toString());
113: }
114: }
115:
116: // Helper. Returns UML package at the XPath, which is corresponding to the given model element
117: public static org.omg.uml.modelmanagement.UmlPackage getUmlPackage(
118: String pUMLModelName, ModelElement pModelElement,
119: String pXPath) throws ModelRepositoryException {
120: org.omg.uml.modelmanagement.UmlPackage lFoundElement = findUmlPackage(
121: pUMLModelName, pModelElement, pXPath);
122: if (lFoundElement == null)
123: throw new ModelRepositoryInternalException(
124: "Unexpected program condition. UML Package matching given MetaBoss Model Element not found. MetaBoss Model Element Ref: "
125: + pModelElement.getRef()
126: + ". UMLModel XPath: " + pXPath);
127: return lFoundElement;
128: }
129:
130: // Helper. Returns UML package at the XPath, which is corresponding to the given model element or null if none found
131: public static org.omg.uml.modelmanagement.UmlPackage findUmlPackage(
132: String pUMLModelName, ModelElement pModelElement,
133: String pXPath) throws ModelRepositoryException {
134: List lFoundPackages = getModelRepository().searchByXPath(
135: pUMLModelName, pXPath);
136: if (lFoundPackages.isEmpty())
137: return null;
138: if (lFoundPackages.size() != 1)
139: throw new ModelRepositoryInternalException(
140: "Unexpected program condition. More than one package matched given Model Element. MetaBoss Model Element Ref: "
141: + pModelElement.getRef()
142: + ". UMLModel XPath: " + pXPath);
143: return (org.omg.uml.modelmanagement.UmlPackage) lFoundPackages
144: .get(0);
145: }
146:
147: // Helper. Returns UML DataType corresponding to the given DataType or throws exception if none found
148: public static org.omg.uml.foundation.core.DataType getUmlDataType(
149: String pUMLModelName, DataType pDataType)
150: throws ModelRepositoryException {
151: org.omg.uml.foundation.core.DataType lFoundElement = findUmlDataType(
152: pUMLModelName, pDataType);
153: if (lFoundElement == null)
154: throw new ModelRepositoryInternalException(
155: "Unexpected program condition. UML DataType matching given MetaBoss DataType not found. MetaBoss DataType Ref: "
156: + pDataType.getRef()
157: + ". UMLModel XPath: "
158: + UMLStylesheet.getDataTypeXPath(pDataType));
159: return lFoundElement;
160: }
161:
162: // Helper. Returns UML DataType corresponding to the given DataType or returns null if none found
163: public static org.omg.uml.foundation.core.DataType findUmlDataType(
164: String pUMLModelName, DataType pDataType)
165: throws ModelRepositoryException {
166:
167: String lXPath = UMLStylesheet.getDataTypeXPath(pDataType);
168: List lFoundElements = getModelRepository().searchByXPath(
169: pUMLModelName, lXPath);
170: if (lFoundElements.isEmpty())
171: return null;
172: if (lFoundElements.size() != 1)
173: throw new ModelRepositoryInternalException(
174: "Unexpected program condition. More than one UML DataType matched given Model DataType. MetaBoss DataTypeRef: "
175: + pDataType.getRef()
176: + ". UMLModel XPath: "
177: + lXPath);
178: return (org.omg.uml.foundation.core.DataType) lFoundElements
179: .get(0);
180: }
181:
182: // Helper. Returns UML StateMachine corresponding to the given StateMachine or throws exception if none found
183: public static org.omg.uml.behavioralelements.statemachines.StateMachine getUmlStateMachine(
184: String pUMLModelName, StateMachine pStateMachine)
185: throws ModelRepositoryException {
186: org.omg.uml.behavioralelements.statemachines.StateMachine lFoundElement = findUmlStateMachine(
187: pUMLModelName, pStateMachine);
188: if (lFoundElement == null)
189: throw new ModelRepositoryInternalException(
190: "Unexpected program condition. UML StateMachine matching given MetaBoss StateMachine is not found. MetaBoss StateMachine Ref: "
191: + pStateMachine.getRef()
192: + ". UMLModel XPath: "
193: + UMLStylesheet
194: .getStateMachineXPath(pStateMachine));
195: return lFoundElement;
196: }
197:
198: // Helper. Returns UML StateMachine corresponding to the given StateMachine or returns null if none found
199: public static org.omg.uml.behavioralelements.statemachines.StateMachine findUmlStateMachine(
200: String pUMLModelName, StateMachine pStateMachine)
201: throws ModelRepositoryException {
202:
203: String lXPath = UMLStylesheet
204: .getStateMachineXPath(pStateMachine);
205: List lFoundElements = getModelRepository().searchByXPath(
206: pUMLModelName, lXPath);
207: if (lFoundElements.isEmpty())
208: return null;
209: if (lFoundElements.size() != 1)
210: throw new ModelRepositoryInternalException(
211: "Unexpected program condition. More than one UML StateMachine matched given MetaBoss StateMachine. MetaBoss StateMachine Ref: "
212: + pStateMachine.getRef()
213: + ". UMLModel XPath: " + lXPath);
214: return (org.omg.uml.behavioralelements.statemachines.StateMachine) lFoundElements
215: .get(0);
216: }
217:
218: // Helper. Returns UML State corresponding to the given State or throws exception if none found
219: public static org.omg.uml.behavioralelements.statemachines.StateVertex getUmlState(
220: String pUMLModelName, State pState)
221: throws ModelRepositoryException {
222: org.omg.uml.behavioralelements.statemachines.StateVertex lFoundElement = findUmlState(
223: pUMLModelName, pState);
224: if (lFoundElement == null)
225: throw new ModelRepositoryInternalException(
226: "Unexpected program condition. UML State matching given MetaBoss State is not found. MetaBoss State Ref: "
227: + pState.getRef()
228: + ". UMLModel XPath: "
229: + UMLStylesheet.getStateXPath(pState));
230: return lFoundElement;
231: }
232:
233: // Helper. Returns UML State corresponding to the given State or returns null if none found
234: public static org.omg.uml.behavioralelements.statemachines.StateVertex findUmlState(
235: String pUMLModelName, State pState)
236: throws ModelRepositoryException {
237:
238: String lXPath = UMLStylesheet.getStateXPath(pState);
239: List lFoundElements = getModelRepository().searchByXPath(
240: pUMLModelName, lXPath);
241: if (lFoundElements.isEmpty())
242: return null;
243: if (lFoundElements.size() != 1)
244: throw new ModelRepositoryInternalException(
245: "Unexpected program condition. More than one UML State matched given MetaBoss State. MetaBoss State Ref: "
246: + pState.getRef()
247: + ". UMLModel XPath: "
248: + lXPath);
249: return (org.omg.uml.behavioralelements.statemachines.StateVertex) lFoundElements
250: .get(0);
251: }
252:
253: // Helper. Returns UML Class corresponding to the given Model Element or throws exception if none found
254: public static org.omg.uml.foundation.core.UmlClass getUmlClass(
255: String pUMLModelName, ModelElement pModelElement,
256: String pXPath) throws ModelRepositoryException {
257: org.omg.uml.foundation.core.UmlClass lFoundElement = findUmlClass(
258: pUMLModelName, pModelElement, pXPath);
259: if (lFoundElement == null)
260: throw new ModelRepositoryInternalException(
261: "Unexpected program condition. UML Class matching given Model Element not found. MetaBoss Model Element Ref: "
262: + pModelElement.getRef()
263: + ". UMLModel XPath: " + pXPath);
264: return lFoundElement;
265: }
266:
267: // Helper. Returns UML Class corresponding to the given Model Element or null if none found
268: public static org.omg.uml.foundation.core.UmlClass findUmlClass(
269: String pUMLModelName, ModelElement pModelElement,
270: String pXPath) throws ModelRepositoryException {
271:
272: List lFoundElements = getModelRepository().searchByXPath(
273: pUMLModelName, pXPath);
274: if (lFoundElements.isEmpty())
275: return null;
276: if (lFoundElements.size() != 1)
277: throw new ModelRepositoryInternalException(
278: "Unexpected program condition. More than one UML Class matched given Model Element. MetaBoss Model Element Ref: "
279: + pModelElement.getRef()
280: + ". UMLModel XPath: " + pXPath);
281: return (org.omg.uml.foundation.core.UmlClass) lFoundElements
282: .get(0);
283: }
284:
285: // Helper. Returns UML Class corresponding to the given Model Element or null if none found
286: public static org.omg.uml.foundation.core.Binding findUmlBinding(
287: org.omg.uml.foundation.core.ModelElement pModelElement,
288: String pXPath) throws ModelRepositoryException {
289:
290: List lFoundElements = getModelRepository().searchByXPath(
291: pModelElement, pXPath);
292: if (lFoundElements.isEmpty())
293: return null;
294: if (lFoundElements.size() != 1)
295: throw new ModelRepositoryInternalException(
296: "Unexpected program condition. More than one UML Binding matched given XPath: "
297: + pXPath);
298: return (org.omg.uml.foundation.core.Binding) lFoundElements
299: .get(0);
300: }
301:
302: // Helper. Returns UML Class corresponding to the given Model Element or null if none found
303: public static String getSingleOptionalTagValue(
304: org.omg.uml.foundation.core.ModelElement pModelElement,
305: String pTagName) throws ModelRepositoryException {
306: try {
307: List lFoundElements = getModelRepository().searchByXPath(
308: pModelElement,
309: UMLStylesheet
310: .getModelElementTagValueXPath(pTagName));
311: if (lFoundElements.size() == 1) {
312: Collection lValues = (Collection) lFoundElements.get(0);
313: if (lValues != null && lValues.isEmpty() == false) {
314: if (lValues.size() > 1)
315: throw new ConstraintViolationException(
316: pModelElement, null,
317: "There can only be at most one value for the '"
318: + pTagName + "' tag.");
319: return (String) lValues.iterator().next();
320: }
321: } else if (!lFoundElements.isEmpty())
322: throw new ConstraintViolationException(pModelElement,
323: null, "There can only be at most one '"
324: + pTagName
325: + "' attached to the model element.");
326: return null;
327: } catch (ConstraintViolationException e) {
328: throw new ModelValidationException(
329: "Error encountered while extracting a value of the '"
330: + pTagName + "' tag", e);
331: }
332: }
333:
334: // Helper. Returns array of string values of the particular tag
335: public static String[] getMultipleOptionalTagValue(
336: org.omg.uml.foundation.core.ModelElement pModelElement,
337: String pTagName) throws ModelRepositoryException {
338: List lFoundValues = new ArrayList();
339: List lFoundElements = getModelRepository().searchByXPath(
340: pModelElement,
341: UMLStylesheet.getModelElementTagValueXPath(pTagName));
342: for (Iterator lElementsIterator = lFoundElements.iterator(); lElementsIterator
343: .hasNext();) {
344: Collection lValues = (Collection) lElementsIterator.next();
345: lFoundValues.addAll(lValues);
346: }
347: return (String[]) lFoundValues.toArray(new String[lFoundValues
348: .size()]);
349: }
350:
351: // Helper. Attaches instance of the single value tag to the specified element
352: public static void attachSingleTagToElement(
353: org.omg.uml.foundation.core.ModelElement pModelElement,
354: org.omg.uml.foundation.core.TagDefinition pTagDefinition,
355: String pTagValue) throws ModelRepositoryException {
356: org.omg.uml.foundation.core.TaggedValue lTaggedValue = ((org.omg.uml.foundation.core.CorePackage) pTagDefinition
357: .refImmediatePackage()).getTaggedValue()
358: .createTaggedValue();
359: lTaggedValue.setType(pTagDefinition);
360: lTaggedValue
361: .setVisibility(org.omg.uml.foundation.datatypes.VisibilityKindEnum.VK_PUBLIC);
362: lTaggedValue.setModelElement(pModelElement);
363: lTaggedValue.getDataValue().add(pTagValue);
364: }
365:
366: // Work on multiplicity
367: public static org.omg.uml.foundation.datatypes.Multiplicity createMultiplicityInstance(
368: org.omg.uml.UmlPackage pTargetUMLModelExtent,
369: int pLowerLimit, int pUpperLimit) {
370: org.omg.uml.foundation.datatypes.MultiplicityRange lMultiplicityRange = pTargetUMLModelExtent
371: .getDataTypes().getMultiplicityRange()
372: .createMultiplicityRange();
373: lMultiplicityRange.setLower(pLowerLimit);
374: lMultiplicityRange.setUpper(pUpperLimit);
375: org.omg.uml.foundation.datatypes.Multiplicity lMultiplicity = pTargetUMLModelExtent
376: .getDataTypes().getMultiplicity().createMultiplicity();
377: lMultiplicity.getRange().add(lMultiplicityRange);
378: return lMultiplicity;
379: }
380:
381: // This helper method retrieves model repository for use
382: private static ModelRepository getModelRepository()
383: throws ModelRepositoryException {
384: if (sModelRepository == null) {
385: synchronized (sModelRepositoryCreationSemaphore) {
386: if (sModelRepository == null) {
387: try {
388: Context lContext = new InitialContext();
389: sModelRepository = (ModelRepository) lContext
390: .lookup(ModelRepository.COMPONENT_URL);
391: } catch (NamingException e) {
392: throw new ModelRepositoryNotFoundException(e);
393: }
394: }
395: }
396: }
397: return sModelRepository;
398: }
399: }
|