001/* 002 * Copyright 2014 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.cms.tag; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025 026import javax.jcr.RepositoryException; 027 028import org.apache.avalon.framework.parameters.Parameters; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.cocoon.ProcessingException; 032import org.apache.cocoon.acting.ServiceableAction; 033import org.apache.cocoon.environment.ObjectModelHelper; 034import org.apache.cocoon.environment.Redirector; 035import org.apache.cocoon.environment.Request; 036import org.apache.cocoon.environment.SourceResolver; 037import org.apache.commons.lang.StringUtils; 038import org.xml.sax.SAXException; 039 040import org.ametys.cms.tag.jcr.AbstractJCRTagProvider; 041import org.ametys.core.cocoon.JSonReader; 042import org.ametys.plugins.repository.AmetysObjectResolver; 043import org.ametys.plugins.repository.AmetysRepositoryException; 044 045/** 046 * SAX events for tags 047 * 048 */ 049public abstract class AbstractGetTagsAction extends ServiceableAction 050{ 051 /** The tag provider extension point */ 052 protected AbstractTagProviderExtensionPoint<? extends Tag> _tagProviderExtPt; 053 054 /** The Ametys object resolver */ 055 protected AmetysObjectResolver _resolver; 056 057 @SuppressWarnings("unchecked") 058 @Override 059 public void service(ServiceManager serviceManager) throws ServiceException 060 { 061 super.service(serviceManager); 062 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 063 _tagProviderExtPt = (AbstractTagProviderExtensionPoint< ? extends Tag>) serviceManager.lookup(getTagProviderEPRole()); 064 } 065 066 /** 067 * Get the tag provider extension point role 068 * @return the tag provider extension point role 069 */ 070 public abstract String getTagProviderEPRole(); 071 072 @SuppressWarnings("unchecked") 073 @Override 074 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws IOException, SAXException, ProcessingException 075 { 076 Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 077 078 String parentId = (String) jsParameters.get("node"); 079 String nodeName = (String) jsParameters.get("nodeName"); 080 boolean onlyCustomTags = (Boolean) jsParameters.get("onlyCustomTags"); 081 082 List<String> objectTargetIds = (List<String>) jsParameters.get("objectTargetIds"); 083 084 Map<String, Object> contextualParameters = (Map<String, Object>) jsParameters.get("contextualParameters"); 085 086 List<Map<String, Object>> tags = new ArrayList<>(); 087 088 if (StringUtils.isEmpty(parentId) || parentId.equals("tag-root")) 089 { 090 Set<String> extensionsIds = getProvidersIds(onlyCustomTags); 091 092 for (String id : extensionsIds) 093 { 094 TagProvider<? extends Tag> tagProvider = _tagProviderExtPt.getExtension(id); 095 tags.add(providerToJSON(tagProvider, contextualParameters, jsParameters)); 096 } 097 } 098 else if (nodeName.startsWith("provider_")) 099 { 100 String providerId = nodeName.substring("provider_".length()); 101 TagProvider<? extends Tag> tagProvider = _tagProviderExtPt.getExtension(providerId); 102 103 if (tagProvider != null) 104 { 105 for (Tag tag : _getFilteredTags(tagProvider.getTags(contextualParameters), jsParameters).values()) 106 { 107 tags.add(tagToJSON(tag, tagProvider, objectTargetIds, jsParameters)); 108 } 109 } 110 } 111 else 112 { 113 Set<String> extensionsIds = getProvidersIds(onlyCustomTags); 114 for (String id : extensionsIds) 115 { 116 TagProvider<? extends Tag> tagProvider = _tagProviderExtPt.getExtension(id); 117 if (tagProvider.hasTag(nodeName, contextualParameters)) 118 { 119 Tag parent = tagProvider.getTag(nodeName, contextualParameters); 120 for (Tag tag : _getFilteredTags(parent.getTags(), jsParameters).values()) 121 { 122 tags.add(tagToJSON(tag, tagProvider, objectTargetIds, jsParameters)); 123 } 124 } 125 } 126 } 127 128 Map<String, Object> result = new HashMap<>(); 129 result.put("children", tags); 130 131 Request request = ObjectModelHelper.getRequest(objectModel); 132 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 133 134 return EMPTY_MAP; 135 } 136 137 /** 138 * Get filtered tags 139 * @param tags the tags to filter 140 * @param jsParameters the js parameters 141 * @return the map of tags 142 */ 143 protected Map<String, ? extends Tag> _getFilteredTags(Map<String, ? extends Tag> tags, Map<String, Object> jsParameters) 144 { 145 return tags; 146 } 147 148 /** 149 * Get all providers IDs 150 * @param onlyCustomTags If true, return only JCR providers IDs. 151 * @return a set of providers IDs 152 */ 153 protected Set<String> getProvidersIds(boolean onlyCustomTags) 154 { 155 if (!onlyCustomTags) 156 { 157 return _tagProviderExtPt.getExtensionsIds(); 158 } 159 160 return new HashSet<>(); 161 } 162 163 /** 164 * Returns the tag providers' id 165 * @return The id of tag providers 166 */ 167 protected Set<String> getProvidersId() 168 { 169 return getProvidersIds(false); 170 } 171 172 /** 173 * Get tag's properties to JSON format 174 * @param tag The tag 175 * @param tagProvider the tag provider 176 * @param objectTargetIds the list of Ametys object ids. Can be empty 177 * @param jsParameters the js parameters 178 * @return The tag properties 179 */ 180 protected Map<String, Object> tagToJSON(Tag tag, TagProvider<? extends Tag> tagProvider, List<String> objectTargetIds, Map<String, Object> jsParameters) 181 { 182 Map<String, Object> infos = new HashMap<>(); 183 184 infos.put("id", tag.getId()); 185 infos.put("name", tag.getName()); 186 infos.put("title", tag.getTitle()); 187 infos.put("description", tag.getDescription()); 188 189 boolean authorized = isUserAuthorized(tag, objectTargetIds, jsParameters); 190 infos.put("authorized", authorized); 191 infos.put("creationAllowed", isCreationAllowed(tagProvider, tag)); 192 193 if (tag.getTags().size() == 0) 194 { 195 infos.put("leaf", true); 196 } 197 198 return infos; 199 } 200 201 /** 202 * Get tag provider's properties to JSON format 203 * @param tagProvider the tag provider 204 * @param contextualParameters The contextual parameters 205 * @param jsParameters The js parameters 206 * @return The tag providers properties 207 * @throws AmetysRepositoryException If an error occurred 208 */ 209 protected Map<String, Object> providerToJSON(TagProvider<? extends Tag> tagProvider, Map<String, Object> contextualParameters, Map<String, Object> jsParameters) 210 { 211 Map<String, Object> infos = new HashMap<>(); 212 213 if (tagProvider instanceof AbstractJCRTagProvider) 214 { 215 AbstractJCRTagProvider<? extends Tag> provider = (AbstractJCRTagProvider<? extends Tag>) tagProvider; 216 try 217 { 218 infos.put("id", provider.getRootNode(contextualParameters).getId()); 219 } 220 catch (AmetysRepositoryException e) 221 { 222 getLogger().error("Unable to get JCR tag provider root node", e); 223 } 224 catch (RepositoryException e) 225 { 226 getLogger().error("Unable to get JCR tag provider root node", e); 227 } 228 } 229 else 230 { 231 infos.put("id", tagProvider.getId()); 232 } 233 234 infos.put("type", "provider"); 235 infos.put("name", "provider_" + tagProvider.getId()); 236 infos.put("title", tagProvider.getLabel()); 237 infos.put("description", tagProvider.getDescription()); 238 infos.put("authorized", true); 239 infos.put("creationAllowed", isCreationAllowed(tagProvider, null)); 240 infos.put("iconSmall", "/plugins/cms/resources/img/tag/tags_16.png"); 241 infos.put("iconMedium", "/plugins/cms/resources/img/tag/tags_32.png"); 242 infos.put("iconLarge", "/plugins/cms/resources/img/tag/tags_50.png"); 243 244 if (_getFilteredTags(tagProvider.getTags(contextualParameters), jsParameters).size() == 0) 245 { 246 infos.put("leaf", true); 247 } 248 return infos; 249 } 250 251 /** 252 * Test if a tag is visible to the current user. 253 * @param tag the Tag object. 254 * @param objectTargetIds the ids of current Ametys objects 255 * @param jsParameters The js parameters 256 * @return true if the user has access to the tag, false otherwise. 257 */ 258 protected boolean isUserAuthorized(Tag tag, List<String> objectTargetIds, Map<String, Object> jsParameters) 259 { 260 return true; 261 } 262 263 /** 264 * Determines if the current user can created tag 265 * @param tagProvider The tag provider 266 * @param tag The tag. Can be null. 267 * @return true if creation is allowed 268 */ 269 protected boolean isCreationAllowed(TagProvider<? extends Tag> tagProvider, Tag tag) 270 { 271 return true; 272 } 273}