Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2015-01-25 06:52:45 +0000
committerEike Stepper2015-01-25 06:52:45 +0000
commite86a3e4ec3a954ebfbaaaae198f9fb524818bc1e (patch)
tree7f5702e721bae86d14ad3df405fdcdff9f902ac7
parente1da08f34d2e56c12a6903ede5f83c67f648adfe (diff)
downloadcdo-e86a3e4ec3a954ebfbaaaae198f9fb524818bc1e.tar.gz
cdo-e86a3e4ec3a954ebfbaaaae198f9fb524818bc1e.tar.xz
cdo-e86a3e4ec3a954ebfbaaaae198f9fb524818bc1e.zip
[458348] Enhance SetContainer
https://bugs.eclipse.org/bugs/show_bug.cgi?id=458348
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ContainerPersistence.java117
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IContainer.java29
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/SetContainer.java286
3 files changed, 403 insertions, 29 deletions
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ContainerPersistence.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ContainerPersistence.java
new file mode 100644
index 0000000000..b7a4cd8ed4
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/ContainerPersistence.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2004-2014 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.util.container;
+
+import org.eclipse.net4j.util.container.IContainer.Persistence;
+import org.eclipse.net4j.util.io.IORuntimeException;
+import org.eclipse.net4j.util.io.IOUtil;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+/**
+ * @author Eike Stepper
+ * @since 3.5
+ */
+public abstract class ContainerPersistence<E> implements Persistence<E>
+{
+ public Collection<E> loadElements() throws IORuntimeException
+ {
+ InputStream out = null;
+
+ try
+ {
+ out = openInputStream();
+ ObjectInputStream oos = new ObjectInputStream(new BufferedInputStream(out));
+
+ @SuppressWarnings("unchecked")
+ Collection<E> elements = (Collection<E>)oos.readObject();
+ return elements;
+ }
+ catch (IOException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ catch (ClassNotFoundException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ finally
+ {
+ IOUtil.closeSilent(out);
+ }
+ }
+
+ public void saveElements(Collection<E> elements) throws IORuntimeException
+ {
+ OutputStream out = null;
+
+ try
+ {
+ out = openOutputStream();
+
+ ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(out));
+ oos.writeObject(elements);
+ oos.flush();
+ }
+ catch (IOException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ finally
+ {
+ IOUtil.closeSilent(out);
+ }
+ }
+
+ protected abstract InputStream openInputStream() throws IOException;
+
+ protected abstract OutputStream openOutputStream() throws IOException;
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class FileContainerPersistence<E> extends ContainerPersistence<E>
+ {
+ private final File file;
+
+ public FileContainerPersistence(File file)
+ {
+ this.file = file;
+ }
+
+ public final File getFile()
+ {
+ return file;
+ }
+
+ @Override
+ protected InputStream openInputStream() throws IOException
+ {
+ return new FileInputStream(file);
+ }
+
+ @Override
+ protected OutputStream openOutputStream() throws IOException
+ {
+ return new FileOutputStream(file);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IContainer.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IContainer.java
index 6649ec6fbc..79c318f94d 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IContainer.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/IContainer.java
@@ -12,6 +12,7 @@
package org.eclipse.net4j.util.container;
import org.eclipse.net4j.util.event.INotifier;
+import org.eclipse.net4j.util.io.IORuntimeException;
import java.util.Collection;
@@ -50,4 +51,32 @@ public interface IContainer<E> extends INotifier
public boolean removeAllElements(Collection<E> elements);
}
+
+ /**
+ * A {@link IContainer container} with additional methods to add or remove elements.
+ *
+ * @author Eike Stepper
+ * @since 3.5
+ */
+ public interface Persistable<E> extends IContainer<E>
+ {
+ public Persistence<E> getPersistence();
+
+ public void setPersistence(Persistence<E> persistence);
+
+ public void load() throws IORuntimeException;
+
+ public void save() throws IORuntimeException;
+ }
+
+ /**
+ * @author Eike Stepper
+ * @since 3.5
+ */
+ public interface Persistence<E>
+ {
+ public Collection<E> loadElements() throws IORuntimeException;
+
+ public void saveElements(Collection<E> elements) throws IORuntimeException;
+ }
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/SetContainer.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/SetContainer.java
index 70ac02419a..0d3be1950b 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/SetContainer.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/container/SetContainer.java
@@ -10,12 +10,15 @@
*/
package org.eclipse.net4j.util.container;
-import org.eclipse.net4j.util.container.IContainerDelta.Kind;
import org.eclipse.net4j.util.container.delegate.IContainerSet;
import org.eclipse.net4j.util.container.delegate.IContainerSortedSet;
+import org.eclipse.net4j.util.io.IORuntimeException;
import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -26,12 +29,14 @@ import java.util.Set;
* @see IContainerSet
* @see IContainerSortedSet
*/
-public class SetContainer<E> extends Container<E>
+public class SetContainer<E> extends Container<E> implements IContainer.Modifiable<E>, IContainer.Persistable<E>
{
private final Class<E> componentType;
private final Set<E> set;
+ private Persistence<E> persistence;
+
public SetContainer(Class<E> componentType)
{
this(componentType, new HashSet<E>());
@@ -48,6 +53,30 @@ public class SetContainer<E> extends Container<E>
return componentType;
}
+ /**
+ * @since 3.5
+ */
+ public final Persistence<E> getPersistence()
+ {
+ return persistence;
+ }
+
+ /**
+ * @since 3.5
+ */
+ public final void setPersistence(Persistence<E> persistence)
+ {
+ this.persistence = persistence;
+ }
+
+ /**
+ * @since 3.5
+ */
+ public boolean isSavedWhenModified()
+ {
+ return true;
+ }
+
@Override
public synchronized boolean isEmpty()
{
@@ -55,73 +84,235 @@ public class SetContainer<E> extends Container<E>
return set.isEmpty();
}
- public synchronized E[] getElements()
+ public E[] getElements()
{
checkActive();
- @SuppressWarnings("unchecked")
- E[] a = (E[])Array.newInstance(componentType, set.size());
+ E[] array;
+ synchronized (this)
+ {
+ @SuppressWarnings("unchecked")
+ E[] a = (E[])Array.newInstance(componentType, set.size());
- E[] array = set.toArray(a);
- array = sortElements(array);
+ array = set.toArray(a);
+ }
+ array = sortElements(array);
return array;
}
- public void clear()
+ public boolean addElement(E element)
{
- ContainerEvent<E> event = new ContainerEvent<E>(this);
+ if (!validateElement(element))
+ {
+ return false;
+ }
+
+ IContainerEvent<E> event = null;
synchronized (this)
{
- for (E element : set)
+ if (set.add(element))
{
- event.addDelta(element, Kind.REMOVED);
+ addedElement(element);
+ event = newContainerEvent(element, IContainerDelta.Kind.ADDED);
+ notifyAll();
}
+ }
- set.clear();
- notifyAll();
+ if (event != null)
+ {
+ fireEvent(event);
+ modifiedContainer();
+ return true;
}
- fireEvent(event);
+ return false;
}
- public boolean addElement(E element)
+ /**
+ * @since 3.5
+ */
+ public boolean addAllElements(Collection<E> elements)
{
- boolean added;
+ List<E> validElements = new ArrayList<E>();
+ for (E element : elements)
+ {
+ if (validateElement(element))
+ {
+ validElements.add(element);
+ }
+ }
+
+ ContainerEvent<E> event = null;
synchronized (this)
{
- if (!validateElement(element))
+ for (E element : validElements)
{
- return false;
+ if (set.add(element))
+ {
+ addedElement(element);
+
+ if (event == null)
+ {
+ event = newContainerEvent();
+ }
+
+ event.addDelta(element, IContainerDelta.Kind.ADDED);
+ }
}
- added = set.add(element);
- notifyAll();
+ if (event != null)
+ {
+ notifyAll();
+ }
}
- if (added)
+ if (event != null)
{
- fireElementAddedEvent(element);
+ fireEvent(event);
+ modifiedContainer();
+ return true;
}
- return added;
+ return false;
}
public boolean removeElement(E element)
{
- boolean removed;
+ IContainerEvent<E> event = null;
+ synchronized (this)
+ {
+ if (set.remove(element))
+ {
+ removedElement(element);
+ event = newContainerEvent(element, IContainerDelta.Kind.REMOVED);
+ notifyAll();
+ }
+ }
+
+ if (event != null)
+ {
+ fireEvent(event);
+ modifiedContainer();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @since 3.5
+ */
+ public boolean removeAllElements(Collection<E> elements)
+ {
+ ContainerEvent<E> event = null;
+ synchronized (this)
+ {
+ for (E element : elements)
+ {
+ if (set.remove(element))
+ {
+ removedElement(element);
+
+ if (event == null)
+ {
+ event = newContainerEvent();
+ }
+
+ event.addDelta(element, IContainerDelta.Kind.REMOVED);
+ }
+ }
+
+ if (event != null)
+ {
+ notifyAll();
+ }
+ }
+
+ if (event != null)
+ {
+ fireEvent(event);
+ modifiedContainer();
+ return true;
+ }
+
+ return false;
+ }
+
+ public void clear()
+ {
+ ContainerEvent<E> event = null;
synchronized (this)
{
- removed = set.remove(element);
- notifyAll();
+ for (E element : set)
+ {
+ if (set.contains(element))
+ {
+ removedElement(element);
+
+ if (event == null)
+ {
+ event = newContainerEvent();
+ }
+
+ event.addDelta(element, IContainerDelta.Kind.REMOVED);
+ }
+ }
+
+ if (event != null)
+ {
+ notifyAll();
+ }
}
- if (removed)
+ if (event != null)
{
- fireElementRemovedEvent(element);
+ fireEvent(event);
+ modifiedContainer();
}
+ }
- return removed;
+ /**
+ * @since 3.5
+ */
+ public synchronized void load() throws IORuntimeException
+ {
+ if (persistence != null)
+ {
+ Collection<E> elements = persistence.loadElements();
+
+ set.clear();
+ set.addAll(elements);
+ }
+ }
+
+ /**
+ * @since 3.5
+ */
+ public synchronized void save() throws IORuntimeException
+ {
+ if (persistence != null)
+ {
+ persistence.saveElements(set);
+ }
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+ load();
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ if (!isSavedWhenModified())
+ {
+ save();
+ }
+
+ super.doDeactivate();
}
protected Set<E> getSet()
@@ -129,13 +320,50 @@ public class SetContainer<E> extends Container<E>
return set;
}
+ /**
+ * Called outside synchronized(this).
+ */
protected E[] sortElements(E[] array)
{
return array;
}
+ /**
+ * Called outside synchronized(this).
+ */
protected boolean validateElement(E element)
{
return true;
}
+
+ /**
+ * Called outside synchronized(this).
+ *
+ * @since 3.5
+ */
+ protected void modifiedContainer()
+ {
+ if (isSavedWhenModified())
+ {
+ save();
+ }
+ }
+
+ /**
+ * Called inside synchronized(this).
+ *
+ * @since 3.5
+ */
+ protected void addedElement(E element)
+ {
+ }
+
+ /**
+ * Called inside synchronized(this).
+ *
+ * @since 3.5
+ */
+ protected void removedElement(E element)
+ {
+ }
}

Back to the top