/** * Licensed to the Austrian Association for Software Tool Integration (AASTI) * under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. The AASTI 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.openengsb.ui.admin.edb; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import javax.inject.Inject; import javax.inject.Named; 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.extensions.ajax.markup.html.IndicatingAjaxButton; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.MultiLineLabel; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.IChoiceRenderer; 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.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.openengsb.core.api.model.OpenEngSBModel; import org.openengsb.core.api.model.annotation.OpenEngSBModelId; import org.openengsb.core.api.security.annotation.SecurityAttribute; import org.openengsb.core.api.security.annotation.SecurityAttributes; import org.openengsb.core.ekb.api.QueryInterface; import org.openengsb.labs.delegation.service.ClassProvider; import org.openengsb.ui.admin.basePage.BasePage; import org.ops4j.pax.wicket.api.PaxWicketMountPoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Strings; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; @SecurityAttributes({ @SecurityAttribute(key = "org.openengsb.ui.component", value = "EDB") }) @PaxWicketMountPoint(mountPoint = "edb") public class EdbClient extends BasePage { private static final long serialVersionUID = 9004308842445884996L; public static final String PAGE_NAME_KEY = "edbClient.title"; public static final String PAGE_DESCRIPTION_KEY = "edbClient.description"; private static final Logger LOGGER = LoggerFactory.getLogger(EdbClient.class); static class EkbQuery implements Serializable { private static final long serialVersionUID = 1041945216734701953L; private Class<? extends OpenEngSBModel> model; private String query; public Class<? extends OpenEngSBModel> getModel() { return model; } public void setModel(Class<? extends OpenEngSBModel> model) { this.model = model; } public String getQuery() { return query; } public void setQuery(String query) { this.query = query; } } private final IModel<EkbQuery> queryModel = new Model<EdbClient.EkbQuery>(new EkbQuery()); @Inject @Named("queryInterface") private QueryInterface ekbQueryInterface; @Inject @Named("modelProviders") private List<ClassProvider> modelProviders; private TextField<String> queryField; private IModel<List<? extends OpenEngSBModel>> resultModel; private WebMarkupContainer resultContainer; private FeedbackPanel feedback; private class DomainModelListModel extends LoadableDetachableModel<List<Class<? extends OpenEngSBModel>>> { private static final long serialVersionUID = 608313722757619758L; @SuppressWarnings("unchecked") @Override protected List<Class<? extends OpenEngSBModel>> load() { List<Class<? extends OpenEngSBModel>> result = new ArrayList<Class<? extends OpenEngSBModel>>(); for (ClassProvider p : modelProviders) { for (Class<?> c : p.listClasses()) { if (!OpenEngSBModel.class.isAssignableFrom(c)) { LOGGER.error("Class {} was not correctly woven, so it will not appear in model-dropdown", c.getName()); continue; } result.add((Class<? extends OpenEngSBModel>) c); } } return result; } } public EdbClient() { Form<Object> form = new Form<Object>("form"); final DropDownChoice<Class<? extends OpenEngSBModel>> modelSelector = new DropDownChoice<Class<? extends OpenEngSBModel>>("modelSelector", new Model<Class<? extends OpenEngSBModel>>(), new DomainModelListModel()); modelSelector.add(new AjaxFormComponentUpdatingBehavior("onchange") { private static final long serialVersionUID = -1516333824153580148L; @Override protected void onUpdate(AjaxRequestTarget target) { Class<? extends OpenEngSBModel> convertedInput = modelSelector.getConvertedInput(); queryModel.getObject().setModel(convertedInput); queryField.setEnabled(convertedInput != null); target.add(queryField); } }); modelSelector.setChoiceRenderer(new IChoiceRenderer<Class<?>>() { private static final long serialVersionUID = 805430071751617166L; @Override public Object getDisplayValue(Class<?> object) { return object.getSimpleName(); } @Override public String getIdValue(Class<?> object, int index) { return object.getSimpleName(); } }); form.add(modelSelector); queryField = new AutoCompleteTextField<String>("query") { private static final long serialVersionUID = 5028249986331789802L; @Override protected Iterator<String> getChoices(final String input) { Class<? extends OpenEngSBModel> model = queryModel.getObject().getModel(); BeanInfo beanInfo; try { beanInfo = Introspector.getBeanInfo(model); } catch (IntrospectionException e) { LOGGER.warn("error introspecting {}. Auto-completing won't work." + model); List<String> emptyList = Collections.emptyList(); return emptyList.iterator(); } List<String> allKeys = Lists.transform(Arrays.asList(beanInfo.getPropertyDescriptors()), new Function<PropertyDescriptor, String>() { @Override public String apply(PropertyDescriptor input) { return input.getName() + ":"; } }); if (Strings.isNullOrEmpty(input)) { return allKeys.iterator(); } return Iterators.filter(allKeys.iterator(), new Predicate<String>() { @Override public boolean apply(String item) { return item.contains(input); } }); } }; queryField.setEnabled(false); queryField.setOutputMarkupId(true); queryField.setModel(new PropertyModel<String>(queryModel.getObject(), "query")); form.add(queryField); form.add(new IndicatingAjaxButton("submit") { private static final long serialVersionUID = -5425144434508998591L; @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { EkbQuery query = queryModel.getObject(); List<? extends OpenEngSBModel> models; try { models = ekbQueryInterface.queryByString(query.getModel(), query.getQuery()); resultModel.setObject(models); info(String.format("Found %s results", models.size())); } catch (Exception e) { error(String.format("Error when querying for models %s (%s)", e.getMessage(), e.getClass().getName())); } target.add(feedback); target.add(resultContainer); } @Override protected void onError(AjaxRequestTarget target, Form<?> form) { } }); add(form); List<? extends OpenEngSBModel> emptyList = Collections.emptyList(); resultModel = Model.ofList(emptyList); resultContainer = new WebMarkupContainer("result"); resultContainer.setOutputMarkupId(true); add(resultContainer); resultContainer.add(new ListView<OpenEngSBModel>("list", resultModel) { private static final long serialVersionUID = 5459114215962851286L; @Override protected void populateItem(ListItem<OpenEngSBModel> item) { String idProperty = "id"; Class<? extends OpenEngSBModel> modelClass = queryModel.getObject().getModel(); for (Field m : modelClass.getDeclaredFields()) { if (m.getAnnotation(OpenEngSBModelId.class) != null) { idProperty = m.getName(); break; } } AjaxLink<String> historyLink = new AjaxLink<String>("id", new PropertyModel<String>(item.getModelObject(), idProperty)) { private static final long serialVersionUID = -6539033599615376277L; @Override public void onClick(AjaxRequestTarget target) { this.setResponsePage(new EdbHistoryPanel(getModel().getObject())); } }; historyLink.add(new Label("text", new PropertyModel<String>(item.getModelObject(), idProperty))); item.add(historyLink); MultiLineLabel multiLineLabel = new MultiLineLabel("entries", item.getModelObject().toOpenEngSBModelEntries().toString()); item.add(multiLineLabel); } }); feedback = new FeedbackPanel("feedback"); feedback.setOutputMarkupId(true); form.add(feedback); } }