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

org.richfaces.cdk.ordering.PartialOrderToCompleteOrder Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2011, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.richfaces.cdk.ordering;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;

/**
 * 

* Stores partial orderings in order to be able derive complete ordering. *

* *

* When storing new partial ordering, checks that new partial ordering does not violates partial orderings stored before. *

* * @author Lukas Fryc */ public class PartialOrderToCompleteOrder { // all items stored in partial orderings for quick access private Set allItems = Sets.newLinkedHashSet(); // partial orderings used to check for ordering violation private List partialOrderings = new LinkedList(); // map from items to their dependencies private Map> dependencies = Maps.newLinkedHashMap(); /** *

* Stores collection as partial ordering. *

* *

* Checks that this collection will not violate another partial orderings stored before. *

* * @param collection as partial order */ public void addPartialOrdering(Collection collection) { if (collection == null || collection.isEmpty()) { return; } checkCurrentPartialOrders(collection); allItems.addAll(collection); partialOrderings.add(new PartialOrdering(collection)); registerDependencies(Lists.newLinkedList(collection)); } /** * Provides all items which was stored in collections as partial orderings * * @return all items which was stored in collections as partial orderings */ public Set getAllItems() { return allItems; } /** *

* Provides current complete ordering derived from partial orderings. *

* * @return current complete ordering derived from partial orderings. */ public CompleteOrdering getCompleteOrdering() { return new CompleteOrdering(); } /** * Get all items completely ordered. * * @return all items completely ordered. */ public Collection getCompletelyOrderedItems() { return new CompleteOrdering().sortedCopy(allItems); } /** * Class representing result of deriving complete ordering from stored partial orderings. */ public class CompleteOrdering extends Ordering { private Set ordered = getCurrentOrder(); private Predicate IS_ORDERED = new Predicate() { public boolean apply(T item) { return ordered.contains(item); } }; public int compare(T left, T right) { if (!ordered.contains(left) || !ordered.contains(right)) { throw new IllegalStateException(); } if (left.equals(right)) { return 0; } for (T item : ordered) { if (item.equals(left)) { return -1; } else if (item.equals(right)) { return +1; } } throw new IllegalStateException(); } /** *

* Returns new iterable sorted according to this complete ordering. *

* *

* All items which are unknown in this ordering are stored on the end of returned collection in the same order like in * iterable. *

*/ @SuppressWarnings("unchecked") @Override public List sortedCopy(Iterable iterable) { List originList = (List) Lists.newLinkedList(iterable); Collection onlyOrdered = Collections2.filter(originList, IS_ORDERED); Collection onlyNotOrdered = Collections2.filter(originList, Predicates.not(IS_ORDERED)); List itemsInOrder = super.sortedCopy(onlyOrdered); itemsInOrder.addAll(onlyNotOrdered); return (List) itemsInOrder; } private Set getCurrentOrder() { Set result = Sets.newLinkedHashSet(); DependencyResolver resolver = new DependencyResolver(); for (int i = 0; i < dependencies.size(); i++) { List nodesWithoutDependencies = resolver.findNodesWithoutDependencies(); result.addAll(nodesWithoutDependencies); resolver.removeNodes(nodesWithoutDependencies); } if (resolver.getSize() > 0) { throw new IllegalStateException(); } return result; } private class DependencyResolver { private Map> deps = deepCopyOfDependencies(); private List findNodesWithoutDependencies() { List list = Lists.newLinkedList(); for (Entry> entry : deps.entrySet()) { if (entry.getValue().isEmpty()) { list.add(entry.getKey()); } } return list; } private void removeNodes(List nodes) { for (Set values : deps.values()) { values.removeAll(nodes); } for (T node : nodes) { deps.remove(node); } } private Map> deepCopyOfDependencies() { Map> result = Maps.newLinkedHashMap(); for (Entry> entry : dependencies.entrySet()) { result.put(entry.getKey(), Sets.newHashSet(entry.getValue())); } return result; } public int getSize() { return deps.size(); } } } private void checkCurrentPartialOrders(Collection collection) { for (PartialOrdering p : partialOrderings) { List filtered = p.filter(collection); if (!p.isStrictlyOrdered(filtered)) { throw new IllegalPartialOrderingException("\ncollection: " + collection + "\n" + p); } } } private void registerDependencies(Collection collection) { List reversedOrder = Lists.reverse(Lists.newLinkedList(collection)); Set newItemDependencies = Sets.newLinkedHashSet(collection); for (T newItem : reversedOrder) { newItemDependencies.remove(newItem); registerDependenciesForItem(newItem, Sets.newLinkedHashSet(newItemDependencies)); } } private void registerDependenciesForItem(T item, Set newItemDependencies) { if (!dependencies.containsKey(item)) { dependencies.put(item, Sets.newHashSet()); } Set itemDependences = dependencies.get(item); itemDependences.addAll(newItemDependencies); } private class PartialOrdering extends Ordering { private LinkedList order = Lists.newLinkedList(); private HashSet items = Sets.newHashSet(); public PartialOrdering(Collection collection) { order = Lists.newLinkedList(collection); items = Sets.newHashSet(collection); } public int compare(T left, T right) { if (!items.contains(left)) { throw new IllegalArgumentException("'" + left + "' is not part of this partial ordering"); } if (!items.contains(right)) { throw new IllegalArgumentException("'" + right + "' is not part of this partial ordering"); } return order.indexOf(left) - order.indexOf(right); } public List filter(Collection collection) { List list = new LinkedList(collection); list.retainAll(items); return list; } @Override public String toString() { return "PartialOrder" + order; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy