blob: f933bb4bb7b656b4ce03ca3beaad83eda5911bdd [file] [log] [blame]
/*******************************************************************************
* 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.common.model.util;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.UUID;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
/**
* Implements a list for a containment reference that will automatically split into several resources and save them
* whenever necessary ude to operations on the list. The containmentList is part of a root object that holds the
* containment list. Elements added to the list will be saved to files in the given path with a randomly assigned names
* and the given extension. The list does not support the set method.
*
* @author koegel
* @param <T>
*/
public class AutoSplitAndSaveResourceContainmentList<T extends EObject> implements List<T> {
private static final String ROOT_NAME = "root";
private static final int MAX_CAPACITY = 30;
private final EList<T> list;
private Resource currentResource;
private int currentResourceElementCount;
private final ResourceSet resourceSet;
private final String path;
private final String extension;
private Resource rootResource;
/**
* Constructor.
*
* @param root parent element of list
* @param list the containment list
* @param resourceSet the resourceSet to create the resources in
* @param path the path for new resources
* @param extension the file extension for new resources
*/
public AutoSplitAndSaveResourceContainmentList(EObject root, EList<T> list, ResourceSet resourceSet, String path,
String extension) {
if (list == null || resourceSet == null || path == null || extension == null || root == null) {
throw new IllegalArgumentException();
}
this.resourceSet = resourceSet;
this.path = path;
this.extension = extension;
this.list = list;
Resource eResource = root.eResource();
if (eResource == null) {
URI fileURI = URI.createFileURI(path + File.separatorChar + ROOT_NAME + extension);
rootResource = resourceSet.createResource(fileURI);
rootResource.getContents().add(root);
saveResource(rootResource);
} else {
rootResource = eResource;
}
// init first resource
initCurrentResource(resourceSet);
}
private void initCurrentResource(ResourceSet resourceSet) {
currentResource = createRandomResource(resourceSet, this.path);
currentResourceElementCount = 0;
}
private Resource createRandomResource(ResourceSet resourceSet, String path) {
URI fileURI = URI.createFileURI(path + File.separatorChar + UUID.randomUUID().toString() + extension);
return resourceSet.createResource(fileURI);
}
/**
* {@inheritDoc}
*
* @see java.util.List#add(int, java.lang.Object)
*/
public void add(int index, T element) {
addToResource(element);
list.add(index, element);
saveResource(rootResource);
}
/**
* {@inheritDoc}
*
* @see java.util.List#add(java.lang.Object)
*/
public boolean add(T o) {
addToResource(o);
boolean result = list.add(o);
saveResource(rootResource);
return result;
}
private void addToResource(T o) {
if (o.eResource() != null) {
return;
}
if (currentResourceElementCount > MAX_CAPACITY) {
currentResource = createRandomResource(resourceSet, path);
currentResourceElementCount = 0;
}
currentResource.getContents().add(o);
saveResource(currentResource);
currentResourceElementCount += 1;
}
private void removeFromResource(EObject o) {
Resource eResource = o.eResource();
if (eResource == null) {
return;
}
eResource.getContents().remove(o);
saveResource(eResource);
if (eResource == currentResource) {
currentResourceElementCount -= 1;
}
}
private void saveResource(Resource resource) {
try {
resource.save(null);
} catch (IOException e) {
String message = "Saving to resource failed!";
ModelUtil.log(message, e, IStatus.ERROR);
throw new IllegalStateException(message, e);
}
}
/**
* {@inheritDoc}
*
* @see java.util.List#addAll(java.util.Collection)
*/
public boolean addAll(Collection<? extends T> c) {
for (T element : c) {
addToResource(element);
}
boolean result = list.addAll(c);
saveResource(rootResource);
return result;
}
/**
* {@inheritDoc}
*
* @see java.util.List#addAll(int, java.util.Collection)
*/
public boolean addAll(int index, Collection<? extends T> c) {
for (T element : c) {
addToResource(element);
}
boolean result = list.addAll(index, c);
saveResource(rootResource);
return result;
}
/**
* {@inheritDoc}
*
* @see java.util.List#clear()
*/
public void clear() {
list.clear();
File dir = new File(path);
File[] listFiles = dir.listFiles();
if (listFiles != null) {
for (File file : listFiles) {
if (file.isDirectory() || !file.getName().endsWith(extension)) {
continue;
}
if (file.getName().endsWith(ROOT_NAME + extension)) {
continue;
}
file.delete();
}
}
initCurrentResource(resourceSet);
saveResource(rootResource);
}
/**
* {@inheritDoc}
*
* @see java.util.List#contains(java.lang.Object)
*/
public boolean contains(Object o) {
return list.contains(o);
}
/**
* {@inheritDoc}
*
* @see java.util.List#containsAll(java.util.Collection)
*/
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
/**
* {@inheritDoc}
*
* @see java.util.List#get(int)
*/
public T get(int index) {
return list.get(index);
}
/**
* {@inheritDoc}
*
* @see java.util.List#indexOf(java.lang.Object)
*/
public int indexOf(Object o) {
return list.indexOf(o);
}
/**
* {@inheritDoc}
*
* @see java.util.List#isEmpty()
*/
public boolean isEmpty() {
return list.isEmpty();
}
/**
* {@inheritDoc}
*
* @see java.util.List#iterator()
*/
public Iterator<T> iterator() {
return list.iterator();
}
/**
* {@inheritDoc}
*
* @see java.util.List#lastIndexOf(java.lang.Object)
*/
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
/**
* {@inheritDoc}
*
* @see java.util.List#listIterator()
*/
public ListIterator<T> listIterator() {
return list.listIterator();
}
/**
* {@inheritDoc}
*
* @see java.util.List#listIterator(int)
*/
public ListIterator<T> listIterator(int index) {
return list.listIterator(index);
}
/**
* {@inheritDoc}
*
* @see java.util.List#remove(int)
*/
public T remove(int index) {
T t = list.remove(index);
removeFromResource(t);
saveResource(rootResource);
return t;
}
/**
* {@inheritDoc}
*
* @see java.util.List#remove(java.lang.Object)
*/
@SuppressWarnings("unchecked")
public boolean remove(Object o) {
boolean remove = list.remove(o);
if (o instanceof EObject) {
removeFromResource((T) o);
}
saveResource(rootResource);
return remove;
}
/**
* {@inheritDoc}
*
* @see java.util.List#removeAll(java.util.Collection)
*/
@SuppressWarnings("unchecked")
public boolean removeAll(Collection<?> c) {
boolean result = list.removeAll(c);
for (Object o : c) {
if (o instanceof EObject) {
removeFromResource((T) o);
}
}
saveResource(rootResource);
return result;
}
/**
* {@inheritDoc}
*
* @see java.util.List#retainAll(java.util.Collection)
*/
@SuppressWarnings("unchecked")
public boolean retainAll(Collection<?> c) {
Set<Object> removedElements = new HashSet<Object>();
removedElements.addAll(list);
removedElements.removeAll(c);
boolean result = list.retainAll(c);
for (Object o : removedElements) {
if (o instanceof EObject) {
removeFromResource((T) o);
}
}
saveResource(rootResource);
return result;
}
/**
* Not implemented. Will throw exception on call.
*
* @param index the index
* @param element the new element
* @return will always throw an exception
* @see java.util.List#set(int, java.lang.Object)
*/
public T set(int index, T element) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @see java.util.List#size()
*/
public int size() {
return list.size();
}
/**
* {@inheritDoc}
*
* @see java.util.List#subList(int, int)
*/
public List<T> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
/**
* {@inheritDoc}
*
* @see java.util.List#toArray()
*/
public Object[] toArray() {
return list.toArray();
}
/**
* {@inheritDoc}
*
* @see java.util.List#toArray(T[])
*/
public <D> D[] toArray(D[] a) {
return list.toArray(a);
}
}