001: /*
002: * $Id: LogikusMediator.java,v 1.1 2003/08/19 01:12:57 jonesde Exp $
003: *
004: * Copyright (c) 1999 Steven J. Metsker.
005: * Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
006: *
007: * Permission is hereby granted, free of charge, to any person obtaining a
008: * copy of this software and associated documentation files (the "Software"),
009: * to deal in the Software without restriction, including without limitation
010: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
011: * and/or sell copies of the Software, and to permit persons to whom the
012: * Software is furnished to do so, subject to the following conditions:
013: *
014: * The above copyright notice and this permission notice shall be included
015: * in all copies or substantial portions of the Software.
016: *
017: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
018: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
019: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
020: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
021: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
022: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
023: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
024: */
025: package org.ofbiz.rules.logikus;
026:
027: import javax.swing.*;
028: import java.awt.event.*;
029: import org.ofbiz.rules.engine.*;
030:
031: /**
032: * This class supports a <code>LogikusIde</code> object, handling the interaction of the IDE's components.
033: * <p>
034: * An object of the IDE (Interactive Development
035: * Environment) has text areas for a Logikus program, a
036: * query against the program, and for the results of a
037: * query.
038: * <p>
039: * When a user clicks on the "Next" or "Rest" button, the
040: * mediator parses the program (if it has changed), and
041: * parses the query (if the query has changed). The
042: * mediator then proves the query against the program.
043: * After each proof, the mediator displays the query's
044: * variables in the results text area.
045: * <p>
046: * The mediator uses a separate thread to prove the query.
047: * While this thread conducts a proof, the mediator
048: * disables most of the IDE's components, except for the
049: * "Halt" button, which stops the proof thread.
050: *
051: * @author Steven J. Metsker
052: * @version 1.0
053: */
054: public class LogikusMediator implements ActionListener, Runnable {
055:
056: protected JButton proveNextButton;
057: protected JButton proveRestButton;
058: protected JButton haltButton;
059: protected JButton clearProgramButton;
060: protected JButton clearResultsButton;
061:
062: protected JTextArea programArea;
063: protected JTextArea resultsArea;
064: protected JTextArea queryArea;
065:
066: protected boolean proveRemaining;
067:
068: protected Thread computeThread;
069:
070: protected String lastProgramText = null;
071: protected String lastQueryText = null;
072: protected Program program;
073: protected Query query;
074:
075: /**
076: * This method reacts, when the user presses one of the
077: * IDE's buttons.
078: *
079: * @param ActionEvent the event
080: */
081: public void actionPerformed(ActionEvent event) {
082: Object object = event.getSource();
083:
084: if (object == clearResultsButton) {
085: resultsArea.selectAll();
086: resultsArea.copy();
087: resultsArea.setText("");
088: }
089: if (object == clearProgramButton) {
090: programArea.selectAll();
091: programArea.copy();
092: programArea.setText("");
093: queryArea.setText("");
094: }
095:
096: if (object == proveNextButton || object == proveRestButton) {
097:
098: proveRemaining = (object == proveRestButton);
099: conductProof();
100: }
101: if (object == haltButton) {
102:
103: /*
104: if (computeThread != null) {
105: computeThread.stop();
106: }
107: */
108: computeThread = null;
109: setComputing(false);
110: }
111: }
112:
113: /**
114: * Parse the program and query (if they have changed)
115: * and proved the query in a separate thread.
116: */
117: protected void conductProof() {
118: setComputing(true);
119: try {
120: parseProgramAndQuery();
121: } catch (Exception e) {
122: String text = e.toString();
123:
124: if (e.getMessage() != null) {
125: text = e.getMessage();
126: }
127: resultsArea.append(text + "\n");
128: setComputing(false);
129: return;
130: }
131: computeThread = new Thread(this );
132: computeThread.start();
133: // this thread will setComputing(false) in due time.
134: }
135:
136: /**
137: * Appends the given line to the results text area,
138: * scheduling this event with the event-dispatching thread.
139: *
140: * @param String the string to append to the results
141: * area
142: */
143: protected void display(final String s) {
144: // Using invokeAndWait() keeps appends from outrunning
145: // the event dispatch thread.
146:
147: Runnable r = new Runnable() {
148: public void run() {
149: resultsArea.append(s);
150: }
151: };
152:
153: try {
154: SwingUtilities.invokeAndWait(r);
155: } catch (Exception e) {
156: resultsArea.append(e.getMessage());
157: }
158: }
159:
160: /**
161: * Make the IDE's GUI components available.
162: */
163: public void initialize(JButton proveNextButton,
164: JButton proveRestButton, JButton haltButton,
165: JButton clearProgramButton, JButton clearResultsButton,
166: JTextArea programArea, JTextArea resultsArea,
167: JTextArea queryArea) {
168:
169: this .proveNextButton = proveNextButton;
170: this .proveRestButton = proveRestButton;
171: this .haltButton = haltButton;
172: this .clearProgramButton = clearProgramButton;
173: this .clearResultsButton = clearResultsButton;
174: this .programArea = programArea;
175: this .resultsArea = resultsArea;
176: this .queryArea = queryArea;
177: }
178:
179: /**
180: * Parses the program and query texts.
181: */
182: protected void parseProgramAndQuery() {
183:
184: boolean programChanged = false;
185: String programText = programArea.getText();
186:
187: programChanged = (lastProgramText == null)
188: || (!lastProgramText.equals(programText));
189: if (programChanged) {
190: program = LogikusFacade.program(programText);
191: }
192: lastProgramText = programText;
193:
194: String queryText = queryArea.getText();
195:
196: // create a fresh query if the program changes or the
197: // query text changes
198:
199: if (programChanged || (lastQueryText == null)
200: || (!lastQueryText.equals(queryText))) {
201: query = LogikusFacade.query(queryText, program);
202: }
203: lastQueryText = queryText;
204: }
205:
206: /**
207: * Proves the query against the program.
208: */
209: protected void proveNext() {
210: if (query.canFindNextProof()) {
211: Unification vars = query.variables();
212:
213: if (vars.size() == 0) {
214: display("yes\n");
215: } else {
216: display(vars + "\n");
217: }
218: } else {
219: display("no\n");
220: }
221: }
222:
223: /**
224: * Proves the query against the program until no proofs
225: * remain.
226: */
227: protected void proveRemaining() {
228: Unification vars = query.variables();
229:
230: while (query.canFindNextProof()) {
231: if (vars.size() == 0) {
232: display("yes\n");
233: return;
234: } else {
235: display(vars + "\n");
236: }
237: }
238: display("no\n");
239: }
240:
241: /**
242: * Proves the query against the program.
243: */
244: public void run() {
245: try {
246: if (proveRemaining) {
247: proveRemaining();
248: } else {
249: proveNext();
250: }
251: } catch (Exception e) {
252: resultsArea.append(e.getMessage());
253: } finally {
254: setComputing(false);
255: }
256: }
257:
258: /**
259: * Sets the state of the IDE to computing or not. Most of the
260: * IDE's controls are grayed out during computation of a
261: * program.
262: *
263: * @param boolean if true, indicates that a proof thread
264: * is finding one or more proofs
265: */
266: protected void setComputing(boolean computing) {
267:
268: // computing means everything is disabled, except "Halt"
269:
270: proveNextButton.setEnabled(!computing);
271: proveRestButton.setEnabled(!computing);
272: clearProgramButton.setEnabled(!computing);
273: clearResultsButton.setEnabled(!computing);
274: programArea.setEnabled(!computing);
275: resultsArea.setEnabled(!computing);
276: queryArea.setEnabled(!computing);
277:
278: haltButton.setEnabled(computing);
279: }
280: }
|