/** * Copyright 2012 Universitat Pompeu Fabra. * * Licensed 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.onexus.website.api.pages.search.figures; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.util.encoding.UrlEncoder; import org.apache.wicket.util.string.Strings; import org.onexus.collection.api.Collection; import org.onexus.collection.api.Field; import org.onexus.collection.api.IEntity; import org.onexus.resource.api.ORI; import org.onexus.website.api.Website; import org.onexus.website.api.WebsiteApplication; import org.onexus.website.api.pages.browser.SingleEntitySelection; import org.onexus.website.api.pages.search.SearchLink; import org.onexus.website.api.pages.search.SearchPageStatus; import org.onexus.website.api.pages.search.SearchType; import org.onexus.website.api.pages.search.boxes.FieldsPanel; import org.onexus.website.api.widgets.selection.FilterConfig; import org.onexus.website.api.widgets.selection.MultipleEntitySelection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.regex.Pattern; public class LinksBox extends Panel { private static final int MAX_LABELS = 6; private transient IEntity entity; private transient Iterator<IEntity> entityIterator; private transient ORI collection; private transient FilterConfig filterConfig; private transient SearchPageStatus status; public LinksBox(String id, SearchPageStatus status, IEntity entity) { super(id); this.status = status; this.entity = entity; this.collection = entity.getCollection().getORI(); this.filterConfig = null; } public LinksBox(String id, SearchPageStatus status, ORI collection, FilterConfig filterConfig, Iterator<IEntity> entityIterator) { super(id); this.status = status; this.filterConfig = filterConfig; this.collection = collection; this.entity = null; this.entityIterator = entityIterator; } @Override protected void onInitialize() { super.onInitialize(); // Prepare accordion containers RepeatingView links = new RepeatingView("links"); WebMarkupContainer accordionBody = new WebMarkupContainer("accordion-body"); String bodyId = getMarkupId() + "-body"; accordionBody.setMarkupId(bodyId); add(links); add(accordionBody); if (entityIterator != null) { entity = entityIterator.next(); } // Label Set<String> labels = new HashSet<String>(); Set<String> founds = new HashSet<String>(); String labelField = entity.getCollection().getProperty("FIXED_ENTITY_FIELD"); WebMarkupContainer item = new WebMarkupContainer(links.newChildId()); item.add(new AttributeModifier("class", "active")); links.add(item); WebMarkupContainer activeLink = new WebMarkupContainer("link"); String anchor = entity.getId().replaceAll("[^a-zA-Z0-9\\.\\-]", "_"); activeLink.add(new AttributeModifier("href", "#" + anchor)); activeLink.add(new AttributeModifier("data-toggle", "pill")); item.add(activeLink); // Add first label String label = getLabel(entity, labelField); labels.add(label.toUpperCase()); activeLink.add(new Label("label", label).setEscapeModelStrings(false)); // Add first found key // Search main key String mainField = status.getType().getKeysList().get(0); String found = getLabel(entity, mainField); founds.add(found.toUpperCase()); // Fields values RepeatingView fields = new RepeatingView("fields"); accordionBody.add(fields); Component first = newFieldsBox(fields.newChildId(), labelField, anchor, entity, true); fields.add(first); // Complete the label if (entityIterator != null) { int count = 1; int remaining = 0; while (entityIterator.hasNext()) { entity = entityIterator.next(); count++; label = getLabel(entity, labelField); labels.add(label.toUpperCase()); found = getLabel(entity, mainField); founds.add(found.toUpperCase()); if (count > MAX_LABELS) { remaining++; continue; } item = new WebMarkupContainer(links.newChildId()); links.add(item); activeLink = new WebMarkupContainer("link"); anchor = entity.getId().replaceAll("[^a-zA-Z0-9\\.\\-]", "_"); activeLink.add(new AttributeModifier("href", "#" + anchor)); activeLink.add(new AttributeModifier("data-toggle", "pill")); item.add(activeLink); activeLink.add(new Label("label", label)); fields.add(newFieldsBox(fields.newChildId(), labelField, anchor, entity, false)); } if (remaining > 0) { item = new WebMarkupContainer(links.newChildId()); links.add(item); activeLink = new ExternalLink("link", ""); activeLink.add(new Label("label", "and " + remaining + " more")); activeLink.setEnabled(false); item.add(activeLink); } } // Discover not matched labels Set<String> notFound = new HashSet<String>(); String[] values = status.getSearch().split(","); for (String value : values) { value = value.trim().toUpperCase(); if (!founds.contains(value) && !value.isEmpty()) { notFound.add(value); } } onNotFound(notFound); // Prepare links variables SearchType searchType = status.getType(); String varEntity = filterConfig == null ? entity.getId() : ""; String varFilter = createVarFilter(entity, filterConfig); // Links accordionBody.add(createLinks(collection, searchType, varEntity, varFilter)); } private Component newFieldsBox(String componentId, String labelField, String anchor, IEntity entity, boolean active) { Component box; if (status.getType().getTemplate() == null || status.getType().getTemplate().isEmpty()) { box = new FieldsPanel(componentId, labelField, entity); } else { box = new Label(componentId, replaceEntityValues(status.getType().getTemplate(), entity)).setEscapeModelStrings(false); } if (active) { box.add(new AttributeAppender("class", " active")); } box.setMarkupId(anchor); return box; } private static String createVarFilter(IEntity entity, FilterConfig filterConfig) { if (filterConfig != null) { MultipleEntitySelection browserSelection = new MultipleEntitySelection(filterConfig); return "pfc=" + UrlEncoder.QUERY_INSTANCE.encode(browserSelection.toUrlParameter(false, null), "UTF-8"); } if (entity != null) { SingleEntitySelection singleEntitySelection = new SingleEntitySelection(entity); return "pf=" + UrlEncoder.QUERY_INSTANCE.encode(singleEntitySelection.toUrlParameter(false, null), "UTF-8"); } return ""; } protected void onNotFound(Set<String> valuesNotFound) { } private String getLabel(IEntity entity, String labelField) { return labelField == null ? StringUtils.replace(entity.getId(), "\t", "-") : String.valueOf(entity.get(labelField)); } private WebMarkupContainer createLinks(ORI collectionORI, SearchType searchType, String varEntity, String varFilter) { WebMarkupContainer linksContainer = new WebMarkupContainer("linksContainer"); RepeatingView links = new RepeatingView("links"); if (searchType.getLinks() != null) { String prefix = getPage().getPageParameters().get(Website.PARAMETER_CURRENT_PAGE).isEmpty() ? WebsiteApplication.get().getWebPath() + "/" : ""; linksContainer.setVisible(false); boolean isList = entityIterator != null || filterConfig != null; for (SearchLink searchLink : searchType.getLinks()) { String visible = searchLink.getVisible(); if (!Strings.isEmpty(visible)) { if (isList && !"LIST".equalsIgnoreCase(visible)) { continue; } if (!isList && !"SINGLE".equalsIgnoreCase(visible)) { continue; } } linksContainer.setVisible(true); WebMarkupContainer item = new WebMarkupContainer(links.newChildId()); WebMarkupContainer link = new WebMarkupContainer("link"); link.add(new AttributeModifier("href", prefix + createLink(searchLink.getUrl(), searchType.getCollection(), varEntity, varFilter))); link.add(new Label("label", searchLink.getTitle()).setEscapeModelStrings(false)); item.add(link); links.add(item); } } else { linksContainer.setVisible(false); } linksContainer.add(links); return linksContainer; } public static String createLink(String url, ORI collection, String varEntity, String varFilter) { String link = url; //TODO Remove deprecated variables link = link.replace("$collection", collection.toString()); link = link.replace("$entity", varEntity); link = link.replace("$filter", varFilter); link = link.replace("$[collection]", collection.toString()); link = link.replace("$[entity]", varEntity); link = link.replace("$[filter]", varFilter); return link; } private static String replaceEntityValues(String template, IEntity entity) { Collection collection = entity.getCollection(); for (Field field : collection.getFields()) { template = template.replaceAll("\\$\\[" + field.getId() + "\\]", String.valueOf(entity.get(field.getId()))); } return template; } }