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

org.modeldriven.fuml.xmi.stream.StreamNode Maven / Gradle / Ivy

Go to download

This open source software is a reference implementation, consisting of software and related files, for the OMG specification called the Semantics of a Foundational Subset for Executable UML Models (fUML). The reference implementation is intended to implement the execution semantics of UML activity models, accepting an XMI file from a conformant UML model as its input and providing an execution trace of the selected activity model(s) as its output. The core execution engine, which is directly generated from the normative syntactic and semantic models for fUML, may also be used as a library implementation of fUML in other software.

There is a newer version: 1.5.0a
Show newest version
/*
 * Copyright 2008 Lockheed Martin Corporation, except as stated in the file 
 * entitled Licensing-Information. All modifications copyright 2009 Data Access Technologies, Inc. Licensed under the Academic Free License 
 * version 3.0 (http://www.opensource.org/licenses/afl-3.0.php), except as stated 
 * in the file entitled Licensing-Information. 
 *
 * Contributors:
 *   MDS - initial API and implementation
 *
 */

package org.modeldriven.fuml.xmi.stream;

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

import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.modeldriven.fuml.config.FumlConfiguration;
import org.modeldriven.fuml.config.ImportExemption;
import org.modeldriven.fuml.config.ImportExemptionType;
import org.modeldriven.fuml.config.NamespaceDomain;
import org.modeldriven.fuml.xmi.XmiConstants;
import org.modeldriven.fuml.xmi.XmiNode;
import org.modeldriven.fuml.xmi.XmiNodeVisitor;
import org.modeldriven.fuml.xmi.XmiNodeVisitorStatus;

/**
 * Encapsulates a set of related XML (stream) events. Stream events are objects 
 * allocated by the StAX parser from the current stream and include element and 
 * attribute as well as namespace and location information. The primary event 
 * encapsulated is always a start-element event, but one of more 'characters' 
 * events may be added if character data for the element is encountered in the 
 * stream. 
 * @author Scott Cinnamond
 */
public class StreamNode implements XmiNode {

    private static Log log = LogFactory.getLog(StreamNode.class);
    private XMLEvent startElementEvent;
    private List characterEvents;
    private StreamContext context;
    private Location location;
	private List nodes; // TODO: do we really want interfaces in this list?
	private XmiNode parent; // TODO: same issue
    
    @SuppressWarnings("unused")
	private StreamNode() {}
    
    public StreamNode(XMLEvent startElement, XmiNode parent, StreamContext context) {
        this.startElementEvent = startElement;
        this.parent = parent;
        this.context = context;
        // The Sun StAX impl "loses" element location info, seemingly 
        // immediately after it's read into an event. We just copy it
        // off here. Tried the default event allocator in both
        // the Sun RI and the associated utilities. 
        this.location = new StreamLocation(startElement.getLocation());
        if (log.isDebugEnabled())
        	log.debug("created '" + this.getLocation() + "' node (" + 
        			this.getXmiId() + ")");
    }
    
    public StreamNode(XMLEvent startElement, StreamContext context) {
        this(startElement, null, context);
    }
    
    public Location getLocation() {
		return location;
	}

	public String getLocalName()
    {
        return startElementEvent.asStartElement().getName().getLocalPart();
    }

	public String getNamespaceURI()
	{
	    QName name = startElementEvent.asStartElement().getName();
	    String uri = name.getNamespaceURI();
	    if (uri == null || uri.trim().length() == 0)
	        return this.context.getDefaultNamespace().getNamespaceURI();
	    else
	        return name.getNamespaceURI();
	}
	
	public String getPrefix() {
	    QName name = startElementEvent.asStartElement().getName();
	    String uri = name.getNamespaceURI();
	    if (uri == null || uri.trim().length() == 0)
	        return this.context.getDefaultNamespace().getPrefix();
	    else
	        return name.getPrefix();
	}

	public String getData()
    {
        if (this.characterEvents != null)
        {
            StringBuffer buf = new StringBuffer();
            Iterator events = this.characterEvents.iterator();
            while (events.hasNext())
                buf.append(events.next().asCharacters().getData());
        	return buf.toString();
        }
        return null;
    }
	
    public String getXmiType()
    {
        QName typeAttrib = new QName(context.getXmiNamespace().getNamespaceURI(), 
        		XmiConstants.ATTRIBUTE_XMI_TYPE);
        Attribute attrib = startElementEvent.asStartElement().getAttributeByName(typeAttrib);
        if (attrib != null)
        {    
            String value = attrib.getValue();
            return value.substring(context.getUmlNamespace().getPrefix().length() + 1); // prefix + ':'
        }
        
        return null;
    }
 
    public boolean hasAttribute(QName name)
    {
        Attribute attrib = startElementEvent.asStartElement().getAttributeByName(name);
        return (attrib != null);
    }
    
    @SuppressWarnings("unchecked")
	public boolean hasAttributes()
    {
        if (startElementEvent != null)
        {    
            Iterator attributes = startElementEvent.asStartElement().getAttributes();
            return attributes.hasNext();
        }
        return false;       
    }    

    @SuppressWarnings("unchecked")
	public Iterator getAttributes()
    {
        if (startElementEvent != null)
        {    
            Iterator attributes = startElementEvent.asStartElement().getAttributes();
            return attributes;
        }
        return null;       
    }    

    public Attribute getAttribute(QName name)
    {
        if (startElementEvent != null)
        {    
            Attribute attrib = startElementEvent.asStartElement().getAttributeByName(name);
            return attrib;
        }
        return null;
    }

    public Attribute getAttribute(String name)
    {
        if (startElementEvent != null)
        {    
            Attribute attrib = startElementEvent.asStartElement().getAttributeByName(
                    new QName(name));
            return attrib;
        }
        return null;
    }
    
    public String getAttributeValue(QName name)
    {
        if (startElementEvent != null)
        {    
            Attribute attrib = startElementEvent.asStartElement().getAttributeByName(name);
            if (attrib != null)
                return attrib.getValue();
        }
        return null;
    }

    public String getAttributeValue(String name)
    {
        if (startElementEvent != null)
        {    
            Attribute attrib = startElementEvent.asStartElement().getAttributeByName(
                new QName(name));
            if (attrib != null)
                return attrib.getValue();
        }
        return null;
    }
    
    public boolean hasXmiType()
    {
    	String xmiType = this.getXmiType();
    	return xmiType != null && xmiType.length() > 0;
    }

    public String getXmiId()
    {
        QName typeAttrib = new QName(context.getXmiNamespace().getNamespaceURI(), 
        		XmiConstants.ATTRIBUTE_XMI_ID);
        Attribute attrib = startElementEvent.asStartElement().getAttributeByName(typeAttrib);
        if (attrib != null)
        {    
            String value = attrib.getValue();
            return value;
        }
        
        return null;
    }
    
    public int getLineNumber() {
        return this.location.getLineNumber();	
    }
    
    public int getColumnNumber() {
        return this.location.getColumnNumber();	
    }
    
    public void add(StreamNode node)
    {
        if (nodes == null)
            nodes = new ArrayList();
        nodes.add(node);
        if (log.isDebugEnabled())
        	log.debug("added '" + node.getLocalName() + "' (" + node.getXmiId() + ") child node to "
        		+ this.getLocation() + "' parent node (" + this.getXmiId() + ")");
    }
    
    public XmiNode getParent() {
        return parent;
    }

    public void setParent(XmiNode parent) {
        this.parent = parent;
    }
    
    public List getNodes() {
        return nodes;
    }
    
    public boolean hasNodes() {
        return nodes != null;
    }

    public XmiNode findChildByName(String name)
    {
        if (this.nodes != null)
        {   
            Iterator iter = this.nodes.iterator();
            while (iter.hasNext())
            {
                XmiNode child = iter.next();
                if (child.getLocalName().equals(name))
                {
                    return child;
                }
            }
        }
        return null;
    }
    
    public XmiNode findChildById(String id)
    {
        if (this.nodes != null)
        {   
            Iterator iter = this.nodes.iterator();
            while (iter.hasNext())
            {
                XmiNode child = iter.next();
                if (child.getXmiId().equals(id))
                {
                    return child;
                }
            }
        }
        return null;
    }
    
    public boolean removeChild(XmiNode child)
    {
    	boolean removed = this.nodes.remove(child);
        if (log.isDebugEnabled())
        	log.debug("removed '" + child.getLocalName() + "' (" + child.getXmiId() + ") child node to "
        		+ this.getLocation() + "' parent node (" + this.getXmiId() + ")");
        return removed;
    }
    
    public XMLEvent getStartElementEvent() {
        return startElementEvent;
    }
    
    public void accept(XmiNodeVisitor visitor)
    {
        if (log.isDebugEnabled())
            log.debug(this.getClass().getSimpleName());
        accept(visitor, this, null, null, this, new HashMap(), 
                new XmiNodeVisitorStatus(), 0);
    }
        
    private void accept(XmiNodeVisitor visitor, XmiNode target, 
            XmiNode source, String sourceKey, 
            XmiNode root, 
            Map visited, XmiNodeVisitorStatus status, int level)
    {
        if (log.isDebugEnabled())
            log.debug("accept: " + target.getLocalName());
        
        if (visited.get(target) == null)
            visited.put(target, target);
        else
        {   
            if (log.isDebugEnabled())
                log.debug("ignoring, " + target.getClass().getName());
            return;
        }    
        
        visitor.visit(target, source, sourceKey, status, level);
        if (status.getStatus() == XmiNodeVisitorStatus.STATUS_ABORT)
            return;
        
        List nodes = target.getNodes();
        if (nodes != null)
            for (int i = 0; i < nodes.size(); i++)
            {
                XmiNode child = nodes.get(i);
                if (((StreamNode)child).isIgnored())
                {
                    if (log.isDebugEnabled())
                        log.debug("ignoring XMI 'Extension' node");
                    continue; // bag these and their children for now
                }
                if (log.isDebugEnabled())
                    log.debug("processing node: " + child.getLocalName());
                accept(visitor, child, target, 
                        child.getLocalName(), root, visited, status, level++);                
            }       
    }
    
	public StreamContext getContext() {
		return context;
	}

	public void addCharactersEvent(XMLEvent charactersEvent) {
	    if (this.characterEvents == null)
	        this.characterEvents = new ArrayList();
		this.characterEvents.add(charactersEvent);
	}
    
	public boolean hasCharacters()
	{
		return this.characterEvents != null && characterEvents.size() > 0;
	}
	
	public boolean isIgnored()
	{
	    if (startElementEvent == null)
	        return false; // can't ignore character nodes
	    
        String uri = startElementEvent.asStartElement().getName().getNamespaceURI();
        if (uri == null || uri.length() == 0)
        {
            uri = this.context.getDefaultNamespace().getNamespaceURI();
        }
        
        ImportExemption importExemption = FumlConfiguration.getInstance().findImportExemptionByElement(this.getLocalName());
        
        if (importExemption != null) { 
        	
            NamespaceDomain domain = FumlConfiguration.getInstance().getNamespaceDomain(uri);
        	if (importExemption.getType().ordinal() == ImportExemptionType.ELEMENT.ordinal() &&
        		importExemption.getDomain().ordinal() == domain.ordinal())
        		
            return true;
        }
	    return false;
	}

    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy