/*
* Copyright (c) 2010-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.gui.api.component;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.model.api.ModelInteractionService;
import com.evolveum.midpoint.model.api.RoleSelectionSpecification;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.schema.result.OperationResult;
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.security.SecurityUtils;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
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.model.IModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.model.util.ListModel;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.web.component.AjaxButton;
import com.evolveum.midpoint.web.component.dialog.Popupable;
import com.evolveum.midpoint.web.component.input.QNameChoiceRenderer;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ServiceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
public class TypedAssignablePanel<T extends ObjectType> extends BasePanel<T> implements Popupable{
/**
*
*/
private static final long serialVersionUID = 1L;
private static final String ID_TYPE = "type";
private static final String ID_ROLE_TABLE = "roleTable";
private static final String ID_RESOURCE_TABLE = "resourceTable";
private static final String ID_ORG_TABLE = "orgTable";
private static final String ID_SELECTED_ROLES = "rolesSelected";
private static final String ID_SELECTED_RESOURCES = "resourcesSelected";
private static final String ID_SELECTED_ORGS = "orgSelected";
private static final String ID_TABLES_CONTAINER = "tablesContainer";
private static final String ID_COUNT_CONTAINER = "countContainer";
private static final String ID_SERVICE_TABLE = "serviceTable";
private static final String ID_SELECTED_SERVICES = "servicesSelected";
private static final String ID_BUTTON_ASSIGN = "assignButton";
private static final String DOT_CLASS = TypedAssignablePanel.class.getName();
private static final Trace LOGGER = TraceManager.getTrace(TypedAssignablePanel.class);
private static final String OPERATION_LOAD_ASSIGNABLE_ROLES = DOT_CLASS + "loadAssignableRoles";
private IModel<QName> typeModel;
private PageBase parentPage;
// private PageBase parentPage;
public TypedAssignablePanel(String id, final Class<T> type, boolean multiselect, PageBase parentPage) {
super(id);
this.parentPage = parentPage;
setParent(parentPage);
typeModel = new LoadableModel<QName>(false) {
@Override
protected QName load() {
return compileTimeClassToQName(type);
}
};
initLayout(type, multiselect);
}
private void initLayout(Class<T> type, final boolean multiselect) {
DropDownChoice<QName> typeSelect = new DropDownChoice(ID_TYPE, typeModel,
new ListModel(WebComponentUtil.createAssignableTypesList()), new QNameChoiceRenderer());
typeSelect.add(new OnChangeAjaxBehavior() {
@Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(get(ID_TABLES_CONTAINER));
target.add(addOrReplace(createCountContainer()));
}
});
typeSelect.setOutputMarkupId(true);
add(typeSelect);
WebMarkupContainer tablesContainer = new WebMarkupContainer(ID_TABLES_CONTAINER);
tablesContainer.setOutputMarkupId(true);
add(tablesContainer);
PopupObjectListPanel<T> listRolePanel = createObjectListPanel(ID_ROLE_TABLE, ID_SELECTED_ROLES, RoleType.COMPLEX_TYPE);
tablesContainer.add(listRolePanel);
PopupObjectListPanel<T> listResourcePanel = createObjectListPanel(ID_RESOURCE_TABLE, ID_SELECTED_RESOURCES, ResourceType.COMPLEX_TYPE);
tablesContainer.add(listResourcePanel);
PopupObjectListPanel<T> listOrgPanel = createObjectListPanel(ID_ORG_TABLE, ID_SELECTED_ORGS, OrgType.COMPLEX_TYPE);
tablesContainer.add(listOrgPanel);
PopupObjectListPanel<T> listServicePanel = createObjectListPanel(ID_SERVICE_TABLE, ID_SELECTED_SERVICES, ServiceType.COMPLEX_TYPE);
tablesContainer.add(listServicePanel);
WebMarkupContainer countContainer = createCountContainer();
add(countContainer);
AjaxButton addButton = new AjaxButton(ID_BUTTON_ASSIGN,
createStringResource("userBrowserDialog.button.addButton")) {
@Override
public void onClick(AjaxRequestTarget target) {
List<T> selected = getSelectedData(ID_ROLE_TABLE);
selected.addAll(getSelectedData(ID_RESOURCE_TABLE));
selected.addAll(getSelectedData(ID_ORG_TABLE));
selected.addAll(getSelectedData(ID_SERVICE_TABLE));
TypedAssignablePanel.this.addPerformed(target, selected);
}
};
addButton.add(new VisibleEnableBehaviour() {
@Override
public boolean isVisible() {
return multiselect;
}
});
add(addButton);
}
private List<T> getSelectedData(String id){
return ((ObjectListPanel) get(createComponentPath(ID_TABLES_CONTAINER, id))).getSelectedObjects();
}
private WebMarkupContainer createCountContainer(){
WebMarkupContainer countContainer = new WebMarkupContainer(ID_COUNT_CONTAINER);
countContainer.setOutputMarkupId(true);
countContainer.add(createCountLabel(ID_SELECTED_ORGS, (PopupObjectListPanel<T>)get(createComponentPath(ID_TABLES_CONTAINER, ID_ORG_TABLE))));
countContainer.add(createCountLabel(ID_SELECTED_RESOURCES, (PopupObjectListPanel<T>)get(createComponentPath(ID_TABLES_CONTAINER, ID_RESOURCE_TABLE))));
countContainer.add(createCountLabel(ID_SELECTED_ROLES, (PopupObjectListPanel<T>)get(createComponentPath(ID_TABLES_CONTAINER, ID_ROLE_TABLE))));
countContainer.add(createCountLabel(ID_SELECTED_SERVICES, (PopupObjectListPanel<T>)get(createComponentPath(ID_TABLES_CONTAINER, ID_SERVICE_TABLE))));
return countContainer;
}
private Label createCountLabel(String id, ObjectListPanel panel){
Label label = new Label(id, panel.getSelectedObjects().size());
label.setOutputMarkupId(true);
return label;
}
protected void onClick(AjaxRequestTarget target, T focus) {
getPageBase().hideMainPopup(target);
}
private void refreshCounts(AjaxRequestTarget target) {
addOrReplace(createCountContainer());
target.add(get(ID_COUNT_CONTAINER));
}
private PopupObjectListPanel<T> createObjectListPanel(String id, final String countId, final QName type) {
PopupObjectListPanel<T> listPanel = new PopupObjectListPanel<T>(id, qnameToCompileTimeClass(type), true, getPageBase()) {
@Override
protected void onUpdateCheckbox(AjaxRequestTarget target) {
refreshCounts(target);
}
@Override
protected ObjectQuery addFilterToContentQuery(ObjectQuery query) {
if (type.equals(RoleType.COMPLEX_TYPE)) {
LOGGER.debug("Loading roles which the current user has right to assign");
OperationResult result = new OperationResult(OPERATION_LOAD_ASSIGNABLE_ROLES);
ObjectFilter filter = null;
try {
ModelInteractionService mis = parentPage.getModelInteractionService();
RoleSelectionSpecification roleSpec =
mis.getAssignableRoleSpecification(SecurityUtils.getPrincipalUser().getUser().asPrismObject(), result);
filter = roleSpec.getFilter();
} catch (Exception ex) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load available roles", ex);
result.recordFatalError("Couldn't load available roles", ex);
} finally {
result.recomputeStatus();
}
if (!result.isSuccess() && !result.isHandledError()) {
parentPage.showResult(result);
}
if (query == null){
query = new ObjectQuery();
}
query.addFilter(filter);
}
return query;
}
};
listPanel.setOutputMarkupId(true);
listPanel.add(new VisibleEnableBehaviour() {
@Override
public boolean isVisible() {
return type.equals(typeModel.getObject());
}
});
return listPanel;
}
protected void addPerformed(AjaxRequestTarget target, List<T> selected) {
getPageBase().hideMainPopup(target);
}
private Class qnameToCompileTimeClass(QName typeName) {
return getPageBase().getPrismContext().getSchemaRegistry().getCompileTimeClassForObjectType(typeName);
}
private QName compileTimeClassToQName(Class<T> type) {
PrismObjectDefinition<T> def = getPageBase().getPrismContext().getSchemaRegistry()
.findObjectDefinitionByCompileTimeClass(type);
if (def == null) {
return UserType.COMPLEX_TYPE;
}
return def.getTypeName();
}
@Override
public int getWidth() {
return 900;
}
@Override
public int getHeight() {
return 500;
}
@Override
public StringResourceModel getTitle() {
return getPageBase().createStringResource("TypedAssignablePanel.selectObjects");
}
@Override
public Component getComponent() {
return this;
}
}