/* * 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.isis.viewer.wicket.ui.components.collectioncontents.summary; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Collections; import java.util.List; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.list.AbstractItem; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.Model; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; import org.apache.isis.core.metamodel.spec.ObjectAdapterUtils; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.spec.feature.Contributed; import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel; import org.apache.isis.viewer.wicket.ui.components.collection.count.CollectionCountProvider; import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract; import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel; /** * {@link PanelAbstract Panel} that represents a {@link EntityCollectionModel * collection of entity}s rendered using as a table of summary values with a * chart alongside. */ public class CollectionContentsAsSummary extends PanelAbstract<EntityCollectionModel> implements CollectionCountProvider { private static final String ID_MAX = "max"; private static final String ID_MIN = "min"; private static final String ID_AVG = "avg"; private static final String ID_SUM = "sum"; private static final String ID_PROPERTY_NAME = "propertyName"; private static final String ID_REPEATING_SUMMARY = "repeatingSummary"; private static final long serialVersionUID = 1L; private static final String ID_FEEDBACK = "feedback"; public CollectionContentsAsSummary(final String id, final EntityCollectionModel model) { super(id, model); buildGui(); } private void buildGui() { final EntityCollectionModel model = getModel(); final ObjectSpecification elementSpec = model.getTypeOfSpecification(); final NotificationPanel feedback = new NotificationPanel(ID_FEEDBACK); feedback.setOutputMarkupId(true); addOrReplace(feedback); List<ObjectAssociation> numberAssociations = elementSpec.getAssociations(Contributed.EXCLUDED, CollectionContentsAsSummaryFactory.OF_TYPE_BIGDECIMAL); RepeatingView repeating = new RepeatingView(ID_REPEATING_SUMMARY); addOrReplace(repeating); for (ObjectAssociation numberAssociation : numberAssociations) { AbstractItem item = new AbstractItem(repeating.newChildId()); repeating.add(item); String propertyName = numberAssociation.getName(); item.add(new Label(ID_PROPERTY_NAME, new Model<String>(propertyName))); List<ObjectAdapter> adapters = model.getObject(); Summary summary = new Summary(propertyName, adapters, numberAssociation); addItem(item, ID_SUM, summary.getTotal()); addItem(item, ID_AVG, summary.getAverage()); addItem(item, ID_MIN, summary.getMin()); addItem(item, ID_MAX, summary.getMax()); } } public static class Summary { private BigDecimal sum = BigDecimal.ZERO; private BigDecimal min = null; private BigDecimal max = null; private final List<String> titles = Lists.newArrayList(); private final List<BigDecimal> values = Lists.newArrayList(); private BigDecimal average; private String propertyName; public Summary(List<ObjectAdapter> adapters, ObjectAssociation numberAssociation) { this(null, adapters, numberAssociation); } public Summary(String propertyName, List<ObjectAdapter> adapters, ObjectAssociation numberAssociation) { this.propertyName = propertyName; int nonNullCount = 0; for (ObjectAdapter objectAdapter : adapters) { titles.add(objectAdapter.titleString(null)); final ObjectAdapter valueAdapter = numberAssociation.get(objectAdapter, InteractionInitiatedBy.USER); if (valueAdapter == null) { values.add(null); continue; } final Object valueObj = ObjectAdapterUtils.unwrapObject(valueAdapter); if (valueObj == null) { values.add(null); continue; } nonNullCount++; BigDecimal value = (BigDecimal) valueObj; sum = sum.add(value); min = min != null && min.compareTo(value) < 0 ? min : value; max = max != null && max.compareTo(value) > 0 ? max : value; values.add(value); } average = nonNullCount != 0 ? sum.divide(BigDecimal.valueOf(nonNullCount), 2, RoundingMode.HALF_UP) : null; } public String getPropertyName() { return propertyName; } public BigDecimal getTotal() { return sum; } public BigDecimal getAverage() { return average; } public BigDecimal getMax() { return max; } public BigDecimal getMin() { return min; } public List<String> getTitles() { return Collections.unmodifiableList(titles); } public List<BigDecimal> getValues() { return Collections.unmodifiableList(values); } public List<Number> getValuesAsNumbers() { return asNumbers(getValues()); } private static List<Number> asNumbers(List<BigDecimal> values) { return Lists.newArrayList(Iterables.transform(values, BIGDECIMAL_TO_NUMBER)); } private static final com.google.common.base.Function<BigDecimal, Number> BIGDECIMAL_TO_NUMBER = new com.google.common.base.Function<BigDecimal, Number>(){ public Number apply(BigDecimal value) { return value; } }; } private void addItem(AbstractItem item, String id, BigDecimal amt) { TextField<String> textField = new TextField<String>(id, new Model<String>(format(amt))); item.add(textField); } private String format(BigDecimal amt) { return amt != null ? amt.setScale(2, RoundingMode.HALF_UP).toPlainString() : ""; } @Override protected void onModelChanged() { buildGui(); } @Override public Integer getCount() { final EntityCollectionModel model = getModel(); return model.getCount(); } }