package org.openflexo.foundation.rm; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.logging.Level; import org.apache.commons.io.IOUtils; import org.jdom2.JDOMException; import org.openflexo.foundation.utils.FlexoProgress; import org.openflexo.foundation.utils.FlexoProjectFile; import org.openflexo.foundation.utils.ProjectLoadingCancelledException; import org.openflexo.foundation.utils.ProjectLoadingHandler; import org.openflexo.model.ModelContextLibrary; import org.openflexo.model.StringConverterLibrary; import org.openflexo.model.exceptions.InvalidDataException; import org.openflexo.model.exceptions.ModelDefinitionException; import org.openflexo.model.factory.ModelFactory; import org.openflexo.xmlcode.StringEncoder.Converter; public class FlexoPamelaResource<SRD extends StorageResourceData> extends FlexoStorageResource<SRD> { private static final java.util.logging.Logger logger = org.openflexo.logging.FlexoLogger.getLogger(FlexoPamelaResource.class .getPackage().getName()); private static final class PAMELALoadResourceException extends LoadResourceException { private PAMELALoadResourceException(FlexoFileResource<?> fileResource, String message) { super(fileResource, message); } } public static final class ConverterAdapter<T> extends StringConverterLibrary.Converter<T> { private final Converter<T> converter; public ConverterAdapter(Converter<T> converter) { super(converter.getConverterClass()); this.converter = converter; } @Override public T convertFromString(String value, ModelFactory factory) throws InvalidDataException { // Watch out here: converter is of the old type of XMLCode converter, but 'this' is an instance of a PAMELA converter return converter.convertFromString(value); } @Override public String convertToString(T value) { return converter.convertToString(value); } } // This flag indicates that the name of the resource is the same as the name of the project. private boolean useProjectName; private String name; private ResourceType resourceType; private Class<SRD> resourceDataClass; private ModelFactory modelFactory; public FlexoPamelaResource(FlexoProject project, String name, ResourceType resourceType, Class<SRD> resourceDataClass, FlexoProjectFile file) throws ModelDefinitionException, InvalidFileNameException, DuplicateResourceException { this(project); this.name = name; this.useProjectName = name == null; this.resourceType = resourceType; if (project.getProjectName().equals(name)) { if (logger.isLoggable(Level.WARNING)) { logger.warning("You are creating a PAMELA resource with the exact same name as the project but it is not synched with it."); } } setResourceDataClass(resourceDataClass); setResourceFile(file); this._resourceData = modelFactory.newInstance(resourceDataClass); this._resourceData.setFlexoResource(this); } public FlexoPamelaResource(FlexoProject project, ResourceType resourceType, Class<SRD> resourceDataClass, FlexoProjectFile file) throws ModelDefinitionException, InvalidFileNameException, DuplicateResourceException { this(project); this.useProjectName = true; this.resourceType = resourceType; setResourceDataClass(resourceDataClass); setResourceFile(file); this._resourceData = modelFactory.newInstance(resourceDataClass); this._resourceData.setFlexoResource(this); } public FlexoPamelaResource(FlexoProjectBuilder builder) { this(builder.project); builder.notifyResourceLoading(this); } private FlexoPamelaResource(FlexoProject aProject) { super(aProject); } public ModelFactory getModelFactory() { return modelFactory; } public Class<SRD> getResourceDataClass() { return resourceDataClass; } public void setResourceDataClass(Class<SRD> resourceDataClass) throws ModelDefinitionException { this.resourceDataClass = resourceDataClass; if (resourceDataClass != null) { this.modelFactory = new ModelFactory(ModelContextLibrary.getModelContext(resourceDataClass)); for (Converter<?> c : project.getStringEncoder().getConverters()) { modelFactory.addConverter(new ConverterAdapter(c)); } } } @Override public ResourceType getResourceType() { if (resourceType == null) { return ResourceType.PAMELA_RESOURCE; } return resourceType; } public void setResourceType(ResourceType resourceType) { this.resourceType = resourceType; } @Override public String getName() { if (isUseProjectName()) { return getProject().getName(); } return name; } @Override public void setName(String name) { this.name = name; } public boolean isUseProjectName() { return useProjectName; } public void setUseProjectName(boolean useProjectName) { this.useProjectName = useProjectName; if (useProjectName) { name = null; } } @Override protected void saveResourceData(boolean clearIsModified) throws SaveResourceException { FileOutputStream out = null; try { out = new FileOutputStream(getFile()); modelFactory.serialize(getResourceData(), out); } catch (IOException e) { e.printStackTrace(); throw new SaveResourceException(this); } finally { IOUtils.closeQuietly(out); } } @Override protected boolean isLoadable() { return super.isLoadable() && resourceDataClass != null; } @Override protected SRD performLoadResourceData(FlexoProgress progress, ProjectLoadingHandler loadingHandler) throws LoadResourceException, FileNotFoundException, ProjectLoadingCancelledException { if (!isLoadable()) { return null; } FileInputStream fis = new FileInputStream(getFile()); try { return (SRD) modelFactory.deserialize(fis); } catch (IOException e) { e.printStackTrace(); throw new PAMELALoadResourceException(this, "I/O exception: " + e.getMessage()); } catch (JDOMException e) { e.printStackTrace(); throw new PAMELALoadResourceException(this, "XML exception (JDOM): " + e.getMessage()); } catch (InvalidDataException e) { e.printStackTrace(); throw new PAMELALoadResourceException(this, "XML exception (Invalid XML): " + e.getMessage()); } catch (ModelDefinitionException e) { e.printStackTrace(); throw new PAMELALoadResourceException(this, "XML exception (Invalid model): " + e.getMessage()); } finally { IOUtils.closeQuietly(fis); } } }