Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.finos.legend.sdlc.server.resources.EntityAccessResource Maven / Gradle / Ivy
// Copyright 2020 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.finos.legend.sdlc.server.resources;
import org.eclipse.collections.api.factory.Maps;
import org.finos.legend.sdlc.domain.model.entity.Entity;
import org.finos.legend.sdlc.server.domain.api.entity.EntityAccessContext;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;
abstract class EntityAccessResource extends BaseResource
{
private static final char TAGGED_VALUE_DELIMITER = '/';
protected List getEntityPaths(EntityAccessContext entityAccessContext, Set classifierPaths, Set packages, boolean includeSubPackages, String nameRegex, Set stereotypes, Collection taggedValueRegexes)
{
Predicate entityPathPredicate = getEntityPathPredicate(packages, includeSubPackages, nameRegex);
Predicate classifierPathPredicate = getClassifierPathPredicate(classifierPaths);
Predicate> contentPredicate = getContentPredicate(stereotypes, taggedValueRegexes);
return entityAccessContext.getEntityPaths(entityPathPredicate, classifierPathPredicate, contentPredicate);
}
protected List getEntities(EntityAccessContext entityAccessContext, Set classifierPaths, Set packages, boolean includeSubPackages, String nameRegex, Set stereotypes, Collection taggedValueRegexes)
{
Predicate entityPathPredicate = getEntityPathPredicate(packages, includeSubPackages, nameRegex);
Predicate classifierPathPredicate = getClassifierPathPredicate(classifierPaths);
Predicate> contentPredicate = getContentPredicate(stereotypes, taggedValueRegexes);
return entityAccessContext.getEntities(entityPathPredicate, classifierPathPredicate, contentPredicate);
}
private Predicate getEntityPathPredicate(Set packages, boolean includeSubPackages, String nameRegex)
{
Pattern namePattern = compileRegex(nameRegex);
if (packages == null)
{
return (namePattern == null) ? null : path -> pathMatchesName(path, namePattern);
}
switch (packages.size())
{
case 0:
{
return (namePattern == null) ? null : path -> pathMatchesName(path, namePattern);
}
case 1:
{
String pkg = packages.stream().findAny().get();
if (namePattern == null)
{
return includeSubPackages ? path -> pathMatchesPackageOrSubPackage(path, pkg) : path -> pathMatchesPackage(path, pkg);
}
return includeSubPackages ? path -> pathMatchesPackageOrSubPackageAndName(path, pkg, namePattern) : path -> pathMatchesPackageAndName(path, pkg, namePattern);
}
default:
{
if (namePattern == null)
{
return includeSubPackages ? path -> pathMatchesAnyPackageOrSubPackage(path, packages) : path -> pathMatchesAnyPackage(path, packages);
}
return includeSubPackages ? path -> pathMatchesAnyPackageOrSubpackageAndName(path, packages, namePattern) : path -> pathMatchesAnyPackageAndName(path, packages, namePattern);
}
}
}
private Predicate getClassifierPathPredicate(Set classifierPaths)
{
if (classifierPaths == null)
{
return null;
}
switch (classifierPaths.size())
{
case 0:
{
return null;
}
case 1:
{
String classifierPath = classifierPaths.stream().findAny().get();
return classifierPath::equals;
}
default:
{
return classifierPaths::contains;
}
}
}
private Predicate> getContentPredicate(Set stereotypes, Collection taggedValueRegexes)
{
Predicate> predicate = null;
if ((stereotypes != null) && !stereotypes.isEmpty())
{
predicate = content -> entityHasAnyStereotype(content, stereotypes);
}
if ((taggedValueRegexes != null) && !taggedValueRegexes.isEmpty())
{
Map taggedValuePatterns = Maps.mutable.ofInitialCapacity(taggedValueRegexes.size());
for (String taggedValueRegex : taggedValueRegexes)
{
int delimIndex = taggedValueRegex.indexOf(TAGGED_VALUE_DELIMITER);
String tag;
String regex;
if (delimIndex < 0)
{
tag = taggedValueRegex;
regex = "";
}
else
{
tag = taggedValueRegex.substring(0, delimIndex).trim();
regex = (delimIndex == taggedValueRegex.length() - 1) ? "" : taggedValueRegex.substring(delimIndex + 1).trim();
}
Pattern pattern = compileRegex(regex);
if (pattern != null)
{
Pattern old = taggedValuePatterns.put(tag, pattern);
if (old != null)
{
String oldRegex = old.pattern();
if (!oldRegex.equals(regex))
{
// combine patterns disjunctively
String newRegex = (((old.flags() & Pattern.LITERAL) == Pattern.LITERAL) ? Pattern.quote(oldRegex) : oldRegex) + "|" + (((pattern.flags() & Pattern.LITERAL) == Pattern.LITERAL) ? Pattern.quote(regex) : regex);
Pattern newPattern = Pattern.compile(newRegex, Pattern.CASE_INSENSITIVE);
taggedValuePatterns.put(tag, newPattern);
}
}
}
}
Predicate> taggedValuePred = content -> entityMatchesAnyTaggedValuePattern(content, taggedValuePatterns);
predicate = (predicate == null) ? taggedValuePred : predicate.and(taggedValuePred);
}
return predicate;
}
private static Pattern compileRegex(String regex)
{
if (regex == null)
{
return null;
}
try
{
return Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
}
catch (Exception ignore)
{
// Not a valid regex, so interpret as a literal string
return Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
}
}
private static boolean pathMatchesName(String path, Pattern namePattern)
{
return pathMatchesName(path, namePattern, path.lastIndexOf(':'));
}
private static boolean pathMatchesPackage(String path, String pkg)
{
return pathMatchesPackage(path, pkg, path.lastIndexOf(':'));
}
private static boolean pathMatchesPackageOrSubPackage(String path, String pkg)
{
return pathMatchesPackageOrSubPackage(path, pkg, path.lastIndexOf(':'));
}
private static boolean pathMatchesAnyPackage(String path, Set packages)
{
return pathMatchesAnyPackage(path, packages, path.lastIndexOf(':'));
}
private static boolean pathMatchesAnyPackageOrSubPackage(String path, Set packagesWithTrailingColons)
{
return pathMatchesAnyPackageOrSubPackage(path, packagesWithTrailingColons, path.lastIndexOf(':'));
}
private static boolean pathMatchesPackageAndName(String path, String pkg, Pattern namePattern)
{
int lastColonIndex = path.lastIndexOf(':');
return pathMatchesPackage(path, pkg, lastColonIndex) && pathMatchesName(path, namePattern, lastColonIndex);
}
private static boolean pathMatchesPackageOrSubPackageAndName(String path, String pkg, Pattern namePattern)
{
int lastColonIndex = path.lastIndexOf(':');
return pathMatchesPackageOrSubPackage(path, pkg, lastColonIndex) && pathMatchesName(path, namePattern, lastColonIndex);
}
private static boolean pathMatchesAnyPackageAndName(String path, Set packages, Pattern namePattern)
{
int lastColonIndex = path.lastIndexOf(':');
return pathMatchesName(path, namePattern, lastColonIndex) && pathMatchesAnyPackage(path, packages, lastColonIndex);
}
private static boolean pathMatchesAnyPackageOrSubpackageAndName(String path, Set packages, Pattern namePattern)
{
int lastColonIndex = path.lastIndexOf(':');
return pathMatchesName(path, namePattern, lastColonIndex) && pathMatchesAnyPackageOrSubPackage(path, packages, lastColonIndex);
}
private static boolean pathMatchesName(String path, Pattern namePattern, int lastColonIndex)
{
return namePattern.matcher(path).region(lastColonIndex + 1, path.length()).find();
}
private static boolean pathMatchesPackage(String path, String pkg, int lastColonIndex)
{
return (pkg.length() == (lastColonIndex - 1)) && path.startsWith(pkg);
}
private static boolean pathMatchesPackageOrSubPackage(String path, String pkg, int lastColonIndex)
{
return (pkg.length() <= (lastColonIndex - 1)) && (path.charAt(pkg.length()) == ':') && path.startsWith(pkg);
}
private static boolean pathMatchesAnyPackage(String path, Set packages, int lastColonIndex)
{
return packages.contains(path.substring(0, lastColonIndex - 1));
}
private static boolean pathMatchesAnyPackageOrSubPackage(String path, Set packages, int lastColonIndex)
{
String pathPackage = path.substring(0, lastColonIndex - 1);
return packages.contains(pathPackage) || packages.stream().anyMatch(pkg -> (pathPackage.length() > pkg.length()) && pathPackage.startsWith(pkg) && (pathPackage.charAt(pkg.length()) == ':'));
}
private static boolean entityHasAnyStereotype(Map entityContent, Set stereotypes)
{
Object entityStereotypes = entityContent.get("stereotypes");
if (entityStereotypes instanceof Iterable)
{
for (Object entityStereotype : (Iterable) entityStereotypes)
{
if (entityStereotype instanceof Map)
{
String stereotypePath = getAnnotationPath((Map) entityStereotype);
if ((stereotypePath != null) && stereotypes.contains(stereotypePath))
{
return true;
}
}
}
}
return false;
}
private static boolean entityMatchesAnyTaggedValuePattern(Map entityContent, Map taggedValuePatterns)
{
Object entityTaggedValues = entityContent.get("taggedValues");
if (entityTaggedValues instanceof Iterable)
{
for (Object entityTaggedValue : (Iterable) entityTaggedValues)
{
if (entityTaggedValue instanceof Map)
{
Object entityTag = ((Map) entityTaggedValue).get("tag");
if (entityTag instanceof Map)
{
String tagPath = getAnnotationPath((Map) entityTag);
if (tagPath != null)
{
Pattern pattern = taggedValuePatterns.get(tagPath);
if (pattern != null)
{
Object value = ((Map) entityTaggedValue).get("value");
if ((value instanceof String) && pattern.matcher((String) value).find())
{
return true;
}
}
}
}
}
}
}
return false;
}
private static String getAnnotationPath(Map annotationJson)
{
Object profile = annotationJson.get("profile");
if (profile instanceof String)
{
Object value = annotationJson.get("value");
if (value instanceof String)
{
return profile + "." + value;
}
}
return null;
}
}