All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cloud.security.ams.dcl.client.dcn.DcnBuilder Maven / Gradle / Ivy

The newest version!
/************************************************************************
 * © 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 ************************************************************************/
package com.sap.cloud.security.ams.dcl.client.dcn;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.sap.cloud.security.ams.dcl.client.annotation.Beta;
import com.sap.cloud.security.ams.dcl.client.el.AttributeName;
import com.sap.cloud.security.ams.dcl.client.el.Call;
import com.sap.cloud.security.ams.dcl.client.el.QualifiedName;
import com.sap.cloud.security.ams.dcl.client.el.QualifiedNamesBuilder;

@Beta
public final class DcnBuilder {
    private DcnBuilder() {
    }

    //
    //
    //

    public static QualifiedName q(String name) {
        return QualifiedNamesBuilder.globalParseQualifiedName(Objects.requireNonNull(name));
    }

    public static AttributeName a(String name) {
        return QualifiedNamesBuilder.globalParseAttributeName(Objects.requireNonNull(name));
    }

    //
    //
    //

    public static DcnSchemaBuilder schema() {
        return new DcnSchemaBuilderImpl();
    }

    public static DcnSchemaBuilder tenantSchema(QualifiedName dclPackage, String tenant) {
        return new DcnSchemaBuilderImpl(dclPackage, tenant);
    }

    //
    //
    //
    public static final String STAR = null;

    public static Rule grant(String action, String resource) {
        return grant0(asSingletonList(action), asSingletonList(resource), null);
    }

    public static Rule grant(List actions, String resource) {
        return grant0(actions, asSingletonList(resource), null);
    }

    public static Rule grant(String action, List resources) {
        return grant0(asSingletonList(action), resources, null);
    }

    public static Rule grant(List actions, List resources) {
        return grant0(actions, resources, null);
    }

    public static Rule grant(String action, String resource, Call condition) {
        return grant0(asSingletonList(action), asSingletonList(resource), condition);
    }

    public static Rule grant(List actions, String resource, Call condition) {
        return grant0(actions, asSingletonList(resource), condition);
    }

    public static Rule grant(String action, List resources, Call condition) {
        return grant0(asSingletonList(action), resources, condition);
    }

    public static Rule grant(List actions, List resources, Call condition) {
        return grant0(actions, resources, condition);
    }

    public static Rule grant(String action, String resource, boolean condition) {
        return grant0(asSingletonList(action), asSingletonList(resource), condition);
    }

    public static Rule grant(List actions, String resource, boolean condition) {
        return grant0(actions, asSingletonList(resource), condition);
    }

    public static Rule grant(String action, List resources, boolean condition) {
        return grant0(asSingletonList(action), resources, condition);
    }

    public static Rule grant(List actions, List resources, boolean condition) {
        return grant0(actions, resources, condition);
    }

    public static Rule grant(String action, String resource, AttributeName condition) {
        return grant0(asSingletonList(action), asSingletonList(resource), condition);
    }

    public static Rule grant(List actions, String resource, AttributeName condition) {
        return grant0(actions, asSingletonList(resource), condition);
    }

    public static Rule grant(String action, List resources, AttributeName condition) {
        return grant0(asSingletonList(action), resources, condition);
    }

    public static Rule grant(List actions, List resources, AttributeName condition) {
        return grant0(actions, resources, condition);
    }

    private static Rule grant0(List actions, List resources, Object condition) {
        expectNoEmptyStringOrNull(actions, "Action names must not be ");
        expectNoEmptyStringOrNull(resources, "Resource names must not be ");
        Rule result = new Rule();
        result.actions(actions);
        result.resources(resources);
        result.condition(condition);
        result.effect(Effect.GRANT);
        return result;
    }

    //
    //
    //

    private static final PolicyMember[] EMPTY_POLICY_MEMBER_ARRAY = new PolicyMember[0];

    public static Policy policy(QualifiedName qualifiedName) {
        return policy(qualifiedName, EMPTY_POLICY_MEMBER_ARRAY);
    }

    public static Policy policy(QualifiedName qualifiedName, PolicyMember... members) {
        expectPackageQualifiedName(qualifiedName);

        Policy result = new Policy();
        result.qualifiedName(qualifiedName);
        List uses = null;
        List rules = null;

        for (PolicyMember member : members) {
            if (member instanceof Rule) {
                Rule m = (Rule) member;
                if (rules == null) {
                    rules = new ArrayList<>();
                    result.rules(rules);
                }
                rules.add(m);
            } else if (member instanceof Use) {
                Use m = (Use) member;
                if (uses == null) {
                    uses = new ArrayList<>();
                    result.uses(uses);
                }
                uses.add(m);
            } else {
                throw new IllegalArgumentException("The following element cannot be added to a policy: " + member);
            }
        }
        return result;
    }

    /**
     * Creates {@link Policy} object and parses the qualifiedName to a {@code QualifiedName} object. From a performance perspective, it's better to
     * directly provide a {@code QualifiedName} object.
     * 
     * @param qualifiedName
     *            to be parsed qualifiedName
     * @return Policy object
     */
    public static Policy policy(String qualifiedName) {
        return policy(q(qualifiedName));
    }

    /**
     * Creates {@link Use} object and parses the qualifiedName to a {@code QualifiedName} object. From a performance perspective, it's better to
     * directly provide a {@code QualifiedName} object.
     * 
     * @param qualifiedName
     *            to be parsed qualifiedName
     * @param members
     *            to be added to the policy
     * @return Policy object
     */
    public static Policy policy(String qualifiedName, PolicyMember... members) {
        return policy(q(qualifiedName), members);
    }

    //
    //
    //

    public static Use use(Policy policy) {
        return use(policy.qualifiedName(), (List>) null);
    }

    public static Use use(Policy policy, List> restrictionsList) {
        return use(policy.qualifiedName(), restrictionsList);
    }

    public static Use use(QualifiedName qualifiedName) {
        return use(qualifiedName, (List>) null);
    }

    public static Use use(QualifiedName qualifiedName, List> restrictionsList) {
        expectPackageQualifiedName(qualifiedName);

        Use result = new Use();
        result.qualifiedPolicyName(qualifiedName);
        result.restrictions(restrictionsList);
        return result;
    }

    /**
     * Creates {@link Use} object and parses the qualifiedName to a {@code QualifiedName} object. From a performance perspective, it's better to
     * directly provide a {@code QualifiedName} or {@link Policy} object.
     * 
     * @param qualifiedName
     *            to be parsed qualifiedName
     * @return Use object
     */
    public static Use use(String qualifiedName) {
        return use(q(qualifiedName), (List>) null);
    }

    /**
     * Creates {@link Use} object and parses the qualifiedName to a {@code QualifiedName} object. From a performance perspective, it's better to
     * directly provide a {@code QualifiedName} or {@link Policy} object.
     * 
     * @param qualifiedName
     *            to be parsed qualifiedName
     * @param restrictionsList
     *            list of restrictions to be added
     * @return Use object
     */
    public static Use use(String qualifiedName, List> restrictionsList) {
        return use(q(qualifiedName), restrictionsList);
    }

    //
    //
    //

    public static Function function(QualifiedName qualifiedName, DataType returnType, Object coputation) {
        expectPackageQualifiedName(qualifiedName);

        Function result = new Function();
        result.qualifiedName(qualifiedName);
        result.result(coputation);
        result.returnType(returnType);
        return result;
    }

    /**
     * Creates {@link Function} object and parses the qualifiedName to a {@code QualifiedName} object. From a performance perspective, it's better to
     * directly provide a {@code QualifiedName} object.
     * 
     * @param qualifiedName
     *            to be parsed qualifiedName
     * @param computation
     *            function body
     * @return Function object
     */
    public static Function function(String qualifiedName, DataType returnType, Object computation) {
        return function(q(qualifiedName), returnType, computation);
    }

    //
    //
    //

    public static Call eq(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.EQ, o1, o2);
    }

    public static Call ne(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.NE, o1, o2);
    }

    public static Call lt(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.LT, o1, o2);
    }

    public static Call le(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.LE, o1, o2);
    }

    public static Call ge(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.GE, o1, o2);
    }

    public static Call gt(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.GT, o1, o2);
    }

    //

    public static Call and(Object... members) {
        check2(members.length, "AND");
        return Call.create(Call.QualifiedNames.AND, members);
    }

    public static Call and(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.AND, o1, o2);
    }

    public static Call and(Object o1, Object o2, Object o3) {
        return Call.create(Call.QualifiedNames.AND, o1, o2, o3);
    }

    public static Call andFrom(Collection members) {
        check2(members.size(), "AND");
        return Call.createFrom(Call.QualifiedNames.AND, members);
    }

    public static Call or(Object... members) {
        check2(members.length, "OR");
        return Call.create(Call.QualifiedNames.OR, members);
    }

    public static Call or(Object o1, Object o2) {
        return Call.create(Call.QualifiedNames.OR, o1, o2);
    }

    public static Call or(Object o1, Object o2, Object o3) {
        return Call.create(Call.QualifiedNames.OR, o1, o2, o3);
    }

    public static Call orFrom(Collection members) {
        check2(members.size(), "OR");
        return Call.createFrom(Call.QualifiedNames.OR, members);
    }

    public static Call in(Object o, Collection coll) {
        return Call.create(Call.QualifiedNames.IN, o, coll);
    }

    public static Call notIn(Object o, Collection coll) {
        return Call.create(Call.QualifiedNames.NOT_IN, o, coll);
    }

    public static Call isNull(AttributeName att) {
        return Call.create(Call.QualifiedNames.IS_NULL, att);
    }

    public static Call isNotNull(AttributeName att) {
        return Call.create(Call.QualifiedNames.IS_NOT_NULL, att);
    }

    public static Call like(Object value, String pattern) {
        return Call.create(Call.QualifiedNames.LIKE, value, pattern);
    }

    public static Call like(Object value, String pattern, String escape) {
        return Call.create(Call.QualifiedNames.LIKE, value, pattern, escape);
    }

    public static Call notLike(Object value, String pattern) {
        return Call.create(Call.QualifiedNames.NOT_LIKE, value, pattern);
    }

    public static Call notLike(Object value, String pattern, String escape) {
        return Call.create(Call.QualifiedNames.NOT_LIKE, value, pattern, escape);
    }

    public static Call between(Object value, Object lower, Object upper) {
        return Call.create(Call.QualifiedNames.BETWEEN, value, lower, upper);
    }

    public static Call notBetween(Object value, Object lower, Object upper) {
        return Call.create(Call.QualifiedNames.NOT_BETWEEN, value, lower, upper);
    }

    //
    //
    //

    public static Call call(QualifiedName function) {
        return Call.create(function);
    }

    public static Call call(Function function) {
        return Call.create(function.qualifiedName());
    }

    /**
     * Creates {@link Call} object and parses the qualifiedName to a {@code QualifiedName} object. From a performance perspective, it's better to
     * directly provide a {@code QualifiedName} object.
     * 
     * @param qualifiedName
     *            to be parsed qualifiedName
     * @return Call object
     */
    public static Call call(String qualifiedName) {
        return call(q(qualifiedName));
    }

    //
    //
    //

    @SafeVarargs
    public static  List list(T... args) {
        return Arrays.asList(args);
    }

    public static List actions(String... args) {
        return Arrays.asList(args);
    }

    public static List resources(String... args) {
        return Arrays.asList(args);
    }

    public static List restrict(Call... calls) {
        return list(calls);
    }

    //
    //
    //

    private static void check2(int count, String operation) {
        if (count < 2) {
            throw new IllegalArgumentException(operation + " needs at least two arguments. Only " + count + " given.");
        }
    }

    private static  List asSingletonList(T data) {
        return data != null ? Collections.singletonList(data) : null;
    }

    private static void expectPackageQualifiedName(QualifiedName qualifiedName) {
        if (qualifiedName == null) {
            throw new IllegalArgumentException("QualifiedName must not be null");
        }
        if (qualifiedName.size() < 2) {
            throw new IllegalArgumentException("QualifiedName must have at least two segments.");
        }
    }

    private static void expectNoEmptyStringOrNull(List data, String message) {
        if (data != null && !data.isEmpty()) {
            for (String d : data) {
                if (d == null) {
                    throw new IllegalArgumentException(message + "null.");
                }
                if (d.isEmpty()) {
                    throw new IllegalArgumentException(message + "empty.");
                }
            }
        }
    }
}