class ToscaTypeConverter {

    @SuppressWarnings("unchecked")
    public PropertyValue toPropertyValue(Object resolvedPropertyValue, PropertyDefinition propertyDefinition) {
        if (resolvedPropertyValue == null) {
            return null;
        }

        if (ToscaTypes.isSimple(propertyDefinition.getType())) {
            return new ScalarPropertyValue(resolvedPropertyValue.toString());
        }

        switch (propertyDefinition.getType()) {
            case ToscaTypes.MAP:
                if (resolvedPropertyValue instanceof Map) {
                    Map<String, Object> map = (Map<String, Object>) resolvedPropertyValue;
                    Map<String, Object> resultMap = Maps.newHashMap();
                    map.forEach((key, value) -> resultMap.put(key, toPropertyValue(value, propertyDefinition.getEntrySchema())));
                    return new ComplexPropertyValue(resultMap);
                } else {
                throw new IllegalStateException(
                        "Property value: expected type [" + Map.class.getSimpleName() + "] but got [" + resolvedPropertyValue.getClass().getName() + "]");
                }

            case ToscaTypes.LIST:
                if (resolvedPropertyValue instanceof Collection) {
                    List list = (List) resolvedPropertyValue;
                    List resultList = new LinkedList();
                    for (Object item : list) {
                        resultList.add(toPropertyValue(item, propertyDefinition.getEntrySchema()));
                    }
                    return new ListPropertyValue(resultList);
                } else {
                throw new IllegalStateException("Property value: expected type [" + Collection.class.getSimpleName() + "] but got ["
                        + resolvedPropertyValue.getClass().getName() + "]");
                }

            default:
                DataType dataType = findDataType(propertyDefinition.getType());

                if (dataType == null) {
                throw new NotFoundException("Data type  [" + propertyDefinition.getType() + "] cannot be found");
                }

                if (dataType.isDeriveFromSimpleType()) {
                    return new ScalarPropertyValue(resolvedPropertyValue.toString());
                } else if (resolvedPropertyValue instanceof Map) {
                    Map<String, Object> map = (Map<String, Object>) resolvedPropertyValue;
                    /*
                 * Map<String, Object> resultMap = Maps.newHashMap();
                 * 
                 * map.forEach((key, value) -> {
                 * PropertyDefinition entryDefinition = dataType.getProperties().get(key);
                 * if(entryDefinition == null){
                 * throw new IllegalStateException("DataType [" + propertyDefinition.getType() + "] does not contains any definition for entry [" + key + "]");
                 * }
                 * resultMap.put(key, toPropertyValue(value, entryDefinition));
                 * });
                 * return new ComplexPropertyValue(resultMap);
                 */
                    return new ComplexPropertyValue(map);
                } else {
                throw new IllegalStateException(
                        "Property value: expected type [" + propertyDefinition.getType() + "] but got [" + resolvedPropertyValue.getClass().getName() + "]");
                }
        }

    }

    public  ToscaTypeConverter(DataTypesFetcher.DataTypeFinder dataTypeFinder);

}