| /******************************************************************************** |
| * 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()); |
| } |
| } |