blob: 72320430ec0991ae14b88ce345a977b54d1fe0bb [file] [log] [blame]
/*******************************************************************************
* 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;
}
}