| /******************************************************************************* |
| * 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); |
| } |
| |
| } |