All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.link_intersystems.graph.GraphFacade Maven / Gradle / Ivy

Go to download

There is a newer version: 1.9.7
Show newest version
/**
 * Copyright 2011 Link Intersystems GmbH 
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.link_intersystems.graph; import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; import static java.util.Arrays.asList; import static java.util.Spliterator.ORDERED; import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.stream.StreamSupport.stream; /** * Facade to ease the use of components within the graph package. * * @author René Link * [rene.link@link- * intersystems.com] * @since 1.2.0; */ public abstract class GraphFacade { /** * Traverses the graph using the breadth first traversal strategy. Starting at * the given {@link Node} and applies the given {@link Consumer} on every * {@link Node} . * * @param start the {@link Node} to start the traversal from. * @param nodeProcessor the closure that should be applied to every node. * @since 1.2.0; */ public static void traverseBreadthFirst(Node start, Consumer nodeProcessor) { Iterator objectGraphIterator = new BreadthFirstNodeIterator(start); forAllDo(objectGraphIterator, nodeProcessor); } /** * Traverses the graph using the depth first traversal strategy. Starting at the * given {@link Node} and applies the given {@link Consumer} on every * {@link Node} . * * @param start the {@link Node} to start the traversal from. * @param nodeProcessor the closure that should be applied to every node. * @since 1.0.0; */ public static void traverseDepthFirst(Node start, Consumer nodeProcessor) { DepthFirstNodeIterator objectGraphTransformer = new DepthFirstNodeIterator(start); forAllDo(objectGraphTransformer, nodeProcessor); } static void forAllDo(Iterator iterator, Consumer closure) { while (iterator.hasNext()) { T next = iterator.next(); closure.accept(next); } } public enum NodeIterateStrategy { DEPTH_FIRST { @Override public Iterator iterator(Node startNode) { return new DepthFirstNodeIterator(startNode); } }, BREADTH_FIRST { @Override public Iterator iterator(Node startNode) { return new BreadthFirstNodeIterator(startNode); } }; public abstract Iterator iterator(Node startNode); } /** * Creates a predicated {@link Node} iterator that iterates the {@link Node} s * per Predicate that is specified using the {@link NodeIterateStrategy}. *

* Take the following node structure for example * *

     *                   A
     *      +------------+------------+
     *      B            C            D
     * +----+----+       |        +---+------------+
     * E    F    G       H        I   J            K
     *                                      +------+------+
     *                                      L      M      N
     * 
*

* If we assume that we have 3 {@link Predicate}s *

    *
  • The 1. {@link Predicate} matches {@link Node}s A,C,H,D,K
  • *
  • The 2. {@link Predicate} matches {@link Node}s A,B,E,F
  • *
  • The 3. {@link Predicate} matches {@link Node}s D,J,M,N
  • *
* and we construct a per predicated node iterator using * *
     * {@link GraphFacade#perPredicateNodeIterator(NodeIterateStrategy, Node, Predicate...) GraphFacade.perPredicatedNodeIterator(BREADTH_FIRST, startNodeA, pred1, pred2, pred3)};
     * 
*

* The resulting iterator will iterate the node structure using a breadth first * strategy for every {@link Predicate} starting at startNodeA.
* The result will be: * *

     * breadth first  breadth first   breadth first
     *   matching       matching       matching
     *    pred1          pred2           pred3
     * +-----------+   +-------+       +-------+
     *   A C D H K      A B E F         D J M N
     *
     * iterate order -->
     * 
* *

* * @param nodeIterateStrategy * @param startNode * @param nodeIterateOrderPredicates * @return */ @SuppressWarnings("unchecked") public static Iterator perPredicateNodeIterator(NodeIterateStrategy nodeIterateStrategy, Node startNode, Predicate... nodeIterateOrderPredicates) { class FilteredIterator implements Iterator { private final Iterator filtered; public FilteredIterator(Iterator iterator, Predicate filter) { filtered = stream(spliteratorUnknownSize(iterator, ORDERED), false).filter(filter).iterator(); } @Override public boolean hasNext() { return filtered.hasNext(); } @Override public E next() { return filtered.next(); } } class ChainedIterator implements Iterator { private Iterator> chain; private Iterator current = Collections.emptyIterator(); @SafeVarargs public ChainedIterator(Iterator... iterators) { this(asList(iterators)); } public ChainedIterator(Collection> iterators) { chain = iterators.iterator(); } @Override public boolean hasNext() { while (!current.hasNext() && chain.hasNext()) { current = chain.next(); } return current.hasNext(); } @Override public E next() { if (!hasNext()) { throw new NoSuchElementException(); } return current.next(); } } List> iterators = new ArrayList<>(); for (int i = 0; i < nodeIterateOrderPredicates.length; i++) { Predicate predicate = nodeIterateOrderPredicates[i]; Iterator nodeStrategyIterator = nodeIterateStrategy.iterator(startNode); Iterator predicateFilterIterator = new FilteredIterator<>(nodeStrategyIterator, predicate); iterators.add(predicateFilterIterator); } return new ChainedIterator<>(iterators); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy