    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;
    016
    017    import java.io.IOException;
    018    import java.io.InputStream;
    019    import java.io.OutputStream;
    020    import java.util.ArrayList;
    021    import java.util.Collection;
    022    import java.util.Properties;
    023    import java.util.Random;
    024    import java.util.Stack;
    025
    026    import nextapp.echo2.app.ApplicationInstance;
    027    import nextapp.echo2.app.Color;
    028    import nextapp.echo2.app.Column;
    029    import nextapp.echo2.app.ContentPane;
    030    import nextapp.echo2.app.Extent;
    031    import nextapp.echo2.app.Font;
    032    import nextapp.echo2.app.Insets;
    033    import nextapp.echo2.app.ResourceImageReference;
    034    import nextapp.echo2.app.Row;
    035    import nextapp.echo2.app.SplitPane;
    036    import nextapp.echo2.app.TaskQueueHandle;
    037    import nextapp.echo2.app.event.ActionEvent;
    038    import nextapp.echo2.app.event.ActionListener;
    039    import nextapp.echo2.app.filetransfer.Download;
    040    import nextapp.echo2.app.filetransfer.DownloadProvider;
    041    import ch.uzh.ifi.attempto.acewiki.core.grammar.StandardGrammar;
    042    import ch.uzh.ifi.attempto.acewiki.core.ontology.Individual;
    043    import ch.uzh.ifi.attempto.acewiki.core.ontology.NounConcept;
    044    import ch.uzh.ifi.attempto.acewiki.core.ontology.OfRole;
    045    import ch.uzh.ifi.attempto.acewiki.core.ontology.Ontology;
    046    import ch.uzh.ifi.attempto.acewiki.core.ontology.OntologyElement;
    047    import ch.uzh.ifi.attempto.acewiki.core.ontology.TrAdjRole;
    048    import ch.uzh.ifi.attempto.acewiki.core.ontology.VerbRole;
    049    import ch.uzh.ifi.attempto.acewiki.core.text.OntologyTextElement;
    050    import ch.uzh.ifi.attempto.acewiki.gui.ListItem;
    051    import ch.uzh.ifi.attempto.acewiki.gui.editor.NounForm;
    052    import ch.uzh.ifi.attempto.acewiki.gui.editor.NounOfForm;
    053    import ch.uzh.ifi.attempto.acewiki.gui.editor.ProperNameForm;
    054    import ch.uzh.ifi.attempto.acewiki.gui.editor.TrAdjForm;
    055    import ch.uzh.ifi.attempto.acewiki.gui.editor.VerbForm;
    056    import ch.uzh.ifi.attempto.acewiki.gui.editor.WordEditorWindow;
    057    import ch.uzh.ifi.attempto.acewiki.gui.page.ArticlePage;
    058    import ch.uzh.ifi.attempto.acewiki.gui.page.IndexPage;
    059    import ch.uzh.ifi.attempto.acewiki.gui.page.SearchPage;
    060    import ch.uzh.ifi.attempto.acewiki.gui.page.StartPage;
    061    import ch.uzh.ifi.attempto.acewiki.gui.page.WikiPage;
    062    import ch.uzh.ifi.attempto.chartparser.Grammar;
    063    import ch.uzh.ifi.attempto.echocomp.GeneralButton;
    064    import ch.uzh.ifi.attempto.echocomp.Label;
    065    import ch.uzh.ifi.attempto.echocomp.MessageWindow;
    066    import ch.uzh.ifi.attempto.echocomp.SmallButton;
    067    import ch.uzh.ifi.attempto.echocomp.SolidLabel;
    068    import ch.uzh.ifi.attempto.echocomp.Style;
    069    import ch.uzh.ifi.attempto.echocomp.VSpace;
    070    import ch.uzh.ifi.attempto.echocomp.WindowPane;
    071    import ch.uzh.ifi.attempto.preditor.PreditorWindow;
    072
    073    /**
    074     * This class represents an AceWiki wiki.
    075     *
    076     * @author Tobias Kuhn
    077     */
    078    public class Wiki implements ActionListener {
    079
    080            private static final long serialVersionUID = 2777443689044226043L;
    081
    082            private final Ontology ontology;
    083
    084            private WikiPage currentPage;
    085            private ContentPane mainPane = new ContentPane();
    086            private ContentPane contentPane = new ContentPane();
    087            private Row navigationButtons = new Row();
    088            private Logger logger;
    089
    090            private GeneralButton backButton = new GeneralButton("<Back", this);
    091            private GeneralButton forwardButton = new GeneralButton("Forward>", this);
    092            private GeneralButton refreshButton = new GeneralButton("Refresh", this);
    093
    094            private SmallButton indexButton = new SmallButton("Index", this, 12);
    095            private SmallButton homeButton = new SmallButton("Main Page", this, 12);
    096            private SmallButton randomButton = new SmallButton("Random Article", this, 12);
    097            private SmallButton searchButton = new SmallButton("Search", this, 12);
    098            private SmallButton newButton = new SmallButton("New Word...", this, 12);
    099            private SmallButton exportButton = new SmallButton("Export", this, 12);
    100            private SmallButton logoutButton = new SmallButton("Logout", this, 12);
    101            private ListItem logoutListItem;
    102            private Label logo;
    103
    104            private StartPage startPage;
    105
    106            private Stack<WikiPage> history = new Stack<WikiPage>();
    107            private Stack<WikiPage> forward = new Stack<WikiPage>();
    108
    109            private ArrayList<WindowPane> windows = new ArrayList<WindowPane>();
    110
    111            private Grammar grammar = new StandardGrammar();
    112
    113            private TaskQueueHandle taskQueue;
    114
    115            private ApplicationInstance application;
    116
    117            private static Properties properties;
    118
    119            /**
    120             * Creates a new wiki instance.
    121             *
    122             * @param ontology The ontology that is loaded into the wiki.
    123             * @param title The title of the wiki.
    124             * @param description The description of the wiki.
    125             * @param sessionID The session id.
    126             */
    127            Wiki(Ontology ontology, String title, String description, int sessionID) {
    128                    this.ontology = ontology;
    129
    130                    logger = new Logger(ontology.getName(), sessionID);
    131                    application = ApplicationInstance.getActive();
    132                    taskQueue = application.createTaskQueue();
    133
    134                    SplitPane splitPane1 = new SplitPane(SplitPane.ORIENTATION_VERTICAL_TOP_BOTTOM);
    135                    splitPane1.setSeparatorPosition(new Extent(50));
    136                    splitPane1.setSeparatorHeight(new Extent(0));
    137
    138                    navigationButtons.setInsets(new Insets(5, 5, 5, 26));
    139                    navigationButtons.setCellSpacing(new Extent(5));
    140                    navigationButtons.setBackground(new Color(230, 230, 230));
    141
    142                    navigationButtons.add(backButton);
    143                    navigationButtons.add(forwardButton);
    144                    navigationButtons.add(refreshButton);
    145
    146                    ContentPane menuBar = new ContentPane();
    147                    menuBar.add(navigationButtons);
    148
    149                    SplitPane splitPane2 = new SplitPane(SplitPane.ORIENTATION_HORIZONTAL_LEFT_RIGHT, new Extent(145));
    150                    splitPane2.setSeparatorHeight(new Extent(0));
    151
    152                    ContentPane sideBar = new ContentPane();
    153                    sideBar.setBackground(new Color(230, 230, 230));
    154                    Column sideCol = new Column();
    155                    sideCol.setInsets(new Insets(10, 10));
    156
    157                    logo = new Label();
    158                    sideCol.add(logo);
    159
    160                    sideCol.add(new VSpace(30));
    161
    162                    SolidLabel label1 = new SolidLabel("Navigation:", Font.ITALIC);
    163                    label1.setFont(new Font(Style.fontTypeface, Font.ITALIC, new Extent(10)));
    164                    sideCol.add(label1);
    165                    sideCol.add(new ListItem(homeButton));
    166                    sideCol.add(new ListItem(indexButton));
    167                    sideCol.add(new ListItem(randomButton));
    168                    sideCol.add(new ListItem(searchButton));
    169
    170                    sideCol.add(new VSpace(10));
    171
    172                    SolidLabel label2 = new SolidLabel("Actions:", Font.ITALIC);
    173                    label2.setFont(new Font(Style.fontTypeface, Font.ITALIC, new Extent(10)));
    174                    sideCol.add(label2);
    175                    sideCol.add(new ListItem(newButton));
    176                    sideCol.add(new ListItem(exportButton));
    177                    logoutListItem = new ListItem(logoutButton);
    178                    logoutButton.setWidth(new Extent(110));
    179                    logoutListItem.setVisible(false);
    180                    sideCol.add(logoutListItem);
    181
    182                    //sideCol.add(new VSpace(20));
    183                    //sideCol.add(new ItalicLabel("Session ID: " + sessionID));
    184
    185                    sideBar.add(sideCol);
    186
    187                    SplitPane splitPane3 = new SplitPane(SplitPane.ORIENTATION_HORIZONTAL_LEFT_RIGHT);
    188                    splitPane3.setSeparatorWidth(new Extent(1));
    189                    splitPane3.setSeparatorColor(Color.BLACK);
    190                    splitPane3.setSeparatorPosition(new Extent(0));
    191                    splitPane3.add(new Label());
    192
    193                    SplitPane splitPane4 = new SplitPane(SplitPane.ORIENTATION_VERTICAL_TOP_BOTTOM);
    194                    splitPane4.setSeparatorHeight(new Extent(1));
    195                    splitPane4.setSeparatorColor(Color.BLACK);
    196                    splitPane4.setSeparatorPosition(new Extent(0));
    197                    splitPane4.add(new Label());
    198
    199                    splitPane3.add(splitPane4);
    200                    splitPane4.add(mainPane);
    201
    202                    splitPane1.add(menuBar);
    203                    splitPane1.add(splitPane3);
    204
    205                    splitPane2.add(sideBar);
    206                    splitPane2.add(splitPane1);
    207
    208                    contentPane.add(splitPane2);
    209
    210                    startPage = new StartPage(this, title, description);
    211
    212                    setCurrentPage(startPage);
    213                    update();
    214            }
    215
    216            /**
    217             * Returns the content pane containing the wiki GUI.
    218             *
    219             * @return The content pane.
    220             */
    221            public ContentPane getContentPane() {
    222                    return contentPane;
    223            }
    224
    225            /**
    226             * Displays the window in the wiki.
    227             *
    228             * @param window The window to be shown.
    229             */
    230            public void showWindow(WindowPane window) {
    231                    if (window instanceof WordEditorWindow || window instanceof PreditorWindow) {
    232                            ArrayList<WindowPane> windowsNew = new ArrayList<WindowPane>();
    233                            for (WindowPane wp : windows) {
    234                                    if (wp.isVisible()) windowsNew.add(wp);
    235                            }
    236                            windows = windowsNew;
    237                            int c = windows.size();
    238                            window.setPositionX(new Extent(50 + (c % 5)*40));
    239                            window.setPositionY(new Extent(50 + (c % 5)*20));
    240                            windows.add(window);
    241                    }
    242                    getContentPane().add(window);
    243            }
    244
    245            /**
    246             * Switches to the given page.
    247             *
    248             * @param page The page to switch to.
    249             */
    250            public void showPage(WikiPage page) {
    251                    if (!currentPage.equals(page)) {
    252                            history.push(currentPage);
    253                            forward.clear();
    254                    }
    255                    setCurrentPage(page);
    256                    log("navi", "goto: " + page);
    257                    update();
    258            }
    259
    260            /**
    261             * Switches to the page of the given ontology element.
    262             *
    263             * @param e The ontology element the page of which should be shown.
    264             */
    265            public void showPage(OntologyElement e) {
    266                    showPage(ArticlePage.create(e, this));
    267            }
    268
    269            /**
    270             * Go to the previous page in the history.
    271             */
    272            public void back() {
    273                    if (history.isEmpty()) return;
    274                    forward.push(currentPage);
    275                    WikiPage page = history.pop();
    276                    setCurrentPage(page);
    277                    log("navi", "back: " + page);
    278                    update();
    279            }
    280
    281            /**
    282             * Go to the next page in the history.
    283             */
    284            public void forward() {
    285                    if (forward.isEmpty()) return;
    286                    history.push(currentPage);
    287                    WikiPage page = forward.pop();
    288                    setCurrentPage(page);
    289                    log("navi", "forw: " + page);
    290                    update();
    291            }
    292
    293            /**
    294             * Show the start page.
    295             */
    296            public void showStartPage() {
    297                    showPage(startPage);
    298            }
    299
    300            /**
    301             * Show the index page.
    302             */
    303            public void showIndexPage() {
    304                    showPage(new IndexPage(this));
    305            }
    306
    307            /**
    308             * Show the search page.
    309             */
    310            public void showSearchPage() {
    311                    showPage(new SearchPage(this));
    312            }
    313
    314            /**
    315             * Returns the ontology;
    316             *
    317             * @return The ontology.
    318             */
    319            public Ontology getOntology() {
    320                    return ontology;
    321            }
    322
    323            /**
    324             * Returns all ontology elements.
    325             *
    326             * @return A collection of all ontology elements.
    327             */
    328            public Collection<OntologyElement> getOntologyElements() {
    329                    return ontology.getOntologyElements();
    330            }
    331
    332            /**
    333             * Updates the GUI.
    334             */
    335            public void update() {
    336                    mainPane.removeAll();
    337                    mainPane.add(currentPage);
    338
    339                    backButton.setEnabled(!history.isEmpty());
    340                    forwardButton.setEnabled(!forward.isEmpty());
    341
    342                    if (ontology.isConsistent()) {
    343                            logo.setIcon(new ResourceImageReference("ch/uzh/ifi/attempto/acewiki/gui/img/AceWikiLogoSmall.png"));
    344                    } else {
    345                            logo.setIcon(new ResourceImageReference("ch/uzh/ifi/attempto/acewiki/gui/img/AceWikiLogoSmallRed.png"));
    346                    }
    347            }
    348
    349            private void setCurrentPage(WikiPage currentPage) {
    350                    this.currentPage = currentPage;
    351                    refresh();
    352            }
    353
    354            /**
    355             * Refreshes the current page.
    356             */
    357            public void refresh() {
    358                    currentPage.update();
    359            }
    360
    361            public void actionPerformed(ActionEvent e) {
    362                    if (e.getSource() == backButton) {
    363                            log("page", "pressed: back");
    364                            back();
    365                    } else if (e.getSource() == forwardButton) {
    366                            log("page", "pressed: forward");
    367                            forward();
    368                    } else if (e.getSource() == indexButton) {
    369                            log("page", "pressed: index");
    370                            showIndexPage();
    371                    } else if (e.getSource() == homeButton) {
    372                            log("page", "pressed: main page");
    373                            showStartPage();
    374                    } else if (e.getSource() == randomButton) {
    375                            log("page", "pressed: random page");
    376                            ArrayList<OntologyElement> elements = new ArrayList<OntologyElement>(ontology.getOntologyElements());
    377                            if (elements.size() > 0) {
    378                                    int r = (new Random()).nextInt(elements.size());
    379                                    showPage(elements.get(r));
    380                            } else {
    381                                    showStartPage();
    382                            }
    383                    } else if (e.getSource() == refreshButton) {
    384                            log("page", "pressed: refresh");
    385                            update();
    386                            refresh();
    387                    } else if (e.getSource() == newButton) {
    388                            log("page", "pressed: new word");
    389                            WordEditorWindow w = WordEditorWindow.createCreatorWindow();
    390                            w.addTab(new ProperNameForm(new Individual(), w, this, this));
    391                            w.addTab(new NounForm(new NounConcept(), 0, w, this, this));
    392                            w.addTab(new NounOfForm(new OfRole(), w, this, this));
    393                            w.addTab(new VerbForm(new VerbRole(), 0, w, this, this));
    394                            w.addTab(new TrAdjForm(new TrAdjRole(), w, this, this));
    395                            showWindow(w);
    396                    } else if (e.getSource() == searchButton) {
    397                            log("page", "pressed: search");
    398                            showSearchPage();
    399                    } else if (e.getSource() == exportButton) {
    400                            final String f = ontology.getOWLOntologyAsXML();
    401                            DownloadProvider provider = new DownloadProvider() {
    402
    403                                    public String getContentType() {
    404                                            return "application/owl+xml";
    405                                    }
    406
    407                                    public String getFileName() {
    408                                            return ontology.getName() + ".owl";
    409                                    }
    410
    411                                    public int getSize() {
    412                                            return f.length();
    413                                    }
    414
    415                                    public void writeFile(OutputStream out) throws IOException {
    416                                            out.write(f.getBytes());
    417                                            out.close();
    418                                    }
    419
    420                            };
    421                    application.enqueueCommand(new Download(provider, true));
    422                    } else if (e.getSource() == logoutButton) {
    423                            showWindow(new MessageWindow("Logout", "Do you really want to log out?", null, this, "Yes", "No"));
    424                    } else if (e.getSource() instanceof MessageWindow && e.getActionCommand().equals("Yes")) {
    425                            ((AceWikiApp) ApplicationInstance.getActive()).logout();
    426                    } else if (e.getSource() instanceof OntologyTextElement) {
    427                            // for newly generated elements
    428                            OntologyTextElement te = (OntologyTextElement) e.getSource();
    429                            log("edit", "new word: " + te.getOntologyElement().getWord());
    430                            showPage(te.getOntologyElement());
    431                    }
    432            }
    433
    434            /**
    435             * Writes the log entry to the log file.
    436             *
    437             * @param type The type of the log entry.
    438             * @param text The text of the log entry.
    439             */
    440            public void log(String type, String text) {
    441                    logger.log(type, text);
    442            }
    443
    444            /**
    445             * Sets the user name.
    446             *
    447             * @param username The user name.
    448             */
    449            public void setUsername(String username) {
    450                    logger.setUsername(username);
    451                    logoutButton.setText("Logout: " + username);
    452                    logoutListItem.setVisible(true);
    453            }
    454
    455            /**
    456             * Returns the grammar to be used for this wiki.
    457             *
    458             * @return The grammar.
    459             */
    460            public Grammar getGrammar() {
    461                    return grammar;
    462            }
    463
    464            /**
    465             * Runs the task without showing a wait window while it is executed.
    466             *
    467             * @param task The task.
    468             */
    469            public void enqueueTask(Runnable task) {
    470                    application.enqueueTask(taskQueue, task);
    471            }
    472
    473            /**
    474             * Runs the task and shows a wait window while it is executed.
    475             *
    476             * @param title The title of the wait window.
    477             * @param message The message of the wait window.
    478             * @param task The task.
    479             */
    480            public void enqueueTaskShowingWaitWindow(String title, String message, final Task task) {
    481                    final MessageWindow waitWindow = new MessageWindow(
    482                            title,
    483                            new ResourceImageReference("ch/uzh/ifi/attempto/acewiki/gui/img/wait.gif"),
    484                            message,
    485                            null,
    486                            null
    487                    );
    488                    waitWindow.setClosable(false);
    489                    showWindow(waitWindow);
    490
    491                    Thread thread = new Thread() {
    492                            public void run() {
    493                                    task.run();
    494                                    application.enqueueTask(taskQueue, new Runnable() {
    495                                            public synchronized void run() {
    496                                                    waitWindow.setVisible(false);
    497                                                    task.updateGUI();
    498                                            }
    499                                    });
    500                            }
    501                    };
    502                    thread.start();
    503            }
    504
    505            public static String getInfo(String key) {
    506                    if (properties == null) {
    507                            String f = "ch/uzh/ifi/attempto/acewiki/acewiki.properties";
    508                            InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(f);
    509                            properties = new Properties();
    510                            try {
    511                                    properties.load(in);
    512                            } catch (Exception ex) {
    513                                    ex.printStackTrace();
    514                            }
    515                    }
    516
    517                    return properties.getProperty(key);
    518            }
    519
    520    }