static OProperty<?> buildPropery(
     String propName, EdmType type, Object value, String invalidCharacterReplacement)
     throws TransformationException, SQLException, IOException {
   if (!(type instanceof EdmSimpleType)) {
     if (type instanceof EdmCollectionType) {
       EdmCollectionType collectionType = (EdmCollectionType) type;
       EdmType componentType = collectionType.getItemType();
       Builder<OObject> b = OCollections.newBuilder(componentType);
       if (value instanceof Array) {
         value = ((Array) value).getArray();
       }
       int length = java.lang.reflect.Array.getLength(value);
       for (int i = 0; i < length; i++) {
         Object o = java.lang.reflect.Array.get(value, i);
         OProperty p = buildPropery("x", componentType, o, invalidCharacterReplacement);
         if (componentType instanceof EdmSimpleType) {
           b.add(OSimpleObjects.create((EdmSimpleType) componentType, p.getValue()));
         } else {
           throw new AssertionError("Multi-dimensional arrays are not yet supported.");
           // b.add((OCollection)p.getValue());
         }
       }
       return OProperties.collection(propName, collectionType, b.build());
     }
     throw new AssertionError("non-simple types are not yet supported");
   }
   EdmSimpleType expectedType = (EdmSimpleType) type;
   if (value == null) {
     return OProperties.null_(propName, expectedType);
   }
   Class<?> sourceType = DataTypeManager.getRuntimeType(value.getClass());
   Class<?> targetType =
       DataTypeManager.getDataTypeClass(
           ODataTypeManager.teiidType(expectedType.getFullyQualifiedTypeName()));
   if (sourceType != targetType) {
     Transform t = DataTypeManager.getTransform(sourceType, targetType);
     if (t == null && BlobType.class == targetType) {
       if (sourceType == ClobType.class) {
         return OProperties.binary(propName, ClobType.getString((Clob) value).getBytes());
       }
       if (sourceType == SQLXML.class) {
         return OProperties.binary(propName, ((SQLXML) value).getString().getBytes());
       }
     }
     value = DataTypeManager.convertToRuntimeType(value, true);
     value = t != null ? t.transform(value, targetType) : value;
     value = replaceInvalidCharacters(expectedType, value, invalidCharacterReplacement);
     if (value instanceof BinaryType) {
       value = ((BinaryType) value).getBytesDirect();
     }
     return OProperties.simple(propName, expectedType, value);
   }
   value = replaceInvalidCharacters(expectedType, value, invalidCharacterReplacement);
   return OProperties.simple(propName, expectedType, value);
 }
  @Override
  public BaseResponse callFunction(
      ODataContext context,
      EdmFunctionImport name,
      Map<String, OFunctionParameter> params,
      QueryInfo queryInfo) {
    BaseResponse response;

    ServiceOperationsProducerMock.LOGGER.debug("EdmFunctionImport Object:    " + name.getName());
    ServiceOperationsProducerMock.LOGGER.debug("EdmFunctionImport Parameter: " + params);
    ServiceOperationsProducerMock.LOGGER.debug("EdmFunctionImport QueryInfo: " + queryInfo);

    this.queryParameter = params;
    this.queryInfo = queryInfo;

    if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING.equals(name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_PUT.equals(
        name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_GET.equals(
        name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_DELETE.equals(
        name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_PATCH.equals(
        name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_MERGE.equals(
        name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_POST.equals(
        name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_BOOLEAN.equals(name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.BOOLEAN, name.getName(), ServiceOperationsProducerMock.BOOLEAN_VALUE);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_INT16.equals(name.getName())) {
      response =
          Responses.simple(
              EdmSimpleType.INT16, name.getName(), ServiceOperationsProducerMock.INT16_VALUE);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_ENTITY.equals(name.getName())) {
      OEntity entity = this.createEmployeeEntity();
      response = Responses.entity(entity);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COMPLEX_TYPE.equals(
        name.getName())) {
      OComplexObject complexObject = this.createComplexTypeLocation();
      response =
          Responses.complexObject(
              complexObject, ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COMPLEX_TYPE);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_STRING.equals(
        name.getName())) {
      Builder<OObject> collectionBuilder = OCollections.newBuilder(EdmSimpleType.STRING);
      collectionBuilder
          .add(
              OSimpleObjects.create(
                  EdmSimpleType.STRING, ServiceOperationsProducerMock.COLLECTION_STRING1))
          .build();
      collectionBuilder
          .add(
              OSimpleObjects.create(
                  EdmSimpleType.STRING, ServiceOperationsProducerMock.COLLECTION_STRING2))
          .build();
      OCollection<OObject> collection = collectionBuilder.build();
      response =
          Responses.collection(
              collection,
              null,
              null,
              null,
              ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_STRING);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_DOUBLE.equals(
        name.getName())) {
      Builder<OObject> collectionBuilder = OCollections.newBuilder(EdmSimpleType.DOUBLE);
      collectionBuilder
          .add(
              OSimpleObjects.create(
                  EdmSimpleType.DOUBLE, ServiceOperationsProducerMock.COLLECTION_DOUBLE1))
          .build();
      collectionBuilder
          .add(
              OSimpleObjects.create(
                  EdmSimpleType.DOUBLE, ServiceOperationsProducerMock.COLLECTION_DOUBLE2))
          .build();
      OCollection<OObject> collection = collectionBuilder.build();
      response =
          Responses.collection(
              collection,
              null,
              null,
              null,
              ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_DOUBLE);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_COMPLEX_TYPE.equals(
        name.getName())) {
      OComplexObject complexObject1 = this.createComplexTypeLocation();
      OComplexObject complexObject2 = this.createComplexTypeLocation();

      EdmComplexType type =
          this.getMetadata()
              .findEdmComplexType(ServiceOperationsProducerMock.COMPLEY_TYPE_NAME_LOCATION);
      Builder<OObject> collectionBuilder = OCollections.newBuilder(type);

      collectionBuilder.add(complexObject1);
      collectionBuilder.add(complexObject2);

      OCollection<OObject> collection = collectionBuilder.build();
      response =
          Responses.collection(
              collection,
              null,
              null,
              null,
              ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_COMPLEX_TYPE);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_ENTITY.equals(
        name.getName())) {
      OEntity entity = this.createEmployeeEntity();

      Builder<OObject> collectionBuilder = OCollections.newBuilder(entity.getType());
      collectionBuilder.add(entity);
      OCollection<OObject> collection = collectionBuilder.build();

      response =
          Responses.collection(
              collection,
              entity.getEntitySet(),
              null,
              null,
              ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_ENTITY);
    } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_ENTITYSET.equals(
        name.getName())) {
      List<OEntity> entities = new ArrayList<OEntity>();
      entities.add(createEmployeeEntity());
      response = Responses.entities(entities, name.getEntitySet(), null, null);
    } else {
      throw new RuntimeException("Unsupported Test Case for FunctionImport: " + name.getName());
    }

    return response;
  }