blob: 7c93adb834782a9eeffb93bda12c9d918539a41f [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2020 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.nodeprovider.control;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.mdm.api.base.ServiceNotProvidedException;
import org.eclipse.mdm.api.base.adapter.Attribute;
import org.eclipse.mdm.api.base.adapter.ModelManager;
import org.eclipse.mdm.api.base.model.BaseEntity;
import org.eclipse.mdm.api.base.model.Channel;
import org.eclipse.mdm.api.base.model.ChannelGroup;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.Environment;
import org.eclipse.mdm.api.base.model.Measurement;
import org.eclipse.mdm.api.base.model.Test;
import org.eclipse.mdm.api.base.model.TestStep;
import org.eclipse.mdm.api.base.query.ComparisonOperator;
import org.eclipse.mdm.api.base.query.DataAccessException;
import org.eclipse.mdm.api.base.query.Filter;
import org.eclipse.mdm.api.dflt.EntityManager;
import org.eclipse.mdm.api.dflt.model.Pool;
import org.eclipse.mdm.api.dflt.model.Project;
import org.eclipse.mdm.businessobjects.control.NavigationActivity;
import org.eclipse.mdm.businessobjects.utils.ServiceUtils;
import org.eclipse.mdm.connector.boundary.ConnectorService;
import org.eclipse.mdm.nodeprovider.entity.NodeProvider;
import org.eclipse.mdm.nodeprovider.utils.SerializationUtil;
import org.eclipse.mdm.protobuf.Mdm.Node;
/**
* Simple implementation of a {@link NodeProvider} which loads {@link Node}s
* based on {@link NavigationActivity}. The returned Node hierachy is similar to
* the hierarchy stored in the datastore, without options to change the
* structure. For a configurable {@link NodeProvider} see
* {@link GenericNodeProvider}.
*
*/
public class DefaultNodeProvider implements NodeProvider {
private final NavigationActivity navigationActivity;
private final ConnectorService connectorService;
/**
* Construct a new {@link DefaultNodeProvider} using the given
* {@link ConnectorService}.
*
* @param connectorService
*/
public DefaultNodeProvider(final ConnectorService connectorService) {
this.connectorService = connectorService;
this.navigationActivity = new NavigationActivity(connectorService);
}
/**
* Constructor for unit tests.
*
* @param navigationActivity
* @param connectorService
*/
DefaultNodeProvider(final NavigationActivity navigationActivity, final ConnectorService connectorService) {
this.connectorService = connectorService;
this.navigationActivity = navigationActivity;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return "Default";
}
/**
* {@inheritDoc}
*/
@Override
public List<Node> getRoots() {
return getChildren(null);
}
/**
* {@inheritDoc}
*/
@Override
public List<Node> getChildren(final Node parent) {
if (parent == null) {
return navigationActivity.getEnvironments().stream().map(this::convertNode).collect(Collectors.toList());
} else {
return convert(parent);
}
}
public Optional<? extends Entity> getParent(final Entity child) {
EntityManager entityManager = connectorService.getContextByName(child.getSourceName()).getEntityManager()
.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
String typeName = ServiceUtils.workaroundForTypeMapping(child.getTypeName());
if (compareTypes(Project.class, typeName)) {
return Optional.of(entityManager.loadEnvironment());
} else if (compareTypes(Pool.class, typeName)) {
return entityManager.loadParent(child, Project.class);
} else if (compareTypes(Test.class, typeName)) {
return entityManager.loadParent(child, Pool.class);
} else if (compareTypes(TestStep.class, typeName)) {
return entityManager.loadParent(child, Test.class);
} else if (compareTypes(Measurement.class, typeName)) {
return entityManager.loadParent(child, TestStep.class);
} else if (compareTypes(ChannelGroup.class, typeName)) {
return entityManager.loadParent(child, Measurement.class);
} else if (compareTypes(Channel.class, typeName)) {
return entityManager.loadParent(child, ChannelGroup.class);
} else {
return Optional.empty();
}
}
public Entity getEntity(final Node child) {
EntityManager entityManager = connectorService.getContextByName(child.getSource()).getEntityManager()
.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
String typeName = ServiceUtils.workaroundForTypeMapping(child.getType());
if (compareTypes(Project.class, typeName)) {
return entityManager.load(Project.class, child.getId());
} else if (compareTypes(Pool.class, typeName)) {
return entityManager.load(Pool.class, child.getId());
} else if (compareTypes(Test.class, typeName)) {
return entityManager.load(Test.class, child.getId());
} else if (compareTypes(TestStep.class, typeName)) {
return entityManager.load(TestStep.class, child.getId());
} else if (compareTypes(Measurement.class, typeName)) {
return entityManager.load(Measurement.class, child.getId());
} else if (compareTypes(ChannelGroup.class, typeName)) {
return entityManager.load(ChannelGroup.class, child.getId());
} else if (compareTypes(Channel.class, typeName)) {
return entityManager.load(Channel.class, child.getId());
} else {
throw new DataAccessException("Cannot load entity with type " + typeName + " and id" + child.getId());
}
}
/**
* {@inheritDoc}
*/
@Override
public List<Node> getTreePath(Node node) {
List<Node> nodes = new ArrayList<>();
Optional<? extends Entity> current = Optional.of(getEntity(node));
while (current.isPresent()) {
nodes.add(convertNode(current.get()));
current = getParent(current.get());
}
Collections.reverse(nodes);
return nodes;
}
private List<Node> convert(final Node parent) {
String typeName = ServiceUtils.workaroundForTypeMapping(parent.getType());
String source = parent.getSource();
List<? extends BaseEntity> entities;
String parentId = parent.getId();
boolean hasParentId = StringUtils.isNotBlank(parentId);
if (compareTypes(Environment.class, typeName)) {
entities = navigationActivity.getProjects(source);
} else if (hasParentId && compareTypes(Project.class, typeName)) {
entities = navigationActivity.getPools(source, parentId);
} else if (hasParentId && compareTypes(Pool.class, typeName)) {
entities = navigationActivity.getTests(source, parentId);
} else if (hasParentId && compareTypes(Test.class, typeName)) {
entities = navigationActivity.getTestSteps(source, parentId);
} else if (hasParentId && compareTypes(TestStep.class, typeName)) {
entities = navigationActivity.getMeasurements(source, parentId);
} else if (hasParentId && compareTypes(Measurement.class, typeName)) {
entities = navigationActivity.getChannelGroups(source, parentId);
} else if (hasParentId && compareTypes(ChannelGroup.class, typeName)) {
entities = navigationActivity.getChannels(source, parentId);
} else if (compareTypes(Channel.class, typeName)) {
entities = Collections.emptyList();
} else {
entities = navigationActivity.getEnvironments();
}
return convertNodes(entities);
}
private <T extends Entity> boolean compareTypes(final Class<T> typeClass, final String typeName) {
return typeClass.getSimpleName().equals(typeName);
}
private <T extends Entity> List<Node> convertNodes(final List<T> entities) {
return entities.stream().map(this::convertNode).collect(Collectors.toList());
}
private Node convertNode(Entity entity) {
ModelManager modelManager = connectorService.getContextByName(entity.getSourceName()).getModelManager()
.orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
Attribute idAttribute = modelManager.getEntityType(entity).getIDAttribute();
Filter filter = Filter.and().add(ComparisonOperator.EQUAL.create(idAttribute, entity.getID()));
return SerializationUtil.createNode(entity.getSourceName(),
ServiceUtils.workaroundForTypeMapping(entity.getTypeName()), entity.getID(), idAttribute.getName(),
filter, entity.getName());
}
}