org.apache.wicket.extensions.markup.html.repeater.tree.TableTree.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.extensions.markup.html.repeater.tree.TableTree.java

Source

/*
 * 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.wicket.extensions.markup.html.repeater.tree;

import java.util.List;
import java.util.Optional;
import java.util.Set;

import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.tree.table.ITreeColumn;
import org.apache.wicket.extensions.markup.html.repeater.tree.table.ITreeDataProvider;
import org.apache.wicket.extensions.markup.html.repeater.tree.table.NodeModel;
import org.apache.wicket.extensions.markup.html.repeater.tree.table.TreeDataProvider;
import org.apache.wicket.markup.repeater.IItemReuseStrategy;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RefreshingView;
import org.apache.wicket.markup.repeater.data.IDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;

/**
 * A tree with tabular markup.
 * 
 * @author svenmeier
 * 
 * @param <T>
 *            The model object type
 * @param <S>
 *            the type of the sort property
 */
public abstract class TableTree<T, S> extends AbstractTree<T> {
    private static final long serialVersionUID = 1L;

    private final DataTable<T, S> table;

    /**
     * Constructor
     * 
     * @param id
     *            component id
     * @param columns
     *            list of IColumn objects
     * @param dataProvider
     *            imodel for data provider
     * @param rowsPerPage
     *            number of rows per page
     */
    public TableTree(final String id, final List<? extends IColumn<T, S>> columns,
            final ITreeProvider<T> dataProvider, final long rowsPerPage) {
        this(id, columns, dataProvider, rowsPerPage, null);
    }

    /**
     * Constructor
     * 
     * @param id
     *            component id
     * @param columns
     *            list of IColumn objects
     * @param provider
     *            provider of the tree
     * @param rowsPerPage
     *            number of rows per page
     * @param state
     *            the expansion state
     */
    public TableTree(final String id, final List<? extends IColumn<T, S>> columns, final ITreeProvider<T> provider,
            final long rowsPerPage, IModel<? extends Set<T>> state) {
        super(id, provider, state);

        Args.notEmpty(columns, "columns");
        for (IColumn<T, S> column : columns) {
            if (column instanceof ITreeColumn<?, ?>) {
                ((ITreeColumn<T, S>) column).setTree(this);
            }
        }

        this.table = newDataTable("table", columns, newDataProvider(provider), rowsPerPage);
        add(table);

        // see #updateBranch(Object, AjaxRequestTarget)
        setOutputMarkupId(true);
    }

    /**
     * Factory method for the wrapped {@link DataTable}.
     * 
     * Note: If overwritten, the DataTable's row items have to output their markupId, or
     * {@link #updateNode(Object, Optional)} will fail.
     * 
     * @param id
     * @param columns
     * @param dataProvider
     * @param rowsPerPage
     * @return nested data table
     */
    protected DataTable<T, S> newDataTable(String id, List<? extends IColumn<T, S>> columns,
            IDataProvider<T> dataProvider, long rowsPerPage) {
        return new DataTable<T, S>(id, columns, dataProvider, rowsPerPage) {
            private static final long serialVersionUID = 1L;

            @Override
            protected Item<T> newRowItem(String id, int index, IModel<T> model) {
                Item<T> item = TableTree.this.newRowItem(id, index, model);

                // see #update(Node);
                item.setOutputMarkupId(true);

                return item;
            }
        };
    }

    /**
     * Get the nested table.
     * 
     * @return the nested table
     */
    public DataTable<T, S> getTable() {
        return table;
    }

    /**
     * Sets the item reuse strategy. This strategy controls the creation of {@link Item}s.
     * 
     * @see RefreshingView#setItemReuseStrategy(IItemReuseStrategy)
     * @see IItemReuseStrategy
     * 
     * @param strategy
     *            item reuse strategy
     * @return this for chaining
     */
    @Override
    public final TableTree<T, S> setItemReuseStrategy(final IItemReuseStrategy strategy) {
        table.setItemReuseStrategy(strategy);

        super.setItemReuseStrategy(strategy);

        return this;
    }

    /**
     * For updating of a single branch the whole table is added to the ART.
     */
    @Override
    public void updateBranch(T node, IPartialPageRequestHandler target) {
        // TableTree always outputs markupId
        target.add(this);
    }

    /**
     * For an update of a node the complete row item is added to the ART.
     */
    @Override
    public void updateNode(T t, IPartialPageRequestHandler target) {
        final IModel<T> model = getProvider().model(t);
        table.getBody().visitChildren(Item.class, new IVisitor<Item<T>, Void>() {
            @Override
            public void component(Item<T> item, IVisit<Void> visit) {
                NodeModel<T> nodeModel = (NodeModel<T>) item.getModel();

                if (model.equals(nodeModel.getWrappedModel())) {
                    // row items are configured to output their markupId
                    target.add(item);
                    visit.stop();
                    return;
                }
                visit.dontGoDeeper();
            }
        });
        model.detach();
    }

    /**
     * Hook method to create an {@link ITreeDataProvider}.
     * 
     * @param provider
     *            the tree provider
     * @return the data provider
     */
    protected ITreeDataProvider<T> newDataProvider(ITreeProvider<T> provider) {
        return new TreeDataProvider<T>(provider) {
            private static final long serialVersionUID = 1L;

            @Override
            protected boolean iterateChildren(T object) {
                return TableTree.this.getState(object) == State.EXPANDED;
            }
        };
    }

    /**
     * Create a row item for the nested {@link DataTable}.
     * 
     * @param id
     *            component id
     * @param index
     *            index of row
     * @param model
     *            model for row
     * @return row item
     */
    protected Item<T> newRowItem(String id, int index, IModel<T> model) {
        Item<T> item = new Item<>(id, index, model);

        return item;
    }
}