/* * Data Hub Service (DHuS) - For Space data distribution. * Copyright (C) 2016 GAEL Systems * * This file is part of DHuS software sources. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package fr.gael.dhus.olingo.v1.visitor; import fr.gael.dhus.util.functional.tuple.Duo; import fr.gael.dhus.util.functional.tuple.Trio; import org.apache.commons.collections4.Factory; import org.apache.commons.collections4.Transformer; /** * An executable expression tree to filter Collections. * * @param <T> type of elements from the collection being filtered. */ public class ExecutableExpressionTree<T> { private final Node<T,Boolean> rootNode; public ExecutableExpressionTree(Node<T,Boolean> root_node) { this.rootNode = root_node; } public Object exec(T t) { return rootNode.exec(t); } /** * A node of the Expression Tree. * @param <T> accepted type of exec(T), type of the Collection entry. * @param <R> returned type of exec(T). */ public static abstract class Node<T,R> { /** * Executes this Node with the given data. * @param element input. * @return output. */ public abstract R exec(T element); /** * Creates a dynamic leave from a Transformer. * @param <T> Type of the Collection entry. * @param <R> Return type. * @param p Transformer that provides us data from the collection entry. * @return a new Node. */ public static <T,R> Node<T,R> createLeave(final Transformer<T,R> p) { return new Node<T,R>() { @Override public R exec(T element) { return p.transform(element); } }; } /** * Creates a constant leave from a Factory. * @param <T> Type of the Collection entry. * @param <R> Return type. * @param p a Provider. * @return a new Node. */ public static <T,R> Node<T,R> createLeave(final Factory<R> p) { return new Node<T,R>() { @Override public R exec(T element) { return p.create(); } }; } /** * Creates a Node from a Transformer. * @param <T> Type of the Collection entry. * @param <R> Return type. * @param t a transformer that accepts a <?> and returns a <?>. * @param sub Node at `depth+1` in the tree. * @return a new Node. */ public static <T,R> Node<T,R> createNode(final Transformer<Object,R> t, final Node<T,?> sub) { return new Node<T,R>() { @Override public R exec(T element) { return t.transform(sub.exec(element)); } }; } /** * Creates a Node from a Transformer<Duo<?,?>,?>. * @param <T> Type of the Collection entry. * @param <R> Return type. * @param t a bi-transformer that accepts a <?,?> and returns a <?>. * @param sub1 first Node at `depth+1` in the tree, serves as first parameter for `t`. * @param sub2 second Node at `depth+1` in the tree. serves as second parameter for `t`. * @return a new Node. */ public static <T,R> Node<T,R> createNode(final Transformer<Duo<Object,Object>,R> t, final Node<T,?> sub1, final Node<T,?> sub2) { return new Node<T,R>() { @Override public R exec(T element) { Object o1 = sub1.exec(element); Object o2 = sub2.exec(element); return t.transform(new Duo<>(o1, o2)); } }; } /** * Creates a Duo Node, it is a Node that takes a Duo<T,T> as input, * transforms `A` with `sub1`, `B` with `sub2` and return their * tranformation through given transformer `t`. * * @param <T> input type. * @param <R> return type. * @param t transformer for this Node. * @param sub1 first Node at `depth+1` in the tree, serves as first parameter for `t`. * @param sub2 second Node at `depth+1` in the tree, serves as second parameter for `t`. * @return a new Node. */ public static <T,R> Node<Duo<T,T>,R> createDuoNode(final Transformer<Duo<Object,Object>,R> t, final Node<T,?> sub1, final Node<T,?> sub2) { return new Node<Duo<T,T>,R>() { @Override public R exec(Duo<T, T> element) { Object o1 = sub1.exec(element.getA()); Object o2 = sub2.exec(element.getB()); return t.transform(new Duo<>(o1, o2)); } }; } /** * Creates a Node from a Transformer<Trio<?,?,?>,?>. * @param <T> Type of the Collection entry. * @param <R> Return type. * @param t a tri-transformer that accepts a <?,?,?> and returns a <?>. * @param sub1 first Node at `depth+1` in the tree. * @param sub2 second Node at `depth+1` in the tree. * @param sub3 third Node at `depth+1` in the tree. * @return a new Node. */ public static <T,R> Node<T,R> createNode(final Transformer<Trio<Object,Object,Object>,R> t, final Node<T,?> sub1, final Node<T,?> sub2, final Node<T,?> sub3) { return new Node<T,R>() { @Override public R exec(T element) { Object o1 = sub1.exec(element); Object o2 = sub2.exec(element); Object o3 = sub3.exec(element); return t.transform(new Trio<>(o1, o2, o3)); } }; } } }