eu.stratosphere.api.java.operators.Keys Maven / Gradle / Ivy
/***********************************************************************************************************************
*
* 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.api.java.operators;
import java.util.Arrays;
import eu.stratosphere.api.common.InvalidProgramException;
import eu.stratosphere.api.java.functions.KeySelector;
import eu.stratosphere.api.java.typeutils.TupleTypeInfo;
import eu.stratosphere.api.java.typeutils.TypeExtractor;
import eu.stratosphere.types.TypeInformation;
public abstract class Keys {
public abstract int getNumberOfKeyFields();
public boolean isEmpty() {
return getNumberOfKeyFields() == 0;
}
public abstract boolean areCompatibale(Keys> other);
public abstract int[] computeLogicalKeyPositions();
// --------------------------------------------------------------------------------------------
// Specializations for field indexed / expression-based / extractor-based grouping
// --------------------------------------------------------------------------------------------
public static class FieldPositionKeys extends Keys {
private final int[] groupingFields;
private final TypeInformation>[] types;
public FieldPositionKeys(int[] groupingFields, TypeInformation type) {
this(groupingFields, type, false);
}
public FieldPositionKeys(int[] groupingFields, TypeInformation type, boolean allowEmpty) {
if (!type.isTupleType()) {
throw new InvalidProgramException("Specifying keys via field positions is only valid for tuple data types");
}
if (!allowEmpty && (groupingFields == null || groupingFields.length == 0)) {
throw new IllegalArgumentException("The grouping fields must not be empty.");
}
TupleTypeInfo> tupleType = (TupleTypeInfo>)type;
this.groupingFields = makeFields(groupingFields, (TupleTypeInfo>) type);
types = new TypeInformation[this.groupingFields.length];
for(int i = 0; i < this.groupingFields.length; i++) {
types[i] = tupleType.getTypeAt(this.groupingFields[i]);
}
}
@Override
public int getNumberOfKeyFields() {
return this.groupingFields.length;
}
@Override
public boolean areCompatibale(Keys> other) {
if (other instanceof FieldPositionKeys) {
FieldPositionKeys> oKey = (FieldPositionKeys>) other;
if(oKey.types.length != this.types.length) {
return false;
}
for(int i=0; i sfk = (SelectorFunctionKeys, ?>) other;
return sfk.keyType.equals(this.types[0]);
}
else {
return false;
}
}
@Override
public int[] computeLogicalKeyPositions() {
return this.groupingFields;
}
}
// --------------------------------------------------------------------------------------------
public static class SelectorFunctionKeys extends Keys {
private final KeySelector keyExtractor;
private final TypeInformation keyType;
public SelectorFunctionKeys(KeySelector keyExtractor, TypeInformation type) {
this.keyExtractor = keyExtractor;
this.keyType = TypeExtractor.getKeySelectorTypes(keyExtractor, type);
}
public TypeInformation getKeyType() {
return keyType;
}
public KeySelector getKeyExtractor() {
return keyExtractor;
}
@Override
public int getNumberOfKeyFields() {
return 1;
}
@Override
public boolean areCompatibale(Keys> other) {
if (other instanceof SelectorFunctionKeys) {
@SuppressWarnings("unchecked")
SelectorFunctionKeys, K> sfk = (SelectorFunctionKeys, K>) other;
return sfk.keyType.equals(this.keyType);
}
else if (other instanceof FieldPositionKeys) {
FieldPositionKeys> fpk = (FieldPositionKeys>) other;
if(fpk.types.length != 1) {
return false;
}
return fpk.types[0].equals(this.keyType);
}
else {
return false;
}
}
@Override
public int[] computeLogicalKeyPositions() {
return new int[] {0};
}
}
// --------------------------------------------------------------------------------------------
public static class ExpressionKeys extends Keys {
public ExpressionKeys(String expression, TypeInformation type) {
}
@Override
public int getNumberOfKeyFields() {
throw new UnsupportedOperationException("Expression keys not yet implemented");
}
@Override
public boolean areCompatibale(Keys> other) {
throw new UnsupportedOperationException("Expression keys not yet implemented");
}
@Override
public int[] computeLogicalKeyPositions() {
throw new UnsupportedOperationException("Expression keys not yet implemented");
}
}
// --------------------------------------------------------------------------------------------
// Utilities
// --------------------------------------------------------------------------------------------
private static int[] makeFields(int[] fields, TupleTypeInfo> type) {
int inLength = type.getArity();
// null parameter means all fields are considered
if (fields == null || fields.length == 0) {
fields = new int[inLength];
for (int i = 0; i < inLength; i++) {
fields[i] = i;
}
return fields;
} else {
return rangeCheckAndOrderFields(fields, inLength-1);
}
}
private static final int[] rangeCheckAndOrderFields(int[] fields, int maxAllowedField) {
// order
Arrays.sort(fields);
// range check and duplicate eliminate
int i = 1, k = 0;
int last = fields[0];
if (last < 0 || last > maxAllowedField) {
throw new IllegalArgumentException("Tuple position is out of range.");
}
for (; i < fields.length; i++) {
if (fields[i] < 0 || i > maxAllowedField) {
throw new IllegalArgumentException("Tuple position is out of range.");
}
if (fields[i] != last) {
k++;
fields[k] = fields[i];
}
}
// check if we eliminated something
if (k == fields.length - 1) {
return fields;
} else {
return Arrays.copyOfRange(fields, 0, k);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy