/** * Copyright (c) 2017 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.provisioning.ucf.impl.builtin; import java.util.Collection; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException; import com.evolveum.midpoint.provisioning.ucf.api.ManagedConnector; import com.evolveum.midpoint.provisioning.ucf.api.ManagedConnectorConfiguration; import com.evolveum.midpoint.provisioning.ucf.api.Operation; import com.evolveum.midpoint.provisioning.ucf.api.connectors.AbstractManualConnectorInstance; import com.evolveum.midpoint.repo.api.RepositoryAware; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.constants.ConnectorTestOperation; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.processor.ResourceAttribute; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.OidUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; /** * @author Radovan Semancik * */ @ManagedConnector(type="ManualConnector", version="1.0.0") public class ManualConnectorInstance extends AbstractManualConnectorInstance implements RepositoryAware { public static final String OPERATION_QUERY_CASE = ".queryCase"; private static final Trace LOGGER = TraceManager.getTrace(ManualConnectorInstance.class); private ManualConnectorConfiguration configuration; private RepositoryService repositoryService; @ManagedConnectorConfiguration public ManualConnectorConfiguration getConfiguration() { return configuration; } public void setConfiguration(ManualConnectorConfiguration configuration) { this.configuration = configuration; } @Override public RepositoryService getRepositoryService() { return repositoryService; } @Override public void setRepositoryService(RepositoryService repositoryService) { this.repositoryService = repositoryService; } @Override protected String createTicketAdd(PrismObject<? extends ShadowType> object, Collection<Operation> additionalOperations, OperationResult result) throws CommunicationException, GenericFrameworkException, SchemaException, ObjectAlreadyExistsException, ConfigurationException { LOGGER.info("Creating case to add account\n{}", object.debugDump(1)); String description = "Please create account "+object; PrismObject<CaseType> acase = addCase(description, result); return acase.getOid(); } @Override protected String createTicketModify(ObjectClassComplexTypeDefinition objectClass, Collection<? extends ResourceAttribute<?>> identifiers, Collection<Operation> changes, OperationResult result) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException, ObjectAlreadyExistsException, ConfigurationException { LOGGER.info("Creating case to modify account {}:\n{}", identifiers, DebugUtil.debugDump(changes, 1)); String description = "Please modify account "+identifiers+": "+changes; PrismObject<CaseType> acase = addCase(description, result); return acase.getOid(); } @Override protected String createTicketDelete(ObjectClassComplexTypeDefinition objectClass, Collection<? extends ResourceAttribute<?>> identifiers, OperationResult result) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException { LOGGER.info("Creating case to delete account {}", identifiers); String description = "Please delete account "+identifiers; PrismObject<CaseType> acase; try { acase = addCase(description, result); } catch (ObjectAlreadyExistsException e) { // should not happen throw new SystemException(e.getMessage(), e); } return acase.getOid(); } private PrismObject<CaseType> addCase(String description, OperationResult result) throws SchemaException, ObjectAlreadyExistsException { PrismObject<CaseType> acase = getPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(CaseType.class).instantiate(); CaseType caseType = acase.asObjectable(); String caseOid = OidUtil.generateOid(); caseType.setOid(caseOid); // TODO: human-readable case ID caseType.setName(new PolyStringType(caseOid)); caseType.setDescription(description); // subtype caseType.setState(SchemaConstants.CASE_STATE_OPEN); // TODO: case payload // TODO: a lot of other things // TODO: move to case-manager LOGGER.info("CREATING CASE:\n{}", acase.debugDump(1)); repositoryService.addObject(acase, null, result); return acase; } @Override public OperationResultStatus queryOperationStatus(String asyncronousOperationReference, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { OperationResult result = parentResult.createMinorSubresult(OPERATION_QUERY_CASE); PrismObject<CaseType> acase; try { acase = repositoryService.getObject(CaseType.class, asyncronousOperationReference, null, result); } catch (ObjectNotFoundException | SchemaException e) { result.recordFatalError(e); throw e; } CaseType caseType = acase.asObjectable(); String state = caseType.getState(); if (QNameUtil.matchWithUri(SchemaConstants.CASE_STATE_OPEN_QNAME, state)) { result.recordSuccess(); return OperationResultStatus.IN_PROGRESS; } else if (QNameUtil.matchWithUri(SchemaConstants.CASE_STATE_CLOSED_QNAME, state)) { String outcome = caseType.getOutcome(); OperationResultStatus status = translateOutcome(outcome); result.recordSuccess(); return status; } else { SchemaException e = new SchemaException("Unknown case state "+state); result.recordFatalError(e); throw e; } } private OperationResultStatus translateOutcome(String outcome) { // TODO: better algorithm if (outcome == null) { return null; } else if (outcome.equals(OperationResultStatusType.SUCCESS.value())) { return OperationResultStatus.SUCCESS; } else { return OperationResultStatus.UNKNOWN; } } @Override protected void connect(OperationResult result) { // Nothing to do } @Override public void test(OperationResult parentResult) { OperationResult connectionResult = parentResult .createSubresult(ConnectorTestOperation.CONNECTOR_CONNECTION.getOperation()); connectionResult.addContext(OperationResult.CONTEXT_IMPLEMENTATION_CLASS, ManualConnectorInstance.class); connectionResult.addContext("connector", getConnectorObject()); if (repositoryService == null) { connectionResult.recordFatalError("No repository service"); return; } connectionResult.recordSuccess(); } @Override public void dispose() { // Nothing to dispose } }