/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* PreludeTestsSupport.java
* Created: Mar 6, 2006
* By: Bo Ilic
*/
package org.openquark.cal.foreignsupport.module.Prelude_Tests;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.Vector;
import org.openquark.cal.foreignsupport.module.Prelude.OrderingValue;
import org.openquark.cal.runtime.CalFunction;
import org.openquark.cal.util.EquivalenceRelation;
import org.openquark.cal.util.FixedSizeList;
/**
* Place to put some Java support for the Prelude_Tests module.
* @author Bo Ilic
*/
public final class PreludeTestsSupport {
private PreludeTestsSupport() {}
public static final java.util.List<String> nuttyVector = new Vector<String>(Arrays.asList(new String[] {"pecan", "almond", "peanut", "walnut"}));
public static final java.util.List<String> fruityArrayList = new ArrayList<String>(Arrays.asList(new String[] {"apple", "orange", "pear"}));
public static final Object[] nutsAndFruits = new java.util.List[] {nuttyVector, fruityArrayList};
public static final Object[] cityStrings = new String[] {"Vancouver", "Seattle", "Victoria"};
public static final boolean TRUE = true;
public static final boolean FALSE = false;
/**
* Helper class that contains the foreign implementation for the groupAllBy function:
*
* groupAllBy :: (a -> a -> Boolean) -> [a] -> [[a]];
*
* For example,
* groupAllBy (\p q -> fst p == fst q) [('a', 1.0), ('a', 2.0), ('b', 3.0), ('c', 4.0), ('a', 5.0), ('b', 6.0)]
* == [[('a', 1.0), ('a', 2.0), ('a', 5.0)], [('b', 3.0), ('b', 6.0)], [('c', 4.0)]];
*
* @author Bo Ilic
*/
public static final class GroupAllBy {
private GroupAllBy() {}
public static <T> java.util.List<java.util.List<T>> groupAllBy(java.util.List<T> list, EquivalenceRelation<T> eqRelation) {
if (eqRelation == null || list == null) {
throw new NullPointerException();
}
LinkedList<T> sourceList = new LinkedList<T>(list);
java.util.List<java.util.List<T>> resultListList = new ArrayList<java.util.List<T>>();
sourceListIteration: while (!sourceList.isEmpty()) {
T elem = sourceList.removeFirst();
for (int i = 0, sizeResultListList = resultListList.size(); i < sizeResultListList; ++i) {
java.util.List<T> resultList = resultListList.get(i);
if (eqRelation.equivalent(resultList.get(0), elem)) {
resultList.add(elem);
continue sourceListIteration;
}
}
java.util.List<T> newResultList = new ArrayList<T>();
newResultList.add(elem);
resultListList.add(newResultList);
}
return resultListList;
}
}
/**
* A Java singly linked list, similar to the Prelude.List type. This is intended to be used for
* performance experiments with the basic evaluation loop of CAL
* @author Bo Ilic
*/
public static abstract class List {
private List() {}
public static final class Cons extends List {
private final Object head;
private final List tail;
public Cons (Object head, List tail) {
if (tail == null) {
throw new NullPointerException("tail cannot be null.");
}
this.head = head;
this.tail = tail;
}
public Object getHead() {
return head;
}
public List getTail() {
return tail;
}
}
public static final class Nil extends List {
public static final Nil NIL = new Nil ();
private Nil() {}
}
/**
* @param n must be >= 1.
* @return the List 1, 2, 3, ... n.
*/
public static List upTo (int n) {
List list = Nil.NIL;
for (int i = n; i > 0; --i) {
//we call JavaPrimitives.makeInteger instead of just new Integer() to simulate the caching behavior for
//ints used by lecc.
list = new Cons (Integer.valueOf(i), list);
}
return list;
}
/**
* {@inheritDoc}
*/
@Override
public final String toString () {
StringBuilder result = new StringBuilder("[");
List currentNode = this;
boolean needsSeparator = false;
while (currentNode != Nil.NIL) {
if (needsSeparator) {
result.append(", ");
} else {
needsSeparator = true;
}
Cons currentCons = (Cons)currentNode;
result.append(currentCons.getHead());
currentNode = currentCons.getTail();
}
result.append(']');
return result.toString();
}
/**
* @return the length of this List. Will be O(n) in the length.
*/
public final int length () {
List currentNode = this;
int counter = 0;
while (currentNode != Nil.NIL) {
++counter;
currentNode = ((Cons)currentNode).getTail();
}
return counter;
}
}
/**
* Test class for scope resolution static errors. Foreign types in CAL should not be able to access non-public classes
* and methods.
* @author Bo Ilic
*/
static class PackageScopeInnerClass {
//not really public, since it is in a package scope class
public PackageScopeInnerClass() {
}
//not really public, since it is in a package scope class
static public int publicScopeIntField = 1;
//not really public, since it is in a package scope class
static public int publicScopeAddOne (int i) {
return i + 1;
}
}
static public class PublicScopeExtendsPackageScopeInnerClass extends PackageScopeInnerClass {
}
/**
* Test class for scope resolution static errors. Foreign types in CAL should not be able to access non-public classes
* and methods.
* @author Bo Ilic
*/
static public class PublicScopeInnerClass {
static int packageScopeAddOne (int i) {
return i + 1;
}
static protected int protectedScopeAddOne (int i) {
return i + 1;
}
static public int publicScopeAddOne (int i) {
return i + 1;
}
}
/**
* Example of creating a Java Comparator from a CalFunction. This is done directly (and more efficienlty) in the Prelude
* via the makeComparator function, but can also be accomplished this way.
*
* @author Bo Ilic
*/
static public final class CalComparator implements Comparator<Object> {
private final CalFunction function;
public CalComparator(CalFunction function) {
if (function == null) {
throw new NullPointerException();
}
this.function = function;
}
public int compare(Object o1, Object o2) {
return ((OrderingValue)function.evaluate(FixedSizeList.make(o1, o2))).toInt();
}
}
/**
* Similar to String.valueOf, except arrays (at the outermost level) are handled by displaying
* their components. For example, an int[][] could display as: [[1, 2], [2, 3, 4], [3]].
* This is a useful method for debug code involving arrays, as the default implementation of toString on
* arrays is just Object.toString i.e. shows the class name followed by a reference id.
*
* @param object
* @return String
*/
static public final String toStringHandlingArrays(Object object) {
if (object == null || !object.getClass().isArray()) {
return String.valueOf(object);
}
final int length = Array.getLength(object);
StringBuilder result = new StringBuilder("[");
for (int i = 0; i < length; ++i) {
if (i > 0) {
result.append(", ");
}
result.append(toStringHandlingArrays(Array.get(object, i)));
}
result.append("]");
return result.toString();
}
static public char[] charPrimArray() {
return new char[] {'p', 'r', 'i', 'm'};
}
static public Character[] charReferenceArray() {
return new Character[] {new Character('r'), new Character('e'), new Character('f')};
}
static public Set<Character> charSet() {
Set<Character> s = new LinkedHashSet<Character>();
s.add(new Character('s'));
s.add(new Character('e'));
s.add(new Character('t'));
return s;
}
static public Iterator<Character> charIterator() {
Set<Character> s = new LinkedHashSet<Character>();
s.add(new Character('i'));
s.add(new Character('t'));
return s.iterator();
}
static public Enumeration<Character> charEnumeration() {
Set<Character> s = new LinkedHashSet<Character>();
s.add(new Character('e'));
s.add(new Character('n'));
s.add(new Character('u'));
s.add(new Character('m'));
return Collections.enumeration(s);
}
static public final class Counter {
private Counter() {}
private final static ThreadLocal<Integer> value = new ThreadLocal<Integer>();
public static int increment() {
int returnValue = value.get().intValue() + 1;
value.set(Integer.valueOf(returnValue));
return returnValue;
}
public static void reset() {
value.set(Integer.valueOf(0));
}
}
}