/*********************************************************************************************************************** * 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; } } }