/* * 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.dashboard; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider; import org.apache.wicket.extensions.markup.html.repeater.tree.NestedTree; import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder; import org.apache.wicket.extensions.markup.html.repeater.tree.theme.WindowsTheme; import org.apache.wicket.markup.html.form.ChoiceRenderer; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.markup.html.panel.EmptyPanel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.spring.injection.annot.SpringBean; import ro.nextreports.engine.util.ParameterUtil; import ro.nextreports.server.StorageConstants; import ro.nextreports.server.domain.Chart; import ro.nextreports.server.domain.Entity; import ro.nextreports.server.domain.Report; import ro.nextreports.server.exception.NotFoundException; import ro.nextreports.server.report.ReportConstants; import ro.nextreports.server.report.next.NextUtil; import ro.nextreports.server.service.ReportService; import ro.nextreports.server.service.StorageService; import ro.nextreports.server.util.EntityComparator; import ro.nextreports.server.web.common.form.FormContentPanel; import ro.nextreports.server.web.common.form.FormPanel; import ro.nextreports.server.web.core.tree.EntityTreeProvider; /** * @author Decebal Suiu */ public class AddWidgetPanel extends FormContentPanel { private static final long serialVersionUID = 1L; @SpringBean private StorageService storageService; @SpringBean private ReportService reportService; private WidgetType type; private Entity entity; private Component swapComponent; private ITreeProvider<Entity> treeProvider; private EntityTree tree; private IModel<Entity> selected; public AddWidgetPanel() { super(FormPanel.CONTENT_ID); final EmptyPanel emptyTree = new EmptyPanel("tree"); emptyTree.setOutputMarkupId(true); swapComponent = emptyTree; swapComponent.setOutputMarkupId(true); add(swapComponent); List<WidgetType> types = new ArrayList<WidgetType>(); types.addAll(Arrays.asList(WidgetType.values())); IChoiceRenderer<WidgetType> renderer = new ChoiceRenderer<WidgetType> () { private static final long serialVersionUID = 1L; @Override public Object getDisplayValue(WidgetType object) { return getString(object.toString()); } @Override public String getIdValue(WidgetType object, int index) { return object.toString(); } }; DropDownChoice<WidgetType> typeDropDownChoice = new DropDownChoice<WidgetType>("type", new PropertyModel<WidgetType>(this, "type"), types, renderer); typeDropDownChoice.setOutputMarkupPlaceholderTag(true); add(typeDropDownChoice); typeDropDownChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") { private static final long serialVersionUID = 1L; @Override protected void onUpdate(AjaxRequestTarget target) { if (type == null) { if (tree != null) { swapComponent.replaceWith(emptyTree); swapComponent = emptyTree; tree = null; } } else { tree = createTree(getRootPath()); tree.setOutputMarkupId(true); swapComponent.replaceWith(tree); swapComponent = tree; } target.add(swapComponent); target.add(getFeedbackPanel()); } }); } public boolean isDrillDownable() { if (entity instanceof Chart) { return ((Chart) entity).getDrillDownEntities().size() > 0; } else if (entity instanceof Report) { return ((Report) entity).getDrillDownEntities().size() > 0; } return false; } public boolean isChart() { return WidgetType.CHART.equals(type); } public boolean isTable() { return WidgetType.TABLE.equals(type); } public boolean isAlarm() { return WidgetType.ALARM.equals(type); } public boolean isIndicator() { return WidgetType.INDICATOR.equals(type); } public boolean isDisplay() { return WidgetType.DISPLAY.equals(type); } public boolean isPivot() { return WidgetType.PIVOT.equals(type); } public Entity getEntity() { return entity; } protected EntityTree createTree(String rootPath) { treeProvider = new EntityTreeProvider(rootPath) { private static final long serialVersionUID = 1L; @Override protected boolean acceptEntityAsChild(Entity entity) { if (WidgetType.CHART.equals(type)) { return true; } if ((entity instanceof ro.nextreports.server.domain.Folder) || (entity instanceof Chart)) { return true; } if (entity instanceof Report) { Report report = (Report) entity; boolean isTableReport = WidgetType.TABLE.equals(type) && report.getType().equals(ReportConstants.NEXT) && report.isTableType(); boolean isAlarmReport = WidgetType.ALARM.equals(type) && report.getType().equals(ReportConstants.NEXT) && report.isAlarmType(); boolean isIndicatorReport = WidgetType.INDICATOR.equals(type) && report.getType().equals(ReportConstants.NEXT) && report.isIndicatorType(); boolean isDisplayReport = WidgetType.DISPLAY.equals(type) && report.getType().equals(ReportConstants.NEXT) && report.isDisplayType(); boolean isPivot = WidgetType.PIVOT.equals(type) && report.getType().equals(ReportConstants.NEXT); if (isTableReport || isAlarmReport || isIndicatorReport || isPivot || isDisplayReport) { ro.nextreports.engine.Report nextReport = NextUtil.getNextReport(storageService.getSettings(), report); if (ParameterUtil.allParametersHaveDefaults(ParameterUtil.getUsedNotHiddenParametersMap(nextReport))) { if (isAlarmReport || isIndicatorReport || isDisplayReport || (isTableReport && NextUtil.reportHasHeader(nextReport)) || isPivot) { return true; } } } } return false; } @Override protected List<Entity> getChildren(String id) throws NotFoundException { // sort List<Entity> children = super.getChildren(id); Collections.sort(children, new EntityComparator()); return children; } }; return new EntityTree("tree", treeProvider); } protected boolean isSelected(Entity entity) { IModel<Entity> model = treeProvider.model(entity); try { return (selected != null) && selected.equals(model) && !(selected.getObject() instanceof ro.nextreports.server.domain.Folder); } finally { model.detach(); } } private String getRootPath() { String rootPath; if (WidgetType.CHART.equals(type)) { rootPath = StorageConstants.CHARTS_ROOT; } else { rootPath = StorageConstants.REPORTS_ROOT; } return rootPath; } private void onNodeClicked(Entity entity, AjaxRequestTarget target) { if (!(entity instanceof ro.nextreports.server.domain.Folder)) { this.entity = entity; } else { this.entity = null; } target.add(getFeedbackPanel()); } private class EntityTree extends NestedTree<Entity> { private static final long serialVersionUID = 1L; public EntityTree(String id, ITreeProvider<Entity> provider) { super(id, provider); add(new WindowsTheme()); } @Override protected Component newContentComponent(String id, IModel<Entity> model) { return new Folder<Entity>(id, this, model) { private static final long serialVersionUID = 1L; @Override protected boolean isClickable() { return true; } @Override protected String getOtherStyleClass(Entity t) { if (t instanceof ro.nextreports.server.domain.Folder) { return getClosedStyleClass(); } return super.getOtherStyleClass(t); } @Override protected void onClick(AjaxRequestTarget target) { // I don't want the default behavior (collapse node if it's expanded) // super.onClick(target); Entity entity = getModelObject(); if (tree.getState(entity) == State.COLLAPSED) { tree.expand(entity); } else { tree.updateNode(entity, target); } // refresh the old selected node if (selected != null) { tree.updateNode(selected.getObject(), target); selected.detach(); selected = null; } selected = treeProvider.model(getModelObject()); onNodeClicked(getModelObject(), target); } @Override protected boolean isSelected() { return AddWidgetPanel.this.isSelected(getModelObject()); } @Override protected IModel<?> newLabelModel(IModel<Entity> model) { return Model.of(model.getObject().getName()); } }; } } }