Skip to content

Commit

Permalink
Change getProperty
Browse files Browse the repository at this point in the history
Improve properties access
  • Loading branch information
nfeybesse committed Jul 21, 2016
1 parent 5b3b609 commit d1c07d3
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public CarColorApp(AbstractRoot engine, ServerWebSocket webSocket) {
new GenericSection(this, FlexDirection.COLUMN) {
{
addStyleClass("modal");
bindStyle(ReactorStatics.DISPLAY, ReactorStatics.DISPLAY,
model -> Bindings.createStringBinding(() -> getProperty(ReactorStatics.SELECTION, model).getValue() != null ? "flex" : "none", this.getProperty(ReactorStatics.SELECTION, model)));
bindStyle(ReactorStatics.DISPLAY, ReactorStatics.DISPLAY, model -> Bindings.createStringBinding(
() -> getProperty(ReactorStatics.SELECTION, model).getValue() != null ? "flex" : "none",
this.getProperty(ReactorStatics.SELECTION, model)));

new GenericSection(this, FlexDirection.COLUMN) {
{
Expand Down
30 changes: 22 additions & 8 deletions gs-reactor/src/main/java/org/genericsystem/reactor/Model.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.genericsystem.reactor;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -28,7 +29,8 @@ public class Model {
@Override
public Map<String, ObservableValue<Object>> get(Object key) {
Map<String, ObservableValue<Object>> properties = super.get(key);
if (properties == null)
if (properties == null) {
assert viewContextsMap.keySet().contains(key);
put((Tag) key, properties = new HashMap<String, ObservableValue<Object>>() {
@Override
public ObservableValue<Object> get(Object key) {
Expand All @@ -38,6 +40,7 @@ public ObservableValue<Object> get(Object key) {
return property;
};
});
}
return properties;
};
};
Expand All @@ -55,25 +58,36 @@ public <SUBMODEL extends Model> List<SUBMODEL> getSubContexts(Tag<SUBMODEL> tag)
return (List<SUBMODEL>) subContextsMap.get(tag);
}

public Map<Tag<?>, Map<String, ObservableValue<Object>>> getProperties() {
return propertiesMap;
public boolean containsProperty(Tag<?> tag, String propertyName) {
return propertiesMap.containsKey(tag) ? propertiesMap.get(tag).containsKey(propertyName) : false;
}

public <T> ObservableValue<T> getObservableValue(Tag<?> tag, String propertyName) {
return (ObservableValue<T>) propertiesMap.get(tag).get(propertyName);
}

public <T> ObservableValue<T> getObservableValue(Tag<?> tag, String name) {
return (ObservableValue<T>) propertiesMap.get(tag).get(name);
public <T> Property<T> getProperty(Tag<?> tag, String propertyName) {
return (Property<T>) propertiesMap.get(tag).get(propertyName);
}

public <T> Property<T> getProperty(Tag<?> tag, String name) {
return (Property<T>) propertiesMap.get(tag).get(name);
public Collection<Map<String, ObservableValue<Object>>> getPropertiesMaps() {
return propertiesMap.values();
}

// Avoid direct access to map
@Deprecated
public Map<Tag<?>, Map<String, ObservableValue<Object>>> getProperties() {
return propertiesMap;
}

public void storeProperty(Tag tag, String propertyName, ObservableValue value) {
assert viewContextsMap.keySet().contains(tag);
if (propertiesMap.get(tag).containsKey(propertyName))
throw new IllegalStateException("Unable to store an already used property : " + propertyName);
propertiesMap.get(tag).put(propertyName, value);
}

public List<Model> allSubContexts() {
public List<Model> subContexts() {
return subContextsMap.values().stream().flatMap(list -> list.stream()).collect(Collectors.toList());
}

Expand Down
92 changes: 57 additions & 35 deletions gs-reactor/src/main/java/org/genericsystem/reactor/Tag.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ public <NODE extends HtmlDomNode> void bindOptionalStyleClass(String styleClass,
});
}

public <NODE extends HtmlDomNode> void bindOptionalStyleClass(String styleClass, String modelPropertyName, Function<M, ObservableValue<Boolean>> applyOnModel) {
public <NODE extends HtmlDomNode> void bindOptionalStyleClass(String styleClass, String modelPropertyName,
Function<M, ObservableValue<Boolean>> applyOnModel) {
storeProperty(modelPropertyName, applyOnModel);
bindOptionalStyleClass(styleClass, modelPropertyName);
}
Expand All @@ -127,8 +128,8 @@ public void forEach(ObservableListExtractor observableListExtractor) {

public <MODEL extends Model> void forEach(Function<MODEL, ObservableList<M>> applyOnModel) {
metaBinding = (childElement, viewContext) -> {
M model = (M) viewContext.getModelContext();
ObservableList<M> models = applyOnModel.apply((MODEL) model);
MODEL model = viewContext.getModelContext();
ObservableList<M> models = applyOnModel.apply(model);
viewContext.getModelContext().setSubContexts(childElement, new TransformationObservableList<M, MODEL>(models, (index, subModel) -> {
subModel.parent = model;
viewContext.createViewContextChild(index, subModel, childElement);
Expand All @@ -141,23 +142,25 @@ public void forEach(StringExtractor stringExtractor, ObservableListExtractor obs
metaBinding = (childElement, viewContext) -> {
GenericModel model = (GenericModel) viewContext.getModelContext();
ObservableList<Generic> generics = observableListExtractor.apply(model.getGenerics());
TransformationObservableList<Generic, GenericModel> subModels = new TransformationObservableList<Generic, GenericModel>(generics, (index, generic) -> {
// System.out.println("Change detected on : " + System.identityHashCode(generics) + " newValue : " + generic.info());
GenericModel duplicate = new GenericModel(model, GenericModel.addToGenerics(generic, model.getGenerics()), stringExtractor);
viewContext.createViewContextChild(index, duplicate, childElement);
return duplicate;
}, m -> {
assert !model.destroyed;
assert !m.destroyed;
// TODO unregister viewContext before removing in list ?
m.destroy();
});
TransformationObservableList<Generic, GenericModel> subModels = new TransformationObservableList<Generic, GenericModel>(generics,
(index, generic) -> {
// System.out.println("Change detected on : " + System.identityHashCode(generics) + " newValue : " + generic.info());
GenericModel duplicate = new GenericModel(model, GenericModel.addToGenerics(generic, model.getGenerics()), stringExtractor);
viewContext.createViewContextChild(index, duplicate, childElement);
return duplicate;
}, m -> {
assert !model.destroyed;
assert !m.destroyed;
// TODO unregister viewContext before removing in list ?
m.destroy();
});
model.setSubContexts(childElement, subModels);
subModels.addListener((ListChangeListener<? super GenericModel>) change -> {
Property<GenericModel> selection = getProperty(ReactorStatics.SELECTION, model);
if (selection != null) {
if (getProperty(ReactorStatics.SELECTION_INDEX, model) != null) {
int selectionShift = getProperty(ReactorStatics.SELECTION_SHIFT, model) != null ? (Integer) getProperty(ReactorStatics.SELECTION_SHIFT, model).getValue() : 0;
int selectionShift = getProperty(ReactorStatics.SELECTION_SHIFT, model) != null ? (Integer) getProperty(ReactorStatics.SELECTION_SHIFT,
model).getValue() : 0;
Number oldIndex = (Number) getProperty(ReactorStatics.SELECTION_INDEX, model).getValue();
Number newIndex = subModels.indexOf(selection.getValue()) + selectionShift;
if (newIndex != oldIndex)
Expand All @@ -177,18 +180,29 @@ public <T> Property<T> getProperty(String propertyName, Model model) {
}

private <T> Property<T> getProperty(String propertyName, Model[] model) {
if (model[0].getProperties().get(this).containsKey(propertyName))
return (Property<T>) model[0].getProperty(this, propertyName);
Model initModel = model[0];
Tag<M> tag_ = this.getParent();
while (model[0] != null && tag_ != null && !model[0].getProperties().get(tag_).containsKey(propertyName)) {
if (tag_.getParent() != null && tag_.getParent().metaBinding != null)
Tag<?> tag = this;
while (tag != null && model[0] != null) {
if (model[0].containsProperty(tag, propertyName))
return model[0].getProperty(tag, propertyName);
if (tag.metaBinding != null && model[0].getViewContext(tag.getParent()) == null)
model[0] = model[0].getParent();
tag_ = tag_.getParent();
tag = tag.getParent();
}
return model[0] != null && tag_ != null ? (Property<T>) model[0].getProperty(tag_, propertyName) : null;
return null;
}

// private <T> Property<T> getProperty(String propertyName, Model[] model) {
// if (model[0].containsProperty(this, propertyName))
// return model[0].getProperty(this, propertyName);
// Tag<M> tag = this.getParent();
// while (model[0] != null && tag != null && !model[0].containsProperty(tag, propertyName)) {
// if (tag.getParent() != null && tag.getParent().metaBinding != null)
// model[0] = model[0].getParent();
// tag = tag.getParent();
// }
// return model[0] != null && tag != null ? model[0].getProperty(tag, propertyName) : null;
// }

public <MODEL extends GenericModel> void select_(Function<MODEL, ObservableValue<M>> applyOnModel) {
select_(null, applyOnModel);
}
Expand All @@ -206,13 +220,16 @@ public <MODEL extends GenericModel> void select_(StringExtractor stringExtractor
};
observableValue.addListener(listener);
listener.changed(observableValue, null, observableValue.getValue());
model.setSubContexts(childElement, new TransformationObservableList<M, MODEL>(subModels, (index, selectedModel) -> {
Generic[] gs = ((GenericModel) selectedModel).getGenerics();
// assert Arrays.equals(gs, gs2) : Arrays.toString(gs) + " vs " + Arrays.toString(gs2);
GenericModel childModel = new GenericModel(viewContext.getModelContext(), gs, stringExtractor != null ? stringExtractor : ((GenericModel) selectedModel).getStringExtractor());
viewContext.createViewContextChild(index, childModel, childElement);
return (MODEL) childModel;
}, Model::destroy));
model.setSubContexts(
childElement,
new TransformationObservableList<M, MODEL>(subModels, (index, selectedModel) -> {
Generic[] gs = ((GenericModel) selectedModel).getGenerics();
// assert Arrays.equals(gs, gs2) : Arrays.toString(gs) + " vs " + Arrays.toString(gs2);
GenericModel childModel = new GenericModel(model, gs, stringExtractor != null ? stringExtractor : ((GenericModel) selectedModel)
.getStringExtractor());
viewContext.createViewContextChild(index, childModel, childElement);
return (MODEL) childModel;
}, Model::destroy));
};
}

Expand Down Expand Up @@ -250,10 +267,12 @@ protected <SUBMODEL extends GenericModel> void bindBiDirectionalSelection(Tag su
Generic selectedGeneric = ((GenericModel) modelContext).getGeneric();
Optional<SUBMODEL> selectedModel = subContexts.stream().filter(sub -> selectedGeneric.equals(sub.getGeneric())).findFirst();
Property<GenericModel> selection = getProperty(ReactorStatics.SELECTION, modelContext);
int selectionShift = getProperty(ReactorStatics.SELECTION_SHIFT, modelContext) != null ? (Integer) getProperty(ReactorStatics.SELECTION_SHIFT, modelContext).getValue() : 0;
int selectionShift = getProperty(ReactorStatics.SELECTION_SHIFT, modelContext) != null ? (Integer) getProperty(ReactorStatics.SELECTION_SHIFT,
modelContext).getValue() : 0;
selection.setValue(selectedModel.isPresent() ? selectedModel.get() : null);
Property<Number> selectionIndex = getProperty(ReactorStatics.SELECTION_INDEX, modelContext);
BidirectionalBinding.bind(selectionIndex, selection, number -> number.intValue() - selectionShift >= 0 ? (GenericModel) subContexts.get(number.intValue() - selectionShift) : null,
BidirectionalBinding.bind(selectionIndex, selection,
number -> number.intValue() - selectionShift >= 0 ? (GenericModel) subContexts.get(number.intValue() - selectionShift) : null,
genericModel -> subContexts.indexOf(genericModel) + selectionShift);
});
}
Expand All @@ -272,11 +291,13 @@ private void bindBiDirectionalMapElement(String propertyName, String name, Funct
bindBiDirectionalMapElement(propertyName, name, getMap, ApiStatics.STRING_CONVERTERS.get(String.class));
}

private <T extends Serializable> void bindBiDirectionalMapElement(String propertyName, String name, Function<Model, ObservableMap<String, String>> getMap, StringConverter<T> stringConverter) {
private <T extends Serializable> void bindBiDirectionalMapElement(String propertyName, String name, Function<Model, ObservableMap<String, String>> getMap,
StringConverter<T> stringConverter) {
bindBiDirectionalMapElement(propertyName, name, getMap, model -> stringConverter);
}

private <T extends Serializable> void bindBiDirectionalMapElement(String propertyName, String name, Function<Model, ObservableMap<String, String>> getMap, Function<M, StringConverter<T>> getStringConverter) {
private <T extends Serializable> void bindBiDirectionalMapElement(String propertyName, String name, Function<Model, ObservableMap<String, String>> getMap,
Function<M, StringConverter<T>> getStringConverter) {
addPrefixBinding(modelContext -> {
ObservableMap<String, String> map = getMap.apply(modelContext);
StringConverter<T> stringConverter = getStringConverter.apply(modelContext);
Expand Down Expand Up @@ -363,7 +384,8 @@ public <T extends Serializable> void bindBiDirectionalAttribute(String propertyN
bindBiDirectionalMapElement(propertyName, attributeName, model -> model.getObservableAttributes(this), stringConverter);
}

public <T extends Serializable> void bindBiDirectionalAttribute(String propertyName, String attributeName, Function<M, StringConverter<T>> getStringConverter) {
public <T extends Serializable> void bindBiDirectionalAttribute(String propertyName, String attributeName,
Function<M, StringConverter<T>> getStringConverter) {
bindBiDirectionalMapElement(propertyName, attributeName, model -> model.getObservableAttributes(this), getStringConverter);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ private ViewContext(int indexInChildren, ViewContext<?> parent, Model modelConte

}

public Model getModelContext() {
return modelContext;
@SuppressWarnings("unchecked")
public <MODEL extends Model> MODEL getModelContext() {
return (MODEL) modelContext;
}

public ViewContext<?> createViewContextChild(Integer index, Model childModelContext, Tag<?> element) {
Expand All @@ -55,6 +56,7 @@ protected RootViewContext<?> getRootViewContext() {
return parent.getRootViewContext();
}

@SuppressWarnings({ "unchecked" })
public <NODE extends HtmlDomNode> NODE getNode() {
return (NODE) node;
}
Expand Down
33 changes: 18 additions & 15 deletions gs-reactor/src/main/java/org/genericsystem/reactor/Visitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@
import java.util.Map;
import java.util.stream.Collectors;

import org.genericsystem.common.Generic;
import org.genericsystem.reactor.Model.TriFunction;
import org.genericsystem.reactor.model.GenericModel;

import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
import javafx.beans.value.ObservableValue;

import org.genericsystem.common.Generic;
import org.genericsystem.reactor.Model.TriFunction;
import org.genericsystem.reactor.model.GenericModel;

public class Visitor {

public void visit(Model modelContext) {
prefix(modelContext);
for (Model childContext : modelContext.allSubContexts()) { // why all the subcontexts here ?
for (Model childContext : modelContext.subContexts())
visit(childContext);
}
postfix(modelContext);
}

Expand All @@ -38,10 +37,12 @@ public static class HolderVisitor extends Visitor {
@Override
public void prefix(Model model) {
GenericModel gModel = (GenericModel) model;
for (Map<String, ObservableValue<Object>> properties : model.getProperties().values()) {
if (properties.containsKey(ReactorStatics.VALUE) && properties.containsKey(ReactorStatics.ACTION) && properties.get(ReactorStatics.VALUE).getValue() != null && properties.get(ReactorStatics.ACTION).getValue() != null) {
TriFunction<Generic[], Serializable, Generic, Generic> action = (TriFunction<Generic[], Serializable, Generic, Generic>) properties.get(ReactorStatics.ACTION).getValue();
Generic g = action.apply(gModel.getGenerics(), (Serializable) properties.get(ReactorStatics.VALUE).getValue(), newInstance);
for (Map<String, ObservableValue<Object>> tagPropertiesMap : model.getPropertiesMaps()) {
if (tagPropertiesMap.containsKey(ReactorStatics.VALUE) && tagPropertiesMap.containsKey(ReactorStatics.ACTION)
&& tagPropertiesMap.get(ReactorStatics.VALUE).getValue() != null && tagPropertiesMap.get(ReactorStatics.ACTION).getValue() != null) {
TriFunction<Generic[], Serializable, Generic, Generic> action = (TriFunction<Generic[], Serializable, Generic, Generic>) tagPropertiesMap
.get(ReactorStatics.ACTION).getValue();
Generic g = action.apply(gModel.getGenerics(), (Serializable) tagPropertiesMap.get(ReactorStatics.VALUE).getValue(), newInstance);
if (newInstance == null)
newInstance = g;
}
Expand All @@ -51,9 +52,9 @@ public void prefix(Model model) {
@Override
public void postfix(Model model) {
List<Generic> generics = new ArrayList<>();
for (Model subModel : model.allSubContexts())
for (Model subModel : model.subContexts())
for (Tag tag : subModel.getProperties().keySet())
if (subModel.getProperties().get(tag).containsKey(ReactorStatics.SELECTION))
if (subModel.containsProperty(tag, ReactorStatics.SELECTION))
if (subModel.getProperty(tag, ReactorStatics.SELECTION).getValue() != null)
generics.add(((GenericModel) subModel.getProperty(tag, ReactorStatics.SELECTION).getValue()).getGeneric());
if (!generics.isEmpty() && generics.size() + 1 == ((GenericModel) model).getGeneric().getComponents().size()) // test OK?
Expand All @@ -64,7 +65,7 @@ public void postfix(Model model) {
public static class ClearVisitor extends Visitor {
@Override
public void prefix(Model model) {
for (Map<String, ObservableValue<Object>> properties : model.getProperties().values()) {
for (Map<String, ObservableValue<Object>> properties : model.getPropertiesMaps()) {
if (properties.containsKey(ReactorStatics.VALUE))
((Property) properties.get(ReactorStatics.VALUE)).setValue(null);
if (properties.containsKey(ReactorStatics.SELECTION))
Expand All @@ -80,7 +81,8 @@ public static class CheckInputsValidityVisitor extends Visitor {
public CheckInputsValidityVisitor(Model modelContext) {
super();
visit(modelContext);
invalid = Bindings.createBooleanBinding(() -> propertiesInvalid.stream().map(input -> (Boolean) input.getValue()).filter(bool -> bool != null).reduce(false, (a, b) -> a || b), propertiesInvalid.stream().toArray(ObservableValue[]::new));
invalid = Bindings.createBooleanBinding(() -> propertiesInvalid.stream().map(input -> (Boolean) input.getValue()).filter(bool -> bool != null)
.reduce(false, (a, b) -> a || b), propertiesInvalid.stream().toArray(ObservableValue[]::new));
}

public ObservableValue<Boolean> isInvalid() {
Expand All @@ -89,7 +91,8 @@ public ObservableValue<Boolean> isInvalid() {

@Override
public void prefix(Model model) {
propertiesInvalid.addAll(model.getProperties().values().stream().filter(properties -> properties.containsKey(ReactorStatics.INVALID)).map(properties -> properties.get(ReactorStatics.INVALID)).collect(Collectors.toList()));
propertiesInvalid.addAll(model.getPropertiesMaps().stream().filter(properties -> properties.containsKey(ReactorStatics.INVALID))
.map(properties -> properties.get(ReactorStatics.INVALID)).collect(Collectors.toList()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -304,17 +304,7 @@ protected void header() {
new HtmlHyperLink<GenericModel>(this) {
{
bindText(GenericModel::getString);
bindAction(model -> {
GenericModel cm = model;
while (cm != null) {
for (Tag tag : cm.getProperties().keySet())
if (cm.getProperties().get(tag).containsKey(ReactorStatics.SELECTION)) {
cm.getProperty(tag, ReactorStatics.SELECTION).setValue(model);
return;
}
cm = (GenericModel) cm.getParent();
}
});
bindAction(model -> getProperty(ReactorStatics.SELECTION, model).setValue(model));
}
};

Expand Down
Loading

0 comments on commit d1c07d3

Please sign in to comment.