View Javadoc
1   /* 
2    WSMO Studio - a Semantic Web Service Editor
3    Copyright (c) 2004-2006, OntoText Lab. / SIRMA Group
4    
5    This library is free software; you can redistribute it and/or modify it under
6    the terms of the GNU Lesser General Public License as published by the Free
7    Software Foundation; either version 2.1 of the License, or (at your option)
8    any later version.
9    This library is distributed in the hope that it will be useful, but WITHOUT
10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   details.
13   You should have received a copy of the GNU Lesser General Public License along
14   with this library; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16   */
17  
18  /***
19   * <p>Title: WSMO Studio</p>
20   * <p>Description: Semantic Web Service Editor</p>
21   * <p>Copyright:  Copyright (c) 2004-2006</p>
22   * <p>Company: OntoText Lab. / SIRMA </p>
23   */
24  
25  package org.wsmostudio.ui.editors;
26  
27  import java.util.*;
28  
29  import org.eclipse.jface.action.*;
30  import org.eclipse.jface.resource.JFaceResources;
31  import org.eclipse.swt.SWT;
32  import org.eclipse.swt.custom.SashForm;
33  import org.eclipse.swt.events.*;
34  import org.eclipse.swt.layout.*;
35  import org.eclipse.swt.widgets.*;
36  import org.omwg.logicalexpression.LogicalExpression;
37  import org.omwg.ontology.*;
38  import org.wsmo.common.*;
39  import org.wsmo.wsml.ParserException;
40  import org.wsmostudio.runtime.*;
41  import org.wsmostudio.ui.GUIHelper;
42  import org.wsmostudio.ui.Utils;
43  import org.wsmostudio.ui.editors.common.NFPPanel;
44  import org.wsmostudio.ui.editors.model.*;
45  
46  /***
47   * An helper UI component which is an essential part of the AxiomEditor. Apart 
48   * from that this component is reused in the Capability Editor (where it appears
49   * is a standalone modal dialog window).
50   * This component reveals the content of an Axiom as a list of logical 
51   * expressions and a text editor area supporting expressions modification.
52   *
53   * @author not attributable
54   * @version $Revision: 1389 $ $Date: 2007-12-04 17:25:33 +0200 $
55   */
56  
57  public class AxiomEditorPanel {
58  
59      private NFPPanel nfpPanel;
60      private Text editorField;
61      private AxiomModel model;
62      private Table exprList;
63      
64      private int selectionIndex = -1;
65      private boolean contentChanged = false;
66      
67      public AxiomEditorPanel(Composite parent, AxiomModel axiomModel) {
68          this.model = axiomModel;
69          parent.setLayout(new GridLayout(1, false));
70          
71          nfpPanel = new NFPPanel(parent, model);
72          
73          Group axGr = new Group(parent, SWT.NONE);
74          axGr.setLayout(new GridLayout(1, false));
75          axGr.setLayoutData(new GridData(GridData.FILL_BOTH));        
76          axGr.setText("Logical Expressions");
77  
78          SashForm splitter = new SashForm(axGr, SWT.VERTICAL);
79          splitter.setLayoutData(new GridData(GridData.FILL_BOTH));
80          splitter.setLayout(new GridLayout(1, false));
81          createTable(splitter);
82          createContextMenu();
83          
84          Group editorGroup = new Group(splitter, SWT.NONE);
85          editorGroup.setText("Expression Editor");
86          editorGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
87          editorGroup.setLayout(new GridLayout(1, false));
88          
89          editorField = new Text(editorGroup, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
90          editorField.setLayoutData(new GridData(GridData.FILL_BOTH));
91          editorField.addTraverseListener(new TraverseListener() {
92              public void keyTraversed(TraverseEvent e) {
93                  if (e.character == SWT.ESC) { 
94  		            e.doit = false;
95  		        }
96              }
97          });
98          editorField.addModifyListener(new ModifyListener() {
99              public void modifyText(ModifyEvent e) {
100                 if (selectionIndex < 0 
101                         || selectionIndex >= exprList.getItemCount()) {
102                     return;
103                 }
104                 exprList.getItem(selectionIndex).setData(editorField.getText());
105                 exprList.getItem(selectionIndex).setText(Utils.normalizeSpaces(editorField.getText()));
106                 if (false == exprList.isFocusControl()) {
107                     contentChanged = true;
108                     model.setChanged();
109                 }
110             }
111         });
112         editorField.setEnabled(exprList.getItemCount() > 0 
113                                && exprList.getSelectionCount() > 0);
114         
115         splitter.setWeights(new int[] { 1, 2 });
116     }
117 
118     private void createTable(Composite parent) {
119         exprList = new Table(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
120         exprList.setLayoutData(new GridData(GridData.FILL_BOTH));
121         exprList.setLinesVisible(false);
122         exprList.setHeaderVisible(true);
123         
124         TableColumn column = new TableColumn(exprList, SWT.NONE);
125         column.setWidth(500);
126         
127         reloadDefinitionsInTable();
128     	exprList.addSelectionListener(new SelectionAdapter() {
129     	    public void widgetSelected(SelectionEvent e) {
130     	        if (exprList.getSelectionIndex() == selectionIndex) {
131     	            return; // no new selection
132     	        }
133     	        selectionIndex = exprList.getSelectionIndex();
134                 editorField.setText(exprList.getSelection()[0].getData().toString());
135     	        editorField.setEnabled(true);
136     	    }
137     	});
138     }
139     
140     public void reloadDefinitionsInTable() {
141         nfpPanel.update();
142         if (contentChanged == true) {
143             return;
144         }
145         String selectedDefText = null;
146         if (exprList.getItemCount() > 0) {
147             if (exprList.getSelectionIndex() != -1) {
148                 selectedDefText = exprList.getSelection()[0].getData().toString();
149             }
150             exprList.removeAll();
151         }
152         ObservableModel tmpModel = model;
153         while (tmpModel.getAdapter(TopEntity.class) == null) {
154             tmpModel = tmpModel.getMasterModel();
155         }
156         TopEntity nsHolder = (TopEntity)tmpModel.getAdapter(TopEntity.class);
157         TableItem item = null;
158         for(LogicalExpression le : model.getAxiom().listDefinitions()) {
159             item = GUIHelper.createTableItem(exprList, 
160                                          le, 
161                                          WsmoImageRegistry.LOG_EXPR_ICON);
162             item.setData(le.toString(nsHolder));
163             item.setText(Utils.normalizeSpaces(le.toString(nsHolder)));
164             if (selectedDefText != null
165                     && selectedDefText.equals(item.getData().toString())) {
166                 exprList.setSelection(exprList.getItemCount()-1);
167                 editorField.setText(selectedDefText);
168                 editorField.setEnabled(true);
169                 selectedDefText = null; // avoid selecting twice
170             }
171         }
172     }
173     
174     private void createContextMenu() {
175     	final MenuManager menuMgr = new MenuManager();
176     	menuMgr.setRemoveAllWhenShown(true);
177     	menuMgr.addMenuListener(new IMenuListener() {
178     		public void menuAboutToShow(IMenuManager mgr) {
179     			fillContextMenu(menuMgr);
180     		}
181     	});
182     	exprList.setMenu(menuMgr.createContextMenu(exprList));
183     }
184 
185     private void fillContextMenu(MenuManager menuMgr) {
186 
187     	if (false == GUIHelper.containsCursor(exprList)) {
188     		return;
189     	}
190     	menuMgr.add(new Action("Add Expression") {
191     		public void run() {
192     			handleAddExpression();
193     		}
194     	});
195     	TableItem[] sel = exprList.getSelection();
196     	if (sel != null 
197     			&& sel.length > 0 
198     			&& GUIHelper.containsCursor(sel[0].getBounds(), exprList)) {
199     		menuMgr.add(new Separator());
200     		menuMgr.add(new Action("Remove Expression") {
201     			public void run() {
202     				handleRemoveExpression();
203     			}
204     		});
205     	}
206     }
207     public void dispose() {
208         editorField.dispose();
209         nfpPanel.dispose();
210     }
211     
212     public void setFocus() {
213         exprList.setFocus();
214     }
215  
216     public void handleRemoveExpression() {
217         TableItem[] sel = exprList.getSelection();
218         LogicalExpression remExpr = (LogicalExpression)sel[0].getData(); 
219         if (remExpr != null) {
220             model.removeDefinition(remExpr);
221         }
222 
223         sel[0].dispose();
224         if (exprList.getItemCount() == 0) {
225             editorField.setEnabled(false);
226         }
227         selectionIndex = -1;
228         editorField.setText("");
229         model.setChanged();
230     }
231     
232     public void handleAddExpression() {
233         TableItem item = new TableItem(exprList, SWT.None);
234         item.setImage(JFaceResources.getImageRegistry().get(
235                 WsmoImageRegistry.LOG_EXPR_ICON));
236         item.setText(" ");
237         item.setData(" ");
238         exprList.setSelection(new TableItem[] { item });
239         selectionIndex = exprList.getItemCount()-1;
240         editorField.setText(exprList.getSelection()[0].getData().toString());
241         editorField.setEnabled(true);
242         exprList.showSelection();
243     }
244     
245     public void doUpdate() throws Exception{
246         if (contentChanged == false) {
247             return; // no need to update
248         }
249         Set<LogicalExpression> newExprs = compileExpressions();
250         Axiom axiom = model.getAxiom();
251         for (LogicalExpression le : new HashSet<LogicalExpression>(axiom.listDefinitions())) {
252             // if an expression is not changed - remove from todo list ...
253             if (newExprs.contains(le)) {
254                 newExprs.remove(le);
255             }
256             else { // ... otherwise remove from the original
257                 model.removeDefinition(le);
258             }
259         }
260         for(LogicalExpression le : newExprs) {
261             model.addDefinition(le);
262         }
263         contentChanged = false;
264     }
265     
266     private Set<LogicalExpression> compileExpressions() throws Exception {
267         TableItem[] items = exprList.getItems();
268         Set<LogicalExpression> resultSet = new HashSet<LogicalExpression>();
269         
270         String prefix = nsAsString()
271                + "ontology _\"http://temporary.764635375\""
272                + "\naxiom _\"http://temporary.764635375#dummyAx\""
273                + "\ndefinedBy\n";
274         
275         int noOfNL = 0; // the number of new lines in the prefix (needed for error location correction)
276         for(int i = 0; i < prefix.length(); i++) {
277             if (prefix.charAt(i) == '\n') {
278                 noOfNL ++;
279             }
280         }
281         
282         StringBuffer tempBuffer;
283         
284         for(int i = 0; i < items.length; i++) {
285             
286             String tempExpr = items[i].getData().toString().trim();
287             if (tempExpr.trim().length() == 0) {
288                 continue;
289             }
290             
291             tempBuffer = new StringBuffer(prefix);
292             tempBuffer.append(tempExpr);
293             if (false == tempExpr.trim().endsWith(".")) {
294                 tempBuffer.append('.');
295             }
296             tempBuffer.append('\n');
297             try {
298                 TopEntity[] onto = WSMORuntime.getRuntime().getWsmlParser().parse(tempBuffer);
299                 Axiom tempAx =  (Axiom)((Ontology)onto[0]).listAxioms().iterator().next();
300                 Set<LogicalExpression> les = new HashSet<LogicalExpression>(tempAx.listDefinitions());
301                 resultSet.addAll(les);
302                 for (LogicalExpression le : les) { // clean-up
303                     tempAx.removeDefinition(le);
304                 }
305             }
306             catch(ParserException pe) {
307                 exprList.setSelection(i);
308                 selectionIndex = i;
309                 editorField.setText(items[i].getData().toString());
310                 ParserException peNew = new ParserException("Expression cannot be processed:\n"
311                                     +pe.getMessage(), pe);
312                 pe.setErrorLine(Math.max(0, pe.getErrorLine() - noOfNL));// error line correction
313                 peNew.setErrorLine(Math.max(0, pe.getErrorLine() - noOfNL));// error line correction
314                 throw pe;
315             }
316         }
317         return resultSet;
318     }
319     
320     /***
321      * Detects the closest NS container (TopEntity) and generates a string representation
322      * of the Namespaces section.
323      * @return the namespaces section as WSML string
324      */
325     private String nsAsString() {
326         ObservableModel tmpModel = model;
327         while (tmpModel.getAdapter(TopEntity.class) == null) {
328             tmpModel = tmpModel.getMasterModel();
329             if (tmpModel == null) {
330                 return "";
331             }
332         }
333         TopEntity nsHolder = (TopEntity)tmpModel.getAdapter(TopEntity.class);
334         StringBuffer result = new StringBuffer();
335         if (nsHolder.getDefaultNamespace() == null
336                 && nsHolder.listNamespaces().size() == 0) {
337             return "";
338         }
339         result.append("namespace { ");
340         Set<Namespace> nss = nsHolder.listNamespaces();
341         if (nsHolder.getDefaultNamespace() != null) {
342             result.append("_\"")
343                   .append(nsHolder.getDefaultNamespace().getIRI().toString())
344                   .append('\"');
345             if (nss.size() > 0) {
346                 result.append(',');
347             }
348         }
349         for (Iterator<Namespace> it = nss.iterator(); it.hasNext();) {
350             Namespace ns = it.next();
351             result.append('\n')
352                   .append(ns.getPrefix())
353                   .append(" _\"")
354                   .append(ns.getIRI().toString())
355                   .append('\"');
356             if (it.hasNext()) {
357                 result.append(',');
358             }
359         }
360         return result.append("\n}\n").toString();
361     }
362 
363 }
364 
365 /*
366  * $Log$
367  * Revision 1.24  2007/07/19 13:08:30  alex_simov
368  * - rfe [1751326] Navigation through the editor tab
369  * - concepts/attributes which are from a different namespace are prefixed
370  *
371  * Revision 1.23  2007/04/17 14:35:32  alex_simov
372  * migration to the latest wsmo4j (java 5)
373  *
374  * Revision 1.22  2006/12/19 14:00:27  alex_simov
375  * ui refreshing fix
376  *
377  * Revision 1.21  2006/11/24 16:54:04  alex_simov
378  * ui improvements
379  *
380  * Revision 1.20  2006/08/01 16:07:29  alex_simov
381  * bugfix[1531709]: Context menus relied on right button mouse click instead of
382  * being registered as dedicated context menus for the corresponding UI
383  * controls
384  *
385  * Revision 1.19  2006/02/13 12:32:30  alex_simov
386  * bugfix[1426182] : namespaces not detected while parsing logical expressions
387  *
388  * Revision 1.18  2006/02/03 15:49:47  alex_simov
389  * a new LogExpr compilation as a work-around of factory's misbehaviour
390  *
391  * Revision 1.17  2006/01/09 12:51:13  alex_simov
392  * Copyright message in header updated
393  *
394  * Revision 1.16  2005/11/24 13:34:13  alex_simov
395  * logical expression field contains now wrapped text
396  * (instead of horizontal scroll bar)
397  * [bug issue 1365441]
398  *
399  * Revision 1.15  2005/11/09 16:17:39  alex_simov
400  * UIModels notification improved
401  *
402  * Revision 1.14  2005/11/02 08:57:02  alex_simov
403  * moving to a better Model-View-Contoller architecture
404  *
405  * Revision 1.13  2005/09/30 12:13:53  alex_simov
406  * unused variable 'item' assignment
407  *
408  * Revision 1.12  2005/09/21 15:09:11  alex_simov
409  * minor fixes
410  *
411  * Revision 1.11  2005/09/08 16:46:25  alex_simov
412  * Migrating to Java 1.5
413  *
414  * Revision 1.10  2005/09/02 15:33:19  alex_simov
415  * LogicalExpression import redirected
416  *
417  * Revision 1.9  2005/08/31 14:56:40  alex_simov
418  * fixes after wsmo4j changes
419  *
420  * Revision 1.8  2005/08/02 10:33:20  alex_simov
421  * minor code and/or javadoc fixes
422  *
423  * Revision 1.7  2005/07/29 15:08:02  alex_simov
424  * added javadoc: class description, footer
425  *
426  *
427  */