001/* 002 * Copyright (c) 2004-2012, Willem Cazander 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, are permitted provided 006 * that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, this list of conditions and the 009 * following disclaimer. 010 * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 011 * the following disclaimer in the documentation and/or other materials provided with the distribution. 012 * 013 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 014 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 015 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 016 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 017 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 018 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 019 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 020 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 021 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 022 */ 023 024package org.x4o.xml.element; 025 026import java.util.List; 027import java.util.Map; 028import java.util.HashMap; 029import java.util.ArrayList; 030import java.util.logging.Logger; 031 032import javax.el.ELContext; 033import javax.el.ExpressionFactory; 034 035import org.x4o.xml.core.X4OPhase; 036import org.x4o.xml.core.config.X4OLanguageConfiguration; 037 038/** 039 * An AbstractElementLanguage. 040 * 041 * @author Willem Cazander 042 * @version 1.0 Aug 20, 2005 043 */ 044public abstract class AbstractElementLanguage implements ElementLanguageLocal { 045 046 private Logger logger = null; 047 private ExpressionFactory expressionFactory = null; 048 private ELContext eLContext = null; 049 private ElementAttributeValueParser elementAttributeValueParser = null; 050 private ElementObjectPropertyValue elementObjectPropertyValue = null; 051 private X4OPhase currentX4OPhase = null; 052 private Map<Element, X4OPhase> dirtyElements = null; 053 private Element rootElement = null; 054 private X4OLanguageConfiguration languageConfiguration = null; 055 private List<ElementLanguageModule> elementLanguageModules = null; 056 057 /** 058 * Creates a new empty ElementLanguage. 059 */ 060 public AbstractElementLanguage() { 061 logger = Logger.getLogger(AbstractElementLanguage.class.getName()); 062 logger.finest("Creating new ParsingContext"); 063 elementLanguageModules = new ArrayList<ElementLanguageModule>(20); 064 currentX4OPhase = X4OPhase.FIRST_PHASE; 065 dirtyElements = new HashMap<Element, X4OPhase>(40); 066 } 067 068 /** 069 * @see org.x4o.xml.element.ElementLanguage#getELContext() 070 */ 071 public ELContext getELContext() { 072 return eLContext; 073 } 074 075 /** 076 * @see org.x4o.xml.element.ElementLanguageLocal#setELContext(javax.el.ELContext) 077 */ 078 public void setELContext(ELContext context) { 079 if (eLContext!=null) { 080 throw new IllegalStateException("Can only set elContext once."); 081 } 082 eLContext = context; 083 } 084 085 /** 086 * @see org.x4o.xml.element.ElementLanguage#getExpressionFactory() 087 */ 088 public ExpressionFactory getExpressionFactory() { 089 return expressionFactory; 090 } 091 092 /** 093 * @see org.x4o.xml.element.ElementLanguageLocal#setExpressionFactory(javax.el.ExpressionFactory) 094 */ 095 public void setExpressionFactory(ExpressionFactory expressionFactory) { 096 if (this.expressionFactory!=null) { 097 throw new IllegalStateException("Can only set expressionFactory once."); 098 } 099 this.expressionFactory = expressionFactory; 100 } 101 102 /** 103 * @return the elementAttributeValueParser 104 */ 105 public ElementAttributeValueParser getElementAttributeValueParser() { 106 return elementAttributeValueParser; 107 } 108 109 /** 110 * @param elementAttributeValueParser the elementAttributeValueParser to set 111 */ 112 public void setElementAttributeValueParser(ElementAttributeValueParser elementAttributeValueParser) { 113 if (this.elementAttributeValueParser!=null) { 114 throw new IllegalStateException("Can only set elementAttributeValueParser once."); 115 } 116 this.elementAttributeValueParser = elementAttributeValueParser; 117 } 118 119 /** 120 * @return the elementObjectPropertyValue 121 */ 122 public ElementObjectPropertyValue getElementObjectPropertyValue() { 123 return elementObjectPropertyValue; 124 } 125 126 /** 127 * @param elementObjectPropertyValue the elementObjectPropertyValue to set 128 */ 129 public void setElementObjectPropertyValue(ElementObjectPropertyValue elementObjectPropertyValue) { 130 if (this.elementObjectPropertyValue!=null) { 131 throw new IllegalStateException("Can only set elementObjectPropertyValue once."); 132 } 133 this.elementObjectPropertyValue = elementObjectPropertyValue; 134 } 135 136 /** 137 * @see org.x4o.xml.element.ElementLanguage#getCurrentX4OPhase() 138 */ 139 public X4OPhase getCurrentX4OPhase() { 140 return currentX4OPhase; 141 } 142 143 /** 144 * @see org.x4o.xml.element.ElementLanguage#setCurrentX4OPhase(org.x4o.xml.core.X4OPhase) 145 */ 146 public void setCurrentX4OPhase(X4OPhase currentX4OPhase) { 147 this.currentX4OPhase = currentX4OPhase; 148 } 149 150 /** 151 * @see org.x4o.xml.element.ElementLanguage#addDirtyElement(org.x4o.xml.element.Element, org.x4o.xml.core.X4OPhase) 152 */ 153 public void addDirtyElement(Element element, X4OPhase phase) { 154 if (dirtyElements.containsKey(element)) { 155 throw new IllegalArgumentException("Can't add an element twice."); 156 } 157 dirtyElements.put(element,phase); 158 } 159 160 /** 161 * @see org.x4o.xml.element.ElementLanguage#getDirtyElements() 162 */ 163 public Map<Element, X4OPhase> getDirtyElements() { 164 return dirtyElements; 165 } 166 167 /** 168 * @see org.x4o.xml.element.ElementLanguage#getRootElement() 169 */ 170 public Element getRootElement() { 171 return rootElement; 172 } 173 174 /** 175 * @see org.x4o.xml.element.ElementLanguage#setRootElement(org.x4o.xml.element.Element) 176 */ 177 public void setRootElement(Element element) { 178 if (element==null) { 179 throw new NullPointerException("May not set rootElement to null"); 180 } 181 // allowed for reusing this context in multiple parse sessions. 182 //if (rootElement!=null) { 183 // throw new IllegalStateException("Can't set rootElement when it is already set."); 184 //} 185 rootElement=element; 186 } 187 188 /** 189 * @return the languageConfiguration 190 */ 191 public X4OLanguageConfiguration getLanguageConfiguration() { 192 return languageConfiguration; 193 } 194 195 /** 196 * @param languageConfiguration the languageConfiguration to set 197 */ 198 public void setLanguageConfiguration(X4OLanguageConfiguration languageConfiguration) { 199 this.languageConfiguration = languageConfiguration; 200 } 201 202 /** 203 * @see org.x4o.xml.element.ElementLanguage#addElementLanguageModule(org.x4o.xml.element.ElementLanguageModule) 204 */ 205 public void addElementLanguageModule(ElementLanguageModule elementLanguageModule) { 206 if (elementLanguageModule.getId()==null) { 207 throw new NullPointerException("Can't add module without id."); 208 } 209 elementLanguageModules.add(elementLanguageModule); 210 } 211 212 /** 213 * @see org.x4o.xml.element.ElementLanguage#getElementLanguageModules() 214 */ 215 public List<ElementLanguageModule> getElementLanguageModules() { 216 return elementLanguageModules; 217 } 218 219 220 /** 221 * @see org.x4o.xml.element.ElementLanguage#findElementBindingHandlers(java.lang.Object,java.lang.Object) 222 */ 223 public List<ElementBindingHandler> findElementBindingHandlers(Object parent,Object child) { 224 List<ElementBindingHandler> result = new ArrayList<ElementBindingHandler>(50); 225 for (int i=0;i<elementLanguageModules.size();i++) { 226 ElementLanguageModule module = elementLanguageModules.get(i); 227 findElementBindingHandlerInList(parent,child,result,module.getElementBindingHandlers()); 228 } 229 for (ElementInterface ei:findElementInterfaces(parent)) { 230 findElementBindingHandlerInList(parent,child,result,ei.getElementBindingHandlers()); 231 } 232 return result; 233 } 234 235 private void findElementBindingHandlerInList(Object parent,Object child,List<ElementBindingHandler> result,List<ElementBindingHandler> checkList) { 236 for (ElementBindingHandler binding:checkList) { 237 boolean parentBind = false; 238 if (parent instanceof Class) { 239 parentBind = binding.getBindParentClass().isAssignableFrom((Class<?>)parent); 240 } else { 241 parentBind = binding.getBindParentClass().isInstance(parent); 242 } 243 if (parentBind==false) { 244 continue; 245 } 246 boolean childBind = false; 247 for (Class<?> childClass:binding.getBindChildClasses()) { 248 if (child instanceof Class && childClass.isAssignableFrom((Class<?>)child)) { 249 childBind=true; 250 break; 251 } else if (childClass.isInstance(child)) { 252 childBind=true; 253 break; 254 } 255 } 256 if (parentBind & childBind) { 257 result.add(binding); 258 } 259 } 260 } 261 262 /** 263 * @see org.x4o.xml.element.ElementLanguage#findElementInterfaces(java.lang.Object) 264 */ 265 public List<ElementInterface> findElementInterfaces(Object elementObject) { 266 if (elementObject==null) { 267 throw new NullPointerException("Can't search for null object."); 268 } 269 List<ElementInterface> result = new ArrayList<ElementInterface>(50); 270 for (int i=0;i<elementLanguageModules.size();i++) { 271 ElementLanguageModule module = elementLanguageModules.get(i); 272 for (ElementInterface ei:module.getElementInterfaces()) { 273 Class<?> eClass = ei.getInterfaceClass(); 274 logger.finest("Checking interface handler: "+ei+" for class: "+eClass); 275 if (elementObject instanceof Class && eClass.isAssignableFrom((Class<?>)elementObject)) { 276 logger.finer("Found interface match from class; "+elementObject); 277 result.add(ei); 278 } else if (eClass.isInstance(elementObject)) { 279 logger.finer("Found interface match from object; "+elementObject); 280 result.add(ei); 281 } 282 } 283 } 284 return result; 285 } 286 287 /** 288 * @see org.x4o.xml.element.ElementLanguage#findElementNamespaceContext(java.lang.String) 289 */ 290 public ElementNamespaceContext findElementNamespaceContext(String namespaceUri) { 291 292 // TODO: refactor so no search for every tag !! 293 ElementNamespaceContext result = null; 294 for (int i=0;i<elementLanguageModules.size();i++) { 295 ElementLanguageModule module = elementLanguageModules.get(i); 296 result = module.getElementNamespaceContext(namespaceUri); 297 if (result!=null) { 298 return result; 299 } 300 } 301 return result; 302 } 303}