/*
* Copyright (c) 2016 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.assignment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.Component;
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.ComponentTag;
import org.apache.wicket.markup.html.basic.Label;
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.IModel;
import org.apache.wicket.model.Model;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.path.ItemPath;
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.web.page.admin.users.dto.UserDtoStatus;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
/**
* @author semancik
*/
public class SimpleParametricRoleSelector<F extends FocusType, R extends AbstractRoleType> extends SimpleRoleSelector<F,R> {
private static final long serialVersionUID = 1L;
private static final Trace LOGGER = TraceManager.getTrace(SimpleParametricRoleSelector.class);
private static final String ID_LABEL_ROLE = "labelRole";
private static final String ID_LABEL_PARAM = "labelParam";
private static final String ID_LIST_PARAM = "listParam";
private static final String ID_ITEM_PARAM = "itemParam";
private static final String ID_ADD_INPUT = "addInput";
private static final String ID_ADD_LINK = "addLink";
private static final String ID_DELETE_LINK = "deleteLink";
private String labelParam = null;
private String labelRole = null;
private ItemPath parameterPath;
private ListView<String> paramList;
final private IModel<List<String>> paramListModel;
private String selectedParam = null;
public SimpleParametricRoleSelector(String id, IModel<List<AssignmentEditorDto>> assignmentModel, List<PrismObject<R>> availableRoles, ItemPath parameterPath) {
super(id, assignmentModel, availableRoles);
this.parameterPath = parameterPath;
paramListModel = initParamListModel(assignmentModel);
initLayout();
}
public String getLabelParam() {
return labelParam;
}
public void setLabelParam(String labelParam) {
this.labelParam = labelParam;
}
public String getLabelRole() {
return labelRole;
}
public void setLabelRole(String labelRole) {
this.labelRole = labelRole;
}
private IModel<List<String>> initParamListModel(final IModel<List<AssignmentEditorDto>> assignmentModel) {
return new IModel<List<String>>() {
private List<String> list = null;
@Override
public void detach() {
}
@Override
public List<String> getObject() {
if (list == null) {
list = initParamList(assignmentModel.getObject());
}
return list;
}
@Override
public void setObject(List<String> list) {
this.list = list;
}
};
}
private List<String> initParamList(List<AssignmentEditorDto> assignmentDtos) {
List<String> params = new ArrayList<>();
for (AssignmentEditorDto assignmentDto: assignmentDtos) {
String paramVal = getParamValue(assignmentDto);
if (paramVal != null) {
if (!params.contains(paramVal)) {
params.add(paramVal);
}
}
}
Collections.sort(params);
return params;
}
private String getParamValue(AssignmentEditorDto assignmentDto) {
PrismContainerValue newValue;
try {
newValue = assignmentDto.getNewValue(getPageBase().getPrismContext());
} catch (SchemaException e) {
throw new SystemException(e.getMessage(),e);
}
if (newValue != null) {
PrismProperty<String> paramProp = newValue.findProperty(parameterPath);
if (paramProp != null) {
return paramProp.getRealValue();
}
}
PrismContainerValue oldValue = assignmentDto.getOldValue();
if (oldValue != null) {
PrismProperty<String> paramProp = oldValue.findProperty(parameterPath);
if (paramProp != null) {
return paramProp.getRealValue();
}
}
return null;
}
private void initLayout() {
IModel<String> labelParamModel = new IModel<String>() {
@Override
public void detach() {
}
@Override
public String getObject() {
return getLabelParam();
}
@Override
public void setObject(String object) {
}
};
add(new Label(ID_LABEL_PARAM, labelParamModel) {
@Override
protected void onConfigure() {
setVisible(getLabelParam() != null);
super.onConfigure();
}
});
IModel<String> labelRoleModel = new IModel<String>() {
@Override
public void detach() {
}
@Override
public String getObject() {
return getLabelRole();
}
@Override
public void setObject(String object) {
}
};
add(new Label(ID_LABEL_ROLE, labelRoleModel) {
@Override
protected void onConfigure() {
setVisible(getLabelRole() != null);
super.onConfigure();
}
});
paramList = new ListView<String>(ID_LIST_PARAM, paramListModel) {
@Override
protected void populateItem(ListItem<String> item) {
item.add(createParamLink(ID_ITEM_PARAM, item.getModel()));
}
};
paramList.setOutputMarkupId(true);
add(paramList);
final Model<String> addInputModel = new Model<String>();
TextField<String> addInput = new TextField<>(ID_ADD_INPUT, addInputModel);
addInput.setOutputMarkupId(true);
addInput.add(new AjaxFormComponentUpdatingBehavior("blur") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
// nothing to do, Ajax behavior is there only to get data to model
}
});
add(addInput);
AjaxLink<String> addLink = new AjaxLink<String>(ID_ADD_LINK) {
@Override
public void onClick(AjaxRequestTarget target) {
String newParam = addInputModel.getObject();
LOGGER.debug("ADD cliked, input field value: {}", newParam);
if (!StringUtils.isBlank(newParam)) {
addParam(newParam);
}
addInputModel.setObject(null);
target.add(SimpleParametricRoleSelector.this);
}
};
add(addLink);
AjaxLink<String> deleteLink = new AjaxLink<String>(ID_DELETE_LINK) {
@Override
public void onClick(AjaxRequestTarget target) {
LOGGER.debug("DELETE cliked, selected param: {}", selectedParam);
deleteParam(selectedParam);
target.add(SimpleParametricRoleSelector.this);
}
};
add(deleteLink);
}
private Component createParamLink(String id, IModel<String> itemModel) {
AjaxLink<String> button = new AjaxLink<String>(id, itemModel) {
@Override
public IModel<?> getBody() {
return new Model<String>(getModel().getObject());
}
@Override
public void onClick(AjaxRequestTarget target) {
LOGGER.trace("{} CLICK param: {}", this, getModel().getObject());
toggleParam(getModel().getObject());
target.add(SimpleParametricRoleSelector.this);
}
@Override
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
String param = getModel().getObject();
if (param.equals(selectedParam)) {
tag.put("class", "list-group-item active");
} else {
tag.put("class", "list-group-item");
}
}
};
button.setOutputMarkupId(true);
return button;
}
private void toggleParam(String param) {
selectedParam = param;
}
private void addParam(String newParam) {
List<String> params = paramListModel.getObject();
if (!params.contains(newParam)) {
params.add(newParam);
}
}
private void deleteParam(String paramToDelete) {
paramListModel.getObject().remove(paramToDelete);
// make sure that all the assignments with the parameter parameter are also removed from assignement model
Iterator<AssignmentEditorDto> iterator = getAssignmentModel().getObject().iterator();
while (iterator.hasNext()) {
AssignmentEditorDto dto = iterator.next();
if (isManagedRole(dto) && paramToDelete.equals(getParamValue(dto))) {
if (dto.getStatus() == UserDtoStatus.ADD) {
iterator.remove();
} else {
dto.setStatus(UserDtoStatus.DELETE);
}
}
}
}
@Override
protected AssignmentEditorDto createAddAssignmentDto(PrismObject<R> role, PageBase pageBase) {
AssignmentEditorDto dto = super.createAddAssignmentDto(role, pageBase);
PrismContainerValue<AssignmentType> newValue;
try {
newValue = dto.getNewValue(getPageBase().getPrismContext());
PrismProperty<String> prop = newValue.findOrCreateProperty(parameterPath);
prop.setRealValue(selectedParam);
} catch (SchemaException e) {
throw new SystemException(e.getMessage(), e);
}
return dto;
}
@Override
protected boolean willProcessAssignment(AssignmentEditorDto dto) {
if (!super.willProcessAssignment(dto)) {
return false;
}
if (selectedParam == null) {
return false;
}
return selectedParam.equals(getParamValue(dto));
}
}