// Use 'string' type for properties with custom converter.
// Arrays are automatically resolved by ElasticSearch, so no worries.
@SuppressWarnings("unchecked")
	public static Map<String, Object> getElasticMapping(SearchableClassMapping scm) {
        Map<String, Object> elasticTypeMappingProperties = new LinkedHashMap<String, Object>();
        String parentType = null;
        if (!scm.isAll()) {
            // "_all" : {"enabled" : true}
            elasticTypeMappingProperties.put("_all",
                Collections.singletonMap("enabled", false));
        }
        // Map each domain properties in supported format, or object for complex type
        for(SearchableClassPropertyMapping scpm : scm.getPropertiesMapping()) {
            // Does it have custom mapping?
            GrailsDomainClassProperty property = scpm.getGrailsProperty();
            String propType = property.getTypePropertyName();
            Map<String, Object> propOptions = new LinkedHashMap<String, Object>();
            // Add the custom mapping (searchable static property in domain model)
            propOptions.putAll(scpm.getAttributes());
            if (!(SUPPORTED_FORMAT.contains(propType))) {
            	LOG.debug("propType not supported: " + propType + " name: " + property.getName());
            	if (scpm.isGeoPoint()) {
            	  propType = "geo_point";
            	}
            	else if (property.isBasicCollectionType()) {
                    // Handle embedded persistent collections, ie List<String> listOfThings
                    String basicType = ClassUtils.getShortName(property.getReferencedPropertyType()).toLowerCase(Locale.ENGLISH);
                    if (SUPPORTED_FORMAT.contains(basicType)) {
                        propType = basicType;
                    }
                // Handle arrays
                } else if (property.getReferencedPropertyType().isArray()) {
                    String basicType = ClassUtils.getShortName(property.getReferencedPropertyType().getComponentType()).toLowerCase(Locale.ENGLISH);
                    if (SUPPORTED_FORMAT.contains(basicType)) {
                        propType = basicType;
                    }
                } else if (isDateType(property.getReferencedPropertyType())) {
                    propType = "date";
                } else if (GrailsClassUtils.isJdk5Enum(property.getReferencedPropertyType())) {
                    propType = "string";
                } else if (scpm.getConverter() != null) {
                    // Use 'string' type for properties with custom converter.
                    // Arrays are automatically resolved by ElasticSearch, so no worries.
                    propType = "string";
                } else if (java.math.BigDecimal.class.isAssignableFrom(property.getReferencedPropertyType())) {
                    propType = "double";
                } else {
                    // todo should this be string??
                    propType = "object";
                }
                if (scpm.getReference() != null) {
                    propType = "object";      // fixme: think about composite ids.
                } else if (scpm.isComponent()) {
                    // Proceed with nested mapping.
                    // todo limit depth to avoid endless recursion?
                    propType = "object";
                    //noinspection unchecked
                    propOptions.putAll((Map<String, Object>)
                            (getElasticMapping(scpm.getComponentPropertyMapping()).values().iterator().next()));
                }
                // Once it is an object, we need to add id & class mappings, otherwise
                // ES will fail with NullPointer.
                if (scpm.isComponent() || scpm.getReference() != null) {
                    Map<String, Object> props = (Map<String, Object>) propOptions.get("properties");
                    if (props == null) {
                        props = new LinkedHashMap<String, Object>();
                        propOptions.put("properties", props);
                    }
                    props.put("id", defaultDescriptor("long", "not_analyzed", true));
                    props.put("class", defaultDescriptor("string", "no", true));
                    props.put("ref", defaultDescriptor("string", "no", true));
                }
                if (scpm.isParentKey()) {
                  parentType = property.getTypePropertyName();
                  scm.setParent(scpm);
                }
            }
            else if (scpm.isGeoPoint()) {
              propType = "geo_point";
            }
            propOptions.put("type", propType);
            // See http://www.elasticsearch.com/docs/elasticsearch/mapping/all_field/
            if (!propType.equals("object") && scm.isAll()) {
                // does it make sense to include objects into _all?
                if (scpm.shouldExcludeFromAll()) {
                    propOptions.put("include_in_all", false);
                } else {
                    propOptions.put("include_in_all", true);
                }
            }
            // todo only enable this through configuration...
            if (propType.equals("string") && scpm.isAnalyzed()) {
                propOptions.put("term_vector", "with_positions_offsets");
            }
            elasticTypeMappingProperties.put(scpm.getPropertyName(), propOptions);
        }
        Map<String, Object> mapping = new LinkedHashMap<String, Object>();
        Map<String, Object> objectMapping = new LinkedHashMap<String, Object>();
        if (parentType != null) {
          objectMapping.put("_parent", Collections.singletonMap("type", parentType));
        }
        objectMapping.put("properties", elasticTypeMappingProperties);
        mapping.put(scm.getElasticTypeName(), objectMapping);
        return mapping;
    }
propType = "string";
} else if (scpm.getConverter() != null) {
// Use 'string' type for properties with custom converter.
// Arrays are automatically resolved by ElasticSearch, so no worries.
propType = "string";
} else if (java.math.BigDecimal.class.isAssignableFrom(property.getReferencedPropertyType())) {
} else if (property.getReferencedPropertyType().isArray()) {
String basicType = ClassUtils.getShortName(property.getReferencedPropertyType().getComponentType()).toLowerCase(Locale.ENGLISH);
if (SUPPORTED_FORMAT.contains(basicType)) {
propType = basicType;
}
} else if (isDateType(property.getReferencedPropertyType())) {
propType = "date";
} else if (GrailsClassUtils.isJdk5Enum(property.getReferencedPropertyType())) {
propType = "string";
} else if (scpm.getConverter() != null) {
// Use 'string' type for properties with custom converter.
// Arrays are automatically resolved by ElasticSearch, so no worries.
propType = "string";
} else if (java.math.BigDecimal.class.isAssignableFrom(property.getReferencedPropertyType())) {
propType = "double";
} else {
// todo should this be string??
propType = "object";
}
if (scpm.getReference() != null) {
propType = "object"; // fixme: think about composite ids.
} else if (scpm.isComponent()) {
if (scpm.isGeoPoint()) {
propType = "geo_point";
}
else if (property.isBasicCollectionType()) {
// Handle embedded persistent collections, ie List<String> listOfThings
String basicType = ClassUtils.getShortName(property.getReferencedPropertyType()).toLowerCase(Locale.ENGLISH);
if (SUPPORTED_FORMAT.contains(basicType)) {
propType = basicType;
}
// Handle arrays
} else if (property.getReferencedPropertyType().isArray()) {
String basicType = ClassUtils.getShortName(property.getReferencedPropertyType().getComponentType()).toLowerCase(Locale.ENGLISH);
if (SUPPORTED_FORMAT.contains(basicType)) {
propType = basicType;
}
} else if (isDateType(property.getReferencedPropertyType())) {
propType = "date";
} else if (GrailsClassUtils.isJdk5Enum(property.getReferencedPropertyType())) {
propType = "string";
} else if (scpm.getConverter() != null) {
// Use 'string' type for properties with custom converter.
// Arrays are automatically resolved by ElasticSearch, so no worries.
propType = "string";
} else if (java.math.BigDecimal.class.isAssignableFrom(property.getReferencedPropertyType())) {
propType = "double";
} else {
// todo should this be string??
propType = "object";
}
if (scpm.getReference() != null) {
propType = "object"; // fixme: think about composite ids.
} else if (scpm.isComponent()) {
// Proceed with nested mapping.
// todo limit depth to avoid endless recursion?
propType = "object";
//noinspection unchecked
propOptions.putAll((Map<String, Object>)
(getElasticMapping(scpm.getComponentPropertyMapping()).values().iterator().next()));
}
// Once it is an object, we need to add id & class mappings, otherwise
// ES will fail with NullPointer.
if (scpm.isComponent() || scpm.getReference() != null) {