001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.acacia.client; 029 030import org.opencms.acacia.shared.CmsContentDefinition; 031import org.opencms.acacia.shared.CmsType; 032 033import java.util.ArrayList; 034import java.util.HashMap; 035import java.util.List; 036import java.util.Map; 037import java.util.function.Consumer; 038 039/** 040 * The root attribute handler.<p> 041 */ 042public class CmsRootHandler implements I_CmsAttributeHandler { 043 044 /** The sub handlers. */ 045 protected List<Map<String, CmsAttributeHandler>> m_handlers; 046 047 /** The attribute handler by id. */ 048 private Map<String, CmsAttributeHandler> m_handlerById; 049 050 /** 051 * Constructor.<p> 052 */ 053 public CmsRootHandler() { 054 055 m_handlers = new ArrayList<Map<String, CmsAttributeHandler>>(); 056 m_handlers.add(new HashMap<String, CmsAttributeHandler>()); 057 m_handlerById = new HashMap<String, CmsAttributeHandler>(); 058 } 059 060 /** 061 * Clears the handler hierarchy. 062 */ 063 public void clearHandlers() { 064 065 for (Map<String, CmsAttributeHandler> handlers : m_handlers) { 066 for (CmsAttributeHandler handler : handlers.values()) { 067 handler.clearHandlers(); 068 } 069 handlers.clear(); 070 } 071 m_handlers.clear(); 072 m_handlers.add(new HashMap<String, CmsAttributeHandler>()); 073 m_handlerById.clear(); 074 } 075 076 /** 077 * @see org.opencms.acacia.client.I_CmsAttributeHandler#collectSimplePath(org.opencms.acacia.client.I_CmsAttributeHandler) 078 */ 079 public String collectSimplePath(I_CmsAttributeHandler childHandler) { 080 081 return ""; 082 } 083 084 /** 085 * Ensures attribute handler maps are available up to the specified index.<p> 086 * This is required during inline editing, where only a fragment of the handlers data structure is build and used.<p> 087 * 088 * @param index the index of the currently edited attribute 089 */ 090 public void ensureHandlers(int index) { 091 092 if (m_handlers.size() <= index) { 093 // make sure the handler maps are available 094 // this may be necessary 095 for (int i = m_handlers.size(); i <= index; i++) { 096 insertHandlers(i); 097 } 098 } 099 } 100 101 /** 102 * @see org.opencms.acacia.client.I_CmsAttributeHandler#getAttributeName() 103 */ 104 public String getAttributeName() { 105 106 throw new UnsupportedOperationException(); 107 } 108 109 /** 110 * @see org.opencms.acacia.client.I_CmsAttributeHandler#getChildHandler(java.lang.String, int) 111 */ 112 public CmsAttributeHandler getChildHandler(String attributeName, int index) { 113 114 CmsAttributeHandler result = null; 115 if (m_handlers.size() > index) { 116 result = m_handlers.get(index).get(attributeName); 117 } else { 118 return null; 119 } 120 if (result == null) { 121 for (Map.Entry<String, CmsAttributeHandler> entry : m_handlers.get(index).entrySet()) { 122 String key = entry.getKey(); 123 int opencmsPos = key.indexOf("opencms://"); 124 if (opencmsPos > 0) { 125 String reducedKey = key.substring(opencmsPos); 126 if (reducedKey.equals(attributeName)) { 127 result = entry.getValue(); 128 break; 129 } 130 } 131 } 132 } 133 return result; 134 } 135 136 /** 137 * @see org.opencms.acacia.client.I_CmsAttributeHandler#getChildHandlerBySimpleName(java.lang.String, int) 138 */ 139 public CmsAttributeHandler getChildHandlerBySimpleName(String name, int index) { 140 141 if (m_handlers.size() > index) { 142 for (String attributeName : m_handlers.get(index).keySet()) { 143 if (attributeName.equals(name) || attributeName.endsWith(name)) { 144 return m_handlers.get(index).get(attributeName); 145 } 146 } 147 } 148 return null; 149 } 150 151 /** 152 * Returns the handler for the given id.<p> 153 * 154 * @param entityId the entity id 155 * @param attributeName the attribute name 156 * 157 * @return the handler 158 */ 159 public CmsAttributeHandler getHandlerById(String entityId, String attributeName) { 160 161 return m_handlerById.get(entityId + "/" + attributeName); 162 } 163 164 /** 165 * Returns the attribute handler for the given path.<p> 166 * 167 * @param pathNames the path names 168 * 169 * @return the attribute handler 170 */ 171 public CmsAttributeHandler getHandlerByPath(String[] pathNames) { 172 173 I_CmsAttributeHandler handler = this; 174 int index = 0; 175 for (int i = 0; i < pathNames.length; i++) { 176 177 String attributeName = pathNames[i]; 178 int nextIndex = CmsContentDefinition.extractIndex(attributeName); 179 attributeName = CmsContentDefinition.removeIndex(attributeName); 180 if ((handler instanceof CmsAttributeHandler) 181 && ((CmsAttributeHandler)handler).getAttributeType().isChoice()) { 182 // in case of a choice attribute, skip to the next path name 183 attributeName = CmsType.CHOICE_ATTRIBUTE_NAME; 184 185 i++; 186 if (i < pathNames.length) { 187 nextIndex = CmsContentDefinition.extractIndex(pathNames[i]); 188 } 189 } 190 191 handler = handler.getChildHandler(attributeName, index); 192 index = nextIndex; 193 } 194 195 return (CmsAttributeHandler)handler; 196 } 197 198 /** 199 * Returns the attribute handler to the given simple path.<p> 200 * 201 * @param pathNames the simple path elements 202 * 203 * @return the attribute handler 204 */ 205 public CmsAttributeHandler getHandlersBySimplePath(String[] pathNames) { 206 207 I_CmsAttributeHandler handler = this; 208 int index = 0; 209 for (int i = 0; i < pathNames.length; i++) { 210 String attributeName = pathNames[i]; 211 int nextIndex = CmsContentDefinition.extractIndex(attributeName); 212 if (nextIndex > 0) { 213 nextIndex--; 214 } 215 attributeName = CmsContentDefinition.removeIndex(attributeName); 216 if ((handler instanceof CmsAttributeHandler) 217 && ((CmsAttributeHandler)handler).getAttributeType().isChoice()) { 218 // in case of a choice attribute, skip to the next level 219 attributeName = CmsType.CHOICE_ATTRIBUTE_NAME; 220 } 221 handler = handler.getChildHandlerBySimpleName(attributeName, index); 222 index = nextIndex; 223 } 224 return (CmsAttributeHandler)handler; 225 } 226 227 /** 228 * @see org.opencms.acacia.client.I_CmsAttributeHandler#insertHandlers(int) 229 */ 230 public void insertHandlers(int index) { 231 232 if (index <= m_handlers.size()) { 233 m_handlers.add(index, new HashMap<String, CmsAttributeHandler>()); 234 } else { 235 throw new IndexOutOfBoundsException("index of " + index + " too big, current size: " + m_handlers.size()); 236 } 237 } 238 239 /** 240 * @see org.opencms.acacia.client.I_CmsAttributeHandler#removeHandlers(int) 241 */ 242 public void removeHandlers(int index) { 243 244 m_handlers.remove(index); 245 } 246 247 /** 248 * @see org.opencms.acacia.client.I_CmsAttributeHandler#setHandler(int, java.lang.String, org.opencms.acacia.client.CmsAttributeHandler) 249 */ 250 public void setHandler(int index, String attributeName, CmsAttributeHandler handler) { 251 252 m_handlers.get(index).put(attributeName, handler); 253 handler.setParentHandler(this); 254 setHandlerById(attributeName, handler); 255 } 256 257 /** 258 * @see org.opencms.acacia.client.I_CmsAttributeHandler#setHandlerById(java.lang.String, org.opencms.acacia.client.CmsAttributeHandler) 259 */ 260 public void setHandlerById(String attributeName, CmsAttributeHandler handler) { 261 262 m_handlerById.put(handler.getEntityId() + "/" + attributeName, handler); 263 } 264 265 /** 266 * Recruses over all child handlers of this handler and passes them to a callback.<p> 267 * 268 * @param handler the handler whose child handlers should be processed 269 */ 270 public void visit(Consumer<I_CmsAttributeHandler> handler) { 271 272 handler.accept(this); 273 for (CmsAttributeHandler child : m_handlerById.values()) { 274 child.visit(handler); 275 } 276 } 277 278 /** 279 * Initializes the sub handlers maps for the given value count.<p> 280 * 281 * @param count the value count 282 */ 283 protected void initHandlers(int count) { 284 285 if (count == 0) { 286 m_handlers.clear(); 287 } else { 288 while (m_handlers.size() < count) { 289 m_handlers.add(new HashMap<String, CmsAttributeHandler>()); 290 } 291 } 292 m_handlerById.clear(); 293 } 294}