/* 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.web.page.admin.configuration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.prism.PrismPropertyDefinitionImpl;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.web.component.dialog.*;
import com.evolveum.midpoint.web.component.search.Search;
import com.evolveum.midpoint.web.component.search.SearchFactory;
import com.evolveum.midpoint.web.component.search.SearchPanel;
import com.evolveum.midpoint.web.page.admin.server.PageTaskEdit;
import com.evolveum.midpoint.web.page.admin.server.PageTasks;
import com.evolveum.midpoint.web.util.OnePageParameterEncoder;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
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.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.ModelPublicConstants;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.AndFilter;
import com.evolveum.midpoint.prism.query.EqualFilter;
import com.evolveum.midpoint.prism.query.InOidFilter;
import com.evolveum.midpoint.prism.query.NotFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectPaging;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.QueryJaxbConvertor;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.util.DOMUtil;
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.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.application.AuthorizationAction;
import com.evolveum.midpoint.web.application.PageDescriptor;
import com.evolveum.midpoint.web.component.data.BoxedTablePanel;
import com.evolveum.midpoint.web.component.data.RepositoryObjectDataProvider;
import com.evolveum.midpoint.web.component.data.Table;
import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn;
import com.evolveum.midpoint.web.component.data.column.InlineMenuHeaderColumn;
import com.evolveum.midpoint.web.component.data.column.InlineMenuable;
import com.evolveum.midpoint.web.component.data.column.LinkColumn;
import com.evolveum.midpoint.web.component.data.column.TwoValueLinkPanel;
import com.evolveum.midpoint.web.component.input.ChoiceableChoiceRenderer;
import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.configuration.component.DebugButtonPanel;
import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction;
import com.evolveum.midpoint.web.page.admin.configuration.component.PageDebugDownloadBehaviour;
import com.evolveum.midpoint.web.page.admin.configuration.dto.DebugConfDialogDto;
import com.evolveum.midpoint.web.page.admin.configuration.dto.DebugObjectItem;
import com.evolveum.midpoint.web.page.admin.configuration.dto.DebugSearchDto;
import com.evolveum.midpoint.web.page.admin.dto.ObjectViewDto;
import com.evolveum.midpoint.web.session.ConfigurationStorage;
import com.evolveum.midpoint.web.session.UserProfileStorage;
import com.evolveum.midpoint.web.util.ObjectTypeGuiDescriptor;
import com.evolveum.prism.xml.ns._public.query_3.QueryType;
/**
* @author lazyman
*/
@PageDescriptor(url = "/admin/config/debugs", action = {
@AuthorizationAction(actionUri = PageAdminConfiguration.AUTH_CONFIGURATION_ALL, label = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_LABEL, description = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_DESCRIPTION),
@AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_CONFIGURATION_DEBUGS_URL, label = "PageDebugList.auth.debugs.label", description = "PageDebugList.auth.debugs.description") })
public class PageDebugList extends PageAdminConfiguration {
private static final Trace LOGGER = TraceManager.getTrace(PageDebugList.class);
private static final String DOT_CLASS = PageDebugList.class.getName() + ".";
private static final String OPERATION_DELETE_OBJECTS = DOT_CLASS + "deleteObjects";
private static final String OPERATION_LAXATIVE_DELETE = DOT_CLASS + "laxativeDelete";
private static final String OPERATION_LOAD_RESOURCES = DOT_CLASS + "loadResources";
private static final String OPERATION_DELETE_SHADOWS = DOT_CLASS + "deleteShadows";
private static final String ID_MAIN_FORM = "mainForm";
private static final String ID_ZIP_CHECK = "zipCheck";
private static final String ID_TABLE = "table";
private static final String ID_CHOICE_CONTAINER = "choiceContainer";
private static final String ID_CHOICE = "choice";
private static final String ID_EXPORT = "export";
private static final String ID_EXPORT_ALL = "exportAll";
private static final String ID_SEARCH_FORM = "searchForm";
private static final String ID_RESOURCE = "resource";
private static final String ID_TABLE_HEADER = "tableHeader";
private static final String ID_SEARCH = "search";
private static final Integer DELETE_LOG_INTERVAL = 50;
// search form model;
private IModel<DebugSearchDto> searchModel;
// confirmation dialog model
private IModel<DebugConfDialogDto> confDialogModel;
private IModel<List<ObjectViewDto>> resourcesModel;
public PageDebugList() {
searchModel = new LoadableModel<DebugSearchDto>(false) {
@Override
protected DebugSearchDto load() {
ConfigurationStorage storage = getSessionStorage().getConfiguration();
DebugSearchDto dto = storage.getDebugSearchDto();
if (dto == null) {
dto = new DebugSearchDto();
dto.setType(ObjectTypes.SYSTEM_CONFIGURATION);
setupSearchDto(dto);
}
return dto;
}
};
confDialogModel = new LoadableModel<DebugConfDialogDto>() {
@Override
protected DebugConfDialogDto load() {
return new DebugConfDialogDto();
}
};
resourcesModel = new LoadableModel<List<ObjectViewDto>>(false) {
@Override
protected List<ObjectViewDto> load() {
return loadResources();
}
};
initLayout();
}
private List<ObjectViewDto> loadResources() {
List<ObjectViewDto> objects = new ArrayList<>();
try {
OperationResult result = new OperationResult(OPERATION_LOAD_RESOURCES);
List<PrismObject<ResourceType>> list = WebModelServiceUtils.searchObjects(ResourceType.class,
null, SelectorOptions.createCollection(GetOperationOptions.createRaw()), result, this,
null);
for (PrismObject obj : list) {
ObjectViewDto dto = new ObjectViewDto(obj.getOid(), WebComponentUtil.getName(obj));
objects.add(dto);
}
} catch (Exception ex) {
// todo implement error handling
}
Collections.sort(objects, (o1, o2) -> String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName()));
return objects;
}
private void initLayout() {
Form main = new Form(ID_MAIN_FORM);
add(main);
DebugSearchDto dto = searchModel.getObject();
Class type = dto.getType().getClassDefinition();
RepositoryObjectDataProvider provider = new RepositoryObjectDataProvider(this, type) {
@Override
protected void saveProviderPaging(ObjectQuery query, ObjectPaging paging) {
ConfigurationStorage storage = getSessionStorage().getConfiguration();
storage.setPaging(paging);
}
};
DebugSearchDto search = searchModel.getObject();
ObjectQuery query = search.getSearch().createObjectQuery(getPrismContext());
provider.setQuery(createQuery(query));
addOrReplaceTable(provider);
PageDebugDownloadBehaviour ajaxDownloadBehavior = new PageDebugDownloadBehaviour();
main.add(ajaxDownloadBehavior);
}
private void initDownload(AjaxRequestTarget target, Class<? extends ObjectType> type, ObjectQuery query) {
List<PageDebugDownloadBehaviour> list = get(ID_MAIN_FORM)
.getBehaviors(PageDebugDownloadBehaviour.class);
PageDebugDownloadBehaviour downloadBehaviour = list.get(0);
downloadBehaviour.setType(type);
downloadBehaviour.setQuery(query);
downloadBehaviour.setUseZip(hasToZip());
downloadBehaviour.initiate(target);
}
private void addOrReplaceTable(RepositoryObjectDataProvider provider) {
Form mainForm = (Form) get(ID_MAIN_FORM);
BoxedTablePanel table = new BoxedTablePanel(ID_TABLE, provider, initColumns(provider.getType()),
UserProfileStorage.TableId.CONF_DEBUG_LIST_PANEL,
(int) getItemsPerPage(UserProfileStorage.TableId.CONF_DEBUG_LIST_PANEL)) {
@Override
protected WebMarkupContainer createHeader(String headerId) {
return new SearchFragment(headerId, ID_TABLE_HEADER, PageDebugList.this, searchModel,
resourcesModel);
}
};
table.setOutputMarkupId(true);
ConfigurationStorage storage = getSessionStorage().getConfiguration();
table.setCurrentPage(storage.getPaging());
mainForm.addOrReplace(table);
}
private List<IColumn> initColumns(final Class<? extends ObjectType> type) {
List<IColumn> columns = new ArrayList<>();
IColumn column = new CheckBoxHeaderColumn<ObjectType>();
columns.add(column);
column = new LinkColumn<DebugObjectItem>(createStringResource("pageDebugList.name"),
DebugObjectItem.F_NAME, DebugObjectItem.F_NAME) {
@Override
public void populateItem(Item<ICellPopulator<DebugObjectItem>> cellItem, String componentId,
final IModel<DebugObjectItem> rowModel) {
TwoValueLinkPanel panel = new TwoValueLinkPanel(componentId,
new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
DebugObjectItem object = rowModel.getObject();
if (object == null) {
return null;
}
StringBuilder sb = new StringBuilder();
sb.append(object.getName());
if (object.getStatus() != null && object.getStatus() != OperationResultStatusType.SUCCESS
&& object.getStatus() != OperationResultStatusType.HANDLED_ERROR) {
sb.append(" (");
sb.append(object.getStatus());
sb.append(")");
}
return sb.toString();
}
},
new PropertyModel<String>(rowModel, DebugObjectItem.F_OID)) {
@Override
public void onClick(AjaxRequestTarget target) {
DebugObjectItem object = rowModel.getObject();
objectEditPerformed(target, object.getOid(), type);
}
@Override
public boolean isEnabled() {
return rowModel.getObject().getOid() != null;
}
};
cellItem.add(panel);
cellItem.add(new AttributeModifier("class", "col-md-3"));
}
};
columns.add(column);
columns.add(new PropertyColumn(createStringResource("pageDebugList.description"),
DebugObjectItem.F_DESCRIPTION));
if (ShadowType.class.isAssignableFrom(type)) {
columns.add(new PropertyColumn(createStringResource("pageDebugList.resourceName"),
DebugObjectItem.F_RESOURCE_NAME));
columns.add(new PropertyColumn(createStringResource("pageDebugList.resourceType"),
DebugObjectItem.F_RESOURCE_TYPE));
}
column = new AbstractColumn<DebugObjectItem, String>(new Model(), null) {
@Override
public String getCssClass() {
return "debug-list-buttons";
}
@Override
public void populateItem(Item<ICellPopulator<DebugObjectItem>> cellItem, String componentId,
IModel<DebugObjectItem> rowModel) {
cellItem.add(new DebugButtonPanel<DebugObjectItem>(componentId, rowModel) {
@Override
public void deletePerformed(AjaxRequestTarget target, IModel<DebugObjectItem> model) {
deleteSelected(target, model.getObject());
}
@Override
public void exportPerformed(AjaxRequestTarget target, IModel<DebugObjectItem> model) {
exportSelected(target, model.getObject());
}
});
}
};
columns.add(column);
column = new InlineMenuHeaderColumn<InlineMenuable>(initInlineMenu()) {
@Override
public void populateItem(Item<ICellPopulator<InlineMenuable>> cellItem, String componentId,
IModel<InlineMenuable> rowModel) {
// we don't need row inline menu
cellItem.add(new Label(componentId));
}
};
columns.add(column);
return columns;
}
private List<InlineMenuItem> initInlineMenu() {
List<InlineMenuItem> headerMenuItems = new ArrayList<>();
headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.exportSelected"),
true, new HeaderMenuAction(this) {
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
exportSelected(target, null);
}
}));
headerMenuItems
.add(new InlineMenuItem(createStringResource("pageDebugList.menu.exportAllSelectedType"),
true, new HeaderMenuAction(this) {
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
exportAllType(target);
}
}));
headerMenuItems
.add(new InlineMenuItem(createStringResource("pageDebugList.menu.exportShadowsOnResource"),
new Model(true), new AbstractReadOnlyModel<Boolean>() {
@Override
public Boolean getObject() {
DebugSearchDto dto = searchModel.getObject();
return ObjectTypes.SHADOW.equals(dto.getType());
}
}, false, new HeaderMenuAction(this) {
@Override
public void onClick(AjaxRequestTarget target) {
exportAllShadowsOnResource(target);
}
}));
headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.exportAll"), true,
new HeaderMenuAction(this) {
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
exportAll(target);
}
}));
headerMenuItems.add(new InlineMenuItem());
headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteSelected"),
true, new HeaderMenuAction(this) {
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
deleteSelected(target, null);
}
}));
headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteAllType"), true,
new HeaderMenuAction(this) {
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
deleteAllType(target);
}
}));
headerMenuItems
.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteShadowsOnResource"),
new Model(true), new AbstractReadOnlyModel<Boolean>() {
@Override
public Boolean getObject() {
DebugSearchDto dto = searchModel.getObject();
return ObjectTypes.SHADOW.equals(dto.getType());
}
}, false, new HeaderMenuAction(this) {
@Override
public void onClick(AjaxRequestTarget target) {
deleteAllShadowsOnResource(target);
}
}));
headerMenuItems.add(new InlineMenuItem());
headerMenuItems.add(new InlineMenuItem(createStringResource("pageDebugList.menu.deleteAllIdentities"),
true, new HeaderMenuAction(this) {
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
deleteAllIdentities(target);
}
}));
return headerMenuItems;
}
private boolean hasToZip() {
BoxedTablePanel table = (BoxedTablePanel) getListTable();
SearchFragment header = (SearchFragment) table.getHeader();
AjaxCheckBox zipCheck = header.getZipCheck();
return zipCheck.getModelObject();
}
private Table getListTable() {
return (Table) get(createComponentPath(ID_MAIN_FORM, ID_TABLE));
}
/**
* called when object type is changed, search panel will be refreshed
*/
private void listObjectsPerformed(AjaxRequestTarget target) {
DebugSearchDto dto = searchModel.getObject();
setupSearchDto(dto);
Search search = dto.getSearch();
ObjectQuery query = search.createObjectQuery(getPrismContext());
listObjectsPerformed(query, target);
}
private void setupSearchDto(DebugSearchDto dto) {
ObjectTypes type = dto.getType();
Search search = SearchFactory.createSearch(type.getClassDefinition(), getPrismContext(),
getModelInteractionService());
dto.setSearch(search);
}
private void listObjectsPerformed(ObjectQuery query, AjaxRequestTarget target) {
DebugSearchDto dto = searchModel.getObject();
ObjectTypes selected = dto.getType();
RepositoryObjectDataProvider provider = getTableDataProvider();
provider.setQuery(createQuery(query));
if (selected != null) {
provider.setType(selected.getClassDefinition());
addOrReplaceTable(provider);
}
// save object type category to session storage, used by back button
ConfigurationStorage storage = getSessionStorage().getConfiguration();
storage.setDebugSearchDto(dto);
Table table = getListTable();
target.add((Component) table);
}
private ObjectQuery createQuery(ObjectQuery searchQuery) {
DebugSearchDto dto = searchModel.getObject();
List<ObjectFilter> filters = new ArrayList<>();
if (ObjectTypes.SHADOW.equals(dto.getType()) && dto.getResource() != null) {
String oid = dto.getResource().getOid();
ObjectFilter objectFilter = QueryBuilder.queryFor(ShadowType.class, getPrismContext())
.item(ShadowType.F_RESOURCE_REF).ref(oid)
.buildFilter();
filters.add(objectFilter);
}
if (searchQuery != null && searchQuery.getFilter() != null) {
filters.add(searchQuery.getFilter());
}
if (filters.isEmpty()) {
return null;
}
ObjectFilter filter = filters.size() > 1 ? AndFilter.createAnd(filters) : filters.get(0);
ObjectQuery query = new ObjectQuery();
query.setFilter(filter);
return query;
}
private void objectEditPerformed(AjaxRequestTarget target, String oid, Class<? extends ObjectType> type) {
PageParameters parameters = new PageParameters();
parameters.add(PageDebugView.PARAM_OBJECT_ID, oid);
parameters.add(PageDebugView.PARAM_OBJECT_TYPE, type.getSimpleName());
navigateToNext(PageDebugView.class, parameters);
}
private RepositoryObjectDataProvider getTableDataProvider() {
Table tablePanel = getListTable();
DataTable table = tablePanel.getDataTable();
return (RepositoryObjectDataProvider) table.getDataProvider();
}
private IModel<String> createDeleteConfirmString() {
return new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
DebugConfDialogDto dto = confDialogModel.getObject();
switch (dto.getOperation()) {
case DELETE_ALL_TYPE:
String key = ObjectTypeGuiDescriptor.getDescriptor(dto.getType())
.getLocalizationKey();
String type = createStringResource(key).getString();
return createStringResource("pageDebugList.message.deleteAllType", type).getString();
case DELETE_SELECTED:
List<DebugObjectItem> selectedList = dto.getObjects();
if (selectedList.size() > 1) {
return createStringResource("pageDebugList.message.deleteSelectedConfirm",
selectedList.size()).getString();
}
DebugObjectItem selectedItem = selectedList.get(0);
return createStringResource("pageDebugList.message.deleteObjectConfirm",
selectedItem.getName()).getString();
case DELETE_RESOURCE_SHADOWS:
DebugSearchDto search = searchModel.getObject();
return createStringResource("pageDebugList.messsage.deleteAllResourceShadows",
search.getResource().getName()).getString();
}
return "";
}
};
}
private void deleteAllIdentitiesConfirmed(AjaxRequestTarget target, DeleteAllDto dto) {
Collection<SelectorOptions<GetOperationOptions>> options = new ArrayList<>();
GetOperationOptions opt = GetOperationOptions.createRaw();
options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, opt));
OperationResult result = new OperationResult(OPERATION_LAXATIVE_DELETE);
String taskOid = null;
try {
if (dto.getDeleteUsers()) {
ObjectQuery query = createDeleteAllUsersQuery();
taskOid = deleteObjectsAsync(UserType.COMPLEX_TYPE, query, true, "Delete all users", result);
}
if (dto.getDeleteOrgs()) {
taskOid = deleteObjectsAsync(OrgType.COMPLEX_TYPE, null, true, "Delete all orgs", result);
}
if (dto.getDeleteAccountShadow()) {
taskOid = deleteAllShadowsConfirmed(result, true);
}
if (dto.getDeleteNonAccountShadow()) {
taskOid = deleteAllShadowsConfirmed(result, false);
}
} catch (Exception ex) {
result.computeStatus(getString("pageDebugList.message.laxativeProblem"));
LoggingUtils.logUnexpectedException(LOGGER, getString("pageDebugList.message.laxativeProblem"), ex);
}
if (taskOid != null) {
PageParameters parameters = new PageParameters();
parameters.add(OnePageParameterEncoder.PARAMETER, taskOid);
navigateToNext(PageTaskEdit.class, parameters);
} else {
navigateToNext(PageTasks.class);
}
target.add(getFeedbackPanel());
result.recomputeStatus();
showResult(result);
}
private ObjectQuery createDeleteAllUsersQuery() {
InOidFilter inOid = InOidFilter.createInOid(SystemObjectsType.USER_ADMINISTRATOR.value());
NotFilter not = new NotFilter(inOid);
return ObjectQuery.createObjectQuery(not);
}
private String deleteAllShadowsConfirmed(OperationResult result, boolean deleteAccountShadows)
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException {
ObjectFilter kindFilter = QueryBuilder.queryFor(ShadowType.class, getPrismContext())
.item(ShadowType.F_KIND).eq(ShadowKindType.ACCOUNT)
.buildFilter();
String taskName;
ObjectQuery query;
if (deleteAccountShadows) {
taskName = "Delete all account shadows";
query = ObjectQuery.createObjectQuery(kindFilter);
} else {
taskName = "Delete all non-account shadows";
query = ObjectQuery.createObjectQuery(NotFilter.createNot(kindFilter));
}
return deleteObjectsAsync(ShadowType.COMPLEX_TYPE, query, true, taskName, result);
}
private void exportSelected(AjaxRequestTarget target, DebugObjectItem item) {
List<DebugObjectItem> selected = getSelectedData(target, item);
if (selected.isEmpty()) {
return;
}
List<String> oids = new ArrayList<>();
for (DebugObjectItem dItem : selected) {
oids.add(dItem.getOid());
}
ObjectFilter filter = InOidFilter.createInOid(oids);
DebugSearchDto searchDto = searchModel.getObject();
initDownload(target, searchDto.getType().getClassDefinition(), ObjectQuery.createObjectQuery(filter));
}
private void exportAllType(AjaxRequestTarget target) {
DebugSearchDto searchDto = searchModel.getObject();
initDownload(target, searchDto.getType().getClassDefinition(), null);
}
private void exportAll(AjaxRequestTarget target) {
initDownload(target, ObjectType.class, null);
}
private void deleteAllType(AjaxRequestTarget target) {
DebugSearchDto searchDto = searchModel.getObject();
DebugConfDialogDto dto = new DebugConfDialogDto(DebugConfDialogDto.Operation.DELETE_ALL_TYPE, null,
searchDto.getType().getClassDefinition());
confDialogModel.setObject(dto);
showMainPopup(getDeleteConfirmationPanel(), target);
}
private List<DebugObjectItem> getSelectedData(AjaxRequestTarget target, DebugObjectItem item) {
List<DebugObjectItem> items;
if (item != null) {
items = new ArrayList<>();
items.add(item);
return items;
}
items = WebComponentUtil.getSelectedData(getListTable());
if (items.isEmpty()) {
warn(getString("pageDebugList.message.nothingSelected"));
target.add(getFeedbackPanel());
}
return items;
}
private void deleteSelected(AjaxRequestTarget target, DebugObjectItem item) {
List<DebugObjectItem> selected = getSelectedData(target, item);
if (selected.isEmpty()) {
return;
}
DebugSearchDto searchDto = searchModel.getObject();
DebugConfDialogDto dto = new DebugConfDialogDto(DebugConfDialogDto.Operation.DELETE_SELECTED,
selected, searchDto.getType().getClassDefinition());
confDialogModel.setObject(dto);
showMainPopup(getDeleteConfirmationPanel(), target);
}
private void deleteAllIdentities(AjaxRequestTarget target) {
DeleteAllPanel dialog = new DeleteAllPanel(getMainPopupBodyId()){
@Override
public void yesPerformed(AjaxRequestTarget target) {
hideMainPopup(target);
deleteAllIdentitiesConfirmed(target, getModel().getObject());
}
};
showMainPopup(dialog, target);
}
private void deleteAllTypeConfirmed(AjaxRequestTarget target) {
DebugSearchDto dto = searchModel.getObject();
LOGGER.debug("Deleting all of type {}", dto.getType());
OperationResult result = new OperationResult(OPERATION_DELETE_OBJECTS);
String taskOid = null;
try {
ObjectQuery query = null;
if (ObjectTypes.USER.equals(dto.getType())) {
query = createDeleteAllUsersQuery();
}
QName type = dto.getType().getTypeQName();
taskOid = deleteObjectsAsync(type, query, true, "Delete all of type " + type.getLocalPart(),
result);
info(getString("pageDebugList.messsage.deleteAllOfType", dto.getType()));
} catch (Exception ex) {
result.recomputeStatus();
result.recordFatalError("Couldn't delete objects of type " + dto.getType(), ex);
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't delete objects of type " + dto.getType(), ex);
}
showResult(result);
if (taskOid != null) {
PageParameters parameters = new PageParameters();
parameters.add(OnePageParameterEncoder.PARAMETER, taskOid);
navigateToNext(PageTaskEdit.class, parameters);
} else {
navigateToNext(PageTasks.class);
}
target.add(getFeedbackPanel());
}
private void deleteSelectedConfirmed(AjaxRequestTarget target, List<DebugObjectItem> items) {
DebugConfDialogDto dto = confDialogModel.getObject();
OperationResult result = new OperationResult(OPERATION_DELETE_OBJECTS);
for (DebugObjectItem bean : items) {
WebModelServiceUtils.deleteObject(dto.getType(), bean.getOid(), ModelExecuteOptions.createRaw(),
result, this);
}
result.computeStatusIfUnknown();
RepositoryObjectDataProvider provider = getTableDataProvider();
provider.clearCache();
showResult(result);
target.add((Component) getListTable());
target.add(getFeedbackPanel());
}
private void deleteAllShadowsOnResource(AjaxRequestTarget target) {
DebugSearchDto dto = searchModel.getObject();
if (dto.getResource() == null) {
error(getString("pageDebugList.message.resourceNotSelected"));
target.add(getFeedbackPanel());
return;
}
LOGGER.debug("Displaying delete all shadows on resource {} confirmation dialog",
dto.getResource().getName());
DebugConfDialogDto dialogDto = new DebugConfDialogDto(
DebugConfDialogDto.Operation.DELETE_RESOURCE_SHADOWS, null, null);
confDialogModel.setObject(dialogDto);
showMainPopup(getDeleteConfirmationPanel(), target);
}
private void exportAllShadowsOnResource(AjaxRequestTarget target) {
DebugSearchDto dto = searchModel.getObject();
if (dto.getResource() == null) {
error(getString("pageDebugList.message.resourceNotSelected"));
target.add(getFeedbackPanel());
return;
}
ObjectQuery objectQuery = QueryBuilder.queryFor(ShadowType.class, getPrismContext())
.item(ShadowType.F_RESOURCE_REF).ref(dto.getResource().getOid())
.build();
initDownload(target, dto.getType().getClassDefinition(), objectQuery);
}
private Popupable getDeleteConfirmationPanel() {
return new ConfirmationPanel(getMainPopupBodyId(), createDeleteConfirmString()) {
private static final long serialVersionUID = 1L;
@Override
public void yesPerformed(AjaxRequestTarget target) {
ModalWindow modalWindow = findParent(ModalWindow.class);
if (modalWindow != null) {
modalWindow.close(target);
DebugConfDialogDto dto = confDialogModel.getObject();
switch (dto.getOperation()) {
case DELETE_ALL_TYPE:
deleteAllTypeConfirmed(target);
break;
case DELETE_SELECTED:
deleteSelectedConfirmed(target, dto.getObjects());
break;
case DELETE_RESOURCE_SHADOWS:
deleteAllShadowsOnResourceConfirmed(target);
break;
}
}
}
@Override
public boolean getLabelEscapeModelStrings() {
return false;
}
};
}
private void deleteAllShadowsOnResourceConfirmed(AjaxRequestTarget target) {
DebugSearchDto dto = searchModel.getObject();
String resourceOid = dto.getResource().getOid();
LOGGER.debug("Deleting shadows on resource {}", resourceOid);
OperationResult result = new OperationResult(OPERATION_DELETE_SHADOWS);
String taskOid = null;
try {
ObjectQuery objectQuery = QueryBuilder.queryFor(ShadowType.class, getPrismContext())
.item(ShadowType.F_RESOURCE_REF).ref(dto.getResource().getOid())
.build();
QName type = ShadowType.COMPLEX_TYPE;
taskOid = deleteObjectsAsync(type, objectQuery, true,
"Delete shadows on " + dto.getResource().getName(), result);
info(getString("pageDebugList.messsage.deleteAllShadowsStarted", dto.getResource().getName()));
} catch (Exception ex) {
result.recomputeStatus();
result.recordFatalError("Couldn't delete shadows.", ex);
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't delete shadows", ex);
}
showResult(result);
if (taskOid != null) {
PageParameters parameters = new PageParameters();
parameters.add(OnePageParameterEncoder.PARAMETER, taskOid);
navigateToNext(PageTaskEdit.class, parameters);
} else {
navigateToNext(PageTasks.class);
}
target.add(getFeedbackPanel());
}
private String deleteObjectsAsync(QName type, ObjectQuery objectQuery, boolean raw, String taskName,
OperationResult result)
throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException {
Task task = createSimpleTask(result.getOperation());
task.setHandlerUri(ModelPublicConstants.DELETE_TASK_HANDLER_URI);
if (objectQuery == null) {
objectQuery = new ObjectQuery();
}
QueryType query = QueryJaxbConvertor.createQueryType(objectQuery, getPrismContext());
PrismPropertyDefinition queryDef = new PrismPropertyDefinitionImpl(
SchemaConstants.MODEL_EXTENSION_OBJECT_QUERY, QueryType.COMPLEX_TYPE, getPrismContext());
PrismProperty<QueryType> queryProp = queryDef.instantiate();
queryProp.setRealValue(query);
task.setExtensionProperty(queryProp);
PrismPropertyDefinition typeDef = new PrismPropertyDefinitionImpl(
SchemaConstants.MODEL_EXTENSION_OBJECT_TYPE, DOMUtil.XSD_QNAME, getPrismContext());
PrismProperty<QName> typeProp = typeDef.instantiate();
typeProp.setRealValue(type);
task.setExtensionProperty(typeProp);
PrismPropertyDefinition rawDef = new PrismPropertyDefinitionImpl(
SchemaConstants.MODEL_EXTENSION_OPTION_RAW, DOMUtil.XSD_BOOLEAN, getPrismContext());
PrismProperty<QName> rawProp = rawDef.instantiate();
rawProp.setRealValue(raw);
task.setExtensionProperty(rawProp);
task.setName(taskName);
task.savePendingModifications(result);
TaskManager taskManager = getTaskManager();
taskManager.switchToBackground(task, result);
result.setBackgroundTaskOid(task.getOid());
return task.getOid();
}
private static class SearchFragment extends Fragment {
public SearchFragment(String id, String markupId, MarkupContainer markupProvider,
IModel<DebugSearchDto> model, IModel<List<ObjectViewDto>> resourcesModel) {
super(id, markupId, markupProvider, model);
initLayout(resourcesModel);
}
private void initLayout(IModel<List<ObjectViewDto>> resourcesModel) {
final Form searchForm = new Form(ID_SEARCH_FORM);
add(searchForm);
searchForm.setOutputMarkupId(true);
final IModel<DebugSearchDto> model = (IModel) getDefaultModel();
EnumChoiceRenderer<ObjectTypes> renderer = new EnumChoiceRenderer<ObjectTypes>() {
protected String resourceKey(ObjectTypes object) {
ObjectTypeGuiDescriptor descr = ObjectTypeGuiDescriptor.getDescriptor(object);
String key = descr != null ? descr.getLocalizationKey()
: ObjectTypeGuiDescriptor.ERROR_LOCALIZATION_KEY;
return key;
}
};
WebMarkupContainer choiceContainer = new WebMarkupContainer(ID_CHOICE_CONTAINER);
choiceContainer.setOutputMarkupId(true);
choiceContainer.add(new AttributeAppender("style", new LoadableModel<String>() {
private static final long serialVersionUID = 1L;
@Override
public String load(){
PageDebugList page = (PageDebugList) getPage();
return page.searchModel.getObject().getSearch().isFullTextSearchEnabled() ?
"margin-top: -15px;" : "";
}
}));
searchForm.add(choiceContainer);
DropDownChoice choice = new DropDownChoice(ID_CHOICE,
new PropertyModel(model, DebugSearchDto.F_TYPE), createChoiceModel(renderer), renderer);
choiceContainer.add(choice);
choice.add(new OnChangeAjaxBehavior() {
@Override
protected void onUpdate(AjaxRequestTarget target) {
PageDebugList page = (PageDebugList) getPage();
page.listObjectsPerformed(target);
}
});
DropDownChoice resource = new DropDownChoice(ID_RESOURCE,
new PropertyModel(model, DebugSearchDto.F_RESOURCE), resourcesModel,
createResourceRenderer());
resource.setNullValid(true);
resource.add(new AjaxFormComponentUpdatingBehavior("blur") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
// nothing to do, it's here just to update model
}
});
resource.add(new OnChangeAjaxBehavior() {
@Override
protected void onUpdate(AjaxRequestTarget target) {
PageDebugList page = (PageDebugList) getPage();
page.listObjectsPerformed(target);
}
});
resource.add(new VisibleEnableBehaviour() {
@Override
public boolean isVisible() {
DebugSearchDto dto = model.getObject();
return ObjectTypes.SHADOW.equals(dto.getType());
}
});
searchForm.add(resource);
AjaxCheckBox zipCheck = new AjaxCheckBox(ID_ZIP_CHECK, new Model<>(false)) {
@Override
protected void onUpdate(AjaxRequestTarget target) {
}
};
add(zipCheck);
SearchPanel search = new SearchPanel(ID_SEARCH,
new PropertyModel<Search>(model, DebugSearchDto.F_SEARCH)) {
@Override
public void searchPerformed(ObjectQuery query, AjaxRequestTarget target) {
PageDebugList page = (PageDebugList) getPage();
page.listObjectsPerformed(query, target);
}
};
searchForm.add(search);
}
public AjaxCheckBox getZipCheck() {
return (AjaxCheckBox) get(ID_ZIP_CHECK);
}
private IModel<List<ObjectTypes>> createChoiceModel(final IChoiceRenderer<ObjectTypes> renderer) {
return new LoadableModel<List<ObjectTypes>>(false) {
@Override
protected List<ObjectTypes> load() {
List<ObjectTypes> choices = new ArrayList<>();
Collections.addAll(choices, ObjectTypes.values());
choices.remove(ObjectTypes.OBJECT);
Collections.sort(choices, new Comparator<ObjectTypes>() {
@Override
public int compare(ObjectTypes o1, ObjectTypes o2) {
String str1 = (String) renderer.getDisplayValue(o1);
String str2 = (String) renderer.getDisplayValue(o2);
return String.CASE_INSENSITIVE_ORDER.compare(str1, str2);
}
});
return choices;
}
};
}
private IChoiceRenderer<ObjectViewDto> createResourceRenderer() {
return new ChoiceableChoiceRenderer<ObjectViewDto>() {
@Override
public Object getDisplayValue(ObjectViewDto object) {
if (object == null) {
return getString("pageDebugList.resource");
}
return object.getName();
}
};
}
}
}