/*
* Copyright (c) 2010-2013 Evolveum
*
* 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 com.evolveum.midpoint.schema.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Element;
import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismReference;
import com.evolveum.midpoint.schema.CapabilityUtil;
import com.evolveum.midpoint.schema.constants.MidPointConstants;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationLockoutStatusCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationStatusCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationValidityCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.AddRemoveAttributeValuesCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.AuxiliaryObjectClassesCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CountObjectsCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CreateCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CredentialsCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.DeleteCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.LiveSyncCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.PagedSearchCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.PasswordCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ReadCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ScriptCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.TestConnectionCapabilityType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.UpdateCapabilityType;
import com.evolveum.prism.xml.ns._public.types_3.SchemaDefinitionType;
/**
* Methods that would belong to the ResourceType class but cannot go there
* because of JAXB.
*
* @author Radovan Semancik
*/
public class ResourceTypeUtil {
public static String getConnectorOid(PrismObject<ResourceType> resource) {
return getConnectorOid(resource.asObjectable());
}
public static String getConnectorOid(ResourceType resource) {
if (resource.getConnectorRef() != null) {
return resource.getConnectorRef().getOid();
} else if (resource.getConnector() != null) {
return resource.getConnector().getOid();
} else {
return null;
}
}
/**
* The usage of "resolver" is experimental. Let's see if it will be
* practical ...
*
* @see ObjectResolver
*/
public static ConnectorType getConnectorType(ResourceType resource, ObjectResolver resolver, OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
if (resource.getConnector() != null) {
return resource.getConnector();
} else if (resource.getConnectorRef() != null) {
return resolver.resolve(resource.getConnectorRef(), ConnectorType.class,
null, "resolving connector in " + resource, null, parentResult); // TODO task
} else {
return null;
}
}
@SuppressWarnings("unchecked")
public static PrismObject<ConnectorType> getConnectorIfPresent(PrismObject<ResourceType> resource) {
PrismReference existingConnectorRef = resource.findReference(ResourceType.F_CONNECTOR_REF);
if (existingConnectorRef == null || existingConnectorRef.isEmpty()) {
return null;
}
return (PrismObject<ConnectorType>) existingConnectorRef.getValue().getObject();
}
public static Element getResourceXsdSchema(ResourceType resource) {
XmlSchemaType xmlSchemaType = resource.getSchema();
if (xmlSchemaType == null) {
return null;
}
return ObjectTypeUtil.findXsdElement(xmlSchemaType);
}
public static Element getResourceXsdSchema(PrismObject<ResourceType> resource) {
PrismContainer<XmlSchemaType> xmlSchema = resource.findContainer(ResourceType.F_SCHEMA);
if (xmlSchema == null) {
return null;
}
return ObjectTypeUtil.findXsdElement(xmlSchema);
}
public static void setResourceXsdSchema(ResourceType resourceType, Element xsdElement) {
PrismObject<ResourceType> resource = resourceType.asPrismObject();
setResourceXsdSchema(resource, xsdElement);
}
public static void setResourceXsdSchema(PrismObject<ResourceType> resource, Element xsdElement) {
try {
PrismContainer<XmlSchemaType> schemaContainer = resource.findOrCreateContainer(ResourceType.F_SCHEMA);
PrismProperty<SchemaDefinitionType> definitionProperty = schemaContainer.findOrCreateProperty(XmlSchemaType.F_DEFINITION);
ObjectTypeUtil.setXsdSchemaDefinition(definitionProperty, xsdElement);
} catch (SchemaException e) {
// Should not happen
throw new IllegalStateException("Internal schema error: "+e.getMessage(),e);
}
}
/**
* Returns collection of capabilities. Note: there is difference between empty set and null.
* Empty set means that we know the resource has no capabilities. Null means that the
* capabilities were not yet determined.
*/
public static Collection<Object> getNativeCapabilitiesCollection(ResourceType resource) {
if (resource.getCapabilities() == null) {
// No capabilities, not initialized
return null;
}
CapabilityCollectionType nativeCap = resource.getCapabilities().getNative();
if (nativeCap == null) {
return null;
}
return nativeCap.getAny();
}
public static boolean hasSchemaGenerationConstraints(ResourceType resource){
if (resource == null){
return false;
}
if (resource.getSchema() == null){
return false;
}
if (resource.getSchema().getGenerationConstraints() == null){
return false;
}
List<QName> constainst = resource.getSchema().getGenerationConstraints().getGenerateObjectClass();
if (constainst == null){
return false;
}
return !constainst.isEmpty();
}
public static List<QName> getSchemaGenerationConstraints(ResourceType resource){
if (hasSchemaGenerationConstraints(resource)){
return resource.getSchema().getGenerationConstraints().getGenerateObjectClass();
}
return null;
}
public static List<QName> getSchemaGenerationConstraints(PrismObject<ResourceType> resource){
if (resource == null){
return null;
}
return getSchemaGenerationConstraints(resource.asObjectable());
}
/**
* Assumes that native capabilities are already cached.
*/
@Nullable
public static <T extends CapabilityType> T getEffectiveCapability(ResourceType resource, Class<T> capabilityClass) {
return getEffectiveCapability(resource, null, capabilityClass);
}
/**
* Assumes that native capabilities are already cached.
*/
public static <T extends CapabilityType> T getEffectiveCapability(ResourceType resource,
ResourceObjectTypeDefinitionType resourceObjectTypeDefinitionType,
Class<T> capabilityClass) {
T capability = getEffectiveCapabilityInternal(resource, resourceObjectTypeDefinitionType, capabilityClass);
if (CapabilityUtil.isCapabilityEnabled(capability)) {
return capability;
} else {
// Disabled or null capability, pretend that it is not there
return null;
}
}
private static <T extends CapabilityType> T getEffectiveCapabilityInternal(ResourceType resource,
ResourceObjectTypeDefinitionType resourceObjectTypeDefinitionType,
Class<T> capabilityClass) {
if (resourceObjectTypeDefinitionType != null && resourceObjectTypeDefinitionType.getConfiguredCapabilities() != null) {
T configuredCapability = CapabilityUtil.getCapability(resourceObjectTypeDefinitionType.getConfiguredCapabilities().getAny(), capabilityClass);
if (configuredCapability != null) {
return configuredCapability;
}
// No capability at the level of resource object type, continuing at the resource level
}
for (ConnectorInstanceSpecificationType additionalConnector: resource.getAdditionalConnector()) {
T connectorCapability = CapabilityUtil.getEffectiveCapability(additionalConnector.getCapabilities(), capabilityClass);
if (CapabilityUtil.isCapabilityEnabled(connectorCapability)) {
return connectorCapability;
}
}
return CapabilityUtil.getEffectiveCapability(resource.getCapabilities(), capabilityClass);
}
public static <T extends CapabilityType> boolean hasEffectiveCapability(ResourceType resource, Class<T> capabilityClass) {
return getEffectiveCapability(resource, capabilityClass) != null;
}
/**
* Assumes that native capabilities are already cached.
*/
public static List<Object> getAllCapabilities(ResourceType resource) throws SchemaException {
return getEffectiveCapabilities(resource, true);
}
/**
* Assumes that native capabilities are already cached.
*/
public static List<Object> getEffectiveCapabilities(ResourceType resource) throws SchemaException {
return getEffectiveCapabilities(resource, false);
}
private static List<Object> getEffectiveCapabilities(ResourceType resource, boolean includeDisabled) throws SchemaException {
List<Object> rv = new ArrayList<>();
if (resource.getCapabilities() == null) {
return rv;
}
List<Object> configuredCaps = resource.getCapabilities().getConfigured() != null ? resource.getCapabilities().getConfigured().getAny() : Collections.emptyList();
List<Object> nativeCaps = resource.getCapabilities().getNative() != null ? resource.getCapabilities().getNative().getAny() : Collections.emptyList();
for (Object configuredCapability : configuredCaps) {
if (includeDisabled || CapabilityUtil.isCapabilityEnabled(configuredCapability)) {
rv.add(configuredCapability);
}
}
for (Object nativeCapability: nativeCaps) {
if (!CapabilityUtil.containsCapabilityWithSameElementName(configuredCaps, nativeCapability)) {
if (includeDisabled || CapabilityUtil.isCapabilityEnabled(nativeCapability)) {
rv.add(nativeCapability);
}
}
}
return rv;
}
public static boolean isActivationCapabilityEnabled(ResourceType resource) {
return getEffectiveCapability(resource, ActivationCapabilityType.class) != null;
}
public static boolean isActivationLockoutStatusCapabilityEnabled(ResourceType resource) {
return getEffectiveActivationLockoutStatusCapability(resource) != null;
}
public static ActivationLockoutStatusCapabilityType getEffectiveActivationLockoutStatusCapability(ResourceType resource) {
ActivationCapabilityType act = getEffectiveCapability(resource, ActivationCapabilityType.class);
if (act == null || act.getLockoutStatus() == null || Boolean.FALSE.equals(act.getLockoutStatus().isEnabled())) {
return null;
} else {
return act.getLockoutStatus();
}
}
public static ActivationStatusCapabilityType getEffectiveActivationStatusCapability(ResourceType resource) {
ActivationCapabilityType act = getEffectiveCapability(resource, ActivationCapabilityType.class);
if (act == null || act.getStatus() == null || Boolean.FALSE.equals(act.getStatus().isEnabled())) {
return null;
} else {
return act.getStatus();
}
}
public static boolean isActivationStatusCapabilityEnabled(ResourceType resource) {
return getEffectiveActivationStatusCapability(resource) != null;
}
public static ActivationValidityCapabilityType getEffectiveActivationValidFromCapability(ResourceType resource) {
ActivationCapabilityType act = getEffectiveCapability(resource, ActivationCapabilityType.class);
if (act == null || act.getValidFrom() == null || Boolean.FALSE.equals(act.getValidFrom().isEnabled())) {
return null;
} else {
return act.getValidFrom();
}
}
public static ActivationValidityCapabilityType getEffectiveActivationValidToCapability(ResourceType resource) {
ActivationCapabilityType act = getEffectiveCapability(resource, ActivationCapabilityType.class);
if (act == null || act.getValidTo() == null || Boolean.FALSE.equals(act.getValidTo().isEnabled())) {
return null;
} else {
return act.getValidTo();
}
}
public static boolean isActivationValidityCapabilityEnabled(ResourceType resource) {
return getEffectiveActivationValidFromCapability(resource) != null || getEffectiveActivationValidToCapability(resource) != null;
}
public static boolean isCredentialsCapabilityEnabled(ResourceType resource) {
return getEffectiveCapability(resource, CredentialsCapabilityType.class) != null;
}
public static boolean isCreateCapabilityEnabled(ResourceType resource){
return getEffectiveCapability(resource, CreateCapabilityType.class) != null;
}
public static boolean isCountObjectsCapabilityEnabled(ResourceType resource){
return getEffectiveCapability(resource, CountObjectsCapabilityType.class) != null;
}
public static boolean isPasswordCapabilityEnabled(ResourceType resource){
return getEffectivePasswordCapability(resource) != null;
}
public static PasswordCapabilityType getEffectivePasswordCapability(ResourceType resource) {
CredentialsCapabilityType cct = getEffectiveCapability(resource, CredentialsCapabilityType.class);
if (cct == null || cct.getPassword() == null || Boolean.FALSE.equals(cct.getPassword().isEnabled())) {
return null;
} else {
return cct.getPassword();
}
}
public static boolean isLiveSyncCapabilityEnabled(ResourceType resource) {
return getEffectiveCapability(resource, LiveSyncCapabilityType.class) != null;
}
public static boolean isScriptCapabilityEnabled(ResourceType resource) {
return getEffectiveCapability(resource, ScriptCapabilityType.class) != null;
}
public static boolean isTestConnectionCapabilityEnabled(ResourceType resource) {
return getEffectiveCapability(resource, TestConnectionCapabilityType.class) != null;
}
public static boolean isAuxiliaryObjectClassCapabilityEnabled(ResourceType resource) {
return getEffectiveCapability(resource, AuxiliaryObjectClassesCapabilityType.class) != null;
}
public static boolean isPagedSearchCapabilityEnabled(ResourceType resource) {
return getEffectiveCapability(resource, PagedSearchCapabilityType.class) != null;
}
public static boolean isReadCapabilityEnabled(ResourceType resource){
return getEffectiveCapability(resource, ReadCapabilityType.class) != null;
}
public static boolean isUpdateCapabilityEnabled(ResourceType resource){
return getEffectiveCapability(resource, UpdateCapabilityType.class) != null;
}
public static boolean isAddRemoveAttributesValuesCapabilityEnabled(ResourceType resource){
return getEffectiveCapability(resource, AddRemoveAttributeValuesCapabilityType.class) != null;
}
public static boolean isDeleteCapabilityEnabled(ResourceType resource){
return getEffectiveCapability(resource, DeleteCapabilityType.class) != null;
}
public static boolean hasResourceNativeActivationCapability(ResourceType resource) {
ActivationCapabilityType activationCapability = null;
// check resource native capabilities. if resource cannot do
// activation, it sholud be null..
if (resource.getCapabilities() != null && resource.getCapabilities().getNative() != null) {
activationCapability = CapabilityUtil.getCapability(resource.getCapabilities().getNative().getAny(),
ActivationCapabilityType.class);
}
if (activationCapability == null) {
return false;
}
return true;
}
public static boolean hasResourceNativeActivationStatusCapability(ResourceType resource) {
ActivationCapabilityType activationCapability = null;
if (resource.getCapabilities() != null && resource.getCapabilities().getNative() != null) {
activationCapability = CapabilityUtil.getCapability(resource.getCapabilities().getNative().getAny(),
ActivationCapabilityType.class);
}
return CapabilityUtil.getEffectiveActivationStatus(activationCapability) != null;
}
public static boolean hasResourceNativeActivationLockoutCapability(ResourceType resource) {
ActivationCapabilityType activationCapability = null;
// check resource native capabilities. if resource cannot do
// activation, it sholud be null..
if (resource.getCapabilities() != null && resource.getCapabilities().getNative() != null) {
activationCapability = CapabilityUtil.getCapability(resource.getCapabilities().getNative().getAny(),
ActivationCapabilityType.class);
}
return CapabilityUtil.getEffectiveActivationLockoutStatus(activationCapability) != null;
}
public static boolean hasResourceConfiguredActivationCapability(ResourceType resource) {
if (resource.getCapabilities() == null) {
return false;
}
if (resource.getCapabilities().getConfigured() != null) {
ActivationCapabilityType configuredCapability = CapabilityUtil.getCapability(resource.getCapabilities().getConfigured().getAny(), ActivationCapabilityType.class);
if (configuredCapability != null) {
return true;
}
// No configured capability entry, fallback to native capability
}
return false;
}
public static ResourceObjectTypeDefinitionType getResourceObjectTypeDefinitionType (
ResourceType resource, ShadowKindType kind, String intent) {
if (resource == null) {
throw new IllegalArgumentException("The resource is null");
}
SchemaHandlingType schemaHandling = resource.getSchemaHandling();
if (schemaHandling == null) {
return null;
}
if (kind == null) {
kind = ShadowKindType.ACCOUNT;
}
for (ResourceObjectTypeDefinitionType objType: schemaHandling.getObjectType()) {
if (objType.getKind() == kind || (objType.getKind() == null && kind == ShadowKindType.ACCOUNT)) {
if (intent == null && objType.isDefault()) {
return objType;
}
if (objType.getIntent() != null && objType.getIntent().equals(intent)) {
return objType;
}
if (objType.getIntent() == null && objType.isDefault() && intent != null && intent.equals(SchemaConstants.INTENT_DEFAULT)) {
return objType;
}
}
}
return null;
}
public static PrismContainer<ConnectorConfigurationType> getConfigurationContainer(ResourceType resourceType) {
return getConfigurationContainer(resourceType.asPrismObject());
}
public static PrismContainer<ConnectorConfigurationType> getConfigurationContainer(PrismObject<ResourceType> resource) {
return resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION);
}
@NotNull
public static String getResourceNamespace(PrismObject<ResourceType> resource) {
return getResourceNamespace(resource.asObjectable());
}
@NotNull
public static String getResourceNamespace(ResourceType resourceType) {
if (resourceType.getNamespace() != null) {
return resourceType.getNamespace();
}
return MidPointConstants.NS_RI;
}
public static boolean isSynchronizationOpportunistic(ResourceType resourceType) {
SynchronizationType synchronization = resourceType.getSynchronization();
if (synchronization == null) {
return false;
}
if (synchronization.getObjectSynchronization().isEmpty()) {
return false;
}
ObjectSynchronizationType objectSynchronizationType = synchronization.getObjectSynchronization().iterator().next();
if (objectSynchronizationType.isEnabled() != null && !objectSynchronizationType.isEnabled()) {
return false;
}
Boolean isOpportunistic = objectSynchronizationType.isOpportunistic();
return isOpportunistic == null || isOpportunistic;
}
public static int getDependencyOrder(ResourceObjectTypeDependencyType dependency) {
if (dependency.getOrder() == 0) {
return 0;
} else {
return dependency.getOrder();
}
}
public static ResourceObjectTypeDependencyStrictnessType getDependencyStrictness(
ResourceObjectTypeDependencyType dependency) {
if (dependency.getStrictness() == null) {
return ResourceObjectTypeDependencyStrictnessType.STRICT;
} else {
return dependency.getStrictness();
}
}
public static boolean isForceLoadDependentShadow(ResourceObjectTypeDependencyType dependency){
Boolean force = dependency.isForceLoad();
if (force == null){
return false;
}
return force;
}
public static boolean isDown(ResourceType resource){
return (resource.getOperationalState() != null && AvailabilityStatusType.DOWN == resource.getOperationalState().getLastAvailabilityStatus());
}
public static AvailabilityStatusType getLastAvailabilityStatus(ResourceType resource){
if (resource.getOperationalState() == null) {
return null;
}
if (resource.getOperationalState().getLastAvailabilityStatus() == null) {
return null;
}
return resource.getOperationalState().getLastAvailabilityStatus();
}
public static boolean isAvoidDuplicateValues(ResourceType resource) {
if (resource.getConsistency() == null) {
return false;
}
if (resource.getConsistency().isAvoidDuplicateValues() == null) {
return false;
}
return resource.getConsistency().isAvoidDuplicateValues();
}
public static boolean isCaseIgnoreAttributeNames(ResourceType resource) {
if (resource.getConsistency() == null) {
return false;
}
if (resource.getConsistency().isCaseIgnoreAttributeNames() == null) {
return false;
}
return resource.getConsistency().isCaseIgnoreAttributeNames();
}
// always returns non-null value
public static List<ObjectReferenceType> getOwnerRef(ResourceType resource) {
if (resource.getBusiness() == null) {
return new ArrayList<>();
}
return resource.getBusiness().getOwnerRef();
}
// always returns non-null value
public static List<ObjectReferenceType> getApproverRef(ResourceType resource) {
if (resource.getBusiness() == null) {
return new ArrayList<>();
}
return resource.getBusiness().getApproverRef();
}
@NotNull
public static Collection<Class<? extends CapabilityType>> getNativeCapabilityClasses(ResourceType resource) {
Set<Class<? extends CapabilityType>> rv = new HashSet<>();
if (resource.getCapabilities() == null || resource.getCapabilities().getNative() == null) {
return rv;
}
for (Object o : resource.getCapabilities().getNative().getAny()) {
rv.add(CapabilityUtil.asCapabilityType(o).getClass());
}
return rv;
}
@NotNull
public static ShadowKindType fillDefault(ShadowKindType kind) {
return kind != null ? kind : ShadowKindType.ACCOUNT;
}
@NotNull
public static String fillDefault(String intent) {
return intent != null ? intent : SchemaConstants.INTENT_DEFAULT;
}
public static ResourceObjectTypeDefinitionType findObjectTypeDefinition(PrismObject<ResourceType> resourceObject, @Nullable ShadowKindType kind,
@Nullable String intent) {
if (resourceObject == null || resourceObject.asObjectable().getSchemaHandling() == null) {
return null;
}
for (ResourceObjectTypeDefinitionType def : resourceObject.asObjectable().getSchemaHandling().getObjectType()) {
if (fillDefault(kind).equals(fillDefault(def.getKind())) && fillDefault(intent).equals(fillDefault(def.getIntent()))) {
return def;
}
}
return null;
}
@Nullable
public static ObjectSynchronizationType findObjectSynchronization(@Nullable ResourceType resource, @Nullable ShadowKindType kind, @Nullable String intent) {
if (resource == null || resource.getSynchronization() == null) {
return null;
}
for (ObjectSynchronizationType def : resource.getSynchronization().getObjectSynchronization()) {
if (fillDefault(kind).equals(fillDefault(def.getKind())) && fillDefault(intent).equals(fillDefault(def.getIntent()))) {
return def;
}
}
return null;
}
@NotNull
public static QName fillDefaultFocusType(QName focusType) {
return focusType != null ? focusType : UserType.COMPLEX_TYPE;
}
}