code: public SplitDataProperties<T> splitsOrderedBy(String orderFields, Order[] orders) {
  
  		if (orderFields == null || orders == null) {
  			throw new InvalidProgramException("OrderFields or Orders may not be null.");
  		}
  
  		String[] orderKeysA = orderFields.split(";");
  		if (orderKeysA.length == 0) {
  			throw new InvalidProgramException("OrderFields may not be empty.");
  		} else if (orders.length == 0) {
  			throw new InvalidProgramException("Orders may not be empty");
  		} else if (orderKeysA.length != orders.length) {
  			throw new InvalidProgramException("Number of OrderFields and Orders must match.");
  		}
  
  		if (this.splitGroupKeys != null) {
  			throw new InvalidProgramException("DataSource may either be grouped or sorted.");
  		}
  
  		this.splitOrdering = new Ordering();
  
  		for (int i = 0; i < orderKeysA.length; i++) {
  			String keyExp = orderKeysA[i];
  			Keys.ExpressionKeys<T> ek = new Keys.ExpressionKeys<>(keyExp, this.type);
  			int[] flatKeys = ek.computeLogicalKeyPositions();
  
  			for (int key : flatKeys) {
  				// check for duplicates
  				for (int okey : splitOrdering.getFieldPositions()) {
  					if (key == okey) {
  						throw new InvalidProgramException("Duplicate field in field expression " + keyExp);
  					}
  				}
  				// append key
  				this.splitOrdering.appendOrdering(key, null, orders[i]);
  			}
  		}
  		return this;
  	}
docs: Defines that the data within an input split is sorted on the fields defined by the field expressions
  in the specified orders. Multiple field expressions must be separated by the semicolon ';' character.
  All records of an input split must be emitted by the input format in the defined order.
  
  <p><b>
  IMPORTANT: Providing wrong information with SplitDataProperties can cause wrong results!
  </b>
  
  @param orderFields The field expressions of the grouping key.
  @param orders The orders of the fields.
  @return This SplitDataProperties object.