001/* 002 * Copyright 2019 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.web.search.misc; 017 018import java.util.Arrays; 019import java.util.Collection; 020import java.util.List; 021import java.util.Map; 022import java.util.stream.Collectors; 023 024import org.apache.avalon.framework.component.Component; 025import org.apache.avalon.framework.context.Context; 026import org.apache.avalon.framework.context.ContextException; 027import org.apache.avalon.framework.context.Contextualizable; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.apache.cocoon.components.ContextHelper; 032import org.apache.cocoon.environment.Request; 033import org.apache.commons.lang3.StringUtils; 034 035import org.ametys.cms.search.query.AndQuery; 036import org.ametys.cms.search.query.Query; 037import org.ametys.cms.search.query.Query.Operator; 038import org.ametys.core.util.JSONUtils; 039import org.ametys.web.repository.site.Site; 040import org.ametys.web.search.query.SiteQuery; 041 042import com.google.common.collect.ImmutableMap; 043 044/** 045 * Helper for getting a {@link SiteQuery} from a user-submitted value. 046 */ 047public class SiteQueryHelper implements Component, Serviceable, Contextualizable 048{ 049 /** Avalon Role */ 050 public static final String ROLE = SiteQueryHelper.class.getName(); 051 052 private JSONUtils _jsonUtils; 053 private Context _context; 054 055 @Override 056 public void contextualize(Context context) throws ContextException 057 { 058 _context = context; 059 } 060 061 @Override 062 public void service(ServiceManager manager) throws ServiceException 063 { 064 _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE); 065 } 066 067 /** 068 * Gets a {@link Query} testing {@link Site} from a user-submitted value 069 * @param value a user-submitted value 070 * @param operator The operator 071 * @param contextualParameters the search contextual parameters. 072 * @param criterionId The criterion id (for logging purposes only) 073 * @return The {@link Query} 074 */ 075 @SuppressWarnings("unchecked") 076 public Query getQuery(Object value, Operator operator, Map<String, Object> contextualParameters, String criterionId) 077 { 078 // Handles a list of given site names (SITES_LIST) as well as "CURRENT_SITE", "OTHER_SITES" and "SITES" (all sites). 079 Map<String, Object> valueMap = _parseSite(value, criterionId); 080 081 String context = (String) valueMap.get("context"); 082 083 Request request = ContextHelper.getRequest(_context); 084 String currentSite = (String) request.getAttribute("siteName"); 085 if (StringUtils.isBlank(currentSite)) 086 { 087 currentSite = (String) contextualParameters.get("siteName"); 088 } 089 090 if ("CURRENT_SITE".equals(context)) 091 { 092 return new SiteQuery(Operator.EQ, currentSite); 093 } 094 else if ("OTHER_SITES".equals(context)) 095 { 096 return new AndQuery(new SiteQuery(), new SiteQuery(Operator.NE, currentSite)); 097 } 098 else if ("SITES".equals(context)) 099 { 100 return new SiteQuery(); 101 } 102 103 // "SITES_LIST" context: get the site list from the value map. 104 List<String> names = (List<String>) valueMap.get("sites"); 105 106 // Standard context: site list. 107 return new SiteQuery(operator, names); 108 } 109 110 @SuppressWarnings("unchecked") 111 private Map<String, Object> _parseSite(Object value, String criterionId) 112 { 113 if (value instanceof Map) 114 { 115 return (Map<String, Object>) value; 116 } 117 else if (value instanceof Collection) 118 { 119 String strValue = ((Collection<?>) value).stream() 120 .filter(String.class::isInstance) 121 .map(String.class::cast) 122 .collect(Collectors.joining(",")); 123 return _parseSite(strValue, criterionId); 124 } 125 else if (value instanceof String) 126 { 127 String strValue = (String) value; 128 if (strValue.startsWith("{")) 129 { 130 // Usually when coming from BO site widget 131 return _jsonUtils.convertJsonToMap(strValue); 132 } 133 else 134 { 135 // Consider it as the list of sites itself 136 // Usually when coming from FO 137 return ImmutableMap.of( 138 "context", "SITES_LIST", 139 "sites", Arrays.asList(strValue.split(",")) 140 ); 141 } 142 } 143 else 144 { 145 throw new IllegalArgumentException("The value " + value + " for criterion " + criterionId + " is not a valid Site value."); 146 } 147 } 148} 149