All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.eugene.models.object.xml.ObjectModelImpl Maven / Gradle / Ivy

/*
 * #%L
 * EUGene :: EUGene
 * 
 * $Id: ObjectModelImpl.java 863 2010-04-15 14:22:49Z tchemit $
 * $HeadURL: http://svn.nuiton.org/svn/eugene/tags/eugene-2.0.2/eugene/src/main/java/org/nuiton/eugene/models/object/xml/ObjectModelImpl.java $
 * %%
 * Copyright (C) 2004 - 2010 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

package org.nuiton.eugene.models.object.xml;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelClassifier;
import org.nuiton.eugene.models.object.ObjectModelEnumeration;
import org.nuiton.eugene.models.object.ObjectModelInterface;

/**
 * Implementation class for the root node abstraction of object model trees.
 * This an entry point for browsing a model tree. This object offers as well
 * several facilities for a direct access to some of the object model elements.
 * In this concrete class, the tree is build by parsing an object model xml
 * description using lutinxml XMLObjectParser.
 * 
 * Created: 14 janv. 2004
 *
 * @author Cédric Pineau 
 * Copyright Code Lutin
 * @version $Revision: 863 $
 *
 * Last update : $Date: 2010-04-15 16:22:49 +0200 (jeu., 15 avril 2010) $
 * by : *
 * @plexus.component role="org.nuiton.eugene.models.Model" role-hint="objectmodel"
 */
public class ObjectModelImpl implements ObjectModel {
    /**
     * logger
     */
    private static final Log log = LogFactory.getLog(ObjectModelImpl.class);
    protected String name;
    protected String version;
    protected Map classes = new HashMap();
    protected Map interfaces = new HashMap();
    protected Map classifiers = new HashMap();
    protected Map enumerations = new HashMap();
    protected List comments = new ArrayList();
    private Map tagValues = new HashMap();

    /**
     * Used to add others specific object to the model
     * The key defined must be unique to get the significative extension associated to
     */
    private Map extensions = new HashMap();

    public void setName(String name) {
        this.name = name;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @Override
    public String getVersion() {
        return version;
    }

    public void addClass(ObjectModelClassImpl clazz) {
        //if (clazz == null)
        //    return new ObjectModelClassImpl(this, null);
        clazz.postInit();
        clazz.setObjectModelImpl(this);

        if (!clazz.isExtern()) {
            ObjectModelElementImpl initialElement = (ObjectModelElementImpl) classes.get(clazz.getQualifiedName());
            if (initialElement == null) {
                classes.put(clazz.getQualifiedName(), clazz);
                classifiers.put(clazz.getQualifiedName(), clazz);
            } else {
                if (!(initialElement instanceof ObjectModelClassImpl)) {
                    throw new IllegalArgumentException(
                            "\"" + clazz + "\" is incompatible with already defined element \"" + initialElement + "\"");
                }
                ObjectModelClassImpl initialClazz = (ObjectModelClassImpl) initialElement;

                // La classe existe déjà. On va prendre tout ce que contient la
                // nouvelle classe et l'ajouter à la précédente si nécessaire.

                mergeClasses(initialClazz, clazz);
//                clazz = initialClazz;
            }
        }
        //return clazz;
    }

    public void addAssociationClass(ObjectModelAssociationClassImpl clazz) {
        //if (clazz == null)
        //    return new ObjectModelAssociationClassImpl(this, null);
        clazz.postInit();
        clazz.setObjectModelImpl(this);

        if (!clazz.isExtern()) {
            ObjectModelElementImpl initialElement = (ObjectModelElementImpl) classes.get(clazz.getQualifiedName());
            if (initialElement == null) {
                classes.put(clazz.getQualifiedName(), clazz);
                classifiers.put(clazz.getQualifiedName(), clazz);
            } else {
                if (!(initialElement instanceof ObjectModelAssociationClassImpl)) {
                    throw new IllegalArgumentException(
                            "\"" + clazz + "\" is incompatible with already defined element \"" + initialElement + "\"");
                }
                ObjectModelAssociationClassImpl initialClazz = (ObjectModelAssociationClassImpl) initialElement;

                mergeAssociationClasses(initialClazz, clazz);
//                clazz = initialClazz;
            }
        }
        //return clazz;
    }

    public void addComment(String comment) {
        comments.add(comment);
    }

    /**
     * Returns the name of this model.
     * 
     * @return the name of this model.
     */
    @Override
    public String getName() {
        return name;
    }

    /**
     * Returns all classifiers defined in this model.
     * 
     * @see ObjectModelClassifier
     * 
     * @return a Collection containing all ObjectModelClassifier for this model.
     */
    @Override
    public Collection getClassifiers() {
        return classifiers.values();
    }

    /**
     * Returns the classifier corresponding to the given qualified name, or null
     * if the model contains no classifier for this qualified name.
     * 
     * @param qualifiedClassifierName -
     *            the qualified name of the classifier to retrieve.
     * 
     * @return the ObjectModelClassifier of the found classifier, or null if the
     *         model contains no classifier for this qualified name.
     */
    @Override
    public ObjectModelClassifier getClassifier(String qualifiedClassifierName) {
        return qualifiedClassifierName == null ? null
                : classifiers.get(qualifiedClassifierName);
    }

    /**
     * Returns all classes defined in this model.
     * 
     * @see ObjectModelClass
     * 
     * @return a Collection containing all ObjectModelClass for this model.
     */
    @Override
    public Collection getClasses() {
        return classes.values();
    }

    /**
     * Returns the class corresponding to the given qualified name, or null if
     * the model contains no class for this qualified name.
     * 
     * @param qualifiedClassName -
     *            the qualified name of the class to retrieve.
     * 
     * @return the ObjectModelClass of the found class, or null if the model
     *         contains no class for this qualified name.
     */
    @Override
    public ObjectModelClass getClass(String qualifiedClassName) {
        if (qualifiedClassName == null) {
            return null;
        }
        if (!hasClass(qualifiedClassName)) {
            if (log.isDebugEnabled()) {
                log.debug("Class " + qualifiedClassName + " not found in model");
            }
            return null;
        }
        return classes.get(qualifiedClassName);
    }

    @Override
    public boolean hasClass(String qualifiedClassName) {
        boolean hasClass = classes.containsKey(qualifiedClassName);
        return hasClass;
    }

    public void addInterface(ObjectModelInterfaceImpl interfacez) {
        //if (interfacez == null)
        //    return new ObjectModelInterfaceImpl(this, null);
        interfacez.postInit();
        interfacez.setObjectModelImpl(this);

        if (!interfacez.isExtern()) {
            ObjectModelElementImpl initialElement = (ObjectModelElementImpl) interfaces.get(interfacez.getQualifiedName());
            if (initialElement == null) {
                interfaces.put(interfacez.getQualifiedName(), interfacez);
                classifiers.put(interfacez.getQualifiedName(), interfacez);
            } else {
                if (!(initialElement instanceof ObjectModelInterfaceImpl)) {
                    throw new IllegalArgumentException(
                            "\"" + interfacez + "\" is incompatible with already defined element \"" + initialElement + "\"");
                }
                ObjectModelInterfaceImpl initialInterfacez = (ObjectModelInterfaceImpl) initialElement;

                mergeClassifiers(initialInterfacez, interfacez);
//                interfacez = initialInterfacez;
            }
        }
        //return interfacez;
    }

    /**
     * Returns the interface corresponding to the given qualified name, or null
     * if the model contains no interface for this qualified name.
     * 
     * @param qualifiedInterfaceName -
     *            the qualified name of the interface to retrieve.
     * 
     * @return the ObjectModelInterface of the found interface, or null if the
     *         model contains no interface for this qualified name.
     */
    @Override
    public ObjectModelInterface getInterface(String qualifiedInterfaceName) {
        ObjectModelInterface result = interfaces.get(qualifiedInterfaceName);
        if (result == null && log.isDebugEnabled()) {
            log.debug("Interface " + qualifiedInterfaceName + " not found in model");
        }
        return result;
    }

    /**
     * Returns all interfaces defined in this model.
     * 
     * @see ObjectModelInterface
     * 
     * @return a Collection containing all ObjectModelInterface for this model.
     */
    @Override
    public Collection getInterfaces() {
        return interfaces.values();
    }

    public void addEnumeration(ObjectModelEnumerationImpl enumeration) {
        enumeration.postInit();
        enumeration.setObjectModelImpl(this);
        classifiers.put(enumeration.getQualifiedName(), enumeration);
        enumerations.put(enumeration.getQualifiedName(), enumeration);
    }

    @Override
    public Collection getEnumerations() {
        return enumerations.values();
    }

    @Override
    public ObjectModelEnumeration getEnumeration(String qualifiedEnumerationName) {
        ObjectModelEnumeration result = enumerations.get(qualifiedEnumerationName);
        if (result == null && log.isDebugEnabled()) {
            log.debug("Enumeration " + qualifiedEnumerationName + " not found in model");
        }
        return result;
    }

    /**
     * Returns all comments not lied to a particular model element
     * 
     * @return a List containing all comments for this model as Strings.
     */
    @Override
    public List getComments() {
        return comments;
    }

    protected void mergeClassifiers(
            ObjectModelClassifierImpl initialClazzifier,
            ObjectModelClassifierImpl additionalClazzifier) {
        Iterator it;

        // On n'utilise pas les parsetXXX puisque les post-init sont censés être
        // déjà faits...

        // System.out.println("Doc initial : " +
        // initialClazzifier.documentation);
        // System.out.println("Doc additional : " +
        // additionalClazzifier.documentation);
        String description = "";
        String sourceDoc = "";
        if (initialClazzifier.documentation != null) {
            description += initialClazzifier.getDescription();
            if (initialClazzifier.documentation.contains("--")) {
                sourceDoc += initialClazzifier.getSourceDocumentation();
            }
        }
        if (additionalClazzifier.documentation != null) {
            if (!description.equals("")) {
                description += " - ";
            }
            description += additionalClazzifier.getDescription();
            if (additionalClazzifier.documentation.contains("--")) {
                if (!sourceDoc.equals("")) {
                    sourceDoc += " - ";
                }
                sourceDoc += additionalClazzifier.getSourceDocumentation();
            }
        }
        if (!description.equals("") || !sourceDoc.equals("")) {
            initialClazzifier.documentation = description + "--" + sourceDoc;
        }
        // System.out.println("Doc after : " + initialClazzifier.documentation);

        for (it = additionalClazzifier.interfacesRefs.iterator(); it.hasNext();) {
            ObjectModelImplRef interfaceRef = (ObjectModelImplRef) it.next();
            if (!contains(initialClazzifier.interfacesRefs, interfaceRef)) {
                initialClazzifier.interfacesRefs.add(interfaceRef);
            }
            initialClazzifier.interfaces = null; // On force ainsi à
            // regénérer l'objet
        }
        for (it = additionalClazzifier.getOperations().iterator(); it.hasNext();) {
            ObjectModelOperationImpl operation = (ObjectModelOperationImpl) it.next();
            if (!contains(initialClazzifier.getOperations(), operation)) {
                initialClazzifier.operations.add(operation);
            }
        }
        for (it = additionalClazzifier.getComments().iterator(); it.hasNext();) {
            String comment = (String) it.next();
            if (!initialClazzifier.comments.contains(comment)) {
                initialClazzifier.comments.add(comment);
            }
        }
        for (it = additionalClazzifier.getStereotypes().iterator(); it.hasNext();) {
            String stereotype = (String) it.next();
            if (!initialClazzifier.getStereotypes().contains(stereotype)) {
                initialClazzifier.stereotypes.add(stereotype);
            }
        }

        for (it = additionalClazzifier.getTagValues().keySet().iterator(); it.hasNext();) {
            String tagName = (String) it.next();
            if (!initialClazzifier.getTagValues().containsKey(tagName)) {
                initialClazzifier.tagValues.put(tagName, additionalClazzifier.getTagValue(tagName));
            }
        }
    }

    /**
     * This method takes two ObjectModelClassImpl and merges both of them in the
     * first one
     * 
     * @param initialClazz
     *            the instance of ObjectModelClassImpl to be modified
     * @param additionalClazz
     *            the instance of ObjectModelClassImpl tu be used for merging
     */
    private void mergeClasses(ObjectModelClassImpl initialClazz,
            ObjectModelClassImpl additionalClazz) {
        Iterator it;
        mergeClassifiers(initialClazz, additionalClazz);

        for (it = additionalClazz.getAttributes().iterator(); it.hasNext();) {
            ObjectModelAttributeImpl attribute = (ObjectModelAttributeImpl) it.next();
            if (!contains(initialClazz.getAttributes(), attribute)) {
                initialClazz.attributes.put(attribute.getName(), attribute);
                initialClazz.orderedAttributes.add(attribute);
            }
        }
        for (it = additionalClazz.superclassesRefs.iterator(); it.hasNext();) {
            ObjectModelImplRef superclassRef = (ObjectModelImplRef) it.next();
            if (!contains(initialClazz.superclassesRefs, superclassRef)) {
                initialClazz.superclassesRefs.add(superclassRef);
            }
            initialClazz.superclasses = null; // On force ainsi à regénérer
            // l'objet
        }
    }

    private void mergeAssociationClasses(
            ObjectModelAssociationClassImpl initialAssocClazz,
            ObjectModelAssociationClassImpl additionalAssocClazz) {
        mergeClasses(initialAssocClazz, additionalAssocClazz);
        Iterator it;
        for (it = additionalAssocClazz.participantsRefs.iterator(); it.hasNext();) {
            ObjectModeImplAssociationClassParticipant participant = (ObjectModeImplAssociationClassParticipant) it.next();
            if (!contains(initialAssocClazz.participantsRefs, participant)) {
                initialAssocClazz.participantsRefs.add(participant);
            }
            initialAssocClazz.participantsAttributes = null; // On force
            // ainsi à
            // regénérer
            // l'objet
            initialAssocClazz.participantsClassifiers = null; // On force
            // ainsi à
            // regénérer
            // l'objet
        }
    }

    private boolean contains(Collection coll,
            ObjectModelAttributeImpl toFind) {
        for (ObjectModelAttribute attribute : coll) {
            if (attribute.getName().equals(toFind.getName())) { // Seul le nom
                // de l'attribut
                // compte
                return true;
            }
        }
        return false;
    }

    private boolean contains(Collection coll, ObjectModelOperationImpl toFind) {
        return coll.contains(toFind); // Le equals(...) de
        // ObjectModelOperationImpl convient
    }

    private boolean contains(Collection coll, ObjectModelImplRef toFind) {
        return coll.contains(toFind); // Le equals(...) de ObjectModelImplRef
        // convient
    }

    public ObjectModelImplTagValue addTagValue(ObjectModelImplTagValue tagValue) {
        if (tagValue == null) {
            return new ObjectModelImplTagValue();
        }
        tagValues.put(tagValue.getName(), tagValue.getValue());
        return tagValue;
    }

    /**
     * Returns the tagValues associated with this element. For each entry, the
     * key is the name of the tagValue, the value is the value of the tagValue
     * :-)
     * 
     * @return a Map containing all tagValues associated with this element
     */
    @Override
    public Map getTagValues() {
        return tagValues;
    }

    /**
     * Returns the tagValue corresponding to the given name, or null if the
     * element has no associated tagValue for this name.
     * 
     * @return the value of the found tagValue, or null if the element has no
     *         associated tagValue for this name.
     */
    @Override
    public String getTagValue(String tagValue) {
        return tagValue == null ? null : tagValues.get(tagValue);
    }

    /**
     * Get the extension associated to the reference (unique). Create it if not exist.
     * @param  object type returned
     * @param reference unique corresponding to the extension to get
     * @param extensionClass class of the extension
     * @return the object value for the extension
     * @throws ClassCastException when extensionClass is not valid
     * @throws RuntimeException when instantiation problem to create new extension
     */
    @Override
    @SuppressWarnings("unchecked")
    public  O getExtension(String reference, Class extensionClass) throws RuntimeException {
        if (reference == null) {
            throw new NullPointerException("reference parameter can not be null in method ObjectModelImpl#getExtension");
        }
        if (extensionClass == null) {
            throw new NullPointerException("extensionClass parameter can not be null in method ObjectModelImpl#getExtension.");
        }
        Object object = extensions.get(reference);
        O result;
        if (object != null && !extensionClass.isAssignableFrom(object.getClass())) {
            throw new ClassCastException("Invalid cast for " + extensionClass.getName());
        }
        if (object == null) {
            try {
                result = extensionClass.newInstance();
            } catch (Exception eee) { // IllegalAccessException and InstantiationException
                throw new RuntimeException("Unable to create new extension '" +extensionClass.getName() +
                        "' for '" + reference + "'", eee);
            }
            extensions.put(reference, result);
        } else {
            result = (O)object;
        }
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy