001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.util;
033
034import java.util.Collection;
035
036import org.graphstream.graph.Edge;
037import org.graphstream.graph.Element;
038import org.graphstream.graph.Node;
039
040public class Filters {
041        public static <T extends Element> Filter<T> falseFilter() {
042                return new Filter<T>() {
043                        public boolean isAvailable(T e) {
044                                return false;
045                        }
046                };
047        }
048
049        public static <T extends Element> Filter<T> trueFilter() {
050                return new Filter<T>() {
051                        public boolean isAvailable(T e) {
052                                return true;
053                        }
054                };
055        }
056
057        public static <T extends Element> Filter<T> byAttributeFilter(String key,
058                        Object expectedValue) {
059                return new ByAttributeFilter<T>(key, expectedValue);
060        }
061
062        public static <T extends Element, U extends Element> Filter<Element> separateNodeAndEdgeFilter(
063                        Filter<T> nodeFilter, Filter<U> edgeFilter) {
064                return new SeparateNodeEdgeFilter<T, U>(nodeFilter, edgeFilter);
065        }
066
067        public static <T extends Element, U extends Element> Filter<T> byExtremitiesFilter(
068                        Filter<U> f) {
069                return new ExtremitiesFilter<T, U>(f);
070        }
071
072        public static <T extends Element> Filter<T> byIdFilter(String idPattern) {
073                return new ByIdFilter<T>(idPattern);
074        }
075
076        public static <T extends Element> Filter<T> isContained(
077                        final Collection<? extends T> set) {
078                return new Filter<T>() {
079                        public boolean isAvailable(T e) {
080                                return set.contains(e);
081                        }
082                };
083        }
084
085        public static <T extends Element> Filter<T> isIdContained(
086                        final Collection<String> set) {
087                return new Filter<T>() {
088                        public boolean isAvailable(T e) {
089                                return set.contains(e.getId());
090                        }
091                };
092        }
093
094        public static <T extends Element> Filter<T> and(Filter<T> f1, Filter<T> f2) {
095                return new AndFilter<T>(f1, f2);
096        }
097
098        public static <T extends Element> Filter<T> or(Filter<T> f1, Filter<T> f2) {
099                return new OrFilter<T>(f1, f2);
100        }
101
102        public static <T extends Element> Filter<T> xor(Filter<T> f1, Filter<T> f2) {
103                return new XorFilter<T>(f1, f2);
104        }
105
106        public static <T extends Element> Filter<T> not(Filter<T> f) {
107                return new NotFilter<T>(f);
108        }
109
110        static class ByAttributeFilter<T extends Element> implements Filter<T> {
111
112                protected String key;
113                protected Object value;
114
115                ByAttributeFilter(String key, Object value) {
116                        this.key = key;
117                        this.value = value;
118                }
119
120                public boolean isAvailable(T e) {
121                        return e.hasAttribute(key)
122                                        && (value == null ? e.getAttribute(key) == null : value
123                                                        .equals(e.getAttribute(key)));
124                }
125        }
126
127        static class ByIdFilter<T extends Element> implements Filter<T> {
128                String nodePattern;
129                String edgePattern;
130
131                ByIdFilter(String pattern) {
132                        this(pattern, pattern);
133                }
134
135                ByIdFilter(String nodePattern, String edgePattern) {
136                        this.nodePattern = nodePattern;
137                        this.edgePattern = edgePattern;
138                }
139
140                public boolean isAvailable(Element e) {
141                        if (e instanceof Edge)
142                                return e.getId().matches(edgePattern);
143
144                        return e.getId().matches(nodePattern);
145                }
146        }
147
148        static class SeparateNodeEdgeFilter<T extends Element, U extends Element>
149                        implements Filter<Element> {
150
151                Filter<T> nodeFilter;
152                Filter<U> edgeFilter;
153
154                SeparateNodeEdgeFilter(Filter<T> nodeFilter, Filter<U> edgeFilter) {
155                        this.nodeFilter = nodeFilter;
156                        this.edgeFilter = edgeFilter;
157                }
158
159                @SuppressWarnings("unchecked")
160                public boolean isAvailable(Element e) {
161                        if (e instanceof Edge)
162                                return edgeFilter.isAvailable((U) e);
163
164                        return nodeFilter.isAvailable((T) e);
165                }
166        }
167
168        static class ExtremitiesFilter<T extends Element, U extends Element>
169                        implements Filter<T> {
170                Filter<U> f;
171
172                ExtremitiesFilter(Filter<U> f) {
173                        this.f = f;
174                }
175
176                @SuppressWarnings("unchecked")
177                public boolean isAvailable(T e) {
178                        if (e instanceof Node)
179                                return true;
180
181                        return f.isAvailable((U) ((Edge) e).getNode0())
182                                        && f.isAvailable((U) ((Edge) e).getNode1());
183                }
184        }
185
186        static class AndFilter<T extends Element> implements Filter<T> {
187                Filter<T> f1, f2;
188
189                AndFilter(Filter<T> f1, Filter<T> f2) {
190                        this.f1 = f1;
191                        this.f2 = f2;
192                }
193
194                public boolean isAvailable(T e) {
195                        return f1.isAvailable(e) && f2.isAvailable(e);
196                }
197        }
198
199        static class OrFilter<T extends Element> implements Filter<T> {
200                Filter<T> f1, f2;
201
202                OrFilter(Filter<T> f1, Filter<T> f2) {
203                        this.f1 = f1;
204                        this.f2 = f2;
205                }
206
207                public boolean isAvailable(T e) {
208                        return f1.isAvailable(e) || f2.isAvailable(e);
209                }
210        }
211
212        static class XorFilter<T extends Element> implements Filter<T> {
213                Filter<T> f1, f2;
214
215                XorFilter(Filter<T> f1, Filter<T> f2) {
216                        this.f1 = f1;
217                        this.f2 = f2;
218                }
219
220                public boolean isAvailable(T e) {
221                        return f1.isAvailable(e) ^ f2.isAvailable(e);
222                }
223        }
224
225        static class NotFilter<T extends Element> implements Filter<T> {
226                Filter<T> f;
227
228                NotFilter(Filter<T> f) {
229                        this.f = f;
230                }
231
232                public boolean isAvailable(T e) {
233                        return !f.isAvailable(e);
234                }
235        }
236}