/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* 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 eu.stratosphere.pact.runtime.test.util;
import java.util.Comparator;
import java.util.Random;
import eu.stratosphere.types.IntValue;
import eu.stratosphere.types.Record;
import eu.stratosphere.types.StringValue;
import eu.stratosphere.util.MutableObjectIterator;
/**
* Test data utilities classes.
*/
public final class TestData {
/**
* Private constructor (container class should not be instantiated)
*/
private TestData() {
}
/**
* Key comparator.
*/
public static class KeyComparator implements Comparator<Key> {
@Override
public int compare(Key k1, Key k2) {
return k1.compareTo(k2);
}
};
/**
* Key implementation.
*/
public static class Key extends IntValue {
private static final long serialVersionUID = 1L;
public Key() {
super();
}
public Key(int k) {
super(k);
}
public int getKey() {
return getValue();
}
public void setKey(int key) {
setValue(key);
}
}
/**
* Value implementation.
*/
public static class Value extends StringValue {
private static final long serialVersionUID = 1L;
public Value() {
super();
}
public Value(String v) {
super(v);
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj)
{
if (this == obj) {
return true;
}
if (obj.getClass() == TestData.Value.class) {
final StringValue other = (StringValue) obj;
int len = this.length();
if (len == other.length()) {
final char[] tc = this.getCharArray();
final char[] oc = other.getCharArray();
int i = 0, j = 0;
while (len-- != 0) {
if (tc[i++] != oc[j++]) {
return false;
}
}
return true;
}
}
return false;
}
}
/**
* Pair generator.
*/
public static class Generator implements MutableObjectIterator<Record>{
public enum KeyMode {
SORTED, RANDOM
};
public enum ValueMode {
FIX_LENGTH, RANDOM_LENGTH, CONSTANT
};
private static char[] alpha = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'a', 'b', 'c',
'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' };
private final long seed;
private final int keyMax;
private final int valueLength;
private final KeyMode keyMode;
private final ValueMode valueMode;
private Random random;
private int counter;
private Key key;
private Value value;
public Generator(long seed, int keyMax, int valueLength) {
this(seed, keyMax, valueLength, KeyMode.RANDOM, ValueMode.FIX_LENGTH);
}
public Generator(long seed, int keyMax, int valueLength, KeyMode keyMode, ValueMode valueMode)
{
this(seed, keyMax, valueLength, keyMode, valueMode, null);
}
public Generator(long seed, int keyMax, int valueLength, KeyMode keyMode, ValueMode valueMode, Value constant) {
this.seed = seed;
this.keyMax = keyMax;
this.valueLength = valueLength;
this.keyMode = keyMode;
this.valueMode = valueMode;
this.random = new Random(seed);
this.counter = 0;
this.key = new Key();
this.value = constant == null ? new Value() : constant;
}
public Record next(Record reuse) {
this.key.setKey(keyMode == KeyMode.SORTED ? ++counter : Math.abs(random.nextInt() % keyMax) + 1);
if (this.valueMode != ValueMode.CONSTANT) {
this.value.setValue(randomString());
}
reuse.setField(0, this.key);
reuse.setField(1, this.value);
return reuse;
}
public boolean next(eu.stratosphere.types.Value[] target) {
this.key.setKey(keyMode == KeyMode.SORTED ? ++counter : Math.abs(random.nextInt() % keyMax) + 1);
// TODO change this to something proper
((IntValue)target[0]).setValue(this.key.getValue());
((IntValue)target[1]).setValue(random.nextInt());
return true;
}
public int sizeOf(Record rec) {
// key
int valueLength = Integer.SIZE / 8;
// value
String text = rec.getField(1, Value.class).getValue();
int strlen = text.length();
int utflen = 0;
int c;
for (int i = 0; i < strlen; i++) {
c = text.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
utflen++;
} else if (c > 0x07FF) {
utflen += 3;
} else {
utflen += 2;
}
}
valueLength += 2 + utflen;
return valueLength;
}
public void reset() {
this.random = new Random(seed);
this.counter = 0;
}
private String randomString() {
int length;
if (valueMode == ValueMode.FIX_LENGTH) {
length = valueLength;
} else {
length = valueLength - random.nextInt(valueLength / 3);
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
sb.append(alpha[random.nextInt(alpha.length)]);
}
return sb.toString();
}
}
/**
* Record reader mock.
*/
public static class GeneratorIterator implements MutableObjectIterator<Record> {
private final Generator generator;
private final int numberOfRecords;
private int counter;
public GeneratorIterator(Generator generator, int numberOfRecords) {
this.generator = generator;
this.generator.reset();
this.numberOfRecords = numberOfRecords;
this.counter = 0;
}
@Override
public Record next(Record target) {
if (counter < numberOfRecords) {
counter++;
return generator.next(target);
}
else {
return null;
}
}
public void reset() {
this.counter = 0;
}
}
// --------------------------------------------------------------------------------------------
public static class ConstantValueIterator implements MutableObjectIterator<Record>
{
private final Key key;
private final Value value;
private final String valueValue;
private final int numPairs;
private int pos;
public ConstantValueIterator(int keyValue, String valueValue, int numPairs)
{
this.key = new Key(keyValue);
this.value = new Value();
this.valueValue = valueValue;
this.numPairs = numPairs;
}
@Override
public Record next(Record reuse) {
if (pos < this.numPairs) {
this.value.setValue(this.valueValue + ' ' + pos);
reuse.setField(0, this.key);
reuse.setField(1, this.value);
pos++;
return reuse;
}
else {
return null;
}
}
public void reset() {
this.pos = 0;
}
}
}