/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* 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:
******************************************************************************/
package org.eclipse.emf.emfstore.server.core.helper;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.emfstore.common.model.ModelElementId;
import org.eclipse.emf.emfstore.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.server.model.ProjectHistory;
import org.eclipse.emf.emfstore.server.model.ProjectId;
import org.eclipse.emf.emfstore.server.model.versioning.ChangePackage;
import org.eclipse.emf.emfstore.server.model.versioning.Version;
import org.eclipse.emf.emfstore.server.model.versioning.operations.AbstractOperation;
/**
* This cache maps modelelements on verions, where these modelelements where changed. This is needed for the getHistory
* method. WARNING: Newly created projects will be added to cache as soon as the server is restarted. Fix this.
*
* @author wesendon
*/
public class HistoryCache {
private HashMap<ProjectId, HashMap<ModelElementId, TreeSet<Version>>> historyCache;
/**
* Default constructor.
*/
public HistoryCache() {
historyCache = new HashMap<ProjectId, HashMap<ModelElementId, TreeSet<Version>>>();
}
/**
* Initializes the cache.
*
* @param projects the projects
*/
public void initCache(List<ProjectHistory> projects) {
for (ProjectHistory project : projects) {
EList<Version> projectVersions = project.getVersions();
if (projectVersions.size() > 0) {
HashMap<ModelElementId, TreeSet<Version>> initialHashMap = buildInitialHashMap(projectVersions.get(0));
for (Version version : projectVersions) {
// System.out.println("Checking version: " + version.getPrimarySpec().getIdentifier());
addChangePackageToCache(initialHashMap, version);
}
historyCache.put(project.getProjectId(), initialHashMap);
}
}
// printMap();
}
/**
* Adds the ME of a version to the cache.
*
* @param projectId the projectId
* @param version the version
*/
public void addVersionToCache(ProjectId projectId, Version version) {
HashMap<ModelElementId, TreeSet<Version>> hashMap = historyCache.get(projectId);
if (hashMap != null & version != null) {
addChangePackageToCache(hashMap, version);
}
}
private void addChangePackageToCache(HashMap<ModelElementId, TreeSet<Version>> hashMap, Version version) {
ChangePackage changes = version.getChanges();
if (changes != null) {
EList<AbstractOperation> operations = changes.getOperations();
extractOperations(hashMap, version, operations);
}
}
private void extractOperations(HashMap<ModelElementId, TreeSet<Version>> hashMap, Version version,
EList<AbstractOperation> operations) {
for (AbstractOperation abstractOperation : operations) {
for (ModelElementId elementId : abstractOperation.getAllInvolvedModelElements()) {
addModelElement(hashMap, version, elementId);
}
}
}
private void addModelElement(HashMap<ModelElementId, TreeSet<Version>> hashMap, Version version, ModelElementId id) {
// System.out.println(id.getId() + " ---> " + version.getPrimarySpec().getIdentifier());
TreeSet<Version> set = hashMap.get(id);
if (set == null) {
set = getTreeSet();
hashMap.put(id, set);
}
set.add(version);
}
private HashMap<ModelElementId, TreeSet<Version>> buildInitialHashMap(Version version) {
Set<EObject> allModelElements = version.getProjectState().getAllModelElements();
HashMap<ModelElementId, TreeSet<Version>> hashMap = new HashMap<ModelElementId, TreeSet<Version>>(
(int) (allModelElements.size() * 1.15) + 1);
for (EObject element : allModelElements) {
hashMap.put(ModelUtil.getProject(element).getModelElementId(element), initVersionSet(version));
}
return hashMap;
}
private TreeSet<Version> initVersionSet(Version version) {
TreeSet<Version> versionList = getTreeSet();
versionList.add(version);
return versionList;
}
/**
* Returns versions where the specified ME was touched in the specified project.
*
* @param projectId project id
* @param modelElementId modelelement id
* @return set of versions
*/
public TreeSet<Version> getChangesForModelElement(ProjectId projectId, ModelElementId modelElementId) {
HashMap<ModelElementId, TreeSet<Version>> map = historyCache.get(projectId);
if (map == null) {
return getTreeSet();
}
TreeSet<Version> hashSet = map.get(modelElementId);
if (hashSet == null) {
return getTreeSet();
}
return hashSet;
}
private TreeSet<Version> getTreeSet() {
return new TreeSet<Version>(new Comparator<Version>() {
public int compare(Version o1, Version o2) {
if (o1.getPrimarySpec().getIdentifier() == o2.getPrimarySpec().getIdentifier()) {
return 0;
}
if (o1.getPrimarySpec().getIdentifier() < o2.getPrimarySpec().getIdentifier()) {
return 1;
} else {
return -1;
}
}
});
}
/**
* Debug method.
*/
public void printMap() {
for (ProjectId projectId : historyCache.keySet()) {
System.out.println("PROJECT: " + projectId.getId());
HashMap<ModelElementId, TreeSet<Version>> map = historyCache.get(projectId);
for (ModelElementId meId : map.keySet()) {
System.out.print("\tME: " + meId.getId() + " ");
for (Version version : map.get(meId)) {
System.out.print(version.getPrimarySpec().getIdentifier() + ", ");
}
System.out.println("");
}
}
}
}