blob: a54912c7a40bc7b2bb47e694f8b31c796a1736e0 [file] [log] [blame]
package org.eclipse.mdm.api.odsadapter.lookup;
import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_ENUMERATION_CLASS;
import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_SCALAR_TYPE;
import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_SEQUENCE;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.mdm.api.base.model.Core;
import org.eclipse.mdm.api.base.model.Deletable;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.ScalarType;
import org.eclipse.mdm.api.base.model.Value;
import org.eclipse.mdm.api.base.model.ValueType;
import org.eclipse.mdm.api.base.query.Attribute;
import org.eclipse.mdm.api.base.query.DefaultCore;
import org.eclipse.mdm.api.base.query.EntityType;
import org.eclipse.mdm.api.base.query.Record;
import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
import org.eclipse.mdm.api.dflt.model.CatalogComponent;
/**
* Container for entities by executing an {@link EntityRequest}.
*
* @param <T>
* The entity type.
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
*/
final class EntityResult<T extends Entity> {
// ======================================================================
// Instance variables
// ======================================================================
private final Map<String, EntityRecord<T>> entityRecords = new HashMap<>();
private final List<T> entities = new ArrayList<>();
final EntityRequest<T> request;
// ======================================================================
// Constructors
// ======================================================================
/**
* Constructor.
*
* @param request
* The associated {@link EntityRequest}.
*/
EntityResult(EntityRequest<T> request) {
this.request = request;
}
// ======================================================================
// Public methods
// ======================================================================
/**
* Returns the {@link EntityRecord} identified by given instance ID.
*
* @param id
* The instance ID.
* @return {@code Optional} is empty if {@code EntityRecord} not found.
*/
public Optional<EntityRecord<T>> get(String id) {
return Optional.ofNullable(entityRecords.get(id));
}
/**
* Creates an {@link EntityRecord} for given {@link Record} and mapps it
* internally by its instance ID.
*
* @param record
* The {@code Record}.
* @return The created {@code EntityRecord} is returned.
*/
public EntityRecord<T> add(Record record) {
return create(new DefaultCore(record));
}
/**
* Creates an {@link EntityRecord} for given {@link Record} using given
* parent {@code EntityRecord} and mapps it internally by its instance ID.
*
* @param parentRecord
* The created {@code EntityRecord} will be related as a child
* with this one.
* @param record
* The {@code Record}.
* @return The created {@code EntityRecord} is returned.
*/
public EntityRecord<T> add(EntityRecord<?> parentRecord, Record record) {
Core core = new DefaultCore(record);
if (CatalogAttribute.class.equals(request.entityConfig.getEntityClass())) {
// add read only properties from application model
adjustCatalogAttributeCore(parentRecord.entity, core);
}
EntityRecord<T> childRecord = create(core);
childRecord.core.getPermanentStore().set(parentRecord.entity);
parentRecord.core.getChildrenStore().add((Deletable) childRecord.entity);
return childRecord;
}
/**
* Returns the {@link Entity}s of this entity result.
*
* @return Returned {@code Collection} is unmodifiable.
*/
public List<T> getEntities() {
return Collections.unmodifiableList(entities);
}
/**
* Returns the {@link Entity}s of this entity result sorted.
*
* @return Returned {@code Collection} is unmodifiable.
*/
public List<T> getSortedEntities() {
return Collections.unmodifiableList(
entities.stream().sorted(request.entityConfig.getComparator()).collect(Collectors.toList()));
}
/**
* Returns the instance IDs of the entities held by this entity result.
*
* @return Returned {@code Collection} is unmodifiable.
*/
public Collection<String> getIDs() {
return Collections.unmodifiableCollection(entityRecords.keySet());
}
/**
* Checks whether this entity result holds entities or is empty.
*
* @return Returns {@code true} if this entity result has no entities.
*/
public boolean isEmpty() {
return entities.isEmpty();
}
// ======================================================================
// Private methods
// ======================================================================
/**
* Adds further meta data to the given {@link CatalogAttribute}
* {@link Core}.
*
* @param catalogComponent
* The parent {@link CatalogComponent}.
* @param catalogAttributeCore
* The {@code CatalogAttribute} {@code Core}.
*/
private void adjustCatalogAttributeCore(Entity catalogComponent, Core catalogAttributeCore) {
EntityType entityType = request.modelManager.getEntityType(catalogComponent.getName());
Attribute attribute = entityType.getAttribute(catalogAttributeCore.getValues().get(Entity.ATTR_NAME).extract());
Map<String, Value> values = catalogAttributeCore.getValues();
Value enumerationClass = ValueType.STRING.create(VATTR_ENUMERATION_CLASS);
values.put(VATTR_ENUMERATION_CLASS, enumerationClass);
if (attribute.getValueType().isEnumerationType()) {
enumerationClass.set(attribute.getEnumClass().getName());
}
Value scalarType = ValueType.ENUMERATION.create(ScalarType.class, VATTR_SCALAR_TYPE);
scalarType.set(ScalarType.valueOf(attribute.getValueType().toSingleType().name()));
values.put(VATTR_SCALAR_TYPE, scalarType);
values.put(VATTR_SEQUENCE, ValueType.BOOLEAN.create(VATTR_SEQUENCE, attribute.getValueType().isSequence()));
}
/**
* Creates a new {@link EntityRecord} instance for given {@link Core}. The
* {@link EntityRecord} is internally mapped the its instance ID.
*
* @param core
* The {@code Core}.
* @return The created {@link EntityRecord} is returned.
*/
private EntityRecord<T> create(Core core) {
Constructor<T> constructor = null;
boolean isAccessible = false;
try {
constructor = request.entityConfig.getEntityClass().getDeclaredConstructor(Core.class);
isAccessible = constructor.isAccessible();
constructor.setAccessible(true);
EntityRecord<T> entityRecord = new EntityRecord<>(constructor.newInstance(core), core);
entityRecords.put(core.getID(), entityRecord);
entities.add(entityRecord.entity);
return entityRecord;
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException
| InvocationTargetException e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
if (constructor != null) {
constructor.setAccessible(isAccessible);
}
}
}
}