/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.components.widget;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.openflexo.antar.binding.AbstractBinding.BindingEvaluationContext;
import org.openflexo.antar.binding.Bindable;
import org.openflexo.antar.binding.BindingDefinition.BindingDefinitionType;
import org.openflexo.antar.binding.BindingFactory;
import org.openflexo.antar.binding.BindingModel;
import org.openflexo.antar.binding.BindingVariable;
import org.openflexo.antar.binding.DataBinding;
import org.openflexo.foundation.ontology.AbstractOntologyObject;
import org.openflexo.foundation.ontology.FlexoOntology;
import org.openflexo.foundation.ontology.OntologyClass;
import org.openflexo.foundation.ontology.OntologyIndividual;
import org.openflexo.foundation.ontology.OntologyUtils;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.viewpoint.binding.EditionPatternBindingFactory;
import org.openflexo.foundation.viewpoint.binding.OntologyObjectPathElement.OntologyIndividualPathElement;
import org.openflexo.toolbox.FileResource;
import org.openflexo.toolbox.StringUtils;
/**
* Widget allowing to select an OntologyIndividual<br>
*
* This widget provides many configuration options:
* <ul>
* <li>context: required, defines ontology context</li>
* <li>strictMode: required, default is false, when true, indicates that properties are retrieved from declared context ontology only</li>
* <li>hierarchicalMode: required, default is true, defines if properties are stored relative to a storage class, defined either as the
* domain class, or the top-level class where this property is used as a restriction</li>
* <li>type: when set, defines type class of searched individuals</li>
* </ul>
*
* Additionnaly, this widget provides a way to define custom renderers for different types of individuals. See
* {@link #setRepresentationForIndividualOfClass(String, String, OntologyClass)}
*
* @author sguerin
*
*/
@SuppressWarnings("serial")
public class FIBIndividualSelector extends FIBModelObjectSelector<OntologyIndividual> implements Bindable {
static final Logger logger = Logger.getLogger(FIBIndividualSelector.class.getPackage().getName());
public static final FileResource FIB_FILE = new FileResource("Fib/FIBIndividualSelector.fib");
private FlexoOntology context;
private OntologyClass type;
private boolean hierarchicalMode = true;
private boolean strictMode = false;
private boolean showOWLAndRDFConcepts = false;
private OntologyBrowserModel model = null;
private BindingModel bindingModel;
private String defaultRenderer = null;
private static EditionPatternBindingFactory EDITION_PATTERN_BINDING_FACTORY = new EditionPatternBindingFactory();
private HashMap<OntologyClass, DataBinding<String>> renderers;
public FIBIndividualSelector(OntologyIndividual editedObject) {
super(editedObject);
bindingModel = new BindingModel();
renderers = new HashMap<OntologyClass, DataBinding<String>>();
}
@Override
public BindingFactory getBindingFactory() {
return EDITION_PATTERN_BINDING_FACTORY;
}
@Override
public BindingModel getBindingModel() {
return bindingModel;
}
@Override
public void delete() {
super.delete();
context = null;
}
@Override
public File getFIBFile() {
return FIB_FILE;
}
@Override
public Class<OntologyIndividual> getRepresentedType() {
return OntologyIndividual.class;
}
public String getRenderer() {
if (getType() != null) {
if (renderers.get(getType()) != null) {
return renderers.get(getType()).toString();
}
}
return defaultRenderer;
}
@CustomComponentParameter(name = "renderer", type = CustomComponentParameter.Type.OPTIONAL)
public void setRenderer(String renderer) {
defaultRenderer = renderer;
if (getType() != null) {
setRepresentationForIndividualOfClass("individual", renderer, getType());
}
}
public String renderObject(AbstractOntologyObject object) {
if (object instanceof OntologyIndividual) {
return renderedString((OntologyIndividual) object);
}
return object.getName();
}
/**
* Provides custom renderer for individuals of a given ontology class.<br>
* For example call: <code>
* selector.setRepresentationForIndividualOfClass("personne", "personne.nom+' '+personne.prenom",
* o.getClass("http://www.openflexo.org/test/Family.owl#Personne"));
* </code>
*
* @param variableName
* @param expression
* @param type
*/
public void setRepresentationForIndividualOfClass(String variableName, String expression, OntologyClass type) {
if (renderers.get(type) == null || !renderers.get(type).toString().equals(expression)) {
if (renderers.get(type) != null) {
logger.info("Was " + renderers.get(type).toString() + " now " + expression);
}
OntologyIndividualPathElement newPathElement = new OntologyIndividualPathElement(variableName, type, null,
type.getFlexoOntology());
if (bindingModel.bindingVariableNamed(variableName) != null) {
logger.warning("Duplicated binding variable " + variableName);
bindingModel.removeFromBindingVariables(bindingModel.bindingVariableNamed(variableName));
}
bindingModel.addToBindingVariables(newPathElement);
DataBinding<String> db = new DataBinding<String>(expression, this, String.class, BindingDefinitionType.GET);
renderers.put(type, db);
}
}
protected DataBinding<String> getRenderer(OntologyIndividual individual) {
if (individual == null) {
return null;
}
// If default renderer was not already applied to default type, then do it now
if (StringUtils.isNotEmpty(defaultRenderer) && getType() != null && renderers.get(getType()) == null) {
setRepresentationForIndividualOfClass("individual", defaultRenderer, getType());
}
if (renderers == null) {
return null;
}
List<OntologyClass> matchingClasses = new ArrayList<OntologyClass>();
for (OntologyClass cl : renderers.keySet()) {
if (cl.isSuperConceptOf(individual)) {
matchingClasses.add(cl);
}
}
OntologyClass mostSpecializedClass = OntologyUtils.getMostSpecializedClass(matchingClasses);
return renderers.get(mostSpecializedClass);
}
public class BindingEvaluator implements BindingEvaluationContext {
public BindingEvaluator(OntologyIndividual individual) {
}
@Override
public Object getValue(BindingVariable variable) {
// TODO Auto-generated method stub
return null;
}
}
@Override
public String renderedString(final OntologyIndividual editedObject) {
DataBinding<String> binding = getRenderer(editedObject);
if (binding == null) {
return null;
}
if (editedObject != null) {
try {
String returned = binding.getBindingValue(new BindingEvaluationContext() {
@Override
public Object getValue(BindingVariable variable) {
return editedObject;
}
});
return returned;
} catch (Exception e) {
return editedObject.getName();
}
}
return "";
}
public String getContextOntologyURI() {
if (getContext() != null) {
return getContext().getURI();
}
return null;
}
@CustomComponentParameter(name = "contextOntologyURI", type = CustomComponentParameter.Type.MANDATORY)
public void setContextOntologyURI(String ontologyURI) {
// logger.info("Sets ontology with " + ontologyURI);
if (getProject() != null) {
FlexoOntology context = getProject().getResourceCenter().getOpenFlexoResourceCenter().retrieveBaseOntologyLibrary()
.getOntology(ontologyURI);
if (context != null) {
setContext(context);
}
}
}
public FlexoOntology getContext() {
return context;
}
@CustomComponentParameter(name = "context", type = CustomComponentParameter.Type.MANDATORY)
public void setContext(FlexoOntology context) {
this.context = context;
update();
setRepresentationForIndividualOfClass("defaultIndividual", "defaultIndividual.uriName", context.getThingConcept());
}
public OntologyClass getType() {
return type;
}
@CustomComponentParameter(name = "type", type = CustomComponentParameter.Type.OPTIONAL)
public void setType(OntologyClass rootClass) {
this.type = rootClass;
update();
// setRepresentationForIndividualOfClass("defaultType", "defaultType.uriName", rootClass);
}
public String getTypeURI() {
if (getType() != null) {
return getType().getURI();
}
return null;
}
@CustomComponentParameter(name = "typeURI", type = CustomComponentParameter.Type.MANDATORY)
public void setTypeURI(String aClassURI) {
// logger.info("Sets typeClassURI with " + aClassURI + " context=" + getContext());
if (getContext() != null) {
OntologyClass typeClass = getContext().getClass(aClassURI);
if (typeClass != null) {
setType(typeClass);
}
}
}
public boolean getHierarchicalMode() {
return hierarchicalMode;
}
@CustomComponentParameter(name = "hierarchicalMode", type = CustomComponentParameter.Type.OPTIONAL)
public void setHierarchicalMode(boolean hierarchicalMode) {
this.hierarchicalMode = hierarchicalMode;
update();
}
public boolean getStrictMode() {
return strictMode;
}
@CustomComponentParameter(name = "strictMode", type = CustomComponentParameter.Type.OPTIONAL)
public void setStrictMode(boolean strictMode) {
this.strictMode = strictMode;
update();
}
public boolean getShowOWLAndRDFConcepts() {
return showOWLAndRDFConcepts;
}
@CustomComponentParameter(name = "showOWLAndRDFConcepts", type = CustomComponentParameter.Type.OPTIONAL)
public void setShowOWLAndRDFConcepts(boolean showOWLAndRDFConcepts) {
this.showOWLAndRDFConcepts = showOWLAndRDFConcepts;
update();
}
public OntologyBrowserModel getModel() {
if (model == null) {
model = new OntologyBrowserModel(getContext()) {
@Override
public void recomputeStructure() {
super.recomputeStructure();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
getPropertyChangeSupport().firePropertyChange("model", null, getModel());
}
});
}
};
model.setStrictMode(getStrictMode());
model.setHierarchicalMode(getHierarchicalMode());
model.setDisplayPropertiesInClasses(false);
model.setRootClass(getType());
model.setShowClasses(false);
model.setShowIndividuals(true);
model.setShowObjectProperties(false);
model.setShowDataProperties(false);
model.setShowAnnotationProperties(false);
model.setShowOWLAndRDFConcepts(showOWLAndRDFConcepts);
model.recomputeStructure();
}
return model;
}
public void update() {
if (model != null) {
model.delete();
model = null;
// setEditedObject(this);
fireEditedObjectChanged();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
getPropertyChangeSupport().firePropertyChange("model", null, getModel());
}
});
}
}
@Override
public void setProject(FlexoProject project) {
super.setProject(project);
if (project != null) {
setContext(project.getProjectOntology());
}
}
// Please uncomment this for a live test
// Never commit this uncommented since it will not compile on continuous build
// To have icon, you need to choose "Test interface" in the editor (otherwise, flexo controller is not insanciated in EDIT mode)
/*public static void main(String[] args) {
FIBAbstractEditor editor = new FIBAbstractEditor() {
@Override
public Object[] getData() {
FlexoResourceCenter testResourceCenter = LocalResourceCenterImplementation
.instanciateTestLocalResourceCenterImplementation(new FileResource("TestResourceCenter"));
FIBIndividualSelector selector = new FIBIndividualSelector(null);
// selector.setContext(resourceCenter.retrieveBaseOntologyLibrary().getFlexoConceptOntology());
FlexoOntology o = testResourceCenter.retrieveBaseOntologyLibrary().getOntology(
// "http://www.thalesgroup.com/ontologies/sepel-ng/MappingSpecifications.owl");
// "http://www.openflexo.org/test/TestInstances.owl");
"http://www.openflexo.org/test/Family.owl");
o.loadWhenUnloaded();
selector.setContext(o);
selector.setHierarchicalMode(true); // false
selector.setStrictMode(true);
selector.setRepresentationForIndividualOfClass("personne", "personne.nom+' '+personne.prenom",
o.getClass("http://www.openflexo.org/test/Family.owl#Personne"));
selector.setRepresentationForIndividualOfClass("sexe", "'SEXE:'+sexe.uriName",
o.getClass("http://www.openflexo.org/test/Family.owl#Sexe"));
return makeArray(selector);
}
@Override
public File getFIBFile() {
return FIB_FILE;
}
@Override
public FIBController makeNewController(FIBComponent component) {
return new FlexoFIBController(component);
}
};
editor.launch();
}*/
}