blob: 433a83b6288d2e4afad699328c1718283cb29ceb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.syncope.core.persistence.neo4j.entity;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.to.OrgUnit;
import org.apache.syncope.common.lib.to.Provision;
import org.apache.syncope.common.lib.types.ConnConfProperty;
import org.apache.syncope.common.lib.types.ConnectorCapability;
import org.apache.syncope.common.lib.types.IdMImplementationType;
import org.apache.syncope.common.lib.types.TraceLevel;
import org.apache.syncope.core.persistence.api.entity.ConnInstance;
import org.apache.syncope.core.persistence.api.entity.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.Implementation;
import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
import org.apache.syncope.core.persistence.api.entity.policy.PropagationPolicy;
import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
import org.apache.syncope.core.persistence.common.validation.ExternalResourceCheck;
import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jAccountPolicy;
import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jPasswordPolicy;
import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jPropagationPolicy;
import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jPullPolicy;
import org.apache.syncope.core.persistence.neo4j.entity.policy.Neo4jPushPolicy;
import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
import org.springframework.data.annotation.Transient;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.PostLoad;
import org.springframework.data.neo4j.core.schema.Relationship;
@Node(Neo4jExternalResource.NODE)
@ExternalResourceCheck
public class Neo4jExternalResource extends AbstractProvidedKeyNode implements ExternalResource {
private static final long serialVersionUID = -6937712883512073278L;
public static final String NODE = "ExternalResource";
public static final String RESOURCE_CONNECTOR_REL = "RESOURCE_CONNECTOR";
public static final String RESOURCE_PASSWORD_POLICY_REL = "RESOURCE_PASSWORD_POLICY";
public static final String RESOURCE_ACCOUNT_POLICY_REL = "RESOURCE_ACCOUNT_POLICY";
public static final String RESOURCE_PROPAGATION_POLICY_REL = "RESOURCE_PROPAGATION_POLICY";
public static final String RESOURCE_PULL_POLICY_REL = "RESOURCE_PULL_POLICY";
public static final String RESOURCE_PUSH_POLICY_REL = "RESOURCE_PUSH_POLICY";
public static final String RESOURCE_PROVISION_SORTER_REL = "RESOURCE_PROVISION_SORTER";
public static final String RESOURCE_PROPAGATION_ACTIONS_REL = "RESOURCE_PROPAGATION_ACTIONS";
protected static final TypeReference<Set<ConnectorCapability>> CAPABILITY_TYPEREF =
new TypeReference<Set<ConnectorCapability>>() {
};
protected static final TypeReference<List<Provision>> PROVISION_TYPEREF =
new TypeReference<List<Provision>>() {
};
/**
* Should this resource enforce the mandatory constraints?
*/
@NotNull
private Boolean enforceMandatoryCondition = false;
/**
* Priority index for propagation ordering.
*/
private Integer propagationPriority;
@NotNull
private TraceLevel createTraceLevel = TraceLevel.FAILURES;
@NotNull
private TraceLevel updateTraceLevel = TraceLevel.FAILURES;
@NotNull
private TraceLevel deleteTraceLevel = TraceLevel.FAILURES;
@NotNull
private TraceLevel provisioningTraceLevel = TraceLevel.FAILURES;
/**
* Configuration properties that are override from the connector instance.
*/
private String jsonConf;
@NotNull
private Boolean overrideCapabilities = false;
private String capabilitiesOverride;
@Transient
private final Set<ConnectorCapability> capabilitiesOverrideSet = new HashSet<>();
private String provisions;
@Transient
private final List<Provision> provisionList = new ArrayList<>();
private String orgUnit;
/**
* The resource type is identified by the associated connector.
*/
@Relationship(type = RESOURCE_CONNECTOR_REL, direction = Relationship.Direction.OUTGOING)
private Neo4jConnInstance connector;
@Relationship(type = RESOURCE_PASSWORD_POLICY_REL, direction = Relationship.Direction.OUTGOING)
private Neo4jPasswordPolicy passwordPolicy;
@Relationship(type = RESOURCE_ACCOUNT_POLICY_REL, direction = Relationship.Direction.OUTGOING)
private Neo4jAccountPolicy accountPolicy;
@Relationship(type = RESOURCE_PROPAGATION_POLICY_REL, direction = Relationship.Direction.OUTGOING)
private Neo4jPropagationPolicy propagationPolicy;
@Relationship(type = RESOURCE_PULL_POLICY_REL, direction = Relationship.Direction.OUTGOING)
private Neo4jPullPolicy pullPolicy;
@Relationship(type = RESOURCE_PUSH_POLICY_REL, direction = Relationship.Direction.OUTGOING)
private Neo4jPushPolicy pushPolicy;
@Relationship(type = RESOURCE_PROVISION_SORTER_REL, direction = Relationship.Direction.OUTGOING)
private Neo4jImplementation provisionSorter;
@Relationship(type = RESOURCE_PROPAGATION_ACTIONS_REL, direction = Relationship.Direction.OUTGOING)
private SortedSet<Neo4jImplementationRelationship> propagationActions = new TreeSet<>();
@Transient
private List<Neo4jImplementation> sortedPropagationActions = new SortedSetList<>(
propagationActions, Neo4jImplementationRelationship.builder());
@Override
public boolean isEnforceMandatoryCondition() {
return enforceMandatoryCondition;
}
@Override
public void setEnforceMandatoryCondition(final boolean enforceMandatoryCondition) {
this.enforceMandatoryCondition = enforceMandatoryCondition;
}
@Override
public Optional<Provision> getProvisionByAnyType(final String anyType) {
return getProvisions().stream().
filter(provision -> provision.getAnyType().equals(anyType)).findFirst();
}
@Override
public Optional<Provision> getProvisionByObjectClass(final String objectClass) {
return getProvisions().stream().
filter(provision -> provision.getObjectClass().equals(objectClass)).findFirst();
}
@Override
public List<Provision> getProvisions() {
return provisionList;
}
@Override
public OrgUnit getOrgUnit() {
return Optional.ofNullable(orgUnit).map(ou -> POJOHelper.deserialize(ou, OrgUnit.class)).orElse(null);
}
@Override
public void setOrgUnit(final OrgUnit orgUnit) {
this.orgUnit = orgUnit == null ? null : POJOHelper.serialize(orgUnit);
}
@Override
public Integer getPropagationPriority() {
return propagationPriority;
}
@Override
public void setPropagationPriority(final Integer propagationPriority) {
this.propagationPriority = propagationPriority;
}
@Override
public TraceLevel getCreateTraceLevel() {
return createTraceLevel;
}
@Override
public void setCreateTraceLevel(final TraceLevel createTraceLevel) {
this.createTraceLevel = createTraceLevel;
}
@Override
public TraceLevel getDeleteTraceLevel() {
return deleteTraceLevel;
}
@Override
public void setDeleteTraceLevel(final TraceLevel deleteTraceLevel) {
this.deleteTraceLevel = deleteTraceLevel;
}
@Override
public TraceLevel getUpdateTraceLevel() {
return updateTraceLevel;
}
@Override
public void setUpdateTraceLevel(final TraceLevel updateTraceLevel) {
this.updateTraceLevel = updateTraceLevel;
}
@Override
public TraceLevel getProvisioningTraceLevel() {
return provisioningTraceLevel;
}
@Override
public void setProvisioningTraceLevel(final TraceLevel provisioningTraceLevel) {
this.provisioningTraceLevel = provisioningTraceLevel;
}
@Override
public Set<ConnConfProperty> getConfOverride() {
Set<ConnConfProperty> confOverride = new HashSet<>();
if (!StringUtils.isBlank(jsonConf)) {
confOverride.addAll(List.of(POJOHelper.deserialize(jsonConf, ConnConfProperty[].class)));
}
return confOverride;
}
@Override
public void setConfOverride(final Set<ConnConfProperty> confOverride) {
jsonConf = POJOHelper.serialize(new HashSet<>(confOverride));
}
@Override
public boolean isOverrideCapabilities() {
return overrideCapabilities;
}
@Override
public void setOverrideCapabilities(final boolean overrideCapabilities) {
this.overrideCapabilities = overrideCapabilities;
}
@Override
public Set<ConnectorCapability> getCapabilitiesOverride() {
return capabilitiesOverrideSet;
}
@Override
public ConnInstance getConnector() {
return connector;
}
@Override
public void setConnector(final ConnInstance connector) {
checkType(connector, Neo4jConnInstance.class);
this.connector = (Neo4jConnInstance) connector;
}
@Override
public AccountPolicy getAccountPolicy() {
return accountPolicy;
}
@Override
public void setAccountPolicy(final AccountPolicy accountPolicy) {
checkType(accountPolicy, Neo4jAccountPolicy.class);
this.accountPolicy = (Neo4jAccountPolicy) accountPolicy;
}
@Override
public PasswordPolicy getPasswordPolicy() {
return passwordPolicy;
}
@Override
public void setPasswordPolicy(final PasswordPolicy passwordPolicy) {
checkType(passwordPolicy, Neo4jPasswordPolicy.class);
this.passwordPolicy = (Neo4jPasswordPolicy) passwordPolicy;
}
@Override
public PropagationPolicy getPropagationPolicy() {
return propagationPolicy;
}
@Override
public void setPropagationPolicy(final PropagationPolicy propagationPolicy) {
checkType(propagationPolicy, Neo4jPropagationPolicy.class);
this.propagationPolicy = (Neo4jPropagationPolicy) propagationPolicy;
}
@Override
public PullPolicy getPullPolicy() {
return pullPolicy;
}
@Override
public void setPullPolicy(final PullPolicy pullPolicy) {
checkType(pullPolicy, Neo4jPullPolicy.class);
this.pullPolicy = (Neo4jPullPolicy) pullPolicy;
}
@Override
public PushPolicy getPushPolicy() {
return pushPolicy;
}
@Override
public void setPushPolicy(final PushPolicy pushPolicy) {
checkType(pushPolicy, Neo4jPushPolicy.class);
this.pushPolicy = (Neo4jPushPolicy) pushPolicy;
}
@Override
public Implementation getProvisionSorter() {
return provisionSorter;
}
@Override
public void setProvisionSorter(final Implementation provisionSorter) {
checkType(provisionSorter, Neo4jImplementation.class);
checkImplementationType(provisionSorter, IdMImplementationType.PROVISION_SORTER);
this.provisionSorter = (Neo4jImplementation) provisionSorter;
}
@Override
public boolean add(final Implementation propagationAction) {
checkType(propagationAction, Neo4jImplementation.class);
checkImplementationType(propagationAction, IdMImplementationType.PROPAGATION_ACTIONS);
return sortedPropagationActions.contains((Neo4jImplementation) propagationAction)
|| sortedPropagationActions.add((Neo4jImplementation) propagationAction);
}
@Override
public List<? extends Implementation> getPropagationActions() {
return sortedPropagationActions;
}
protected void json2list(final boolean clearFirst) {
if (clearFirst) {
getCapabilitiesOverride().clear();
getProvisions().clear();
}
if (capabilitiesOverride != null) {
getCapabilitiesOverride().addAll(POJOHelper.deserialize(capabilitiesOverride, CAPABILITY_TYPEREF));
}
if (provisions != null) {
getProvisions().addAll(POJOHelper.deserialize(provisions, PROVISION_TYPEREF));
}
}
@PostLoad
public void postLoad() {
sortedPropagationActions = new SortedSetList<>(propagationActions, Neo4jImplementationRelationship.builder());
json2list(false);
}
public void postSave() {
json2list(true);
}
public void list2json() {
capabilitiesOverride = POJOHelper.serialize(getCapabilitiesOverride());
provisions = POJOHelper.serialize(getProvisions());
}
}