Java tutorial
/* * 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 ro.nextreports.server.web.report.jasper; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.wicket.Component; import org.apache.wicket.RestartResponseException; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.extensions.markup.html.form.DateTextField; import org.apache.wicket.extensions.markup.html.form.palette.Palette; import org.apache.wicket.extensions.markup.html.form.palette.component.Recorder; import org.apache.wicket.extensions.yui.calendar.DatePicker; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.panel.EmptyPanel; import org.apache.wicket.markup.html.panel.Panel; 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.apache.wicket.spring.injection.annot.SpringBean; import ro.nextreports.server.domain.DataSource; import ro.nextreports.server.domain.Report; import ro.nextreports.server.domain.ReportRuntimeParameterModel; import ro.nextreports.server.report.ExternalParameter; import ro.nextreports.server.report.ReportConstants; import ro.nextreports.server.report.jasper.JasperParameter; import ro.nextreports.server.report.jasper.JasperParameterSource; import ro.nextreports.server.report.jasper.JasperReportsUtil; import ro.nextreports.server.report.jasper.JasperRuntimeParameterModel; import ro.nextreports.server.service.DataSourceService; import ro.nextreports.server.service.ReportService; import ro.nextreports.server.service.StorageService; import ro.nextreports.server.util.ServerUtil; import ro.nextreports.server.web.common.misc.ExtendedPalette; import ro.nextreports.server.web.core.MessageErrorPage; import ro.nextreports.server.web.report.ManualListPanel; import ro.nextreports.server.web.report.ReportRuntimeModel; import ro.nextreports.engine.queryexec.IdName; import ro.nextreports.engine.queryexec.QueryParameter; public class JasperRuntimePanel extends Panel { public static final String USER_PARAM = "__USER__"; private Report report; @SpringBean private ReportService reportService; @SpringBean private StorageService storageService; @SpringBean private DataSourceService dataSourceService; private static List<String> typeList; private Map<String, Serializable> paramMap; private Map<String, QueryParameter> convertMap; private List<QueryParameter> convertList; private Map<QueryParameter, Component> paramComponentsMap; private ReportRuntimeModel runtimeModel; // all dependent parameters that must be initialized after completing default values private transient List<QueryParameter> depParameters = new ArrayList<QueryParameter>(); public JasperRuntimePanel(String id, final Report report, ReportRuntimeModel runtimeModel) { super(id); typeList = reportService.getSupportedOutputs(report); this.report = report; this.runtimeModel = runtimeModel; if (runtimeModel.getExportType() == null) { runtimeModel.setExportType(ReportConstants.HTML_FORMAT); } try { paramMap = reportService.getReportUserParameters(report, new ArrayList<ExternalParameter>()); convertMap = convert(report.getDataSource(), paramMap); convertList = new LinkedList<QueryParameter>(convertMap.values()); paramComponentsMap = new HashMap<QueryParameter, Component>(); } catch (Exception e) { //@todo alert e.printStackTrace(); getSession().error(e.getMessage()); throw new RestartResponseException( new MessageErrorPage(e.getMessage() + " : Verify the parameters sources.")); } addComponents(); } @SuppressWarnings("unchecked") private Map<String, QueryParameter> convert(DataSource ds, Map<String, Serializable> params) throws Exception { Map<String, QueryParameter> result = new LinkedHashMap<String, QueryParameter>(); Set s = params.entrySet(); for (Object value : s) { Map.Entry<String, Serializable> me = (Map.Entry<String, Serializable>) value; JasperParameter jp = (JasperParameter) me.getValue(); String className = JasperReportsUtil.getValueClassName(storageService, ds, jp); QueryParameter qp = new QueryParameter(jp.getName(), jp.getDescription(), className); //System.out.println(">>> Source = " + jp.getSelect()); qp.setSource(jp.getSelect()); qp.setMandatory(jp.isMandatory()); qp.setRuntimeName(jp.getShortName()); if (JasperParameterSource.LIST.equals(jp.getType())) { qp.setSelection(QueryParameter.MULTIPLE_SELECTION); qp.setManualSource(true); } else if (JasperParameterSource.COMBO.equals(jp.getType())) { qp.setSelection(QueryParameter.SINGLE_SELECTION); qp.setManualSource(true); } else { // SINGLE qp.setSelection(QueryParameter.SINGLE_SELECTION); qp.setManualSource(false); } //System.out.println("Convert qp=" + qp.getName() + " " + qp.getSelection() + " " + qp.getValueClass()); result.put(me.getKey(), qp); } return result; } // populate dependent parameters after all items (createItem) have been created! protected void onBeforeRender() { super.onBeforeRender(); if (runtimeModel.isEdit()) { for (QueryParameter parameter : convertMap.values()) { populateDependentParameters(parameter, null); } } } @SuppressWarnings("unchecked") private void addComponents() { // initialize model for (QueryParameter parameter : convertList) { if (!runtimeModel.isEdit() || (USER_PARAM.equals(parameter.getName()))) { JasperRuntimeParameterModel jasperRuntimeModel = createRuntimeModel(parameter); runtimeModel.getParameters().put(parameter.getName(), jasperRuntimeModel); } } if (!runtimeModel.isEdit()) { // if some parameters initialized have default values, their dependent parameters // have to be initialized too for (QueryParameter qp : depParameters) { populateDependentParameters(qp, null); } } ListView<QueryParameter> listView = new ListView<QueryParameter>("params", new ArrayList<QueryParameter>(convertMap.values())) { @Override protected void populateItem(ListItem<QueryParameter> item) { createItem(item); } }; listView.setReuseItems(true); add(listView); add(new DropDownChoice("exportType", new PropertyModel(runtimeModel, "exportType"), typeList) .setRequired(true)); } @SuppressWarnings("unchecked") private void createItem(ListItem<QueryParameter> item) { WebMarkupContainer paletteContainer = new WebMarkupContainer("paletteContainer"); final QueryParameter parameter = item.getModelObject(); IModel generalModel = new PropertyModel(runtimeModel.getParameters(), parameter.getName() + ".rawValue"); IModel listModel = new PropertyModel(runtimeModel.getParameters(), parameter.getName() + ".valueList"); AjaxFormComponentUpdatingBehavior ajaxUpdate = createAjax(parameter); final TextField textField = new TextField("txtValue", generalModel); textField.setVisible(false); try { textField.setType(Class.forName(parameter.getValueClassName())); } catch (ClassNotFoundException e) { e.printStackTrace(); error(e.getMessage()); } final DateTextField txtDate = new DateTextField("txtDate", generalModel) { @Override public IModel<String> getLabel() { return new Model<String>(getParameterName(parameter)); } }; txtDate.add(new DatePicker() { @Override protected boolean enableMonthYearSelection() { return true; } }); txtDate.setVisible(false); final CheckBox chkBox = new CheckBox("chkBox", generalModel); chkBox.setVisible(false); DropDownChoice downChoice = new DropDownChoice("cmbValue", generalModel, new ArrayList<String>()); downChoice.setVisible(false); Component currentComponent; if (parameter.getSelection().equalsIgnoreCase(QueryParameter.SINGLE_SELECTION)) { if (parameter.getSource() != null && parameter.getSource().trim().length() > 0) { // combo downChoice = new DropDownChoice("cmbValue", generalModel, new LoadableDetachableModel() { @Override protected Object load() { return runtimeModel.getParameters().get(parameter.getName()).getValues(); } }); if (parameter.isMandatory()) { downChoice.setRequired(true); } downChoice.setLabel(new Model<String>(getParameterName(parameter))); downChoice.setVisible(true); currentComponent = downChoice; } else { // not combo if (parameter.getValueClassName().contains("Date")) { if (parameter.isMandatory()) { txtDate.setRequired(true); } txtDate.setVisible(true); currentComponent = txtDate; } else if (parameter.getValueClassName().contains("Boolean")) { if (parameter.isMandatory()) { chkBox.setRequired(true); } chkBox.setLabel(new Model<String>(getParameterName(parameter))); chkBox.setVisible(true); currentComponent = chkBox; } else { if (parameter.isMandatory()) { textField.setRequired(true); } textField.setLabel(new Model<String>(getParameterName(parameter))); textField.setVisible(true); currentComponent = textField; } } paletteContainer.add(new EmptyPanel("palette")); } else { if (parameter.getSource() != null && parameter.getSource().trim().length() > 0) { Palette palette = createPalette(parameter, listModel, ajaxUpdate); paletteContainer.add(palette.setOutputMarkupId(true)); currentComponent = palette; } else { ManualListPanel list = new ManualListPanel(parameter, listModel, 10, ajaxUpdate); paletteContainer.add(list.setOutputMarkupId(true)); currentComponent = list; } } if (USER_PARAM.equals(parameter.getName())) { currentComponent.setEnabled(false); } paramComponentsMap.put(parameter, currentComponent); // if this parameter has dependent parameters // we must update values for those using an ajax update // for Palette this is done in its class if (getChildDependentParameters(parameter).size() > 0) { if (!(currentComponent instanceof Palette)) { currentComponent.add(ajaxUpdate); } } String name = getDisplayableParameterName(parameter); Label lbl = new Label("name", name); lbl.setEscapeModelStrings(false); item.add(lbl); item.add(txtDate.setOutputMarkupId(true)); item.add(downChoice.setOutputMarkupId(true)); item.add(paletteContainer.setOutputMarkupId(true)); item.add(textField.setOutputMarkupId(true)); item.add(chkBox.setOutputMarkupId(true)); } private JasperRuntimeParameterModel createRuntimeModel(QueryParameter parameter) { boolean isMultipleSelection = parameter.getSelection().equalsIgnoreCase(QueryParameter.MULTIPLE_SELECTION); JasperRuntimeParameterModel runtimeModel = new JasperRuntimeParameterModel(parameter.getName(), getParameterName(parameter), isMultipleSelection); runtimeModel.setMandatory(parameter.isMandatory()); List<IdName> values = new ArrayList<IdName>(); // set in the model only the values for parameters which are not dependent //System.out.println("*** param="+parameter.getName() + " source="+parameter.getSource()+ " dep="+parameter.isDependent() + " selection="+parameter.getSelection()); if ((parameter.getSource() != null) && (parameter.getSource().trim().length() > 0) && !parameter.isDependent()) { if (QueryParameter.SINGLE_SELECTION.equals(parameter.getSelection())) { runtimeModel.setCombo(true); } try { values = dataSourceService.getParameterValues(report.getDataSource(), parameter); //System.out.println("values="+values); } catch (Exception e) { //System.out.println(e.getMessage()); info(e.getMessage()); } } runtimeModel.setParameterValues(values); boolean populateDependent = false; if (USER_PARAM.equals(parameter.getName())) { runtimeModel.setRawValue(ServerUtil.getUsernameWithoutRealm()); populateDependent = true; } // mark the dependent parameters that must be populated after initilize the default values if (populateDependent) { this.runtimeModel.getParameters().put(parameter.getName(), runtimeModel); depParameters.add(parameter); } return runtimeModel; } private AjaxFormComponentUpdatingBehavior createAjax(final QueryParameter parameter) { return new AjaxFormComponentUpdatingBehavior("onchange") { @Override protected void onUpdate(AjaxRequestTarget target) { populateDependentParameters(parameter, target); } }; } private void populateDependentParameters(QueryParameter parameter, AjaxRequestTarget target) { Map<String, QueryParameter> childParams = getChildDependentParameters(parameter); //System.out.println("??? param=" + parameter + " childSize="+ childParams.size()); // update model parameter values for every child parameter for (QueryParameter childParam : childParams.values()) { if (!convertList.contains(childParam)) { continue; } Component childComponent = paramComponentsMap.get(childParam); List<IdName> values = new ArrayList<IdName>(); boolean allParentsHaveValues = true; Map<String, QueryParameter> allParentParams = getParentDependentParameters(childParam); for (QueryParameter parentParam : allParentParams.values()) { if (runtimeModel.getParameters().get(parentParam.getName()).getProcessingValue() == null) { allParentsHaveValues = false; break; } } if ((childParam.getSource() != null) && (childParam.getSource().trim().length() > 0) && allParentsHaveValues) { try { Map<String, Serializable> allParameterValues = new HashMap<String, Serializable>(); for (String name : runtimeModel.getParameters().keySet()) { ReportRuntimeParameterModel model = runtimeModel.getParameters().get(name); allParameterValues.put(model.getName(), (Serializable) model.getProcessingValue()); } values = dataSourceService.getDependentParameterValues(report.getDataSource(), childParam, convertMap, allParameterValues); } catch (Exception e) { //System.out.println(e.getMessage()); info(e.getMessage()); } } JasperRuntimeParameterModel parameterModel = (JasperRuntimeParameterModel) runtimeModel.getParameters() .get(childParam.getName()); if (values != null && values.size() > 0) { parameterModel.setParameterValues(values); } else { parameterModel.setParameterValues(new ArrayList<IdName>()); } if (target != null) { target.add(childComponent); } } } @SuppressWarnings("unchecked") private Palette createPalette(final QueryParameter parameter, IModel listModel, final AjaxFormComponentUpdatingBehavior ajaxUpdate) { return new ExtendedPalette("palette", listModel, new LoadableDetachableModel() { @Override protected Object load() { if (runtimeModel.getParameters().get(parameter.getName()).getValues().size() > 0) { return runtimeModel.getParameters().get(parameter.getName()).getValues(); } else { return new ArrayList<IdName>(); } } }, new IChoiceRenderer() { public Object getDisplayValue(Object object) { IdName value = (IdName) object; return (value.getName() == null) ? value.getId() : value.getName(); } public String getIdValue(Object object, int index) { if (object == null) { return ""; } if (!(object instanceof IdName)) { return object.toString(); } IdName value = (IdName) object; if (value.getId() == null) { return Integer.toString(index); } Object returnValue = value.getId(); if (returnValue == null) { return ""; } // IMPORTANT : if values start or end with space , on submit first rawValue will be ignored! // so we assure that the id never starts or ends with space! // // replace comma with other character (otherwise values with comma will be interpreted as two // values and no selection will be done for them) return "@" + returnValue.toString().replace(",", "-") + "@"; } }, 10, false, true) { @Override protected Recorder newRecorderComponent() { Recorder recorder = super.newRecorderComponent(); if (parameter.isMandatory()) { recorder.setLabel(new Model<String>(getParameterName(parameter))); recorder.setRequired(true); } if (getChildDependentParameters(parameter).size() > 0) { recorder.add(ajaxUpdate); } return recorder; } }; } private String getDisplayableParameterName(QueryParameter parameter) { String name = getParameterName(parameter); if (parameter.isMandatory()) { name += " <em>*</em>"; } return name; } private String getParameterName(QueryParameter parameter) { String name = parameter.getRuntimeName(); if ((name == null) || name.trim().equals("")) { name = parameter.getName(); } return name; } private QueryParameter getParameter(String paramName) { return convertMap.get(paramName); } private Map<String, QueryParameter> getChildDependentParameters(QueryParameter p) { Map<String, QueryParameter> result = new LinkedHashMap<String, QueryParameter>(); List<QueryParameter> params = getParameters(); for (QueryParameter param : params) { if (!param.equals(p) && (param.getSource() != null)) { //System.out.println("---> param " + param.getName() + " : source=" + param.getSource()); if (param.isDependent()) { List<String> names = param.getDependentParameterNames(); if (names.contains(p.getName())) { result.put(param.getName(), param); } } } } return result; } private Map<String, QueryParameter> getParentDependentParameters(QueryParameter p) { List<String> names = p.getDependentParameterNames(); Map<String, QueryParameter> result = new LinkedHashMap<String, QueryParameter>(); for (String name : names) { result.put(name, getParameter(name)); } return result; } private List<QueryParameter> getParameters() { return new LinkedList<QueryParameter>(convertMap.values()); } }