blob: dad79c4f0ea2146d6af58c6506bd15856282df6f [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.lookup.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.model.ContextComponent;
import org.eclipse.mdm.api.base.model.ContextRoot;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
/**
* Repository for {@link EntityConfig}s.
*
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
*/
public final class EntityConfigRepository {
// ======================================================================
// Instance variables
// ======================================================================
// root types
private final Map<Key<?>, EntityConfig<?>> entityConfigs = new HashMap<>();
// child types (implicit load only!)
private final Map<Key<?>, EntityConfig<?>> childConfigs = new HashMap<>();
private final Map<String, EntityConfig<?>> contextConfigs = new HashMap<>();
// ======================================================================
// Public methods
// ======================================================================
/**
* Returns the {@link EntityConfig} associated with given {@link Key}. This
* method tries to find the associated {@code EntityConfig} in the root
* configurations. If it is not found there, then it tries to find it in the
* child {@code EntityConfig}s.
*
* @param <T> The entity type.
* @param key Used as identifier.
* @return The {@code EntityConfig} is returned.
* @throws IllegalArgumentException Thrown if unable to find associated
* {@code EntityConfig}.
*/
public <T extends Entity> EntityConfig<T> find(Key<T> key) {
Optional<EntityConfig<T>> entityConfig = get(entityConfigs, key);
if (entityConfig.isPresent()) {
return entityConfig.get();
}
return get(childConfigs, key)
.orElseThrow(() -> new IllegalArgumentException("Entity configuration not found."));
}
/**
* Returns the {@link EntityConfig} associated with given {@link Key}. This
* method tries to find the associated {@code EntityConfig} in the root
* configurations.
*
* @param <T> The entity type.
* @param key Used as identifier.
* @return The {@code EntityConfig} is returned.
* @throws IllegalArgumentException Thrown if unable to find associated
* {@code EntityConfig}.
*/
public <T extends Entity> EntityConfig<T> findRoot(Key<T> key) {
return get(entityConfigs, key)
.orElseThrow(() -> new IllegalArgumentException("Entity configuration not found."));
}
/**
* Returns the {@link EntityConfig} associated with given {@link Key}. This
* method tries to find the associated {@code EntityConfig} in the child
* configurations.
*
* @param <T> The entity type.
* @param key Used as identifier.
* @return The {@code EntityConfig} is returned.
* @throws IllegalArgumentException Thrown if unable to find associated
* {@code EntityConfig}.
*/
public <T extends Entity> EntityConfig<T> findImplicit(Key<T> key) {
return get(childConfigs, key)
.orElseThrow(() -> new IllegalArgumentException("Entity configuration not found."));
}
/**
* Returns the {@link EntityConfig} associated with given {@link EntityType}.
*
* @param entityType Its name is used as identifier.
* @return The {@code EntityConfig} is returned.
* @throws IllegalArgumentException Thrown if unable to find associated
* {@code EntityConfig}.
*/
public EntityConfig<?> find(EntityType entityType) {
Optional<EntityConfig<?>> entityConfig = entityConfigs.values().stream()
.filter(ec -> ec.getEntityType().equals(entityType)).findFirst();
if (entityConfig.isPresent()) {
// entity config is a root type
return entityConfig.get();
}
entityConfig = childConfigs.values().stream().filter(ec -> ec.getEntityType().equals(entityType)).findFirst();
if (entityConfig.isPresent()) {
// entity config is an implicitly loaded child type
return entityConfig.get();
}
EntityConfig<?> config = contextConfigs.get(entityType.getName());
if (config == null) {
throw new IllegalArgumentException("Entity configuration for type '" + entityType + "' not found.");
}
// config is either a context component or context sensor type
return config;
}
/**
* Stores given {@link EntityConfig} in this repository.
*
* @param entityConfig The {@code EntityConfig}.
* @throws IllegalArgumentException Thrown if an attempt to overwrite an
* existing {@code EntityConfig} is recorded.
*/
public void register(EntityConfig<?> entityConfig) {
registerChildConfigs(entityConfig);
EntityConfig<?> currentByClass = entityConfigs.put(entityConfig.getKey(), entityConfig);
if (currentByClass != null) {
throw new IllegalArgumentException("It is not allowed to overwrite existing configurations.");
}
}
// ======================================================================
// Private methods
// ======================================================================
/**
* Recursively registers all child configurations of given {@link EntityConfig}.
*
* @param entityConfig The {@code EntityConfig}.
* @throws IllegalArgumentException Thrown if an attempt to overwrite an
* existing {@code EntityConfig} is recorded.
*/
private void registerChildConfigs(EntityConfig<?> entityConfig) {
Class<? extends Entity> entityClass = entityConfig.getEntityClass();
if (ContextRoot.class.equals(entityClass) || ContextComponent.class.equals(entityClass)) {
for (EntityConfig<?> childConfig : entityConfig.getChildConfigs()) {
if (contextConfigs.put(childConfig.getEntityType().getName(), childConfig) != null) {
throw new IllegalArgumentException("It is not allowed to overwrite existing configurations.");
}
registerChildConfigs(childConfig);
}
return;
}
for (EntityConfig<?> childConfig : entityConfig.getChildConfigs()) {
if (childConfigs.put(childConfig.getKey(), childConfig) != null) {
throw new IllegalArgumentException("It is not allowed to overwrite existing configurations.");
}
registerChildConfigs(childConfig);
}
}
/**
* Retrieves the {@link EntityConfig} associated with given {@link Key} from
* given {@code Map}.
*
* @param <T> The entity type.
* @param entityConfigs Used to retrieve requested {@code EntityConfig}.
* @param key Used as identifier.
* @return {@code Optional} is empty if {@code EntityConfig} not found.
*/
@SuppressWarnings("unchecked")
private static <T extends Entity> Optional<EntityConfig<T>> get(Map<Key<?>, EntityConfig<?>> entityConfigs,
Key<T> key) {
return Optional.ofNullable((EntityConfig<T>) entityConfigs.get(key));
}
}