/* $Id: TestProjectWithProfiles.java 18234 2010-04-09 22:39:12Z euluis $
*****************************************************************************
* Copyright (c) 2009-2010 Contributors - see below
* 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:
* euluis
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 2007-2009 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.kernel;
import static org.argouml.model.Model.getCoreFactory;
import static org.argouml.model.Model.getExtensionMechanismsHelper;
import static org.argouml.model.Model.getFacade;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
import org.argouml.FileHelper;
import org.argouml.application.helpers.ApplicationVersion;
import org.argouml.model.InitializeModel;
import org.argouml.model.Model;
import org.argouml.model.XmiReferenceException;
import org.argouml.model.XmiReferenceRuntimeException;
import org.argouml.persistence.AbstractFilePersister;
import org.argouml.persistence.OpenException;
import org.argouml.persistence.PersistenceManager;
import org.argouml.persistence.SaveException;
import org.argouml.profile.Profile;
import org.argouml.profile.ProfileException;
import org.argouml.profile.ProfileFacade;
import org.argouml.profile.ProfileManager;
import org.argouml.profile.ProfileMother;
import org.argouml.profile.UserDefinedProfile;
import org.argouml.profile.init.InitProfileSubsystem;
/**
* Tests the {@link ProjectImpl} with profiles, specifically this enables the
* testing of the org.argouml.profile subsystem API for the project and the
* interactions between {@link ProfileConfiguration} and the {@link Project}.
*
* @author Luis Sergio Oliveira (euluis)
*/
public class TestProjectWithProfiles extends TestCase {
private File testCaseDir;
/*
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
InitializeModel.initializeMDR();
new InitProfileSubsystem().init();
initAppVersion();
assertNotNull(ApplicationVersion.getVersion());
String testCaseDirNamePrefix = getClass().getPackage().getName();
testCaseDir = FileHelper.setUpDir4Test(testCaseDirNamePrefix);
}
@Override
protected void tearDown() throws Exception {
FileHelper.delete(testCaseDir);
super.tearDown();
}
/**
* Basic test that a new project contains a {@link ProfileConfiguration}
* and that this contains the default profiles.
*/
public void testCreatedProjectContainsProfileConfiguration() {
List<Profile> defaultProfiles
= ProfileFacade.getManager().getDefaultProfiles();
Project project = ProjectManager.getManager().makeEmptyProject();
ProfileConfiguration profileConfiguration =
project.getProfileConfiguration();
assertNotNull(profileConfiguration);
assertNotNull(profileConfiguration.getProfiles());
for (Profile profile : defaultProfiles) {
assertTrue(profileConfiguration.getProfiles().contains(profile));
}
}
/**
* WARNING: not a unit test, this is more like a functional test, where
* several subsystems are tested.
*
* This test does:
* <ol>
* <li>set UML Profile for MetaProfile as a default profile</li>
* <li>create a new project and assert that it has the MetaProfile
* as part of the project's profile configuration</li>
* <li>create a dependency from the project's model to the
* MetaProfile</li>
* <li>remove the MetaProfile from the project's profile
* configuration</li>
* <li>assert that the project's model elements that had a dependency to
* the MetaProfile don't get inconsistent</li>
* <li>save the project into a new file</li>
* <li>reopen the project and assert that the MetaProfile isn't part of
* the profile configuration</li>
* <li>assert that the project's model elements that had a dependency to
* the MetaProfile are consistent</li>
* </ol>
* @throws OpenException if there was an error during a project load
* @throws SaveException if there was an error during a project save
* @throws InterruptedException if save or load was interrupted
*/
public void testRemoveProfileWithModelThatRefersToProfile()
throws OpenException, SaveException, InterruptedException {
// set MetaProfile as a default profile
ProfileManager profileManager = ProfileFacade.getManager();
Profile metaProfile = profileManager.getProfileForClass(
"org.argouml.profile.internal.ProfileMeta");
if (!profileManager.getDefaultProfiles().contains(metaProfile)) {
profileManager.addToDefaultProfiles(metaProfile);
}
// create a new project and assert that it has the MetaProfile
// as part of the project's profile configuration
Project project = ProjectManager.getManager().makeEmptyProject();
assertTrue(project.getProfileConfiguration().getProfiles().contains(
metaProfile));
Object pckge = null;
try {
pckge = metaProfile.getProfilePackages().iterator().next();
} catch (ProfileException pe) {
fail();
}
assertNotNull(pckge);
Object theStereotype = null;
Iterator iter = Model.getFacade().getOwnedElements(pckge).iterator();
while (theStereotype == null && iter.hasNext()) {
Object elem = iter.next();
if (Model.getFacade().isAStereotype(elem) &&
Model.getFacade().getName(elem).equals("Critic")) {
theStereotype = elem;
}
}
assertNotNull(theStereotype);
// create a dependency from the project's model to the MetaProfile
Object model = project.getUserDefinedModelList().get(0);
assertNotNull(model);
Object foo = Model.getCoreFactory().buildComment(null, model);
Model.getCoreHelper().setName(foo, "foo");
Model.getCoreHelper().addStereotype(foo, theStereotype);
// remove the MetaProfile from the project's profile configuration
project.getProfileConfiguration().removeProfile(metaProfile, model);
// assert that the project's model element that had a dependency to
// the MetaProfile doesn't get inconsistent
theStereotype =
Model.getFacade().getStereotypes(foo).iterator().next();
assertNotNull(theStereotype);
// save the project into a new file
File file = getFileInTestDir(
"testRemoveProfileWithModelThatRefersToProfile.zargo");
AbstractFilePersister persister = saveProject(project, file);
project.remove();
// reopen the project and assert that the MetaProfile isn't part of
// the profile configuration, including the fact that the stereotype
// <<Critic>> isn't found
project = persister.doLoad(file);
project.postLoad();
assertFalse(project.getProfileConfiguration().getProfiles().contains(
metaProfile));
// assert that the project's model elements that had a dependency to
// the UML profile for Java are consistent
pckge = project.getUserDefinedModelList().get(0);
assertNotNull(pckge);
foo = null;
iter = Model.getFacade().getOwnedElements(pckge).iterator();
while (foo == null && iter.hasNext()) {
Object elem = iter.next();
if (Model.getFacade().isAComment(elem) &&
Model.getFacade().getName(elem).equals("foo")) {
foo = elem;
}
}
assertNotNull(foo);
theStereotype =
Model.getFacade().getStereotypes(foo).iterator().next();
assertNotNull(theStereotype);
// TODO: with new reference resolving scheme, the model sub-system will
// cache the systemId of the profile, open it and resolve the profile
// on its own. Thus, the java.util.List will be found and the return
// value will be present again...
//assertNotNull(returnParamType);
}
private File getFileInTestDir(String fileName) {
return new File(testCaseDir, fileName);
}
/**
* WARNING: not a unit test, this is more like a functional test, where
* several subsystems are tested.
*
* This test does:
* <ol>
* <li>setup a user defined profile</li>
* <li>add it to the project configuration</li>
* <li>create a dependency between the project's model and the user
* defined profile</li>
* <li>save the project</li>
* <li>load the project and assert that the model element that depends on
* the profile is consistent</li>
* </ol>
*
* @throws Exception when things go wrong
*/
public void testProjectWithUserDefinedProfilePersistency()
throws Exception {
// setup a user defined profile
File userDefinedProfileFile = createUserProfileFile(testCaseDir,
"testProjectWithUserDefinedProfilePersistency-TestUserProfile.xmi");
// add it to the project configuration
ProfileManager profileManager = ProfileFacade.getManager();
Profile userDefinedProfile =
new UserDefinedProfile(userDefinedProfileFile, profileManager);
profileManager.registerProfile(userDefinedProfile);
profileManager.addSearchPathDirectory(testCaseDir.getAbsolutePath());
Project project = ProjectManager.getManager().makeEmptyProject();
Object model = project.getUserDefinedModelList().get(0);
Model.getCoreHelper().setName(model,
"testProjectWithUserDefinedProfilePersistency-model");
// create a dependency between the project's model and the user defined
// profile
project.getProfileConfiguration().addProfile(userDefinedProfile, model);
Object fooClass = getCoreFactory().buildClass(
"testProjectWithUserDefinedProfilePersistency-class", model);
Collection stereotypes = getExtensionMechanismsHelper().getStereotypes(
project.getModels());
Object stStereotype = null;
for (Object stereotype : stereotypes) {
if (ProfileMother.STEREOTYPE_NAME_ST.equals(
getFacade().getName(stereotype))) {
stStereotype = stereotype;
break;
}
}
assertNotNull("Didn't find stereotype", stStereotype);
Model.getCoreHelper().addStereotype(fooClass, stStereotype);
assertEquals("Setting stereotype didn't work", 1,
getFacade().getStereotypes(fooClass).size());
// save the project
File file = getFileInTestDir(
"testProjectWithUserDefinedProfilePersistency.zargo");
AbstractFilePersister persister = saveProject(project, file);
project.remove();
// load the project
project = persister.doLoad(file);
project.postLoad();
// assert that the model element that depends on the profile is
// consistent
fooClass = project.findType(
"testProjectWithUserDefinedProfilePersistency-class", false);
assertNotNull(fooClass);
Collection fooStereotypes = getFacade().getStereotypes(fooClass);
assertEquals(1, fooStereotypes.size());
assertEquals(ProfileMother.STEREOTYPE_NAME_ST,
getFacade().getName(fooStereotypes.iterator().next()));
}
/**
* WARNING: not a unit test, this is more like a functional test, where
* several subsystems are tested.
*
* This test does:
* <ol>
* <li>setup a user defined profile</li>
* <li>add it to the project configuration</li>
* <li>create a dependency between the project's model and the user
* defined profile</li>
* <li>save the project</li>
* <li>remove the directory where the user defined profile was stored in
* order to test the handling of opening a zargo without the user defined
* profile</li>
* <li>initialize the model and profile subsystems to simulate a fresh
* ArgoUML session</li>
* <li>load the project and assert that the model element that depends on
* the profile is consistent</li>
* </ol>
*
* @throws Exception when things go wrong
*/
public void testProjectWithRemovedUserDefinedProfilePersistency()
throws Exception {
final String testName =
"testProjectWithRemovedUserDefinedProfilePersistency";
File userDefinedProfileFile = createUserProfileFile(testCaseDir,
testName + "-TestUserProfile.xmi");
// add it to the project configuration
ProfileManager profileManager = ProfileFacade.getManager();
Profile userDefinedProfile =
new UserDefinedProfile(userDefinedProfileFile, profileManager);
profileManager.registerProfile(userDefinedProfile);
profileManager.addSearchPathDirectory(testCaseDir.getAbsolutePath());
Project project = ProjectManager.getManager().makeEmptyProject();
Object model = project.getUserDefinedModelList().get(0);
// create a dependency between the project's model and the user defined
// profile
project.getProfileConfiguration().addProfile(userDefinedProfile, model);
final String className = "Foo4" + testName;
Object fooClass = getCoreFactory().buildClass(className, model);
Collection stereotypes = getExtensionMechanismsHelper().getStereotypes(
project.getModels());
Object stStereotype = null;
for (Object stereotype : stereotypes) {
if (ProfileMother.STEREOTYPE_NAME_ST.equals(
getFacade().getName(stereotype))) {
stStereotype = stereotype;
break;
}
}
Model.getCoreHelper().addStereotype(fooClass, stStereotype);
// save the project
File file = getFileInTestDir(testName + ".zargo");
AbstractFilePersister persister = saveProject(project, file);
// remove the user defined profile and the directory where it is
profileManager.removeProfile(userDefinedProfile);
profileManager.removeSearchPathDirectory(testCaseDir.getAbsolutePath());
// initialize the model and profile subsystems to simulate a fresh
// ArgoUML session
InitializeModel.initializeMDR();
new InitProfileSubsystem().init();
try {
project = persister.doLoad(file);
fail("Failed to throw exception for missing user defined profile");
} catch (OpenException e) {
// Success - expected exception
Throwable cause = e.getCause();
assertTrue("Cause isn't of one of the expected types.",
cause instanceof XmiReferenceRuntimeException
|| cause instanceof XmiReferenceException);
}
}
/**
* @param project the ArgoUML {@link Project} to save in file.
* @param file the {@link File} in which an ArgoUML {@link Project} will
* be persisted.
* @return the persister used and usable for file.
* @throws SaveException if saving the file goes wrong.
* @throws InterruptedException if an interrupt occurs while saving.
* TODO: move this to an helper class.
*/
public static AbstractFilePersister saveProject(Project project, File file)
throws SaveException, InterruptedException {
AbstractFilePersister persister = getProjectPersister(file);
project.setVersion(ApplicationVersion.getVersion());
persister.save(project, file);
return persister;
}
/**
* Get an {@link AbstractFilePersister} for file.
*
* @param file the {@link File} in which an ArgoUML {@link Project} will
* be persisted.
* @return the appropriate persister for file or null if the file's
* extension doesn't match a supported persister.
* TODO: move this to an helper class.
*/
public static AbstractFilePersister getProjectPersister(File file) {
AbstractFilePersister persister =
PersistenceManager.getInstance().getPersisterFromFileName(
file.getAbsolutePath());
return persister;
}
/**
* Initialize the ArgoUML application version, so that
* {@link ApplicationVersion#getVersion()} doesn't return null.
*
* @throws Exception if something goes wrong...
* TODO: move this to an helper class.
*/
@SuppressWarnings("unchecked")
public static void initAppVersion() throws Exception {
if (ApplicationVersion.getVersion() == null) {
Class argoVersionClass =
Class.forName("org.argouml.application.ArgoVersion");
Method initMethod = argoVersionClass.getDeclaredMethod("init");
initMethod.setAccessible(true);
initMethod.invoke(null);
}
}
private File createUserProfileFile(File directory, String filename)
throws IOException {
ProfileMother mother = new ProfileMother();
Object profileModel = mother.createSimpleProfileModel();
Model.getCoreHelper().setName(profileModel, filename);
File userDefinedProfileFile = new File(directory, filename);
mother.saveProfileModel(profileModel, userDefinedProfileFile);
// Clean up after ourselves by deleting profile model
Model.getUmlFactory().delete(profileModel);
return userDefinedProfileFile;
}
}