[nodemodel] Make node model serializable

applied patch https://bugs.eclipse.org/bugs/attachment.cgi?id=212979
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=359824
This commit is contained in:
Jan Koehnlein 2012-04-20 12:09:28 +02:00
parent 0791813424
commit f56b26ff2d
16 changed files with 1147 additions and 94 deletions

View file

@ -1,90 +1,90 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.xtext;singleton:=true
Bundle-Version: 2.3.0.qualifier
Bundle-ClassPath: .
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: org.eclipse.xtext,
org.eclipse.xtext.common,
org.eclipse.xtext.common.parseTreeConstruction,
org.eclipse.xtext.common.parser.packrat;x-internal:=true,
org.eclipse.xtext.common.parser.packrat.consumers;x-internal:=true,
org.eclipse.xtext.common.services,
org.eclipse.xtext.conversion,
org.eclipse.xtext.conversion.impl,
org.eclipse.xtext.debug;x-internal:=true,
org.eclipse.xtext.diagnostics,
org.eclipse.xtext.documentation,
org.eclipse.xtext.documentation.impl,
org.eclipse.xtext.formatting,
org.eclipse.xtext.formatting.impl,
org.eclipse.xtext.generator,
org.eclipse.xtext.generator.trace;x-internal:=true,
org.eclipse.xtext.grammaranalysis;x-internal:=true,
org.eclipse.xtext.grammaranalysis.impl;x-internal:=true,
org.eclipse.xtext.impl,
org.eclipse.xtext.internal;x-internal:=true,
org.eclipse.xtext.linking,
org.eclipse.xtext.linking.impl,
org.eclipse.xtext.linking.lazy,
org.eclipse.xtext.mwe,
org.eclipse.xtext.naming,
org.eclipse.xtext.nodemodel,
org.eclipse.xtext.nodemodel.impl,
org.eclipse.xtext.nodemodel.util,
org.eclipse.xtext.parseTreeConstruction;x-internal:=true,
org.eclipse.xtext.parser,
org.eclipse.xtext.parser.antlr,
org.eclipse.xtext.parser.antlr.internal;x-internal:=true,
org.eclipse.xtext.parser.impl,
org.eclipse.xtext.parser.packrat;x-internal:=true,
org.eclipse.xtext.parser.packrat.consumers;x-internal:=true,
org.eclipse.xtext.parser.packrat.debug;x-internal:=true,
org.eclipse.xtext.parser.packrat.internal;x-internal:=true,
org.eclipse.xtext.parser.packrat.matching;x-internal:=true,
org.eclipse.xtext.parser.packrat.tokens;x-internal:=true,
org.eclipse.xtext.parsetree.reconstr,
org.eclipse.xtext.parsetree.reconstr.impl,
org.eclipse.xtext.resource,
org.eclipse.xtext.resource.containers,
org.eclipse.xtext.resource.generic,
org.eclipse.xtext.resource.impl,
org.eclipse.xtext.scoping,
org.eclipse.xtext.scoping.impl,
org.eclipse.xtext.serializer,
org.eclipse.xtext.serializer.acceptor;x-internal:=true,
org.eclipse.xtext.serializer.analysis;x-internal:=true,
org.eclipse.xtext.serializer.diagnostic;x-internal:=true,
org.eclipse.xtext.serializer.impl;x-internal:=true,
org.eclipse.xtext.serializer.sequencer;x-internal:=true,
org.eclipse.xtext.serializer.tokens;x-internal:=true,
org.eclipse.xtext.service,
org.eclipse.xtext.services;x-internal:=true,
org.eclipse.xtext.util,
org.eclipse.xtext.validation,
org.eclipse.xtext.validation.impl,
org.eclipse.xtext.xtext;x-internal:=true,
org.eclipse.xtext.xtext.ecoreInference;x-internal:=true
Require-Bundle: org.eclipse.emf.ecore.xmi;visibility:=reexport,
org.eclipse.emf.ecore;bundle-version="2.5.0";visibility:=reexport,
org.eclipse.xtext.util;bundle-version="2.0.0";visibility:=reexport,
org.antlr.runtime;bundle-version="[3.2.0,3.2.1)";visibility:=reexport,
com.google.inject;bundle-version="2.0.0";resolution:=optional;visibility:=reexport,
org.eclipse.emf.codegen;bundle-version="2.5.0";resolution:=optional,
org.eclipse.emf.codegen.ecore;bundle-version="2.5.0";resolution:=optional,
org.eclipse.emf.mwe.core;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
org.eclipse.emf.mwe.utils;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
org.eclipse.emf.common,
org.eclipse.xtend;bundle-version="1.1.0";resolution:=optional,
org.eclipse.xtend.typesystem.emf;bundle-version="1.0.1";resolution:=optional,
org.eclipse.core.runtime;bundle-version="3.5.0";resolution:=optional,
org.eclipse.core.resources;bundle-version="3.5.0";resolution:=optional,
org.eclipse.jdt.annotation;bundle-version="1.0.0";resolution:=optional,
org.eclipse.xtext.smap;bundle-version="2.3.0";resolution:=optional
Import-Package: org.apache.log4j;version="1.2.15"
Bundle-ActivationPolicy: lazy
Bundle-Activator: org.eclipse.xtext.internal.Activator
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.xtext;singleton:=true
Bundle-Version: 2.3.0.qualifier
Bundle-ClassPath: .
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: org.eclipse.xtext,
org.eclipse.xtext.common,
org.eclipse.xtext.common.parseTreeConstruction,
org.eclipse.xtext.common.parser.packrat;x-internal:=true,
org.eclipse.xtext.common.parser.packrat.consumers;x-internal:=true,
org.eclipse.xtext.common.services,
org.eclipse.xtext.conversion,
org.eclipse.xtext.conversion.impl,
org.eclipse.xtext.debug;x-internal:=true,
org.eclipse.xtext.diagnostics,
org.eclipse.xtext.documentation,
org.eclipse.xtext.documentation.impl,
org.eclipse.xtext.formatting,
org.eclipse.xtext.formatting.impl,
org.eclipse.xtext.generator,
org.eclipse.xtext.generator.trace;x-internal:=true,
org.eclipse.xtext.grammaranalysis;x-internal:=true,
org.eclipse.xtext.grammaranalysis.impl;x-internal:=true,
org.eclipse.xtext.impl,
org.eclipse.xtext.internal;x-internal:=true,
org.eclipse.xtext.linking,
org.eclipse.xtext.linking.impl,
org.eclipse.xtext.linking.lazy,
org.eclipse.xtext.mwe,
org.eclipse.xtext.naming,
org.eclipse.xtext.nodemodel,
org.eclipse.xtext.nodemodel.impl,
org.eclipse.xtext.nodemodel.serialization;x-friends:="org.eclipse.xtext.builder,org.eclipse.xtext.tests",
org.eclipse.xtext.nodemodel.util,
org.eclipse.xtext.parseTreeConstruction;x-internal:=true,
org.eclipse.xtext.parser,
org.eclipse.xtext.parser.antlr,
org.eclipse.xtext.parser.antlr.internal;x-internal:=true,
org.eclipse.xtext.parser.impl,
org.eclipse.xtext.parser.packrat;x-internal:=true,
org.eclipse.xtext.parser.packrat.consumers;x-internal:=true,
org.eclipse.xtext.parser.packrat.debug;x-internal:=true,
org.eclipse.xtext.parser.packrat.internal;x-internal:=true,
org.eclipse.xtext.parser.packrat.matching;x-internal:=true,
org.eclipse.xtext.parser.packrat.tokens;x-internal:=true,
org.eclipse.xtext.parsetree.reconstr,
org.eclipse.xtext.parsetree.reconstr.impl,
org.eclipse.xtext.resource,
org.eclipse.xtext.resource.containers,
org.eclipse.xtext.resource.generic,
org.eclipse.xtext.resource.impl,
org.eclipse.xtext.scoping,
org.eclipse.xtext.scoping.impl,
org.eclipse.xtext.serializer,
org.eclipse.xtext.serializer.acceptor;x-internal:=true,
org.eclipse.xtext.serializer.analysis;x-internal:=true,
org.eclipse.xtext.serializer.diagnostic;x-internal:=true,
org.eclipse.xtext.serializer.impl;x-internal:=true,
org.eclipse.xtext.serializer.sequencer;x-internal:=true,
org.eclipse.xtext.serializer.tokens;x-internal:=true,
org.eclipse.xtext.service,
org.eclipse.xtext.services;x-internal:=true,
org.eclipse.xtext.util,
org.eclipse.xtext.validation,
org.eclipse.xtext.validation.impl,
org.eclipse.xtext.xtext;x-internal:=true,
org.eclipse.xtext.xtext.ecoreInference;x-internal:=true
Require-Bundle: org.eclipse.emf.ecore.xmi;visibility:=reexport,
org.eclipse.emf.ecore;bundle-version="2.5.0";visibility:=reexport,
org.eclipse.xtext.util;bundle-version="2.0.0";visibility:=reexport,
org.antlr.runtime;bundle-version="[3.2.0,3.2.1)";visibility:=reexport,
com.google.inject;bundle-version="2.0.0";resolution:=optional;visibility:=reexport,
org.eclipse.emf.codegen;bundle-version="2.5.0";resolution:=optional,
org.eclipse.emf.codegen.ecore;bundle-version="2.5.0";resolution:=optional,
org.eclipse.emf.mwe.core;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
org.eclipse.emf.mwe.utils;bundle-version="1.2.0";resolution:=optional;visibility:=reexport,
org.eclipse.emf.common,
org.eclipse.xtend;bundle-version="1.1.0";resolution:=optional,
org.eclipse.xtend.typesystem.emf;bundle-version="1.0.1";resolution:=optional,
org.eclipse.core.runtime;bundle-version="3.5.0";resolution:=optional,
org.eclipse.core.resources;bundle-version="3.5.0";resolution:=optional,
org.eclipse.jdt.annotation;bundle-version="1.0.0";resolution:=optional,
org.eclipse.xtext.smap;bundle-version="2.3.0";resolution:=optional
Import-Package: org.apache.log4j;version="1.2.15"
Bundle-ActivationPolicy: lazy
Bundle-Activator: org.eclipse.xtext.internal.Activator

View file

@ -7,10 +7,17 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.nodemodel.BidiIterator;
import org.eclipse.xtext.nodemodel.BidiTreeIterable;
import org.eclipse.xtext.nodemodel.BidiTreeIterator;
@ -18,6 +25,9 @@ import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
import org.eclipse.xtext.nodemodel.util.NodeTreeIterator;
import org.eclipse.xtext.nodemodel.util.ReversedBidiTreeIterable;
import org.eclipse.xtext.util.Strings;
@ -26,6 +36,7 @@ import com.google.common.collect.Iterators;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public abstract class AbstractNode implements INode, BidiTreeIterable<INode> {
@ -174,7 +185,7 @@ public abstract class AbstractNode implements INode, BidiTreeIterable<INode> {
public ICompositeNode getRootNode() {
if (parent == null)
return null;
CompositeNode candidate = parent;
AbstractNode candidate = parent;
while(candidate.basicGetParent() != null)
candidate = candidate.basicGetParent();
return candidate.getRootNode();
@ -266,4 +277,109 @@ public abstract class AbstractNode implements INode, BidiTreeIterable<INode> {
return prev != this;
}
enum NodeType {
CompositeNode, LeafNode, CompositeNodeWithSemanticElement, CompositeNodeWithSyntaxError, CompositeNodeWithSemanticElementAndSyntaxError, RootNode, HiddenLeafNode, HiddenLeafNodeWithSyntaxError, LeafNodeWithSyntaxError
}
abstract NodeType getNodeId();
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
int length = SerializationUtil.readInt(in, true);
if (length == 1) {
int grammarId = SerializationUtil.readInt(in, true);
grammarElementOrArray = context.getGrammarElement(grammarId);
} else {
if (length > 0) {
EObject[] grammarElements = new EObject[length];
for (int i = 0; i < length; ++i) {
int grammarId = SerializationUtil.readInt(in, true);
EObject grammarElement = context.getGrammarElement(grammarId);
grammarElements[i] = grammarElement;
}
grammarElementOrArray = grammarElements;
} else {
if (length != -1) {
throw new IllegalStateException("Read unexpected length of grammar element array from stream: "
+ length);
}
grammarElementOrArray = null;
}
}
}
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
if (grammarElementOrArray instanceof EObject) {
EObject eObject = (EObject) grammarElementOrArray;
SerializationUtil.writeInt(out, 1, true);
writeGrammarId(out, scc, eObject);
} else {
if (grammarElementOrArray instanceof EObject[]) {
EObject[] eObjects = (EObject[]) grammarElementOrArray;
SerializationUtil.writeInt(out, eObjects.length, true);
for (EObject eObject : eObjects) {
writeGrammarId(out, scc, eObject);
}
} else {
SerializationUtil.writeInt(out, -1, true);
}
}
}
private void writeGrammarId(DataOutputStream out, SerializationConversionContext scc, EObject eObject)
throws IOException {
Integer grammarId = scc.getGrammarElementId(eObject);
if (grammarId == null) {
throw new IllegalStateException("Must write a grammar element but got an unknown EMF object of class "
+ eObject.getClass().getName());
}
SerializationUtil.writeInt(out, grammarId.intValue(), true);
}
int fillGrammarElementToIdMap(int currentId, Map<EObject, Integer> grammarElementToIdMap,
List<String> grammarIdToURIMap) {
if (grammarElementOrArray != null) {
if (grammarElementOrArray instanceof EObject) {
EObject grammarElement = (EObject) grammarElementOrArray;
currentId = updateMapping(currentId, grammarElementToIdMap, grammarIdToURIMap, grammarElement);
}
if (grammarElementOrArray instanceof EObject[]) {
EObject[] grammarElements = (EObject[]) grammarElementOrArray;
for (EObject grammarElement : grammarElements) {
currentId = updateMapping(currentId, grammarElementToIdMap, grammarIdToURIMap, grammarElement);
}
}
}
return currentId;
}
private int updateMapping(int currentId, Map<EObject, Integer> grammarElementToIdMap,
List<String> grammarIdToURIMap, EObject grammarElement) {
if (!grammarElementToIdMap.containsKey(grammarElement)) {
URI uri = EcoreUtil.getURI(grammarElement);
if (uri == null) {
throw new IllegalStateException("While building the map of grammar elements to an ID, "
+ "got a grammar element that does not have an URI. The " + "grammar element has class "
+ grammarElement.eClass().getName());
}
grammarElementToIdMap.put(grammarElement, currentId);
grammarIdToURIMap.add(uri.toString());
++currentId;
}
if (currentId != grammarIdToURIMap.size()) {
throw new IllegalStateException("The next id for a grammar element will be " + currentId
+ " but the number of elements in "
+ "the map of grammar elements to IDs contains a different number of elements: "
+ grammarIdToURIMap.size());
}
return currentId;
}
}

View file

@ -7,18 +7,28 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.BidiIterable;
import org.eclipse.xtext.nodemodel.BidiTreeIterator;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
import org.eclipse.xtext.nodemodel.util.EmptyBidiIterable;
import org.eclipse.xtext.nodemodel.util.NodeIterable;
import org.eclipse.xtext.nodemodel.util.SingletonBidiIterable;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class CompositeNode extends AbstractNode implements ICompositeNode {
@ -70,7 +80,7 @@ public class CompositeNode extends AbstractNode implements ICompositeNode {
public int getTotalOffset() {
if (firstChild != null)
return firstChild.getTotalOffset();
CompositeNode compositeWithSiblings = this;
AbstractNode compositeWithSiblings = this;
while(!compositeWithSiblings.basicHasNextSibling() && compositeWithSiblings.basicGetParent() != null) {
compositeWithSiblings = compositeWithSiblings.basicGetParent();
}
@ -153,5 +163,131 @@ public class CompositeNode extends AbstractNode implements ICompositeNode {
EObject[] grammarElements = (EObject[]) grammarElementOrArray;
return grammarElements[0];
}
private static final NodeType[] NODE_TYPE_VALUES = NodeType.values();
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
int childNodeCount = SerializationUtil.readInt(in, true);
if (childNodeCount > 0) {
AbstractNode child = null;
AbstractNode prevChild = null;
for (int i = 0; i < childNodeCount; ++i) {
int nodeId = SerializationUtil.readInt(in, true);
NodeType nodeType = NODE_TYPE_VALUES[nodeId];
child = createChildNode(nodeType);
child.readData(in, context);
if (firstChild == null) {
firstChild = child;
}
child.basicSetParent(this);
child.basicSetPreviousSibling(prevChild);
prevChild = child;
}
firstChild.basicSetPreviousSibling(child);
// All left links are fine, now the right ones
child = firstChild.basicGetPreviousSibling();
prevChild = firstChild;
while (child != firstChild) {
child.basicSetNextSibling(prevChild);
prevChild = child;
child = child.basicGetPreviousSibling();
}
firstChild.basicSetNextSibling(prevChild);
}
lookAhead = SerializationUtil.readInt(in, true);
}
private AbstractNode createChildNode(AbstractNode.NodeType type) {
switch (type) {
case CompositeNode:
return new CompositeNode();
case CompositeNodeWithSemanticElement:
return new CompositeNodeWithSemanticElement();
case CompositeNodeWithSemanticElementAndSyntaxError:
return new CompositeNodeWithSemanticElementAndSyntaxError();
case CompositeNodeWithSyntaxError:
return new CompositeNodeWithSyntaxError();
case HiddenLeafNode:
return new HiddenLeafNode();
case HiddenLeafNodeWithSyntaxError:
return new HiddenLeafNodeWithSyntaxError();
case LeafNode:
return new LeafNode();
case LeafNodeWithSyntaxError:
return new LeafNodeWithSyntaxError();
case RootNode:
return new RootNode();
default:
throw new IllegalArgumentException("Trying to construct a non-existing INode");
}
}
@Override
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
super.write(out, scc);
int childNodeCount = getChildCount();
SerializationUtil.writeInt(out, childNodeCount, true);
AbstractNode it = firstChild;
for (int i = 0; i < childNodeCount; ++i) {
SerializationUtil.writeInt(out, it.getNodeId().ordinal(), true);
it.write(out, scc);
it = it.basicGetNextSibling();
}
SerializationUtil.writeInt(out, lookAhead, true);
}
private int getChildCount() {
if (firstChild == null) {
return 0;
}
AbstractNode it = firstChild;
int count = 0;
do {
++count;
it = it.basicGetNextSibling();
} while (it != firstChild);
return count;
}
@Override
int fillGrammarElementToIdMap(int currentId, Map<EObject, Integer> grammarElementToIdMap,
List<String> grammarIdToURIMap) {
currentId = super.fillGrammarElementToIdMap(currentId, grammarElementToIdMap, grammarIdToURIMap);
if (firstChild != null) {
AbstractNode it = firstChild;
do {
currentId = it.fillGrammarElementToIdMap(currentId, grammarElementToIdMap, grammarIdToURIMap);
it = it.basicGetNextSibling();
} while (it != firstChild);
}
return currentId;
}
@Override
NodeType getNodeId() {
return NodeType.CompositeNode;
}
}

View file

@ -7,14 +7,22 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class CompositeNodeWithSemanticElement extends CompositeNode implements Adapter {
@ -55,5 +63,37 @@ public class CompositeNodeWithSemanticElement extends CompositeNode implements A
public boolean isAdapterForType(Object type) {
return type instanceof Class<?> && INode.class.isAssignableFrom((Class<?>)type);
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
boolean isNull = in.readBoolean();
if (!isNull) {
int id = SerializationUtil.readInt(in, true);
semanticElement = context.getSemanticObject(id);
semanticElement.eAdapters().add(this);
}
}
@Override
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
super.write(out, scc);
boolean isNull = semanticElement == null;
out.writeBoolean(isNull);
if (!isNull) {
Integer id = scc.getEObjectId(semanticElement);
SerializationUtil.writeInt(out, id, true);
}
}
@Override
NodeType getNodeId() {
return NodeType.CompositeNodeWithSemanticElement;
}
}

View file

@ -7,10 +7,18 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class CompositeNodeWithSemanticElementAndSyntaxError extends CompositeNodeWithSemanticElement {
@ -25,4 +33,22 @@ public class CompositeNodeWithSemanticElementAndSyntaxError extends CompositeNod
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
this.syntaxErrorMessage = syntaxErrorMessage;
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
context.setHasErrors(true);
}
@Override
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
super.write(out, scc);
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
}
@Override
NodeType getNodeId() {
return NodeType.CompositeNodeWithSemanticElementAndSyntaxError;
}
}

View file

@ -7,10 +7,19 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class CompositeNodeWithSyntaxError extends CompositeNode {
@ -25,5 +34,24 @@ public class CompositeNodeWithSyntaxError extends CompositeNode {
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
this.syntaxErrorMessage = syntaxErrorMessage;
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
context.setHasErrors(true);
}
@Override
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
super.write(out, scc);
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
}
@Override
NodeType getNodeId() {
return NodeType.CompositeNodeWithSyntaxError;
}
}

View file

@ -9,6 +9,7 @@ package org.eclipse.xtext.nodemodel.impl;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class HiddenLeafNode extends LeafNode {
@ -18,4 +19,8 @@ public class HiddenLeafNode extends LeafNode {
return true;
}
@Override
NodeType getNodeId() {
return NodeType.HiddenLeafNode;
}
}

View file

@ -7,10 +7,18 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class HiddenLeafNodeWithSyntaxError extends HiddenLeafNode {
@ -25,5 +33,24 @@ public class HiddenLeafNodeWithSyntaxError extends HiddenLeafNode {
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
this.syntaxErrorMessage = syntaxErrorMessage;
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
context.setHasErrors(true);
}
@Override
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
super.write(out, scc);
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
}
}
@Override
NodeType getNodeId() {
return NodeType.HiddenLeafNodeWithSyntaxError;
}
}

View file

@ -7,12 +7,19 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collections;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class LeafNode extends AbstractNode implements ILeafNode {
@ -56,4 +63,22 @@ public class LeafNode extends AbstractNode implements ILeafNode {
return Collections.<ILeafNode>singletonList(this);
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
totalLength = SerializationUtil.readInt(in, true);
}
@Override
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
super.write(out, scc);
SerializationUtil.writeInt (out, totalLength, true);
}
@Override
NodeType getNodeId() {
return NodeType.LeafNode;
}
}

View file

@ -7,10 +7,18 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class LeafNodeWithSyntaxError extends LeafNode {
@ -25,5 +33,22 @@ public class LeafNodeWithSyntaxError extends LeafNode {
protected void basicSetSyntaxErrorMessage(SyntaxErrorMessage syntaxErrorMessage) {
this.syntaxErrorMessage = syntaxErrorMessage;
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
syntaxErrorMessage = SerializationUtil.readSyntaxErrorMessage(in, context);
context.setHasErrors(true);
}
@Override
void write(DataOutputStream out, SerializationConversionContext scc) throws IOException {
super.write(out, scc);
SerializationUtil.writeSyntaxErrorMessage(out, scc, syntaxErrorMessage);
}
@Override
NodeType getNodeId() {
return NodeType.LeafNodeWithSyntaxError;
}
}

View file

@ -7,15 +7,21 @@
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import com.google.common.collect.Lists;
/**
* @author Sebastian Zarnekow - Initial contribution and API
* @author Mark Christiaens - Serialization support
* @noextend This class is not intended to be subclassed by clients.
*/
public class RootNode extends CompositeNodeWithSemanticElementAndSyntaxError {
@ -168,5 +174,61 @@ public class RootNode extends CompositeNodeWithSemanticElementAndSyntaxError {
}
return result;
}
@Override
void readData(DataInputStream in, DeserializationConversionContext context) throws IOException {
super.readData(in, context);
basicSetCompleteContent(context.getCompleteContent());
int totalLength = fixupOffsets(this, 0);
if (totalLength != getCompleteContent().length()) {
throw new IllegalStateException("The length of the resource's content was " + getCompleteContent().length()
+ " but the length calculated based upon the serialized form of the RootNode was " + totalLength);
}
}
private int fixupOffsets(INode node, int nodeOffset) {
if (node instanceof LeafNode) {
LeafNode leafNode = (LeafNode) node;
leafNode.basicSetTotalOffset(nodeOffset);
return leafNode.getTotalLength() + nodeOffset;
}
if (node instanceof CompositeNode) {
CompositeNode compositeNode = (CompositeNode) node;
int currentOffset = nodeOffset;
AbstractNode firstChild = compositeNode.basicGetFirstChild();
if (firstChild != null) {
AbstractNode it = firstChild;
do {
currentOffset = fixupOffsets(it, currentOffset);
it = it.basicGetNextSibling();
} while (it != firstChild);
}
return currentOffset;
}
return 0;
}
@Override
NodeType getNodeId() {
return NodeType.RootNode;
}
/**
* @since 2.3
* @noreference This method is not intended to be referenced by clients.
*/
public void fillGrammarElementToIdMap(Map<EObject, Integer> grammarElementToIdMap,
List<String> grammarIdToURIMap) {
fillGrammarElementToIdMap(0, grammarElementToIdMap, grammarIdToURIMap);
}
}

View file

@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) and others. All rights reserved. This program and the
* accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.nodemodel.impl;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Date;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.serialization.DeserializationConversionContext;
import org.eclipse.xtext.nodemodel.serialization.SerializationConversionContext;
import org.eclipse.xtext.resource.XtextResource;
/**
* @author Mark Christiaens - Initial contribution
*
* @since 2.3
* @noinstantiate This class is not intended to be instantiated by clients.
* @noextend This class is not intended to be subclassed by clients.
*/
public class SerializableNodeModel {
public int formatVersion;
public Date date;
public RootNode root;
public SerializableNodeModel(XtextResource resource) {
ICompositeNode rootNode = resource.getParseResult().getRootNode();
if (rootNode != null) {
root = (RootNode) rootNode;
}
formatVersion = 1;
date = new Date();
}
public SerializableNodeModel() {
}
/**
* @noreference This method is not intended to be referenced by clients.
*/
public void writeObjectData(DataOutputStream out, SerializationConversionContext scc) throws IOException {
String[] grammarIdToURIMap = scc.getGrammarIdToURIMap();
out.writeInt(grammarIdToURIMap.length);
for (String string : grammarIdToURIMap) {
out.writeUTF(string);
}
root.write(out, scc);
}
/**
* @noreference This method is not intended to be referenced by clients.
*/
public void readObjectData(DataInputStream in, DeserializationConversionContext context) throws IOException {
int grammarIdToURIMapLength = in.readInt();
String[] grammarIdToURIMap = new String[grammarIdToURIMapLength];
for (int i = 0; i < grammarIdToURIMapLength; ++i) {
grammarIdToURIMap[i] = in.readUTF();
if (grammarIdToURIMap[i] == null) {
throw new IllegalStateException("During deserialzing the grammar id to URI map got a null reference. ");
}
}
context.setGrammarIdToURIMap(grammarIdToURIMap);
root = new RootNode();
root.readData(in, context);
}
}

View file

@ -0,0 +1,102 @@
/*******************************************************************************
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) and others. All rights reserved. This program and the
* accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.nodemodel.serialization;
import java.io.IOException;
import java.util.List;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtext.IGrammarAccess;
import org.eclipse.xtext.resource.XtextResource;
import com.google.common.collect.Lists;
/**
* @author mark.christiaens - Initial contribution and API
*
* @since 2.3
*/
public class DeserializationConversionContext {
private EObject[] grammarIdToGrammarElementMap;
final private List<EObject> idToEObjectMap;
final private IGrammarAccess grammarAccess;
final private String completeContent;
private boolean hasErrors;
public DeserializationConversionContext(XtextResource xr, String completeContent) throws IOException {
this.grammarAccess = xr.getResourceServiceProvider().get(IGrammarAccess.class);
this.idToEObjectMap = Lists.newArrayList();
this.completeContent = completeContent;
this.hasErrors = false;
fillIdToEObjectMap(xr);
}
public void setGrammarIdToURIMap(String[] grammarIdToURIMap) {
grammarIdToGrammarElementMap = new EObject[grammarIdToURIMap.length];
ResourceSet grammarResourceSet = grammarAccess.getGrammar().eResource().getResourceSet();
for (int grammarId = 0; grammarId < grammarIdToURIMap.length; ++grammarId) {
URI uri = URI.createURI(grammarIdToURIMap[grammarId], true);
EObject grammarElement = grammarResourceSet.getEObject(uri, true);
if (grammarElement == null) {
throw new IllegalStateException(
"Apparently the grammar has changed so that it's no longer possible to identify the "
+ "serialized grammar elements. The following grammar element URI is no longer valid: "
+ uri.toString());
}
grammarIdToGrammarElementMap[grammarId] = grammarElement;
}
}
public EObject getGrammarElement(int grammarId) {
if (grammarId >= grammarIdToGrammarElementMap.length) {
throw new IllegalStateException(
"Trying to obtain a grammar element that does not (or no longer) exists with id: " + grammarId);
}
EObject result = grammarIdToGrammarElementMap[grammarId];
return result;
}
public void fillIdToEObjectMap(Resource resource) {
SerializationUtil.fillIdToEObjectMap(resource, idToEObjectMap);
}
public EObject getSemanticObject(int id) {
EObject eObject = idToEObjectMap.get(id);
if (eObject == null) {
throw new IllegalStateException(
"Trying to get an EMF object in the EMF resource that does not exist. We are looking for id: "
+ id);
}
return eObject;
}
public void setHasErrors(boolean hasErrors) {
this.hasErrors = hasErrors;
}
boolean hasErrors() {
return hasErrors;
}
public String getCompleteContent() {
return completeContent;
}
}

View file

@ -0,0 +1,80 @@
/*******************************************************************************
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) and others. All rights reserved. This program and the
* accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.nodemodel.serialization;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.nodemodel.impl.RootNode;
import org.eclipse.xtext.resource.XtextResource;
/**
* @author Mark Christiaens - Initial contribution
*
* @since 2.3
*/
public class SerializationConversionContext {
final private Map<EObject, Integer> grammarElementToIdMap;
final private ArrayList<String> grammarIdToURIMap;
final private Map<EObject, Integer> eObjectToIdMap;
public SerializationConversionContext(XtextResource resource) {
grammarElementToIdMap = new IdentityHashMap<EObject, Integer>();
grammarIdToURIMap = new ArrayList<String>();
eObjectToIdMap = new IdentityHashMap<EObject, Integer>();
fillEObjectToIdMap(resource);
fillGrammarElementToIdMap(resource);
}
public Integer getGrammarElementId(EObject grammarElement) {
final Integer id = grammarElementToIdMap.get(grammarElement);
if (id == null) {
throw new IllegalArgumentException(
"Trying to fetch a grammar element that does not (no longer) exists with id: " + id);
}
return id;
}
protected void fillEObjectToIdMap(Resource resource) {
ArrayList<EObject> idToEObjectMap = new ArrayList<EObject>();
SerializationUtil.fillIdToEObjectMap(resource, idToEObjectMap);
for (int id = 0; id < idToEObjectMap.size(); ++id) {
eObjectToIdMap.put(idToEObjectMap.get(id), id);
}
}
protected void fillGrammarElementToIdMap(XtextResource r) {
RootNode it = (RootNode) r.getParseResult().getRootNode();
it.fillGrammarElementToIdMap(grammarElementToIdMap, grammarIdToURIMap);
}
public Integer getEObjectId(EObject eObject) {
Integer id = eObjectToIdMap.get(eObject);
if (id == null) {
throw new IllegalArgumentException("Tryin to fetch an EMF object that does not exist (no longer) with id: "
+ id);
}
return id;
}
public String[] getGrammarIdToURIMap() {
String[] map = grammarIdToURIMap.toArray(new String[0]);
return map;
}
}

View file

@ -0,0 +1,248 @@
/*******************************************************************************
* Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.nodemodel.serialization;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
/**
* @author mark.christiaens - Initial contribution and API
*
* @since 2.3
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class SerializationUtil {
public static final int KIB = 1024;
public static void fillIdToEObjectMap(Resource resource, List<EObject> map) {
TreeIterator<EObject> allContents = EcoreUtil.getAllContents(resource, false);
if (allContents.hasNext()) {
EObject root = allContents.next();
fillIdToEObjectMap(root, map);
}
}
public static void fillIdToEObjectMap(EObject eObject, List<EObject> map) {
map.add(eObject);
EList<EObject> eContents = eObject.eContents();
for (EObject child : eContents) {
fillIdToEObjectMap(child, map);
}
}
public static long milliDiff(long startLoad, long doneLoad) {
return (doneLoad - startLoad) / 1000000;
}
public static String getCompleteContent(XtextResource xr) throws IOException, UnsupportedEncodingException {
XtextResourceSet resourceSet = (XtextResourceSet) xr.getResourceSet();
URIConverter uriConverter = resourceSet.getURIConverter();
URI uri = xr.getURI();
String encoding = xr.getEncoding();
InputStream inputStream = null;
try {
inputStream = uriConverter.createInputStream(uri);
return getCompleteContent(encoding, inputStream);
} finally {
tryClose(inputStream, null);
}
}
public static String getCompleteContent(String encoding, InputStream inputStream)
throws UnsupportedEncodingException, IOException {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, encoding);
StringBuilder sb = new StringBuilder ();
char[] buffer = new char[128 * KIB];
int n = inputStreamReader.read(buffer);
while (n != -1) {
sb.append (buffer, 0, n);
n = inputStreamReader.read(buffer);
}
return sb.toString();
}
public static byte [] getCompleteContent(InputStream inputStream)
throws IOException {
byte[] buffer = new byte[128 * KIB];
int nextFreePos = 0;
int n = inputStream.read(buffer, nextFreePos, buffer.length - nextFreePos);
while (n != -1) {
nextFreePos += n;
if (nextFreePos >= buffer.length) {
buffer = copyOf(buffer, buffer.length*2);
}
n = inputStream.read(buffer, nextFreePos, buffer.length - nextFreePos);
}
return copyOf(buffer, nextFreePos);
}
static byte[] copyOf(byte[] original, int newLength) {
byte[] copy = new byte[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
public static void writeSyntaxErrorMessage(DataOutputStream out, SerializationConversionContext scc,
SyntaxErrorMessage syntaxErrorMessage) throws IOException {
if (syntaxErrorMessage == null) {
out.writeBoolean(true);
} else {
out.writeBoolean(false);
SerializationUtil.writeString(out, syntaxErrorMessage.getMessage());
SerializationUtil.writeString(out, syntaxErrorMessage.getIssueCode());
SerializationUtil.writeStringArray(out, syntaxErrorMessage.getIssueData());
}
}
public static SyntaxErrorMessage readSyntaxErrorMessage(DataInputStream in, DeserializationConversionContext context)
throws IOException {
boolean isNull = in.readBoolean();
if (isNull)
return null;
String message = SerializationUtil.readString(in);
String issueCode = SerializationUtil.readString(in);
String[] issueData = SerializationUtil.readStringArray(in);
SyntaxErrorMessage result = new SyntaxErrorMessage(message, issueCode, issueData);
return result;
}
static public int writeInt(DataOutputStream out, int value, boolean optimizePositive) throws IOException {
if (!optimizePositive)
value = (value << 1) ^ (value >> 31);
if ((value & ~0x7F) == 0) {
out.writeByte((byte) value);
return 1;
}
out.writeByte((byte) ((value & 0x7F) | 0x80));
value >>>= 7;
if ((value & ~0x7F) == 0) {
out.writeByte((byte) value);
return 2;
}
out.writeByte((byte) ((value & 0x7F) | 0x80));
value >>>= 7;
if ((value & ~0x7F) == 0) {
out.writeByte((byte) value);
return 3;
}
out.writeByte((byte) ((value & 0x7F) | 0x80));
value >>>= 7;
if ((value & ~0x7F) == 0) {
out.writeByte((byte) value);
return 4;
}
out.writeByte((byte) ((value & 0x7F) | 0x80));
value >>>= 7;
out.writeByte((byte) value);
return 5;
}
static public int readInt(DataInputStream in, boolean optimizePositive) throws IOException {
for (int offset = 0, result = 0; offset < 32; offset += 7) {
int b = in.readByte();
result |= (b & 0x7F) << offset;
if ((b & 0x80) == 0) {
if (!optimizePositive)
result = (result >>> 1) ^ -(result & 1);
return result;
}
}
throw new IOException("Malformed integer");
}
public static final void writeString(DataOutputStream out, String s) throws IOException {
boolean isNull = s == null;
out.writeBoolean(isNull);
if (!isNull) {
out.writeUTF(s);
}
}
public static final String readString(DataInputStream in) throws IOException {
boolean isNull = in.readBoolean();
if (isNull) {
return null;
}
String string = in.readUTF();
return string;
}
public static void writeStringArray(DataOutputStream out, String[] ss) throws IOException {
out.writeBoolean(ss == null);
if (ss != null) {
writeInt(out, ss.length, true);
for (String data : ss) {
writeString(out, data);
}
}
}
public static String[] readStringArray(DataInputStream in) throws IOException {
boolean isIssueDataNull = in.readBoolean();
String[] result = null;
if (!isIssueDataNull) {
int issueDataLength = readInt(in, true);
result = new String[issueDataLength];
for (int i = 0; i < issueDataLength; ++i) {
result[i] = readString(in);
}
}
return result;
}
public static void tryClose(Closeable stream, Logger logger) throws IOException {
if (stream != null) {
try {
stream.close();
} catch (Exception e) {
if (logger != null) {
logger.error("Could not close an stream for a cache entry: " + e, e);
}
}
}
}
}

View file

@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2011 Sigasi N.V. (http://www.sigasi.com) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.nodemodel.serialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.xtext.nodemodel.SyntaxErrorMessage;
import org.eclipse.xtext.nodemodel.serialization.SerializationUtil;
import org.junit.Assert;
import org.junit.Test;
/** @author Mark Christiaens */
public class SerializationUtilTest extends Assert {
@Test
public void testSyntaxErrorMessage() throws IOException {
final String message = "hi";
String [] issueCodes = { null, "issue" };
String [][] issueDatas = { null, {null}, {"issue data"}};
for (String[] issueData : issueDatas) {
for (String issueCode : issueCodes) {
SyntaxErrorMessage sem = new SyntaxErrorMessage(message, issueCode, issueData);
ByteArrayOutputStream out = new ByteArrayOutputStream ();
DataOutputStream dout = new DataOutputStream(out);
SerializationUtil.writeSyntaxErrorMessage(dout, null, sem);
dout.close();
byte[] array = out.toByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(array);
DataInputStream din = new DataInputStream(in);
SyntaxErrorMessage sem2 = SerializationUtil.readSyntaxErrorMessage(din, null);
assertEquals(sem, sem2);
}
}
ByteArrayOutputStream out = new ByteArrayOutputStream ();
DataOutputStream dout = new DataOutputStream(out);
SerializationUtil.writeSyntaxErrorMessage(dout, null, null);
dout.close();
byte[] array = out.toByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(array);
DataInputStream din = new DataInputStream(in);
SyntaxErrorMessage readMessage = SerializationUtil.readSyntaxErrorMessage(din, null);
assertNull(readMessage);
}
}