/**
* <copyright>
* </copyright>
*
*
*/
package org.reuseware.air.language.abstractsyntax.resource.as.mopp;
public class AsPrinter2 implements org.reuseware.air.language.abstractsyntax.resource.as.IAsTextPrinter {
private class PrintToken {
private String text;
private String tokenName;
public PrintToken(String text, String tokenName) {
this.text = text;
this.tokenName = tokenName;
}
public String getText() {
return text;
}
public String getTokenName() {
return tokenName;
}
}
public final static java.lang.String NEW_LINE = java.lang.System.getProperties().getProperty("line.separator");
/**
* Holds the resource that is associated with this printer. May be null if the
* printer is used stand alone.
*/
private org.reuseware.air.language.abstractsyntax.resource.as.IAsTextResource resource;
private java.util.Map<?, ?> options;
private java.io.OutputStream outputStream;
private java.util.List<PrintToken> tokenOutputStream;
private org.reuseware.air.language.abstractsyntax.resource.as.IAsTokenResolverFactory tokenResolverFactory = new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsTokenResolverFactory();
private boolean handleTokenSpaceAutomatically = true;
private int tokenSpace = 1;
/**
* A flag that indicates whether token have already been printed for the some
* object. The flag is set to false whenever printing of an EObject tree is
* started. The status of the flag is used to avoid printing default token space
* in front of the root object.
*/
private boolean startedPrintingObject = false;
/**
* The number of tab characters the were printed before the current line. This
* number is used to calculate the relative indendation when printing contained
* objects.
*/
private int currentTabs;
/**
* The number of tab characters that must be printed before the current object.
* This number is used to calculate the indendation of new lines, when line breaks
* are printed within one object.
*/
private int tabsBeforeCurrentObject;
private int newTabsBeforeCurrentObject;
public AsPrinter2(java.io.OutputStream outputStream, org.reuseware.air.language.abstractsyntax.resource.as.IAsTextResource resource) {
super();
this.outputStream = outputStream;
this.resource = resource;
}
public void print(org.eclipse.emf.ecore.EObject element) throws java.io.IOException {
tokenOutputStream = new java.util.ArrayList<PrintToken>();
currentTabs = 0;
tabsBeforeCurrentObject = 0;
startedPrintingObject = true;
doPrint(element, new java.util.ArrayList<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement>());
java.io.PrintWriter writer = new java.io.PrintWriter(new java.io.BufferedOutputStream(outputStream));
if (handleTokenSpaceAutomatically) {
printSmart(writer);
} else {
printBasic(writer);
}
writer.flush();
}
protected void doPrint(org.eclipse.emf.ecore.EObject element, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements) {
if (element == null) {
throw new java.lang.IllegalArgumentException("Nothing to write.");
}
if (outputStream == null) {
throw new java.lang.IllegalArgumentException("Nothing to write on.");
}
if (element instanceof org.reuseware.air.language.abstractsyntax.AbstractSyntax) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_0, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.Import) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_1, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.ASProgram) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_2, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.ConcreteNodeDefinition) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_3, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.InterfaceNodeDefinition) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_4, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.Attribute) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_5, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.Containment) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_6, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.InternalReference) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_7, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.ExternalReference) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_8, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.PLUS) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_9, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.STAR) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_10, foundFormattingElements);
return;
}
if (element instanceof org.reuseware.air.language.abstractsyntax.QUESTIONMARK) {
printInternal(element, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.AS_11, foundFormattingElements);
return;
}
addWarningToResource("The printer can not handle " + element.eClass().getName() + " elements", element);
}
public void printInternal(org.eclipse.emf.ecore.EObject eObject, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement ruleElement, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements) {
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformationAdapter layoutInformationAdapter = getLayoutInformationAdapter(eObject);
java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> originalLayoutInformations = layoutInformationAdapter.getLayoutInformations();
// create a copy of the original list of layout information object in order to be
// able to remove used informations during printing
java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations = new java.util.ArrayList<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation>(originalLayoutInformations.size());
layoutInformations.addAll(originalLayoutInformations);
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator decoratorTree = getDecoratorTree(ruleElement);
decorateTree(decoratorTree, eObject);
printTree(decoratorTree, eObject, foundFormattingElements, layoutInformations);
}
/**
* creates a tree of decorator objects which reflects the syntax tree that is
* attached to the given syntax element
*/
public org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator getDecoratorTree(org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement syntaxElement) {
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement[] children = syntaxElement.getChildren();
int childCount = children.length;
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator[] childDecorators = new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator[childCount];
for (int i = 0; i < childCount; i++) {
childDecorators[i] = getDecoratorTree(children[i]);
}
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator decorator = new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator(syntaxElement, childDecorators);
return decorator;
}
public void decorateTree(org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject) {
java.util.Map<java.lang.String, java.lang.Integer> printCountingMap = initializePrintCountingMap(eObject);
java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator> keywordsToPrint = new java.util.ArrayList<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator>();
decorateTreeBasic(decorator, eObject, printCountingMap, keywordsToPrint);
for (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator keywordToPrint : keywordsToPrint) {
// for keywords the concrete index does not matter, but we must add one to
// indicate that the keyword needs to be printed here. Thus, we use 0 as index.
keywordToPrint.addIndexToPrint(0);
}
}
/**
* Tries to decorate the decorator with an attribute value, or reference holded by
* eObject. Returns true if an attribute value or reference was found.
*/
public boolean decorateTreeBasic(org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject, java.util.Map<java.lang.String, java.lang.Integer> printCountingMap, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator> keywordsToPrint) {
boolean foundFeatureToPrint = false;
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement syntaxElement = decorator.getDecoratedElement();
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality cardinality = syntaxElement.getCardinality();
boolean isFirstIteration = true;
while (true) {
java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator> subKeywordsToPrint = new java.util.ArrayList<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator>();
boolean keepDecorating = false;
if (syntaxElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsKeyword) {
subKeywordsToPrint.add(decorator);
} else if (syntaxElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsTerminal) {
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsTerminal terminal = (org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsTerminal) syntaxElement;
org.eclipse.emf.ecore.EStructuralFeature feature = terminal.getFeature();
if (feature == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.ANONYMOUS_FEATURE) {
return false;
}
int countLeft = printCountingMap.get(feature.getName());
if (countLeft > terminal.getMandatoryOccurencesAfter()) {
decorator.addIndexToPrint(countLeft);
printCountingMap.put(feature.getName(), countLeft - 1);
keepDecorating = true;
}
}
if (syntaxElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsChoice) {
// for choices we do print only the choice which does print at least one feature
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator childToPrint = null;
for (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator childDecorator : decorator.getChildDecorators()) {
// pick first choice as default, will be overridden if a choice that prints a
// feature is found
if (childToPrint == null) {
childToPrint = childDecorator;
}
if (doesPrintFeature(childDecorator, eObject, printCountingMap)) {
childToPrint = childDecorator;
break;
}
}
keepDecorating |= decorateTreeBasic(childToPrint, eObject, printCountingMap, subKeywordsToPrint);
} else {
// for all other syntax element we do print all children
for (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator childDecorator : decorator.getChildDecorators()) {
keepDecorating |= decorateTreeBasic(childDecorator, eObject, printCountingMap, subKeywordsToPrint);
}
}
foundFeatureToPrint |= keepDecorating;
// only print keywords if a feature was printed or the syntax element is mandatory
if (cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.ONE) {
keywordsToPrint.addAll(subKeywordsToPrint);
} else if (cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.PLUS) {
if (isFirstIteration) {
keywordsToPrint.addAll(subKeywordsToPrint);
} else {
if (keepDecorating) {
keywordsToPrint.addAll(subKeywordsToPrint);
}
}
} else if (keepDecorating && (cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.STAR || cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.QUESTIONMARK)) {
keywordsToPrint.addAll(subKeywordsToPrint);
}
if (cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.ONE || cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.QUESTIONMARK) {
break;
} else if (!keepDecorating) {
break;
}
isFirstIteration = false;
}
return foundFeatureToPrint;
}
/**
* Checks whether decorating the given node will use at least one attribute value,
* or reference holded by eObject. Returns true if a printable attribute value or
* reference was found. This method is used to decide which choice to pick, when
* multiple choices are available. We pick the choice that prints at least one
* attribute or reference.
*/
public boolean doesPrintFeature(org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject, java.util.Map<java.lang.String, java.lang.Integer> printCountingMap) {
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement syntaxElement = decorator.getDecoratedElement();
if (syntaxElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsTerminal) {
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsTerminal terminal = (org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsTerminal) syntaxElement;
org.eclipse.emf.ecore.EStructuralFeature feature = terminal.getFeature();
if (feature == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsGrammarInformationProvider.ANONYMOUS_FEATURE) {
return false;
}
int countLeft = printCountingMap.get(feature.getName());
if (countLeft > terminal.getMandatoryOccurencesAfter()) {
// found a feature to print
return true;
}
}
for (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator childDecorator : decorator.getChildDecorators()) {
if (doesPrintFeature(childDecorator, eObject, printCountingMap)) {
return true;
}
}
return false;
}
public boolean printTree(org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations) {
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement printElement = decorator.getDecoratedElement();
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality cardinality = printElement.getCardinality();
java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> cloned = new java.util.ArrayList<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement>();
cloned.addAll(foundFormattingElements);
boolean foundSomethingAtAll = false;
boolean foundSomethingToPrint;
while (true) {
foundSomethingToPrint = false;
java.lang.Integer indexToPrint = decorator.getNextIndexToPrint();
if (indexToPrint != null) {
if (printElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsKeyword) {
printKeyword(eObject, (org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsKeyword) printElement, foundFormattingElements, layoutInformations);
foundSomethingToPrint = true;
} else if (printElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsPlaceholder) {
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsPlaceholder placeholder = (org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsPlaceholder) printElement;
printFeature(eObject, placeholder, indexToPrint, foundFormattingElements, layoutInformations);
foundSomethingToPrint = true;
} else if (printElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsContainment) {
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsContainment containment = (org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsContainment) printElement;
printContainedObject(eObject, containment, indexToPrint, foundFormattingElements, layoutInformations);
foundSomethingToPrint = true;
}
}
if (foundSomethingToPrint) {
foundSomethingAtAll = true;
}
if (printElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsWhiteSpace) {
foundFormattingElements.add((org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsWhiteSpace) printElement);
}
if (printElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsLineBreak) {
foundFormattingElements.add((org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsLineBreak) printElement);
}
for (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsSyntaxElementDecorator childDecorator : decorator.getChildDecorators()) {
foundSomethingToPrint |= printTree(childDecorator, eObject, foundFormattingElements, layoutInformations);
org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement decoratedElement = decorator.getDecoratedElement();
if (foundSomethingToPrint && decoratedElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsChoice) {
break;
}
}
if (cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.ONE || cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.QUESTIONMARK) {
break;
} else if (!foundSomethingToPrint) {
break;
}
}
// only print formatting elements if a feature was printed or the syntax element
// is mandatory
if (!foundSomethingAtAll && (cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.STAR || cardinality == org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsCardinality.QUESTIONMARK)) {
foundFormattingElements.clear();
foundFormattingElements.addAll(cloned);
}
return foundSomethingToPrint;
}
public void printKeyword(org.eclipse.emf.ecore.EObject eObject, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsKeyword keyword, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations) {
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation layoutInformation = getLayoutInformation(layoutInformations, keyword, null, eObject);
printFormattingElements(foundFormattingElements, layoutInformations, layoutInformation);
String value = keyword.getValue();
tokenOutputStream.add(new PrintToken(value, "'" + org.reuseware.air.language.abstractsyntax.resource.as.util.AsStringUtil.escapeToANTLRKeyword(value) + "'"));
}
public void printFeature(org.eclipse.emf.ecore.EObject eObject, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsPlaceholder placeholder, int count, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations) {
org.eclipse.emf.ecore.EStructuralFeature feature = placeholder.getFeature();
if (feature instanceof org.eclipse.emf.ecore.EAttribute) {
printAttribute(eObject, (org.eclipse.emf.ecore.EAttribute) feature, placeholder, count, foundFormattingElements, layoutInformations);
} else {
printReference(eObject, (org.eclipse.emf.ecore.EReference) feature, placeholder, count, foundFormattingElements, layoutInformations);
}
}
public void printAttribute(org.eclipse.emf.ecore.EObject eObject, org.eclipse.emf.ecore.EAttribute attribute, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsPlaceholder placeholder, int count, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations) {
java.lang.String result;
java.lang.Object attributeValue = getValue(eObject, attribute, count);
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation layoutInformation = getLayoutInformation(layoutInformations, placeholder, attributeValue, eObject);
java.lang.String visibleTokenText = getVisibleTokenText(layoutInformation);
// if there is text for the attribute we use it
if (visibleTokenText != null) {
result = visibleTokenText;
} else {
// if no text is available, the attribute is deresolved to obtain its textual
// representation
org.reuseware.air.language.abstractsyntax.resource.as.IAsTokenResolver tokenResolver = tokenResolverFactory.createTokenResolver(placeholder.getTokenName());
tokenResolver.setOptions(getOptions());
java.lang.String deResolvedValue = tokenResolver.deResolve(attributeValue, attribute, eObject);
result = deResolvedValue;
}
if (result != null && !"".equals(result)) {
printFormattingElements(foundFormattingElements, layoutInformations, layoutInformation);
}
// write result to the output stream
tokenOutputStream.add(new PrintToken(result, placeholder.getTokenName()));
}
public void printContainedObject(org.eclipse.emf.ecore.EObject eObject, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsContainment containment, int count, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations) {
org.eclipse.emf.ecore.EStructuralFeature reference = containment.getFeature();
java.lang.Object o = getValue(eObject, reference, count);
// save current number of tabs to restore them after printing the contained object
int oldTabsBeforeCurrentObject = tabsBeforeCurrentObject;
int oldCurrentTabs = currentTabs;
// use current number of tabs to indent contained object. we do not directly set
// 'tabsBeforeCurrentObject' because the first element of the new object must be
// printed with the old number of tabs.
newTabsBeforeCurrentObject = tabsBeforeCurrentObject + currentTabs;
currentTabs = 0;
doPrint((org.eclipse.emf.ecore.EObject) o, foundFormattingElements);
// restore number of tabs after printing the contained object
tabsBeforeCurrentObject = oldTabsBeforeCurrentObject;
currentTabs = oldCurrentTabs;
}
public void printFormattingElements(java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations, org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation layoutInformation) {
java.lang.String hiddenTokenText = getHiddenTokenText(layoutInformation);
if (hiddenTokenText != null) {
// removed used information
layoutInformations.remove(layoutInformation);
tokenOutputStream.add(new PrintToken(hiddenTokenText, null));
foundFormattingElements.clear();
startedPrintingObject = false;
tabsBeforeCurrentObject = newTabsBeforeCurrentObject;
return;
}
if (foundFormattingElements.size() > 0) {
for (org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement foundFormattingElement : foundFormattingElements) {
if (foundFormattingElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsWhiteSpace) {
int amount = ((org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsWhiteSpace) foundFormattingElement).getAmount();
for (int i = 0; i < amount; i++) {
tokenOutputStream.add(new PrintToken(" ", null));
}
}
if (foundFormattingElement instanceof org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsLineBreak) {
currentTabs = ((org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsLineBreak) foundFormattingElement).getTabs();
tokenOutputStream.add(new PrintToken(NEW_LINE, null));
for (int i = 0; i < tabsBeforeCurrentObject + currentTabs; i++) {
tokenOutputStream.add(new PrintToken("\t", null));
}
}
}
foundFormattingElements.clear();
startedPrintingObject = false;
} else {
if (startedPrintingObject) {
// if no elements have been printed yet, we do not add the default token space,
// because spaces before the first element are not desired.
startedPrintingObject = false;
} else {
if (!handleTokenSpaceAutomatically) {
tokenOutputStream.add(new PrintToken(getWhiteSpaceString(tokenSpace), null));
}
}
}
// after printing the first element, we can use the new number of tabs.
tabsBeforeCurrentObject = newTabsBeforeCurrentObject;
}
private Object getValue(org.eclipse.emf.ecore.EObject eObject, org.eclipse.emf.ecore.EStructuralFeature feature, int count) {
// get value of feature
java.lang.Object o = eObject.eGet(feature);
if (o instanceof java.util.List<?>) {
java.util.List<?> list = (java.util.List<?>) o;
int index = list.size() - count;
o = list.get(index);
}
return o;
}
@SuppressWarnings("unchecked")
public void printReference(org.eclipse.emf.ecore.EObject eObject, org.eclipse.emf.ecore.EReference reference, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsPlaceholder placeholder, int count, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsFormattingElement> foundFormattingElements, java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations) {
java.lang.Object referencedObject = getValue(eObject, reference, count);
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation layoutInformation = getLayoutInformation(layoutInformations, placeholder, referencedObject, eObject);
printFormattingElements(foundFormattingElements, layoutInformations, layoutInformation);
// NC-References must always be printed by deresolving the reference. We cannot
// use the visible token information, because deresolving usually depends on
// attribute values of the referenced object instead of the object itself.
String tokenName = placeholder.getTokenName();
org.reuseware.air.language.abstractsyntax.resource.as.IAsTokenResolver tokenResolver = tokenResolverFactory.createTokenResolver(tokenName);
tokenResolver.setOptions(getOptions());
@SuppressWarnings("rawtypes")
org.reuseware.air.language.abstractsyntax.resource.as.IAsReferenceResolver referenceResolver = getReferenceResolverSwitch().getResolver(reference);
referenceResolver.setOptions(getOptions());
java.lang.String deresolvedReference = referenceResolver.deResolve((org.eclipse.emf.ecore.EObject) referencedObject, eObject, reference);
java.lang.String deresolvedToken = tokenResolver.deResolve(deresolvedReference, reference, eObject);
// write result to output stream
tokenOutputStream.add(new PrintToken(deresolvedToken, tokenName));
}
public java.util.Map<java.lang.String, java.lang.Integer> initializePrintCountingMap(org.eclipse.emf.ecore.EObject eObject) {
// The printCountingMap contains a mapping from feature names to the number of
// remaining elements that still need to be printed. The map is initialized with
// the number of elements stored in each structural feature. For lists this is the
// list size. For non-multiple features it is either 1 (if the feature is set) or
// 0 (if the feature is null).
java.util.Map<java.lang.String, java.lang.Integer> printCountingMap = new java.util.LinkedHashMap<java.lang.String, java.lang.Integer>();
java.util.List<org.eclipse.emf.ecore.EStructuralFeature> features = eObject.eClass().getEAllStructuralFeatures();
for (org.eclipse.emf.ecore.EStructuralFeature feature : features) {
int count = 0;
java.lang.Object featureValue = eObject.eGet(feature);
if (featureValue != null) {
if (featureValue instanceof java.util.List<?>) {
count = ((java.util.List<?>) featureValue).size();
} else {
count = 1;
}
}
printCountingMap.put(feature.getName(), count);
}
return printCountingMap;
}
public java.util.Map<?,?> getOptions() {
return options;
}
public void setOptions(java.util.Map<?,?> options) {
this.options = options;
}
public org.reuseware.air.language.abstractsyntax.resource.as.IAsTextResource getResource() {
return resource;
}
protected org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsReferenceResolverSwitch getReferenceResolverSwitch() {
return (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsReferenceResolverSwitch) new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsMetaInformation().getReferenceResolverSwitch();
}
protected void addWarningToResource(final java.lang.String errorMessage, org.eclipse.emf.ecore.EObject cause) {
org.reuseware.air.language.abstractsyntax.resource.as.IAsTextResource resource = getResource();
if (resource == null) {
// the resource can be null if the printer is used stand alone
return;
}
resource.addProblem(new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsProblem(errorMessage, org.reuseware.air.language.abstractsyntax.resource.as.AsEProblemType.ERROR), cause);
}
protected org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformationAdapter getLayoutInformationAdapter(org.eclipse.emf.ecore.EObject element) {
for (org.eclipse.emf.common.notify.Adapter adapter : element.eAdapters()) {
if (adapter instanceof org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformationAdapter) {
return (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformationAdapter) adapter;
}
}
org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformationAdapter newAdapter = new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformationAdapter();
element.eAdapters().add(newAdapter);
return newAdapter;
}
private org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation getLayoutInformation(java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation> layoutInformations, org.reuseware.air.language.abstractsyntax.resource.as.grammar.AsSyntaxElement syntaxElement, java.lang.Object object, org.eclipse.emf.ecore.EObject container) {
for (org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation layoutInformation : layoutInformations) {
if (syntaxElement == layoutInformation.getSyntaxElement()) {
if (object == null) {
return layoutInformation;
} else if (object == layoutInformation.getObject(container)) {
return layoutInformation;
}
}
}
return null;
}
private java.lang.String getHiddenTokenText(org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation layoutInformation) {
if (layoutInformation != null) {
return layoutInformation.getHiddenTokenText();
} else {
return null;
}
}
private java.lang.String getVisibleTokenText(org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsLayoutInformation layoutInformation) {
if (layoutInformation != null) {
return layoutInformation.getVisibleTokenText();
} else {
return null;
}
}
protected String getWhiteSpaceString(int count) {
return getRepeatingString(count, ' ');
}
private String getRepeatingString(int count, char character) {
StringBuffer result = new StringBuffer();
for (int i = 0; i < count; i++) {
result.append(character);
}
return result.toString();
}
public void setHandleTokenSpaceAutomatically(boolean handleTokenSpaceAutomatically) {
this.handleTokenSpaceAutomatically = handleTokenSpaceAutomatically;
}
public void setTokenSpace(int tokenSpace) {
this.tokenSpace = tokenSpace;
}
/**
* Prints the current tokenOutputStream to the given writer (as it is).
*/
public void printBasic(java.io.PrintWriter writer) throws java.io.IOException {
for (PrintToken nextToken : tokenOutputStream) {
writer.write(nextToken.getText());
}
}
/**
* Prints the current tokenOutputStream to the given writer.
*
* This methods implements smart whitespace printing. It does so by writing output
* to a token stream instead of printing the raw token text to a PrintWriter.
* Tokens in this stream hold both the text and the type of the token (i.e., its
* name).
*
* To decide where whitespace is needed, sequences of successive tokens are
* searched that can be printed without separating whitespace. To determine such
* groups we start with two successive non-whitespace tokens, concatenate their
* text and use the generated ANTLR lexer to split the text. If the resulting
* token sequence of the concatenated text is exactly the same as the one that is
* to be printed, no whitespace is needed. The tokens in the sequence are checked
* both regarding their type and their text. If two tokens successfully form a
* group a third one is added and so on.
*/
public void printSmart(java.io.PrintWriter writer) throws java.io.IOException {
// stores the text of the current group of tokens. this text is given to the lexer
// to check whether it can be correctly scanned.
StringBuilder currentBlock = new StringBuilder();
// stores the index of the first token of the current group.
int currentBlockStart = 0;
// stores the text that was already successfully checked (i.e., is can be scanned
// correctly and can thus be printed).
String validBlock = "";
for (int i = 0; i < tokenOutputStream.size(); i++) {
PrintToken tokenI = tokenOutputStream.get(i);
currentBlock.append(tokenI.getText());
// if declared or preserved whitespace is found - print block
if (tokenI.getTokenName() == null) {
writer.write(currentBlock.toString());
// reset all values
currentBlock = new StringBuilder();
currentBlockStart = i + 1;
validBlock = "";
continue;
}
// now check whether the current block can be scanned
org.reuseware.air.language.abstractsyntax.resource.as.IAsTextScanner scanner = new org.reuseware.air.language.abstractsyntax.resource.as.mopp.AsMetaInformation().createLexer();
scanner.setText(currentBlock.toString());
// retrieve all tokens from scanner and add them to list 'tempTokens'
java.util.List<org.reuseware.air.language.abstractsyntax.resource.as.IAsTextToken> tempTokens = new java.util.ArrayList<org.reuseware.air.language.abstractsyntax.resource.as.IAsTextToken>();
org.reuseware.air.language.abstractsyntax.resource.as.IAsTextToken nextToken = scanner.getNextToken();
while (nextToken != null && nextToken.getText() != null) {
tempTokens.add(nextToken);
nextToken = scanner.getNextToken();
}
boolean sequenceIsValid = true;
// check whether the current block was scanned to the same token sequence
for (int t = 0; t < tempTokens.size(); t++) {
PrintToken printTokenT = tokenOutputStream.get(currentBlockStart + t);
org.reuseware.air.language.abstractsyntax.resource.as.IAsTextToken tempToken = tempTokens.get(t);
if (!tempToken.getText().equals(printTokenT.getText())) {
sequenceIsValid = false;
break;
}
String commonTokenName = tempToken.getName();
String printTokenName = printTokenT.getTokenName();
if (printTokenName.length() > 2 && printTokenName.startsWith("'") && printTokenName.endsWith("'")) {
printTokenName = printTokenName.substring(1, printTokenName.length() - 1);
}
if (!commonTokenName.equals(printTokenName)) {
sequenceIsValid = false;
break;
}
}
if (sequenceIsValid) {
// sequence is still valid, try adding one more token in the next iteration of the
// loop
validBlock += tokenI.getText();
} else {
// sequence is not valid, must print whitespace to separate tokens
// print text that is valid so far
writer.write(validBlock);
// print separating whitespace
writer.write(" ");
// add current token as initial value for next iteration
currentBlock = new StringBuilder(tokenI.getText());
currentBlockStart = i;
validBlock = tokenI.getText();
}
}
// flush remaining valid text to writer
writer.write(validBlock);
}
}