blob: 41abfc29ea013a02d9a9f3a25cdbde5e9ebc048c [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
package org.eclipse.mdm.api.odsadapter.query;
import static org.eclipse.mdm.api.dflt.model.CatalogAttribute.VATTR_ENUMERATION_NAME;
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.HashSet;
import java.util.Optional;
import java.util.Set;
import org.eclipse.mdm.api.base.adapter.ChildrenStore;
import org.eclipse.mdm.api.base.adapter.Core;
import org.eclipse.mdm.api.base.adapter.DefaultCore;
import org.eclipse.mdm.api.base.adapter.EntityStore;
import org.eclipse.mdm.api.base.model.AxisType;
import org.eclipse.mdm.api.base.model.BaseEntity;
import org.eclipse.mdm.api.base.model.ContextType;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.EnumRegistry;
import org.eclipse.mdm.api.base.model.Enumeration;
import org.eclipse.mdm.api.base.model.EnumerationValue;
import org.eclipse.mdm.api.base.model.Interpolation;
import org.eclipse.mdm.api.base.model.ScalarType;
import org.eclipse.mdm.api.base.model.SequenceRepresentation;
import org.eclipse.mdm.api.base.model.TypeSpecification;
import org.eclipse.mdm.api.base.model.User;
import org.eclipse.mdm.api.base.model.ValueType;
import org.eclipse.mdm.api.base.model.VersionState;
import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
import org.eclipse.mdm.api.dflt.model.EntityFactory;
import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
/**
* ODS implementation of the {@link EntityFactory}.
*
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
*/
public final class ODSEntityFactory extends EntityFactory {
// ======================================================================
// Class variables
// ======================================================================
private static final Set<Class<? extends EnumerationValue>> ENUM_CLASSES = new HashSet<>();
static {
ENUM_CLASSES.add(ScalarType.class);
ENUM_CLASSES.add(VersionState.class);
ENUM_CLASSES.add(Interpolation.class);
ENUM_CLASSES.add(AxisType.class);
ENUM_CLASSES.add(SequenceRepresentation.class);
ENUM_CLASSES.add(TypeSpecification.class);
}
// ======================================================================
// Instance variables
// ======================================================================
private final ODSModelManager modelManager;
private final Optional<User> loggedInUser;
// ======================================================================
// Constructors
// ======================================================================
/**
* Constructor.
*
* @param modelManager Used to create {@link Core}s.
* @param loggedInUser The logged in {@link User}.
*/
public ODSEntityFactory(ODSModelManager modelManager, Optional<User> loggedInUser) {
this.modelManager = modelManager;
this.loggedInUser = loggedInUser;
}
// ======================================================================
// Public methods
// ======================================================================
/**
* Extracts the {@link Core} from an {@link Entity} instance. This method
* effectively makes access to the Core of a BaseEntity publicly available (by
* calling the corresponding protected method of BaseEntityFactory, which is
* this class's superclass) to users of ODSEntityFactory.
*
* @param entity The {@link Entity} from which to extract the {@link Core}.
* @return The entity's {@link Core}.
*/
public static Core extract(Entity entity) {
if (entity instanceof BaseEntity) {
return getCore((BaseEntity) entity);
} else {
throw new IllegalArgumentException("Entity of type '" + entity.getClass().getSimpleName()
+ "' does not extend '" + BaseEntity.class.getName() + "'");
}
}
/**
* Create an instance of a class implementing the {@link Entity} interface with
* core as the instance's {@link Core}. This method effectively makes the
* protected BaseEntity constructor publicly available (by calling the
* corresponding protected method of BaseEntityFactory, which is this class's
* superclass) to users of ODSEntityFactory.
*
* @param clazz The class to instantiate, must implement the {@link Entity}
* interface.
* @param core The {@link Core} to use for the newly created instance.
* @return The newly created instance.
*/
@SuppressWarnings("unchecked")
public <T extends Entity> T createEntity(Class<T> clazz, Core core) {
if (BaseEntity.class.isAssignableFrom(clazz)) {
return (T) createBaseEntity(clazz.asSubclass(BaseEntity.class), core);
} else {
throw new IllegalArgumentException(
"Class '" + clazz.getSimpleName() + "' does not extend '" + BaseEntity.class.getName() + "'");
}
}
// ======================================================================
// Protected methods
// ======================================================================
/**
* {@inheritDoc}
*/
@Override
protected Optional<User> getLoggedInUser() {
return loggedInUser;
}
/**
* {@inheritDoc}
*/
@Override
protected <T extends Entity> Core createCore(Class<T> entityClass) {
return createCore(new Key<>(entityClass));
}
/**
* {@inheritDoc}
*/
@Override
protected <T extends Entity> Core createCore(Class<T> entityClass, ContextType contextType) {
return createCore(new Key<>(entityClass, contextType));
}
/**
* {@inheritDoc}
*/
public static final EntityStore getMutableStore(BaseEntity entity) {
return EntityFactory.getMutableStore(entity);
}
/**
* {@inheritDoc}
*/
public static final EntityStore getPermanentStore(BaseEntity entity) {
return EntityFactory.getPermanentStore(entity);
}
/**
* {@inheritDoc}
*/
public static final ChildrenStore getChildrenStore(BaseEntity entity) {
return EntityFactory.getChildrenStore(entity);
}
/**
* {@inheritDoc}
*/
@Override
protected <T extends Entity> Core createCore(String name, Class<T> entityClass) {
EntityConfig<?> entityConfig = modelManager.getEntityConfig(modelManager.getEntityType(name));
if (!entityClass.equals(entityConfig.getEntityClass())) {
throw new IllegalArgumentException("Incompatible entity class expected '" + entityClass.getName()
+ "' but got '" + entityConfig.getEntityClass().getName() + "'");
}
Core core = new DefaultCore(entityConfig.getEntityType());
core.getValues().get(Entity.ATTR_MIMETYPE).set(entityConfig.getMimeType());
return core;
}
/**
* {@inheritDoc}
*/
@Override
protected void validateEnum(Enumeration<?> enumerationObj) {
EnumRegistry er = EnumRegistry.getInstance();
// check if enum is properly registered
if (er.get(enumerationObj.getName()) == null) {
throw new IllegalArgumentException("Given enum class '" + enumerationObj.getName() + "' is not supported.");
}
}
/**
* {@inheritDoc}
*/
@Override
protected <T extends BaseEntity> T createBaseEntity(Class<T> clazz, Core core) {
try {
Constructor<T> constructor = clazz.getDeclaredConstructor(Core.class);
try {
return constructor.newInstance(core);
} catch (IllegalAccessException exc) {
return super.createBaseEntity(clazz, core);
}
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException exc) {
throw new IllegalStateException(exc.getMessage(), exc);
}
}
// ======================================================================
// Private methods
// ======================================================================
/**
* Creates a configured {@link Core} for given {@link Key}.
*
* @param <T> The entity type.
* @param key Used as identifier to resolve the {@link EntityConfig}.
* @return The created {@code Core} is returned.
*/
private <T extends Entity> Core createCore(Key<T> key) {
EntityConfig<T> entityConfig = modelManager.findEntityConfig(key);
Core core = new DefaultCore(entityConfig.getEntityType());
core.getValues().get(Entity.ATTR_MIMETYPE).set(entityConfig.getMimeType());
if (CatalogAttribute.class.equals(entityConfig.getEntityClass())) {
core.getValues().put(VATTR_ENUMERATION_NAME, ValueType.STRING.create(VATTR_ENUMERATION_NAME));
core.getValues().put(VATTR_SCALAR_TYPE,
ValueType.ENUMERATION.create(EnumRegistry.getInstance().get("ScalarType"), VATTR_SCALAR_TYPE));
core.getValues().put(VATTR_SEQUENCE, ValueType.BOOLEAN.create(VATTR_SEQUENCE));
}
return core;
}
}