Commits

Stephen McKamey  committed d5f85fd

- simplifying interface with method chaining & by moving data into DuelContext

  • Participants
  • Parent commits bac2195
  • Tags v0.2.0

Comments (0)

Files changed (4)

File duel/duel-runtime/src/main/java/org/duelengine/duel/DuelContext.java

 package org.duelengine.duel;
 
+import java.util.Map;
+
 /**
  * Maintains context state for a single binding/render cycle (usually a request).
  * DuelContext is NOT thread-safe and not intended to be reusable.
 	private Appendable output;
 	private ClientIDStrategy clientID;
 	private DataEncoder encoder;
+	private FormatPrefs format;
 
+	private Object data;
 	private ExtraState extraState = ExtraState.NONE;
 	private SparseMap extras;
 	private SparseMap dirty;
 
-	private FormatPrefs format;
-
-	public DuelContext() {
-	}
-
-	public DuelContext(Appendable output) {
-		this.output = output;
-	}
-
 	public Appendable getOutput() {
 		if (this.output == null) {
 			this.output = new StringBuilder();
 		}
-
 		return this.output;
 	}
 
 	public DuelContext setOutput(Appendable output) {
 		this.output = output;
+
 		return this;
 	}
 
 
 	public DuelContext setClientID(ClientIDStrategy value) {
 		this.clientID = value;
+
 		return this;
 	}
 
 		return this;
 	}
 
+	public Object getData() {
+		return this.data;
+	}
+
+	public DuelContext setData(Object data) {
+		this.data = data;
+
+		return this;
+	}
+
+	public DuelContext clearExtras() {
+		this.extraState = ExtraState.NONE;
+		this.extras = null;
+		this.dirty = null;
+
+		return this;
+	}
+
+	public DuelContext putExtras(Map<String, ?> values) {
+		if (values == null) {
+			throw new NullPointerException("values");
+		}
+		for (String ident : values.keySet()) {
+			this.putExtra(ident, values.get(ident));
+		}
+
+		return this;
+	}
+
 	public DuelContext putExtra(String ident, Object value) {
 		if (ident == null) {
 			throw new NullPointerException("ident");
 				this.dirty.putSparse(ident, value);
 				break;
 		}
+
 		return this;
 	}
 

File duel/duel-runtime/src/main/java/org/duelengine/duel/DuelView.java

  */
 public abstract class DuelView {
 
-	private static final Object DEFAULT_DATA = null;
 	private static final int DEFAULT_INDEX = 0;
 	private static final int DEFAULT_COUNT = 1;
 	private static final String DEFAULT_KEY = null;
-	
+
 	private static final HTMLFormatter formatter = new HTMLFormatter();
 	private Map<String, DuelPart> parts = null;
 
 			throw new NullPointerException("output");
 		}
 
-		this.render(new DuelContext(output), DEFAULT_DATA, DEFAULT_INDEX, DEFAULT_COUNT, DEFAULT_KEY);
+		// build a context
+		this.render(new DuelContext().setOutput(output));
 	}
 
 	/**
 			throw new NullPointerException("output");
 		}
 
-		this.render(new DuelContext(output), DuelData.asProxy(data, true), DEFAULT_INDEX, DEFAULT_COUNT, DEFAULT_KEY);
+		// build a context
+		this.render(new DuelContext().setOutput(output).setData(data));
 	}
 
 	/**
-	 * Renders the view to the output
+	 * Binds the view to any data and renders the view to the output
 	 * @param context
 	 */
 	public void render(DuelContext context)
 			throw new NullPointerException("context");
 		}
 
-		this.render(context, DEFAULT_DATA, DEFAULT_INDEX, DEFAULT_COUNT, DEFAULT_KEY);
-	}
-
-	/**
-	 * Binds the view to the data and renders the view to the output
-	 * @param context
-	 * @param data
-	 */
-	public void render(DuelContext context, Object data)
-		throws IOException {
-
-		if (context == null) {
-			throw new NullPointerException("context");
-		}
-
-		this.render(context, DuelData.asProxy(data, true), DEFAULT_INDEX, DEFAULT_COUNT, DEFAULT_KEY);
+		this.render(context, DuelData.asProxy(context.getData(), true), DEFAULT_INDEX, DEFAULT_COUNT, DEFAULT_KEY);
 	}
 
 	/**

File duel/duel-runtime/src/main/java/org/duelengine/duel/rs/DuelController.java

 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
-import java.util.Map;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.StreamingOutput;
 import org.duelengine.duel.DuelContext;
 import org.duelengine.duel.DuelView;
 
 /**
- * MVC-style controller for using DUEL views in JAX-RS
+ * Simple MVC-style controller for using DUEL views in JAX-RS
  */
 public abstract class DuelController {
 
 	protected abstract DuelContext getViewContext();
 
 	/**
-	 * Renders a view to the response.
+	 * Builds a view result
 	 */
-	protected StreamingOutput view(Class<DuelView> view) {
-		return this.view(view, null, null);
+	protected ViewResult view(Class<? extends DuelView> view) {
+		return new ViewResult(view, this.getViewContext());
 	}
 
 	/**
-	 * Renders a view to the response after binding with data.
-	 */
-	protected StreamingOutput view(Class<DuelView> view, Object data) {
-		return this.view(view, data, null);
-	}
-
-	/**
-	 * Renders a view to the response after binding with data and extra ambient values.
-	 */
-	protected StreamingOutput view(Class<DuelView> view, Object data, Map<String, ?> extras) {
-		try {
-			DuelContext context = this.getViewContext();
-			if (extras != null) {
-				for (String ident : extras.keySet()) {
-					context.putExtra(ident, extras.get(ident));
-				}
-			}
-			return new ViewResult(view, data, context);
-
-		} catch (Exception ex) {
-			ex.printStackTrace();
-			return this.error(ex);
-		}
-	}
-
-	/**
-	 * Renders an error message.
+	 * Renders an error message to the response
 	 */
 	protected StreamingOutput error(final Exception ex) {
 		return new StreamingOutput() {
 			@Override
-			public void write(OutputStream stream) throws IOException, WebApplicationException {
+			public void write(OutputStream stream)
+				throws IOException, WebApplicationException {
+
 				new OutputStreamWriter(stream, "UTF-8").write(ex.toString());
 			}
 		};

File duel/duel-runtime/src/main/java/org/duelengine/duel/rs/ViewResult.java

 package org.duelengine.duel.rs;
 
+import java.util.Map;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.core.StreamingOutput;
 import org.duelengine.duel.DuelContext;
 import org.duelengine.duel.DuelView;
 
 /**
- * Simple adapter for using DUEL views in JAX-RS
+ * Simple adapter for rendering DUEL views in JAX-RS
  */
 public class ViewResult implements StreamingOutput {
 
 	private final DuelContext context;
 	private final DuelView view;
-	private final Object data;
 
-	public ViewResult(Class<DuelView> view, Object data, DuelContext context) {
+	public ViewResult(Class<? extends DuelView> view, DuelContext context) {
 
 		if (view == null) {
 			throw new NullPointerException("view");
 		}
-
 		try {
 			this.view = view.newInstance();
 		} catch (Exception ex) {
-			throw new IllegalArgumentException("Error instantiating view: "+view.getSimpleName(), ex);
+			throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR);
 		}
 
-		this.data = data;
 		this.context = (context != null) ? context : new DuelContext();
 	}
 
-	public ViewResult putExtra(String ident, Object value) {
-		this.context.putExtra(ident, value);
+	public ViewResult data(Object data) {
+		this.context.setData(data);
 
 		return this;
 	}
 
-	public void writeError(Writer output, Exception ex)
-		throws IOException {
+	public ViewResult extras(Map<String, ?> extras) {
+		this.context.putExtras(extras);
 
-		output.append("Error:");
-		output.append(ex.toString());
+		return this;
+	}
+
+	public ViewResult extra(String ident, Object value) {
+		this.context.putExtra(ident, value);
+
+		return this;
 	}
 
 	@Override
 		throws IOException, WebApplicationException {
 
 		Writer output = new OutputStreamWriter(stream, this.context.getFormat().getEncoding());
-		this.context.setOutput(output);
 
 		try {
-			if (this.data == null) {
-				this.view.render(this.context);
-			} else {
-				this.view.render(this.context, data);
-			}
+			this.view.render(this.context.setOutput(output));
+ 			output.flush();
 
 		} catch (Exception ex) {
-			this.writeError(output, ex);
+			throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR);
 
  		} finally {
- 			output.flush();
 			this.context.setOutput(null);
 		}
 	}