/*
* (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.foundation.viewpoint;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.filter.ElementFilter;
import org.jdom2.input.SAXBuilder;
import org.openflexo.antar.binding.BindingFactory;
import org.openflexo.antar.binding.BindingModel;
import org.openflexo.fge.DataBinding;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.ontology.FlexoOntology;
import org.openflexo.foundation.ontology.ImportedOWLOntology;
import org.openflexo.foundation.ontology.ImportedOntology;
import org.openflexo.foundation.ontology.dm.OEDataModification;
import org.openflexo.foundation.ontology.owl.OWLOntology;
import org.openflexo.foundation.viewpoint.binding.EditionPatternBindingFactory;
import org.openflexo.foundation.viewpoint.binding.EditionPatternPathElement;
import org.openflexo.foundation.viewpoint.dm.CalcDrawingShemaInserted;
import org.openflexo.foundation.viewpoint.dm.CalcDrawingShemaRemoved;
import org.openflexo.foundation.viewpoint.dm.CalcPaletteInserted;
import org.openflexo.foundation.viewpoint.dm.CalcPaletteRemoved;
import org.openflexo.toolbox.FileUtils;
import org.openflexo.toolbox.JavaUtils;
import org.openflexo.toolbox.RelativePathFileConverter;
import org.openflexo.toolbox.StringUtils;
import org.openflexo.xmlcode.AccessorInvocationException;
import org.openflexo.xmlcode.InvalidModelException;
import org.openflexo.xmlcode.InvalidObjectSpecificationException;
import org.openflexo.xmlcode.InvalidXMLDataException;
import org.openflexo.xmlcode.StringEncoder;
import org.openflexo.xmlcode.XMLDecoder;
import org.openflexo.xmlcode.XMLMapping;
public class ViewPoint extends ViewPointObject {
private static final String URI_XML_ATTRIBUTE_NAME = "uri";
private static final String VIEW_POINT_ELEMENT_XML_TAG = "ViewPoint";
private static final String VIEWPOINT_DIRECTORY_EXTENSION = ".viewpoint";
private static final Logger logger = Logger.getLogger(ViewPoint.class.getPackage().getName());
// TODO: We must find a better solution
static {
StringEncoder.getDefaultInstance()._addConverter(DataBinding.CONVERTER);
}
private String name;
private String viewPointURI;
private String description;
private String version;
private Vector<EditionPattern> editionPatterns;
private LocalizedDictionary localizedDictionary;
private ImportedOntology viewpointOntology;
private Vector<ViewPointPalette> palettes;
private Vector<ExampleDrawingShema> shemas;
private File viewPointDirectory;
private File owlFile;
private File xmlFile;
private ViewPointLibrary _library;
private boolean isLoaded = false;
private boolean isLoading = false;
private RelativePathFileConverter relativePathFileConverter;
public static File getViewPointFile(File viewPointDirectory) {
return new File(viewPointDirectory, getViewPointBaseName(viewPointDirectory) + ".xml");
}
public static String getViewPointBaseName(File viewPointDirectory) {
return viewPointDirectory.getName().substring(0, viewPointDirectory.getName().length() - VIEWPOINT_DIRECTORY_EXTENSION.length());
}
public static String getURI(File viewpointDirectory) throws JDOMException, IOException {
File viewPointFile = getViewPointFile(viewpointDirectory);
Document document = readXMLFile(viewPointFile);
Element element = getElement(document, VIEW_POINT_ELEMENT_XML_TAG);
return element.getAttributeValue(URI_XML_ATTRIBUTE_NAME);
}
public static ViewPoint openViewPoint(File viewPointDirectory, ViewPointLibrary library, ViewPointFolder folder) {
String baseName = getViewPointBaseName(viewPointDirectory);
File xmlFile = getViewPointFile(viewPointDirectory);
if (xmlFile.exists()) {
ImportedOntology viewPointOntology = readViewpointOntology(xmlFile, library);
FileInputStream inputStream = null;
try {
ViewPointBuilder builder = new ViewPointBuilder(viewPointOntology);
RelativePathFileConverter relativePathFileConverter = new RelativePathFileConverter(viewPointDirectory);
inputStream = new FileInputStream(xmlFile);
if (logger.isLoggable(Level.FINE)) {
logger.fine("Reading file " + xmlFile.getAbsolutePath());
}
ViewPoint returned = (ViewPoint) XMLDecoder.decodeObjectWithMapping(inputStream, library.get_VIEW_POINT_MODEL(), builder,
new StringEncoder(StringEncoder.getDefaultInstance(), relativePathFileConverter));
if (logger.isLoggable(Level.FINE)) {
logger.fine("DONE reading file " + xmlFile.getAbsolutePath());
}
returned.init(baseName, viewPointDirectory, xmlFile, library, viewPointOntology, folder);
return returned;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidXMLDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidObjectSpecificationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AccessorInvocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidModelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
} else {
logger.severe("Not found: " + xmlFile);
// TODO: implement a search here (find the good XML file)
return null;
}
}
public static ViewPoint newViewPoint(String baseName, String viewpointURI, File owlFile, File viewpointDir, ViewPointLibrary library,
ViewPointFolder folder) {
File xmlFile = new File(viewpointDir, baseName + ".xml");
ViewPoint viewpoint = new ViewPoint();
viewpoint.owlFile = owlFile;
viewpoint._setViewPointURI(viewpointURI);
ImportedOntology viewPointOntology = loadViewpointOntology(viewpointURI, owlFile, library);
viewpoint.init(baseName, viewpointDir, xmlFile, library, viewPointOntology, folder);
viewpoint.save();
return viewpoint;
}
private static ImportedOntology readViewpointOntology(File viewPointFile, ViewPointLibrary library) {
if (viewPointFile == null || !viewPointFile.exists() || viewPointFile.length() == 0) {
if (viewPointFile.length() == 0) {
viewPointFile.delete();
}
return null;
}
File owlFile = null;
String viewPointURI = null;
Document document;
try {
logger.fine("Try to find ontology for viewpoint" + viewPointFile);
document = readXMLFile(viewPointFile);
Element root = getElement(document, VIEW_POINT_ELEMENT_XML_TAG);
if (root != null) {
String owlFileAttribute = root.getAttributeValue("owlFile");
if (owlFileAttribute != null) {
owlFile = new File(viewPointFile.getParent(), owlFileAttribute);
viewPointURI = root.getAttributeValue(URI_XML_ATTRIBUTE_NAME);
}
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (owlFile != null && owlFile.exists()) {
return loadViewpointOntology(viewPointURI, owlFile, library);
}
return null;
}
private static ImportedOntology loadViewpointOntology(String viewPointURI, File owlFile, ViewPointLibrary library) {
ImportedOntology viewpointOntology = null;
if (owlFile.exists()) {
logger.fine("Found " + owlFile);
String ontologyURI = OWLOntology.findOntologyURI(owlFile);
if (StringUtils.isEmpty(ontologyURI)) {
ontologyURI = viewPointURI;
}
viewpointOntology = library.getOntologyLibrary().importOntology(ontologyURI, owlFile);
viewpointOntology.setIsReadOnly(false);
}
return viewpointOntology;
}
private static Document readXMLFile(File f) throws JDOMException, IOException {
FileInputStream fio = new FileInputStream(f);
SAXBuilder parser = new SAXBuilder();
Document reply = parser.build(fio);
return reply;
}
private static Element getElement(Document document, String name) {
Iterator<Element> it = document.getDescendants(new ElementFilter(name));
if (it.hasNext()) {
return it.next();
} else {
return null;
}
}
private static Element getElement(Element from, String name) {
Iterator<Element> it = from.getDescendants(new ElementFilter(name));
if (it.hasNext()) {
return it.next();
} else {
return null;
}
}
public static class ViewPointBuilder {
private ViewPoint viewPoint;
private ImportedOntology viewPointOntology;
public ViewPointBuilder(ViewPoint viewPoint) {
this.viewPoint = viewPoint;
if (viewPoint != null) {
this.viewPointOntology = (ImportedOntology) viewPoint.getViewpointOntology();
}
}
public ViewPointBuilder(ImportedOntology viewPointOntology) {
this.viewPointOntology = viewPointOntology;
// viewPointOntology.loadWhenUnloaded();
}
public ImportedOntology getViewPointOntology() {
return viewPointOntology;
}
public ViewPoint getViewPoint() {
return viewPoint;
}
public void setViewPoint(ViewPoint viewPoint) {
this.viewPoint = viewPoint;
}
}
// Used during deserialization, do not use it
public ViewPoint(ViewPointBuilder builder) {
super(builder);
if (builder != null) {
builder.setViewPoint(this);
}
editionPatterns = new Vector<EditionPattern>();
}
// Used during deserialization, do not use it
private ViewPoint() {
super(null);
editionPatterns = new Vector<EditionPattern>();
}
private void init(String baseName, File viewpointDir, File xmlFile, ViewPointLibrary library, ImportedOntology ontology,
ViewPointFolder folder) {
logger.info("Registering viewpoint " + baseName + " URI=" + getViewPointURI());
name = baseName;
viewPointDirectory = viewpointDir;
_library = library;
folder.addToViewPoints(this);
relativePathFileConverter = new RelativePathFileConverter(viewPointDirectory);
this.xmlFile = xmlFile;
/*if (owlFile == null) {
owlFile = new File(viewpointDir, baseName + ".owl");
}
if (owlFile.exists()) {
logger.fine("Found " + owlFile);
viewpointOntology = _library.getOntologyLibrary().importOntology(viewPointURI, owlFile);
viewpointOntology.setIsReadOnly(false);
}
else {
logger.warning("Could not find " + owlFile);
return;
}*/
viewpointOntology = ontology;
for (EditionPattern ep : getEditionPatterns()) {
for (PatternRole pr : ep.getPatternRoles()) {
if (pr instanceof ShapePatternRole) {
((ShapePatternRole) pr).tryToFindAGR();
}
}
}
}
private StringEncoder encoder;
@Override
public StringEncoder getStringEncoder() {
if (encoder == null) {
return encoder = new StringEncoder(super.getStringEncoder(), relativePathFileConverter);
}
return encoder;
}
@Override
public void saveToFile(File aFile) {
super.saveToFile(aFile);
clearIsModified(true);
}
public void save() {
logger.info("Saving ViewPoint to " + xmlFile.getAbsolutePath() + "...");
// Following was used to debug (display purpose only)
/*Converter<File> previousConverter = StringEncoder.getDefaultInstance()._converterForClass(File.class);
StringEncoder.getDefaultInstance()._addConverter(relativePathFileConverter);
try {
System.out.println("File: " + XMLCoder.encodeObjectWithMapping(this, getXMLMapping(), getStringEncoder()));
} catch (InvalidObjectSpecificationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidModelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AccessorInvocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DuplicateSerializationIdentifierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringEncoder.getDefaultInstance()._addConverter(previousConverter);
*/
File dir = xmlFile.getParentFile();
if (!dir.exists()) {
dir.mkdirs();
}
File temporaryFile = null;
try {
makeLocalCopy();
temporaryFile = File.createTempFile("temp", ".xml", dir);
saveToFile(temporaryFile);
FileUtils.rename(temporaryFile, xmlFile);
clearIsModified(true);
logger.info("Saved ViewPoint to " + xmlFile.getAbsolutePath() + ". Done.");
} catch (IOException e) {
e.printStackTrace();
logger.severe("Could not save ViewPoint to " + xmlFile.getAbsolutePath());
if (temporaryFile != null) {
temporaryFile.delete();
}
}
}
private void makeLocalCopy() throws IOException {
if (xmlFile != null && xmlFile.exists()) {
String localCopyName = xmlFile.getName() + "~";
File localCopy = new File(xmlFile.getParentFile(), localCopyName);
FileUtils.copyFileToFile(xmlFile, localCopy);
}
}
@Override
public String getClassNameKey() {
return "view_point";
}
private void findPalettes(File dir) {
if (dir == null) {
return;
}
if (palettes == null) {
palettes = new Vector<ViewPointPalette>();
}
for (File f : dir.listFiles()) {
if (!f.isDirectory() && f.getName().endsWith(".palette") && f.length() > 0) {
ViewPointPalette palette = ViewPointPalette.instanciateCalcPalette(this, f);
if (palette != null) {
addToCalcPalettes(palette);
}
} else if (f.isDirectory() && !f.getName().equals("CVS")) {
findPalettes(f);
}
}
}
private void findShemas(File dir) {
if (dir == null) {
return;
}
if (shemas == null) {
shemas = new Vector<ExampleDrawingShema>();
}
for (File f : dir.listFiles()) {
if (!f.isDirectory() && f.getName().endsWith(".shema")) {
ExampleDrawingShema palette = ExampleDrawingShema.instanciateShema(this, f);
addToCalcShemas(palette);
} else if (f.isDirectory() && !f.getName().equals("CVS")) {
findShemas(f);
}
}
}
public void loadWhenUnloaded() {
if (!isLoaded && !isLoading && viewpointOntology != null) {
load();
}
}
protected void load() {
// logger.info("------------------------------------------------- "+calcURI);
logger.info("Try to load ViewPoint " + viewPointURI);
isLoading = true;
logger.info("viewpointOntology=" + viewpointOntology);
if (viewpointOntology != null) {
logger.info(viewpointOntology.getURI() + " isLoaded=" + viewpointOntology.isLoaded() + " isLoading="
+ viewpointOntology.isLoading());
viewpointOntology.loadWhenUnloaded();
}
// Deprecated code
/*if (getLocalizedDictionary() != null) {
FlexoLocalization.addToLocalizedDelegates(getLocalizedDictionary());
}*/
if (viewpointOntology != null) {
isLoaded = true;
}
isLoading = false;
logger.info("Loaded ViewPoint " + viewPointURI);
/*for (OntologyClass clazz : getOntologyLibrary().getAllClasses()) {
System.out.println("Found: " + clazz);
}*/
}
@Override
public String getFullyQualifiedName() {
return getURI();
}
public File getViewPointDirectory() {
return viewPointDirectory;
}
@Override
public String getURI() {
return getViewPointURI();
}
public String getViewPointURI() {
return viewPointURI;
}
public void _setViewPointURI(String vpURI) {
if (vpURI != null) {
// We prevent ',' so that we can use it as a delimiter in tags.
vpURI = vpURI.replace(",", "");
}
this.viewPointURI = vpURI;
}
@Override
public String toString() {
return "ViewPoint:" + getViewPointURI();
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public void setDescription(String description) {
this.description = description;
}
public String getVersion() {
return version;
}
public void setVersion(String aVersion) {
if (requireChange(version, aVersion)) {
String old = this.version;
this.version = aVersion;
setChanged();
notifyObservers(new OEDataModification("version", old, version));
}
}
@Override
public FlexoOntology getViewpointOntology() {
if (isDeserializing()) {
return super.getViewpointOntology();
}
return viewpointOntology;
}
public void setViewpointOntology(ImportedOWLOntology viewpointOntology) {
this.viewpointOntology = viewpointOntology;
}
@Override
public ViewPointLibrary getViewPointLibrary() {
return _library;
}
@Override
public String getInspectorName() {
return Inspectors.VPM.ONTOLOGY_CALC_INSPECTOR;
}
public Vector<ViewPointPalette> getPalettes() {
if (palettes == null) {
findPalettes(viewPointDirectory);
}
return palettes;
}
public ViewPointPalette getPalette(String paletteName) {
if (paletteName == null) {
return null;
}
for (ViewPointPalette p : getPalettes()) {
if (paletteName.equals(p.getName())) {
return p;
}
}
return null;
}
public void addToCalcPalettes(ViewPointPalette aPalette) {
palettes.add(aPalette);
setChanged();
notifyObservers(new CalcPaletteInserted(aPalette, this));
}
public void removeFromCalcPalettes(ViewPointPalette aPalette) {
palettes.remove(aPalette);
setChanged();
notifyObservers(new CalcPaletteRemoved(aPalette, this));
}
public Vector<ExampleDrawingShema> getShemas() {
if (shemas == null) {
findShemas(viewPointDirectory);
}
return shemas;
}
public ExampleDrawingShema getShema(String shemaName) {
if (shemaName == null) {
return null;
}
for (ExampleDrawingShema s : getShemas()) {
if (shemaName.equals(s.getName())) {
return s;
}
}
return null;
}
public void addToCalcShemas(ExampleDrawingShema aShema) {
shemas.add(aShema);
setChanged();
notifyObservers(new CalcDrawingShemaInserted(aShema, this));
}
public void removeFromCalcShemas(ExampleDrawingShema aShema) {
shemas.remove(aShema);
setChanged();
notifyObservers(new CalcDrawingShemaRemoved(aShema, this));
}
@Override
public ViewPoint getViewPoint() {
return this;
}
protected void notifyEditionSchemeModified() {
_allEditionPatternWithDropScheme = null;
_allEditionPatternWithLinkScheme = null;
}
private Vector<EditionPattern> _allEditionPatternWithDropScheme;
private Vector<EditionPattern> _allEditionPatternWithLinkScheme;
public Vector<EditionPattern> getAllEditionPatternWithDropScheme() {
if (_allEditionPatternWithDropScheme == null) {
_allEditionPatternWithDropScheme = new Vector<EditionPattern>();
for (EditionPattern p : getEditionPatterns()) {
if (p.hasDropScheme()) {
_allEditionPatternWithDropScheme.add(p);
}
}
}
return _allEditionPatternWithDropScheme;
}
public Vector<EditionPattern> getAllEditionPatternWithLinkScheme() {
if (_allEditionPatternWithLinkScheme == null) {
_allEditionPatternWithLinkScheme = new Vector<EditionPattern>();
for (EditionPattern p : getEditionPatterns()) {
if (p.hasLinkScheme()) {
_allEditionPatternWithLinkScheme.add(p);
}
}
}
return _allEditionPatternWithLinkScheme;
}
public Vector<EditionPattern> getAllRootEditionPatterns() {
Vector<EditionPattern> returned = new Vector<EditionPattern>();
for (EditionPattern ep : getEditionPatterns()) {
if (ep.isRoot()) {
returned.add(ep);
}
}
return returned;
}
public Vector<EditionPattern> getEditionPatterns() {
return editionPatterns;
}
public void setEditionPatterns(Vector<EditionPattern> editionPatterns) {
this.editionPatterns = editionPatterns;
}
public void addToEditionPatterns(EditionPattern pattern) {
pattern.setCalc(this);
editionPatterns.add(pattern);
_allEditionPatternWithDropScheme = null;
_allEditionPatternWithLinkScheme = null;
setChanged();
notifyObservers(new EditionPatternCreated(pattern));
}
public void removeFromEditionPatterns(EditionPattern pattern) {
pattern.setCalc(null);
editionPatterns.remove(pattern);
setChanged();
notifyObservers(new EditionPatternDeleted(pattern));
}
@Override
public LocalizedDictionary getLocalizedDictionary() {
if (localizedDictionary == null) {
localizedDictionary = new LocalizedDictionary(null);
localizedDictionary.setCalc(this);
}
return localizedDictionary;
}
public void setLocalizedDictionary(LocalizedDictionary localizedDictionary) {
localizedDictionary.setCalc(this);
this.localizedDictionary = localizedDictionary;
}
@Override
public XMLMapping getXMLMapping() {
return getViewPointLibrary().get_VIEW_POINT_MODEL();
}
public EditionPattern getEditionPattern(String editionPatternId) {
for (EditionPattern concept : editionPatterns) {
if (concept.getName().equals(editionPatternId)) {
return concept;
}
}
logger.warning("Not found EditionPattern:" + editionPatternId);
return null;
}
public Vector<LinkScheme> getAllConnectors() {
Vector<LinkScheme> returned = new Vector<LinkScheme>();
for (EditionPattern ep : getViewPoint().getEditionPatterns()) {
for (LinkScheme s : ep.getLinkSchemes()) {
returned.add(s);
}
}
return returned;
}
public Vector<LinkScheme> getConnectorsMatching(EditionPattern fromConcept, EditionPattern toConcept) {
Vector<LinkScheme> returned = new Vector<LinkScheme>();
for (EditionPattern ep : getViewPoint().getEditionPatterns()) {
for (LinkScheme s : ep.getLinkSchemes()) {
if (s.isValidTarget(fromConcept, toConcept)) {
returned.add(s);
}
}
}
return returned;
}
public File getOwlFile() {
return owlFile;
}
public void setOwlFile(File owlFile) {
this.owlFile = owlFile;
}
@Override
public final void finalizeDeserialization(Object builder) {
for (EditionPattern ep : getEditionPatterns()) {
ep.finalizeEditionPatternDeserialization();
}
super.finalizeDeserialization(builder);
}
private BindingModel _bindingModel;
@Override
public BindingModel getBindingModel() {
if (_bindingModel == null) {
createBindingModel();
}
return _bindingModel;
}
public void updateBindingModel() {
logger.fine("updateBindingModel()");
_bindingModel = null;
createBindingModel();
}
private void createBindingModel() {
_bindingModel = new BindingModel();
for (EditionPattern ep : getEditionPatterns()) {
_bindingModel.addToBindingVariables(new EditionPatternPathElement<ViewPoint>(ep, this));
}
}
@Override
public BindingFactory getBindingFactory() {
return EDITION_PATTERN_BINDING_FACTORY;
}
private static EditionPatternBindingFactory EDITION_PATTERN_BINDING_FACTORY = new EditionPatternBindingFactory();
@Override
public String getLanguageRepresentation() {
// Voir du cote de GeneratorFormatter pour formatter tout ca
StringBuffer sb = new StringBuffer();
System.out.println("loaded: " + getViewpointOntology().isLoaded());
for (FlexoOntology o : getViewpointOntology().getImportedOntologies()) {
if (o != getOntologyLibrary().getOWLOntology()) {
String modelName = JavaUtils.getVariableName(o.getName());
sb.append("import " + modelName + " as " + o.getURI() + ";" + StringUtils.LINE_SEPARATOR);
}
}
sb.append("ViewDefinition " + getName() + " uri=\"" + getURI() + "\"");
sb.append(" {" + StringUtils.LINE_SEPARATOR);
// TODO iterate on slots here
sb.append("ModelSlot defaultModelSlot implements toto;");
sb.append(StringUtils.LINE_SEPARATOR);
for (EditionPattern ep : getEditionPatterns()) {
sb.append(ep.getLanguageRepresentation());
sb.append(StringUtils.LINE_SEPARATOR);
}
sb.append("}" + StringUtils.LINE_SEPARATOR);
return sb.toString();
}
}