package alien4cloud.ui.form;
import static alien4cloud.ui.form.GenericFormConstants.ARRAY_TYPE;
import static alien4cloud.ui.form.GenericFormConstants.COMPLEX_TYPE;
import static alien4cloud.ui.form.GenericFormConstants.CONTENT_TYPE_KEY;
import static alien4cloud.ui.form.GenericFormConstants.MAP_TYPE;
import static alien4cloud.ui.form.GenericFormConstants.ORDER_KEY;
import static alien4cloud.ui.form.GenericFormConstants.PROPERTY_TYPE_KEY;
import static alien4cloud.ui.form.GenericFormConstants.TOSCA_DEFINITION_KEY;
import static alien4cloud.ui.form.GenericFormConstants.TOSCA_TYPE;
import static alien4cloud.ui.form.GenericFormConstants.TYPE_KEY;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.alien4cloud.tosca.model.CSARDependency;
import org.alien4cloud.tosca.model.definitions.PropertyDefinition;
import org.alien4cloud.tosca.model.types.DataType;
import org.alien4cloud.tosca.model.types.PrimitiveDataType;
import org.springframework.stereotype.Component;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import alien4cloud.component.ICSARRepositorySearchService;
import alien4cloud.exception.InvalidArgumentException;
import alien4cloud.tosca.normative.ToscaType;
@Component
public class ToscaPropertyFormDescriptorGenerator {
@Resource
private ICSARRepositorySearchService csarRepositorySearchService;
public Map<String, Object> generateDescriptor(PropertyDefinition propertyDefinition, Set<CSARDependency> dependencies) {
return doGenerateDescriptor(Sets.<String> newHashSet(), propertyDefinition, dependencies);
}
private Map<String, Object> doGenerateDescriptor(Set<String> processedDataTypes, PropertyDefinition propertyDefinition, Set<CSARDependency> dependencies) {
if (ToscaType.isSimple(propertyDefinition.getType())) {
return generateDescriptorForSimpleType(propertyDefinition);
} else if (ToscaType.LIST.equals(propertyDefinition.getType())) {
PropertyDefinition entryDefinition = propertyDefinition.getEntrySchema();
if (entryDefinition == null) {
throw new InvalidArgumentException("List type without entry schema");
}
return generateDescriptorForListType(processedDataTypes, entryDefinition, dependencies);
} else if (ToscaType.MAP.equals(propertyDefinition.getType())) {
PropertyDefinition entryDefinition = propertyDefinition.getEntrySchema();
if (entryDefinition == null) {
throw new InvalidArgumentException("Map type without entry schema");
}
return generateDescriptorForMapType(processedDataTypes, entryDefinition, dependencies);
} else {
DataType dataType = csarRepositorySearchService.getElementInDependencies(DataType.class, propertyDefinition.getType(), dependencies);
if (dataType == null) {
throw new InvalidArgumentException("Data type <" + propertyDefinition.getType() + "> do not exist in dependencies " + dependencies);
}
if (processedDataTypes.add(dataType.getElementId())) {
return generateDescriptorForDataType(processedDataTypes, dataType, dependencies);
} else {
return generateDescriptorForSimpleType(propertyDefinition);
}
}
}
private Map<String, Object> generateDescriptorForDataType(Set<String> processedDataTypes, DataType dataType, Set<CSARDependency> dependencies) {
Map<String, Object> dataTypeDescriptors = Maps.newHashMap();
if (dataType instanceof PrimitiveDataType) {
dataTypeDescriptors.put(TYPE_KEY, TOSCA_TYPE);
PropertyDefinition propertyDefinition = new PropertyDefinition();
propertyDefinition.setType(dataType.getDerivedFrom().get(0));
propertyDefinition.setConstraints(((PrimitiveDataType) dataType).getConstraints());
dataTypeDescriptors.put(TOSCA_DEFINITION_KEY, propertyDefinition);
} else {
dataTypeDescriptors.put(TYPE_KEY, COMPLEX_TYPE);
Map<String, Object> propertyTypes = Maps.newHashMap();
dataTypeDescriptors.put(PROPERTY_TYPE_KEY, propertyTypes);
if (dataType.getProperties() != null) {
for (Map.Entry<String, PropertyDefinition> propertyDefinitionEntry : dataType.getProperties().entrySet()) {
propertyTypes.put(propertyDefinitionEntry.getKey(),
doGenerateDescriptor(processedDataTypes, propertyDefinitionEntry.getValue(), dependencies));
}
dataTypeDescriptors.put(ORDER_KEY, dataType.getProperties().keySet());
}
}
return dataTypeDescriptors;
}
private Map<String, Object> generateDescriptorForSimpleType(PropertyDefinition propertyDefinition) {
Map<String, Object> typeDescriptor = Maps.newHashMap();
typeDescriptor.put(TYPE_KEY, TOSCA_TYPE);
typeDescriptor.put(TOSCA_DEFINITION_KEY, propertyDefinition);
return typeDescriptor;
}
private Map<String, Object> generateDescriptorForListType(Set<String> processedDataTypes, PropertyDefinition entryDefinition,
Set<CSARDependency> dependencies) {
Map<String, Object> listDescriptors = Maps.newHashMap();
listDescriptors.put(TYPE_KEY, ARRAY_TYPE);
listDescriptors.put(CONTENT_TYPE_KEY, doGenerateDescriptor(processedDataTypes, entryDefinition, dependencies));
return listDescriptors;
}
private Map<String, Object> generateDescriptorForMapType(Set<String> processedDataTypes, PropertyDefinition entryDefinition,
Set<CSARDependency> dependencies) {
Map<String, Object> mapDescriptors = Maps.newHashMap();
mapDescriptors.put(TYPE_KEY, MAP_TYPE);
mapDescriptors.put(CONTENT_TYPE_KEY, doGenerateDescriptor(processedDataTypes, entryDefinition, dependencies));
return mapDescriptors;
}
}