alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.lib.jmi.xmi;

import java.io.*;
import java.util.*;
import java.net.URL;

import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import org.netbeans.lib.jmi.util.DebugException;
import org.netbeans.api.xmi.*;

import javax.jmi.reflect.*;
import javax.jmi.model.*;
import org.netbeans.lib.jmi.util.Logger;

public class WriterBase extends XMIWriter {

    private static final String XMI_VERSION = "1.2";
    public static final String EXPORTER_NAME = "Netbeans XMI Writer";
    public static final String EXPORTER_VERSION = "1.0";

    public static final int ATTR_HREF = 0;
    public static final int ATTR_XMI_ID = 1;
    public static final int ATTR_XMI_IDREF = 2;
    
    public static final char HREF_DELIMITER = '#';    

    // variables ................................................................

    // content handler used to produce XMI
    protected ContentHandler contentHandler;
    // output config    
    protected OutputConfig configuration;
    // header provider
    protected XMIHeaderProvider headerProvider = null;
    // xmi reference provider
    protected XMIReferenceProvider provider;
    // default xmi reference provider
    protected XMIReferenceProvider defaultProvider = new DefaultProvider ();
    // encoding to be used
    protected String encoding = null;
    // attributes added for currently processed element
    protected AttributesImpl attributes;
    // system id of the document the writer writes in or null if it is not known
    protected String thisSystemId = null;
    // name of the currently processed element
    protected String elementName;
    // indicates if some element is being currently processed
    protected boolean elementStarted;
    
    protected OutputStreamWriter stream;
    // temp variable storing passed OutputStream parameter to be used by init () method
    protected OutputStream outputStream = null;

    // known namespaces
    protected HashMap namespaces;

    // stores objects to be written having immediate composite serialized in some external document
    protected List lightOutermosts;
    // stores all currently written components
    protected Set writtenComponents;
    // used to detect components that stay unwritten because of presence of composite associations with ends that are not visible via references
    protected Set nonWrittenComponents;
    // stores all instances having already generated xmi id (RefObject - key, String - value)
    protected HashMap xmiIds;
    // counts the number of all serialized instances
    protected int instancesCounter = 0;

    /* Serves to record already processed packages (when contents of packages are processed
     * recursive - see writePackage, writeAssociations, writeStaticAttributes and findNamespaces
     * methods) to avoid multiple searching trough a package.
     */
    protected HashSet processedPackages;

    // caches storing instance-scoped and class-scoped attributes and references
    protected HashMap instanceAttributes_cache;
    protected HashMap classAttributes_cache;
    protected HashMap references_cache;

    // cache storing structures' fields
    protected HashMap structureFields_cache;
    // cache storing enum prefixes specified by a tag attached to EnumerationType
    protected HashMap labelPrefix_cache;

    // indicates if the method writing Collection of RefObjects is called or not
    protected boolean collectionWriting = false;
    // set and list of outermost composite objects to be write by write(Collection) method
    protected Set objectsToWrite = null;
    protected List objectsToWriteAsCollection = null;

    // init .....................................................................

    public WriterBase() {
        configuration = new OutputConfig ();
    }

    public WriterBase(XMIOutputConfig config) {
        configuration = new OutputConfig ();
        configuration.setReferenceProvider (config.getReferenceProvider ());
        if (config instanceof OutputConfig) {
            configuration.setHeaderProvider (((OutputConfig) config).getHeaderProvider());
            configuration.setEncoding (((OutputConfig) config).getEncoding());
        }
    }
    
    public void init () throws IOException {
        collectionWriting = false;

        attributes = new AttributesImpl ();

        namespaces = new HashMap ();
        xmiIds = new HashMap ();        
        nonWrittenComponents = new HashSet ();
        writtenComponents = new HashSet ();
        processedPackages = new HashSet ();
        instancesCounter = 0;
        instanceAttributes_cache = new HashMap ();
        classAttributes_cache = new HashMap ();
        references_cache = new HashMap ();
        structureFields_cache = new HashMap ();
        labelPrefix_cache = new HashMap ();
    
        lightOutermosts = new LinkedList ();
        if (configuration == null) {
            provider = defaultProvider;
        } else {
            provider = configuration.getReferenceProvider ();            
            if (provider == null)
                provider = defaultProvider;
            if (configuration instanceof OutputConfig) {
                headerProvider = ((OutputConfig) configuration).getHeaderProvider ();
                encoding = ((OutputConfig) configuration).getEncoding ();
            }
        }
        
        if (outputStream != null) {
            try {
                if (encoding == null) {
                    stream = new OutputStreamWriter (outputStream);
                } else {
                    stream = new OutputStreamWriter (outputStream, encoding);
                }
                contentHandler = new DefaultWriter (stream, encoding);
                // clear outputStream variable
                outputStream = null;
            } catch (UnsupportedEncodingException e) {
                throw new IOException ("Unsupported encoding: " + encoding);
            }
        } // if
    }

    // javax.jmi.xmi.XmiWriter interface implementation .........................

    public void write (OutputStream os, RefPackage extent, String xmiVersion) throws IOException {
        write (os, null, extent, xmiVersion);
    }

    public void write (OutputStream os, Collection objects, String xmiVersion) throws IOException {
        write (os, null, objects, xmiVersion);
    }

    public void write(OutputStream stream, RefPackage extent) {
        try {
            write(stream, extent, null);
        } catch (IOException e) {
            DebugException ne = new DebugException(e.toString());
            Logger.getDefault().annotate(ne, e);
            throw ne;
        }
    }

    // org.netbeans.api.xmi.XMIWriter implmentation .............................
        
    public XMIOutputConfig getConfiguration() {
        return configuration;
    }
        
    public void write(OutputStream stream, String uri, RefPackage extent, String xmiVersion) throws IOException {
        thisSystemId = uri;        
        outputStream = stream;
        write (extent);
    }
        
    public void write(OutputStream stream, String uri, Collection objects, String xmiVersion) throws IOException {
        thisSystemId = uri;
        outputStream = stream;
        write (objects);
    }
    
    // ..........................................................................
    
    public void write(ContentHandler handler, String uri, RefPackage extent, String xmiVersion) throws IOException {
        thisSystemId = uri;
        contentHandler = handler;
        write (extent);
    }
        
    public void write(ContentHandler handler, String uri, Collection objects, String xmiVersion) throws IOException {
        thisSystemId = uri;
        contentHandler = handler;
        write (objects);
    }
    
    public void write (RefPackage extent) throws IOException {
        Logger.getDefault().log("XMI writer started");
        long time = System.currentTimeMillis ();
        init ();        
        processedPackages.clear ();
        findNamespaces (extent);
        writeDocument (extent);        
        time = System.currentTimeMillis () - time;
        Logger.getDefault().log("finished, TIME: " + time/1000.0 + "[s]");
    }

    public void write (Collection objects) throws IOException {
        init ();
        //
        collectionWriting = true;
        //
        processedPackages.clear ();
        RefPackage extent;
        objectsToWrite = new HashSet ();
        objectsToWriteAsCollection = new LinkedList ();
        Set tempSet = new HashSet ();
        if ((objects == null) || (objects.size () == 0)) {
            extent = null;
        } else {
            Iterator iter = objects.iterator ();
            while (iter.hasNext ()) {
                Object obj = iter.next ();
                if (!(obj instanceof RefObject))
                    throw new DebugException ("Bad object (not instance of RefObject) in input collection: " + obj.getClass ().getName ());
                tempSet.add (obj);
            } // while
            iter = objects.iterator ();
            RefFeatured featured;
            RefObject container;
            while (iter.hasNext ()) {
                RefObject obj = (RefObject) iter.next ();
                container = obj;
                boolean found = false;
                do {
                    featured = container.refImmediateComposite ();
                    container = (featured instanceof RefObject) ? (RefObject) featured : null;
                    if ((container != null) && tempSet.contains (container)) {
                        found = true;
                        break;
                    }
                } while (container != null);
                if (!found) {
                    objectsToWrite.add (obj);
                    objectsToWriteAsCollection.add (obj);
                }
            } // while
            extent = ((RefObject) objectsToWriteAsCollection.get (0)).refOutermostPackage ();
            findNamespaces (extent);
        }
        writeDocument (extent);
    }
    
    // methods ..................................................................

    protected void findNamespaces (RefPackage pkg) {
        String name;
        Iterator iter;

        if (processedPackages.contains (pkg))
            return;

        MofPackage metaPackage = (MofPackage) pkg.refMetaObject ();
        name = getTagValue (metaPackage, XmiConstants.TAGID_XMI_NAMESPACE);
        if (name != null) {
            iter = metaPackage.getQualifiedName ().iterator ();
            String fqName = (String) iter.next ();
            while (iter.hasNext ())
                fqName = fqName.concat (XmiConstants.DOT_SEPARATOR).concat ((String) iter.next ());
            namespaces.put (fqName, name);
        }

        processedPackages.add (pkg);
        iter =  pkg.refAllPackages ().iterator ();
        while (iter.hasNext ()) {
            findNamespaces ((RefPackage) iter.next ());
        }
    }

    public static String getTagValue (ModelElement element, String tagId) {
        Collection tags = ((ModelPackage) element.refImmediatePackage()).
            getAttachesTo().getTag (element);
        Tag tag = null;
        for (Iterator it = tags.iterator(); it.hasNext();) {
            Object obj = it.next ();
            if (!(obj instanceof Tag))
                continue;
            Tag temp = (Tag) obj;
            if (tagId.equals (temp.getTagId ())) {
                tag = temp;
                break;
            }
        }
        if (tag == null)
            return null;
        Collection values = tag.getValues ();
        if (values.size () == 0)
            return null;
        return (String) values.iterator ().next ();
    }

    /**
     * Finds all attributes and references belonging to a mof class and caches them.
     */
    protected void cacheContainedElements (MofClass mofClass) {
        List temp = new LinkedList ();
        List superClasses = mofClass.allSupertypes ();
        Namespace namespace = null;
        Iterator it = superClasses.iterator ();
        while (it.hasNext ()) {
            namespace = (Namespace) it.next ();
            temp.addAll (namespace.getContents ());
        }
        temp.addAll (mofClass.getContents ());
        List instanceAttributes = new LinkedList ();
        List classAttributes = new LinkedList ();
        List references = new LinkedList ();
        Set referencedEnds = new HashSet ();
        it = temp.iterator ();
        while (it.hasNext ()) {
            RefObject refObject = (RefObject) it.next ();
            if (refObject instanceof Feature) {
                boolean instanceLevel = ((Feature) refObject).getScope ().equals (ScopeKindEnum.INSTANCE_LEVEL);
                if ((refObject instanceof Attribute) && (!((Attribute) refObject).isDerived ())) {
                    if (instanceLevel) {
                        instanceAttributes.add (refObject);
                    } else {
                        classAttributes.add (refObject);
                    }
                } else if (refObject instanceof Reference) {
                    AssociationEnd end = ((Reference) refObject).getReferencedEnd ();
                    Association assoc = (Association) end.getContainer ();
                    if (!assoc.isDerived () && !referencedEnds.contains (end)) {
                        references.add (refObject);
                        referencedEnds.add (end);
                    }
                } // else
            } // if (refObject instanceof Feature)
        } // while
        instanceAttributes_cache.put (mofClass, instanceAttributes);
        classAttributes_cache.put (mofClass, classAttributes);
        references_cache.put (mofClass, references);
    }

    /**
     * For a given mof class, returns list of all instance-scoped attributes
     * (references are not included).
     *
     * @param mofClass
     * @return list of all non-derived instance-scoped attributes (including inherited ones)
     */
    protected List instanceAttributes (MofClass mofClass) {
        List list = (List) instanceAttributes_cache.get (mofClass);
        if (list == null) {
            cacheContainedElements (mofClass);
            list = (List) instanceAttributes_cache.get (mofClass);
        }
        return list;
    }

    /**
     * For a given mof class, returns list of all class-scoped attributes.
     *
     * @param mofClass
     * @return list of all non-derived class-scoped attributes (including inherited ones)
     */
    protected List classAttributes (MofClass mofClass) {
        List list = (List) classAttributes_cache.get (mofClass);
        if (list == null) {
            cacheContainedElements (mofClass);
            list = (List) classAttributes_cache.get (mofClass);
        }
        return list;
    }

    /**
     * For a given mof class, returns list of all references.
     *
     * @param mofClass
     * @return list of all non-derived references (including inherited ones)
     */
    protected List references (MofClass mofClass) {
        List list = (List) references_cache.get (mofClass);
        if (list == null) {
            cacheContainedElements (mofClass);
            list = (List) references_cache.get (mofClass);
        }
        return list;
    }

    /**
     * Returns list of all fields belonging to the given StructureType.
     */
    public List structureFields (StructureType type) {
        List fields = (List) structureFields_cache.get (type);
        if (fields != null)
            return fields;
        // find fields and cache them
        fields = new LinkedList ();
        Iterator content = type.getContents ().iterator ();
        while (content.hasNext ()) {
            Object element = content.next ();
            if (element instanceof StructureField)
                fields.add (element);
        } // while
        structureFields_cache.put (type, fields);
        return fields;
    }

    /**
     * Returns labels prefix given by "unprefix" tag attached to EnumerationType or
     * the empty String if no such tag is present.
     */
    public String labelPrefix (EnumerationType type) {
        String prefix = (String) labelPrefix_cache.get (type);
        if (prefix != null)
            return prefix;
        prefix = getTagValue (type, XmiConstants.TAGID_XMI_ENUMERATION_UNPREFIX);
        if (prefix == null)
            prefix = "";
        labelPrefix_cache.put (type, prefix);
        return prefix;
    }

    // **************************************************************************
    // Methods related to writing to content handler.
    // **************************************************************************

    protected void startElement (String name) {
        if (elementStarted) {
            writeStartElement ();
        }
        elementName = name;
        elementStarted = true;
    }

    /**
     * Writes end of an XML element to the output stream.
     *
     * @param name name of the XML element to be written
     */
    protected void endElement (String name) {
        if (elementStarted) {
            writeStartElement ();
        }
        try {
            contentHandler.endElement (null, null, name);
        } catch (SAXException e) {
        }
    }

    /**
     * Writes an attribute of the currenly written XML elemnt to the output stream.
     *
     * @param name attribute name
     * @param value value of the attribute
     */
    protected void addAttribute (String name, String value) {
        attributes.addAttribute(null, null, name, null, value); // uri, localName, qName, type, value
    }

    /**
     * Writes characters into body of the currenly written XML elemnt.
     * Before the string is written, @link #replaceSpecialChars is called
     * on it to replace special XML characters.
     *
     * @param text string to be written
     */
    protected void characters (String text) {
        if (elementStarted) {
            writeStartElement ();
        }
        try {
            contentHandler.characters (text.toCharArray(), 0, text.length ());
        } catch (SAXException e) {
        }
    }

    protected void writeStartElement () {
        try {
            contentHandler.startElement (null, null, elementName, attributes);
        } catch (SAXException e) {
        }
        elementStarted = false;
        attributes.clear ();
    }

    // **************************************************************************

    /**
     * Checks if a given instance is already cached. In not, generates an xmi.id for it,
     * stores it in cache and returns the generated id, otherwise returns already stored id.
     */
    protected String getXmiId (RefObject obj) {
        String xmiId = ((String) xmiIds.get (obj));
        if (xmiId == null) {
            instancesCounter++;
            xmiId = "a" + instancesCounter;            
            xmiIds.put (obj, xmiId);
        }
        return xmiId;
    }

    /**
     * Called when an istances has been written.
     */
    protected void markWritten (RefObject obj) {
        // used to handle written status of components only
        writtenComponents.add (obj);
        nonWrittenComponents.remove (obj);
    }

    protected void writeDocument (RefPackage pkg) {        
        try {
            contentHandler.startDocument();
        } catch (SAXException e) {
        }        

        startElement (XmiConstants.XMI_ROOT);
        addAttribute ("xmi.version", XMI_VERSION);
        writeNamespaces ();
        addAttribute ("timestamp", new Date ().toString ());
        
        writeHeader ();
        
        // content
        startElement (XmiConstants.XMI_CONTENT);
        if (!collectionWriting) {
            processedPackages.clear();
            writePackage (pkg);
         
            RefObject obj;
            while (nonWrittenComponents.size () > 0) {
                Iterator iter = nonWrittenComponents.iterator ();
                do {                    
                    obj = (RefObject) iter.next ();
                } while (nonWrittenComponents.contains (obj.refImmediateComposite ()));
                writeInstance (obj, true);
                while (lightOutermosts.size() > 0) {
                    obj = (RefObject) lightOutermosts.remove(0);
                    writeInstance (obj, true);
                } // while
            } // while
            
            processedPackages.clear();
            writeStaticAttributes (pkg);
        } else {
            writeObjects ();
        }        
        processedPackages.clear();
        writeAssociations (pkg);
        endElement (XmiConstants.XMI_CONTENT);
        // end of content
        endElement (XmiConstants.XMI_ROOT);
        try {
            contentHandler.endDocument();
        } catch (SAXException e) {
        }
    }

    protected void writeHeader () {
        // header
        startElement (XmiConstants.XMI_HEADER);
        if ((contentHandler instanceof DefaultWriter) && (headerProvider != null)) {
            writeStartElement ();
            characters ("");
            Writer ps = ((DefaultWriter) contentHandler).getWriter ();
            headerProvider.writeHeader (ps);
        } else { // write default header            
            startElement (XmiConstants.XMI_DOCUMENTATION);
            // exporter
            startElement ("XMI.exporter");
            characters (EXPORTER_NAME);
            endElement ("XMI.exporter");
            // exporter version
            startElement ("XMI.exporterVersion");
            characters (EXPORTER_VERSION);
            endElement ("XMI.exporterVersion");
            endElement (XmiConstants.XMI_DOCUMENTATION);            
        }
        endElement (XmiConstants.XMI_HEADER);
        // ... end of header
    }
    
    protected void writeNamespaces () {
        HashMap temp = new HashMap ();
        Iterator iter = namespaces.entrySet ().iterator ();
        while (iter.hasNext ()) {
            String name = (String) ((Map.Entry) iter.next ()).getValue ();
            if (temp.get (name) == null) {
                temp.put (name, name);
                addAttribute ("xmlns:" + name, XmiConstants.TAGID_XMI_NAMESPACE + "." + name);
            } // if
        } // while
    }

    /**
     * Serializes instances contained in a package and in all its sub-packages.
     */
    protected void writePackage (RefPackage pkg) {

        if (processedPackages.contains (pkg))
            return;

        Iterator classes = pkg.refAllClasses ().iterator ();
        while (classes.hasNext ()) {
            RefClass proxy = (RefClass) classes.next ();
            Iterator instances = proxy.refAllOfClass ().iterator ();
            while (instances.hasNext ()) {
                RefObject obj = (RefObject) instances.next ();
                if (obj == null) {
                    continue;
                }
                if (obj.equals (obj.refOutermostComposite ())) {
                    // non-outermost instance is serialized as a part of content
                    // of an outermost instance
                    writeInstance (obj, true);
                    while (lightOutermosts.size() > 0) {
                        obj = (RefObject) lightOutermosts.remove(0);
                        writeInstance (obj, true);
                    } // while
                } else {
                    if (!writtenComponents.contains (obj)) {
                        nonWrittenComponents.add (obj);
                    } 
                }
            } // while
        } // while

        processedPackages.add (pkg);
        Iterator containedPackages = pkg.refAllPackages ().iterator ();
        while (containedPackages.hasNext ())
            writePackage ((RefPackage) containedPackages.next ());
    }

    protected void writeObjects () {
        Iterator iter = objectsToWriteAsCollection.iterator ();
        while (iter.hasNext ()) {
            writeInstance ((RefObject) iter.next (), true);
        }
    }

    /**
     * Serializes an instance.
     *
     * @param obj object to be serialized
     * @param isTop true if the instance is serialized as a top-element (i.e. direct sub-element of )
     */
    protected void writeInstance (RefObject obj, boolean isTop) {
        RefClass proxy = obj.refClass ();
        ModelElement element = (ModelElement) obj.refMetaObject ();
        String name = qualifiedName (element);
        XMIReferenceProvider.XMIReference xmiRef = provider.getReference (obj);
        String xmiId = xmiRef.getXmiId ();
        String systemId = xmiRef.getSystemId ();
        if ((systemId != null) && (thisSystemId != null) && (thisSystemId.equals (systemId)))
            systemId = null;
        
        markWritten (obj);
        if (systemId != null) { // object from an external document
            if (!isTop) { // serialize href
                startElement (name);
                addAttribute (XmiConstants.XMI_HREF, systemId + HREF_DELIMITER + xmiId);
                endElement (name);
            }
            collectLightOutermosts (obj, proxy);
            return;
        }
                
        startElement (name);
        addAttribute (XmiConstants.XMI_ID, xmiId);
        Iterator attrs = instanceAttributes ((MofClass) proxy.refMetaObject ()).iterator ();
        List attrsInContent = new LinkedList ();
        while (attrs.hasNext ()) {
            Attribute attr = (Attribute) attrs.next ();
            if (!VisibilityKindEnum.PUBLIC_VIS.equals(attr.getVisibility()))
                continue;
            boolean isMultivalued = isMultivalued (attr);
            Object value;
            try {
            value = obj.refGetValue (attr);
            } catch (Exception e) {
                Logger.getDefault().annotate(e, ((ModelElement) obj.refMetaObject ()).getName () + " " + attr.getName ());
                Logger.getDefault().notify(e);
                value = Boolean.FALSE; // [PENDING]
            }
            Object valueToWrite = value;
            if (value == null)
                continue; // optional attribute of no value
            if (isMultivalued) {
                Collection col = (Collection) value;
                if (col.size () > 0) {
                    attrsInContent.add (attr);
                }
                continue;
                /*
                if (col.isEmpty ())
                    continue;
                if (col.size () > 1) {
                    // values have to be serialized in content
                    attrsInContent.add (attr);
                    continue;
                } else
                    valueToWrite = col.iterator ().next ();
                 */
            } // if
            Classifier type = getType (attr);            
            if (!(type instanceof PrimitiveType) && !(type instanceof EnumerationType)) {
                // values have to be serialized in content
                attrsInContent.add (attr);
            } else
                writeValueInAttr (attr, valueToWrite);
        } // while
        Iterator iter = attrsInContent.iterator ();
        while (iter.hasNext ()) {
            Attribute attr = (Attribute) iter.next ();
            writeValueInContent (attr, obj.refGetValue (attr));
        } // while
        Iterator refs = references ((MofClass) proxy.refMetaObject ()).iterator ();
        while (refs.hasNext ()) {
            Reference ref = (Reference) refs.next ();
            writeReference (obj, ref);
        }
        endElement (name);
    }
    
    protected void collectLightOutermosts (RefObject obj, RefClass proxy) {
        Iterator iter;
        Iterator attrs = instanceAttributes ((MofClass) proxy.refMetaObject ()).iterator ();        
        while (attrs.hasNext ()) {
            Attribute attr = (Attribute) attrs.next ();
            Classifier type = getType (attr);            
            if ((type instanceof PrimitiveType) || (type instanceof EnumerationType))
                continue;
            boolean isMultivalued = isMultivalued (attr);
            Object value = obj.refGetValue (attr);            
            Collection values;
            if (value == null)
                continue; // optional attribute of no value
            if (isMultivalued) {
                values = (Collection) value;                
            } else {
                values = new LinkedList ();
                values.add (value);
            }
            iter = values.iterator ();
            if (type instanceof MofClass) {
                while (iter.hasNext ()) {
                    addLightOutermost ((RefObject) iter.next ());
                }
            } else if (type instanceof StructureType) {
                while (iter.hasNext ()) {
                    collectStructure ((StructureType) type, (RefStruct) iter.next ());
                }
            } else if (type instanceof CollectionType) {
                while (iter.hasNext ()) {
                    collectCollection ((CollectionType) type, (Collection) iter.next ());
                }
            }
        } // while
        
        Iterator refs = references ((MofClass) proxy.refMetaObject ()).iterator ();
        while (refs.hasNext ()) {
            Reference ref = (Reference) refs.next ();
            /*
            AggregationKind kind = ref.getReferencedEnd ().getAggregation ();            
            if (AggregationKindEnum.COMPOSITE.equals (kind))
                return; // do not serialize reference to immediate composite object
             */
            AggregationKind kind = ref.getExposedEnd ().getAggregation ();
            if (AggregationKindEnum.COMPOSITE.equals (kind)) {
                Object temp = obj.refGetValue (ref);
                if (temp == null)
                    continue;
                Collection values;
                if (isMultivalued (ref))
                    values = (Collection) temp;
                else {
                    values = new LinkedList ();
                    values.add (temp);
                }                
                iter = values.iterator ();
                while (iter.hasNext ()) {
                    addLightOutermost ((RefObject) iter.next ());                    
                } // while
            } // if
        } // while
    }
        
    protected void collectStructure (StructureType type, RefStruct value) {
        Iterator iter = structureFields (type).iterator ();
        while (iter.hasNext ()) {
            StructureField field = (StructureField) iter.next ();
            Classifier fieldType = getType (field);
            if (fieldType instanceof StructureType) {
                collectStructure ((StructureType) fieldType, (RefStruct) value.refGetValue (field.getName()));
            } else if (fieldType instanceof MofClass) {
                addLightOutermost ((RefObject) value.refGetValue (field.getName()));
            } else if (fieldType instanceof CollectionType) {
                collectCollection ((CollectionType) fieldType, (Collection) value.refGetValue (field.getName()));
            }
        } // while
    }
    
    protected void collectCollection (CollectionType collType, Collection col) {
        Classifier type = collType.getType ();
        Iterator iter = col.iterator ();
        if (type instanceof StructureType) {
            while (iter.hasNext ())
                collectStructure ((StructureType) type, (RefStruct) iter.next ());
        } else if (type instanceof CollectionType) {
            while (iter.hasNext ())
                collectCollection ((CollectionType) type, (Collection) iter.next ());
        } else if (type instanceof MofClass) {
            while (iter.hasNext ())
                addLightOutermost ((RefObject) iter.next ());
        }
    }
    
    protected void addLightOutermost (RefObject obj) {
        lightOutermosts.add (obj);
    }
    
    /**
     * Writes reference to an instance (e.g. ).
     *
     * @param externalOnly parameter related to XMI 2.0
     * @param hrefForced parameter related to XMI 2.0
     */
    protected void writeInstanceRef (RefObject obj, boolean externalOnly, boolean hrefForced) {
        String name = qualifiedName ((ModelElement) obj.refMetaObject ());
        XMIReferenceProvider.XMIReference xmiRef = provider.getReference (obj);
        String xmiId = xmiRef.getXmiId ();
        String systemId = xmiRef.getSystemId ();
        if ((systemId != null) && (thisSystemId != null) && (thisSystemId.equals (systemId)))
            systemId = null;                
        startElement (name);
        if (systemId == null) {
            addAttribute (XmiConstants.XMI_IDREF, xmiId);
        } else {            
            addAttribute (XmiConstants.XMI_HREF, systemId + HREF_DELIMITER + xmiId);
        }
        endElement (name);
    }

    /**
     * Serializes an attribute's value of Primitive or Enumeration type
     * via XML attribute value.
     */
    protected void writeValueInAttr (TypedElement attr, Object value) {
        String name = elementName (attr);
        String asText;
        Classifier type = attr.getType ();
        if (type instanceof EnumerationType) {
            String prefix = labelPrefix ((EnumerationType) type);
            // (optional) enumeration label prefix have to be removed before label is serialized as a String
            asText = value.toString ().substring (prefix.length ());
        } else
            asText = value.toString ();
        addAttribute (name, asText);
    }

    /**
     * Serializes an attribute's or field's (multi-)value into content of an owning element.
     */
    protected void writeValueInContent (TypedElement attr, Object value) {
        if (value == null)
            return;
        String name = qualifiedName (attr);
        Classifier type = getType (attr);        
        Collection values;
        boolean isMultivalued = false;
        if (attr instanceof StructuralFeature)
            isMultivalued = isMultivalued ((StructuralFeature) attr);
        if (isMultivalued)
            values = (Collection) value;
        else {
            values = new LinkedList ();
            values.add (value);
        }
        Iterator iter = values.iterator ();
        if (type instanceof StructureType) {
            startElement (name);
            while (iter.hasNext ()) {
                writeStructure ((StructureType) type , (RefStruct) iter.next ());
            }
            endElement (name);
        } else if (type instanceof MofClass) {
            startElement (name);
            while (iter.hasNext ()) {
                RefObject obj = (RefObject) iter.next ();
                writeInstance (obj, false);
            }
            endElement (name);
        } else if (type instanceof PrimitiveType) {
            while (iter.hasNext ()) {
                Object obj = iter.next ();
                startElement (name);
                characters (obj.toString ());
                endElement (name);
            }
        } else if (type instanceof EnumerationType) {
            while (iter.hasNext ()) {
                Object obj = iter.next ();
                startElement (name);
                String prefix = labelPrefix ((EnumerationType) type);
                // (optional) enumeration label prefix have to be removed before label is serialized as a String
                String label = obj.toString ().substring (prefix.length ());
                addAttribute (XmiConstants.XMI_VALUE, label);
                endElement (name);
            }
        } else if (type instanceof CollectionType) {
            startElement (name);
            while (iter.hasNext ()) {
                writeCollection ((CollectionType) type , (Collection) iter.next ());
            }
            endElement (name);
        } else {
            throw new DebugException ("Unsupported type: " + type.getName ());
        } // if
    }

    /**
     * Serializes structure.
     */
    /*
    protected void writeStructure (StructureType type, RefStruct value) {
        String name = qualifiedName (type);
        startElement (name);
        Iterator content = structureFields (type).iterator ();
        List fields = new LinkedList ();
        while (content.hasNext ()) {
            Object field = content.next ();
            Classifier fieldType = getType ((StructureField) field);            
            if ((fieldType instanceof PrimitiveType) ||
                (fieldType instanceof EnumerationType)) {
                writeValueInAttr (
                    (StructureField) field,
                    value.refGetValue (((ModelElement) field).getName ())
                );
            } else
                fields.add (field);
        } // while
        Iterator iter = fields.iterator ();
        while (iter.hasNext ()) {
            StructureField field = (StructureField) iter.next ();
            Classifier fieldType = getType (field);
            String fieldName = qualifiedName (field);
            Object fieldValue = value.refGetValue (((ModelElement) field).getName ());
            startElement (fieldName);            
            if (fieldType instanceof MofClass)
                writeInstance ((RefObject) fieldValue);
            else if (fieldType instanceof StructureType)
                writeStructure ((StructureType) fieldType, (RefStruct) fieldValue);
            endElement (fieldName);
        } // while
        endElement (name);
    }
     */

    // [PENDING] temporally changed, xmi.field tags are used to generate structure value
    protected void writeStructure (StructureType type, RefStruct value) {
        Iterator iter = structureFields (type).iterator ();
        while (iter.hasNext ()) {
            StructureField field = (StructureField) iter.next ();
            Classifier fieldType = getType (field);            
            String fieldName = qualifiedName (field);
            Object fieldValue = value.refGetValue (((ModelElement) field).getName ());
            startElement (XmiConstants.XMI_FIELD);
            if (fieldType instanceof MofClass)
                writeInstanceRef ((RefObject) fieldValue, false, false);
            else if (fieldType instanceof StructureType)
                writeStructure ((StructureType) fieldType, (RefStruct) fieldValue);
            else if (fieldType instanceof CollectionType)
                writeCollection ((CollectionType) fieldType, (Collection) fieldValue);
            else if (fieldType instanceof PrimitiveType) {
                characters (fieldValue.toString ());
            }
            endElement (XmiConstants.XMI_FIELD);
        } // while
    }

    protected void writeCollection (CollectionType collType, Collection value) {
        String collTypeName = qualifiedName (collType);
        startElement (collTypeName);
        Iterator iter = value.iterator ();
        Classifier type = collType.getType ();
        String typeName = qualifiedName (type);
        if (type instanceof MofClass) {
            while (iter.hasNext ()) {
                writeInstanceRef ((RefObject) iter.next (), false, false);
            }
        } else if (type instanceof StructureType) {
            while (iter.hasNext ()) {
                startElement (typeName);                
                Object o = iter.next ();
                writeStructure ((StructureType) type, (RefStruct) o);
                endElement (typeName);
            }
        } else if (type instanceof CollectionType) {
            while (iter.hasNext ()) {
                // startElement (typeName);
                writeCollection ((CollectionType) type, (Collection) iter.next ());
                // endElement (typeName);
            }
        } else if (type instanceof PrimitiveType) {            
            while (iter.hasNext ()) {
                startElement (typeName);
                characters (iter.next ().toString ());
                endElement (typeName);
            }
        } // if
        endElement (collTypeName);
    }
    
    /**
     * Serializes Reference.
     */
    protected void writeReference (RefObject obj, Reference ref) {
        AggregationKind kind = ref.getReferencedEnd ().getAggregation ();
        if (AggregationKindEnum.COMPOSITE.equals (kind))
            return; // do not serialize reference to immediate composite object
        kind = ref.getExposedEnd ().getAggregation ();
        boolean isComposite = AggregationKindEnum.COMPOSITE.equals (kind);
        Object temp = obj.refGetValue (ref);
        if (temp == null)
            return;
        Collection values;
        if (isMultivalued (ref))
            values = (Collection) temp;
        else {
            values = new LinkedList ();
            values.add (temp);
        }
        Iterator iter;
        
        if (collectionWriting) {
            // exclude all referenced instances that are not in the transitive closure generated by input collection
            Collection cValues = new LinkedList ();
            iter = values.iterator ();
            while (iter.hasNext ()) {
                RefObject referencedObject = (RefObject) iter.next ();
                if (isInClosure (referencedObject)) {
                    cValues.add (referencedObject);
                } // if
            }  // while
            values = cValues;
        } // if
        
        if (values.isEmpty ())
            return;        

        String name = qualifiedName (ref);
        startElement (name);
        iter = values.iterator ();
        while (iter.hasNext ()) {
            RefObject endValue = (RefObject) iter.next ();
            if (isComposite)
                writeInstance (endValue, false);
            else
                writeInstanceRef (endValue, false, false);
        } // while
        endElement (name);
    }

    /**
     * Serializes values of class-scoped attributes of classes contained in a
     * given package and its sub-packages.
     */
    protected void writeStaticAttributes (RefPackage pkg) {
        if (processedPackages.contains (pkg))
            return;
        Iterator iter = pkg.refAllClasses ().iterator ();
        while (iter.hasNext ()) {
            RefClass proxy = (RefClass) iter.next ();
            Iterator attrs = classAttributes ((MofClass) proxy.refMetaObject ()).iterator ();
            while (attrs.hasNext ()) {
                Attribute attr = (Attribute) attrs.next ();
                writeValueInContent (attr, proxy.refGetValue (attr));
            } // while
        } // while
        processedPackages.add (pkg);
        // write values of class-scoped attributes of classes contained in sub-packages
        Iterator containedPackages = pkg.refAllPackages ().iterator ();
        while (containedPackages.hasNext ())
            writeStaticAttributes ((RefPackage) containedPackages.next ());
    }

    /**
     * Serializes association links that are not serialized via References.
     * All associations contained in a given package and its sub-packages are checked.
     */
    protected void writeAssociations (RefPackage pkg) {
        if (processedPackages.contains (pkg))
            return;
        Iterator iter = pkg.refAllAssociations ().iterator ();
        while (iter.hasNext ()) {
            RefAssociation proxy = (RefAssociation) iter.next ();
            Association assoc = (Association) proxy.refMetaObject ();
            if (assoc.isDerived ())
                continue;
            // indicates if at least one link has been written
            boolean aLinkWritten = false;
            String name = qualifiedName (assoc);
            AssociationEnd end1 = null, end2 = null;

            Iterator content = assoc.getContents ().iterator ();
            while (content.hasNext ()) {
                Object obj = content.next ();
                if (obj instanceof AssociationEnd) {
                    if (end1 == null)
                        end1 = (AssociationEnd) obj;
                    else {
                        end2 = (AssociationEnd) obj;
                        break;
                    }
                } // if
            } // while
            MofClass type1 = (MofClass) end1.getType ();
            MofClass type2 = (MofClass) end2.getType ();
            boolean isComposite1 = AggregationKindEnum.COMPOSITE.equals(end1.getAggregation ());
            boolean isComposite2 = AggregationKindEnum.COMPOSITE.equals(end2.getAggregation ());
            boolean ref_1_exists = referenceExists (type1, end2);
            boolean ref_2_exists = referenceExists (type2, end1);                        

            if ((ref_1_exists && ref_2_exists) || 
                (ref_1_exists && !isComposite2) ||
                (ref_2_exists && !isComposite1))
                continue; // skip this Association, all its links have been already written via References
            
            boolean isNavigable1 = end1.isNavigable ();
            boolean isNavigable2 = end2.isNavigable ();            

            // temporal caches storing MofClasses and information if they contain a reference
            // related to the association
            HashMap cache_1 = new HashMap ();
            HashMap cache_2 = new HashMap ();
            Iterator links = proxy.refAllLinks ().iterator ();

            while (links.hasNext ()) {
                RefAssociationLink link = (RefAssociationLink) links.next ();
                RefObject value_1 = link.refFirstEnd ();
                RefObject value_2 = link.refSecondEnd ();

                if (collectionWriting && !(isInClosure (value_1) && isInClosure (value_2)))
                    continue;

                Boolean flag_1 = Boolean.FALSE, flag_2 = Boolean.FALSE;
                if (isNavigable1) {
                    type1 = (MofClass) value_1.refMetaObject ();
                    flag_1 = (Boolean) cache_1.get (type1);
                    if (flag_1 == null) {
                        if (referenceExists (type1, end2))
                            flag_1 = Boolean.TRUE;
                        else
                            flag_1 = Boolean.FALSE;
                        cache_1.put (type1, flag_1);
                    } // if                    
                } // if
                if (isNavigable2) {
                    type2 = (MofClass) value_2.refMetaObject ();
                    flag_2 = (Boolean) cache_2.get (type2);
                    if (flag_2 == null) {
                        if (referenceExists (type2, end1))
                            flag_2 = Boolean.TRUE;
                        else
                            flag_2 = Boolean.FALSE;
                        cache_2.put (type2, flag_2);
                    } // if                    
                } // if                            
                
                ref_1_exists = flag_1.booleanValue();
                ref_2_exists = flag_2.booleanValue();
                
                if ((ref_1_exists && ref_2_exists) || 
                    (ref_1_exists && !isComposite2) ||
                    (ref_2_exists && !isComposite1))
                    continue;
                
                // serialize link
                if (!aLinkWritten) {
                    // write 
                    startElement (name);
                    aLinkWritten = true;
                }
                writeInstanceRef (value_1, false, false); // [PENDING] XMI 2.0 writer should override this
                writeInstanceRef (value_2, false, false); // [PENDING] XMI 2.0 writer should override this
            } // while (goes through all links of the association)
            if (aLinkWritten)
                endElement (name);
        } // while (goes through all associations in the package)

        processedPackages.add (pkg);
        Iterator containedPackages = pkg.refAllPackages ().iterator ();
        while (containedPackages.hasNext ())
            writeAssociations ((RefPackage) containedPackages.next ());
    }


    /**
     * Tests if a mof class has a reference exposing given association end.
     */
    protected boolean referenceExists (MofClass mofClass, AssociationEnd assocEnd) {
        if (!assocEnd.isNavigable ()) {
            return false;
        }
        Iterator references = references (mofClass).iterator ();
        while (references.hasNext ()) {
            Reference ref = (Reference) references.next ();
            AssociationEnd end = ref.getReferencedEnd ();
            if (end.equals (assocEnd))
                return true;
        }
        return false;
    }

    /**
     * True if the passed instance have to be written by write(Collection) method.
     */
    protected boolean isInClosure (RefObject obj) {
        RefObject container = obj;
        RefFeatured featured;
        while (container != null) {
            if (objectsToWrite.contains (container))
                return true;
            featured = container.refImmediateComposite ();
            container = ((featured instanceof RefObject) && (featured != obj))? (RefObject) featured : null;
        }
        return false;
    }

    /**
     * Returns fully qualified name of an model element.
     */
    protected String qualifiedName (ModelElement element) {
        Iterator iter = element.getQualifiedName ().iterator ();
        String name = (String) iter.next ();
        while (iter.hasNext ())
            name = name.concat (XmiConstants.DOT_SEPARATOR).concat ((String) iter.next ());

        int index = name.lastIndexOf ('.');
        String pName = name.substring (0, index);
        String sName = name.substring (index + 1, name.length ());
        if (!(element instanceof MofClass) && !(element instanceof Association)) {
            index = pName.lastIndexOf ('.');
            if (index > -1) {            
                pName = pName.substring (0, index);
                sName = name.substring (index + 1, name.length ());
            }
        }

        String namespace = (String) namespaces.get (pName);

        if (namespace != null)
            return namespace + ":" + sName;
        return name;
    }

    protected String elementName (ModelElement elem) {
        return elem.getName ();
    }
    
    /**
     * True iff given StructuralFeature is multivalued.
     */
    protected static boolean isMultivalued (StructuralFeature feature) {
        MultiplicityType multType = feature.getMultiplicity ();
        return multType.getUpper () != 1;
    }

    protected static Classifier getType (TypedElement elem) {
        Classifier type = elem.getType ();
        while (type instanceof AliasType)
            type = ((AliasType) type).getType ();
        return type;
    }        

    // default XMIReferenceProvider ..............................................
    
    class DefaultProvider implements XMIReferenceProvider {
        
        public XMIReferenceProvider.XMIReference getReference (RefObject obj) {            
            return new XMIReferenceProvider.XMIReference (null, getXmiId(obj));
        }
        
    }
    
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.