/*
* Copyright (c) 2010-2014 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.web.component.wizard.resource.component.schemahandling;
import com.evolveum.midpoint.gui.api.component.BasePanel;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.CommonException;
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.component.input.ObjectReferenceChoiceRenderer;
import com.evolveum.midpoint.web.page.admin.resources.PageResourceWizard;
import com.evolveum.midpoint.web.util.InfoTooltipBehavior;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author shood
* */
public class ResourceDependencyEditor extends BasePanel<List<ResourceObjectTypeDependencyType>> {
private static enum ChangeState{
SKIP, FIRST, LAST
}
private static final Trace LOGGER = TraceManager.getTrace(ResourceDependencyEditor.class);
private static final String DOT_CLASS = ResourceDependencyEditor.class.getName() + ".";
private static final String OPERATION_LOAD_RESOURCES = DOT_CLASS + "createResourceList";
private static final String ID_CONTAINER = "protectedContainer";
private static final String ID_REPEATER = "repeater";
private static final String ID_DEPENDENCY_LINK = "dependencyLink";
private static final String ID_DEPENDENCY_LINK_NAME = "dependencyLinkName";
private static final String ID_DEPENDENCY_BODY = "dependencyBodyContainer";
private static final String ID_ORDER = "order";
private static final String ID_STRICTNESS = "strictness";
private static final String ID_KIND = "kind";
private static final String ID_INTENT = "intent";
private static final String ID_REF = "resourceRef";
private static final String ID_ADD_BUTTON = "addButton";
private static final String ID_DELETE_BUTTON = "deleteDependency";
private static final String ID_T_ORDER = "orderTooltip";
private static final String ID_T_STRICTNESS = "strictnessTooltip";
private static final String ID_T_KIND = "kindTooltip";
private static final String ID_T_INTENT = "intentTooltip";
private static final String ID_T_RESOURCE_REF = "resourceRefTooltip";
private ChangeState changeState = ChangeState.FIRST;
private Map<String, String> resourceMap = new HashMap<>();
public ResourceDependencyEditor(String id, IModel<List<ResourceObjectTypeDependencyType>> model, PageResourceWizard parentPage) {
super(id, model);
initLayout(parentPage);
}
@Override
public IModel<List<ResourceObjectTypeDependencyType>> getModel(){
IModel<List<ResourceObjectTypeDependencyType>> model = super.getModel();
if(model.getObject() == null){
model.setObject(new ArrayList<ResourceObjectTypeDependencyType>());
}
return model;
}
protected void initLayout(final PageResourceWizard parentPage){
WebMarkupContainer container = new WebMarkupContainer(ID_CONTAINER);
container.setOutputMarkupId(true);
add(container);
ListView repeater = new ListView<ResourceObjectTypeDependencyType>(ID_REPEATER, getModel()) {
@Override
protected void populateItem(final ListItem<ResourceObjectTypeDependencyType> item) {
WebMarkupContainer linkContainer = new WebMarkupContainer(ID_DEPENDENCY_LINK);
linkContainer.setOutputMarkupId(true);
linkContainer.add(new AttributeModifier("href", createCollapseItemId(item, true)));
item.add(linkContainer);
Label linkLabel = new Label(ID_DEPENDENCY_LINK_NAME, createDependencyLabelModel(item));
linkContainer.add(linkLabel);
AjaxLink delete = new AjaxLink(ID_DELETE_BUTTON) {
@Override
public void onClick(AjaxRequestTarget target) {
deleteDependencyPerformed(target, item);
}
};
parentPage.addEditingVisibleBehavior(delete);
linkContainer.add(delete);
WebMarkupContainer dependencyBody = new WebMarkupContainer(ID_DEPENDENCY_BODY);
dependencyBody.setOutputMarkupId(true);
dependencyBody.setMarkupId(createCollapseItemId(item, false).getObject());
if(changeState != ChangeState.SKIP){
dependencyBody.add(new AttributeModifier("class", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
if(changeState == ChangeState.FIRST && item.getIndex() == 0){
return "panel-collapse collapse in";
} else if(changeState == ChangeState.LAST && item.getIndex() == (getModelObject().size()-1)){
return "panel-collapse collapse in";
} else {
return "panel-collapse collapse";
}
}
}));
}
item.add(dependencyBody);
TextField order = new TextField<>(ID_ORDER, new PropertyModel<Integer>(item.getModelObject(), "order"));
order.add(prepareAjaxOnComponentTagUpdateBehavior());
parentPage.addEditingEnabledBehavior(order);
dependencyBody.add(order);
DropDownChoice strictness = new DropDownChoice<>(ID_STRICTNESS,
new PropertyModel<ResourceObjectTypeDependencyStrictnessType>(item.getModelObject(), "strictness"),
WebComponentUtil.createReadonlyModelFromEnum(ResourceObjectTypeDependencyStrictnessType.class),
new EnumChoiceRenderer<ResourceObjectTypeDependencyStrictnessType>(this));
strictness.add(prepareAjaxOnComponentTagUpdateBehavior());
parentPage.addEditingEnabledBehavior(strictness);
dependencyBody.add(strictness);
DropDownChoice kind = new DropDownChoice<>(ID_KIND,
new PropertyModel<ShadowKindType>(item.getModelObject(), "kind"),
WebComponentUtil.createReadonlyModelFromEnum(ShadowKindType.class),
new EnumChoiceRenderer<ShadowKindType>(this));
kind.add(prepareAjaxOnComponentTagUpdateBehavior());
parentPage.addEditingEnabledBehavior(kind);
dependencyBody.add(kind);
TextField intent = new TextField<>(ID_INTENT, new PropertyModel<String>(item.getModelObject(), "intent"));
intent.add(prepareAjaxOnComponentTagUpdateBehavior());
parentPage.addEditingEnabledBehavior(intent);
dependencyBody.add(intent);
DropDownChoice resource = new DropDownChoice<>(ID_REF,
new PropertyModel<ObjectReferenceType>(item.getModelObject(), "resourceRef"),
new AbstractReadOnlyModel<List<ObjectReferenceType>>() {
@Override
public List<ObjectReferenceType> getObject() {
return WebModelServiceUtils.createObjectReferenceList(ResourceType.class, getPageBase(), resourceMap);
}
}, new ObjectReferenceChoiceRenderer(resourceMap));
resource.add(prepareAjaxOnComponentTagUpdateBehavior());
parentPage.addEditingEnabledBehavior(resource);
dependencyBody.add(resource);
Label orderTooltip = new Label(ID_T_ORDER);
orderTooltip.add(new InfoTooltipBehavior());
dependencyBody.add(orderTooltip);
Label strictnessTooltip = new Label(ID_T_STRICTNESS);
strictnessTooltip.add(new InfoTooltipBehavior());
dependencyBody.add(strictnessTooltip);
Label kindTooltip = new Label(ID_T_KIND);
kindTooltip.add(new InfoTooltipBehavior());
dependencyBody.add(kindTooltip);
Label intentTooltip = new Label(ID_T_INTENT);
intentTooltip.add(new InfoTooltipBehavior());
dependencyBody.add(intentTooltip);
Label resourceRefTooltip = new Label(ID_T_RESOURCE_REF);
resourceRefTooltip.add(new InfoTooltipBehavior());
dependencyBody.add(resourceRefTooltip);
}
};
repeater.setOutputMarkupId(true);
container.add(repeater);
AjaxLink add = new AjaxLink(ID_ADD_BUTTON) {
@Override
public void onClick(AjaxRequestTarget target) {
addDependencyPerformed(target);
}
};
parentPage.addEditingVisibleBehavior(add);
add(add);
}
private IModel<String> createDependencyLabelModel(final ListItem<ResourceObjectTypeDependencyType> item){
return new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
StringBuilder sb = new StringBuilder();
ResourceObjectTypeDependencyType dep = item.getModelObject();
sb.append("#").append(item.getIndex()+1).append(" - ");
if(dep.getResourceRef() != null){
sb.append(resourceMap.get(dep.getResourceRef().getOid())).append(":");
}
if(dep.getKind() != null){
sb.append(dep.getKind().toString()).append(":");
}
if(dep.getIntent() != null){
sb.append(dep.getIntent()).append(":");
}
sb.append(dep.getOrder()).append(":");
if(dep.getStrictness() != null){
sb.append(dep.getStrictness().toString());
}
return sb.toString();
}
};
}
private AjaxFormComponentUpdatingBehavior prepareAjaxOnComponentTagUpdateBehavior(){
return new AjaxFormComponentUpdatingBehavior("blur") {
@Override
protected void onUpdate(AjaxRequestTarget target) {}
};
}
private List<ObjectReferenceType> createResourceList(){
resourceMap.clear();
OperationResult result = new OperationResult(OPERATION_LOAD_RESOURCES);
Task task = getPageBase().createSimpleTask(OPERATION_LOAD_RESOURCES);
List<PrismObject<ResourceType>> resources = null;
List<ObjectReferenceType> references = new ArrayList<>();
try {
resources = getPageBase().getModelService().searchObjects(ResourceType.class, new ObjectQuery(), null, task, result);
result.recomputeStatus();
} catch (CommonException|RuntimeException e){
result.recordFatalError("Couldn't get resource list.", e);
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't get resource list.", e);
}
// TODO - show error somehow
// if(!result.isSuccess()){
// getPageBase().showResult(result);
// }
if(resources != null){
ObjectReferenceType ref;
for(PrismObject<ResourceType> r: resources){
resourceMap.put(r.getOid(), WebComponentUtil.getName(r));
ref = new ObjectReferenceType();
ref.setType(ResourceType.COMPLEX_TYPE);
ref.setOid(r.getOid());
references.add(ref);
}
}
return references;
}
private String createResourceReadLabel(ObjectReferenceType ref){
return resourceMap.get(ref.getOid());
}
private WebMarkupContainer getMainContainer(){
return (WebMarkupContainer) get(ID_CONTAINER);
}
private IModel<String> createCollapseItemId(final ListItem<ResourceObjectTypeDependencyType> item, final boolean appendSelector){
return new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
StringBuilder sb = new StringBuilder();
if(appendSelector){
sb.append("#");
}
sb.append("collapse").append(item.getId());
return sb.toString();
}
};
}
private void addDependencyPerformed(AjaxRequestTarget target){
ResourceObjectTypeDependencyType dependency = new ResourceObjectTypeDependencyType();
changeState = ChangeState.LAST;
getModel().getObject().add(dependency);
target.add(getMainContainer());
}
private void deleteDependencyPerformed(AjaxRequestTarget target, ListItem<ResourceObjectTypeDependencyType> item){
changeState = ChangeState.SKIP;
getModel().getObject().remove(item.getModelObject());
target.add(getMainContainer());
}
}