001 // This file is part of the Attempto Java Packages.
002 // Copyright 2008, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
003 //
004 // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the
005 // terms of the GNU Lesser General Public License as published by the Free Software Foundation,
006 // either version 3 of the License, or (at your option) any later version.
007 //
008 // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY
009 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
010 // PURPOSE. See the GNU Lesser General Public License for more details.
011 //
012 // You should have received a copy of the GNU Lesser General Public License along with the Attempto
013 // Java Packages. If not, see http://www.gnu.org/licenses/.
014
015 package ch.uzh.ifi.attempto.acewiki.gui.editor;
016
017 import java.util.ArrayList;
018 import java.util.List;
019
020 import nextapp.echo2.app.event.ActionEvent;
021 import nextapp.echo2.app.event.ActionListener;
022 import ch.uzh.ifi.attempto.acewiki.Task;
023 import ch.uzh.ifi.attempto.acewiki.Wiki;
024 import ch.uzh.ifi.attempto.acewiki.core.ontology.OntologyElement;
025 import ch.uzh.ifi.attempto.acewiki.core.ontology.Sentence;
026 import ch.uzh.ifi.attempto.acewiki.gui.page.ArticlePage;
027 import ch.uzh.ifi.attempto.echocomp.MessageWindow;
028 import ch.uzh.ifi.attempto.preditor.PreditorWindow;
029 import ch.uzh.ifi.attempto.preditor.text.TextContainer;
030 import ch.uzh.ifi.attempto.preditor.text.TextElement;
031
032 /**
033 * This class manages the predictive editor. It creates the editor window and handles its
034 * responses.
035 *
036 * @author Tobias Kuhn
037 */
038 public class SentenceEditorHandler implements ActionListener {
039
040 private static final long serialVersionUID = -2083910385095284075L;
041
042 private PreditorWindow editorWindow;
043 private MessageWindow messageWindow;
044 private ArticlePage page;
045 private Wiki wiki;
046 private boolean edit;
047 private Sentence sentence;
048 private List<Sentence> newSentences = new ArrayList<Sentence>();
049 private int checked = 0;
050
051 private SentenceEditorHandler(Sentence sentence, ArticlePage page, boolean edit) {
052 this.page = page;
053 this.wiki = page.getWiki();
054 this.edit = edit;
055 this.sentence = sentence;
056 AceWikiMenuCreator menuCreator = new AceWikiMenuCreator(wiki, page.getOntologyElement(), this);
057 editorWindow = new PreditorWindow("Sentence Editor", wiki.getGrammar(), menuCreator);
058 editorWindow.addActionListener(this);
059
060 if (edit) {
061 String t = sentence.getPrettyText();
062 // remove the last element (i.e. the period '.' or question mark '?'):
063 editorWindow.addText(t.substring(0, t.length()-1) + " ");
064 }
065 }
066
067 /**
068 * Generates a new preditive editor (short "preditor") window to create a new sentence.
069 *
070 * @param followingSentence The sentence in front of which the new sentences should be added,
071 * or null if the sentences should be added to the end of the article.
072 * @param page The host page into which the sentence should be added.
073 * @return A new preditor window.
074 */
075 public static PreditorWindow generatePreditorAddWindow(Sentence followingSentence, ArticlePage page) {
076 SentenceEditorHandler h = new SentenceEditorHandler(followingSentence, page, false);
077 return h.getPreditorWindow();
078 }
079
080 /**
081 * Generates a new preditive editor (short "preditor") window to create a new sentence.
082 *
083 * @param sentence The sentence that should be edited.
084 * @param page The host page which contains the sentence to be edited.
085 * @return A new preditor window.
086 */
087 public static PreditorWindow generatePreditorEditWindow(Sentence sentence, ArticlePage page) {
088 SentenceEditorHandler h = new SentenceEditorHandler(sentence, page, true);
089 return h.getPreditorWindow();
090 }
091
092 private PreditorWindow getPreditorWindow() {
093 return editorWindow;
094 }
095
096 public void actionPerformed(ActionEvent e) {
097 if (e.getSource() == editorWindow && e.getActionCommand().equals("OK")) {
098 TextContainer textContainer = editorWindow.getTextContainer();
099
100 TextElement finalElement = editorWindow.getPossibleNextToken(".");
101 if (finalElement == null) {
102 finalElement = editorWindow.getPossibleNextToken("?");
103 }
104 if (finalElement != null) textContainer.addElement(finalElement);
105
106 ArrayList<TextElement> l = textContainer.getTextElements();
107 if (l.isEmpty() || l.get(l.size() - 1).getText().matches("[.?]")) {
108 newSentences = Sentence.generateSentences(textContainer, page.getOntologyElement());
109 checkSentence();
110 } else {
111 wiki.log("edit", "error: unfinished sentences");
112 MessageWindow mw = new MessageWindow("Error", "There are unfinished sentences.", editorWindow, "OK");
113 page.getWiki().showWindow(mw);
114 }
115 } else if (e.getSource() == editorWindow && e.getActionCommand().equals("Cancel")) {
116 editorWindow.setVisible(false);
117 editorWindow.dispose();
118 } else if (e.getSource() == messageWindow && e.getActionCommand().equals("a ...")) {
119 checked++;
120 checkSentence();
121 } else if (e.getSource() == messageWindow && e.getActionCommand().equals("every ...")) {
122 String text = newSentences.get(checked).getText();
123 text = text.replaceFirst("^(A|a)n? ", "Every ");
124 newSentences.remove(checked);
125 newSentences.add(checked, new Sentence(text, page.getOntologyElement()));
126 checked++;
127 checkSentence();
128 } else if (e.getSource() == messageWindow && e.getActionCommand().equals("Close")) {
129 checked = 0;
130 } else if (e.getSource() instanceof TextElement) {
131 editorWindow.addTextElement((TextElement) e.getSource());
132 }
133 }
134
135 private void checkSentence() {
136 if (checked >= newSentences.size()) {
137 assertSentences();
138 } else {
139 List<TextElement> t = newSentences.get(checked).getTextElements();
140 String t0 = t.get(0).getText();
141 String t1 = t.get(1).getText();
142 String l = t.get(t.size()-1).getText();
143 if (t0.matches("(A|a)n?") && !t1.matches(".* of") && l.equals(".")) {
144 String s = t.get(1).getText();
145 messageWindow = new MessageWindow(
146 "Warning",
147 "Your sentence \"a " + s + " ...\" is interpreted as \"there is a " + s + " that ...\". " +
148 "Do you want to say \"every " + s + " ...\"?",
149 editorWindow,
150 this,
151 "a ...", "every ..."
152 );
153 wiki.showWindow(messageWindow);
154 } else {
155 checked++;
156 checkSentence();
157 }
158 }
159 }
160
161 private void assertSentences() {
162 final TextContainer textContainer = editorWindow.getTextContainer();
163 final OntologyElement el = page.getOntologyElement();
164
165 Task task = new Task() {
166
167 int success;
168
169 public void run() {
170 if (edit) {
171 wiki.log("edit", "sentence updated: " + textContainer.getText());
172 success = el.edit(sentence, newSentences);
173 } else {
174 wiki.log("edit", "sentence created: " + textContainer.getText());
175 success = el.add(sentence, newSentences);
176 }
177 }
178
179 public void updateGUI() {
180 page.update();
181 if (success == 1) {
182 wiki.showWindow(
183 new MessageWindow(
184 "Conflict",
185 "A sentence is in conflict with the current knowledge. For that reason, " +
186 "it cannot be added to the knowledge base.",
187 "OK"
188 )
189 );
190 } else if (success == 2) {
191 wiki.showWindow(
192 new MessageWindow(
193 "Error",
194 "A sentence could not be added to the knowledge base because the knowledge " +
195 "base got too complex.",
196 "OK"
197 )
198 );
199 }
200 if (page != null) {
201 page.update();
202 page.getWiki().update();
203 }
204 }
205
206 };
207
208 if (edit) {
209 wiki.enqueueTaskShowingWaitWindow("Updating", "The knowledge base is being updated...", task);
210 } else {
211 wiki.enqueueTaskShowingWaitWindow("Updating", "The sentence is being added to the knowledge base...", task);
212 }
213
214 editorWindow.setVisible(false);
215 }
216
217 }