package org.mindswap.swoop.popup; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.ListModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.mindswap.swoop.SwoopModel; import org.mindswap.swoop.reasoner.SwoopReasoner; import org.mindswap.swoop.renderer.CellRenderer; import org.mindswap.swoop.renderer.SwoopCellRenderer; import org.mindswap.swoop.utils.ui.EntityComparator; import org.mindswap.swoop.utils.ui.OntologyComparator; import org.semanticweb.owl.model.OWLClass; import org.semanticweb.owl.model.OWLDataProperty; import org.semanticweb.owl.model.OWLDescription; import org.semanticweb.owl.model.OWLEntity; import org.semanticweb.owl.model.OWLEquivalentPropertiesAxiom; import org.semanticweb.owl.model.OWLException; import org.semanticweb.owl.model.OWLIndividual; import org.semanticweb.owl.model.OWLObjectProperty; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.OWLProperty; import org.semanticweb.owl.model.change.AddDomain; import org.semanticweb.owl.model.change.AddEntity; import org.semanticweb.owl.model.change.AddForeignEntity; import org.semanticweb.owl.model.change.AddIndividualClass; import org.semanticweb.owl.model.change.AddInverse; import org.semanticweb.owl.model.change.AddObjectPropertyRange; import org.semanticweb.owl.model.change.AddPropertyAxiom; import org.semanticweb.owl.model.change.AddSuperProperty; import org.semanticweb.owl.model.change.ChangeVisitor; import org.semanticweb.owl.model.change.OntologyChange; import org.semanticweb.owl.model.change.RemoveEntity; /** * @author Aditya Kalyanpur * This class pops up whenever the user needs to specify an OWL Property * in an Ontology Change (For example: adding a superproperty, inverse property, * hasDomain/Range attribute on a OWL Class, or a property-value for an instance) */ public class PopupAddProperty extends JFrame implements ActionListener, ListSelectionListener, KeyListener { SwoopReasoner reasoner; SwoopModel swoopModel; public List changes; String type; int typeIntCode; Font tahoma = new Font("Tahoma", Font.PLAIN, 11); Font tahomaB = new Font("Tahoma", Font.BOLD, 10); JButton applyBtn, addPropBtn, cancelBtn; JList ontList, propList; JTextField newPropFld; JComboBox propTypeBox; boolean showDataProp = true, showObjectProp = true; public PopupAddProperty(SwoopReasoner reas, String type, SwoopModel swoopModel) { new PopupAddProperty(reas, type, swoopModel, true, true); } public PopupAddProperty(SwoopReasoner reas, String type, SwoopModel swoopModel, boolean showDP, boolean showOP) { // setModal(true); this.reasoner = reas; this.type = getFullType(type); this.swoopModel = swoopModel; this.showDataProp = showDP; this.showObjectProp = showOP; changes = new ArrayList(); setupUI(); } /** * Get the full type of the property-related-change * given its abbreviated type code * @param type - code for the change type * @return */ private String getFullType(String type) { // get full string type from type code if (type.equals("EQU")) { typeIntCode = 0; return "EQUIVALENT PROPERTY"; } if (type.equals("SUB")) { typeIntCode = 1; return "SUB-PROPERTY"; } if (type.equals("SUP")) { typeIntCode = 2; return "SUPER-PROPERTY"; } if (type.equals("DOM")) { typeIntCode = 3; return "DOMAIN OF"; } if (type.equals("RAN")) { typeIntCode = 4; return "RANGE OF"; } if (type.equals("INV")) { typeIntCode = 5; return "INVERSE OF"; } if (type.startsWith("INS")) { typeIntCode = 6; return "TO INSTANCE"; } return ""; } private void setupUI() { JPanel tab1 = new JPanel(); tab1.setLayout(new BorderLayout()); ontList = new JList(); ontList.setFont(tahoma); ontList.setCellRenderer(new CellRenderer()); propList = new JList(); propList.setFont(tahoma); propList.setCellRenderer(new SwoopCellRenderer(swoopModel)); propList.addKeyListener(this); applyBtn = new JButton("Add"); applyBtn.setFont(tahoma); applyBtn.addActionListener(this); addPropBtn = new JButton("Add & Close"); addPropBtn.setFont(tahoma); addPropBtn.addActionListener(this); // special case: adding property-value pair for instance if (typeIntCode==6) { applyBtn.setVisible(false); addPropBtn.setLabel("Select Prop & Proceed"); } JLabel ontLbl = new JLabel("Select Ontology:"); ontLbl.setFont(tahoma); JLabel propLbl = new JLabel("Select Property:"); propLbl.setFont(tahoma); JPanel tab1W = new JPanel(); tab1W.setLayout(new BorderLayout()); tab1W.add(ontLbl, "North"); tab1W.add(new JScrollPane(ontList), "Center"); JPanel tab1E = new JPanel(); tab1E.setLayout(new BorderLayout()); tab1E.add(propLbl, "North"); tab1E.add(new JScrollPane(propList), "Center"); JSplitPane tab1Split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); tab1Split.setOneTouchExpandable(true); tab1Split.setLeftComponent(tab1W); tab1Split.setRightComponent(tab1E); JPanel btnPanel = new JPanel(); btnPanel.setLayout(new GridLayout(1,3)); btnPanel.add(applyBtn); if (typeIntCode==6) btnPanel.add(addPropBtn); cancelBtn = new JButton("Cancel"); cancelBtn.setFont(tahoma); cancelBtn.addActionListener(this); btnPanel.add(cancelBtn); newPropFld = new JTextField(); newPropFld.setFont(tahoma); newPropFld.addKeyListener(this); JPanel newPanel = new JPanel(); newPanel.setLayout(new BorderLayout()); JLabel newLbl = new JLabel("OR Specify New Term/URI: "); newLbl.setFont(tahoma); JPanel newLblPanel = new JPanel(); newLblPanel.setLayout(new BorderLayout()); newLblPanel.add(newLbl, "West"); propTypeBox = new JComboBox(); propTypeBox.addItem("[D]"); propTypeBox.addItem("[O]"); newLblPanel.add(propTypeBox, "Center"); newPanel.add(newLblPanel, "West"); newPanel.add(newPropFld, "Center"); JPanel tab1P = new JPanel(); tab1P.setLayout(new BorderLayout()); tab1P.add(tab1Split, "Center"); tab1P.add(newPanel, "South"); tab1.add(tab1P, "Center"); tab1.add(btnPanel, "South"); fillValues(); // add tabbed pane to frame container Container content = getContentPane(); content.setLayout(new BorderLayout()); JLabel typeLbl = new JLabel("[ ADDING "+type+".. ]"); typeLbl.setFont(tahoma); content.add(typeLbl, "North"); content.add(tab1, "Center"); setSize(450,300); setTitle("Specify Property"); setResizable(true); } /** * Fill the ontology combo-box with all the ontologies present in the SwoopModel * Choosing a different ontology here causes a change in the property list * i.e. fillPropBox() */ private void fillValues() { Set sortedOntSet = new TreeSet(OntologyComparator.INSTANCE); sortedOntSet.addAll(swoopModel.getOntologyURIs()); ontList.setFont(new Font(swoopModel.getFontFace(), Font.PLAIN, 11)); ontList.setListData(sortedOntSet.toArray()); // turn on listeners ontList.addListSelectionListener(this); // select current displayed ontology try { URI currOntURI = swoopModel.getSelectedOntology().getURI(); ontList.setSelectedValue(currOntURI, true); } catch (Exception ex) { ex.printStackTrace(); } } /** * Method called when the user presses the add/apply property change btn * It gets the property selected and passes it to makeChange(..) */ private void addPropertyChange() { try { OWLProperty prop = null; if ((newPropFld.getText()!=null) && (!newPropFld.getText().trim().equals(""))) { // user-specified property name/uri String propStr = newPropFld.getText(); propStr = propStr.replaceAll(" ","_"); if (!isURL(propStr)) propStr = swoopModel.getSelectedOntology().getLogicalURI()+"#"+propStr; URI propURI = new URI(propStr); // **create new property if (propTypeBox.getSelectedIndex()==0) prop = swoopModel.getSelectedOntology().getOWLDataFactory().getOWLDataProperty(propURI); else prop = swoopModel.getSelectedOntology().getOWLDataFactory().getOWLObjectProperty(propURI); makeChange(prop); } else { // get existing property Object[] props = (Object[]) propList.getSelectedValues(); for (int i=0; i<props.length; i++) { prop = (OWLProperty) props[i]; makeChange(prop); } } swoopModel.addUncommittedChanges(changes); changes = new ArrayList(); // reset it after changes have been added } catch (Exception ex) { ex.printStackTrace(); } } /** * Creates the Property related Ontology Change based on the * currently selected ontology, entity and OWL Property passed to it * @param prop - object (OWL Property) of the ontology change */ private void makeChange(OWLProperty prop) { OntologyChange change = null; OWLOntology dispOnt = swoopModel.getSelectedOntology(); switch (typeIntCode) { case 0: // add equivalent property OWLProperty dispProp = (OWLProperty) swoopModel.getSelectedEntity(); Set equSet = new HashSet(); equSet.add(dispProp); equSet.add(prop); try { OWLEquivalentPropertiesAxiom propAxiom = dispOnt.getOWLDataFactory().getOWLEquivalentPropertiesAxiom(equSet); change = new AddPropertyAxiom(dispOnt, propAxiom, null); changes.add(change); } catch (OWLException e) { e.printStackTrace(); } break; case 2: // add sub-property OWLProperty dispProp2 = (OWLProperty) swoopModel.getSelectedEntity(); change = new AddSuperProperty(dispOnt, prop, dispProp2, null); changes.add(change); break; case 1: // add super-property OWLProperty dispProp3 = (OWLProperty) swoopModel.getSelectedEntity(); change = new AddSuperProperty(dispOnt, dispProp3, prop, null); changes.add(change); break; case 3: // add domain OWLClass cla = (OWLClass) swoopModel.getSelectedEntity(); change = new AddDomain(dispOnt, prop, cla, null); changes.add(change); break; case 4: // add range OWLClass cla2 = (OWLClass) swoopModel.getSelectedEntity(); if (prop instanceof OWLDataProperty) { // cannot be! JOptionPane.showMessageDialog(this, "OWL Datatype Property cannot have a Class Range", "Range Definition Error", JOptionPane.ERROR_MESSAGE); } else { change = new AddObjectPropertyRange(dispOnt, (OWLObjectProperty) prop, cla2, null); changes.add(change); } break; case 5: // add inverse OWLObjectProperty propSubj = (OWLObjectProperty) swoopModel.getSelectedEntity(); if (prop instanceof OWLDataProperty) { // cannot be! JOptionPane.showMessageDialog(this, "Inverse cannot be an OWL Datatype Property", "Inverse Definition Error", JOptionPane.ERROR_MESSAGE); } else { //****************************************************************** //changed for Econnections //****************************************************************** if(!propSubj.isLink()){ change = new AddInverse(dispOnt, propSubj, (OWLObjectProperty) prop, null); changes.add(change); } else{ try{ OntologyChange oc = new AddForeignEntity(dispOnt, prop, dispOnt.getURI() , null); changes.add(oc); } catch (OWLException e) {} change = new AddInverse(dispOnt, propSubj, (OWLObjectProperty) prop, null); changes.add(change); OntologyChange oc2 = new RemoveEntity(dispOnt, prop, null); changes.add(oc2); } } //} break; case 6: // add property to instance // prompt user for adding value for property if(prop instanceof OWLObjectProperty){ if(((OWLObjectProperty)prop).isLink()){ URI u = ((OWLObjectProperty)prop).getLinkTarget(); OWLOntology foreignOnto = swoopModel.getOntology(u); try { swoopModel.getReasoner().setOntology(foreignOnto); swoopModel.setSelectedOntology(foreignOnto); } catch (OWLException e) { e.printStackTrace(); } } } PopupAddValue popup = new PopupAddValue(reasoner, swoopModel, prop); popup.setLocation(200, 200); popup.show(); break; } } private boolean isURL(String str) { try { URL url = new URL(str); return true; } catch (Exception ex) {} return false; } public void actionPerformed(ActionEvent e) { if (e.getSource()==addPropBtn) { addPropertyChange(); dispose(); } if (e.getSource()==applyBtn) { addPropertyChange(); } if (e.getSource()==cancelBtn) { dispose(); } } /** * Fill the property box with all the OWL properties (data/object) * defined in the ontology selected by the user in the corresponding ont-combo box */ private void fillPropBox() { try { // fill props in PropBox based on selected ontology URI ontURI = (URI) ontList.getSelectedValue(); OWLOntology currOnt = swoopModel.getOntology(ontURI); Set propSet = new TreeSet(EntityComparator.INSTANCE); if (showDataProp) propSet.addAll(currOnt.getDataProperties()); if (showObjectProp) propSet.addAll(currOnt.getObjectProperties()); propList.setFont(new Font(swoopModel.getFontFace(), Font.PLAIN, 11)); propList.setListData(propSet.toArray()); } catch (Exception ex) { ex.printStackTrace(); } } public void valueChanged(ListSelectionEvent e) { if (e.getSource()==ontList) { fillPropBox(); } } public void keyTyped(KeyEvent arg0) { } public void keyPressed(KeyEvent e) { if (e.getSource()==propList) { String alpha = Character.toString(e.getKeyChar()).toLowerCase(); PopupCommon.listSelector(swoopModel, (JList) e.getSource(), alpha); } if (e.getSource()==newPropFld) { if (e.getKeyCode()==10) { applyBtn.doClick(); } } } public void keyReleased(KeyEvent arg0) { } }