blob: 3fd9245bfe7c71b7d0c24a9bf818bc37a8ca4111 [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2021 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.entity;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.eclipse.mdm.api.base.adapter.Attribute;
import org.eclipse.mdm.api.base.model.Environment;
import org.eclipse.mdm.api.dflt.ApplicationContext;
import org.eclipse.mdm.businessobjects.utils.ServiceUtils;
import org.eclipse.mdm.nodeprovider.control.GenericNodeProvider;
import org.eclipse.mdm.protobuf.Mdm.Node;
import com.google.common.base.Strings;
/**
* A {@link NodeProviderRoot} defines the configuration of a
* {@link GenericNodeProvider}. It consists of an ID to uniquely identify the
* NodeProvider and a name that is displayed to the user. Furthermore it may
* contain {@link NodeLevel}s for each data source name defining the roots of
* the navigation trees. The special data source name
* {@link NodeProviderRoot#WILDCARD} is used for the fallback {@link NodeLevel}
* that is used if no other entry is present.
*
*/
public class NodeProviderRoot {
public static final String WILDCARD = "*";
private String id;
private String name;
private Map<String, NodeLevel> contexts = new HashMap<>();
/**
* Default constructor
*/
public NodeProviderRoot() {
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the contexts
*/
public Map<String, NodeLevel> getContexts() {
return contexts;
}
/**
* @param contexts the contexts to set
*/
public void setContexts(Map<String, NodeLevel> contexts) {
this.contexts = contexts;
}
/**
* Get the {@link NodeLevel} for the given sourceName. If the given sourceName
* has no entry, the {@link NodeLevel} for the {@link NodeProviderRoot#WILDCARD}
* is returned.
*
* @param sourceName
* @return NodeLevel for the given sourceName
*/
public NodeLevel getNodeLevel(String sourceName) {
NodeLevel nl = contexts.get(sourceName);
if (nl == null) {
// if the NodeProviderRoot was constructed via NodeLevelUtil contexts already
// contains a NodeLevel for each source name. If still nothing is found we check
// the wildcard again just to be sure.
nl = contexts.get(WILDCARD);
}
return nl;
}
/**
* Find the parent NodeLevel for a given nodeLevel.
*
* @param context
* @param nodeLevel
* @return parent NodeLevel
*/
public NodeLevel getParentNodeLevel(ApplicationContext context, NodeLevel nodeLevel) {
NodeLevel n = getNodeLevel(context.getSourceName());
if (n.equals(nodeLevel)) {
return null;
}
while (n.getChild() != null && !nodeLevel.equals(n.getChild())) {
n = n.getChild();
}
return n;
}
/**
* Find the child NodeLevel for a given nodeLevel.
*
* @param context
* @param nodeLevel
* @return child NodeLevel
*/
public Optional<NodeLevel> getChildNodeLevel(ApplicationContext context, Node nodeLevel) {
NodeLevel childNodeLevel = null;
if (nodeLevel == null) {
childNodeLevel = getNodeLevel(context, Environment.class.getSimpleName(), null);
} else {
childNodeLevel = getNodeLevel(context, nodeLevel.getType(), nodeLevel.getIdAttribute());
if (childNodeLevel == null) {
return Optional.empty();
}
childNodeLevel = childNodeLevel.getChild();
}
return Optional.ofNullable(childNodeLevel);
}
/**
* @param context
* @param type
* @param filterAttribute
* @return NodeLevel for given type and idAttribute
*/
public NodeLevel getNodeLevel(ApplicationContext context, String type, String filterAttribute) {
NodeLevel n = getNodeLevel(context.getSourceName());
while (n != null && !nodeLevelMatches(n, type, filterAttribute)) {
n = n.getChild();
}
return n;
}
/**
* @param nodeLevel
* @param type
* @param filterAttribute
* @return true, if the given type and idAttribute matches the nodeLevel
*/
/**
* TODO 05.02.2021, jst: Match should respect labelAttributes / value precision
* to work properly for nested virtual nodes of same type with different value
* precision.
*
* Current fails in scenarios like:
*
* (...) | |---Test.DateCreated - YEAR | |---Test.DateCreated - MONTH | |---
* Test.DateCreated - DAY
*/
private boolean nodeLevelMatches(NodeLevel nodeLevel, String type, String filterAttribute) {
String first = nodeLevel.getFilterAttributes().stream().findFirst().map(Attribute::getName).orElse(null);
return ServiceUtils.workaroundForTypeMapping(type)
.equals(ServiceUtils.workaroundForTypeMapping(nodeLevel.getEntityType()))
&& (Strings.isNullOrEmpty(filterAttribute) || filterAttribute.equals(first));
}
}