Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbblajer2009-01-12 08:08:12 -0500
committerbblajer2009-01-12 08:08:12 -0500
commit50f0772b04cf14642e1337bf027b71a9d17cd866 (patch)
treefbce651d5ca638b0aec657c6c40f1a5e3fd16996
parent7348aba1e82f6353e790f85ada8b628c83823dc3 (diff)
downloadorg.eclipse.gmf-tooling-50f0772b04cf14642e1337bf027b71a9d17cd866.tar.gz
org.eclipse.gmf-tooling-50f0772b04cf14642e1337bf027b71a9d17cd866.tar.xz
org.eclipse.gmf-tooling-50f0772b04cf14642e1337bf027b71a9d17cd866.zip
[260701]: Make it possible to get contents of named streams that were created by xpand template evaluation
-rw-r--r--plugins/org.eclipse.gmf.xpand/plugin.xml13
-rw-r--r--plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/BufferOutput.java62
-rw-r--r--plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/StreamsHolder.java15
-rw-r--r--plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/Output.java2
-rw-r--r--plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/XpandStreamsHolder.java71
-rw-r--r--plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/ocl/ExpressionHelper.java24
-rw-r--r--plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/util/XpandStreamOperations.java43
7 files changed, 221 insertions, 9 deletions
diff --git a/plugins/org.eclipse.gmf.xpand/plugin.xml b/plugins/org.eclipse.gmf.xpand/plugin.xml
index e07eb6a43..d4b41e580 100644
--- a/plugins/org.eclipse.gmf.xpand/plugin.xml
+++ b/plugins/org.eclipse.gmf.xpand/plugin.xml
@@ -34,4 +34,17 @@
</content-type>
</extension>
+ <extension
+ point="org.eclipse.m2m.qvt.oml.javaBlackboxUnits">
+ <unit
+ name="StreamOperations"
+ namespace="xpt">
+ <library
+ class="org.eclipse.gmf.internal.xpand.util.XpandStreamOperations">
+ <metamodel
+ nsURI="http://www.eclipse.org/emf/2002/Ecore">
+ </metamodel>
+ </library>
+ </unit>
+ </extension>
</plugin>
diff --git a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/BufferOutput.java b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/BufferOutput.java
index 2cf2f382a..7df4d3604 100644
--- a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/BufferOutput.java
+++ b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/BufferOutput.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Borland Software Corporation
+ * Copyright (c) 2006, 2009 Borland Software Corporation
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,32 +8,57 @@
*/
package org.eclipse.gmf.internal.xpand;
-import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
+import org.eclipse.gmf.internal.xpand.model.XpandStreamsHolder;
+
public class BufferOutput extends AbstractOutput {
/**
* INV: size > 0
*/
private final Stack<StringBuilder> outletStack;
+ /**
+ * INV: size == outletStack.size - 1
+ */
+ private final Stack<String> outletNamesStack;
+
private final Map<String, StringBuilder> namedSlots;
+ private final XpandStreamsHolder streamsHolder;
+
+ private final boolean enforceReadOnlyAfterAccess;
+
public BufferOutput(StringBuilder buffer) {
this(buffer, null);
}
// XXX not map but config to show whether to append/overwrite content
public BufferOutput(StringBuilder buffer, Map<String, StringBuilder> namedSlots) {
+ this(buffer, namedSlots, false);
+ }
+
+ public BufferOutput(StringBuilder buffer, boolean enforceReadOnlyAfterRead) {
+ this(buffer, null, enforceReadOnlyAfterRead);
+ }
+
+ public BufferOutput(StringBuilder buffer, Map<String, StringBuilder> namedSlots, boolean enforceReadOnlyAfterRead) {
assert buffer != null;
outletStack = new Stack<StringBuilder>();
outletStack.push(buffer);
- if (namedSlots != null) {
- this.namedSlots = namedSlots;
+ outletNamesStack = new Stack<String>();
+ streamsHolder = new XpandStreamsHolder();
+ if (namedSlots == null) {
+ this.namedSlots = new HashMap<String, StringBuilder>();
} else {
- this.namedSlots = Collections.emptyMap();
+ this.namedSlots = namedSlots;
+ for (Map.Entry<String, StringBuilder> next : namedSlots.entrySet()) {
+ streamsHolder.addNamedStream(next.getKey(), next.getValue());
+ }
}
+ this.enforceReadOnlyAfterAccess = enforceReadOnlyAfterRead;
}
public void closeFile() {
@@ -42,16 +67,33 @@ public class BufferOutput extends AbstractOutput {
System.err.println("<<<" + msg);
throw new UnsupportedOperationException(msg);
}
+ checkAccessPermitted();
outletStack.pop();
+ outletNamesStack.pop();
+ }
+
+ /**
+ * Throws an exception if the buffer has been configured not to allow write operations after reading and the stream
+ * has in fact been accessed.
+ */
+ private void checkAccessPermitted() {
+ if (enforceReadOnlyAfterAccess && streamsHolder.isAccessed(outletNamesStack.peek())) {
+ throw new UnsupportedOperationException("Cannot write to a stream after its contents have been accessed");
+ }
}
public void openFile(String path, String outletName) {
if (!namedSlots.containsKey(outletName)) {
- String msg = "OPEN FILE ('" + path + "', " + outletName + ")";
- System.err.println(">>>" + msg);
- throw new UnsupportedOperationException(msg);
+// String msg = "OPEN FILE ('" + path + "', " + outletName + ")";
+// System.err.println(">>>" + msg);
+// throw new UnsupportedOperationException(msg);
+ StringBuilder newSlot = new StringBuilder();
+ namedSlots.put(outletName, newSlot);
+ streamsHolder.addNamedStream(outletName, newSlot);
}
outletStack.push(namedSlots.get(outletName));
+ outletNamesStack.push(outletName);
+ checkAccessPermitted();
assert outletStack.peek() != null;
}
@@ -59,4 +101,8 @@ public class BufferOutput extends AbstractOutput {
protected void doAppend(String text) {
outletStack.peek().append(text);
}
+
+ public StreamsHolder getNamedStreams() {
+ return streamsHolder;
+ }
} \ No newline at end of file
diff --git a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/StreamsHolder.java b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/StreamsHolder.java
new file mode 100644
index 000000000..2fddf6abd
--- /dev/null
+++ b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/StreamsHolder.java
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Borland Software Corporation
+ *******************************************************************************/
+package org.eclipse.gmf.internal.xpand;
+
+import java.util.List;
+
+/**
+ * @author bblajer
+ */
+public interface StreamsHolder {
+ public String getStreamContents(String slotName);
+
+ public List<String> getSlotNames();
+}
diff --git a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/Output.java b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/Output.java
index e5538522b..3d2b81ebc 100644
--- a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/Output.java
+++ b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/Output.java
@@ -14,6 +14,7 @@
*/
package org.eclipse.gmf.internal.xpand.model;
+import org.eclipse.gmf.internal.xpand.StreamsHolder;
import org.eclipse.gmf.internal.xpand.expression.ast.SyntaxElement;
/**
@@ -30,4 +31,5 @@ public interface Output {
public void closeFile();
+ public StreamsHolder getNamedStreams();
}
diff --git a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/XpandStreamsHolder.java b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/XpandStreamsHolder.java
new file mode 100644
index 000000000..ab12e028b
--- /dev/null
+++ b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/model/XpandStreamsHolder.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Borland Software Corporation
+ *******************************************************************************/
+package org.eclipse.gmf.internal.xpand.model;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.gmf.internal.xpand.StreamsHolder;
+
+/**
+ * Holder for named streams.
+ */
+public class XpandStreamsHolder implements StreamsHolder {
+ private HashMap<String, StringBuilder> myStreams;
+ private HashSet<String> myStreamsAccessed;
+
+ public String getStreamContents(String slotName) {
+ if (myStreams == null) {
+ throw new EvaluationException("Undefined stream " + slotName, null);
+ }
+ StringBuilder result = myStreams.get(slotName);
+ if (result == null) {
+ throw new EvaluationException("Undefined stream " + slotName, null);
+ }
+ setAccessed(slotName);
+ if (result.length() == 0) {
+ return null;
+ }
+ return result.toString();
+ }
+
+ public List<String> getSlotNames() {
+ if (myStreams == null) {
+ return Collections.emptyList();
+ }
+ //Filter streams that have no content
+ ArrayList<String> result = new ArrayList<String>(myStreams.size());
+ for (Map.Entry<String, StringBuilder> next : myStreams.entrySet()) {
+ if (next.getValue().length() == 0) {
+ continue;
+ }
+ result.add(next.getKey());
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ public void addNamedStream(String name, StringBuilder stream) {
+ if (myStreams == null) {
+ myStreams = new HashMap<String, StringBuilder>();
+ }
+ assert !myStreams.containsKey(name);
+ myStreams.put(name, stream);
+ }
+
+ private void setAccessed(String slotName) {
+ if (myStreamsAccessed == null) {
+ myStreamsAccessed = new HashSet<String>();
+ }
+ myStreamsAccessed.add(slotName);
+ }
+
+ public boolean isAccessed(String slotName) {
+ return myStreamsAccessed != null && myStreamsAccessed.contains(slotName);
+ }
+}
diff --git a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/ocl/ExpressionHelper.java b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/ocl/ExpressionHelper.java
index 8cf3c57b9..64ade9c28 100644
--- a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/ocl/ExpressionHelper.java
+++ b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/ocl/ExpressionHelper.java
@@ -19,11 +19,13 @@ import java.util.Set;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.gmf.internal.xpand.StreamsHolder;
import org.eclipse.gmf.internal.xpand.model.AnalysationIssue;
import org.eclipse.gmf.internal.xpand.model.EvaluationException;
import org.eclipse.gmf.internal.xpand.model.ExecutionContext;
import org.eclipse.gmf.internal.xpand.model.Scope;
import org.eclipse.gmf.internal.xpand.qvtlibraries.XpandGlobalVars;
+import org.eclipse.gmf.internal.xpand.util.XpandStreamOperations;
import org.eclipse.gmf.internal.xpand.xtend.ast.QvtResource;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv;
import org.eclipse.m2m.internal.qvt.oml.evaluator.ModuleInstance;
@@ -79,14 +81,16 @@ public class ExpressionHelper {
QvtOperationalEvaluationEnv evaluationEnv = (QvtOperationalEvaluationEnv) ctx.createEvaluationEnvironment();
QvtOperationalEvaluationVisitor visitor = ctx.createEvaluationVisitor(evaluationEnv);
defineGlobalVariables(ctx, evaluationEnv);
+ initializeStreamsHolder(ctx.getScope(), ctx.getScope().getOutput().getNamedStreams(), evaluationEnv);
Object val = visitor.visitExpression(expression);
+ initializeStreamsHolder(ctx.getScope(), null, evaluationEnv);
clearGlobalVariables(ctx, evaluationEnv);
if (env.getOCLStandardLibrary().getOclInvalid() == val) {
throw new EvaluationException("Can't evaluate expression: retured value is OclInvalid", null);
}
return val;
}
-
+
private EcoreEnvironment getOCLEnvironment(ExecutionContext ctx) {
if (oclEnvironment == null) {
oclEnvironment = ctx.getOCLEnvironment();
@@ -144,6 +148,24 @@ public class ExpressionHelper {
return null;
}
+ /**
+ * Initializes QVT black-box java library with the given value of the streams holder.
+ */
+ private void initializeStreamsHolder(Scope scope, StreamsHolder namedStreams, QvtOperationalEvaluationEnv evaluationEnv) {
+ QvtResource streamOperationResource = scope.findExtension("xpt::StreamOperations");
+ if (streamOperationResource != null) {
+ for (Module module : streamOperationResource.getModules()) {
+ ModuleInstance moduleInstance = evaluationEnv.getThisOfType(module);
+ if (moduleInstance != null) {
+ XpandStreamOperations libInstance = moduleInstance.getAdapter(XpandStreamOperations.class);
+ if (libInstance != null) {
+ libInstance.streamsHolder = namedStreams;
+ }
+ }
+ }
+ }
+ }
+
public int getStart() {
return expressionCS.getStartOffset();
}
diff --git a/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/util/XpandStreamOperations.java b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/util/XpandStreamOperations.java
new file mode 100644
index 000000000..16430dbe3
--- /dev/null
+++ b/plugins/org.eclipse.gmf.xpand/src/org/eclipse/gmf/internal/xpand/util/XpandStreamOperations.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2008, 2009 Borland Software Corporation
+ *
+ * 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
+ *
+ * Contributors:
+ * Boris Blajer (Borland) - initial API and implementation
+ */
+package org.eclipse.gmf.internal.xpand.util;
+
+import java.util.List;
+
+import org.eclipse.gmf.internal.xpand.StreamsHolder;
+import org.eclipse.m2m.qvt.oml.blackbox.java.Operation;
+import org.eclipse.m2m.qvt.oml.blackbox.java.Operation.Kind;
+import org.eclipse.ocl.util.CollectionUtil;
+
+/**
+ * Stream-related operations that should be accessible from within QVT environment.
+ */
+public class XpandStreamOperations {
+ public StreamsHolder streamsHolder;
+
+ @Operation(contextual = false, kind = Kind.HELPER)
+ public List<String> xpandGetStreamNames() {
+ List<String> result = CollectionUtil.<String> createNewSequence();
+ if (streamsHolder != null) {
+ result.addAll(streamsHolder.getSlotNames());
+ }
+ return result;
+ }
+
+ @Operation(contextual = false, kind = Kind.HELPER)
+ public String xpandGetStreamContents(String streamName) {
+ if (streamsHolder == null) {
+ return null;
+ }
+ return streamsHolder.getStreamContents(streamName);
+ }
+}

Back to the top