001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.text.ui;
021
022 import groovy.lang.Closure;
023 import groovy.lang.GroovyObjectSupport;
024 import org.crsh.command.CRaSHCommand;
025 import org.crsh.command.GroovyScriptCommand;
026 import org.crsh.command.InvocationContext;
027 import org.crsh.text.RenderPrintWriter;
028 import org.crsh.text.Renderable;
029 import org.crsh.text.Renderer;
030
031 import java.io.IOException;
032 import java.util.LinkedList;
033 import java.util.Map;
034
035 public class EvalElement extends Element {
036
037 /** The closure to evaluate. */
038 Closure closure;
039
040 public Renderer renderer() {
041
042 Object owner = closure.getOwner();
043
044 //
045 final InvocationContext ctx;
046 Object cmd;
047 while (true) {
048 if (owner instanceof CRaSHCommand) {
049 cmd = owner;
050 ctx = ((CRaSHCommand)cmd).peekContext();
051 break;
052 } else if (owner instanceof GroovyScriptCommand) {
053 cmd = owner;
054 ctx = ((GroovyScriptCommand)cmd).peekContext();
055 break;
056 } else if (owner instanceof Closure) {
057 owner = ((Closure)owner).getOwner();
058 } else {
059 throw new UnsupportedOperationException("Cannot resolver owner " + owner + " to command");
060 }
061 }
062
063 //
064 final LinkedList<Renderer> renderers = new LinkedList<Renderer>();
065
066 //
067 final InvocationContext nested = new InvocationContext() {
068
069 /** . */
070 private LinkedList<Object> buffer = new LinkedList<Object>();
071
072 /** . */
073 private Renderable renderable;
074
075 public RenderPrintWriter getWriter() {
076 return ctx.getWriter();
077 }
078
079 public Map<String, Object> getSession() {
080 return ctx.getSession();
081 }
082
083 public Map<String, Object> getAttributes() {
084 return ctx.getAttributes();
085 }
086
087 public int getWidth() {
088 return ctx.getWidth();
089 }
090
091 public int getHeight() {
092 return ctx.getHeight();
093 }
094
095 public String getProperty(String propertyName) {
096 return ctx.getProperty(propertyName);
097 }
098
099 public String readLine(String msg, boolean echo) {
100 return null;
101 }
102
103 public void provide(Object element) throws IOException {
104 Renderable current = Renderable.getRenderable(element.getClass());
105 if (current == null) {
106 current = Renderable.ANY;
107 }
108 if (current != null) {
109 if (renderable != null && !current.equals(renderable)) {
110 flush();
111 }
112 buffer.addLast(element);
113 renderable = current;
114 }
115 }
116
117 public void flush() throws IOException {
118 // We don't really flush, we just compute renderables from the buffer
119 if (buffer.size() > 0) {
120 Renderer i = renderable.renderer(buffer.iterator());
121 buffer.clear();
122 renderers.add(i);
123 }
124 }
125 };
126
127 if (cmd instanceof CRaSHCommand) {
128 ((CRaSHCommand)cmd).pushContext(nested);
129 } else {
130 ((GroovyScriptCommand)cmd).pushContext(nested);
131 }
132 try {
133 closure.call();
134 }
135 finally {
136 if (cmd instanceof CRaSHCommand) {
137 ((CRaSHCommand)cmd).popContext();
138 } else {
139 ((GroovyScriptCommand)cmd).popContext();
140 }
141 }
142
143 // Be sure to flush
144 try {
145 nested.flush();
146 }
147 catch (IOException e) {
148 e.printStackTrace();
149 }
150
151 //
152 return Renderer.compose(renderers);
153 }
154 }