Changeset 6678


Ignore:
Timestamp:
10/13/15 15:07:57 (9 years ago)
Author:
Twan Goosen
Message:

"Show all" link for collections with more than 50 children
Refs #805

Location:
vlo/branches/vlo-3.3/vlo-web-app/src/main/java/eu/clarin/cmdi/vlo/wicket
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • vlo/branches/vlo-3.3/vlo-web-app/src/main/java/eu/clarin/cmdi/vlo/wicket/panels/record/HierarchyPanel.html

    r6353 r6678  
    3838                <a wicket:id="showAll">Show all... (<span wicket:id="itemCount">999</span>)</a>
    3939            </div>
    40             <div id="tree" wicket:id="tree">[TREE]</div>
     40            <div wicket:id="treeContainer">
     41                <div id="tree" wicket:id="tree">[TREE]</div>
     42            </div>
    4143        </wicket:panel>
    4244    </body>
  • vlo/branches/vlo-3.3/vlo-web-app/src/main/java/eu/clarin/cmdi/vlo/wicket/panels/record/HierarchyPanel.java

    r6362 r6678  
    2121import eu.clarin.cmdi.vlo.FacetConstants;
    2222import eu.clarin.cmdi.vlo.service.solr.SolrDocumentService;
     23import eu.clarin.cmdi.vlo.wicket.components.AjaxFallbackLinkLabel;
    2324import eu.clarin.cmdi.vlo.wicket.components.IndicatingNestedTree;
    2425import eu.clarin.cmdi.vlo.wicket.components.NamedRecordPageLink;
    2526import eu.clarin.cmdi.vlo.wicket.model.SolrDocumentModel;
     27import java.io.Serializable;
    2628import java.util.Collection;
    2729import java.util.Collections;
    2830import java.util.Iterator;
     31import java.util.Objects;
    2932import org.apache.solr.common.SolrDocument;
    3033import org.apache.wicket.Component;
     34import org.apache.wicket.MarkupContainer;
    3135import org.apache.wicket.ajax.AjaxRequestTarget;
    3236import org.apache.wicket.behavior.AttributeAppender;
     
    5862     */
    5963    public static final int INITIAL_PARENTS_SHOWN = 5;
     64    public static final int INITIAL_CHILRDEN_SHOWN = 50;
    6065
    6166    @SpringBean
     
    6368
    6469    private final IDataProvider<SolrDocument> parentsProvider;
    65     private final AbstractTree<SolrDocument> tree;
     70    private final MarkupContainer treeContainer;
     71    private final AbstractTree<ModelWrapper<SolrDocument>> tree;
    6672    private final IModel<SolrDocument> pageDocumentModel;
    6773
     
    7581
    7682        tree = createTree("tree");
    77         add(tree);
     83
     84        treeContainer = new WebMarkupContainer("treeContainer");
     85        treeContainer.setOutputMarkupId(true);
     86        treeContainer.add(tree);
     87        add(treeContainer);
    7888
    7989        setOutputMarkupId(true);
     
    97107                        // tree root up one level, expand root for traceability by user
    98108                        HierarchyPanel.this.setModel(item.getModel());
    99                         tree.expand(item.getModelObject());
     109                        tree.expand(new ModelWrapper<>(item.getModel()));
    100110                        if (target != null) {
    101111                            target.add(HierarchyPanel.this);
     
    103113                    }
    104114                });
    105                
     115
    106116                item.add(new Behavior() {
    107117
     
    148158    }
    149159
    150     private AbstractTree<SolrDocument> createTree(String id) {
    151         final AbstractTree<SolrDocument> result = new IndicatingNestedTree<SolrDocument>(id, new HierarchyTreeProvider()) {
    152 
    153             @Override
    154             protected Component newContentComponent(String id, final IModel<SolrDocument> node) {
    155                 return new NamedRecordPageLink(id, node) {
    156 
    157                     @Override
    158                     protected void onConfigure() {
    159                         setEnabled(!node.equals(pageDocumentModel));
    160                     }
    161                 };
     160    private AbstractTree createTree(String id) {
     161        final HierarchyTreeProvider treeProvider = new HierarchyTreeProvider();
     162        final AbstractTree<ModelWrapper<SolrDocument>> result = new IndicatingNestedTree<ModelWrapper<SolrDocument>>(id, treeProvider) {
     163
     164            @Override
     165            protected Component newContentComponent(String id, final IModel<ModelWrapper<SolrDocument>> node) {
     166                if (node.getObject().isLimit()) {
     167                    return new AjaxFallbackLinkLabel(id, node, Model.of("Show all... (" + node.getObject().getCount() + ")")) {
     168
     169                        @Override
     170                        public void onClick(AjaxRequestTarget target) {
     171                            treeProvider.setChildrenShown(null);
     172                            target.add(treeContainer);
     173                        }
     174
     175                    };
     176                } else {
     177                    return new NamedRecordPageLink(id, node.getObject().getModel()) {
     178
     179                        @Override
     180                        protected void onConfigure() {
     181                            setEnabled(!node.equals(pageDocumentModel));
     182                        }
     183                    };
     184                }
    162185            }
    163186
     
    184207    }
    185208
    186     private class HierarchyTreeProvider extends SortableTreeProvider<SolrDocument, Object> {
    187 
    188         @Override
    189         public Iterator<? extends SolrDocument> getRoots() {
    190             return Iterators.singletonIterator(HierarchyPanel.this.getModel().getObject());
    191         }
    192 
    193         @Override
    194         public boolean hasChildren(SolrDocument node) {
    195             Object partCount = node.getFieldValue(FacetConstants.FIELD_HAS_PART_COUNT);
    196             return (partCount instanceof Number) && ((Number) partCount).intValue() > 0;
    197         }
    198 
    199         @Override
    200         public Iterator<? extends SolrDocument> getChildren(SolrDocument node) {
    201             final Collection<Object> parts = node.getFieldValues(FacetConstants.FIELD_HAS_PART);
    202             return Iterators.transform(parts.iterator(), new Function<Object, SolrDocument>() {
    203 
    204                 @Override
    205                 public SolrDocument apply(Object childId) {
    206                     return documentService.getDocument(childId.toString());
    207                 }
    208             });
    209         }
    210 
    211         @Override
    212         public IModel<SolrDocument> model(SolrDocument object) {
    213             return new SolrDocumentModel(object);
     209    private class HierarchyTreeProvider extends SortableTreeProvider<ModelWrapper<SolrDocument>, Object> {
     210
     211        private Integer childrenShown = INITIAL_CHILRDEN_SHOWN;
     212
     213        public void setChildrenShown(Integer childrenShown) {
     214            this.childrenShown = childrenShown;
     215        }
     216
     217        @Override
     218        public Iterator<? extends ModelWrapper<SolrDocument>> getRoots() {
     219            return Iterators.singletonIterator(
     220                    new ModelWrapper<>(
     221                            HierarchyPanel.this.getModel()));
     222        }
     223
     224        @Override
     225        public boolean hasChildren(ModelWrapper<SolrDocument> node) {
     226            if (node.isLimit()) {
     227                return false;
     228            } else {
     229                final Object partCount = node.getModelObject().getFieldValue(FacetConstants.FIELD_HAS_PART_COUNT);
     230                return (partCount instanceof Number) && ((Number) partCount).intValue() > 0;
     231            }
     232        }
     233
     234        @Override
     235        public Iterator<? extends ModelWrapper<SolrDocument>> getChildren(ModelWrapper<SolrDocument> node) {
     236            if (node.isLimit()) {
     237                return Collections.emptyIterator();
     238            } else {
     239                final Collection<Object> parts = node.getModelObject().getFieldValues(FacetConstants.FIELD_HAS_PART);
     240                final Iterator<Object> objectIterator;
     241                if (childrenShown == null) {
     242                    // unlimited
     243                    objectIterator = parts.iterator();
     244                } else {
     245                    objectIterator = Iterators.limit(parts.iterator(), childrenShown);
     246                }
     247                final Iterator<ModelWrapper<SolrDocument>> iterator = Iterators.transform(objectIterator, new Function<Object, ModelWrapper<SolrDocument>>() {
     248
     249                    @Override
     250                    public ModelWrapper<SolrDocument> apply(Object childId) {
     251                        final SolrDocument document = documentService.getDocument(childId.toString());
     252                        return new ModelWrapper<>(new SolrDocumentModel(document));
     253                    }
     254                });
     255                if (childrenShown != null && parts.size() > childrenShown) {
     256                    return Iterators.concat(iterator, // add empty model wrapper to indicate "end of page"
     257                            Iterators.singletonIterator(new ModelWrapper<SolrDocument>(parts.size())));
     258                } else {
     259                    return iterator;
     260                }
     261            }
     262        }
     263
     264        @Override
     265        public IModel<ModelWrapper<SolrDocument>> model(ModelWrapper<SolrDocument> object) {
     266            return object;
    214267        }
    215268    }
     
    269322    }
    270323
     324    private class ModelWrapper<T> extends AbstractReadOnlyModel<ModelWrapper<T>> implements Serializable {
     325
     326        /**
     327         * Limit reached? TODO: add count
     328         */
     329        private final boolean limit;
     330
     331        /**
     332         * Total number of items (if beyond the limit)
     333         */
     334        private final int count;
     335
     336        /**
     337         * Inner model
     338         */
     339        private final IModel<T> model;
     340
     341        public ModelWrapper(int count) {
     342            this.limit = true;
     343            this.count = count;
     344            this.model = null;
     345        }
     346
     347        public ModelWrapper(IModel<T> model) {
     348            this.limit = false;
     349            this.count = -1;
     350            this.model = model;
     351        }
     352
     353        public boolean isLimit() {
     354            return limit;
     355        }
     356
     357        public IModel<T> getModel() {
     358            return model;
     359        }
     360
     361        public int getCount() {
     362            return count;
     363        }
     364
     365        public T getModelObject() {
     366            if (model == null) {
     367                return null;
     368            } else {
     369                return model.getObject();
     370            }
     371        }
     372
     373        // as IModel<T>
     374        @Override
     375        public void detach() {
     376            if (model != null) {
     377                model.detach();
     378            }
     379        }
     380
     381        // as IModel<T>
     382        @Override
     383        public ModelWrapper<T> getObject() {
     384            return this;
     385        }
     386
     387        @Override
     388        public int hashCode() {
     389            int hash = 5;
     390            hash = 41 * hash + (this.limit ? 1 : 0);
     391            hash = 41 * hash + Objects.hashCode(this.model);
     392            return hash;
     393        }
     394
     395        @Override
     396        public boolean equals(Object obj) {
     397            if (obj == null) {
     398                return false;
     399            }
     400            if (getClass() != obj.getClass()) {
     401                return false;
     402            }
     403            final ModelWrapper<?> other = (ModelWrapper<?>) obj;
     404            if (this.limit != other.limit) {
     405                return false;
     406            }
     407            if (!Objects.equals(this.model, other.model)) {
     408                return false;
     409            }
     410            return true;
     411        }
     412
     413    }
     414
    271415}
Note: See TracChangeset for help on using the changeset viewer.