// $Id: TestJavaImportClass.java 14353 2008-04-16 01:07:56Z tfmorris $
// Copyright (c) 1996-2008 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies. This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason. IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
package org.argouml.uml.reveng;
import java.util.Collection;
import java.util.Iterator;
import java.io.StringReader;
import junit.framework.TestCase;
import org.argouml.model.InitializeModel;
import org.argouml.model.Model;
import org.argouml.profile.init.InitProfileSubsystem;
import org.argouml.uml.reveng.java.JavaLexer;
import org.argouml.uml.reveng.java.JavaRecognizer;
import org.argouml.uml.reveng.java.Modeller;
import antlr.RecognitionException;
import antlr.TokenStreamException;
/**
* Test case to test the import of a Java source file. The content of the Java
* source file is a private constant at the bottom of the source of this class.
* The test methods are specially designed for this Java source constant.
* Feeding of the diagram subsystem is disabled; only model elements are
* created and checked. For testing with another Java source file, copy this
* test case, change the Java source constant and modify the test method (the
* setUp method need not be changed).<p>
*/
public class TestJavaImportClass extends TestCase {
/**
* Construct a test case with the given name to test import of a Java class.
*
* @param str name of the test case
*/
public TestJavaImportClass(String str) {
super(str);
InitializeModel.initializeDefault();
}
/*
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() {
if (isParsed) {
return;
}
JavaLexer lexer = new JavaLexer(new StringReader(PARSERINPUT));
assertNotNull("Creation of lexer failed.", lexer);
lexer.setTokenObjectClass("org.argouml.uml.reveng.java.ArgoToken");
JavaRecognizer parser = new JavaRecognizer(lexer);
assertNotNull("Creation of parser failed.", parser);
parsedModel = Model.getModelManagementFactory().createModel();
assertNotNull("Creation of model failed.", parsedModel);
Model.getModelManagementFactory().setRootModel(parsedModel);
new InitProfileSubsystem().init();
Modeller modeller =
new Modeller(parsedModel, new DummyImportSettings(),
"TestClass.java");
assertNotNull("Creation of Modeller instance failed.", modeller);
try {
parser.compilationUnit(modeller, lexer);
isParsed = true;
} catch (RecognitionException e) {
fail("Parsing of Java source failed." + e);
} catch (TokenStreamException e) {
fail("Parsing of Java source failed." + e);
}
}
/**
* Test if the package was processed correctly.
*/
public void testPackage() {
parsedPackage = Model.getFacade().lookupIn(parsedModel, "testpackage");
assertNotNull("No package \"testpackage\" found in model.",
parsedPackage);
assertEquals("Inconsistent package name.",
"testpackage", Model.getFacade().getName(parsedPackage));
assertEquals("The namespace of the package should be the model.",
parsedModel, Model.getFacade().getNamespace(parsedPackage));
assertTrue("The package should be recognized as a package.",
Model.getFacade().isAPackage(parsedPackage));
}
/**
* Test if the import was processed correctly.
*/
public void testImport() {
if (parsedPackage == null) {
parsedPackage =
Model.getFacade().lookupIn(parsedModel, "testpackage");
assertNotNull("No package \"testpackage\" found in model.",
parsedPackage);
}
Collection ownedElements =
Model.getFacade().getOwnedElements(parsedPackage);
assertNotNull("No elements owned by \"testpackage\".", ownedElements);
Object component = null;
Iterator iter = ownedElements.iterator();
while (iter.hasNext()) {
Object element = iter.next();
if (Model.getFacade().isAComponent(element)) {
component = element;
break;
}
}
assertNotNull("No component found.", component);
assertEquals("The component name is wrong.",
"TestClass.java", Model.getFacade().getName(component));
Collection dependencies =
Model.getFacade().getClientDependencies(component);
assertNotNull("No dependencies found for component.", dependencies);
Object permission = null;
iter = dependencies.iterator();
while (iter.hasNext()) {
Object element = iter.next();
if (Model.getFacade().isAPermission(element)) {
permission = element;
break;
}
}
assertNotNull("No import found.", permission);
assertTrue("isAPackageImport returned false for import/Permission",
Model.getFacade().isAPackageImport(permission));
assertEquals("getPackageImport() found different result than "
+ "getClientDependencies", permission, Model.getCoreHelper()
.getPackageImports(component).iterator().next());
assertEquals("The import name is wrong.",
"TestClass.java -> Observer",
Model.getFacade().getName(permission));
Collection suppliers = Model.getFacade().getSuppliers(permission);
assertNotNull("No suppliers found in import.", suppliers);
Object supplier = null;
iter = suppliers.iterator();
if (iter.hasNext()) {
supplier = iter.next();
}
assertNotNull("No supplier found in import.", supplier);
assertEquals("The import supplier name is wrong.",
"Observer", Model.getFacade().getName(supplier));
Object namespace = Model.getFacade().getNamespace(supplier);
assertNotNull("The import supplier has no namespace.", namespace);
assertEquals("Expected namespace name \"util\".",
"util", Model.getFacade().getName(namespace));
namespace = Model.getFacade().getNamespace(namespace);
assertNotNull("The namespace \"util\" has no namespace.", namespace);
assertEquals("Expected namespace name \"java\".",
"java", Model.getFacade().getName(namespace));
assertEquals("The namespace of \"java\" should be the model.",
parsedModel, Model.getFacade().getNamespace(namespace));
}
/**
* Test if the import was processed correctly.
*/
public void testClass() {
if (parsedPackage == null) {
parsedPackage =
Model.getFacade().lookupIn(parsedModel, "testpackage");
assertNotNull("No package \"testpackage\" found in model.",
parsedPackage);
}
parsedClass = Model.getFacade().lookupIn(parsedPackage, "TestClass");
assertNotNull("No class \"TestClass\" found.", parsedClass);
assertEquals("Inconsistent class name.",
"TestClass", Model.getFacade().getName(parsedClass));
assertEquals("The namespace of the class should be \"testpackage\".",
parsedPackage, Model.getFacade().getNamespace(parsedClass));
assertTrue("The class should be recognized as a class.",
Model.getFacade().isAClass(parsedClass));
assertTrue("The class should be abstract.",
Model.getFacade().isAbstract(parsedClass));
assertTrue("The class should be public.",
Model.getFacade().isPublic(parsedClass));
Collection generalizations =
Model.getFacade().getGeneralizations(parsedClass);
assertNotNull("No generalizations found for class.", generalizations);
Object generalization = null;
Iterator iter = generalizations.iterator();
if (iter.hasNext()) {
generalization = iter.next();
}
assertNotNull("No generalization found for class.", generalization);
assertEquals("The generalization name is wrong.",
"TestClass -> Object", Model.getFacade().getName(generalization));
assertEquals("The child of the generalization should be the class.",
parsedClass, Model.getFacade().getSpecific(generalization));
assertEquals("The parent of the generalization should be \"Object\".",
"Object",
Model.getFacade().getName(
Model.getFacade().getGeneral(generalization)));
Collection dependencies =
Model.getFacade().getClientDependencies(parsedClass);
assertNotNull("No dependencies found for class.", dependencies);
Object abstraction = null;
iter = dependencies.iterator();
if (iter.hasNext()) {
abstraction = iter.next();
}
assertNotNull("No abstraction found for class.", abstraction);
assertEquals("The abstraction name is wrong.",
"TestClass -> Observer", Model.getFacade().getName(abstraction));
try {
assertEquals("The client of the abstraction should be the class.",
parsedClass,
Model.getFacade().getClients(abstraction)
.iterator().next());
} catch (IllegalArgumentException ex) {
fail("The implementation dependency has no clients.");
}
try {
assertEquals(
"The supplier of the abstraction should be \"Observer\".",
"Observer", Model.getFacade().getName(
Model.getFacade().getSuppliers(abstraction)
.iterator().next()));
} catch (IllegalArgumentException ex) {
fail("The abstraction has no suppliers.");
}
}
/**
* Test if the attributes were processed correctly.
*/
public void testAttributes() {
if (parsedPackage == null) {
parsedPackage =
Model.getFacade().lookupIn(parsedModel, "testpackage");
assertNotNull("No package \"testpackage\" found in model.",
parsedPackage);
}
if (parsedClass == null) {
parsedClass =
Model.getFacade().lookupIn(parsedPackage, "TestClass");
assertNotNull("No class \"TestClass\" found.", parsedClass);
}
Collection attributes = Model.getFacade().getAttributes(parsedClass);
assertNotNull("No attributes found ib class.", attributes);
assertEquals("Number of attributes is wrong", 2, attributes.size());
Object attribute = null;
Object attributeForn = null;
Object attributeFors = null;
Iterator iter = attributes.iterator();
while (iter.hasNext()) {
attribute = iter.next();
assertTrue("The attribute should be recognized as an attribute.",
Model.getFacade().isAAttribute(attribute));
if ("n".equals(Model.getFacade().getName(attribute))) {
attributeForn = attribute;
} else if ("s".equals(Model.getFacade().getName(attribute))) {
attributeFors = attribute;
}
}
assertTrue("The attributes have wrong names.",
attributeForn != null && attributeFors != null);
Object attribType = Model.getFacade().getType(attributeForn);
Object initializer = Model.getFacade().getInitialValue(attributeForn);
assertTrue("Attribute n should be private.",
Model.getFacade().isPrivate(attributeForn));
assertFalse("Attribute n should not be final.",
Model.getFacade().isReadOnly(attributeForn));
assertTrue("Attribute n should have type int.",
"int".equals(Model.getFacade().getName(attribType)));
assertTrue("Attribute n has no initializer.",
Model.getFacade().isInitialized(attributeForn)
&& initializer != null);
assertEquals("The initializer of attribute n is wrong.",
" 0", Model.getFacade().getBody(initializer));
attribType = Model.getFacade().getType(attributeFors);
initializer = Model.getFacade().getInitialValue(attributeFors);
assertTrue("Attribute s should be public.",
Model.getFacade().isPublic(attributeFors));
assertTrue("Attribute s should be static.",
Model.getFacade().isStatic(attributeFors));
assertTrue("Attribute s should be final.",
Model.getFacade().isReadOnly(attributeFors));
assertTrue("Attribute s should have type String.",
"String".equals(Model.getFacade().getName(attribType)));
assertTrue("Attribute s has no initializer.",
Model.getFacade().isInitialized(attributeFors)
&& initializer != null);
assertEquals("The initializer of attribute s is wrong.",
" \"final String object\"", Model.getFacade().getBody(initializer));
}
/**
* Test if the association was processed correctly.
*/
public void testAssociation() {
if (parsedPackage == null) {
parsedPackage =
Model.getFacade().lookupIn(parsedModel, "testpackage");
assertNotNull("No package \"testpackage\" found in model.",
parsedPackage);
}
if (parsedClass == null) {
parsedClass =
Model.getFacade().lookupIn(parsedPackage, "TestClass");
assertNotNull("No class \"TestClass\" found.", parsedClass);
}
Collection associationEnds =
Model.getFacade().getAssociationEnds(parsedClass);
assertNotNull("No association ends found ib class.", associationEnds);
assertEquals("Number of association ends is wrong", 2,
associationEnds.size());
Object associationEnd = null;
Object association = null;
int navigableCount = 0;
Iterator iter = associationEnds.iterator();
while (iter.hasNext()) {
associationEnd = iter.next();
assertTrue(
"The attribute end should be recognized as "
+ "an attribute end.",
Model.getFacade().isAAssociationEnd(associationEnd));
assertEquals("The type of both association ends must be the class.",
parsedClass, Model.getFacade().getType(associationEnd));
if (association == null) {
association = Model.getFacade().getAssociation(associationEnd);
assertTrue(
"The attribute should be recognized as an attribute.",
Model.getFacade().isAAssociation(association));
assertEquals("The association name is wrong.",
"TestClass -> TestClass",
Model.getFacade().getName(association));
} else {
assertEquals(
"Association end must belong to the same association.",
association,
Model.getFacade().getAssociation(associationEnd));
}
if (Model.getFacade().isNavigable(associationEnd)) {
++navigableCount;
}
}
assertEquals("Only one association end must be navigable.",
1, navigableCount);
}
/**
* Test if the operations were processed correctly.
*/
public void testOperations() {
if (parsedPackage == null) {
parsedPackage =
Model.getFacade().lookupIn(parsedModel, "testpackage");
assertNotNull("No package \"testpackage\" found in model.",
parsedPackage);
}
if (parsedClass == null) {
parsedClass =
Model.getFacade().lookupIn(parsedPackage, "TestClass");
assertNotNull("No class \"TestClass\" found.", parsedClass);
}
Collection operations = Model.getFacade().getOperations(parsedClass);
assertNotNull("No operations found in class.", operations);
assertEquals("Number of operations is wrong", 4, operations.size());
Object operation = null;
Object operationForTestClass = null;
Object operationForupdate = null;
Object operationForgetString = null;
Object operationForx = null;
Iterator iter = operations.iterator();
while (iter.hasNext()) {
operation = iter.next();
assertTrue("The operation should be recognized as an operation.",
Model.getFacade().isAOperation(operation));
if ("TestClass".equals(Model.getFacade().getName(operation))) {
operationForTestClass = operation;
} else if ("update".equals(Model.getFacade().getName(operation))) {
operationForupdate = operation;
} else if ("getString".equals(
Model.getFacade().getName(operation))) {
operationForgetString = operation;
} else if ("x".equals(Model.getFacade().getName(operation))) {
operationForx = operation;
}
}
assertTrue("The operations have wrong names.",
operationForTestClass != null
&& operationForupdate != null
&& operationForgetString != null
&& operationForx != null);
assertTrue("Operation TestClass should be protected.",
Model.getFacade().isProtected(operationForTestClass));
assertEquals("The body of operation TestClass is wrong.",
BODY2, getBody(operationForTestClass));
assertTrue("Operation update should be public.",
Model.getFacade().isPublic(operationForupdate));
assertEquals("The body of operation update is wrong.",
BODY1,
getBody(operationForupdate));
assertTrue("Operation getString should be static.",
Model.getFacade().isStatic(operationForgetString));
assertTrue("Operation getString should be private.",
Model.getFacade().isPrivate(operationForgetString));
assertEquals("The body of operation getString is wrong.",
BODY3,
getBody(operationForgetString));
assertTrue("Operation x should be abstract.",
Model.getFacade().isAbstract(operationForx));
assertTrue("Operation x should have package visibility.",
Model.getFacade().isPackage(operationForx));
}
/**
* Gets the (first) body of an operation.
*
* @param operation The operation.
* @return The first body.
*/
private static String getBody(Object operation) {
String body = null;
Collection methods = Model.getFacade().getMethods(operation);
if (methods != null && !methods.isEmpty()) {
Object expression =
Model.getFacade().getBody(methods.iterator().next());
body = (String) Model.getFacade().getBody(expression);
}
return body;
}
/**
* Flag, if the Java source is parsed already.
*/
private static boolean isParsed;
/**
* Instances of the model and its components.
*/
private static Object parsedModel;
private static Object parsedPackage;
private static Object parsedClass;
private static final String BODY1 =
"\n if (arg instanceof TestClass) testClass = (TestClass)arg;\n";
private static final String BODY2 =
"\n // A constructor with a single line comment\n"
+ " this.n = n;\n";
private static final String BODY3 =
"\n // A static method\n return s;\n";
/**
* Test input for the parser. It's the content of a Java source file. It's
* hardcoded here, because this test case strongly depends on this.
*/
private static final String PARSERINPUT =
"package testpackage;\n"
+ "import java.util.Observer;\n"
+ "/** A Javadoc comment */\n"
+ "public abstract class TestClass "
+ "extends Object implements Observer {\n"
+ " private int n = 0;\n"
+ " protected static TestClass testClass;\n"
+ " public static final String s = \"final String object\";\n"
+ " protected TestClass(int n) {"
+ BODY2
+ " }\n"
+ " public void update(java.util.Observable o, Object arg) {"
+ BODY1
+ " }\n"
+ " /** Another Javadoc comment */\n"
+ " private static String getString() {"
+ BODY3
+ " }\n"
+ " abstract void x();\n"
+ " /* A multiline\n"
+ " comment\n"
+ " */\n"
+ "}";
}