| /* |
| * 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 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| */ |
| package org.eclipse.gmf.internal.xpand; |
| |
| 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); |
| outletNamesStack = new Stack<String>(); |
| streamsHolder = new XpandStreamsHolder(); |
| if (namedSlots == null) { |
| this.namedSlots = new HashMap<String, StringBuilder>(); |
| } else { |
| this.namedSlots = namedSlots; |
| for (Map.Entry<String, StringBuilder> next : namedSlots.entrySet()) { |
| streamsHolder.addNamedStream(next.getKey(), next.getValue()); |
| } |
| } |
| this.enforceReadOnlyAfterAccess = enforceReadOnlyAfterRead; |
| } |
| |
| public void closeFile() { |
| if (outletStack.size() == 1) { |
| String msg = "CLOSE FILE without previous openFile"; |
| 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); |
| 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; |
| } |
| |
| @Override |
| protected void doAppend(String text) { |
| outletStack.peek().append(text); |
| } |
| |
| public StreamsHolder getNamedStreams() { |
| return streamsHolder; |
| } |
| } |