001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.text.xml.struct; 020 021import lucee.runtime.exp.ExpressionException; 022import lucee.runtime.exp.PageException; 023import lucee.runtime.op.Caster; 024import lucee.runtime.op.Duplicator; 025import lucee.runtime.text.xml.XMLCaster; 026import lucee.runtime.type.Array; 027import lucee.runtime.type.Collection; 028 029import org.w3c.dom.Element; 030import org.w3c.dom.Node; 031 032/** 033 * Element that can contain more than one Element 034 */ 035public final class XMLMultiElementStruct extends XMLElementStruct { 036 037 private static final long serialVersionUID = -4921231279765525776L; 038 private Array array; 039 040 /** 041 * Constructor of the class 042 * @param array 043 * @param caseSensitive 044 * @throws PageException 045 */ 046 public XMLMultiElementStruct(Array array, boolean caseSensitive) throws PageException { 047 super(getFirstRaw(array),caseSensitive); 048 this.array=array; 049 050 if(array.size()==0) 051 throw new ExpressionException("Array must have one Element at least"); 052 053 int[] ints=array.intKeys(); 054 for(int i=0;i<ints.length;i++) { 055 Object o=array.get(ints[i],null); 056 if(!(o instanceof Element)) { 057 throw new ExpressionException("all Element in the Array must be of type Element"); 058 } 059 } 060 } 061 062 private static Element getFirstRaw(Array array) throws PageException { 063 if(array.size()==0) 064 throw new ExpressionException("Array must have one Element at least"); 065 Element el=(Element) array.getE(1); 066 if(el instanceof XMLElementStruct) 067 el=(Element) XMLCaster.toRawNode(((XMLElementStruct)el).getElement()); 068 return el; 069 //return (Element)XMLCaster.toRawNode(array.getE(1)); 070 } 071 072 @Override 073 public Object removeEL(Collection.Key key) { 074 int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE); 075 if(index==Integer.MIN_VALUE)return super.removeEL (key); 076 return removeEL(index); 077 } 078 079 public Object removeEL(int index) { 080 Object o=array.removeEL(index); 081 if(o instanceof Element) { 082 Element el=(Element) o; 083 //try { 084 Node n = XMLCaster.toRawNode(el); 085 el.getParentNode().removeChild(n); 086 //} catch (PageException e) {} 087 } 088 return o; 089 } 090 091 @Override 092 public Object remove(Collection.Key key) throws PageException { 093 int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE); 094 if(index==Integer.MIN_VALUE)return super.remove (key); 095 return remove(index); 096 } 097 098 public Object remove(int index) throws PageException { 099 Object o=array.removeE(index); 100 if(o instanceof Element) { 101 Element el=(Element) o; 102 el.getParentNode().removeChild(XMLCaster.toRawNode(el)); 103 } 104 return o; 105 } 106 107 @Override 108 public Object get(Collection.Key key) throws PageException { 109 int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE); 110 if(index==Integer.MIN_VALUE)return super.get(key); 111 return get(index); 112 } 113 114 public Object get(int index) throws PageException { 115 return array.getE(index); 116 } 117 118 @Override 119 public Object get(Collection.Key key, Object defaultValue) { 120 int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE); 121 if(index==Integer.MIN_VALUE)return super.get(key,defaultValue); 122 return get(index,defaultValue); 123 } 124 125 public Object get(int index, Object defaultValue) { 126 return array.get(index,defaultValue); 127 } 128 129 @Override 130 public Object setEL(Collection.Key key, Object value) { 131 try { 132 return set(key,value); 133 } catch (PageException e1) { 134 return null; 135 } 136 } 137 138 /** 139 * @param index 140 * @param value 141 * @return 142 */ 143 public Object setEL(int index, Object value) { 144 try { 145 return set(index, value); 146 } catch (PageException e) { 147 return null; 148 } 149 } 150 151 @Override 152 public Object set(Collection.Key key, Object value) throws PageException { 153 int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE); 154 if(index==Integer.MIN_VALUE){ 155 return super.set (key,value); 156 } 157 return set(index,value); 158 } 159 160 public Object set(int index, Object value) throws PageException { 161 Element element=XMLCaster.toElement(getOwnerDocument(),value); 162 Object obj = array.get(index,null); 163 164 if(obj instanceof Element) { 165 Element el = ((Element)obj); 166 el.getParentNode().replaceChild(XMLCaster.toRawNode(element), XMLCaster.toRawNode(el)); 167 } 168 else if(array.size()+1==index) { 169 getParentNode().appendChild(XMLCaster.toRawNode(element)); 170 } 171 else { 172 throw new ExpressionException("the index for child node is out of range","valid range is from 1 to "+(array.size()+1)); 173 } 174 return array.setE(index,element); 175 } 176 177 178 @Override 179 public boolean containsKey(Collection.Key key) { 180 return get(key,null)!=null; 181 } 182 183 Array getInnerArray() { 184 return array; 185 } 186 187 188 public Collection duplicate(boolean deepCopy) { 189 try { 190 return new XMLMultiElementStruct((Array) Duplicator.duplicate(array,deepCopy),getCaseSensitive()); 191 } catch (PageException e) { 192 return null; 193 } 194 } 195 196 @Override 197 public Node cloneNode(boolean deep) { 198 try { 199 return new XMLMultiElementStruct((Array) Duplicator.duplicate(array,deep),getCaseSensitive()); 200 } catch (PageException e) { 201 return null; 202 } 203 } 204}