package org.seqcode.projects.seqview.model; import java.util.*; import org.seqcode.gsebricks.verbs.Expander; import org.seqcode.gseutils.*; /** An ExpanderModel wraps an ewok Expander (something that maps an * input of type A to an iterator over type B). The expander's execute method * is called in response to new inputs and the results are cached * such that the getResults() method can be called multiple times. * * This caching is critical to the visualizer- we don't want to rerun the database query * every time the screen is redrawn (eg when the window is resized or uncovered) but the * input hasn't changed */ public class ExpanderModel<IN,OUT> extends SeqViewModel implements Runnable { private boolean newinput; public boolean reloadInput = false; private Expander<IN,OUT> expander; private IN input; private ArrayList<OUT> result; public ExpanderModel(Expander<IN,OUT> ex) { super(); expander = ex; newinput = false; } public synchronized void run() { while(keepRunning()) { try { if (!(newinput || reloadInput)) { wait(); } } catch (InterruptedException ex) { } if (newinput || reloadInput) { reloadInput = false; try { Iterator<OUT>iter = expander.execute(input); result = new ArrayList<OUT>(); clearValues(); while (iter.hasNext()) { OUT nextValue = iter.next(); if(registerValue(nextValue)) { result.add(nextValue); } } } catch (Exception ex) { ex.printStackTrace(); } newinput = false; notifyListeners(); } } } protected void setExpander(Expander<IN,OUT> expander) { synchronized(this) { if (this.expander != null && this.expander instanceof Closeable) { ((Closeable)this.expander).close(); } this.expander = expander; } } public void doReload() { synchronized(this) { reloadInput = true; this.notifyAll(); } } protected void clearValues() { } protected boolean registerValue(OUT value) { return true; } public synchronized void setInput(IN i) { if (newinput == false) { if (!i.equals(input)) { input = i; newinput = true; } else { notifyListeners(); } } } public Iterator<OUT> getResults() { if (newinput == false && result != null) { return result.iterator(); } else { // or should we throw some exception? return null; } } public boolean isReady() {return !newinput;} }