diff --git a/gs-api/pom.xml b/gs-api/pom.xml
index 89ab3c548..9dc125d24 100644
--- a/gs-api/pom.xml
+++ b/gs-api/pom.xml
@@ -11,6 +11,29 @@
Generic System API
jar
+
+
+ io.reactivex.rxjava2
+ rxjavafx
+ 2.1.1
+
+
+ io.reactivex.rxjava2
+ rxjava
+ 2.1.3
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+
+
+
${project.artifactId}
@@ -19,7 +42,7 @@
maven-javadoc-plugin
${maven-javadoc-plugin.version}
-
+
diff --git a/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java b/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java
index b486dddb4..2d1248668 100644
--- a/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java
+++ b/gs-api/src/main/java/org/genericsystem/api/core/Snapshot.java
@@ -1,5 +1,6 @@
package org.genericsystem.api.core;
+import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
@@ -8,6 +9,10 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.reactivex.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@@ -152,6 +157,17 @@ public Stream unfilteredStream() {
return Snapshot.this.stream().filter(predicate);
}
+ @Override
+ public Observable getAddsObservable() {
+ return getParent().getAddsObservable().filter(g -> predicate.test(g));
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return getParent().getRemovesObservable().filter(g -> predicate.test(g));
+ }
+
+
@Override
public T get(Object o) {
T result = Snapshot.this.get(o);
@@ -172,6 +188,16 @@ public IndexFilter getFilter() {
return filter;
}
+ @Override
+ public Observable getAddsObservable() {
+ return getParent().getAddsObservable().filter(g -> filter.test((IGeneric>) g));
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return getParent().getRemovesObservable().filter(g -> filter.test((IGeneric>) g));
+ }
+
@Override
public Stream unfilteredStream() {
throw new UnsupportedOperationException("unfilteredStream() should be called only on unfiltered snapshots.");
@@ -187,6 +213,17 @@ public Stream unfilteredStream() {
return Snapshot.this.stream().filter(g -> filters.stream().allMatch(filter -> filter.test((IGeneric>) g)));
}
+ @Override
+ public Observable getAddsObservable() {
+ return Snapshot.this.getAddsObservable().filter(g -> filters.stream().allMatch(filter -> filter.test((IGeneric>) g)));
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return Snapshot.this.getRemovesObservable().filter(g -> filters.stream().allMatch(filter -> filter.test((IGeneric>) g)));
+ }
+
+
@Override
public T get(Object o) {
T result = Snapshot.this.get(o);
@@ -199,9 +236,27 @@ default List toList() {
return stream().collect(Collectors.toList());
}
+ default Observable getAddsObservable() {
+ return Observable.never();
+ }
+
+ default Observable getRemovesObservable() {
+ return Observable.never();
+ }
+
default ObservableList toObservableList() {
- if (getParent() != null)
- return getParent().toObservableList().filtered(g -> getFilter().test((IGeneric>) g));
- return FXCollections.observableArrayList(toList());
+ Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ ObservableList result = FXCollections.observableArrayList(toList());
+ getAddsObservable().subscribe(g -> {
+ if (!result.contains(g)) {
+ logger.debug("Snapshot {}, generic added, {}", System.identityHashCode(this), g);
+ result.add(g);
+ }
+ }, e -> logger.error("Exception while computing observable list.", e));
+ getRemovesObservable().subscribe(g -> {
+ logger.debug("Snapshot {}, generic removed, {}", System.identityHashCode(this), g);
+ result.remove(g);
+ }, e -> logger.error("Exception while computing observable list.", e));
+ return result;
}
}
diff --git a/gs-defaults/src/main/resources/logback.xml b/gs-api/src/main/resources/logback.xml
similarity index 100%
rename from gs-defaults/src/main/resources/logback.xml
rename to gs-api/src/main/resources/logback.xml
diff --git a/gs-common/src/main/java/org/genericsystem/common/AbstractCache.java b/gs-common/src/main/java/org/genericsystem/common/AbstractCache.java
index 5b42edc1b..394c46803 100644
--- a/gs-common/src/main/java/org/genericsystem/common/AbstractCache.java
+++ b/gs-common/src/main/java/org/genericsystem/common/AbstractCache.java
@@ -354,11 +354,13 @@ public final ObservableValue> getObservable(Generic gener
@Override
public Observable getAddsObservable(Generic generic) {
+ // TODO
return Observable.never();
}
@Override
public Observable getRemovesObservable(Generic generic) {
+ // TODO
return Observable.never();
}
}
diff --git a/gs-common/src/main/java/org/genericsystem/common/Container.java b/gs-common/src/main/java/org/genericsystem/common/Container.java
index dfcba39ba..e43cd8507 100644
--- a/gs-common/src/main/java/org/genericsystem/common/Container.java
+++ b/gs-common/src/main/java/org/genericsystem/common/Container.java
@@ -3,10 +3,10 @@
import java.util.stream.Stream;
import org.genericsystem.api.core.Snapshot;
+import org.genericsystem.defaults.tools.RxJavaHelpers;
+import io.reactivex.Observable;
import javafx.collections.FXCollections;
-import javafx.collections.MapChangeListener;
-import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
/**
@@ -31,14 +31,12 @@ public Stream unfilteredStream() {
}
@Override
- public ObservableList toObservableList() {
- ObservableList result = FXCollections.observableArrayList();
- container.addListener((MapChangeListener) c -> {
- if (c.wasAdded() && !c.wasRemoved())
- result.add(c.getKey());
- if (c.wasRemoved() && !c.wasAdded())
- result.remove(c.getKey());
- });
- return result;
+ public Observable getAddsObservable() {
+ return RxJavaHelpers.additionsOf(container).map(entry -> entry.getKey());
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return RxJavaHelpers.removalsOf(container).map(entry -> entry.getKey());
}
}
\ No newline at end of file
diff --git a/gs-common/src/main/java/org/genericsystem/common/Differential.java b/gs-common/src/main/java/org/genericsystem/common/Differential.java
index ee5bb1b27..bc57c7b96 100644
--- a/gs-common/src/main/java/org/genericsystem/common/Differential.java
+++ b/gs-common/src/main/java/org/genericsystem/common/Differential.java
@@ -20,7 +20,6 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ObservableValue;
-import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
/**
@@ -107,40 +106,21 @@ public Stream unfilteredStream() {
return Stream.concat(adds.contains(generic) ? Stream.empty() : subDifferential.getDependencies(generic).filter(new IndexFilter(FiltersBuilder.NOT_CONTAINED_IN_PARAM, new ArrayList<>(removes.toList()))).stream(),
adds.filter(new IndexFilter(FiltersBuilder.IS_DIRECT_DEPENDENCY_OF, generic)).stream());
}
-
@Override
public Snapshot filter(List filters) {
- return new Snapshot() {
-
- @Override
- public Stream unfilteredStream() {
- List filters_ = new ArrayList<>(filters);
- filters_.add(new IndexFilter(FiltersBuilder.NOT_CONTAINED_IN_PARAM, new ArrayList<>(removes.toList())));
- return Stream.concat(adds.contains(generic) ? Stream.empty() : subDifferential.getDependencies(generic).filter(filters_).stream(), adds.filter(filters).stream().filter(x -> generic.isDirectAncestorOf(x)));
- }
- };
+ List filters_ = new ArrayList<>(filters);
+ filters_.add(new IndexFilter(FiltersBuilder.NOT_CONTAINED_IN_PARAM, new ArrayList<>(removes.toList())));
+ return Snapshot.super.filter(filters_);
+ }
+
+ @Override
+ public Observable getAddsObservable() {
+ return getDifferentialObservable().flatMap(diff -> diff.getAddsObservable(generic));
}
@Override
- public ObservableList toObservableList() {
- ObservableList result = getDependenciesAsOservableListCacheMap().get(generic);
- if (result == null) {
- final ObservableList result_ = FXCollections.observableArrayList(getDifferentialProperty().getValue().getDependencies(generic).toList());
- Observable differentialObs = getDifferentialObservable();
- Observable adds = differentialObs.flatMap(diff -> diff.getAddsObservable(generic));
- Observable removes = differentialObs.flatMap(diff -> diff.getRemovesObservable(generic));
- adds.subscribe(g -> {
- logger.debug("Generic added, {}", g);
- result_.add(g);
- }, e -> logger.error("Exception while computing observable list.", e));
- removes.subscribe(g -> {
- logger.debug("Generic removed, {}", g);
- result_.remove(g);
- }, e -> logger.error("Exception while computing observable list.", e));
- result = result_;
- getDependenciesAsOservableListCacheMap().put(generic, result);
- }
- return result;
+ public Observable getRemovesObservable() {
+ return getDifferentialObservable().flatMap(diff -> diff.getRemovesObservable(generic));
}
};
}
diff --git a/gs-defaults/pom.xml b/gs-defaults/pom.xml
index 282c26a95..5c96ed5c9 100644
--- a/gs-defaults/pom.xml
+++ b/gs-defaults/pom.xml
@@ -17,28 +17,5 @@
gs-api
4.0-SNAPSHOT
-
-
- org.slf4j
- slf4j-api
- ${slf4j.version}
-
-
-
- ch.qos.logback
- logback-classic
- ${logback.version}
-
-
-
- io.reactivex.rxjava2
- rxjavafx
- 2.1.1
-
-
- io.reactivex.rxjava2
- rxjava
- 2.1.3
-
\ No newline at end of file
diff --git a/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultCompositesInheritance.java b/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultCompositesInheritance.java
index 8c349db92..1a8234ff9 100644
--- a/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultCompositesInheritance.java
+++ b/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultCompositesInheritance.java
@@ -4,7 +4,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.genericsystem.api.core.ApiStatics;
@@ -13,15 +12,11 @@
import org.genericsystem.api.core.IndexFilter;
import org.genericsystem.api.core.Snapshot;
import org.genericsystem.defaults.DefaultConfig.NonHeritableProperty;
-import org.genericsystem.defaults.tools.BindingsTools;
import org.genericsystem.defaults.tools.InheritanceComputer;
-import org.genericsystem.defaults.tools.ObservableInheritanceComputer;
+import io.reactivex.Observable;
import javafx.beans.binding.Bindings;
-import javafx.beans.binding.ListBinding;
import javafx.beans.value.ObservableValue;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
/**
* @author Nicolas Feybesse
@@ -82,17 +77,21 @@ default Snapshot getAttributes(T attribute) {
if (nonHeritableProperty == null || attribute.inheritsFrom(nonHeritableProperty) || attribute.isInheritanceEnabled())
return new Snapshot() {
+ InheritanceComputer inheritanceComputer = new InheritanceComputer<>((T) DefaultCompositesInheritance.this, attribute, ApiStatics.STRUCTURAL);
+
@Override
public Stream unfilteredStream() {
- return new InheritanceComputer<>((T) DefaultCompositesInheritance.this, attribute, ApiStatics.STRUCTURAL).inheritanceStream();
+ return inheritanceComputer.inheritanceStream();
}
@Override
- public ObservableList toObservableList() {
- T nonHeritableProperty = getKey(NonHeritableProperty.class, ApiStatics.NO_POSITION);
- if (nonHeritableProperty == null || attribute.inheritsFrom(nonHeritableProperty) || attribute.isInheritanceEnabled())
- return BindingsTools.createMinimalUnitaryChangesBinding(new ObservableInheritanceComputer<>((T) DefaultCompositesInheritance.this, attribute, ApiStatics.STRUCTURAL));
- return getComposites().toObservableList().filtered(holder -> holder.isSpecializationOf(attribute) && holder.getLevel() == ApiStatics.STRUCTURAL);
+ public Observable getAddsObservable() {
+ return inheritanceComputer.getAddsObservable();
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return inheritanceComputer.getRemovesObservable();
}
};
return getComposites().filter(new IndexFilter(FiltersBuilder.IS_SPECIALIZATION_OF, attribute)).filter(new IndexFilter(FiltersBuilder.HAS_LEVEL, ApiStatics.STRUCTURAL));
@@ -144,17 +143,21 @@ default Snapshot getHolders(T attribute) {
if (nonHeritableProperty == null || attribute.inheritsFrom(nonHeritableProperty) || attribute.isInheritanceEnabled())
return new Snapshot() {
+ InheritanceComputer inheritanceComputer = new InheritanceComputer<>((T) DefaultCompositesInheritance.this, attribute, ApiStatics.CONCRETE);
+
@Override
public Stream unfilteredStream() {
- return new InheritanceComputer<>((T) DefaultCompositesInheritance.this, attribute, ApiStatics.CONCRETE).inheritanceStream();
+ return inheritanceComputer.inheritanceStream();
}
@Override
- public ObservableList toObservableList() {
- T nonHeritableProperty = getKey(NonHeritableProperty.class, ApiStatics.NO_POSITION);
- if (nonHeritableProperty == null || attribute.inheritsFrom(nonHeritableProperty) || attribute.isInheritanceEnabled())
- return BindingsTools.createMinimalUnitaryChangesBinding(new ObservableInheritanceComputer<>((T) DefaultCompositesInheritance.this, attribute, ApiStatics.CONCRETE));
- return getComposites().toObservableList().filtered(holder -> holder.isSpecializationOf(attribute) && holder.getLevel() == ApiStatics.CONCRETE);
+ public Observable getAddsObservable() {
+ return inheritanceComputer.getAddsObservable();
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return inheritanceComputer.getRemovesObservable();
}
};
return DefaultCompositesInheritance.this.getComposites().filter(new IndexFilter(FiltersBuilder.IS_SPECIALIZATION_OF, attribute)).filter(new IndexFilter(FiltersBuilder.HAS_LEVEL, ApiStatics.CONCRETE));
@@ -292,18 +295,13 @@ public Stream unfilteredStream() {
}
@Override
- public ObservableList toObservableList() {
- return new ListBinding() {
- private final ObservableList links = getLinks(attribute, value, targets).toObservableList();
- {
- bind(links);
- }
-
- @Override
- protected ObservableList computeValue() {
- return FXCollections.unmodifiableObservableList(FXCollections.observableList(links.stream().map(x -> x.getValue()).collect(Collectors.toList())));
- }
- };
+ public Observable getAddsObservable() {
+ return getLinks(attribute, value, targets).getAddsObservable().map(h -> h.getValue());
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return getLinks(attribute, value, targets).getRemovesObservable().map(h -> h.getValue());
}
};
}
@@ -319,18 +317,13 @@ public Stream unfilteredStream() {
}
@Override
- public ObservableList toObservableList() {
- return new ListBinding() {
- private final ObservableList links = getLinks(attribute, targets).toObservableList();
- {
- bind(links);
- }
-
- @Override
- protected ObservableList computeValue() {
- return FXCollections.unmodifiableObservableList(FXCollections.observableList(links.stream().map(x -> x.getValue()).collect(Collectors.toList())));
- }
- };
+ public Observable getAddsObservable() {
+ return getLinks(attribute, targets).getAddsObservable().map(h -> h.getValue());
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return getLinks(attribute, targets).getRemovesObservable().map(h -> h.getValue());
}
};
}
@@ -345,19 +338,13 @@ public Stream unfilteredStream() {
}
@Override
- public ObservableList toObservableList() {
- return new ListBinding() {
- private final ObservableList holders = getHolders(attribute, pos).toObservableList();
- {
- bind(holders);
- }
-
- @Override
- protected ObservableList computeValue() {
- return FXCollections.unmodifiableObservableList(FXCollections.observableList(holders.stream().map(x -> x.getValue()).collect(Collectors.toList())));
-
- }
- };
+ public Observable getAddsObservable() {
+ return getHolders(attribute, pos).getAddsObservable().map(h -> h.getValue());
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return getHolders(attribute, pos).getRemovesObservable().map(h -> h.getValue());
}
};
}
diff --git a/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultDependencies.java b/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultDependencies.java
index 0c56d03bf..6309702bf 100644
--- a/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultDependencies.java
+++ b/gs-defaults/src/main/java/org/genericsystem/defaults/DefaultDependencies.java
@@ -13,10 +13,9 @@
import org.genericsystem.api.core.IGeneric;
import org.genericsystem.api.core.IndexFilter;
import org.genericsystem.api.core.Snapshot;
-import org.genericsystem.defaults.tools.BindingsTools;
+import org.genericsystem.defaults.tools.RxJavaHelpers;
-import javafx.beans.Observable;
-import javafx.collections.ObservableList;
+import io.reactivex.Observable;
/**
* @author Nicolas Feybesse
@@ -124,8 +123,17 @@ public Stream unfilteredStream() {
}
@Override
- public ObservableList toObservableList() {
- return BindingsTools.createMinimalUnitaryChangesBinding(getInheritings().toObservableList(), () -> getSubInheritings().toList(), g -> new Observable[] { g.getSubInheritings().toObservableList() });
+ public Observable getAddsObservable() {
+ return Observable.merge(getInheritings().getAddsObservable(),
+ Observable.fromIterable(getInheritings()).flatMap(g -> g.getSubInheritings().getAddsObservable()),
+ RxJavaHelpers.additionsOf(getInheritings().toObservableList()).flatMap(g -> g.getSubInheritings().getAddsObservable())).distinct();
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return Observable.merge(getInheritings().getRemovesObservable(),
+ Observable.fromIterable(getInheritings()).flatMap(g -> g.getSubInheritings().getRemovesObservable()),
+ RxJavaHelpers.additionsOf(getInheritings().toObservableList()).flatMap(g -> g.getSubInheritings().getRemovesObservable())).distinct();
}
};
}
@@ -140,8 +148,15 @@ public Stream unfilteredStream() {
}
@Override
- public ObservableList toObservableList() {
- return BindingsTools.createMinimalUnitaryChangesBinding(getSubInheritings().toObservableList(), () -> getSubInstances().toList(), g -> new Observable[] { g.getInstances().toObservableList() });
+ public Observable getAddsObservable() {
+ return Observable.merge(Observable.fromIterable(getSubInheritings()).flatMap(g -> g.getInstances().getAddsObservable()),
+ RxJavaHelpers.additionsOf(getSubInheritings().toObservableList()).flatMap(g -> g.getInstances().getAddsObservable()));
+ }
+
+ @Override
+ public Observable getRemovesObservable() {
+ return Observable.merge(Observable.fromIterable(getSubInheritings()).flatMap(g -> g.getInstances().getRemovesObservable()),
+ RxJavaHelpers.additionsOf(getSubInheritings().toObservableList()).flatMap(g -> g.getInstances().getRemovesObservable()));
}
};
}
diff --git a/gs-defaults/src/main/java/org/genericsystem/defaults/tools/InheritanceComputer.java b/gs-defaults/src/main/java/org/genericsystem/defaults/tools/InheritanceComputer.java
index 78fa2e3b1..1bee91877 100644
--- a/gs-defaults/src/main/java/org/genericsystem/defaults/tools/InheritanceComputer.java
+++ b/gs-defaults/src/main/java/org/genericsystem/defaults/tools/InheritanceComputer.java
@@ -6,13 +6,17 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.genericsystem.api.core.FiltersBuilder;
import org.genericsystem.api.core.IndexFilter;
+import org.genericsystem.api.core.Snapshot;
import org.genericsystem.defaults.DefaultGeneric;
+import io.reactivex.Observable;
+
/**
* @author Nicolas Feybesse
*
@@ -21,28 +25,54 @@
public class InheritanceComputer> {
private final Map> inheritingsCache = new HashMap<>();
+ private final Map> addsCache = new HashMap<>();
+ private final Map> removesCache = new HashMap<>();
private final Set overridden = new HashSet<>();
private final T base;
private final T origin;
private final int level;
+ private final Predicate inheritingsFilter;
public InheritanceComputer(T base, T origin, int level) {
this.base = base;
this.origin = origin;
this.level = level;
+ inheritingsFilter = holder -> !overridden.contains(holder) && !holder.equals(origin) && holder.getLevel() == level;
}
public Stream inheritanceStream() {
- return getInheringsStream(base).filter(holder -> !overridden.contains(holder) && !holder.equals(origin) && holder.getLevel() == level);
+ return getInheritingsStream(base).filter(holder -> inheritingsFilter.test(holder));
+ }
+
+ public Observable getAddsObservable() {
+ return getAddsObservable(base).filter(holder -> inheritingsFilter.test(holder));
+ }
+
+ public Observable getRemovesObservable() {
+ return getRemovesObservable(base).filter(holder -> inheritingsFilter.test(holder));
}
- private Stream getInheringsStream(T superVertex) {
+ private Stream getInheritingsStream(T superVertex) {
Collection result = inheritingsCache.get(superVertex);
if (result == null)
inheritingsCache.put(superVertex, result = buildInheritings(superVertex).inheritanceStream().collect(Collectors.toList()));
return result.stream();
- // return new Inheritings(superVertex).inheritanceStream();
+ // return new Inheritings(superVertex).inheritanceStream();
+ }
+
+ private Observable getAddsObservable(T superVertex) {
+ Observable result = addsCache.get(superVertex);
+ if (result == null)
+ addsCache.put(superVertex, result = buildInheritings(superVertex).inheritanceStreamAdds());
+ return result;
+ }
+
+ private Observable getRemovesObservable(T superVertex) {
+ Observable result = removesCache.get(superVertex);
+ if (result == null)
+ removesCache.put(superVertex, result = buildInheritings(superVertex).inheritanceStreamRemoves());
+ return result;
}
protected Inheritings buildInheritings(T superVertex) {
@@ -57,10 +87,6 @@ protected Inheritings(T localBase) {
this.localBase = localBase;
}
- private Stream inheritanceStream() {
- return fromAboveStream().flatMap(holder -> getStream(holder)).distinct();
- }
-
private boolean hasIntermediateSuperOrIsMeta() {
return localBase.isMeta() || localBase.getSupers().stream().filter(next -> localBase.getMeta().equals(next.getMeta())).count() != 0;
}
@@ -69,25 +95,71 @@ private Stream metaAndSupersStream() {
return Stream.concat(hasIntermediateSuperOrIsMeta() ? Stream.empty() : Stream.of(localBase.getMeta()), localBase.getSupers().stream()).distinct();
}
+ private Stream inheritanceStream() {
+ return fromAboveStream().flatMap(holder -> getStream(holder)).distinct();
+ }
+
+ private Observable inheritanceStreamAdds() {
+ return Observable.merge(fromAboveAdds().flatMap(holder -> getObservable(getStream(holder))).distinct(),
+ Observable.merge(fromAboveAdds(), getObservable(fromAboveStream())).flatMap(holder -> getStreamAdds(holder)).distinct()).distinct();
+ }
+
+ private Observable inheritanceStreamRemoves() {
+ return Observable.merge(Observable.merge(fromAboveAdds(), getObservable(fromAboveStream())).flatMap(holder -> getStreamRemoves(holder)).distinct(),
+ fromAboveRemoves().flatMap(holder -> getObservable(getStream(holder))).distinct()).distinct();
+ }
+
private Stream fromAboveStream() {
- return localBase.isRoot() ? Stream.of(origin) : metaAndSupersStream().flatMap(InheritanceComputer.this::getInheringsStream).distinct();
+ return localBase.isRoot() ? Stream.of(origin) : metaAndSupersStream().flatMap(InheritanceComputer.this::getInheritingsStream).distinct();
+ }
+
+ private Observable fromAboveAdds() {
+ return localBase.isRoot() ? Observable.never() : getObservable(metaAndSupersStream()).flatMap(InheritanceComputer.this::getAddsObservable).distinct();
+ }
+
+ private Observable fromAboveRemoves() {
+ return localBase.isRoot() ? Observable.never() : getObservable(metaAndSupersStream()).flatMap(InheritanceComputer.this::getRemovesObservable).distinct();
+ }
+
+ private Stream getIndexStream(T holder) {
+ return Stream.concat(holder.getLevel() < level ? compositesByMeta(holder).stream() : Stream.empty(), compositesBySuper(holder).stream());
+ }
+
+ private Observable getIndexStreamAdds(T holder) {
+ return Observable.merge(holder.getLevel() < level ? compositesByMeta(holder).getAddsObservable() : Observable.never(), compositesBySuper(holder).getAddsObservable());
+ }
+
+ private Observable getIndexStreamRemoves(T holder) {
+ return Observable.merge(holder.getLevel() < level ? compositesByMeta(holder).getRemovesObservable() : Observable.never(), compositesBySuper(holder).getRemovesObservable());
}
private Stream getStream(final T holder) {
- if (compositesBySuper(holder).count() != 0)
+ if (compositesBySuper(holder).stream().count() != 0)
overridden.add(holder);
- Stream indexStream = Stream.concat(holder.getLevel() < level ? compositesByMeta(holder) : Stream.empty(), compositesBySuper(holder));
- return Stream.concat(Stream.of(holder), indexStream.flatMap(x -> getStream(x)).distinct());
+ return Stream.concat(Stream.of(holder), getIndexStream(holder).flatMap(x -> getStream(x)).distinct());
}
- protected Stream compositesByMeta(T holder) {
- return localBase.getDependencies().filter(Arrays.asList(new IndexFilter(FiltersBuilder.COMPOSITES, localBase), new IndexFilter(FiltersBuilder.HAS_META, holder))).stream();
+ private Observable getStreamAdds(T holder) {
+ Observable indexAdds = getIndexStreamAdds(holder);
+ return Observable.merge(Observable.merge(getObservable(getIndexStream(holder)), indexAdds).flatMap(x -> getStreamAdds(x)).distinct(),
+ indexAdds.flatMap(x -> getObservable(getStream(x))).distinct()).distinct();
}
- protected Stream compositesBySuper(T holder) {
- return localBase.getDependencies().filter(Arrays.asList(new IndexFilter(FiltersBuilder.COMPOSITES, localBase), new IndexFilter(FiltersBuilder.HAS_SUPER, holder))).stream();
+ private Observable getStreamRemoves(T holder) {
+ return Observable.merge(getIndexStreamRemoves(holder).flatMap(x -> getObservable(getStream(x))).distinct(),
+ Observable.merge(getObservable(getIndexStream(holder)), getIndexStreamAdds(holder)).flatMap(x -> getStreamRemoves(x)).distinct()).distinct();
}
- }
+ private Snapshot compositesByMeta(T holder) {
+ return localBase.getDependencies().filter(Arrays.asList(new IndexFilter(FiltersBuilder.COMPOSITES, localBase), new IndexFilter(FiltersBuilder.HAS_META, holder)));
+ }
+ private Snapshot compositesBySuper(T holder) {
+ return localBase.getDependencies().filter(Arrays.asList(new IndexFilter(FiltersBuilder.COMPOSITES, localBase), new IndexFilter(FiltersBuilder.HAS_SUPER, holder)));
+ }
+
+ private Observable getObservable(Stream stream) {
+ return Observable.fromIterable(stream.collect(Collectors.toList()));
+ }
+ }
}
diff --git a/gs-defaults/src/main/java/org/genericsystem/defaults/tools/ObservableInheritanceComputer.java b/gs-defaults/src/main/java/org/genericsystem/defaults/tools/ObservableInheritanceComputer.java
deleted file mode 100644
index eb5a012a1..000000000
--- a/gs-defaults/src/main/java/org/genericsystem/defaults/tools/ObservableInheritanceComputer.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.genericsystem.defaults.tools;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.genericsystem.api.core.FiltersBuilder;
-import org.genericsystem.api.core.IndexFilter;
-import org.genericsystem.defaults.DefaultGeneric;
-
-import javafx.beans.Observable;
-import javafx.beans.binding.ListBinding;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-
-/**
- * @author Nicolas Feybesse
- *
- * @param
- */
-public class ObservableInheritanceComputer> extends ListBinding {
-
- List invalidators = new ArrayList<>();
-
- private final T base;
- private final T origin;
- private final int level;
-
- public ObservableInheritanceComputer(T base, T origin, int level) {
- this.base = base;
- this.origin = origin;
- this.level = level;
- }
-
- @Override
- protected ObservableList computeValue() {
- invalidators.forEach(ObservableInheritanceComputer.this::unbind);
- List newInvalidators = new ArrayList<>();
- List internal = new InheritanceComputer(base, origin, level) {
-
- @Override
- protected Inheritings buildInheritings(T superVertex) {
- return new Inheritings(superVertex) {
- @Override
- protected Stream compositesByMeta(T holder) {
- ObservableList filtered = localBase.getComposites().filter(new IndexFilter(FiltersBuilder.HAS_META, holder)).toObservableList();
- newInvalidators.add(filtered);
- bind(filtered);
- return super.compositesByMeta(holder);
- }
-
- @Override
- protected Stream compositesBySuper(T holder) {
- ObservableList filtered = localBase.getComposites().filter(new IndexFilter(FiltersBuilder.HAS_SUPER, holder)).toObservableList();
- newInvalidators.add(filtered);
- bind(filtered);
- return super.compositesBySuper(holder);
- }
- };
-
- };
- }.inheritanceStream().collect(Collectors.toList());
- invalidators = newInvalidators;
- return FXCollections.observableList(internal);
- }
-}
diff --git a/gs-defaults/src/main/java/org/genericsystem/defaults/tools/RxJavaHelpers.java b/gs-defaults/src/main/java/org/genericsystem/defaults/tools/RxJavaHelpers.java
new file mode 100644
index 000000000..cda0efe05
--- /dev/null
+++ b/gs-defaults/src/main/java/org/genericsystem/defaults/tools/RxJavaHelpers.java
@@ -0,0 +1,108 @@
+package org.genericsystem.defaults.tools;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.rxjavafx.subscriptions.JavaFxSubscriptions;
+import javafx.collections.ListChangeListener;
+import javafx.collections.MapChangeListener;
+import javafx.collections.ObservableList;
+import javafx.collections.ObservableMap;
+
+public class RxJavaHelpers {
+ /**
+ * Creates an observable that emits all additions to an ObservableList.
+ *
+ * @param source The source ObservableList for the item add events.
+ * @return An Observable emitting items added to the ObservableList.
+ */
+ public static Observable additionsOf(final ObservableList source) {
+ return fromObservableListAdds(source);
+ }
+
+ /**
+ * Creates an observable that emits all removals from an ObservableList.
+ *
+ * @param source The source ObservableList for the item removal events.
+ * @return An Observable emitting items removed from the ObservableList.
+ */
+ public static Observable removalsOf(final ObservableList source) {
+ return fromObservableListRemovals(source);
+ }
+
+ /**
+ * Creates an observable that emits all additions to an ObservableMap.
+ *
+ * @param source The source ObservableMap for the item add events.
+ * @return An Observable emitting Entry items added to the ObservableMap.
+ */
+ public static Observable> additionsOf(final ObservableMap source) {
+ return fromObservableMapAdds(source);
+ }
+
+ /**
+ * Creates an observable that emits all removals from an ObservableMap.
+ *
+ * @param source The source ObservableMap for the item removal events.
+ * @return An Observable emitting Entry items removed from the ObservableMap.
+ */
+ public static Observable> removalsOf(final ObservableMap source) {
+ return fromObservableMapRemovals(source);
+ }
+
+ public static Observable fromObservableListAdds(final ObservableList source) {
+
+ return Observable.create((ObservableOnSubscribe) subscriber -> {
+
+ ListChangeListener listener = c -> {
+ while (c.next())
+ if (c.wasAdded())
+ c.getAddedSubList().forEach(subscriber::onNext);
+ };
+ source.addListener(listener);
+ subscriber.setDisposable(JavaFxSubscriptions.unsubscribeInEventDispatchThread(() -> source.removeListener(listener)));
+ });
+ }
+
+ public static Observable fromObservableListRemovals(final ObservableList source) {
+
+ return Observable.create((ObservableOnSubscribe) subscriber -> {
+ ListChangeListener listener = c -> {
+ while (c.next())
+ if (c.wasRemoved())
+ c.getRemoved().forEach(subscriber::onNext);
+ };
+ source.addListener(listener);
+ subscriber.setDisposable(JavaFxSubscriptions.unsubscribeInEventDispatchThread(() -> source.removeListener(listener)));
+ });
+ }
+
+ public static Observable> fromObservableMapAdds(final ObservableMap source) {
+
+ return Observable.create((ObservableOnSubscribe>) subscriber -> {
+
+ MapChangeListener listener = c -> {
+ if (c.wasAdded())
+ subscriber.onNext(new SimpleEntry(c.getKey(),c.getValueAdded()));
+ };
+ source.addListener(listener);
+ subscriber.setDisposable(JavaFxSubscriptions.unsubscribeInEventDispatchThread(() -> source.removeListener(listener)));
+ });
+ }
+
+ public static Observable> fromObservableMapRemovals(final ObservableMap source) {
+
+ return Observable.create((ObservableOnSubscribe>) subscriber -> {
+
+ MapChangeListener listener = c -> {
+ if (c.wasRemoved())
+ subscriber.onNext(new SimpleEntry(c.getKey(),c.getValueRemoved()));
+ };
+ source.addListener(listener);
+ subscriber.setDisposable(JavaFxSubscriptions.unsubscribeInEventDispatchThread(() -> source.removeListener(listener)));
+ });
+ }
+}
\ No newline at end of file
diff --git a/gs-kernel/src/test/java/org/genericsystem/cache/UpdateTest.java b/gs-kernel/src/test/java/org/genericsystem/cache/UpdateTest.java
index 45ef90966..8e3b0562d 100644
--- a/gs-kernel/src/test/java/org/genericsystem/cache/UpdateTest.java
+++ b/gs-kernel/src/test/java/org/genericsystem/cache/UpdateTest.java
@@ -3,7 +3,6 @@
import org.genericsystem.api.core.ApiStatics;
import org.genericsystem.api.core.exceptions.MetaRuleConstraintViolationException;
import org.genericsystem.common.Generic;
-import org.genericsystem.defaults.tools.ObservableInheritanceComputer;
import org.genericsystem.kernel.Engine;
import org.testng.annotations.Test;
@@ -145,7 +144,7 @@ public void testInverseObservation() {
Generic red = color.addInstance("Red");
Generic green = color.addInstance("Green");
Generic audiRed = audi.addLink(carColor, "audiRed", red);
- ObservableList greenCars = new ObservableInheritanceComputer<>(green, carColor, ApiStatics.CONCRETE);
+ ObservableList greenCars = green.getHolders(carColor).toObservableList();
assert greenCars.isEmpty();
System.gc();
// Generic audiGreen = audiRed.updateComponent(green, ApiStatics.TARGET_POSITION);