/* * Copyright 2008 Lockheed Martin Corporation, except as stated in the file * entitled Licensing-Information. All modifications copyright 2009 Data Access Technologies, Inc. Licensed under the Academic Free License * version 3.0 (http://www.opensource.org/licenses/afl-3.0.php), except as stated * in the file entitled Licensing-Information. * * Contributors: * MDS - initial API and implementation * */ package org.modeldriven.fuml.assembly.adapter; import javax.xml.namespace.QName; import javax.xml.stream.events.Attribute; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.modeldriven.fuml.assembly.AssemblyAdapter; import org.modeldriven.fuml.repository.Classifier; import org.modeldriven.fuml.xmi.XmiNode; import org.modeldriven.fuml.xmi.stream.StreamNode; import UMLPrimitiveTypes.UnlimitedNatural; import fUML.Syntax.Classes.Kernel.Element; import fUML.Syntax.Classes.Kernel.LiteralBoolean; import fUML.Syntax.Classes.Kernel.LiteralInteger; import fUML.Syntax.Classes.Kernel.LiteralString; import fUML.Syntax.Classes.Kernel.LiteralUnlimitedNatural; /** * OpaqueExpression is not supported in fUML and this class adapts * away an OpaqueExpression into an fUML Element depending on the expression content. * While the below logic is questionable, the class is intended * to support conversion of these often found. For instance * RSA and Eclipse and other tools generate them as the ObjectFlow guard attribute (below). * <p> * <edge xmi:type="uml:ObjectFlow" xmi:id="_F4BJME_lEduAoLr6GBiiFQ" name="guard_0" source="_8bSJAE_kEduAoLr6GBiiFQ" target="_BxxFgE_lEduAoLr6GBiiFQ"> * <guard xmi:type="uml:OpaqueExpression" xmi:id="_F4BJMU_lEduAoLr6GBiiFQ"> * <body>1</body> * </guard> * <weight xmi:type="uml:LiteralInteger" xmi:id="_F4BJMk_lEduAoLr6GBiiFQ" value="1"/> * </edge> * </p> * The next reasonable type in fUML to accommodate the expression is a LiteralInteger and * the below logic in general swaps OpaqueExpression for some type * of ValueSpecification. * */ public class OpaqueExpressionAdapter implements AssemblyAdapter { private static Log log = LogFactory.getLog(OpaqueExpressionAdapter.class); public Element assembleElement(StreamNode opaqueExpressionNode) { LiteralString literal = new LiteralString(); XmiNode bodyNode = opaqueExpressionNode.findChildByName("body"); String bodyContent = null; if (bodyNode != null) { bodyContent = bodyNode.getData(); } else { Attribute bodyAttrib = opaqueExpressionNode.getAttribute("body"); if (bodyAttrib != null) bodyContent = bodyAttrib.getValue(); } if (bodyContent != null) { bodyContent = bodyContent.trim(); if (bodyContent.startsWith("\"") && bodyContent.endsWith("\"")) { bodyContent = bodyContent.substring(1, bodyContent.length()-1); literal.setValue(bodyContent); return literal; // must be a string, no need to continue. } } literal.setValue(bodyContent); if ("true".equalsIgnoreCase(bodyContent) || "false".equalsIgnoreCase(bodyContent)) { LiteralBoolean literalBoolean = new LiteralBoolean(); literalBoolean.setValue(Boolean.valueOf(bodyContent).booleanValue()); return literalBoolean; } else if ("*".equals(bodyContent)) { LiteralUnlimitedNatural literalUnlimitedNatural = new LiteralUnlimitedNatural(); UnlimitedNatural value = new UnlimitedNatural(); value.naturalValue = -1; literalUnlimitedNatural.setValue(value); return literalUnlimitedNatural; } else { String type = findResultPinType(opaqueExpressionNode); if ("UnlimitedNatural".equals(type)) { int intValue = 0; try { intValue = Integer.valueOf(bodyContent).intValue(); } catch (NumberFormatException e) { log.warn("could not parse content as unlimited-natural integer '" + bodyContent + "'"); } LiteralUnlimitedNatural literalUnlimitedNatural = new LiteralUnlimitedNatural(); UnlimitedNatural value = new UnlimitedNatural(); value.naturalValue = intValue; literalUnlimitedNatural.setValue(value); return literalUnlimitedNatural; } try { if (log.isDebugEnabled()) log.debug("parsing expression: '" + bodyContent + "'"); LiteralInteger literalInt = new LiteralInteger(); literalInt.setValue(Integer.valueOf(bodyContent).intValue()); return literalInt; } catch (NumberFormatException e) { if (log.isDebugEnabled()) log.debug("invalid number format: " + e.getMessage()); literal.setValue(bodyContent); } } return literal; } private String findResultPinType(StreamNode opaqueExpressionNode) { String result = null; StreamNode parent = (StreamNode)opaqueExpressionNode.getParent(); if (parent == null) { log.warn("expected parent node"); return null; } StreamNode resultNode = (StreamNode)parent.findChildByName("result"); if (resultNode != null) { StreamNode typeNode = (StreamNode)resultNode.findChildByName("type"); if (typeNode != null) { QName name = new QName("href"); String href = typeNode.getAttributeValue(name); if (href != null) { // FIXME; gotta be a better way! URI resolver?? SOMETHING! if (href.endsWith("Integer")) result = "Integer"; else if (href.endsWith("String")) result = "String"; else if (href.endsWith("Boolean")) result = "Boolean"; else if (href.endsWith("UnlimitedNatural")) result = "UnlimitedNatural"; } } } return result; } public Classifier getClassifier(StreamNode node) { throw new IllegalStateException("OpaqueExpression should have no classifier"); } }