PropertyContainerConnector.java
01 /*
02  * Copyright 2014-2016 the original author or authors.
03  *
04  * Licensed under the Apache License, Version 2.0 (the "License");
05  * you may not use this file except in compliance with the License.
06  * You may obtain a copy of the License at
07  *
08  *     http://www.apache.org/licenses/LICENSE-2.0
09  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package griffon.plugins.glazedlists.javafx;
17 
18 import ca.odell.glazedlists.ObservableElementList;
19 import javafx.beans.property.Property;
20 import javafx.beans.value.ChangeListener;
21 import javafx.beans.value.ObservableValue;
22 
23 import javax.annotation.Nonnull;
24 import java.lang.ref.WeakReference;
25 import java.util.EventListener;
26 
27 import static java.util.Arrays.binarySearch;
28 import static java.util.Arrays.copyOf;
29 import static java.util.Arrays.sort;
30 import static java.util.Objects.requireNonNull;
31 
32 /**
33  @author Andres Almiray
34  */
35 public class PropertyContainerConnector<T extends PropertyContainer> implements ObservableElementList.Connector<T> {
36     private static final String[] EMPTY_STRING_ARRAY = new String[0];
37     private ObservableElementList<? extends PropertyContainer> list;
38     private final String[] propertyNames;
39 
40     public PropertyContainerConnector() {
41         this.propertyNames = EMPTY_STRING_ARRAY;
42     }
43 
44     public PropertyContainerConnector(@Nonnull String[] propertyNames) {
45         requireNonNull(propertyNames, "Argument 'propertyNames' must not be null");
46         this.propertyNames = copyOf(propertyNames, propertyNames.length);
47         sort(this.propertyNames);
48     }
49 
50     @Override
51     @SuppressWarnings("unchecked")
52     public EventListener installListener(T element) {
53         ElementChangeHandler ecl = new ElementChangeHandler<>(element);
54         for (Property<?> property : element.properties()) {
55             if (matches(property.getName())) {
56                 property.addListener(ecl);
57             }
58         }
59         return ecl;
60     }
61 
62     @Override
63     @SuppressWarnings("unchecked")
64     public void uninstallListener(T element, EventListener listener) {
65         if (listener instanceof ChangeListener) {
66             ChangeListener cl = (ChangeListenerlistener;
67             for (Property<?> property : element.properties()) {
68                 if (matches(property.getName())) {
69                     property.removeListener(cl);
70                 }
71             }
72         }
73     }
74 
75     private boolean matches(@Nonnull String propertyName) {
76         return propertyNames.length == || binarySearch(propertyNames, propertyName> -1;
77     }
78 
79     @Override
80     public void setObservableElementList(ObservableElementList<? extends T> list) {
81         this.list = list;
82     }
83 
84     private class ElementChangeHandler<E> implements ElementChangeListener<E> {
85         private final WeakReference<E> element;
86 
87         private ElementChangeHandler(@Nonnull E element) {
88             this.element = new WeakReference<>(element);
89         }
90 
91         @Override
92         public void changed(ObservableValue<? extends E> observable, E oldValue, E newValue) {
93             list.elementChanged(element.get());
94         }
95     }
96 }