/*
* (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.fib;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Hashtable;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.IOUtils;
import org.jdom2.JDOMException;
import org.openflexo.antar.binding.BindingFactory;
import org.openflexo.antar.binding.DefaultBindingFactory;
import org.openflexo.fib.model.ComponentConstraints;
import org.openflexo.fib.model.DataBinding;
import org.openflexo.fib.model.FIBComponent;
import org.openflexo.toolbox.FileResource;
import org.openflexo.toolbox.RelativePathFileConverter;
import org.openflexo.xmlcode.InvalidModelException;
import org.openflexo.xmlcode.StringEncoder;
import org.openflexo.xmlcode.StringEncoder.Converter;
import org.openflexo.xmlcode.XMLCoder;
import org.openflexo.xmlcode.XMLDecoder;
import org.openflexo.xmlcode.XMLMapping;
public class FIBLibrary {
static final Logger logger = Logger.getLogger(FIBLibrary.class.getPackage().getName());
protected static XMLMapping _fibMapping;
private static FIBLibrary _current;
private Map<String, FIBComponent> _fibDefinitions;
private Map<File, FIBComponent> fibFileDefinitions;
private DefaultBindingFactory bindingFactory = new DefaultBindingFactory();
private FIBLibrary() {
super();
_fibDefinitions = new Hashtable<String, FIBComponent>();
fibFileDefinitions = new Hashtable<File, FIBComponent>();
}
protected static FIBLibrary createInstance() {
_current = new FIBLibrary();
StringEncoder.getDefaultInstance()._addConverter(_current.bindingFactory);
StringEncoder.getDefaultInstance()._addConverter(_current.bindingFactory.getBindingValueFactory());
StringEncoder.getDefaultInstance()._addConverter(_current.bindingFactory.getBindingExpressionFactory());
StringEncoder.getDefaultInstance()._addConverter(_current.bindingFactory.getStaticBindingFactory());
StringEncoder.getDefaultInstance()._addConverter(DataBinding.CONVERTER);
StringEncoder.getDefaultInstance()._addConverter(ComponentConstraints.CONVERTER);
return _current;
}
public static FIBLibrary instance() {
if (_current == null) {
createInstance();
}
return _current;
}
public static boolean hasInstance() {
return _current != null;
}
public BindingFactory getBindingFactory() {
return bindingFactory;
}
public static XMLMapping getFIBMapping() {
if (_fibMapping == null) {
// File mappingFile = new File
// ("../FlexoInspector/Models/InspectorModel.xml");
File mappingFile = new FileResource("Models/FIBModel.xml");
if (!mappingFile.exists()) {
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Could not find file: " + mappingFile.getAbsolutePath());
}
}
try {
_fibMapping = new XMLMapping(mappingFile);
} catch (InvalidModelException e) {
// Warns about the exception
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Exception raised: " + e + " for file " + mappingFile.getAbsolutePath() + ". See console for details.");
}
e.printStackTrace();
} catch (Exception e) {
// Warns about the exception
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Exception raised: " + e.getClass().getName() + " for file " + mappingFile.getAbsolutePath()
+ ". See console for details.");
}
e.printStackTrace();
}
}
return _fibMapping;
}
public boolean componentIsLoaded(File fibFile) {
return fibFileDefinitions.get(fibFile) != null;
}
public boolean componentIsLoaded(String fibResourcePath) {
return _fibDefinitions.get(fibResourcePath) != null;
}
public FIBComponent retrieveFIBComponent(File fibFile) {
return retrieveFIBComponent(fibFile, true);
}
public FIBComponent retrieveFIBComponent(File fibFile, boolean useCache) {
FIBComponent fibComponent = fibFileDefinitions.get(fibFile);
if (!useCache || fibComponent == null || fibComponent.getLastModified().getTime() < fibFile.lastModified()) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Load " + fibFile.getAbsolutePath());
}
RelativePathFileConverter relativePathFileConverter = new RelativePathFileConverter(fibFile.getParentFile());
Converter<File> previousConverter = StringEncoder.getDefaultInstance()._converterForClass(File.class);
StringEncoder.getDefaultInstance()._addConverter(relativePathFileConverter);
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(fibFile);
FIBComponent component = loadFIBComponent(inputStream);
component.setLastModified(new Date(fibFile.lastModified()));
component.setDefinitionFile(fibFile.getAbsolutePath());
fibFileDefinitions.put(fibFile, component);
return component;
} catch (FileNotFoundException e) {
logger.warning("Not found: " + fibFile.getAbsolutePath());
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (JDOMException e) {
e.printStackTrace();
return null;
} finally {
IOUtils.closeQuietly(inputStream);
StringEncoder.getDefaultInstance()._addConverter(previousConverter);
}
}
return fibComponent;
}
public void removeFIBComponentFromCache(File fibFile) {
fibFileDefinitions.remove(fibFile);
}
public FIBComponent retrieveFIBComponent(String fibResourcePath) {
return retrieveFIBComponent(fibResourcePath, true);
}
public FIBComponent retrieveFIBComponent(String fibResourcePath, boolean useCache) {
InputStream inputStream = getClass().getResourceAsStream(fibResourcePath);
try {
return retrieveFIBComponent(fibResourcePath, inputStream, useCache);
} finally {
IOUtils.closeQuietly(inputStream);
}
}
private FIBComponent retrieveFIBComponent(String fibIdentifier, InputStream inputStream, boolean useCache) {
if (!useCache || _fibDefinitions.get(fibIdentifier) == null) {
try {
if (getFIBMapping() != null) {
FIBComponent fibComponent = loadFIBComponent(inputStream);
fibComponent.setDefinitionFile(fibIdentifier);
_fibDefinitions.put(fibIdentifier, fibComponent);
}
} catch (Exception e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised during Fib import '" + fibIdentifier + "': " + e);
}
e.printStackTrace();
}
}
return _fibDefinitions.get(fibIdentifier);
}
private FIBComponent loadFIBComponent(InputStream inputStream) throws IOException, JDOMException {
return (FIBComponent) XMLDecoder.decodeObjectWithMapping(inputStream, getFIBMapping(), this);
}
public static void save(FIBComponent component, File file) {
logger.info("Save to file " + file.getAbsolutePath());
FileOutputStream out = null;
try {
out = new FileOutputStream(file);
saveComponentToStream(component, file, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(out);
}
}
public static void saveComponentToStream(FIBComponent component, File file, OutputStream stream) {
RelativePathFileConverter relativePathFileConverter = new RelativePathFileConverter(file.getParentFile());
XMLCoder coder = new XMLCoder(getFIBMapping(), new StringEncoder(StringEncoder.getDefaultInstance(), relativePathFileConverter));
try {
coder.encodeObject(component, stream);
logger.info("Succeeded to save: " + file);
// System.out.println("> "+coder.encodeObject(component));
} catch (Exception e) {
logger.warning("Failed to save: " + file + " unexpected exception: " + e.getMessage());
e.printStackTrace();
}
}
}