/** Create int-based (non-nested) field position keys on a tuple type. */ public ExpressionKeys(int[] keyPositions, TypeInformation<T> type, boolean allowEmpty) { if (!type.isTupleType() || !(type instanceof CompositeType)) { throw new InvalidProgramException( "Specifying keys via field positions is only valid " + "for tuple data types. Type: " + type); } if (type.getArity() == 0) { throw new InvalidProgramException( "Tuple size must be greater than 0. Size: " + type.getArity()); } if (!allowEmpty && (keyPositions == null || keyPositions.length == 0)) { throw new IllegalArgumentException("The grouping fields must not be empty."); } this.keyFields = new ArrayList<>(); if (keyPositions == null || keyPositions.length == 0) { // use all tuple fields as key fields keyPositions = createIncrIntArray(type.getArity()); } else { rangeCheckFields(keyPositions, type.getArity() - 1); } Preconditions.checkArgument( keyPositions.length > 0, "Grouping fields can not be empty at this point"); // extract key field types CompositeType<T> cType = (CompositeType<T>) type; this.keyFields = new ArrayList<>(type.getTotalFields()); // for each key position, find all (nested) field types String[] fieldNames = cType.getFieldNames(); ArrayList<FlatFieldDescriptor> tmpList = new ArrayList<>(); for (int keyPos : keyPositions) { tmpList.clear(); // get all flat fields cType.getFlatFields(fieldNames[keyPos], 0, tmpList); // check if fields are of key type for (FlatFieldDescriptor ffd : tmpList) { if (!ffd.getType().isKeyType()) { throw new InvalidProgramException( "This type (" + ffd.getType() + ") cannot be used as key."); } } this.keyFields.addAll(tmpList); } }