code: private static FunctionInputDef asFunctionInputDef( String functionName, JsonObject json)
      {
      FunctionInputDef functionInputDef;
  
      try
        {
        functionInputDef = new FunctionInputDef( validIdentifier( functionName));
        
        // Get function annotations
        Optional.ofNullable( json.getJsonObject( HAS_KEY))
          .ifPresent( has -> has.keySet().stream().forEach( key -> functionInputDef.setAnnotation( key, has.getString( key))));
  
        // Get function variables.
        json.keySet().stream()
          .filter( key -> !key.equals( HAS_KEY))
          .forEach( varType -> getVarDefs( varType, json.getJsonObject( varType)).forEach( varDef -> functionInputDef.addVarDef( varDef)));
  
        if( functionInputDef.getVarTypes().length == 0)
          {
          throw new SystemInputException( String.format( "No variables defined for function=%s", functionName));
          }
  
        SystemInputs.getPropertiesUndefined( functionInputDef)
          .entrySet().stream()
          .findFirst()
          .ifPresent( undefined -> {
            String property = undefined.getKey();
            IConditional ref = undefined.getValue().stream().findFirst().orElse( null);
            throw new SystemInputException
              ( String.format
                ( "Property=%s is undefined, but referenced by %s",
                  property,
                  SystemInputs.getReferenceName( ref)));
            });
  
        }
      catch( SystemInputException e)
        {
        throw new SystemInputException( String.format( "Error defining function=%s", functionName), e);
        }
      
      return functionInputDef;
      }
docs: Returns the FunctionInputDef represented by the given JSON object.