
net.sf.jagg.msd.ChainedDiscriminator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jagg-core Show documentation
Show all versions of jagg-core Show documentation
jAgg is a Java 5.0 API that supports “group by” operations on Lists of Java objects: aggregate operations such as count, sum, max, min, avg, and many more. It also allows custom aggregate operations.
The newest version!
package net.sf.jagg.msd;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A ChainedDiscriminator
relies on another
* Discriminator
to perform its work in a separate step, after
* this discriminator's work is done.
*
* @author Randy Gettman
* @since 0.5.0
*/
public abstract class ChainedDiscriminator extends AbstractDiscriminator
{
private static final boolean DEBUG = false;
/**
* Partitions the given List
of elements into another
* List
, in which all of the elements from the given list exist
* in the new list, and all elements that compare equal are adjacent to each
* other, according to the given Extractor
.
* @param elements A List
of elements.
* @param extractor An Extractor
that gives labels for
* each element.
* @param workspace The MsdWorkspace
used in the discrimination
* process.
* @return A List
of Lists
containing all
* equivalence classes. Each equivalence class list contains all elements
* that compare equal to each other. If for any reason, this is unable
* to discriminate the List
, e.g. the elements are non-
* Discriminable
objects, then this returns
* null
.
*/
@SuppressWarnings({"unchecked","ForLoopReplaceableByForEach"})
public List> discriminate(List elements, Extractor extractor, MsdWorkspace workspace)
{
if (DEBUG)
System.err.println(getClass().getName() + " elements: " + Arrays.deepToString(elements.toArray()));
if (elements.size() == 0)
return new ArrayList>(0);
List> curr = new ArrayList>(1);
curr.add(elements);
List> equivClasses;
List> results = new ArrayList>();
ChainedExtractor/**/ chainedExtractor = getChainedExtractor(elements, extractor);
// Index loop.
int index = 0;
// Cannot get a wildcard for the extractor -- which could possibly
// be any type -- to line up with the wildcard for the
// discriminator. That is, one cannot equal another
// . That's okay, the type might vary from one loop
// iteration to the next.
while (!curr.isEmpty())
{
Discriminator/*>*/ discr = getDiscriminator(elements, chainedExtractor, index);
if (discr == null)
{
// Failed to get a Discriminator; can't discriminate.
return null;
}
List> next = new ArrayList>();
if (DEBUG)
System.err.println(" index: " + index);
chainedExtractor.setIndex(index);
// Loop through each equivalence class to create sub-equivalence
// classes.
for (int i = 0; i < curr.size(); i++)
{
List currElements = curr.get(i);
List finished = new ArrayList();
List remaining = new ArrayList();
// Take out those elements that are complete according to the given extractor.
for (int j = 0; j < currElements.size(); j++)
{
E element = currElements.get(j);
if (chainedExtractor.isComplete(element))
finished.add(element);
else
remaining.add(element);
}
// The discriminator will mark the "complete" property in portionExtractor.
equivClasses = (List>) discr.discriminate(remaining, chainedExtractor, workspace);
if (DEBUG)
{
System.err.println(" " + getClass().getName() + " equivClasses:");
for (List equivClass : equivClasses)
System.err.println(" " + Arrays.deepToString(equivClass.toArray()));
if (!finished.isEmpty())
{
System.err.println(" finished:" + Arrays.deepToString(finished.toArray()));
}
}
// Add in finished results in their own equivalence class, if any.
if (!finished.isEmpty())
results.add(finished);
// If the condition says for all of the elements that they all
// terminated, then they are all equivalent, in one class.
if (equivClasses.size() == 1 && chainedExtractor.isAllComplete())
{
results.add(equivClasses.get(0));
}
else
{
// Store the sub-equivalence classes.
for ( int j = 0; j < equivClasses.size(); j++)
{
List equivClass = equivClasses.get(j);
// Don't bother with classes of size 1, which won't change in
// subsequent loops.
if (equivClass.size() > 1)
{
next.add(equivClass);
if (DEBUG)
System.err.println(" Sending equivClass to next loop: " + Arrays.deepToString(equivClass.toArray()));
}
else
results.add(equivClass);
}
}
}
// Prepare for next loop.
curr = next;
index++;
}
// Add the last iteration in.
int size = curr.size();
// Avoid creating an Iterator in a call to "addAll".
for (int i = 0; i < size; i++)
{
results.add(curr.get(i));
}
if (DEBUG)
{
System.err.println(" " + getClass().getName() + " results: ");
for (List result : results)
System.err.println(" " + Arrays.deepToString(result.toArray()));
}
return results;
}
/**
* Returns an Extractor
that extracts a label of unknown type
* from a label of type T
, using the given
* Extractor
, which supplies labels of type T
.
* For the same index, the returned Extractor
must return
* labels of the same type as the type discriminated by the
* Discriminator
returned by getDiscriminator
.
* @param elements The List
of elements.
* @param extractor The Extractor
that extracts a label of type
* T
from the element.
* @param The type of element.
* @return A ChainedExtractor
that extracts a label of unknown
* type from a label of type T
.
* @see #getDiscriminator
*/
protected abstract ChainedExtractor getChainedExtractor(List elements, Extractor extractor);
/**
* Returns a Discriminator
that discriminates on an unknown
* type. For the same index, the returned Discriminator
must
* discriminate on the same type as the labels that are returned by the
* ChainedExtractor
that is returned by
* getChainedExtractor
. If it is known that no more loops are
* necessary, then the returned Discriminator
may be
* null
.
* @param elements The list of elements.
* @param extractor The ChainedExtractor
that was obtained from
* getChainedExtractor
.
* @param index The index of the loop.
* @return A Discriminator
, or null
if it is known
* for sure that no more loops are necessary.
* @see #getChainedExtractor
*/
protected abstract Discriminator> getDiscriminator(List elements, ChainedExtractor extractor,
int index);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy