use of org.molgenis.data.meta.AttributeType in project molgenis by molgenis.
the class EmxMetaDataParser method parseAttributesSheet.
/**
* Load all attributes from the source repository and add it to the {@link IntermediateParseResults}.
*
* @param attributesRepo Repository for the attributes
* @param intermediateResults {@link IntermediateParseResults} with the tags already parsed
*/
private void parseAttributesSheet(Repository<Entity> attributesRepo, IntermediateParseResults intermediateResults) {
for (Attribute attr : attributesRepo.getEntityType().getAtomicAttributes()) {
if (!SUPPORTED_ATTRIBUTE_ATTRIBUTES.contains(attr.getName()) && !((isI18n(attr.getName()) && (attr.getName().startsWith(EMX_ATTRIBUTES_LABEL) || attr.getName().startsWith(EMX_ATTRIBUTES_DESCRIPTION))))) {
// check if casing mismatch
SUPPORTED_ATTRIBUTE_ATTRIBUTES.forEach(emxAttrMetaAttr -> {
if (emxAttrMetaAttr.equalsIgnoreCase(attr.getName())) {
throw new IllegalArgumentException(format("Unsupported attribute metadata: attributes.%s, did you mean attributes.%s?", attr.getName(), emxAttrMetaAttr));
}
});
throw new IllegalArgumentException("Unsupported attribute metadata: attributes." + attr.getName());
}
}
Map<String, Map<String, EmxAttribute>> attributesMap = newLinkedHashMap();
// 1st pass: create attribute stubs
// Header
int rowIndex = 1;
for (Entity attributeEntity : attributesRepo) {
rowIndex++;
String attributeName = attributeEntity.getString(EMX_ATTRIBUTES_NAME);
if (attributeName == null)
throw new IllegalArgumentException(format("attributes.name is missing on line [%d]", rowIndex));
String entityTypeId = attributeEntity.getString(EMX_ATTRIBUTES_ENTITY);
if (entityTypeId == null)
throw new IllegalArgumentException(format("attributes.entity is missing for attribute named: %s on line [%d]", attributeName, rowIndex));
// create attribute
Attribute attribute = attrMetaFactory.create().setName(attributeName);
Map<String, EmxAttribute> entitiesMap = attributesMap.computeIfAbsent(entityTypeId, k -> newLinkedHashMap());
entitiesMap.put(attributeName, new EmxAttribute(attribute));
}
// 2nd pass: set all properties on attribute stubs except for attribute relations
// Header
rowIndex = 1;
for (Entity emxAttrEntity : attributesRepo) {
rowIndex++;
String emxEntityName = emxAttrEntity.getString(EMX_ATTRIBUTES_ENTITY);
Map<String, EmxAttribute> entityMap = attributesMap.get(emxEntityName);
// If an entity is defined in the attribute sheet only,
// make sure to create EntityType and set the backend
EntityType md = intermediateResults.getEntityType(emxEntityName);
if (md == null) {
md = intermediateResults.addEntityType(emxEntityName);
if (dataService != null)
md.setBackend(dataService.getMeta().getDefaultBackend().getName());
}
String emxName = emxAttrEntity.getString(EMX_ATTRIBUTES_NAME);
EmxAttribute emxAttr = entityMap.get(emxName);
Attribute attr = emxAttr.getAttr();
String emxDataType = emxAttrEntity.getString(EMX_ATTRIBUTES_DATA_TYPE);
String emxRefEntity = emxAttrEntity.getString(EMX_ATTRIBUTES_REF_ENTITY);
if (emxDataType != null) {
AttributeType type = toEnum(emxDataType);
if (type == null) {
throw new IllegalArgumentException("attributes.dataType error on line " + rowIndex + ": " + emxDataType + " unknown data type");
}
attr.setDataType(type);
} else {
attr.setDataType(STRING);
}
String emxAttrNillable = emxAttrEntity.getString(EMX_ATTRIBUTES_NILLABLE);
String emxIdAttrValue = emxAttrEntity.getString(EMX_ATTRIBUTES_ID_ATTRIBUTE);
String emxAttrVisible = emxAttrEntity.getString(EMX_ATTRIBUTES_VISIBLE);
String emxAggregatable = emxAttrEntity.getString(EMX_ATTRIBUTES_AGGREGATEABLE);
String emxIsLookupAttr = emxAttrEntity.getString(EMX_ATTRIBUTES_LOOKUP_ATTRIBUTE);
String emxIsLabelAttr = emxAttrEntity.getString(EMX_ATTRIBUTES_LABEL_ATTRIBUTE);
String emxReadOnly = emxAttrEntity.getString(EMX_ATTRIBUTES_READ_ONLY);
String emxUnique = emxAttrEntity.getString(EMX_ATTRIBUTES_UNIQUE);
String expression = emxAttrEntity.getString(EMX_ATTRIBUTES_EXPRESSION);
String validationExpression = emxAttrEntity.getString(EMX_ATTRIBUTES_VALIDATION_EXPRESSION);
String defaultValue = emxAttrEntity.getString(EMX_ATTRIBUTES_DEFAULT_VALUE);
Object emxAttrTags = emxAttrEntity.get(EMX_ENTITIES_TAGS);
List<String> tagIdentifiers = toList(emxAttrTags);
if (tagIdentifiers != null && !tagIdentifiers.isEmpty()) {
attr.setTags(toTags(intermediateResults, tagIdentifiers));
}
if (emxAttrNillable != null) {
if (emxAttrNillable.equalsIgnoreCase("true") || emxAttrNillable.equalsIgnoreCase("false")) {
attr.setNillable(parseBoolean(emxAttrNillable, rowIndex, EMX_ATTRIBUTES_NILLABLE));
} else {
attr.setNullableExpression(emxAttrNillable);
}
}
if (emxIdAttrValue != null) {
if (!emxIdAttrValue.equalsIgnoreCase("true") && !emxIdAttrValue.equalsIgnoreCase("false") && !emxIdAttrValue.equalsIgnoreCase(AUTO)) {
throw new IllegalArgumentException(format("Attributes error on line [%d]. Illegal idAttribute value. Allowed values are 'TRUE', 'FALSE' or 'AUTO'", rowIndex));
}
if (emxIdAttrValue.equalsIgnoreCase("true")) {
if (!isIdAttributeTypeAllowed(attr)) {
throw new MolgenisDataException("Identifier is of type [" + attr.getDataType() + "]. Id attributes can only be of type 'STRING', 'INT' or 'LONG'");
}
}
attr.setAuto(emxIdAttrValue.equalsIgnoreCase(AUTO));
if (!attr.isAuto())
emxAttr.setIdAttr(parseBoolean(emxIdAttrValue, rowIndex, EMX_ATTRIBUTES_ID_ATTRIBUTE));
else
// If it is auto, set idAttr to true
emxAttr.setIdAttr(true);
}
if (attr.isAuto() && !isStringType(attr)) {
throw new IllegalArgumentException(format("Attributes error on line [%d]. Auto attributes can only be of data type 'string'", rowIndex));
}
if (emxAttrVisible != null) {
if (emxAttrVisible.equalsIgnoreCase("true") || emxAttrVisible.equalsIgnoreCase("false")) {
attr.setVisible(parseBoolean(emxAttrVisible, rowIndex, EMX_ATTRIBUTES_VISIBLE));
} else {
attr.setVisibleExpression(emxAttrVisible);
}
}
if (emxAggregatable != null)
attr.setAggregatable(parseBoolean(emxAggregatable, rowIndex, EMX_ATTRIBUTES_AGGREGATEABLE));
if (emxReadOnly != null)
attr.setReadOnly(parseBoolean(emxReadOnly, rowIndex, EMX_ATTRIBUTES_READ_ONLY));
if (emxUnique != null)
attr.setUnique(parseBoolean(emxUnique, rowIndex, EMX_ATTRIBUTES_UNIQUE));
if (expression != null)
attr.setExpression(expression);
if (validationExpression != null)
attr.setValidationExpression(validationExpression);
if (defaultValue != null)
attr.setDefaultValue(defaultValue);
if (emxIsLookupAttr != null) {
boolean isLookAttr = parseBoolean(emxIsLookupAttr, rowIndex, EMX_ATTRIBUTES_LOOKUP_ATTRIBUTE);
if (isLookAttr && isReferenceType(attr)) {
throw new IllegalArgumentException(format("attributes.lookupAttribute error on line [%d] (%s.%s) lookupAttribute cannot be of type %s", rowIndex, emxEntityName, emxName, attr.getDataType().toString()));
}
emxAttr.setLookupAttr(isLookAttr);
}
if (emxIsLabelAttr != null) {
boolean isLabelAttr = parseBoolean(emxIsLabelAttr, rowIndex, EMX_ATTRIBUTES_LABEL_ATTRIBUTE);
if (isLabelAttr && isReferenceType(attr)) {
throw new IllegalArgumentException(format("attributes.labelAttribute error on line [%d] (%s.%s): labelAttribute cannot be of type %s", rowIndex, emxEntityName, emxName, attr.getDataType().toString()));
}
emxAttr.setLabelAttr(isLabelAttr);
}
attr.setLabel(emxAttrEntity.getString(EMX_ATTRIBUTES_LABEL));
for (String attrName : emxAttrEntity.getAttributeNames()) {
if (isI18n(attrName)) {
if (attrName.startsWith(EMX_ATTRIBUTES_LABEL)) {
String label = emxAttrEntity.getString(attrName);
if (label != null) {
String languageCode = getLanguageCode(attrName);
attr.setLabel(languageCode, label);
}
} else if (attrName.startsWith(EMX_ATTRIBUTES_DESCRIPTION)) {
String description = emxAttrEntity.getString(attrName);
if (description != null) {
String languageCode = getLanguageCode(attrName);
attr.setDescription(languageCode, description);
}
}
}
}
attr.setDescription(emxAttrEntity.getString(EMX_ATTRIBUTES_DESCRIPTION));
if (attr.getDataType() == ENUM) {
List<String> enumOptions = DataConverter.toList(emxAttrEntity.get(EMX_ATTRIBUTES_ENUM_OPTIONS));
if (enumOptions == null || enumOptions.isEmpty()) {
throw new IllegalArgumentException(format("Missing enum options for attribute [%s] of entity [%s]", attr.getName(), emxEntityName));
}
attr.setEnumOptions(enumOptions);
}
if (attr.getDataType() != FILE) {
// Only if an attribute is not of type file we apply the normal reference rules
if (isReferenceType(attr) && StringUtils.isEmpty(emxRefEntity)) {
throw new IllegalArgumentException(format("Missing refEntity on line [%d] (%s.%s)", rowIndex, emxEntityName, emxName));
}
}
if (isReferenceType(attr) && attr.isNillable() && attr.isAggregatable()) {
throw new IllegalArgumentException(format("attributes.isAggregatable error on line [%d] (%s.%s): isAggregatable nillable attribute cannot be of type %s", rowIndex, emxEntityName, emxName, attr.getDataType().toString()));
}
String emxRangeMin = emxAttrEntity.getString(EMX_ATTRIBUTES_RANGE_MIN);
Long rangeMin;
if (emxRangeMin != null) {
try {
rangeMin = Long.valueOf(emxRangeMin);
} catch (NumberFormatException e) {
throw new MolgenisDataException(format("Invalid range rangeMin [%s] value for attribute [%s] of entity [%s], should be a long", emxRangeMin, emxName, emxEntityName));
}
} else {
rangeMin = null;
}
String emxRangeMax = emxAttrEntity.getString(EMX_ATTRIBUTES_RANGE_MAX);
Long rangeMax;
if (emxRangeMax != null) {
try {
rangeMax = Long.valueOf(emxRangeMax);
} catch (NumberFormatException e) {
throw new MolgenisDataException(format("Invalid range rangeMax [%s] value for attribute [%s] of entity [%s], should be a long", emxRangeMax, emxName, emxEntityName));
}
} else {
rangeMax = null;
}
if (rangeMin != null || rangeMax != null) {
attr.setRange(new Range(rangeMin, rangeMax));
}
}
// 3rd pass: validate and create attribute relationships
Map<String, Set<String>> rootAttributes = newLinkedHashMap();
// Header
rowIndex = 1;
for (Entity attributeEntity : attributesRepo) {
rowIndex++;
String entityTypeId = attributeEntity.getString(EMX_ATTRIBUTES_ENTITY);
Map<String, EmxAttribute> entityMap = attributesMap.get(entityTypeId);
String attributeName = attributeEntity.getString(EMX_ATTRIBUTES_NAME);
Attribute attribute = entityMap.get(attributeName).getAttr();
// bootstrap attribute parent-children relations for compound attributes
String partOfAttribute = attributeEntity.getString(EMX_ATTRIBUTES_PART_OF_ATTRIBUTE);
if (partOfAttribute != null && !partOfAttribute.isEmpty()) {
EmxAttribute emxCompoundAttribute = entityMap.get(partOfAttribute);
if (emxCompoundAttribute == null) {
throw new IllegalArgumentException("partOfAttribute [" + partOfAttribute + "] of attribute [" + attributeName + "] of entity [" + entityTypeId + "] must refer to an existing compound attribute on line " + rowIndex);
}
Attribute compoundAttribute = emxCompoundAttribute.getAttr();
if (compoundAttribute.getDataType() != COMPOUND) {
throw new IllegalArgumentException("partOfAttribute [" + partOfAttribute + "] of attribute [" + attributeName + "] of entity [" + entityTypeId + "] must refer to a attribute of type [" + COMPOUND + "] on line " + rowIndex);
}
attribute.setParent(compoundAttribute);
}
Set<String> entityRootAttributes = rootAttributes.computeIfAbsent(entityTypeId, k -> new LinkedHashSet<>());
entityRootAttributes.add(attributeName);
}
// store attributes with entities
for (Map.Entry<String, Map<String, EmxAttribute>> entry : attributesMap.entrySet()) {
String entityTypeId = entry.getKey();
Map<String, EmxAttribute> attributes = entry.getValue();
List<EmxAttribute> editableEntityType = newArrayList();
// add root attributes to entity
Set<String> entityAttributeNames = rootAttributes.get(entityTypeId);
if (entityAttributeNames != null) {
for (EmxAttribute attribute : attributes.values()) {
if (entityAttributeNames.contains(attribute.getAttr().getName())) {
editableEntityType.add(attribute);
}
}
}
intermediateResults.addAttributes(entityTypeId, editableEntityType);
}
}
use of org.molgenis.data.meta.AttributeType in project molgenis by molgenis.
the class DynamicEntity method validateValueType.
/**
* Validate is value is of the type defined by the attribute data type.
*
* @param attrName attribute name
* @param value value (must be of the type defined by the attribute data type.)
*/
protected void validateValueType(String attrName, Object value) {
if (value == null) {
return;
}
Attribute attr = entityType.getAttribute(attrName);
if (attr == null) {
throw new UnknownAttributeException(entityType, attrName);
}
AttributeType dataType = attr.getDataType();
switch(dataType) {
case BOOL:
if (!(value instanceof Boolean)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), Boolean.class.getSimpleName(), attrName));
}
break;
case CATEGORICAL:
// expected type is FileMeta. validation is not possible because molgenis-data does not depend on molgenis-file
case FILE:
case XREF:
if (!(value instanceof Entity)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), Entity.class.getSimpleName(), attrName));
}
break;
case CATEGORICAL_MREF:
case MREF:
case ONE_TO_MANY:
if (!(value instanceof Iterable)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), Iterable.class.getSimpleName(), attrName));
}
break;
case COMPOUND:
throw new IllegalArgumentException(format("Unexpected data type [%s] for attribute: [%s]", dataType.toString(), attrName));
case DATE:
if (!(value instanceof LocalDate)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), LocalDate.class.getSimpleName(), attrName));
}
break;
case DATE_TIME:
if (!(value instanceof Instant)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), Instant.class.getSimpleName(), attrName));
}
break;
case DECIMAL:
if (!(value instanceof Double)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), Double.class.getSimpleName(), attrName));
}
if (((Double) value).isNaN()) {
throw new MolgenisDataException(format("Value [%s] for type [%s] is not allowed for attribute: [%s]", value.toString(), Double.class.getSimpleName(), attrName));
}
break;
case EMAIL:
case ENUM:
case HTML:
case HYPERLINK:
case SCRIPT:
case STRING:
case TEXT:
if (!(value instanceof String)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), String.class.getSimpleName(), attrName));
}
break;
case INT:
if (!(value instanceof Integer)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), Integer.class.getSimpleName(), attrName));
}
break;
case LONG:
if (!(value instanceof Long)) {
throw new MolgenisDataException(format("Value [%s] is of type [%s] instead of [%s] for attribute: [%s]", value.toString(), value.getClass().getSimpleName(), Long.class.getSimpleName(), attrName));
}
break;
default:
throw new UnexpectedEnumException(dataType);
}
}
use of org.molgenis.data.meta.AttributeType in project molgenis by molgenis.
the class EntityTypeUtilsTest method isMultipleReferenceTypeProvider.
@DataProvider(name = "isMultipleReferenceTypeProvider")
public static Iterator<Object[]> isMultipleReferenceTypeProvider() {
List<Object[]> dataList = Lists.newArrayList();
for (AttributeType attrType : AttributeType.values()) {
Attribute attr = mock(Attribute.class);
when(attr.getDataType()).thenReturn(attrType);
when(attr.toString()).thenReturn("attr_" + attrType.toString());
boolean isMultipleRefAttr = attrType == CATEGORICAL_MREF || attrType == MREF || attrType == ONE_TO_MANY;
dataList.add(new Object[] { attr, isMultipleRefAttr });
}
return dataList.iterator();
}
use of org.molgenis.data.meta.AttributeType in project molgenis by molgenis.
the class DocumentContentBuilderTest method createDocumentReferenceProvider.
@DataProvider(name = "createDocumentReference")
public static Iterator<Object[]> createDocumentReferenceProvider() {
List<Object[]> dataItems = new ArrayList<>();
String refAttr = "refAttr";
Entity refEntity = createEntity(refAttr, AttributeType.STRING);
when(refEntity.getString(refAttr)).thenReturn("str");
for (AttributeType attributeType : EnumSet.of(CATEGORICAL, FILE, XREF)) {
dataItems.add(new Object[] { attributeType, null, "{\"attr\":null}" });
dataItems.add(new Object[] { attributeType, refEntity, "{\"attr\":{\"refAttr\":\"str\"}}" });
}
return dataItems.iterator();
}
use of org.molgenis.data.meta.AttributeType in project molgenis by molgenis.
the class DocumentContentBuilderTest method createDocumentMultiReferenceProvider.
@DataProvider(name = "createDocumentMultiReference")
public static Iterator<Object[]> createDocumentMultiReferenceProvider() {
List<Object[]> dataItems = new ArrayList<>();
String refAttr = "refAttr";
Entity refEntity = createEntity(refAttr, AttributeType.STRING);
when(refEntity.getString(refAttr)).thenReturn("str");
for (AttributeType attributeType : EnumSet.of(CATEGORICAL_MREF, MREF, ONE_TO_MANY)) {
dataItems.add(new Object[] { attributeType, emptyList(), "{\"attr\":null}" });
dataItems.add(new Object[] { attributeType, singletonList(refEntity), "{\"attr\":[{\"refAttr\":\"str\"}]}" });
}
return dataItems.iterator();
}
Aggregations