docs: public LocalProperties filterBySemanticProperties(SemanticProperties props, int input) {
  
  		if (props == null) {
  			throw new NullPointerException("SemanticProperties may not be null.");
  		}
  
  		LocalProperties returnProps = new LocalProperties();
  
  		// check if sorting is preserved
  		if (this.ordering != null) {
  			Ordering newOrdering = new Ordering();
  
  			for (int i = 0; i < this.ordering.getInvolvedIndexes().size(); i++) {
  				int sourceField = this.ordering.getInvolvedIndexes().get(i);
  				FieldSet targetField = props.getForwardingTargetFields(input, sourceField);
  				if (targetField == null || targetField.size() == 0) {
  					if (i == 0) {
  						// order fully destroyed
  						newOrdering = null;
  						break;
  					} else {
  						// order partially preserved
  						break;
  					}
  				} else {
  					// use any field of target fields for now.  We should use something like field equivalence sets in the future.
  					if(targetField.size() > 1) {
  						LOG.warn("Found that a field is forwarded to more than one target field in " +
  								"semantic forwarded field information. Will only use the field with the lowest index.");
  					}
  					newOrdering.appendOrdering(targetField.toArray()[0], this.ordering.getType(i), this.ordering.getOrder(i));
  				}
  			}
  
  			returnProps.ordering = newOrdering;
  			if (newOrdering != null) {
  				returnProps.groupedFields = newOrdering.getInvolvedIndexes();
  			} else {
  				returnProps.groupedFields = null;
  			}
  		}
  		// check if grouping is preserved
  		else if (this.groupedFields != null) {
  			FieldList newGroupedFields = new FieldList();
  
  			for (Integer sourceField : this.groupedFields) {
  				FieldSet targetField = props.getForwardingTargetFields(input, sourceField);
  				if (targetField == null || targetField.size() == 0) {
  					newGroupedFields = null;
  					break;
  				} else {
  					// use any field of target fields for now.  We should use something like field equivalence sets in the future.
  					if(targetField.size() > 1) {
  						LOG.warn("Found that a field is forwarded to more than one target field in " +
  								"semantic forwarded field information. Will only use the field with the lowest index.");
  					}
  					newGroupedFields = newGroupedFields.addField(targetField.toArray()[0]);
  				}
  			}
  			returnProps.groupedFields = newGroupedFields;
  		}
  
  		if (this.uniqueFields != null) {
  			Set<FieldSet> newUniqueFields = new HashSet<FieldSet>();
  			for (FieldSet fields : this.uniqueFields) {
  				FieldSet newFields = new FieldSet();
  				for (Integer sourceField : fields) {
  					FieldSet targetField = props.getForwardingTargetFields(input, sourceField);
  
  					if (targetField == null || targetField.size() == 0) {
  						newFields = null;
  						break;
  					} else {
  						// use any field of target fields for now.  We should use something like field equivalence sets in the future.
  						if(targetField.size() > 1) {
  							LOG.warn("Found that a field is forwarded to more than one target field in " +
  									"semantic forwarded field information. Will only use the field with the lowest index.");
  						}
  						newFields = newFields.addField(targetField.toArray()[0]);
  					}
  				}
  				if (newFields != null) {
  					newUniqueFields.add(newFields);
  				}
  			}
  
  			if (!newUniqueFields.isEmpty()) {
  				returnProps.uniqueFields = newUniqueFields;
  			} else {
  				returnProps.uniqueFields = null;
  			}
  		}
  
  		return returnProps;
  	}