source: VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/gui/pages/VirtualCollectionDetailsPage.java @ 5573

Last change on this file since 5573 was 5573, checked in by Twan Goosen, 10 years ago

Styling of the VC details page
Refs #594

  • Property svn:eol-style set to native
File size: 15.7 KB
Line 
1package eu.clarin.cmdi.virtualcollectionregistry.gui.pages;
2
3import eu.clarin.cmdi.virtualcollectionregistry.gui.Application;
4import eu.clarin.cmdi.virtualcollectionregistry.gui.DateConverter;
5import eu.clarin.cmdi.virtualcollectionregistry.gui.DetachableVirtualCollectionModel;
6import eu.clarin.cmdi.virtualcollectionregistry.gui.VolatileEntityModel;
7import eu.clarin.cmdi.virtualcollectionregistry.gui.border.AjaxToggleBorder;
8import eu.clarin.cmdi.virtualcollectionregistry.model.Creator;
9import eu.clarin.cmdi.virtualcollectionregistry.model.Resource;
10import eu.clarin.cmdi.virtualcollectionregistry.model.VirtualCollection;
11import eu.clarin.cmdi.virtualcollectionregistry.model.VirtualCollection.Type;
12import java.sql.Date;
13import java.util.Collection;
14import java.util.Iterator;
15import java.util.LinkedList;
16import java.util.List;
17import java.util.Locale;
18import org.apache.wicket.Component;
19import org.apache.wicket.IPageMap;
20import org.apache.wicket.Page;
21import org.apache.wicket.PageParameters;
22import org.apache.wicket.PageReference;
23import org.apache.wicket.Session;
24import org.apache.wicket.authorization.UnauthorizedActionException;
25import org.apache.wicket.behavior.AbstractBehavior;
26import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
27import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
28import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
29import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
30import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
31import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
32import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
33import org.apache.wicket.markup.ComponentTag;
34import org.apache.wicket.markup.html.basic.Label;
35import org.apache.wicket.markup.html.basic.MultiLineLabel;
36import org.apache.wicket.markup.html.border.Border;
37import org.apache.wicket.markup.html.link.ExternalLink;
38import org.apache.wicket.markup.html.link.Link;
39import org.apache.wicket.markup.html.link.PopupSettings;
40import org.apache.wicket.markup.html.list.ListItem;
41import org.apache.wicket.markup.html.list.ListView;
42import org.apache.wicket.markup.html.list.OddEvenListItem;
43import org.apache.wicket.markup.repeater.Item;
44import org.apache.wicket.model.ComponentPropertyModel;
45import org.apache.wicket.model.CompoundPropertyModel;
46import org.apache.wicket.model.IModel;
47import org.apache.wicket.model.Model;
48import org.apache.wicket.model.PropertyModel;
49import org.apache.wicket.util.convert.IConverter;
50import org.apache.wicket.util.string.Strings;
51
52@SuppressWarnings("serial")
53public class VirtualCollectionDetailsPage extends BasePage {
54
55    public static final String PARAM_VC_ID = "id";
56    public static final String PARAM_BACK_PAGE_ID = "backPage";
57    public static final String PARAM_BACK_PAGE_VERSION = "backPageVersion";
58    public static final String PARAM_BACK_PAGE_PAGEMAP_NAME = "backPageMapName";
59    private static final String CSS_CLASS = "collectionDetails";
60    private static final IConverter convDate = new DateConverter();
61    private final HideIfEmptyBehavior hideIfEmpty = new HideIfEmptyBehavior();
62
63    private static final IConverter convEnum = new IConverter() {
64        @Override
65        public String convertToString(Object o, Locale locale) {
66            final Enum<?> enumObj = (Enum<?>) o;
67            final String key
68                    = enumObj.getDeclaringClass().getSimpleName() + "."
69                    + enumObj.name();
70            final String value = Application.get().getResourceSettings()
71                    .getLocalizer().getString(key, null);
72            return Strings.escapeMarkup(value).toString();
73        }
74
75        @Override
76        public Object convertToObject(String s, Locale locale) {
77            return null;
78        }
79    };
80
81    /*
82     * Actually, we really want the behavior to hide the component on
83     * the beforeRender() call, but we always get an exception from Wicket
84     * that we are not supposed to change the page hierarchy anymore. This
85     * class is a hack to avoid this exception.
86     */
87    private static final class HideIfEmptyBehavior extends AbstractBehavior {
88
89        private final List<Component> components = new LinkedList<Component>();
90
91        @Override
92        public void bind(Component component) {
93            super.bind(component);
94            components.add(component);
95        }
96
97        public void hideEmptyComponents() {
98            for (Component component : components) {
99                Object obj = component.getDefaultModelObject();
100                if (obj == null) {
101                    component.setVisible(false);
102                } else {
103                    if (obj instanceof Collection<?>) {
104                        if (((Collection<?>) obj).isEmpty()) {
105                            component.setVisible(false);
106                        }
107                    }
108                }
109            }
110        }
111
112        @Override
113        public void cleanup() {
114            super.cleanup();
115            components.clear();
116        }
117    } // class VirtualCollectionDetailsPage.HideIfEmptyBehavior
118
119    private static class CustomLabel extends Label {
120
121        public CustomLabel(String id) {
122            super(id);
123        }
124
125        @Override
126        public IConverter getConverter(Class<?> type) {
127            if (VirtualCollection.Type.class.isAssignableFrom(type)
128                    || VirtualCollection.Purpose.class.isAssignableFrom(type)
129                    || VirtualCollection.Reproducibility.class.isAssignableFrom(type)) {
130                return convEnum;
131            }
132            if (Date.class.isAssignableFrom(type)) {
133                return convDate;
134            }
135            return super.getConverter(type);
136        }
137    } // class VirtualCollectionDetailsPage.TypeLabel
138
139    public VirtualCollectionDetailsPage(PageParameters params) {
140        this(getVirtualCollectionModel(params), getPageReference(params));
141    }
142
143    public VirtualCollectionDetailsPage(final IModel<VirtualCollection> model, final PageReference previousPage) {
144        super(new CompoundPropertyModel<VirtualCollection>(model));
145        if (model == null) {
146            setResponsePage(Application.get().getHomePage());
147        } else {
148            checkAccess(model.getObject());
149        }
150
151        final Link<Void> backLink = new Link<Void>("back") {
152            @Override
153            public void onClick() {
154                if (previousPage == null) {
155                    setResponsePage(getApplication().getHomePage());
156                } else {
157                    setResponsePage(previousPage.getPage());
158                }
159            }
160        };
161        add(backLink);
162
163        add(new Label("name"));
164       
165        addGeneralProperties(model);
166        addCreators();
167        addResources(model);
168        addGeneratedBy(model);
169    }
170
171    private void addGeneralProperties(final IModel<VirtualCollection> model) {
172        final Border general = new AjaxToggleBorder("generalBorder",
173                new Model<String>("General"), CSS_CLASS);
174        add(general);
175        general.add(new Label("name"));
176        general.add(new CustomLabel("type"));
177        general.add(new CustomLabel("creationDate"));
178        general.add(new MultiLineLabel("description").add(hideIfEmpty));
179        general.add(new CustomLabel("purpose").add(hideIfEmpty));
180        general.add(new CustomLabel("reproducibility").add(hideIfEmpty));
181        general.add(new Label("reproducibilityNotice").add(hideIfEmpty));
182
183        final ExternalLink pidLink = new ExternalLink("pidLink", new PropertyModel<String>(model, "persistentIdentifier.actionableURI"));
184        pidLink.add(new Label("persistentIdentifier.URI"));
185        pidLink.add(hideIfEmpty);
186        general.add(pidLink);
187
188        addKeywords(general);
189    }
190
191    private void addKeywords(final Border general) {
192        final ListView<String> keywords = new ListView<String>("keywords") {
193            @Override
194            protected void populateItem(ListItem<String> item) {
195                item.add(new Label("keyword", item.getModelObject()));
196            }
197        };
198        keywords.add(hideIfEmpty);
199        general.add(keywords);
200    }
201
202    private void addCreators() {
203        final Border creators = new AjaxToggleBorder("creatorsBorder",
204                new Model<String>("Creators"), CSS_CLASS);
205        add(creators);
206        creators.add(new ListView<Creator>("creators") {
207            @Override
208            protected void populateItem(ListItem<Creator> item) {
209                item.add(new Label("person"));
210                item.add(new MultiLineLabel("address").add(hideIfEmpty));
211                item.add(new Label("organisation").add(hideIfEmpty));
212                item.add(new Label("email").add(hideIfEmpty));
213                item.add(new Label("telephone").add(hideIfEmpty));
214                final IModel<String> siteModel
215                        = new ComponentPropertyModel<String>("website");
216                item.add(new ExternalLink("website", siteModel, siteModel)
217                        .setPopupSettings(new PopupSettings())
218                        .add(hideIfEmpty));
219                item.add(new Label("role").add(hideIfEmpty));
220            }
221
222            @Override
223            protected IModel<Creator> getListItemModel(
224                    IModel<? extends List<Creator>> listViewModel, int index) {
225                final List<Creator> creators = listViewModel.getObject();
226                return new CompoundPropertyModel<Creator>(
227                        new VolatileEntityModel<>(creators.get(index)));
228            }
229
230            @Override
231            protected ListItem<Creator> newItem(int index) {
232                final IModel<Creator> model
233                        = getListItemModel(getModel(), index);
234                return new OddEvenListItem<Creator>(index, model) {
235                    @Override
236                    protected void onComponentTag(ComponentTag tag) {
237                        super.onComponentTag(tag);
238                        if (getIndex() == 0) {
239                            tag.append("class", "first", " ");
240                        }
241                    }
242                };
243            }
244        });
245    }
246
247    private void addResources(final IModel<VirtualCollection> model) {
248        final Border resources = new AjaxToggleBorder("resourcesBorder",
249                new Model<String>("Resources"), CSS_CLASS + " resources");
250        add(resources);
251
252        @SuppressWarnings("rawtypes")
253        final IColumn[] cols = new IColumn[2];
254        cols[1] = new PropertyColumn<Resource>(
255                Model.of("Type"), "type") {
256                    @Override
257                    public void populateItem(Item<ICellPopulator<Resource>> item,
258                            String componentId, IModel<Resource> model) {
259                        final Resource.Type type = model.getObject().getType();
260                        item.add(new Label(componentId,
261                                        convEnum.convertToString(type, getLocale())));
262                    }
263
264                    @Override
265                    public String getCssClass() {
266                        return "type";
267                    }
268                   
269                   
270                };
271        cols[0] = new AbstractColumn<Resource>(Model.of("Reference")) {
272
273            @Override
274            public void populateItem(Item<ICellPopulator<Resource>> item, String componentId, IModel<Resource> rowModel) {
275                item.add(new ReferenceLinkPanel(componentId, rowModel));
276            }
277
278            @Override
279            public String getCssClass() {
280                return "reference";
281            }
282
283        };
284
285        final SortableDataProvider<Resource> resourcesProvider = new SortableDataProvider<Resource>() {
286            @Override
287            public Iterator<? extends Resource>
288                    iterator(int first, int count) {
289                return model.getObject().getResources().listIterator(first);
290            }
291
292            @Override
293            public IModel<Resource> model(Resource resource) {
294                return new VolatileEntityModel<Resource>(resource);
295            }
296
297            @Override
298            public int size() {
299                return model.getObject().getResources().size();
300            }
301        };
302
303        final DataTable<Resource> resourcesTable
304                = new AjaxFallbackDefaultDataTable<Resource>("resourcesTable",
305                        cols, resourcesProvider, 64);
306        resources.add(resourcesTable);
307        resources.setVisible(model.getObject().getType() == Type.EXTENSIONAL);
308    }
309
310    private void addGeneratedBy(final IModel<VirtualCollection> model) {
311        final Border generated = new AjaxToggleBorder("generatedByBorder",
312                new Model<String>("Intensional Collection Query"), CSS_CLASS);
313        add(generated);
314        generated.add(new Label("generatedBy.description"));
315        generated.add(new Label("generatedBy.uri").add(hideIfEmpty));
316        generated.add(new Label("generatedBy.query.profile").add(hideIfEmpty));
317        generated.add(new Label("generatedBy.query.value").add(hideIfEmpty));
318        generated.setVisible(model.getObject().getType() == Type.INTENSIONAL);
319    }
320
321    private static IModel<VirtualCollection> getVirtualCollectionModel(PageParameters params) {
322        final Long collectionId = params.getAsLong(PARAM_VC_ID);
323        if (collectionId == null) {
324            Session.get().error("Collection could not be retrieved, id not provided");
325            return null;
326        }
327        return new DetachableVirtualCollectionModel(collectionId);
328    }
329
330    private static PageReference getPageReference(PageParameters params) {
331        final Integer pageId = params.getAsInteger(PARAM_BACK_PAGE_ID);
332        final Integer pageVersion = params.getAsInteger(PARAM_BACK_PAGE_VERSION);
333        final String pageMap = params.getString(PARAM_BACK_PAGE_PAGEMAP_NAME);
334        if (pageId != null && pageVersion != null) {
335            for (IPageMap map : Session.get().getPageMaps()) {
336                if (pageMap == null && map.getName() == null || pageMap != null && pageMap.equals(map.getName())) {
337                    final Page page = map.get(pageId, pageVersion);
338                    if (page != null) {
339                        return page.getPageReference();
340                    }
341                }
342            }
343        }
344        return null;
345    }
346
347    public static PageParameters createPageParameters(VirtualCollection vc, PageReference pageReference) {
348        final PageParameters params = new PageParameters();
349        params.put(VirtualCollectionDetailsPage.PARAM_VC_ID, vc.getId());
350
351        if (pageReference != null) {
352            params.put(VirtualCollectionDetailsPage.PARAM_BACK_PAGE_ID, pageReference.getPageNumber());
353            params.put(VirtualCollectionDetailsPage.PARAM_BACK_PAGE_VERSION, pageReference.getPageVersion());
354            if (pageReference.getPageMapName() != null) {
355                params.put(VirtualCollectionDetailsPage.PARAM_BACK_PAGE_PAGEMAP_NAME, pageReference.getPageMapName());
356            }
357        }
358        return params;
359    }
360
361    /**
362     *
363     * @param vc collection to check for
364     * @throws UnauthorizedActionException if the VC is private and the current
365     * user is not the owner
366     */
367    private void checkAccess(final VirtualCollection vc) throws UnauthorizedActionException {
368        if (vc.isPrivate()
369                && !isUserAdmin()
370                && !getSession().isCurrentUser(vc.getOwner())) {
371            // user trying to access other user's collection
372            throw new UnauthorizedActionException(this, Component.RENDER);
373        }
374    }
375
376    @Override
377    protected void onBeforeRender() {
378        super.onBeforeRender();
379        hideIfEmpty.hideEmptyComponents();
380    }
381
382} // class VirtualCollectionDetailsPage
Note: See TracBrowser for help on using the repository browser.