| /******************************************************************************* |
| * Copyright (c) 2013 SAP AG. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eduard Bartsch (SAP AG) - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.core.internal.resources.semantic; |
| |
| import java.io.File; |
| import java.io.FilenameFilter; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.ResourceTreeNode; |
| import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.SemanticDB; |
| import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.SemanticResourceDBFactory; |
| import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.SemanticResourceDBPackage; |
| import org.eclipse.core.internal.resources.semantic.model.SemanticResourceDB.TreeRoot; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; |
| import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; |
| |
| public class SemanticMetadataPersistenceManager { |
| |
| private static final String METADATA_FILENAME = "metadata.xmi"; //$NON-NLS-1$ |
| final static IPath EMPTY = new Path(""); //$NON-NLS-1$ |
| |
| private SemanticDB db; |
| |
| private Map<String, Resource> metadataResourceMap = new HashMap<String, Resource>(); |
| private File metadataFolder; |
| Resource metadataResource; |
| ResourceSet metadataResourceSet = new ResourceSetImpl(); |
| |
| public SemanticMetadataPersistenceManager(File metadataFolder) { |
| this.metadataFolder = metadataFolder; |
| } |
| |
| public SemanticDB getSemanticDB() { |
| return db; |
| } |
| |
| public String getMetadataResourceLocation(String name) { |
| return getMetadataFile(name).getAbsolutePath(); |
| } |
| |
| public String getMetadataFileName(String name) { |
| return "$." + name + ".xmi"; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| public void init() throws IOException { |
| // Register the appropriate resource factory to handle all file |
| // extensions that would cover XMI as well. |
| metadataResourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() |
| .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl()); |
| |
| metadataFolder.mkdirs(); |
| |
| File metadataFile = getMetadataFile(null); |
| |
| if (!metadataFile.exists()) { |
| initSemanticDB(); |
| } else { |
| loadSemanticDB(); |
| } |
| } |
| |
| public void initSemanticDB() { |
| this.metadataResource = metadataResourceSet.createResource(getResourceURI(METADATA_FILENAME)); |
| |
| this.db = SemanticResourceDBFactory.eINSTANCE.createSemanticDB(); |
| |
| this.metadataResource.getContents().add(this.db); |
| } |
| |
| private void loadSemanticDB() throws IOException { |
| SemanticResourceDBPackage pkg = SemanticResourceDBPackage.eINSTANCE; |
| pkg.eClass(); |
| |
| this.metadataResource = metadataResourceSet.createResource(getResourceURI(METADATA_FILENAME)); |
| |
| this.metadataResource.load(null); |
| |
| EList<EObject> contents = this.metadataResource.getContents(); |
| |
| for (EObject eObject : contents) { |
| if (eObject instanceof SemanticDB) { |
| this.db = (SemanticDB) eObject; |
| this.migrateSemanticDB(); |
| break; |
| } |
| } |
| } |
| |
| public void saveSemanticDB(String projectName) throws IOException { |
| if (SfsTraceLocation.CORE_DB.isActive()) { |
| SfsTraceLocation.getTrace().traceEntry(SfsTraceLocation.CORE_DB.getLocation()); |
| } |
| |
| // force assignment to separate resources |
| EList<TreeRoot> roots = this.db.getRoots(); |
| for (TreeRoot treeRoot : roots) { |
| if (projectName == null || projectName.equals(treeRoot.getName())) { |
| assignToProjectSpecificMetadataResource(treeRoot); |
| } |
| } |
| |
| this.metadataResource.save(null); |
| |
| if (projectName == null) { |
| for (Entry<String, Resource> resourceEntry : this.metadataResourceMap.entrySet()) { |
| resourceEntry.getValue().save(null); |
| } |
| } else { |
| Resource resource = this.metadataResourceMap.get(projectName); |
| |
| resource.save(null); |
| } |
| } |
| |
| public File getMetadataFile(String name) { |
| String fileName; |
| |
| if (name != null) { |
| fileName = getMetadataFileName(name); |
| } else { |
| fileName = METADATA_FILENAME; |
| } |
| |
| return new File(metadataFolder, fileName); |
| } |
| |
| public void migrateSemanticDB() throws IOException { |
| TreeIterator<EObject> objects = this.db.eAllContents(); |
| ArrayList<ResourceTreeNode> toBeRemoved = new ArrayList<ResourceTreeNode>(); |
| Set<String> filesToBeRemoved = listMetadataFiles(); |
| |
| while (objects.hasNext()) { |
| EObject eObject = objects.next(); |
| if (eObject instanceof TreeRoot) { |
| TreeRoot root = (TreeRoot) eObject; |
| |
| if (!root.isExists()) { |
| toBeRemoved.add(root); |
| } else { |
| assignToProjectSpecificMetadataResource(root); |
| filesToBeRemoved.remove(getMetadataFileName(root.getName())); |
| } |
| } else if (eObject instanceof ResourceTreeNode) { |
| ResourceTreeNode node = (ResourceTreeNode) eObject; |
| |
| if (!node.isExists()) { |
| toBeRemoved.add(node); |
| } |
| } |
| } |
| |
| for (ResourceTreeNode resourceTreeNode : toBeRemoved) { |
| if (resourceTreeNode instanceof TreeRoot) { |
| ((TreeRoot) resourceTreeNode).setParentDB(null); |
| this.db.getRoots().remove(resourceTreeNode); |
| } else { |
| resourceTreeNode.setParent(null); |
| } |
| } |
| |
| for (String fileName : filesToBeRemoved) { |
| File file = new File(this.metadataFolder, fileName); |
| if (file.exists()) { |
| file.delete(); |
| } |
| } |
| |
| this.metadataResource.save(null); |
| |
| for (String name : this.metadataResourceMap.keySet()) { |
| File file = getMetadataFile(name); |
| |
| if (!file.exists()) { |
| Resource resource = this.metadataResourceMap.get(name); |
| |
| resource.save(null); |
| } |
| } |
| } |
| |
| private Set<String> listMetadataFiles() { |
| File[] files = this.metadataFolder.listFiles(new FilenameFilter() { |
| public boolean accept(File dir, String name) { |
| return name.endsWith(".xmi") && !name.equals(METADATA_FILENAME); //$NON-NLS-1$ |
| } |
| }); |
| |
| Set<String> names = new HashSet<String>(); |
| for (File file : files) { |
| names.add(file.getName()); |
| } |
| return names; |
| } |
| |
| private void assignToProjectSpecificMetadataResource(TreeRoot root) { |
| Resource resource = this.metadataResourceMap.get(root.getName()); |
| |
| if (resource == null) { |
| org.eclipse.emf.common.util.URI uri = org.eclipse.emf.common.util.URI |
| .createFileURI(getMetadataResourceLocation(root.getName())); |
| resource = this.metadataResourceSet.createResource(uri); |
| this.metadataResourceMap.put(root.getName(), resource); |
| } |
| |
| resource.getContents().add(root); |
| } |
| |
| private org.eclipse.emf.common.util.URI getResourceURI(String fileName) { |
| File metadataFile = new File(metadataFolder, fileName); |
| |
| String metadataLocation = metadataFile.getAbsolutePath(); |
| |
| return org.eclipse.emf.common.util.URI.createFileURI(metadataLocation); |
| } |
| |
| public Resource getMetadataResource() { |
| return this.metadataResource; |
| } |
| |
| } |