Test coverage report for XMIContextStack.java - www.sdmetrics.com
/*
* SDMetrics Open Core for UML design measurement
* Copyright (c) Juergen Wuest
* To contact the author, see <http://www.sdmetrics.com/Contact.html>.
*
* This file is part of the SDMetrics Open Core.
*
* SDMetrics Open Core is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* SDMetrics Open Core 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SDMetrics Open Core. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.sdmetrics.model;
import java.util.ArrayList;
/**
* Manages the stack of model elements being processed during parsing of the XMI
* file.
*/
class XMIContextStack {
/**
* Class to store parser context information for a model element on the
* stack. The context stack holds instances of this class.
*/
private static class Context {
/** The model element of the parse context. */
ModelElement modelElement;
/** Nesting level of the XML element of that model element. */
int nestingLevel;
/** The XMI transformation to use for the model element. */
XMITransformation transformation;
/** The currently active XMI trigger. */
XMITrigger activeTrigger;
}
/** Model element stack to keep track of the parser state. */
private final ArrayList<Context> stack;
/** Index of the top element. */
private int topIndex;
/** Top element on the stack. */
private Context top;
/** Create a new, empty stack. */
XMIContextStack() {
stack = new ArrayList<>();
// keep a default element at the bottom of the stack with reasonable
// values to return when the stack is otherwise empty.
top = new Context();
stack.add(top);
topIndex = 0;
}
/**
* Pushes a new model element on top of the stack.
*
* @param element the model element
* @param trans the XMI transformation applicable to this model element.
* @param nesting Nesting level of the XML element that represents the model
* element.
*/
void push(ModelElement element, XMITransformation trans, int nesting) {
topIndex++;
if (topIndex >= stack.size()) {
top = new Context();
stack.add(top);
} else {
top = stack.get(topIndex);
}
top.modelElement = element;
top.transformation = trans;
top.nestingLevel = nesting;
}
/**
* Removes the model element on top of the stack and returns it.
*
* @return The model element removed from the top of the stack.
*/
ModelElement pop() {
ModelElement result = top.modelElement;
topIndex--;
top = stack.get(topIndex);
return result;
}
/**
* Checks if the stack is empty.
*
* @return <code>true</code> if the stack is empty.
*/
boolean isEmpty() {
return topIndex == 0; // the bottom element does not count
}
/**
* Gets the model element on top of the context stack.
*
* @return Model element on top of the stack
*/
ModelElement getModelElement() {
return top.modelElement;
}
/**
* Gets the XML nesting level for the model element on top of the stack.
*
* @return Nesting level for the top element.
*/
int getNestingLevel() {
return top.nestingLevel;
}
/**
* Retrieves the XMI transformations applicable to the model element on top
* of the stack.
*
* @return XMI transformation for the top element.
*/
XMITransformation getXMITransformation() {
return top.transformation;
}
/**
* Tests if the current parse context accepts new model elements. This is
* the case if the stack is empty, or the model element on top of the stack
* can have sub-elements.
*
* @return <code>true</code> if new elements are accepted.
*/
boolean isAcceptingNewElements() {
if (top.transformation == null) {
return true;
}
return top.transformation.getXMIRecurse();
}
/**
* Sets the active trigger for the XMI transformation on top of the stack.
*
* @param trigger active trigger for the top XMI transformation
*/
void setActiveTrigger(XMITrigger trigger) {
top.activeTrigger = trigger;
}
/**
* Gets the active trigger.
*
* @return The active trigger for the top XMI transformation
*/
XMITrigger getActiveTrigger() {
return top.activeTrigger;
}
/**
* Checks if the active trigger is of the specified type.
*
* @param type trigger type to compare the active trigger to
* @return <code>true</code> if the active trigger is of the specified type,
* <code>false</code> if it is of a different type or there is no
* current active trigger.
*/
boolean activeTriggerTypeEquals(XMITrigger.TriggerType type) {
if (top.activeTrigger == null) {
return false;
}
return top.activeTrigger.type == type;
}
}