mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 01:44:38 +00:00
#939 - Make ModifyAwareSet serializable ... (for serializable entity beans with @DbJson etc)
This commit is contained in:
@@ -1,118 +0,0 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Wraps a collection for the purposes of detecting modifications.
|
||||
*/
|
||||
public class ModifyAwareCollection<E> implements Collection<E> {
|
||||
|
||||
protected final ModifyAwareOwner owner;
|
||||
|
||||
protected final Collection<E> c;
|
||||
|
||||
/**
|
||||
* Create with an Owner and the underlying collection this wraps.
|
||||
* <p>
|
||||
* The owner is notified of the additions and removals.
|
||||
* </p>
|
||||
*/
|
||||
public ModifyAwareCollection(ModifyAwareOwner owner, Collection<E> c) {
|
||||
this.owner = owner;
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return c.toString();
|
||||
}
|
||||
|
||||
public boolean add(E o) {
|
||||
if (c.add(o)) {
|
||||
owner.markAsModified();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> collection) {
|
||||
boolean changed = false;
|
||||
for (E o : collection) {
|
||||
if (c.add(o)) {
|
||||
owner.markAsModified();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (!c.isEmpty()) {
|
||||
owner.markAsModified();
|
||||
}
|
||||
c.clear();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return c.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> collection) {
|
||||
return c.containsAll(collection);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return c.isEmpty();
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return new ModifyAwareIterator<>(owner, c.iterator());
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
if (c.remove(o)) {
|
||||
owner.markAsModified();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> collection) {
|
||||
boolean changed = false;
|
||||
for (Object element : collection) {
|
||||
if (c.remove(element)) {
|
||||
owner.markAsModified();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> collection) {
|
||||
boolean changed = false;
|
||||
Iterator<?> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = it.next();
|
||||
if (!collection.contains(o)) {
|
||||
it.remove();
|
||||
owner.markAsModified();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return c.size();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return c.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
//noinspection SuspiciousToArrayCall
|
||||
return c.toArray(a);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,8 @@ package io.ebeaninternal.server.type;
|
||||
*/
|
||||
public class ModifyAwareFlag implements ModifyAwareOwner {
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
boolean dirty;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,6 +11,8 @@ import java.util.ListIterator;
|
||||
*/
|
||||
public class ModifyAwareList<E> implements List<E>, ModifyAwareOwner {
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
final List<E> list;
|
||||
|
||||
final ModifyAwareOwner owner;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -9,6 +10,8 @@ import java.util.Set;
|
||||
*/
|
||||
public class ModifyAwareMap<K, V> implements Map<K, V>, ModifyAwareOwner {
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
final ModifyAwareOwner owner;
|
||||
|
||||
/**
|
||||
@@ -107,7 +110,7 @@ public class ModifyAwareMap<K, V> implements Map<K, V>, ModifyAwareOwner {
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return new ModifyAwareCollection<>(this, map.values());
|
||||
return new ModifyAwareSet<>(this, new LinkedHashSet<>(map.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Owner object notified when a modification is detected.
|
||||
*/
|
||||
public interface ModifyAwareOwner {
|
||||
public interface ModifyAwareOwner extends Serializable {
|
||||
|
||||
/**
|
||||
* Return true if the value is considered dirty.
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wraps a Set for the purposes of detecting modifications.
|
||||
*/
|
||||
public class ModifyAwareSet<E> extends ModifyAwareCollection<E> implements Set<E>, ModifyAwareOwner {
|
||||
public class ModifyAwareSet<E> implements Set<E>, ModifyAwareOwner {
|
||||
|
||||
/**
|
||||
* Create with an Owner that is notified of modifications.
|
||||
*/
|
||||
public ModifyAwareSet(ModifyAwareOwner owner, Set<E> s) {
|
||||
super(owner, s);
|
||||
}
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
protected final ModifyAwareOwner owner;
|
||||
|
||||
protected final Set<E> set;
|
||||
|
||||
/**
|
||||
* Create as top level with it's own ModifyAwareOwner instance wrapping the given Set.
|
||||
*/
|
||||
public ModifyAwareSet(Set<E> s) {
|
||||
super(new ModifyAwareFlag(), s);
|
||||
public ModifyAwareSet(Set<E> underlying) {
|
||||
this(new ModifyAwareFlag(), underlying);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with an Owner that is notified of modifications.
|
||||
*/
|
||||
public ModifyAwareSet(ModifyAwareOwner owner, Set<E> underlying) {
|
||||
this.owner = owner;
|
||||
this.set = underlying;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,4 +44,96 @@ public class ModifyAwareSet<E> extends ModifyAwareCollection<E> implements Set<E
|
||||
public void resetMarkedDirty() {
|
||||
owner.resetMarkedDirty();
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return set.toString();
|
||||
}
|
||||
|
||||
public boolean add(E o) {
|
||||
if (set.add(o)) {
|
||||
owner.markAsModified();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> collection) {
|
||||
boolean changed = false;
|
||||
for (E o : collection) {
|
||||
if (set.add(o)) {
|
||||
owner.markAsModified();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (!set.isEmpty()) {
|
||||
owner.markAsModified();
|
||||
}
|
||||
set.clear();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return set.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> collection) {
|
||||
return set.containsAll(collection);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return new ModifyAwareIterator<>(owner, set.iterator());
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
if (set.remove(o)) {
|
||||
owner.markAsModified();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> collection) {
|
||||
boolean changed = false;
|
||||
for (Object element : collection) {
|
||||
if (set.remove(element)) {
|
||||
owner.markAsModified();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> collection) {
|
||||
boolean changed = false;
|
||||
Iterator<?> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = it.next();
|
||||
if (!collection.contains(o)) {
|
||||
it.remove();
|
||||
owner.markAsModified();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return set.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return set.toArray(a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ModifyAwareFlagTest {
|
||||
|
||||
@Test
|
||||
public void serialise() throws IOException, ClassNotFoundException {
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(os);
|
||||
|
||||
ModifyAwareFlag flag = new ModifyAwareFlag();
|
||||
flag.markAsModified();
|
||||
oos.writeObject(flag);
|
||||
oos.flush();
|
||||
oos.close();
|
||||
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
|
||||
ModifyAwareFlag read = (ModifyAwareFlag)ois.readObject();
|
||||
assertThat(read.isMarkedDirty()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,21 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
public class ModifyAwareListTest {
|
||||
@@ -242,4 +250,22 @@ public class ModifyAwareListTest {
|
||||
|
||||
assertTrue(set.isMarkedDirty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serialise() throws IOException, ClassNotFoundException {
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(os);
|
||||
|
||||
ModifyAwareList<String> orig = createList();
|
||||
oos.writeObject(orig);
|
||||
oos.flush();
|
||||
oos.close();
|
||||
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
|
||||
ModifyAwareList<String> read = (ModifyAwareList<String>)ois.readObject();
|
||||
assertThat(read).contains("A", "B", "C", "D", "E");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,19 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ModifyAwareMapTest {
|
||||
@@ -181,4 +188,22 @@ public class ModifyAwareMapTest {
|
||||
assertEquals(map.size(), entries.size());
|
||||
assertFalse(map.isMarkedDirty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serialise() throws IOException, ClassNotFoundException {
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(os);
|
||||
|
||||
ModifyAwareMap<String, String> orig = createMap();
|
||||
oos.writeObject(orig);
|
||||
oos.flush();
|
||||
oos.close();
|
||||
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
|
||||
ModifyAwareMap<String, String> read = (ModifyAwareMap<String, String>)ois.readObject();
|
||||
assertThat(read).hasSize(orig.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ModifyAwareSetTest {
|
||||
|
||||
private ModifyAwareSet<String> createSet() {
|
||||
HashSet<String> set = new HashSet<>();
|
||||
set.addAll(Arrays.asList("A", "B", "C", "D", "E"));
|
||||
return new ModifyAwareSet<>(set);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serialise() throws IOException, ClassNotFoundException {
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(os);
|
||||
|
||||
oos.writeObject(createSet());
|
||||
oos.flush();
|
||||
oos.close();
|
||||
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
|
||||
ModifyAwareSet<String> read = (ModifyAwareSet<String>)ois.readObject();
|
||||
assertThat(read).contains("A", "B", "C", "D", "E");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user