/** * Copyright 2010 The University of North Carolina at Chapel Hill * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package unc.lib.cdr.workbench.project; import edu.unc.lib.schemas.acl.provider.AclItemProviderAdapterFactory; import gov.loc.mets.DocumentRoot; import gov.loc.mets.MetsPackage; import gov.loc.mets.provider.MetsItemProviderAdapterFactory; import gov.loc.mets.util.METSUtils; import gov.loc.mets.util.MetsResourceFactoryImpl; import gov.loc.mods.mods.provider.MODSItemProviderAdapterFactory; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.command.BasicCommandStack; import org.eclipse.emf.common.command.CommandStack; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.Resource.Diagnostic; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceImpl; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.BasicExtendedMetaData; import org.eclipse.emf.ecore.util.ExtendedMetaData; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory; import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3._1999.xlink.provider.XlinkItemProviderAdapterFactory; import unc.lib.cdr.workbench.rcp.Activator; /** * @author Gregory Jansen * */ public class ProjectEMFSession { private static final Path METS_PATH = new Path(".workbench-mets.xml"); private static final Logger log = LoggerFactory.getLogger(ProjectEMFSession.class); private static ComposedAdapterFactory adapterFactory = null; private static Map<String, String> xmlOptions = new HashMap<String, String>(); public static final QualifiedName EDITING_DOMAIN_KEY = new QualifiedName(MetsProjectNature.NATURE_ID, "cdr_producer.editingDomain"); static { adapterFactory = new ComposedAdapterFactory(); adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory()); adapterFactory.addAdapterFactory(new MetsItemProviderAdapterFactory()); adapterFactory.addAdapterFactory(new XlinkItemProviderAdapterFactory()); adapterFactory.addAdapterFactory(new MODSItemProviderAdapterFactory()); adapterFactory.addAdapterFactory(new AclItemProviderAdapterFactory()); adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory()); xmlOptions.put(XMLResource.OPTION_ENCODING, "utf-8"); } private ResourceSet resourceSet = null; private CommandStack commandStack = null; private AdapterFactoryEditingDomain editingDomain = null; private Resource metsResource = null; private ExtendedMetaData extendedMetaData = null; private IProject project = null; public ProjectEMFSession(IProject project) { this.project = project; this.resourceSet = new ResourceSetImpl(); // Register the appropriate resource factory to handle all file // extensions. this.resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new MetsResourceFactoryImpl()); // Register the package to ensure it is available during loading. this.resourceSet.getPackageRegistry().put(MetsPackage.eNS_URI, MetsPackage.eINSTANCE); // Create the command stack that will notify this editor as commands are // executed. this.commandStack = new BasicCommandStack(); this.editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack, resourceSet); this.extendedMetaData = new BasicExtendedMetaData(resourceSet.getPackageRegistry()); load(); try { this.project.setSessionProperty(EDITING_DOMAIN_KEY, this.editingDomain); } catch (CoreException e) { e.printStackTrace(); } } private void load() { IPath f = getMetsFile(); IFile old = getOldMetsFile(); if (!f.toFile().exists() && old.exists()) { try { log.debug("moving {} to {}", old.getLocation(), f); old.move(f, true, new NullProgressMonitor()); } catch (CoreException e) { throw new Error(e); } } String uri = f.toFile().toURI().toString(); try { log.debug("METS attempting to load existing file: {}", uri); this.metsResource = this.resourceSet.getResource(URI.createURI(uri), true); ((ResourceImpl) this.metsResource).setIntrinsicIDToEObjectMap(new HashMap()); this.metsResource.load(xmlOptions); log.debug("METS loaded from existing file"); } catch (Exception e) { log.debug("METS being created: {}", uri); this.metsResource = this.resourceSet.createResource(URI.createURI(uri)); ((ResourceImpl) this.metsResource).setIntrinsicIDToEObjectMap(new HashMap()); DocumentRoot r = METSUtils.createInitialMetsDocument(project.getName() + " Workbench Manifest"); this.metsResource.getContents().add(r); log.debug("METS created: {}", this.metsResource.getContents()); try { this.metsResource.save(xmlOptions); // this.metsResource.load(xmlOptions); log.debug("METS saved for the first time"); } catch (IOException e1) { log.error("Problem creating METS", e1); Status s = new Status(Status.ERROR, Activator.PLUGIN_ID, "Cannot save METS", e1); } } finally { IResourceChangeListener listener = new ProjectCloseListener(); // TODO listen for changes to the project name and update METS ResourcesPlugin.getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.PRE_CLOSE); } for (Diagnostic d : this.metsResource.getErrors()) { log.debug(d.toString()); } } public IPath getMetsFile() { IPath metsPath = this.project.getLocation().append(METS_PATH); return metsPath; } public IFile getOldMetsFile() { return this.project.getFile(METS_PATH); } public static ComposedAdapterFactory getAdapterFactory() { return adapterFactory; } public ResourceSet getResourceSet() { return resourceSet; } public CommandStack getCommandStack() { return commandStack; } public AdapterFactoryEditingDomain getEditingDomain() { return editingDomain; } public Resource getMetsResource() { return metsResource; } public ExtendedMetaData getExtendedMetaData() { return extendedMetaData; } /** * @author Gregory Jansen * */ public class ProjectCloseListener implements IResourceChangeListener { ProjectCloseListener() { } /* * (non-Javadoc) * * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged * (org.eclipse.core.resources.IResourceChangeEvent) */ @Override public void resourceChanged(IResourceChangeEvent event) { IResource res = event.getResource(); if (project.equals(res) && IResourceChangeEvent.PRE_CLOSE == event.getType()) { log.debug("Saving EMF session prior to project close."); IProject p = (IProject) res; MetsProjectNature.get(p).getEMFSession().save(); ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); } } } /** * */ public void save() { try { this.metsResource.save(xmlOptions); } catch (IOException e) { log.error("Cannot save EMF session", e); } // try { // this.project.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor()); // } catch (CoreException e) { // //throw new Error(e); // } } }