Source code
// $Id: DataTypesHelperEUMLImpl.java 19617 2011-07-23 09:04:49Z linus $
/***************************************************************************
* Copyright (c) 2007,2010 Tom Morris and other contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tom Morris - initial implementation
* Thomas Neustupny
* Laurent Braud
***************************************************************************/
package org.argouml.model.euml;
import java.util.ArrayList;
import java.util.List;
import org.argouml.model.DataTypesHelper;
import org.eclipse.emf.common.util.EList;
import org.eclipse.uml2.uml.LiteralBoolean;
import org.eclipse.uml2.uml.LiteralInteger;
import org.eclipse.uml2.uml.LiteralNull;
import org.eclipse.uml2.uml.LiteralString;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.MultiplicityElement;
import org.eclipse.uml2.uml.OpaqueBehavior;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.PseudostateKind;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.ValueSpecification;
/**
* The implementation of the DataTypesHelper for EUML2.
*/
class DataTypesHelperEUMLImpl implements DataTypesHelper {
/**
* The model implementation.
*/
private EUMLModelImplementation modelImpl;
/**
* Constructor.
*
* @param implementation The ModelImplementation.
*/
public DataTypesHelperEUMLImpl(EUMLModelImplementation implementation) {
modelImpl = implementation;
}
public boolean equalsCHOICEKind(Object kind) {
return PseudostateKind.CHOICE_LITERAL.equals(kind);
}
public boolean equalsDeepHistoryKind(Object kind) {
return PseudostateKind.DEEP_HISTORY_LITERAL.equals(kind);
}
public boolean equalsFORKKind(Object kind) {
return PseudostateKind.FORK_LITERAL.equals(kind);
}
public boolean equalsINITIALKind(Object kind) {
return PseudostateKind.INITIAL_LITERAL.equals(kind);
}
public boolean equalsJOINKind(Object kind) {
return PseudostateKind.JOIN_LITERAL.equals(kind);
}
public boolean equalsJUNCTIONKind(Object kind) {
return PseudostateKind.JUNCTION_LITERAL.equals(kind);
}
public boolean equalsShallowHistoryKind(Object kind) {
return PseudostateKind.SHALLOW_HISTORY_LITERAL.equals(kind);
}
public String getBody(Object handle) {
EList<String> bodies = null;
if (handle instanceof OpaqueExpression) {
bodies = ((OpaqueExpression) handle).getBodies();
} else if (handle instanceof OpaqueBehavior) {
bodies = ((OpaqueBehavior) handle).getBodies();
} else {
throw new IllegalArgumentException(
"handle must be instance "
+ "of OpaqueExpression or OpaqueBehavior"); //$NON-NLS-1$
}
return (bodies.size() < 1) ? null : bodies.get(0);
}
public String getLanguage(Object handle) {
EList<String> langs = null;
if (handle instanceof OpaqueExpression) {
langs = ((OpaqueExpression) handle).getLanguages();
} else if (handle instanceof OpaqueBehavior) {
langs = ((OpaqueBehavior) handle).getLanguages();
} else {
throw new IllegalArgumentException(
"handle must be instance of OpaqueExpression" //$NON-NLS-1$
+ " or OpaqueBehavior. We got " + handle); //$NON-NLS-1$
}
return (langs.size() < 1) ? null : langs.get(0);
}
public String multiplicityToString(Object multiplicity) {
if (!(multiplicity instanceof MultiplicityElement)) {
throw new IllegalArgumentException(
"multiplicity must be instance "
+ "of MultiplicityElement"); //$NON-NLS-1$
}
MultiplicityElement mult = (MultiplicityElement) multiplicity;
if (mult.getLower() == mult.getUpper()) {
return DataTypesFactoryEUMLImpl.boundToString(mult.getLower());
} else {
return DataTypesFactoryEUMLImpl.boundToString(
mult.getLower())
+ ".." //$NON-NLS-1$
+ DataTypesFactoryEUMLImpl.boundToString(mult.getUpper());
}
}
public Object setBody(Object handle, String body) {
List<String> bodies = null;
if (handle instanceof OpaqueExpression) {
bodies = ((OpaqueExpression) handle).getBodies();
} else if (handle instanceof OpaqueBehavior) {
bodies = ((OpaqueBehavior) handle).getBodies();
} else {
throw new IllegalArgumentException(
"handle must be instance "
+ "of OpaqueExpression or OpaqueBehavior"); //$NON-NLS-1$
}
// TODO: Support more than one body/language
if (bodies.size() > 1) {
throw new IllegalStateException(
"Only one body/lang supported"); //$NON-NLS-1$
}
bodies.clear();
bodies.add(body);
return handle;
}
public Object setLanguage(Object handle, String language) {
List<String> langs = null;
if (handle instanceof OpaqueExpression) {
langs = ((OpaqueExpression) handle).getLanguages();
} else if (handle instanceof OpaqueBehavior) {
langs = ((OpaqueBehavior) handle).getLanguages();
} else {
throw new IllegalArgumentException(
"handle must be instance "
+ "of OpaqueExpression or OpaqueBehavior"); //$NON-NLS-1$
}
// TODO: Support more than one body/language
if (langs.size() > 1) {
throw new IllegalStateException(
"Only one body/lang supported"); //$NON-NLS-1$
}
langs.clear();
langs.add(language);
return handle;
}
/**
* @see org.argouml.model.DataTypesHelper#getValueSpecifications()
*/
public ArrayList<String> getValueSpecifications() {
ArrayList<String> list = new ArrayList<String>();
//
list.add("OpaqueExpression");
//list.add("OpaqueExpression");
//LiteralSpecification
//list.add("LiteralNull");//When other ok
list.add("LiteralString");
//list.add("LiteralInteger");//When other ok
list.add("LiteralBoolean");
//list.add("LiteralUnlimitedNatural");//When other ok
//list.add("LiteralReal");//UML 2.4
//End LiteralSpecification
//list.add("InstanceValue");
return list;
}
/**
* @see org.argouml.model.DataTypesHelper#createValueValueSpecification(java.lang.String, java.lang.Object)
*/
public Object createValueSpecification(Object handle,
String type) {
ValueSpecification newValueSpecification = null;
if (handle instanceof Property) {
Property property = (Property) handle;
Object[] tabValues = null;
if (type.equals("LiteralBoolean")) {
newValueSpecification =
(ValueSpecification) UMLFactory.eINSTANCE.create(
UMLPackage.eINSTANCE.getLiteralBoolean());
} else if (type.equals("LiteralNull")) {
newValueSpecification =
(ValueSpecification) UMLFactory.eINSTANCE.create(
UMLPackage.eINSTANCE.getLiteralNull());
} else if (type.equals("LiteralString")) {
newValueSpecification =
(ValueSpecification) UMLFactory.eINSTANCE.create(
UMLPackage.eINSTANCE.getLiteralString());
tabValues = new String[]{""};
} else if (type.equals("LiteralUnlimitedNatural")) {
newValueSpecification =
(ValueSpecification) UMLFactory.eINSTANCE.create(
UMLPackage.eINSTANCE.getLiteralUnlimitedNatural());
tabValues = new String[]{"0"};
} else if (type.equals("LiteralInteger")) {
newValueSpecification =
(ValueSpecification) UMLFactory.eINSTANCE.create(
UMLPackage.eINSTANCE.getLiteralInteger());
tabValues = new String[]{"0"};
} else if (type.equals("OpaqueExpression")) {
newValueSpecification =
(ValueSpecification) UMLFactory.eINSTANCE.create(
UMLPackage.eINSTANCE.getOpaqueExpression());
setLanguage(newValueSpecification, "");
setBody(newValueSpecification, "");
}
if (tabValues != null) {
modifyValueSpecification(newValueSpecification, tabValues);
}
if (newValueSpecification != null) {
property.setDefaultValue(newValueSpecification);
}
} // TODO else => Exception !
return newValueSpecification;
}
/**
* @see org.argouml.model.DataTypesHelper#modifyValueSpecification(java.lang.Object, java.lang.Object[])
*/
public void modifyValueSpecification(Object handle, Object[] tabValues) {
// LiteralSpecification
if (handle instanceof LiteralBoolean) {
LiteralBoolean lb = (LiteralBoolean) handle;
if (tabValues != null && tabValues.length == 1) {
Boolean value = (Boolean) tabValues[0];
lb.setValue(value);
}
} else if (handle instanceof LiteralNull) {
// Can't be changed
} else if (handle instanceof LiteralString) {
LiteralString ls = (LiteralString) handle;
if (tabValues != null && tabValues.length == 1) {
String value = (String) tabValues[0];
ls.setValue(value);
}
} else if (handle instanceof LiteralUnlimitedNatural) {
LiteralUnlimitedNatural ls = (LiteralUnlimitedNatural) handle;
if (tabValues != null && tabValues.length == 1) {
Integer value = (Integer) tabValues[0];
ls.setValue(value);
}
} else if (handle instanceof LiteralInteger) {
LiteralInteger ls = (LiteralInteger) handle;
if (tabValues != null && tabValues.length == 1) {
Integer value = (Integer) tabValues[0];
ls.setValue(value);
}
} else if (handle instanceof OpaqueExpression) {
//rewrite it after change setExpression ?
OpaqueExpression oe = (OpaqueExpression) handle;
List<String> bodies = oe.getBodies();
List<String> langs = oe.getLanguages();
// as write in UML specification, we have size(bodies)==size(langs)
// we must have tabValues.length%2==0
bodies.clear();
langs.clear();
for (int i = 0; i < tabValues.length; i += 2) {
bodies.add((String) tabValues[i]);
langs.add((String) tabValues[i + 1]);
}
}
// TODO Expression and InstanceValue (how)
// If anyone have an example.
}
/**
* @see org.argouml.model.DataTypesHelper#getValueSpecificationValues(java.lang.Object)
*/
public Object[] getValueSpecificationValues(Object handle) {
Object[] tabValues = null;
// LiteralSpecification
if (handle instanceof LiteralBoolean) {
LiteralBoolean lb = (LiteralBoolean) handle;
tabValues = new Boolean[]{lb.isValue()};
} else if (handle instanceof LiteralNull) {
// Can't be set
} else if (handle instanceof LiteralString) {
LiteralString ls = (LiteralString) handle;
tabValues = new String[]{ls.getValue()};
} else if (handle instanceof LiteralUnlimitedNatural) {
LiteralUnlimitedNatural lun = (LiteralUnlimitedNatural) handle;
tabValues = new String[]{"" + lun.getValue()};
} else if (handle instanceof LiteralInteger) {
LiteralInteger li = (LiteralInteger) handle;
tabValues = new Integer[]{li.getValue()};
}
else if (handle instanceof OpaqueExpression) {
//rewrite it after change setExpression ?
OpaqueExpression oe = (OpaqueExpression) handle;
List<String> bodies = oe.getBodies();
List<String> langs = oe.getLanguages();
// as write in UML specification, we have size(bodies)==size(langs)
// we must have tabValues.length%2==0
if (bodies.size() > 0) {
tabValues = new String[bodies.size() * 2];
for (int i = 0; i < bodies.size(); i++) {
tabValues[i * 2] = bodies.get(i);
tabValues[i * 2 + 1] = langs.get(i);
}
}
}
// TODO Expression and InstanceValue (how)
// If anyone have an example.
return tabValues;
}
}
Run 1
The code has clear imports, consistent naming, and generally simple methods with descriptive names, which aids readability. However, several issues reduce clarity: repetitive type-checking blocks in getBody, getLanguage, setBody, setLanguage, createValueSpecification, and modifyValueSpecification create unnecessary nesting and duplication. Some methods have ambiguous intent due to commented-out code and TODO comments. The getValueSpecifications method contains many commented lines, making the logic unclear. Action granularity is mostly one action per line, but some sections mix concerns. Reading flow suffers from scattered comments and inconsistent formatting, especially in createValueSpecification where indentation is irregular. Overall, the structure is understandable but could be significantly improved by extracting common type-checking logic into helper methods and cleaning up comments.
Run 2
The code has a clear class structure and consistent method naming, but suffers from significant readability issues. While the top-level organization is logical, several methods—especially createValueSpecification and modifyValueSpecification—contain long if-else chains that could be refactored into a strategy or map-based dispatch for clarity. Nesting remains mostly flat, which is good, but some methods exceed reasonable length and mix concerns. Intent is generally clear from method names and comments, though many commented-out lines add noise without value. Action granularity is mostly one action per line, but formatting is inconsistent (e.g., indentation, line breaks), which disrupts reading flow. Redundant null checks and repeated cast patterns also reduce conciseness. Overall, the code is understandable but would benefit from refactoring long conditionals, removing dead comments, and standardizing formatting to improve readability.
Run 3
The code has a clear class structure and follows consistent patterns, but suffers from significant readability issues. The XML-ish comments and commented-out code clutter the file. Several methods have repetitive if-else chains that could be simplified with polymorphism or a switch. The createValueSpecification method is particularly long and branches heavily. Deep indentation and nested type checks in some areas make the logic harder to follow. Variable names like 'ls', 'lb', 'lun' are cryptic. Some methods (getBody, getLanguage, setBody, setLanguage) duplicate type-checking logic. Magic string literals and inconsistent formatting (inconsistent spacing, alignment) reduce polish. Positive aspects include clear method names and consistent exception handling. Overall, functional but not cleanly refactored.
Run 1
Code Structure: Methods are logically separated by operation, but repeated type-dispatch logic creates duplication. Nesting: Mostly shallow; value-specification methods introduce moderate nesting without becoming deeply tangled. Clarity of intent: Descriptive method names and explicit UML types help, but generic Object parameters, abbreviated variables, implicit body/language pairing, and inconsistent value representations obscure contracts. Code length: Individual methods are manageable, though repetitive branches, boilerplate, and commented-out code unnecessarily expand the class. Action granularity: Generally one action per statement and line, making mutations easy to follow. Reading flow: Straightforward conditionals and consistent method boundaries support scanning, but inconsistent indentation, awkward wrapping, stale comments, and unfinished TODOs interrupt the flow.
Run 2
Code Structure: Methods are logically separated by responsibility, but repeated type-dispatch logic and duplicated body/language handling weaken organization. Nesting: Mostly shallow, with moderate nesting in value-specification creation and modification. Clarity of intent: Descriptive method names make the overall purpose clear; generic Object parameters, abbreviated variables, string-based type selection, and undocumented array conventions obscure details. Code length: Simple helpers are concise, but repetitive branches, verbose factory calls, and commented-out code add unnecessary length. Action granularity: Statements generally perform one action per line, making individual operations easy to follow. Reading flow: Consistent method boundaries and straightforward conditionals support sequential reading, while inconsistent indentation, scattered TODOs, stale comments, and inconsistent value representations interrupt it.
Run 3
Code Structure: Methods are logically separated by responsibility, but repeated type-dispatch logic and body/language handling add duplication. Nesting: Mostly shallow, with moderate nesting in value-specification creation and extraction; no deeply tangled control flow. Clarity of intent: Method names and UML types convey purpose, but generic Object parameters, abbreviations such as tabValues and ls, implicit array conventions, and unfinished comments obscure details. Code length: Simple helpers are concise, while repetitive factory branches, commented-out code, and boilerplate unnecessarily expand the class. Action granularity: Statements generally perform one action per line, making individual operations easy to follow. Reading flow: Consistent early sections and straightforward branching support readability, but inconsistent indentation, awkward line wrapping, stale TODOs, and differing value representations interrupt the flow. Overall, readable and organized, but noticeably weakened by duplication and unclear conventions.