001    // This file is part of AceWiki.
002    // Copyright 2008-2012, AceWiki developers.
003    // 
004    // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
005    // Lesser General Public License as published by the Free Software Foundation, either version 3 of
006    // the License, or (at your option) any later version.
007    // 
008    // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009    // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010    // Lesser General Public License for more details.
011    // 
012    // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
013    // not, see http://www.gnu.org/licenses/.
014    
015    package ch.uzh.ifi.attempto.acewiki.gui;
016    
017    import java.util.ArrayList;
018    import java.util.List;
019    
020    import nextapp.echo.app.event.ActionEvent;
021    import nextapp.echo.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.Article;
025    import ch.uzh.ifi.attempto.acewiki.core.Comment;
026    import ch.uzh.ifi.attempto.acewiki.core.InconsistencyException;
027    import ch.uzh.ifi.attempto.acewiki.core.LanguageHandler;
028    import ch.uzh.ifi.attempto.acewiki.core.LanguageUtils;
029    import ch.uzh.ifi.attempto.acewiki.core.Ontology;
030    import ch.uzh.ifi.attempto.acewiki.core.Sentence;
031    import ch.uzh.ifi.attempto.acewiki.core.SentenceSuggestion;
032    import ch.uzh.ifi.attempto.acewiki.core.Statement;
033    import ch.uzh.ifi.attempto.base.PredictiveParser;
034    import ch.uzh.ifi.attempto.base.TextContainer;
035    import ch.uzh.ifi.attempto.base.TextElement;
036    import ch.uzh.ifi.attempto.echocomp.MessageWindow;
037    import ch.uzh.ifi.attempto.preditor.PreditorWindow;
038    
039    /**
040     * This class manages the predictive editor. It creates the editor window and handles its
041     * responses.
042     * 
043     * @author Tobias Kuhn
044     */
045    public class SentenceEditorHandler implements ActionListener {
046            
047            private static final long serialVersionUID = -2083910385095284075L;
048            
049            private PreditorWindow editorWindow;
050            private MessageWindow messageWindow;
051            private ArticlePage page;
052            private Wiki wiki;
053            private boolean edit;
054            private Statement statement;
055            private List<Sentence> newSentences = new ArrayList<Sentence>();
056            private int checked = 0;
057            private SentenceSuggestion suggestion;
058            
059            private SentenceEditorHandler(Statement statement, ArticlePage page, boolean edit) {
060                    this.page = page;
061                    this.wiki = page.getWiki();
062                    this.edit = edit;
063                    this.statement = statement;
064                    AceWikiMenuCreator menuCreator = new AceWikiMenuCreator(
065                                    wiki,
066                                    page.getOntologyElement(),
067                                    this
068                            );
069                    LanguageHandler lh = wiki.getLanguageHandler();
070                    editorWindow = new PreditorWindow("Sentence Editor", lh.getPredictiveParser());
071                    editorWindow.setMenuCreator(menuCreator);
072                    editorWindow.setLogger(wiki.getLogger());
073                    editorWindow.addActionListener(this);
074                    editorWindow.setTextOperator(lh.getTextOperator());
075                    
076                    if (edit) {
077                            Comment c = (Comment) statement;
078                            editorWindow.addText(LanguageUtils.getPrettyPrinted(c.getText()) + " ");
079                    }
080            }
081            
082            /**
083             * Generates a new preditive editor window for the creation of a new sentence.
084             * 
085             * @param followingStatement The statement in front of which the new sentences should be added,
086             *   or null if the sentences should be added to the end of the article.
087             * @param page The host page into which the sentence should be added.
088             * @return A new preditor window.
089             */
090            public static PreditorWindow generateCreationWindow(Statement followingStatement,
091                            ArticlePage page) {
092                    SentenceEditorHandler h = new SentenceEditorHandler(followingStatement, page, false);
093                    return h.getWindow();
094            }
095            
096            /**
097             * Generates a new preditive editor window for editing an existing sentence.
098             * 
099             * @param sentence The sentence that should be edited.
100             * @param page The host page which contains the sentence to be edited.
101             * @return A new preditor window.
102             */
103            public static PreditorWindow generateEditWindow(Sentence sentence, ArticlePage page) {
104                    SentenceEditorHandler h = new SentenceEditorHandler(sentence, page, true);
105                    return h.getWindow();
106            }
107            
108            private PreditorWindow getWindow() {
109                    return editorWindow;
110            }
111    
112            public void actionPerformed(ActionEvent e) {
113                    Object src = e.getSource();
114                    String c = e.getActionCommand();
115                    if (src == editorWindow && c.matches("OK|Enter")) {
116                            Ontology o = wiki.getOntology();
117                            LanguageHandler lh = wiki.getLanguageHandler();
118                            
119                            for (String t : lh.getEditorController().getAutocompleteTokens()) {
120                                    if (editorWindow.isPossibleNextToken(t)) {
121                                            editorWindow.addTextElement(lh.getTextOperator().createTextElement(t));
122                                            break;
123                                    }
124                            }
125                            
126                            PredictiveParser parser = editorWindow.getPredictiveParser();
127                            if (parser.getTokenCount() == 0) {
128                                    wiki.removeWindow(editorWindow);
129                            } else if (parser.isComplete()) {
130                                    newSentences = o.getStatementFactory().extractSentences(
131                                                    wiki.getLanguageHandler(),
132                                                    editorWindow.getTextContainer(),
133                                                    parser,
134                                                    page.getArticle()
135                                            );
136                                    checkSentence();
137                            } else if (c.equals("OK")) {
138                                    wiki.log("edit", "error: unfinished sentences");
139                                    MessageWindow mw = new MessageWindow(
140                                                    "Error",
141                                                    "There are unfinished sentences.",
142                                                    editorWindow,
143                                                    "OK"
144                                            );
145                                    page.getWiki().showWindow(mw);
146                            }
147                    } else if (src == editorWindow && c.matches("Cancel|Close|Escape")) {
148                            wiki.removeWindow(editorWindow);
149                    } else if (src == messageWindow && c.equals("Close")) {
150                            checked = 0;
151                    } else if (src == messageWindow && suggestion != null) {
152                            Sentence s = suggestion.getSentence(c);
153                            if (s != newSentences.get(checked)) {
154                                    newSentences.remove(checked);
155                                    newSentences.add(checked, s);
156                            }
157                            checked++;
158                            checkSentence();
159                    } else if (src instanceof TextElement) {
160                            editorWindow.addTextElement((TextElement) src);
161                    }
162            }
163            
164            private void checkSentence() {
165                    if (checked >= newSentences.size()) {
166                            assertSentences();
167                    } else {
168                            suggestion = wiki.getLanguageHandler().getSuggestion(newSentences.get(checked));
169                            if (suggestion != null) {
170                                    messageWindow = new MessageWindow(
171                                                    "Suggestion",
172                                                    suggestion.getMessage(),
173                                                    editorWindow,
174                                                    this,
175                                                    suggestion.getOptions()
176                                            );
177                                    wiki.showWindow(messageWindow);
178                            } else {
179                                    checked++;
180                                    checkSentence();
181                            }
182                    }
183            }
184            
185            private void assertSentences() {
186                    final TextContainer textContainer = editorWindow.getTextContainer();
187                    final Article a = page.getArticle();
188                    
189                    Task task = new Task() {
190                            
191                            boolean inconsistent = false;
192                            
193                            public void run() {
194                                    try {
195                                            if (edit) {
196                                                    wiki.log("edit", "sentence updated: " + textContainer.getText());
197                                                    a.edit(statement, new ArrayList<Statement>(newSentences));
198                                            } else {
199                                                    wiki.log("edit", "sentence created: " + textContainer.getText());
200                                                    a.add(statement, new ArrayList<Statement>(newSentences));
201                                            }
202                                    } catch (InconsistencyException ex) {
203                                            inconsistent = true;
204                                    }
205                            }
206                            
207                            public void updateGUI() {
208                                    page.update();
209                                    if (inconsistent) {
210                                            wiki.showWindow(
211                                                    new MessageWindow(
212                                                            "Conflict",
213                                                            "The sentence is in conflict with the current knowledge. For that " +
214                                                                    "reason, it cannot be added to the knowledge base.",
215                                                            "OK"
216                                                    )
217                                            );
218                                    }
219                                    if (page != null) {
220                                            page.update();
221                                            page.getWiki().update();
222                                    }
223                            }
224                            
225                    };
226                    
227                    if (edit) {
228                            wiki.enqueueStrongAsyncTask(
229                                            "Updating",
230                                            "The knowledge base is being updated...",
231                                            task
232                                    );
233                    } else {
234                            wiki.enqueueStrongAsyncTask(
235                                            "Updating",
236                                            "The sentence is being added to the knowledge base...",
237                                            task
238                                    );
239                    }
240                    
241                    wiki.removeWindow(editorWindow);
242            }
243    
244    }