package com.evolveum.midpoint.web.page.admin.server.handlers.dto;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.page.admin.server.dto.TaskAddResourcesDto;
import com.evolveum.midpoint.web.page.admin.server.dto.TaskDto;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author mederly
*/
public class ResourceRelatedHandlerDto extends HandlerDto implements HandlerDtoEditableState {
public static final String F_DRY_RUN = "dryRun";
public static final String F_KIND = "kind";
public static final String F_INTENT = "intent";
public static final String F_OBJECT_CLASS = "objectClass";
public static final String F_RESOURCE_REFERENCE = "resourceRef";
public static final String F_TOKEN_RETRY_UNHANDLED_ERR = "retryUnhandledErr";
private static final String CLASS_DOT = ResourceRelatedHandlerDto.class.getName() + ".";
private static final String OPERATION_LOAD_RESOURCE = CLASS_DOT + "loadResource";
private static final transient Trace LOGGER = TraceManager.getTrace(ResourceRelatedHandlerDto.class);
private boolean dryRun;
private ShadowKindType kind;
private String intent;
private String objectClass;
private List<QName> objectClassList;
private TaskAddResourcesDto resourceRef;
private boolean retryUnhandledErr;
private ResourceRelatedHandlerDto(TaskDto taskDto) {
super(taskDto);
}
public ResourceRelatedHandlerDto(TaskDto taskDto, PageBase pageBase, Task opTask, OperationResult thisOpResult) {
super(taskDto);
TaskType taskType = taskDto.getTaskType();
fillInResourceReference(taskType, pageBase, opTask, thisOpResult);
fillFromExtension(taskType);
}
private void fillFromExtension(TaskType taskType) {
PrismObject<TaskType> task = taskType.asPrismObject();
if (task.getExtension() == null) {
dryRun = false;
return;
}
PrismProperty<Boolean> item = task.getExtension().findProperty(SchemaConstants.MODEL_EXTENSION_DRY_RUN);
if (item == null || item.getRealValue() == null) {
dryRun = false;
} else {
dryRun = item.getRealValue();
}
PrismProperty<ShadowKindType> kindItem = task.getExtension().findProperty(SchemaConstants.MODEL_EXTENSION_KIND);
if(kindItem != null && kindItem.getRealValue() != null){
kind = kindItem.getRealValue();
}
PrismProperty<String> intentItem = task.getExtension().findProperty(SchemaConstants.MODEL_EXTENSION_INTENT);
if(intentItem != null && intentItem.getRealValue() != null){
intent = intentItem.getRealValue();
}
PrismProperty<QName> objectClassItem = task.getExtension().findProperty(SchemaConstants.OBJECTCLASS_PROPERTY_NAME);
if(objectClassItem != null && objectClassItem.getRealValue() != null){
objectClass = objectClassItem.getRealValue().getLocalPart();
}
PrismProperty<Boolean> retrySyncItem = task.getExtension().findProperty(SchemaConstants.SYNC_TOKEN_RETRY_UNHANDLED);
if (retrySyncItem == null || retrySyncItem.getRealValue() == null) {
retryUnhandledErr = true;
} else {
retryUnhandledErr = retrySyncItem.getRealValue();
}
}
public boolean isDryRun() {
return dryRun;
}
public void setDryRun(boolean dryRun) {
this.dryRun = dryRun;
}
public boolean isRetryUnhandledErr() {
return retryUnhandledErr;
}
public void setRetryUnhandledErr(boolean retryUnhandledErr) {
this.retryUnhandledErr = retryUnhandledErr;
}
public String getIntent() {
return intent;
}
public void setIntent(String intent) {
this.intent = intent;
}
public ShadowKindType getKind() {
return kind;
}
public void setKind(ShadowKindType kind) {
this.kind = kind;
}
public String getObjectClass() {
return objectClass;
}
public void setObjectClass(String objectClass) {
this.objectClass = objectClass;
}
public List<QName> getObjectClassList() {
if (objectClassList == null) {
objectClassList = new ArrayList<>();
}
return objectClassList;
}
public void setObjectClassList(List<QName> objectClassList) {
this.objectClassList = objectClassList;
}
private void fillInResourceReference(TaskType task, PageBase pageBase, Task opTask, OperationResult result) {
ObjectReferenceType ref = task.getObjectRef();
if (ref != null && ResourceType.COMPLEX_TYPE.equals(ref.getType())){
resourceRef = new TaskAddResourcesDto(ref.getOid(), taskDto.getTaskObjectName(task, pageBase, opTask, result));
}
updateObjectClassList(pageBase);
}
private void updateObjectClassList(PageBase pageBase){
Task task = pageBase.createSimpleTask(OPERATION_LOAD_RESOURCE);
OperationResult result = task.getResult();
List<QName> objectClassList = new ArrayList<>();
if(resourceRef != null){
PrismObject<ResourceType> resource = WebModelServiceUtils.loadObject(ResourceType.class, resourceRef.getOid(),
pageBase, task, result);
try {
ResourceSchema schema = RefinedResourceSchemaImpl.getResourceSchema(resource, pageBase.getPrismContext());
schema.getObjectClassDefinitions();
for(Definition def: schema.getDefinitions()){
objectClassList.add(def.getTypeName());
}
setObjectClassList(objectClassList);
} catch (Exception e){
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object class list from resource.", e);
}
}
}
public TaskAddResourcesDto getResourceRef() {
return resourceRef;
}
public void setResource(TaskAddResourcesDto resource) {
this.resourceRef = resource;
taskDto.setObjectRef(resource != null ? resource.asObjectReferenceType() : null);
}
@NotNull
@Override
public Collection<ItemDelta<?, ?>> getDeltasToExecute(HandlerDtoEditableState origState, HandlerDtoEditableState currState, PrismContext prismContext)
throws SchemaException {
List<ItemDelta<?, ?>> rv = new ArrayList<>();
// we can safely assume this; also that both are non-null
ResourceRelatedHandlerDto orig = (ResourceRelatedHandlerDto) origState;
ResourceRelatedHandlerDto curr = (ResourceRelatedHandlerDto) currState;
String origResourceOid = orig.getResourceRef() != null ? orig.getResourceRef().getOid() : null;
String currResourceOid = curr.getResourceRef() != null ? curr.getResourceRef().getOid() : null;
if (!StringUtils.equals(origResourceOid, currResourceOid)) {
ObjectReferenceType resourceObjectRef = new ObjectReferenceType();
resourceObjectRef.setOid(curr.getResourceRef().getOid());
resourceObjectRef.setType(ResourceType.COMPLEX_TYPE);
rv.add(DeltaBuilder.deltaFor(TaskType.class, prismContext)
.item(TaskType.F_OBJECT_REF).replace(resourceObjectRef.asReferenceValue()).asItemDelta());
}
if (orig.isDryRun() != curr.isDryRun()) {
addExtensionDelta(rv, SchemaConstants.MODEL_EXTENSION_DRY_RUN, curr.isDryRun(), prismContext);
}
if (orig.isRetryUnhandledErr() != curr.isRetryUnhandledErr()) {
addExtensionDelta(rv, SchemaConstants.SYNC_TOKEN_RETRY_UNHANDLED, curr.isRetryUnhandledErr(), prismContext);
}
if (orig.getKind() != curr.getKind()) {
addExtensionDelta(rv, SchemaConstants.MODEL_EXTENSION_KIND, curr.getKind(), prismContext);
}
if (!StringUtils.equals(orig.getIntent(), curr.getIntent())) {
addExtensionDelta(rv, SchemaConstants.MODEL_EXTENSION_INTENT, curr.getIntent(), prismContext);
}
if (!StringUtils.equals(orig.getObjectClass(), curr.getObjectClass())) {
QName objectClassQName = null;
for (QName q: getObjectClassList()) {
if (q.getLocalPart().equals(objectClass)) {
objectClassQName = q;
}
}
addExtensionDelta(rv, SchemaConstants.OBJECTCLASS_PROPERTY_NAME, objectClassQName, prismContext);
}
return rv;
}
private void addExtensionDelta(List<ItemDelta<?, ?>> rv, QName itemName, Object realValue, PrismContext prismContext)
throws SchemaException {
PrismPropertyDefinition def = prismContext.getSchemaRegistry().findPropertyDefinitionByElementName(itemName);
rv.add(DeltaBuilder.deltaFor(TaskType.class, prismContext)
.item(new ItemPath(TaskType.F_EXTENSION, itemName), def).replace(realValue).asItemDelta());
}
@Override
public HandlerDtoEditableState getEditableState() {
return this;
}
// TODO implement seriously
public ResourceRelatedHandlerDto clone() {
ResourceRelatedHandlerDto clone = new ResourceRelatedHandlerDto(taskDto);
clone.dryRun = dryRun;
clone.retryUnhandledErr = retryUnhandledErr;
clone.kind = kind;
clone.intent = intent;
clone.objectClass = objectClass;
clone.objectClassList = CloneUtil.clone(objectClassList);
clone.resourceRef = CloneUtil.clone(resourceRef);
return clone;
}
}