/*
* 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.resources;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl;
import com.evolveum.midpoint.web.session.SessionStorage;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteQNamePanel;
import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteTextPanel;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.resources.content.dto.ResourceContentSearchDto;
import com.evolveum.midpoint.web.session.ResourceContentStorage;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;
/**
* @author katkav
* @author semancik
*/
public class ResourceContentTabPanel extends Panel {
private static final long serialVersionUID = 1L;
private static final Trace LOGGER = TraceManager.getTrace(ResourceContentTabPanel.class);
enum Operation {
REMOVE, MODIFY;
}
private static final String DOT_CLASS = ResourceContentTabPanel.class.getName() + ".";
private static final String ID_INTENT = "intent";
private static final String ID_REAL_OBJECT_CLASS = "realObjectClass";
private static final String ID_OBJECT_CLASS = "objectClass";
private static final String ID_MAIN_FORM = "mainForm";
private static final String ID_REPO_SEARCH = "repositorySearch";
private static final String ID_RESOURCE_SEARCH = "resourceSearch";
private static final String ID_TABLE = "table";
private PageBase parentPage;
private ShadowKindType kind;
private boolean useObjectClass;
private boolean isRepoSearch = true;
private IModel<ResourceContentSearchDto> resourceContentSearch;
public ResourceContentTabPanel(String id, final ShadowKindType kind,
final IModel<PrismObject<ResourceType>> model, PageBase parentPage) {
super(id, model);
this.parentPage = parentPage;
this.resourceContentSearch = createContentSearchModel(kind);
this.kind = kind;
initLayout(model, parentPage);
}
private IModel<ResourceContentSearchDto> createContentSearchModel(final ShadowKindType kind) {
return new LoadableModel<ResourceContentSearchDto>(true) {
private static final long serialVersionUID = 1L;
@Override
protected ResourceContentSearchDto load() {
isRepoSearch = !getContentStorage(kind, SessionStorage.KEY_RESOURCE_PAGE_REPOSITORY_CONTENT).getResourceSearch();
return getContentStorage(kind, isRepoSearch ? SessionStorage.KEY_RESOURCE_PAGE_REPOSITORY_CONTENT :
SessionStorage.KEY_RESOURCE_PAGE_RESOURCE_CONTENT).getContentSearch();
}
};
}
private void updateResourceContentSearch() {
ResourceContentSearchDto searchDto = resourceContentSearch.getObject();
getContentStorage(kind, isRepoSearch ? SessionStorage.KEY_RESOURCE_PAGE_REPOSITORY_CONTENT :
SessionStorage.KEY_RESOURCE_PAGE_RESOURCE_CONTENT).setContentSearch(searchDto);
}
private ResourceContentStorage getContentStorage(ShadowKindType kind, String searchMode) {
return parentPage.getSessionStorage().getResourceContentStorage(kind, searchMode);
}
private void initLayout(final IModel<PrismObject<ResourceType>> model, final PageBase parentPage) {
setOutputMarkupId(true);
final Form mainForm = new Form(ID_MAIN_FORM);
mainForm.setOutputMarkupId(true);
mainForm.addOrReplace(initTable(model));
add(mainForm);
AutoCompleteTextPanel<String> intent = new AutoCompleteTextPanel<String>(ID_INTENT,
new PropertyModel<String>(resourceContentSearch, "intent"), String.class) {
private static final long serialVersionUID = 1L;
@Override
public Iterator<String> getIterator(String input) {
RefinedResourceSchema refinedSchema = null;
try {
refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(model.getObject(),
parentPage.getPrismContext());
} catch (SchemaException e) {
return new ArrayList<String>().iterator();
}
return RefinedResourceSchemaImpl.getIntentsForKind(refinedSchema, getKind()).iterator();
}
};
intent.getBaseFormComponent().add(new OnChangeAjaxBehavior() {
private static final long serialVersionUID = 1L;
@Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(get(ID_REAL_OBJECT_CLASS));
updateResourceContentSearch();
mainForm.addOrReplace(initTable(model));
target.add(mainForm);
}
});
intent.setOutputMarkupId(true);
intent.add(new VisibleEnableBehaviour() {
private static final long serialVersionUID = 1L;
@Override
public boolean isVisible() {
return !isUseObjectClass();
}
});
add(intent);
Label realObjectClassLabel = new Label(ID_REAL_OBJECT_CLASS, new AbstractReadOnlyModel<String>() {
private static final long serialVersionUID = 1L;
@Override
public String getObject() {
RefinedObjectClassDefinition ocDef;
try {
RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl
.getRefinedSchema(model.getObject(), parentPage.getPrismContext());
if (refinedSchema == null) {
return "NO SCHEMA DEFINED";
}
ocDef = refinedSchema.getRefinedDefinition(getKind(), getIntent());
if (ocDef != null) {
return ocDef.getObjectClassDefinition().getTypeName().getLocalPart();
}
} catch (SchemaException e) {
}
return "NOT FOUND";
}
});
realObjectClassLabel.setOutputMarkupId(true);
add(realObjectClassLabel);
AutoCompleteQNamePanel objectClassPanel = new AutoCompleteQNamePanel(ID_OBJECT_CLASS,
new PropertyModel<QName>(resourceContentSearch, "objectClass")) {
private static final long serialVersionUID = 1L;
@Override
public Collection<QName> loadChoices() {
return createObjectClassChoices(model);
}
@Override
protected void onChange(AjaxRequestTarget target) {
LOGGER.trace("Object class panel update: {}", isUseObjectClass());
updateResourceContentSearch();
mainForm.addOrReplace(initTable(model));
target.add(mainForm);
}
};
objectClassPanel.add(new VisibleEnableBehaviour() {
private static final long serialVersionUID = 1L;
@Override
public boolean isVisible() {
return isUseObjectClass();
}
});
add(objectClassPanel);
AjaxLink<Boolean> repoSearch = new AjaxLink<Boolean>(ID_REPO_SEARCH,
new PropertyModel<Boolean>(resourceContentSearch, "resourceSearch")) {
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
isRepoSearch = true;
getContentStorage(kind, SessionStorage.KEY_RESOURCE_PAGE_REPOSITORY_CONTENT).setResourceSearch(Boolean.FALSE);
getContentStorage(kind, SessionStorage.KEY_RESOURCE_PAGE_RESOURCE_CONTENT).setResourceSearch(Boolean.FALSE);
resourceContentSearch.getObject().setResourceSearch(Boolean.FALSE);
updateResourceContentSearch();
mainForm.addOrReplace(initRepoContent(model));
target.add(getParent().addOrReplace(mainForm));
target.add(this);
target.add(getParent().get(ID_RESOURCE_SEARCH)
.add(AttributeModifier.replace("class", "btn btn-sm btn-default")));
}
@Override
protected void onBeforeRender() {
super.onBeforeRender();
if (!getModelObject().booleanValue())
add(AttributeModifier.replace("class", "btn btn-sm btn-default active"));
}
};
add(repoSearch);
AjaxLink<Boolean> resourceSearch = new AjaxLink<Boolean>(ID_RESOURCE_SEARCH,
new PropertyModel<Boolean>(resourceContentSearch, "resourceSearch")) {
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
isRepoSearch = false;
getContentStorage(kind, SessionStorage.KEY_RESOURCE_PAGE_REPOSITORY_CONTENT).setResourceSearch(Boolean.TRUE);
getContentStorage(kind, SessionStorage.KEY_RESOURCE_PAGE_RESOURCE_CONTENT).setResourceSearch(Boolean.TRUE);
updateResourceContentSearch();
resourceContentSearch.getObject().setResourceSearch(Boolean.TRUE);
mainForm.addOrReplace(initResourceContent(model));
target.add(getParent().addOrReplace(mainForm));
target.add(this.add(AttributeModifier.append("class", " active")));
target.add(getParent().get(ID_REPO_SEARCH)
.add(AttributeModifier.replace("class", "btn btn-sm btn-default")));
}
@Override
protected void onBeforeRender() {
super.onBeforeRender();
getModelObject().booleanValue();
if (getModelObject().booleanValue())
add(AttributeModifier.replace("class", "btn btn-sm btn-default active"));
}
};
add(resourceSearch);
}
private List<QName> createObjectClassChoices(IModel<PrismObject<ResourceType>> model) {
RefinedResourceSchema refinedSchema;
try {
refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(model.getObject(),
parentPage.getPrismContext());
} catch (SchemaException e) {
warn("Could not determine defined obejct classes for resource");
return new ArrayList<QName>();
}
Collection<ObjectClassComplexTypeDefinition> defs = refinedSchema.getObjectClassDefinitions();
List<QName> objectClasses = new ArrayList<QName>(defs.size());
for (ObjectClassComplexTypeDefinition def : defs) {
objectClasses.add(def.getTypeName());
}
return objectClasses;
}
private ResourceContentPanel initTable(IModel<PrismObject<ResourceType>> model) {
if (isResourceSearch()) {
return initResourceContent(model);
} else {
return initRepoContent(model);
}
}
private ResourceContentResourcePanel initResourceContent(IModel<PrismObject<ResourceType>> model) {
String searchMode = isRepoSearch ? SessionStorage.KEY_RESOURCE_PAGE_REPOSITORY_CONTENT :
SessionStorage.KEY_RESOURCE_PAGE_RESOURCE_CONTENT;
ResourceContentResourcePanel resourceContent = new ResourceContentResourcePanel(ID_TABLE, model,
getObjectClass(), getKind(), getIntent(), searchMode, parentPage);
resourceContent.setOutputMarkupId(true);
return resourceContent;
}
private ResourceContentRepositoryPanel initRepoContent(IModel<PrismObject<ResourceType>> model) {
String searchMode = isRepoSearch ? SessionStorage.KEY_RESOURCE_PAGE_REPOSITORY_CONTENT :
SessionStorage.KEY_RESOURCE_PAGE_RESOURCE_CONTENT;
ResourceContentRepositoryPanel repositoryContent = new ResourceContentRepositoryPanel(ID_TABLE, model,
getObjectClass(), getKind(), getIntent(), searchMode, parentPage);
repositoryContent.setOutputMarkupId(true);
return repositoryContent;
}
private ShadowKindType getKind() {
return resourceContentSearch.getObject().getKind();
}
private String getIntent() {
return resourceContentSearch.getObject().getIntent();
}
private QName getObjectClass() {
return resourceContentSearch.getObject().getObjectClass();
}
private boolean isResourceSearch() {
Boolean isResourceSearch = resourceContentSearch.getObject().isResourceSearch();
if (isResourceSearch == null) {
return false;
}
return resourceContentSearch.getObject().isResourceSearch();
}
private boolean isUseObjectClass() {
return resourceContentSearch.getObject().isUseObjectClass();
}
}