blob: d15188a7f55101dc59b4dae7e91205037c9dff79 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.syncope.client.console.panels.search;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.checkbox.bootstraptoggle.BootstrapToggle;
import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.checkbox.bootstraptoggle.BootstrapToggleConfig;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.console.panels.search.SearchClause.Comparator;
import org.apache.syncope.client.console.panels.search.SearchClause.Operator;
import org.apache.syncope.client.console.panels.search.SearchClause.Type;
import org.apache.syncope.client.console.rest.GroupRestClient;
import org.apache.syncope.client.console.rest.RelationshipTypeRestClient;
import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxEventBehavior;
import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.client.ui.commons.SchemaUtils;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.PlainSchemaTO;
import org.apache.syncope.common.lib.to.RelationshipTypeTO;
import org.apache.syncope.common.lib.types.AttrSchemaType;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxCallListener;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.event.Broadcast;
import org.apache.wicket.event.IEventSink;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
public class SearchClausePanel extends FieldPanel<SearchClause> {
private static final long serialVersionUID = -527351923968737757L;
protected static final AttributeModifier PREVENT_DEFAULT_RETURN = AttributeModifier.replace(
"onkeydown",
Model.of("if (event.keyCode == 13) { event.preventDefault(); }"));
protected static final Consumer<AjaxRequestAttributes> AJAX_SUBMIT_ON_RETURN =
attributes -> attributes.getAjaxCallListeners().add(new AjaxCallListener() {
private static final long serialVersionUID = 7160235486520935153L;
@Override
public CharSequence getPrecondition(final Component component) {
return "return (Wicket.Event.keyCode(attrs.event) == 13);";
}
});
public interface Customizer extends Serializable {
default IChoiceRenderer<SearchClause.Type> typeRenderer() {
return new ChoiceRenderer<>();
}
default List<Comparator> comparators() {
return List.of();
}
default String comparatorDisplayValue(Comparator object) {
return object.toString();
}
default Optional<SearchClause.Comparator> comparatorGetObject(String id) {
return Optional.empty();
}
default List<String> properties() {
return List.of();
}
default void setFieldAccess(
FieldPanel<String> value,
AjaxTextFieldPanel property,
LoadableDetachableModel<List<String>> properties) {
value.setEnabled(true);
value.setModelObject(StringUtils.EMPTY);
property.setEnabled(true);
// reload properties list
properties.detach();
property.setChoices(properties.getObject());
}
}
private final boolean required;
private final IModel<List<SearchClause.Type>> types;
private final Customizer customizer;
private final IModel<Map<String, PlainSchemaTO>> anames;
private final IModel<Map<String, PlainSchemaTO>> dnames;
private final Pair<IModel<List<String>>, IModel<Integer>> groupInfo;
private final IModel<List<String>> roleNames;
private final IModel<List<String>> privilegeNames;
private final IModel<List<String>> resourceNames;
private IModel<SearchClause> clause;
private final LoadableDetachableModel<List<Comparator>> comparators;
private final LoadableDetachableModel<List<String>> properties;
private final Fragment operatorFragment;
private final Fragment searchButtonFragment;
private final AjaxLink<Void> searchButton;
private IEventSink resultContainer;
@SuppressWarnings({ "rawtypes", "unchecked" })
private FieldPanel value;
private final GroupRestClient groupRestClient = new GroupRestClient();
public SearchClausePanel(
final String id,
final String name,
final Model<SearchClause> clause,
final boolean required,
final IModel<List<SearchClause.Type>> types,
final Customizer customizer,
final IModel<Map<String, PlainSchemaTO>> anames,
final IModel<Map<String, PlainSchemaTO>> dnames,
final Pair<IModel<List<String>>, IModel<Integer>> groupInfo,
final IModel<List<String>> roleNames,
final IModel<List<String>> privilegeNames,
final IModel<List<String>> resourceNames) {
super(id, name, clause);
this.clause = clause == null ? new Model<>(null) : clause;
this.required = required;
this.types = types;
this.customizer = customizer;
this.anames = anames;
this.dnames = dnames;
this.groupInfo = groupInfo;
this.roleNames = roleNames;
this.privilegeNames = privilegeNames;
this.resourceNames = resourceNames;
searchButton = new AjaxLink<Void>("search") {
private static final long serialVersionUID = 5538299138211283825L;
@Override
public void onClick(final AjaxRequestTarget target) {
if (resultContainer == null) {
send(SearchClausePanel.this, Broadcast.BUBBLE, new SearchEvent(target));
} else {
send(resultContainer, Broadcast.EXACT, new SearchEvent(target));
}
}
};
searchButtonFragment = new Fragment("operator", "searchButtonFragment", this);
searchButtonFragment.add(searchButton.setEnabled(false).setVisible(false));
operatorFragment = new Fragment("operator", "operatorFragment", this);
field = new FormComponent<SearchClause>("container", this.clause) {
private static final long serialVersionUID = -8204140666393922700L;
};
add(field);
comparators = new LoadableDetachableModel<List<Comparator>>() {
private static final long serialVersionUID = 5275935387613157437L;
@Override
protected List<Comparator> load() {
if (field.getModel().getObject() == null || field.getModel().getObject().getType() == null) {
return List.of();
}
switch (field.getModel().getObject().getType()) {
case ATTRIBUTE:
return List.of(SearchClause.Comparator.values());
case ROLE_MEMBERSHIP:
case PRIVILEGE:
case GROUP_MEMBERSHIP:
case GROUP_MEMBER:
case RESOURCE:
return List.of(
SearchClause.Comparator.EQUALS,
SearchClause.Comparator.NOT_EQUALS);
case RELATIONSHIP:
return List.of(
SearchClause.Comparator.IS_NOT_NULL,
SearchClause.Comparator.IS_NULL,
SearchClause.Comparator.EQUALS,
SearchClause.Comparator.NOT_EQUALS);
case CUSTOM:
return customizer.comparators();
default:
return List.of();
}
}
};
properties = new LoadableDetachableModel<List<String>>() {
private static final long serialVersionUID = 5275935387613157437L;
@Override
protected List<String> load() {
if (field.getModel().getObject() == null || field.getModel().getObject().getType() == null) {
return List.of();
}
switch (field.getModel().getObject().getType()) {
case ATTRIBUTE:
List<String> names = new ArrayList<>(dnames.getObject().keySet());
if (anames != null && anames.getObject() != null && !anames.getObject().isEmpty()) {
names.addAll(anames.getObject().keySet());
}
return names.stream().sorted().collect(Collectors.toList());
case GROUP_MEMBERSHIP:
return groupInfo.getLeft().getObject();
case ROLE_MEMBERSHIP:
return roleNames.getObject().stream().
sorted().collect(Collectors.toList());
case PRIVILEGE:
return privilegeNames.getObject().stream().
sorted().collect(Collectors.toList());
case RESOURCE:
return resourceNames.getObject().stream().
sorted().collect(Collectors.toList());
case RELATIONSHIP:
return RelationshipTypeRestClient.list().stream().
map(RelationshipTypeTO::getKey).collect(Collectors.toList());
case CUSTOM:
return customizer.properties();
default:
return List.of();
}
}
};
}
public void enableSearch(final IEventSink resultContainer) {
this.resultContainer = resultContainer;
this.searchButton.setEnabled(true);
this.searchButton.setVisible(true);
field.add(PREVENT_DEFAULT_RETURN);
field.add(new AjaxEventBehavior(Constants.ON_KEYDOWN) {
private static final long serialVersionUID = -7133385027739964990L;
@Override
protected void onEvent(final AjaxRequestTarget target) {
if (resultContainer == null) {
send(SearchClausePanel.this, Broadcast.BUBBLE, new SearchEvent(target));
} else {
send(resultContainer, Broadcast.EXACT, new SearchEvent(target));
}
}
@Override
protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
AJAX_SUBMIT_ON_RETURN.accept(attributes);
}
});
}
@Override
public SearchClause getModelObject() {
return this.clause.getObject();
}
@Override
public FieldPanel<SearchClause> setModelObject(final SearchClause object) {
this.clause.setObject(object);
return super.setModelObject(object);
}
@Override
@SuppressWarnings("rawtypes")
public FieldPanel<SearchClause> setNewModel(final ListItem item) {
clause.setObject(SearchClause.class.cast(item.getModelObject()));
return this;
}
@Override
public FieldPanel<SearchClause> setNewModel(final IModel<SearchClause> model) {
clause = model;
return super.setNewModel(model);
}
@Override
public final MarkupContainer add(final Component... childs) {
return super.add(childs);
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public FieldPanel<SearchClause> settingsDependingComponents() {
SearchClause searchClause = this.clause.getObject();
WebMarkupContainer operatorContainer = new WebMarkupContainer("operatorContainer");
operatorContainer.setOutputMarkupId(true);
field.add(operatorContainer);
BootstrapToggleConfig config = new BootstrapToggleConfig().
withOnStyle(BootstrapToggleConfig.Style.info).
withOffStyle(BootstrapToggleConfig.Style.warning).
withSize(BootstrapToggleConfig.Size.mini);
operatorFragment.add(new BootstrapToggle("operator", new Model<Boolean>() {
private static final long serialVersionUID = -7157802546272668001L;
@Override
public Boolean getObject() {
return searchClause.getOperator() == Operator.AND;
}
@Override
public void setObject(final Boolean object) {
searchClause.setOperator(object ? Operator.AND : Operator.OR);
}
}, config) {
private static final long serialVersionUID = 2969634208049189343L;
@Override
protected IModel<String> getOffLabel() {
return Model.of("OR");
}
@Override
protected IModel<String> getOnLabel() {
return Model.of("AND");
}
@Override
protected CheckBox newCheckBox(final String id, final IModel<Boolean> model) {
CheckBox checkBox = super.newCheckBox(id, model);
checkBox.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
private static final long serialVersionUID = 18266219802290L;
@Override
protected void onUpdate(final AjaxRequestTarget target) {
}
});
return checkBox;
}
}.setOutputMarkupPlaceholderTag(true));
if (getIndex() > 0) {
operatorContainer.add(operatorFragment);
} else {
operatorContainer.add(searchButtonFragment);
}
AjaxTextFieldPanel property = new AjaxTextFieldPanel(
"property", "property", new PropertyModel<>(searchClause, "property"), true);
property.hideLabel().setOutputMarkupId(true).setEnabled(true);
property.setChoices(properties.getObject());
field.add(property);
property.getField().add(PREVENT_DEFAULT_RETURN);
property.getField().add(new IndicatorAjaxEventBehavior(Constants.ON_KEYUP) {
private static final long serialVersionUID = -957948639666058749L;
@Override
protected void onEvent(final AjaxRequestTarget target) {
if (field.getModel().getObject() != null
&& field.getModel().getObject().getType() == Type.GROUP_MEMBERSHIP) {
String[] inputAsArray = property.getField().getInputAsArray();
if (ArrayUtils.isEmpty(inputAsArray)) {
property.setChoices(properties.getObject());
} else if (groupInfo.getRight().getObject() > Constants.MAX_GROUP_LIST_SIZE) {
String inputValue = inputAsArray.length > 1 && inputAsArray[1] != null
? inputAsArray[1]
: property.getField().getInput();
if (!inputValue.startsWith("*")) {
inputValue = "*" + inputValue;
}
if (!inputValue.endsWith("*")) {
inputValue += "*";
}
property.setChoices(groupRestClient.search(
SyncopeConstants.ROOT_REALM,
SyncopeClient.getGroupSearchConditionBuilder().
is(Constants.NAME_FIELD_NAME).equalToIgnoreCase(inputValue).
query(),
1,
Constants.MAX_GROUP_LIST_SIZE,
new SortParam<>(Constants.NAME_FIELD_NAME, true),
null).stream().map(GroupTO::getName).collect(Collectors.toList()));
}
}
}
});
property.getField().add(new IndicatorAjaxEventBehavior(Constants.ON_KEYDOWN) {
private static final long serialVersionUID = -7133385027739964990L;
@Override
protected void onEvent(final AjaxRequestTarget target) {
target.focusComponent(null);
property.getField().inputChanged();
property.getField().validate();
if (property.getField().isValid()) {
property.getField().valid();
property.getField().updateModel();
}
}
@Override
protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
AJAX_SUBMIT_ON_RETURN.accept(attributes);
}
});
AjaxDropDownChoicePanel<SearchClause.Comparator> comparator = new AjaxDropDownChoicePanel<>(
"comparator", "comparator", new PropertyModel<>(searchClause, "comparator"));
comparator.setChoices(comparators);
comparator.setNullValid(false).hideLabel().setOutputMarkupId(true);
comparator.setRequired(required);
comparator.setChoiceRenderer(getComparatorRender(field.getModel()));
field.add(comparator);
renderSearchValueField(searchClause, property);
field.addOrReplace(value);
property.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
private static final long serialVersionUID = -1107858522700306810L;
@Override
protected void onUpdate(final AjaxRequestTarget target) {
renderSearchValueField(searchClause, property);
field.addOrReplace(value);
target.add(value);
}
});
AjaxDropDownChoicePanel<SearchClause.Type> type = new AjaxDropDownChoicePanel<>(
"type", "type", new PropertyModel<>(searchClause, "type"));
type.setChoices(types).setChoiceRenderer(customizer.typeRenderer()).
hideLabel().setRequired(required).setOutputMarkupId(true);
type.setNullValid(false);
type.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
private static final long serialVersionUID = -1107858522700306810L;
@Override
protected void onUpdate(final AjaxRequestTarget target) {
final SearchClause searchClause = new SearchClause();
if (StringUtils.isNotEmpty(type.getDefaultModelObjectAsString())) {
searchClause.setType(Type.valueOf(type.getDefaultModelObjectAsString()));
}
SearchClausePanel.this.clause.setObject(searchClause);
setFieldAccess(searchClause.getType(), property, comparator, value);
// reset property value in case and just in case of change of type
property.setModelObject(StringUtils.EMPTY);
target.add(property);
target.add(comparator);
target.add(value);
}
});
field.add(type);
comparator.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
private static final long serialVersionUID = -1107858522700306810L;
@Override
protected void onUpdate(final AjaxRequestTarget target) {
if (type.getModelObject() == SearchClause.Type.ATTRIBUTE
|| type.getModelObject() == SearchClause.Type.RELATIONSHIP) {
if (comparator.getModelObject() == SearchClause.Comparator.IS_NULL
|| comparator.getModelObject() == SearchClause.Comparator.IS_NOT_NULL) {
value.setModelObject(StringUtils.EMPTY);
value.setEnabled(false);
} else {
value.setEnabled(true);
}
target.add(value);
}
if (type.getModelObject() == SearchClause.Type.RELATIONSHIP) {
property.setEnabled(true);
SearchClause searchClause = new SearchClause();
searchClause.setType(Type.valueOf(type.getDefaultModelObjectAsString()));
searchClause.setComparator(comparator.getModelObject());
SearchClausePanel.this.clause.setObject(searchClause);
target.add(property);
}
}
});
setFieldAccess(searchClause.getType(), property, comparator, value);
return this;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void setFieldAccess(
final Type type,
final AjaxTextFieldPanel property,
final FieldPanel<Comparator> comparator,
final FieldPanel value) {
if (type != null) {
property.setEnabled(true);
comparator.setEnabled(true);
value.setEnabled(true);
switch (type) {
case ATTRIBUTE:
if (!comparator.isEnabled()) {
comparator.setEnabled(true);
comparator.setRequired(true);
}
if (comparator.getModelObject() == SearchClause.Comparator.IS_NULL
|| comparator.getModelObject() == SearchClause.Comparator.IS_NOT_NULL) {
value.setEnabled(false);
value.setModelObject(StringUtils.EMPTY);
}
// reload properties list
properties.detach();
property.setChoices(properties.getObject());
break;
case ROLE_MEMBERSHIP:
value.setEnabled(false);
value.setModelObject(StringUtils.EMPTY);
// reload properties list
properties.detach();
property.setChoices(properties.getObject());
break;
case PRIVILEGE:
value.setEnabled(false);
value.setModelObject(StringUtils.EMPTY);
// reload properties list
properties.detach();
property.setChoices(properties.getObject());
break;
case GROUP_MEMBERSHIP:
value.setEnabled(false);
value.setModelObject(StringUtils.EMPTY);
// reload properties list
properties.detach();
property.setChoices(properties.getObject());
break;
case GROUP_MEMBER:
value.setEnabled(true);
property.setEnabled(false);
property.setModelObject(StringUtils.EMPTY);
break;
case RESOURCE:
value.setEnabled(false);
value.setModelObject(StringUtils.EMPTY);
// reload properties list
properties.detach();
property.setChoices(properties.getObject());
break;
case RELATIONSHIP:
value.setEnabled(true);
value.setModelObject(StringUtils.EMPTY);
property.setEnabled(true);
// reload properties list
properties.detach();
property.setChoices(properties.getObject());
break;
case CUSTOM:
customizer.setFieldAccess(value, property, properties);
break;
default:
break;
}
}
}
private IChoiceRenderer<SearchClause.Comparator> getComparatorRender(final IModel<SearchClause> clause) {
return new IChoiceRenderer<SearchClause.Comparator>() {
private static final long serialVersionUID = -9086043750227867686L;
@Override
public Object getDisplayValue(final SearchClause.Comparator object) {
if (clause == null || clause.getObject() == null || clause.getObject().getType() == null) {
return object.toString();
}
String display;
switch (clause.getObject().getType()) {
case ATTRIBUTE:
switch (object) {
case IS_NULL:
display = "NULL";
break;
case IS_NOT_NULL:
display = "NOT NULL";
break;
case EQUALS:
display = "==";
break;
case NOT_EQUALS:
display = "!=";
break;
case LESS_THAN:
display = "<";
break;
case LESS_OR_EQUALS:
display = "<=";
break;
case GREATER_THAN:
display = ">";
break;
case GREATER_OR_EQUALS:
display = ">=";
break;
default:
display = StringUtils.EMPTY;
}
break;
case GROUP_MEMBERSHIP:
switch (object) {
case EQUALS:
display = "IN";
break;
case NOT_EQUALS:
display = "NOT IN";
break;
default:
display = StringUtils.EMPTY;
}
break;
case GROUP_MEMBER:
switch (object) {
case EQUALS:
display = "WITH";
break;
case NOT_EQUALS:
display = "WITHOUT";
break;
default:
display = StringUtils.EMPTY;
}
break;
case ROLE_MEMBERSHIP:
case PRIVILEGE:
case RESOURCE:
switch (object) {
case EQUALS:
display = "HAS";
break;
case NOT_EQUALS:
display = "HAS NOT";
break;
default:
display = StringUtils.EMPTY;
}
break;
case RELATIONSHIP:
switch (object) {
case IS_NOT_NULL:
display = "EXIST";
break;
case IS_NULL:
display = "NOT EXIST";
break;
case EQUALS:
display = "WITH";
break;
case NOT_EQUALS:
display = "WITHOUT";
break;
default:
display = StringUtils.EMPTY;
}
break;
case CUSTOM:
display = customizer.comparatorDisplayValue(object);
break;
default:
display = object.toString();
}
return display;
}
@Override
public String getIdValue(final SearchClause.Comparator object, final int index) {
return getDisplayValue(object).toString();
}
@Override
public SearchClause.Comparator getObject(
final String id, final IModel<? extends List<? extends SearchClause.Comparator>> choices) {
if (id == null) {
return SearchClause.Comparator.EQUALS;
}
final SearchClause.Comparator comparator;
switch (id) {
case "HAS":
case "IN":
case "WITH":
comparator = SearchClause.Comparator.EQUALS;
break;
case "HAS NOT":
case "NOT IN":
case "WITHOUT":
comparator = SearchClause.Comparator.NOT_EQUALS;
break;
case "NULL":
case "NOT EXIST":
comparator = SearchClause.Comparator.IS_NULL;
break;
case "NOT NULL":
case "EXIST":
comparator = SearchClause.Comparator.IS_NOT_NULL;
break;
case "==":
comparator = SearchClause.Comparator.EQUALS;
break;
case "!=":
comparator = SearchClause.Comparator.NOT_EQUALS;
break;
case "<":
comparator = SearchClause.Comparator.LESS_THAN;
break;
case "<=":
comparator = SearchClause.Comparator.LESS_OR_EQUALS;
break;
case ">":
comparator = SearchClause.Comparator.GREATER_THAN;
break;
case ">=":
comparator = SearchClause.Comparator.GREATER_OR_EQUALS;
break;
default:
// EQUALS to be used as default value
comparator = customizer.comparatorGetObject(id).orElse(SearchClause.Comparator.EQUALS);
break;
}
return comparator;
}
};
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void renderSearchValueField(
final SearchClause searchClause,
final AjaxTextFieldPanel property) {
PlainSchemaTO plainSchemaTO = anames.getObject().get(property.getModelObject());
if (plainSchemaTO == null) {
PlainSchemaTO defaultPlainTO = new PlainSchemaTO();
defaultPlainTO.setType(AttrSchemaType.String);
plainSchemaTO = dnames.getObject().getOrDefault(property.getModelObject(), defaultPlainTO);
}
switch (plainSchemaTO.getType()) {
case Boolean:
value = new AjaxTextFieldPanel(
"value",
"value",
new PropertyModel<>(searchClause, "value"),
true);
((AjaxTextFieldPanel) value).setChoices(Arrays.asList("true", "false"));
break;
case Date:
FastDateFormat fdf = FastDateFormat.getInstance(
plainSchemaTO.getConversionPattern() == null
? SyncopeConstants.DEFAULT_DATE_PATTERN
: plainSchemaTO.getConversionPattern());
value = new AjaxDateTimeFieldPanel(
"value",
"value",
new PropertyModel(searchClause, "value") {
private static final long serialVersionUID = 1177692285167186690L;
@Override
public Object getObject() {
String date = (String) super.getObject();
try {
return date != null ? fdf.parse(date) : null;
} catch (ParseException ex) {
LOG.error("Date parse error {}", date, ex);
}
return null;
}
@Override
public void setObject(final Object object) {
if (object instanceof Date) {
String valueDate = fdf.format(object);
super.setObject(valueDate);
} else {
super.setObject(object);
}
}
}, FastDateFormat.getInstance(SyncopeConstants.DEFAULT_DATE_PATTERN));
break;
case Enum:
value = new AjaxDropDownChoicePanel<>(
"value",
"value",
new PropertyModel(searchClause, "value"),
true);
((AjaxDropDownChoicePanel<String>) value).setChoices(SchemaUtils.getEnumeratedValues(plainSchemaTO));
if (StringUtils.isNotBlank(plainSchemaTO.getEnumerationKeys())) {
Map<String, String> valueMap = SchemaUtils.getEnumeratedKeyValues(plainSchemaTO);
((AjaxDropDownChoicePanel) value).setChoiceRenderer(new IChoiceRenderer<String>() {
private static final long serialVersionUID = -3724971416312135885L;
@Override
public String getDisplayValue(final String value) {
return valueMap.get(value) == null ? value : valueMap.get(value);
}
@Override
public String getIdValue(final String value, final int i) {
return value;
}
@Override
public String getObject(
final String id, final IModel<? extends List<? extends String>> choices) {
return id;
}
});
}
break;
case Long:
value = new AjaxSpinnerFieldPanel.Builder<Long>().enableOnChange().build(
"value",
"Value",
Long.class,
new PropertyModel(searchClause, "value"));
value.add(new AttributeModifier("class", "field value search-spinner"));
break;
case Double:
value = new AjaxSpinnerFieldPanel.Builder<Double>().enableOnChange().step(0.1).build(
"value",
"value",
Double.class,
new PropertyModel(searchClause, "value"));
value.add(new AttributeModifier("class", "field value search-spinner"));
break;
default:
value = new AjaxTextFieldPanel(
"value", "value", new PropertyModel<>(searchClause, "value"), true);
break;
}
value.hideLabel().setOutputMarkupId(true);
value.getField().add(PREVENT_DEFAULT_RETURN);
value.getField().add(new IndicatorAjaxEventBehavior(Constants.ON_KEYDOWN) {
private static final long serialVersionUID = -7133385027739964990L;
@Override
protected void onEvent(final AjaxRequestTarget target) {
target.focusComponent(null);
value.getField().inputChanged();
value.getField().validate();
if (value.getField().isValid()) {
value.getField().valid();
value.getField().updateModel();
}
}
@Override
protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
AJAX_SUBMIT_ON_RETURN.accept(attributes);
}
});
}
@Override
public FieldPanel<SearchClause> clone() {
SearchClausePanel panel = new SearchClausePanel(
getId(), name, null, required, types, customizer, anames, dnames, groupInfo,
roleNames, privilegeNames, resourceNames);
panel.setReadOnly(this.isReadOnly());
panel.setRequired(this.isRequired());
if (searchButton.isEnabled()) {
panel.enableSearch(resultContainer);
}
return panel;
}
public static class SearchEvent implements Serializable {
private static final long serialVersionUID = 2693338614198749301L;
private final AjaxRequestTarget target;
public SearchEvent(final AjaxRequestTarget target) {
this.target = target;
}
public AjaxRequestTarget getTarget() {
return target;
}
}
}