/**
* <copyright>
* </copyright>
*
*
*/
package ssl.resource.ssl.mopp;
public class SslPrinter2 implements ssl.resource.ssl.ISslTextPrinter {
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 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 ssl.resource.ssl.ISslTextResource resource;
private java.util.Map<?, ?> options;
private java.io.OutputStream outputStream;
private java.util.List<PrintToken> tokenOutputStream;
private ssl.resource.ssl.ISslTokenResolverFactory tokenResolverFactory = new ssl.resource.ssl.mopp.SslTokenResolverFactory();
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 that were printed before the current line. This
* number is used to calculate the relative indentation when printing contained
* objects, because all contained objects must start with this indentation
* (tabsBeforeCurrentObject + currentTabs).
*/
private int currentTabs;
/**
* The number of tab characters that must be printed before the current object.
* This number is used to calculate the indentation of new lines, when line breaks
* are printed within one object.
*/
private int tabsBeforeCurrentObject;
private int newTabsBeforeCurrentObject;
public SslPrinter2(java.io.OutputStream outputStream, ssl.resource.ssl.ISslTextResource 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<ssl.resource.ssl.grammar.SslFormattingElement>());
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<ssl.resource.ssl.grammar.SslFormattingElement> 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 ssl.Specification) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_0, foundFormattingElements);
return;
}
if (element instanceof ssl.Testcase) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_1, foundFormattingElements);
return;
}
if (element instanceof ssl.Given) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_2, foundFormattingElements);
return;
}
if (element instanceof ssl.When) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_3, foundFormattingElements);
return;
}
if (element instanceof ssl.Then) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_4, foundFormattingElements);
return;
}
if (element instanceof ssl.CheckMode) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_5, foundFormattingElements);
return;
}
if (element instanceof ssl.CheckLabel) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_6, foundFormattingElements);
return;
}
if (element instanceof ssl.CheckVariableEqualsVariable) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_7, foundFormattingElements);
return;
}
if (element instanceof ssl.CheckVariableEqualsTime) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_8, foundFormattingElements);
return;
}
if (element instanceof ssl.EntersMode) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_9, foundFormattingElements);
return;
}
if (element instanceof ssl.PressButton) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_10, foundFormattingElements);
return;
}
if (element instanceof ssl.ObserveMode) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_11, foundFormattingElements);
return;
}
if (element instanceof ssl.ObserveButton) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_12, foundFormattingElements);
return;
}
if (element instanceof ssl.ObserveLabelValue) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_13, foundFormattingElements);
return;
}
if (element instanceof ssl.ObserveLabelVariable) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_14, foundFormattingElements);
return;
}
if (element instanceof ssl.ObserveVariableChange) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_15, foundFormattingElements);
return;
}
if (element instanceof ssl.ObserveRing) {
printInternal(element, ssl.resource.ssl.grammar.SslGrammarInformationProvider.SSL_16, foundFormattingElements);
return;
}
addWarningToResource("The printer can not handle " + element.eClass().getName() + " elements", element);
}
public void printInternal(org.eclipse.emf.ecore.EObject eObject, ssl.resource.ssl.grammar.SslSyntaxElement ruleElement, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements) {
ssl.resource.ssl.mopp.SslLayoutInformationAdapter layoutInformationAdapter = getLayoutInformationAdapter(eObject);
java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> 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<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations = new java.util.ArrayList<ssl.resource.ssl.mopp.SslLayoutInformation>(originalLayoutInformations.size());
layoutInformations.addAll(originalLayoutInformations);
ssl.resource.ssl.mopp.SslSyntaxElementDecorator 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 ssl.resource.ssl.mopp.SslSyntaxElementDecorator getDecoratorTree(ssl.resource.ssl.grammar.SslSyntaxElement syntaxElement) {
ssl.resource.ssl.grammar.SslSyntaxElement[] children = syntaxElement.getChildren();
int childCount = children.length;
ssl.resource.ssl.mopp.SslSyntaxElementDecorator[] childDecorators = new ssl.resource.ssl.mopp.SslSyntaxElementDecorator[childCount];
for (int i = 0; i < childCount; i++) {
childDecorators[i] = getDecoratorTree(children[i]);
}
ssl.resource.ssl.mopp.SslSyntaxElementDecorator decorator = new ssl.resource.ssl.mopp.SslSyntaxElementDecorator(syntaxElement, childDecorators);
return decorator;
}
public void decorateTree(ssl.resource.ssl.mopp.SslSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject) {
java.util.Map<String, Integer> printCountingMap = initializePrintCountingMap(eObject);
java.util.List<ssl.resource.ssl.mopp.SslSyntaxElementDecorator> keywordsToPrint = new java.util.ArrayList<ssl.resource.ssl.mopp.SslSyntaxElementDecorator>();
decorateTreeBasic(decorator, eObject, printCountingMap, keywordsToPrint);
for (ssl.resource.ssl.mopp.SslSyntaxElementDecorator 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(ssl.resource.ssl.mopp.SslSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject, java.util.Map<String, Integer> printCountingMap, java.util.List<ssl.resource.ssl.mopp.SslSyntaxElementDecorator> keywordsToPrint) {
boolean foundFeatureToPrint = false;
ssl.resource.ssl.grammar.SslSyntaxElement syntaxElement = decorator.getDecoratedElement();
ssl.resource.ssl.grammar.SslCardinality cardinality = syntaxElement.getCardinality();
boolean isFirstIteration = true;
while (true) {
java.util.List<ssl.resource.ssl.mopp.SslSyntaxElementDecorator> subKeywordsToPrint = new java.util.ArrayList<ssl.resource.ssl.mopp.SslSyntaxElementDecorator>();
boolean keepDecorating = false;
if (syntaxElement instanceof ssl.resource.ssl.grammar.SslKeyword) {
subKeywordsToPrint.add(decorator);
} else if (syntaxElement instanceof ssl.resource.ssl.grammar.SslTerminal) {
ssl.resource.ssl.grammar.SslTerminal terminal = (ssl.resource.ssl.grammar.SslTerminal) syntaxElement;
org.eclipse.emf.ecore.EStructuralFeature feature = terminal.getFeature();
if (feature == ssl.resource.ssl.grammar.SslGrammarInformationProvider.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 ssl.resource.ssl.grammar.SslChoice) {
// for choices we do print only the choice which does print at least one feature
ssl.resource.ssl.mopp.SslSyntaxElementDecorator childToPrint = null;
for (ssl.resource.ssl.mopp.SslSyntaxElementDecorator 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 (ssl.resource.ssl.mopp.SslSyntaxElementDecorator 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 == ssl.resource.ssl.grammar.SslCardinality.ONE) {
keywordsToPrint.addAll(subKeywordsToPrint);
} else if (cardinality == ssl.resource.ssl.grammar.SslCardinality.PLUS) {
if (isFirstIteration) {
keywordsToPrint.addAll(subKeywordsToPrint);
} else {
if (keepDecorating) {
keywordsToPrint.addAll(subKeywordsToPrint);
}
}
} else if (keepDecorating && (cardinality == ssl.resource.ssl.grammar.SslCardinality.STAR || cardinality == ssl.resource.ssl.grammar.SslCardinality.QUESTIONMARK)) {
keywordsToPrint.addAll(subKeywordsToPrint);
}
if (cardinality == ssl.resource.ssl.grammar.SslCardinality.ONE || cardinality == ssl.resource.ssl.grammar.SslCardinality.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(ssl.resource.ssl.mopp.SslSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject, java.util.Map<String, Integer> printCountingMap) {
ssl.resource.ssl.grammar.SslSyntaxElement syntaxElement = decorator.getDecoratedElement();
if (syntaxElement instanceof ssl.resource.ssl.grammar.SslTerminal) {
ssl.resource.ssl.grammar.SslTerminal terminal = (ssl.resource.ssl.grammar.SslTerminal) syntaxElement;
org.eclipse.emf.ecore.EStructuralFeature feature = terminal.getFeature();
if (feature == ssl.resource.ssl.grammar.SslGrammarInformationProvider.ANONYMOUS_FEATURE) {
return false;
}
int countLeft = printCountingMap.get(feature.getName());
if (countLeft > terminal.getMandatoryOccurencesAfter()) {
// found a feature to print
return true;
}
}
for (ssl.resource.ssl.mopp.SslSyntaxElementDecorator childDecorator : decorator.getChildDecorators()) {
if (doesPrintFeature(childDecorator, eObject, printCountingMap)) {
return true;
}
}
return false;
}
public boolean printTree(ssl.resource.ssl.mopp.SslSyntaxElementDecorator decorator, org.eclipse.emf.ecore.EObject eObject, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations) {
ssl.resource.ssl.grammar.SslSyntaxElement printElement = decorator.getDecoratedElement();
ssl.resource.ssl.grammar.SslCardinality cardinality = printElement.getCardinality();
java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> cloned = new java.util.ArrayList<ssl.resource.ssl.grammar.SslFormattingElement>();
cloned.addAll(foundFormattingElements);
boolean foundSomethingAtAll = false;
boolean foundSomethingToPrint;
while (true) {
foundSomethingToPrint = false;
Integer indexToPrint = decorator.getNextIndexToPrint();
if (indexToPrint != null) {
if (printElement instanceof ssl.resource.ssl.grammar.SslKeyword) {
printKeyword(eObject, (ssl.resource.ssl.grammar.SslKeyword) printElement, foundFormattingElements, layoutInformations);
foundSomethingToPrint = true;
} else if (printElement instanceof ssl.resource.ssl.grammar.SslPlaceholder) {
ssl.resource.ssl.grammar.SslPlaceholder placeholder = (ssl.resource.ssl.grammar.SslPlaceholder) printElement;
printFeature(eObject, placeholder, indexToPrint, foundFormattingElements, layoutInformations);
foundSomethingToPrint = true;
} else if (printElement instanceof ssl.resource.ssl.grammar.SslContainment) {
ssl.resource.ssl.grammar.SslContainment containment = (ssl.resource.ssl.grammar.SslContainment) printElement;
printContainedObject(eObject, containment, indexToPrint, foundFormattingElements, layoutInformations);
foundSomethingToPrint = true;
} else if (printElement instanceof ssl.resource.ssl.grammar.SslBooleanTerminal) {
ssl.resource.ssl.grammar.SslBooleanTerminal booleanTerminal = (ssl.resource.ssl.grammar.SslBooleanTerminal) printElement;
printBooleanTerminal(eObject, booleanTerminal, indexToPrint, foundFormattingElements, layoutInformations);
foundSomethingToPrint = true;
}
}
if (foundSomethingToPrint) {
foundSomethingAtAll = true;
}
if (printElement instanceof ssl.resource.ssl.grammar.SslWhiteSpace) {
foundFormattingElements.add((ssl.resource.ssl.grammar.SslWhiteSpace) printElement);
}
if (printElement instanceof ssl.resource.ssl.grammar.SslLineBreak) {
foundFormattingElements.add((ssl.resource.ssl.grammar.SslLineBreak) printElement);
}
for (ssl.resource.ssl.mopp.SslSyntaxElementDecorator childDecorator : decorator.getChildDecorators()) {
foundSomethingToPrint |= printTree(childDecorator, eObject, foundFormattingElements, layoutInformations);
ssl.resource.ssl.grammar.SslSyntaxElement decoratedElement = decorator.getDecoratedElement();
if (foundSomethingToPrint && decoratedElement instanceof ssl.resource.ssl.grammar.SslChoice) {
break;
}
}
if (cardinality == ssl.resource.ssl.grammar.SslCardinality.ONE || cardinality == ssl.resource.ssl.grammar.SslCardinality.QUESTIONMARK) {
break;
} else if (!foundSomethingToPrint) {
break;
}
}
// only print formatting elements if a feature was printed or the syntax element
// is mandatory
if (!foundSomethingAtAll && (cardinality == ssl.resource.ssl.grammar.SslCardinality.STAR || cardinality == ssl.resource.ssl.grammar.SslCardinality.QUESTIONMARK)) {
foundFormattingElements.clear();
foundFormattingElements.addAll(cloned);
}
return foundSomethingToPrint;
}
public void printKeyword(org.eclipse.emf.ecore.EObject eObject, ssl.resource.ssl.grammar.SslKeyword keyword, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations) {
ssl.resource.ssl.mopp.SslLayoutInformation layoutInformation = getLayoutInformation(layoutInformations, keyword, null, eObject);
printFormattingElements(foundFormattingElements, layoutInformations, layoutInformation);
String value = keyword.getValue();
tokenOutputStream.add(new PrintToken(value, "'" + ssl.resource.ssl.util.SslStringUtil.escapeToANTLRKeyword(value) + "'"));
}
public void printFeature(org.eclipse.emf.ecore.EObject eObject, ssl.resource.ssl.grammar.SslPlaceholder placeholder, int count, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> 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, ssl.resource.ssl.grammar.SslPlaceholder placeholder, int count, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations) {
String result;
Object attributeValue = getValue(eObject, attribute, count);
ssl.resource.ssl.mopp.SslLayoutInformation layoutInformation = getLayoutInformation(layoutInformations, placeholder, attributeValue, eObject);
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
ssl.resource.ssl.ISslTokenResolver tokenResolver = tokenResolverFactory.createTokenResolver(placeholder.getTokenName());
tokenResolver.setOptions(getOptions());
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 printBooleanTerminal(org.eclipse.emf.ecore.EObject eObject, ssl.resource.ssl.grammar.SslBooleanTerminal booleanTerminal, int count, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations) {
org.eclipse.emf.ecore.EAttribute attribute = booleanTerminal.getAttribute();
String result;
Object attributeValue = getValue(eObject, attribute, count);
ssl.resource.ssl.mopp.SslLayoutInformation layoutInformation = getLayoutInformation(layoutInformations, booleanTerminal, attributeValue, eObject);
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 boolean attribute is converted to its textual
// representation using the literals of the boolean terminal
if (Boolean.TRUE.equals(attributeValue)) {
result = booleanTerminal.getTrueLiteral();
} else {
result = booleanTerminal.getFalseLiteral();
}
}
if (result != null && !"".equals(result)) {
printFormattingElements(foundFormattingElements, layoutInformations, layoutInformation);
// write result to the output stream
tokenOutputStream.add(new PrintToken(result, "'" + ssl.resource.ssl.util.SslStringUtil.escapeToANTLRKeyword(result) + "'"));
}
}
public void printContainedObject(org.eclipse.emf.ecore.EObject eObject, ssl.resource.ssl.grammar.SslContainment containment, int count, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations) {
org.eclipse.emf.ecore.EStructuralFeature reference = containment.getFeature();
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;
newTabsBeforeCurrentObject = tabsBeforeCurrentObject;
currentTabs = oldCurrentTabs;
}
public void printFormattingElements(java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations, ssl.resource.ssl.mopp.SslLayoutInformation layoutInformation) {
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 (ssl.resource.ssl.grammar.SslFormattingElement foundFormattingElement : foundFormattingElements) {
if (foundFormattingElement instanceof ssl.resource.ssl.grammar.SslWhiteSpace) {
int amount = ((ssl.resource.ssl.grammar.SslWhiteSpace) foundFormattingElement).getAmount();
for (int i = 0; i < amount; i++) {
tokenOutputStream.add(new PrintToken(" ", null));
}
}
if (foundFormattingElement instanceof ssl.resource.ssl.grammar.SslLineBreak) {
currentTabs = ((ssl.resource.ssl.grammar.SslLineBreak) 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
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, ssl.resource.ssl.grammar.SslPlaceholder placeholder, int count, java.util.List<ssl.resource.ssl.grammar.SslFormattingElement> foundFormattingElements, java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations) {
Object referencedObject = getValue(eObject, reference, count);
ssl.resource.ssl.mopp.SslLayoutInformation 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();
ssl.resource.ssl.ISslTokenResolver tokenResolver = tokenResolverFactory.createTokenResolver(tokenName);
tokenResolver.setOptions(getOptions());
@SuppressWarnings("rawtypes")
ssl.resource.ssl.ISslReferenceResolver referenceResolver = getReferenceResolverSwitch().getResolver(reference);
referenceResolver.setOptions(getOptions());
String deresolvedReference = referenceResolver.deResolve((org.eclipse.emf.ecore.EObject) referencedObject, eObject, reference);
String deresolvedToken = tokenResolver.deResolve(deresolvedReference, reference, eObject);
// write result to output stream
tokenOutputStream.add(new PrintToken(deresolvedToken, tokenName));
}
public java.util.Map<String, 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<String, Integer> printCountingMap = new java.util.LinkedHashMap<String, Integer>();
java.util.List<org.eclipse.emf.ecore.EStructuralFeature> features = eObject.eClass().getEAllStructuralFeatures();
for (org.eclipse.emf.ecore.EStructuralFeature feature : features) {
int count = 0;
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 ssl.resource.ssl.ISslTextResource getResource() {
return resource;
}
protected ssl.resource.ssl.mopp.SslReferenceResolverSwitch getReferenceResolverSwitch() {
return (ssl.resource.ssl.mopp.SslReferenceResolverSwitch) new ssl.resource.ssl.mopp.SslMetaInformation().getReferenceResolverSwitch();
}
protected void addWarningToResource(final String errorMessage, org.eclipse.emf.ecore.EObject cause) {
ssl.resource.ssl.ISslTextResource resource = getResource();
if (resource == null) {
// the resource can be null if the printer is used stand alone
return;
}
resource.addProblem(new ssl.resource.ssl.mopp.SslProblem(errorMessage, ssl.resource.ssl.SslEProblemType.ERROR), cause);
}
protected ssl.resource.ssl.mopp.SslLayoutInformationAdapter getLayoutInformationAdapter(org.eclipse.emf.ecore.EObject element) {
for (org.eclipse.emf.common.notify.Adapter adapter : element.eAdapters()) {
if (adapter instanceof ssl.resource.ssl.mopp.SslLayoutInformationAdapter) {
return (ssl.resource.ssl.mopp.SslLayoutInformationAdapter) adapter;
}
}
ssl.resource.ssl.mopp.SslLayoutInformationAdapter newAdapter = new ssl.resource.ssl.mopp.SslLayoutInformationAdapter();
element.eAdapters().add(newAdapter);
return newAdapter;
}
private ssl.resource.ssl.mopp.SslLayoutInformation getLayoutInformation(java.util.List<ssl.resource.ssl.mopp.SslLayoutInformation> layoutInformations, ssl.resource.ssl.grammar.SslSyntaxElement syntaxElement, Object object, org.eclipse.emf.ecore.EObject container) {
for (ssl.resource.ssl.mopp.SslLayoutInformation layoutInformation : layoutInformations) {
if (syntaxElement == layoutInformation.getSyntaxElement()) {
if (object == null) {
return layoutInformation;
} else if (object == layoutInformation.getObject(container)) {
return layoutInformation;
}
}
}
return null;
}
private String getHiddenTokenText(ssl.resource.ssl.mopp.SslLayoutInformation layoutInformation) {
if (layoutInformation != null) {
return layoutInformation.getHiddenTokenText();
} else {
return null;
}
}
private String getVisibleTokenText(ssl.resource.ssl.mopp.SslLayoutInformation 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
ssl.resource.ssl.ISslTextScanner scanner = new ssl.resource.ssl.mopp.SslMetaInformation().createLexer();
scanner.setText(currentBlock.toString());
// retrieve all tokens from scanner and add them to list 'tempTokens'
java.util.List<ssl.resource.ssl.ISslTextToken> tempTokens = new java.util.ArrayList<ssl.resource.ssl.ISslTextToken>();
ssl.resource.ssl.ISslTextToken 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);
ssl.resource.ssl.ISslTextToken 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);
}
}