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.Column;
021    import nextapp.echo.app.Extent;
022    import nextapp.echo.app.Font;
023    import nextapp.echo.app.Insets;
024    import nextapp.echo.app.Row;
025    import nextapp.echo.app.event.ActionEvent;
026    import nextapp.echo.app.event.ActionListener;
027    import ch.uzh.ifi.attempto.acewiki.Task;
028    import ch.uzh.ifi.attempto.acewiki.core.CachingReasoner;
029    import ch.uzh.ifi.attempto.acewiki.core.Concept;
030    import ch.uzh.ifi.attempto.acewiki.core.LanguageUtils;
031    import ch.uzh.ifi.attempto.acewiki.core.OntologyElement;
032    import ch.uzh.ifi.attempto.acewiki.core.Sentence;
033    import ch.uzh.ifi.attempto.acewiki.core.StatementFactory;
034    import ch.uzh.ifi.attempto.echocomp.SolidLabel;
035    import ch.uzh.ifi.attempto.echocomp.VSpace;
036    
037    /**
038     * This class represents a page that shows the super-concepts and sub-concepts for a given concept.
039     * Such super- and sub-concept relations are called "hierarchy" in AceWiki.
040     * 
041     * @author Tobias Kuhn
042     */
043    public class HierarchyPage extends WikiPage implements ActionListener {
044    
045            private static final long serialVersionUID = 3126817139010810197L;
046    
047            private static final int pageSize = 25;
048            
049            private ConceptPage page;
050            private RecalcIcon upRecalcIcon = new RecalcIcon("This list is being updated.");
051            private RecalcIcon downRecalcIcon = new RecalcIcon("This list is being updated.");
052            private Title title;
053    
054            private Column upHierarchyColumn = new Column();
055            private Column downHierarchyColumn = new Column();
056            private int upChosenPage = 0;
057            private int downChosenPage = 0;
058            
059            /**
060             * Creates a new hierarchy page.
061             * 
062             * @param page The main page that contains the article.
063             */
064            public HierarchyPage(ConceptPage page) {
065                    super(page.getWiki());
066                    this.page = page;
067                    
068                    addTab("Article", this);
069                    addTab("References", this);
070                    addTab("Individuals", this);
071                    addSelectedTab("Hierarchy");
072                    
073                    OntologyElement oe = page.getOntologyElement();
074                    title = new Title(getHeading(oe), "- Hierarchy", oe.getType(), this);
075                    add(title);
076                    addHorizontalLine();
077                    add(new VSpace(12));
078                    
079                    upRecalcIcon.setVisible(false);
080                    addHeadline("Upward", upRecalcIcon);
081                    add(new VSpace(5));
082                    add(upHierarchyColumn);
083                    
084                    downRecalcIcon.setVisible(false);
085                    addHeadline("Downward", downRecalcIcon);
086                    add(new VSpace(5));
087                    add(downHierarchyColumn);
088            }
089            
090            protected void doUpdate() {
091                    title.setText(getHeading(page.getOntologyElement()));
092                    upHierarchyColumn.removeAll();
093                    downHierarchyColumn.removeAll();
094                    
095                    Concept c = (Concept) page.getOntologyElement();
096                    CachingReasoner cr = getWiki().getOntology().getReasoner();
097                    
098                    if (cr.areCachedSuperConceptsUpToDate(c)) {
099                            upHierarchyColumn.add(new HierarchyComponent(true, true));
100                    } else {
101                            upRecalcIcon.setVisible(true);
102                            upHierarchyColumn.add(new HierarchyComponent(true, true));
103                            page.getWiki().enqueueWeakAsyncTask(new Task() {
104                                    
105                                    private HierarchyComponent delayedComp;
106                                    
107                                    public void run() {
108                                            delayedComp = new HierarchyComponent(true, false);
109                                    }
110                                    
111                                    public void updateGUI() {
112                                            upHierarchyColumn.removeAll();
113                                            upHierarchyColumn.add(delayedComp);
114                                            upRecalcIcon.setVisible(false);
115                                    }
116                                    
117                            });
118                    }
119    
120                    if (cr.areCachedSuperConceptsUpToDate(c)) {
121                            downHierarchyColumn.add(new HierarchyComponent(false, true));
122                    } else {
123                            downRecalcIcon.setVisible(true);
124                            downHierarchyColumn.add(new HierarchyComponent(false, true));
125                            page.getWiki().enqueueWeakAsyncTask(new Task() {
126                                    
127                                    private HierarchyComponent delayedComp;
128                                    
129                                    public void run() {
130                                            delayedComp = new HierarchyComponent(false, false);
131                                    }
132                                    
133                                    public void updateGUI() {
134                                            downHierarchyColumn.removeAll();
135                                            downHierarchyColumn.add(delayedComp);
136                                            downRecalcIcon.setVisible(false);
137                                    }
138                                    
139                            });
140                    }
141            }
142    
143            public void actionPerformed(ActionEvent e) {
144                    if ("Article".equals(e.getActionCommand())) {
145                            log("page", "pressed: article");
146                            getWiki().showPage(page);
147                    } else if ("References".equals(e.getActionCommand())) {
148                            log("page", "pressed: references");
149                            getWiki().showPage(new ReferencesPage(page));
150                    } else if ("Individuals".equals(e.getActionCommand())) {
151                            log("page", "pressed: individuals");
152                            getWiki().showPage(new IndividualsPage(page));
153                    } else if (e.getSource() == title) {
154                            getWiki().showEditorWindow(page.getOntologyElement());
155                    }
156            }
157    
158            public boolean equals(Object obj) {
159                    if (obj instanceof HierarchyPage) {
160                            return page.equals(((HierarchyPage) obj).page);
161                    }
162                    return false;
163            }
164            
165            public boolean isExpired() {
166                    return page.isExpired();
167            }
168            
169            public String toString() {
170                    return "-IND- " + page.getOntologyElement().getWord();
171            }
172    
173            private class HierarchyComponent extends Column implements ActionListener {
174                    
175                    private static final long serialVersionUID = 6461817187189387351L;
176                    
177                    private boolean up;
178                    private Column column = new Column();
179                    private IndexBar indexBar;
180                    private List<Sentence> sentences;
181                    
182                    
183                    public HierarchyComponent(boolean up, boolean cached) {
184                            this.up = up;
185                            indexBar = new IndexBar("Page:", 0, this);
186                            add(indexBar);
187                            column.setInsets(new Insets(10, 2, 5, 10));
188                            column.setCellSpacing(new Extent(2));
189                            add(column);
190                            
191                            Concept concept = (Concept) page.getOntologyElement();
192                            CachingReasoner cr = getWiki().getOntology().getReasoner();
193                            List<Concept> concepts;
194                            
195                            if (up) {
196                                    if (cached) {
197                                            concepts = cr.getCachedSuperConcepts(concept);
198                                    } else {
199                                            concepts = cr.getSuperConcepts(concept);
200                                    }
201                            } else {
202                                    if (cached) {
203                                            concepts = cr.getCachedSubConcepts(concept);
204                                    } else {
205                                            concepts = cr.getSubConcepts(concept);
206                                    }
207                            }
208                            if (concepts != null) {
209                                    sentences = new ArrayList<Sentence>();
210                                    LanguageUtils.sortOntologyElements(concepts);
211                                    for (Concept c : concepts) {
212                                            StatementFactory sf = getWiki().getOntology().getStatementFactory();
213                                            if (up) {
214                                                    sentences.add(sf.createHierarchySentence(concept, c));
215                                            } else {
216                                                    sentences.add(sf.createHierarchySentence(c, concept));
217                                            }
218                                    }
219                            }
220                            
221                            updatePage();
222                    }
223                    
224                    private void updatePage() {
225                            column.removeAll();
226                            
227                            String t;
228                            int chosenPage;
229                            if (up) {
230                                    t = "upward";
231                                    chosenPage = upChosenPage;
232                            } else {
233                                    t = "downward";
234                                    chosenPage = downChosenPage;
235                            }
236                            
237                            if (sentences == null) {
238                                    column.add(new SolidLabel("...", Font.ITALIC, 10));
239                                    indexBar.setVisible(false);
240                            } else {
241                                    if (sentences.size() == 0) {
242                                            indexBar.setVisible(false);
243                                            column.add(new SolidLabel("(" + t + " hierarchy is empty)", Font.ITALIC, 10));
244                                    } else {
245                                            int i = ((sentences.size()-1) / pageSize) + 1;
246                                            if (chosenPage > i) chosenPage = 0;
247                                            indexBar.setNumbers(i);
248                                            indexBar.setActiveButton(chosenPage);
249                                    }
250                                    
251                                    indexBar.setVisible(sentences.size() > pageSize);
252                                    
253                                    int max = sentences.size();
254                                    if (max > (chosenPage + 1) * pageSize) max = (chosenPage + 1) * pageSize;
255                                    for (int i = chosenPage * pageSize; i < max; i++) {
256                                            Row r = new Row();
257                                            r.add(new SentenceComponent(sentences.get(i), HierarchyPage.this));
258                                            column.add(r);
259                                    }
260                            }
261                    }
262                    
263                    public void actionPerformed(ActionEvent e) {
264                            if (e.getSource() == indexBar) {
265                                    if (up) {
266                                            upChosenPage = Integer.parseInt(e.getActionCommand()) - 1;
267                                            log("page", "pressed: page up:" + (upChosenPage+1));
268                                            updatePage();
269                                    } else {
270                                            downChosenPage = Integer.parseInt(e.getActionCommand()) - 1;
271                                            log("page", "pressed: page down:" + (downChosenPage+1));
272                                            updatePage();
273                                    }
274                            }
275                    }
276                    
277            }
278    
279    }