/* $Id: NotationProviderFactory2.java 18852 2010-11-20 19:27:11Z mvw $
*****************************************************************************
* 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:
* Michiel van der Wulp
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 2005-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.notation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
/**
* The NotationProviderFactory2 is a singleton,
* since it is the accesspoint for all Figs
* to access the textual representation of modelobjects,
* and since plugin modules can add extra languages.
*
* @author Michiel
*/
public final class NotationProviderFactory2 {
private static final Logger LOG =
Logger.getLogger(NotationProviderFactory2.class);
/**
* TYPE_NAME the name of the modelelement, e.g. class, package, state
*/
public static final int TYPE_NAME = 1;
/**
* TYPE_TRANSITION the main text shown above the transition.
*/
public static final int TYPE_TRANSITION = 2;
/**
* TYPE_STATEBODY the multiline text shown inside the state body.
*/
public static final int TYPE_STATEBODY = 3;
/**
* TYPE_ACTIONSTATE the text shown in an actionstate.
*/
public static final int TYPE_ACTIONSTATE = 4;
/**
* TYPE_ATTRIBUTE the text shown in a attribute compartment (1 attrib only).
*/
public static final int TYPE_ATTRIBUTE = 5;
/**
* TYPE_OPERATION the text shown in a operation compartment (1 oper only).
*/
public static final int TYPE_OPERATION = 6;
/**
* TYPE_OBJECT the text shown on an object.
*/
public static final int TYPE_OBJECT = 7;
/**
* TYPE_COMPONENTINSTANCE the text shown on a componentInstance.
*/
public static final int TYPE_COMPONENTINSTANCE = 8;
/**
* TYPE_NODEINSTANCE the text shown on a componentInstance.
*/
public static final int TYPE_NODEINSTANCE = 9;
/**
* TYPE_TYPE_OBJECTFLOWSTATE_TYPE the text shown on a
* objectflowstate's type, i.e. its classifier name.
*/
public static final int TYPE_OBJECTFLOWSTATE_TYPE = 10;
/**
* TYPE_OBJECTFLOWSTATE_STATE the text shown on a
* objectflowstate's state.
*/
public static final int TYPE_OBJECTFLOWSTATE_STATE = 11;
/**
* TYPE_CALLSTATE the text shown on a
* callstate's state.
*/
public static final int TYPE_CALLSTATE = 12;
/**
* TYPE_CLASSIFIERROLE the text shown on a
* classifierrole.
*/
public static final int TYPE_CLASSIFIERROLE = 13;
/**
* TYPE_MESSAGE the text shown on a Message
* in a Collaborations diagram.
*/
public static final int TYPE_MESSAGE = 14;
/**
* TYPE_EXTENSION_POINT the text shown on a usecase
* representing the extensionpoint.
*/
public static final int TYPE_EXTENSION_POINT = 15;
/**
* The text shown at the association end that represents the role.
*/
public static final int TYPE_ASSOCIATION_END_NAME = 16;
/**
* The text shown for the association role name.
*/
public static final int TYPE_ASSOCIATION_ROLE = 17;
/**
* The text shown for the association role name.
*/
public static final int TYPE_ASSOCIATION_NAME = 18;
/**
* The text shown for a multiplicity.
*/
public static final int TYPE_MULTIPLICITY = 19;
/**
* The text shown for an enumeration literal.
*/
public static final int TYPE_ENUMERATION_LITERAL = 20;
/**
* TYPE_MESSAGE the text shown on a Message
* in a Collaborations diagram.
*/
public static final int TYPE_SD_MESSAGE = 21;
/**
* defaultLanguage the Notation language used by default, i.e. UML
*/
private NotationName defaultLanguage;
/**
* allLanguages is a HashMap with as key the notationName,
* and as value a second HashMap. This latter HashMap has as key the "type"
* converted to Integer, and as value the provider (NotationProvider).
*/
private Map<NotationName, Map<Integer, Class>> allLanguages;
/**
* The instance is the singleton.
*/
private static NotationProviderFactory2 instance;
/**
* The constructor.
*/
private NotationProviderFactory2() {
super();
allLanguages = new HashMap<NotationName, Map<Integer, Class>>();
}
/**
* @return returns the singleton instance
*/
public static NotationProviderFactory2 getInstance() {
if (instance == null) {
instance = new NotationProviderFactory2();
}
return instance;
}
/**
* Get a NotationProvider for the current project.
* <p>
* If there is any reason for failure, null is returned - no
* exception is thrown.
* The caller is supposed to deal with receiving null.
* <p>
* Use this function when you do not want to monitor model
* changes which may cause the string to change.
*
* @param type the provider type
* @param object the constructor parameter
* @param name the name of the notation language to use
* @return the provider, or null if there was any failure
*/
public NotationProvider getNotationProvider(int type,
Object object, NotationName name) {
Class clazz = getNotationProviderClass(type, name);
if (clazz != null) {
try {
Class[] cp = {Object.class};
Constructor constructor = clazz.getConstructor(cp);
Object[] params = {
object,
};
return (NotationProvider) constructor.newInstance(params);
} catch (SecurityException e) {
// TODO: Why aren't we throwing an exception here?
// Returning null results in NPE and no explanation why.
LOG.error("Exception caught", e);
} catch (NoSuchMethodException e) {
// TODO: Why aren't we throwing an exception here?
// Returning null results in NPE and no explanation why.
LOG.error("Exception caught", e);
} catch (IllegalArgumentException e) {
// TODO: Why aren't we throwing an exception here?
// Returning null results in NPE and no explanation why.
LOG.error("Exception caught", e);
} catch (InstantiationException e) {
// TODO: Why aren't we throwing an exception here?
// Returning null results in NPE and no explanation why.
LOG.error("Exception caught", e);
} catch (IllegalAccessException e) {
// TODO: Why aren't we throwing an exception here?
// Returning null results in NPE and no explanation why.
LOG.error("Exception caught", e);
} catch (InvocationTargetException e) {
// TODO: Why aren't we throwing an exception here?
// Returning null results in NPE and no explanation why.
LOG.error("Exception caught", e);
}
}
return null;
}
/**
* Get a NotationProvider for the current project.
* This also initializes the listeners.
* <p>
* Use this function when you want to monitor model
* changes which may cause the string to change.
*
* @param type the provider type
* @param object the constructor parameter
* @param nr the fig that refreshes after the NotationProvider has changed
* @param name the name of the notation language to use
* @return the provider
*/
public NotationProvider getNotationProvider(int type,
Object object, NotationRenderer nr,
NotationName name) {
NotationProvider p = getNotationProvider(type, object, name);
p.setRenderer(nr);
p.initialiseListener(object);
return p;
}
/**
* This function looks for the requested notation provider type.
* It is guaranteed to deliver:<ul>
* <li>the requested type of the requested notation language,
* <li>the requested type of the default notation, or
* <li><code>null</code>.
* </ul>
*
* @param type the provider type
* @param name the context (i.e. the notation name)
* @return the provider
*/
private Class getNotationProviderClass(int type, NotationName name) {
if (allLanguages.containsKey(name)) {
Map<Integer, Class> t = allLanguages.get(name);
if (t.containsKey(Integer.valueOf(type))) {
return t.get(Integer.valueOf(type));
}
}
Map<Integer, Class> t = allLanguages.get(defaultLanguage);
if (t != null && t.containsKey(Integer.valueOf(type))) {
return t.get(Integer.valueOf(type));
}
return null;
}
/**
* @param type the provider type
* @param notationName the name of the notation (language)
* @param provider the provider
*/
public void addNotationProvider(int type,
NotationName notationName, Class provider) {
if (allLanguages.containsKey(notationName)) {
Map<Integer, Class> t = allLanguages.get(notationName);
t.put(Integer.valueOf(type), provider);
} else {
Map<Integer, Class> t = new HashMap<Integer, Class>();
t.put(Integer.valueOf(type), provider);
allLanguages.put(notationName, t);
}
}
/**
* @param notationName the UML notation that is to be used as default
* if no other is found
*/
public void setDefaultNotation(NotationName notationName) {
if (allLanguages.containsKey(notationName)) {
defaultLanguage = notationName;
}
}
/**
* We need this to remove modules.
*
* @param notationName the notation to be removed
* @return true if the notation was removed
*/
public boolean removeNotation(NotationName notationName) {
if (defaultLanguage == notationName) {
return false;
}
if (allLanguages.containsKey(notationName)) {
return allLanguages.remove(notationName) != null
&& Notation.removeNotation(notationName);
}
return false;
}
}