001    package railo.runtime.text.xml.struct;
002    
003    import org.w3c.dom.Element;
004    import org.w3c.dom.Node;
005    
006    import railo.runtime.exp.ExpressionException;
007    import railo.runtime.exp.PageException;
008    import railo.runtime.op.Caster;
009    import railo.runtime.text.xml.XMLCaster;
010    import railo.runtime.type.Array;
011    import railo.runtime.type.Collection;
012    import railo.runtime.type.KeyImpl;
013    
014    /**
015     * Element that can contain more than one Element
016     */
017    public final class XMLMultiElementStruct extends XMLElementStruct {
018    
019            private static final long serialVersionUID = -4921231279765525776L;
020            private Array array;
021        
022        /**
023         * Constructor of the class
024         * @param array
025         * @param caseSensitive
026         * @throws PageException
027         */
028        public XMLMultiElementStruct(Array array, boolean caseSensitive) throws PageException {
029            super(getFirstRaw(array),caseSensitive);
030            this.array=array;
031            
032            if(array.size()==0)
033                throw new ExpressionException("Array must have one Element at least");
034            
035            int[] ints=array.intKeys();
036            for(int i=0;i<ints.length;i++) {
037                Object o=array.get(ints[i],null);
038                if(!(o instanceof Element)) {
039                    throw new ExpressionException("all Element in the Array must be of type Element");
040                }
041            }
042        }
043    
044            private static Element getFirstRaw(Array array) throws PageException {
045            if(array.size()==0)
046                throw new ExpressionException("Array must have one Element at least");
047            Element el=(Element) array.getE(1);
048            if(el instanceof XMLElementStruct)
049                    el=(Element) XMLCaster.toRawNode(((XMLElementStruct)el).getElement());
050            return el;
051            //return (Element)XMLCaster.toRawNode(array.getE(1));
052        }
053    
054        /**
055         *
056         * @see railo.runtime.text.xml.struct.XMLNodeStruct#removeEL(railo.runtime.type.Collection.Key)
057         */
058        public Object removeEL(Collection.Key key) {
059            int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
060            if(index==Integer.MIN_VALUE)return super.removeEL (key);
061            return removeEL(index);
062        }
063    
064            /**
065             * @see railo.runtime.type.Array#removeEL(int)
066             */
067            public Object removeEL(int index) {
068                    Object o=array.removeEL(index);
069                    if(o instanceof Element) {
070                            Element el=(Element) o;
071                            //try {
072                                    Node n = XMLCaster.toRawNode(el);
073                                    el.getParentNode().removeChild(n);
074                            //} catch (PageException e) {}
075                    }
076                    return o;
077            }
078            
079        
080        /**
081         * @see railo.runtime.type.Collection#remove(java.lang.String)
082         */
083        public Object remove(String key) throws PageException {
084            int index=Caster.toIntValue(key,Integer.MIN_VALUE);
085            if(index==Integer.MIN_VALUE)return super.remove (KeyImpl.init(key));
086            return remove(index);
087        }
088    
089        /**
090         * @see railo.runtime.text.xml.struct.XMLNodeStruct#remove(railo.runtime.type.Collection.Key)
091         */
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            /**
099             * @see railo.runtime.type.Array#removeE(int)
100             */
101            public Object remove(int index) throws PageException {
102                    Object o=array.removeE(index);
103                    if(o instanceof Element) {
104                            Element el=(Element) o;
105                            el.getParentNode().removeChild(XMLCaster.toRawNode(el));
106                    }
107                    return o;
108            }
109    
110        /**
111         * @see railo.runtime.text.xml.struct.XMLNodeStruct#get(railo.runtime.type.Collection.Key)
112         */
113        public Object get(Collection.Key key) throws PageException  {
114            int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
115            if(index==Integer.MIN_VALUE)return super.get(key);
116            return get(index);
117        }
118    
119            /**
120             *
121             * @see railo.runtime.type.Array#getE(int)
122             */
123            public Object get(int index) throws PageException {
124                    return array.getE(index);
125            }
126        
127        /**
128         *
129         * @see railo.runtime.type.Collection#get(java.lang.String, java.lang.Object)
130         */
131        public Object get(Collection.Key key, Object defaultValue) {
132            int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
133            if(index==Integer.MIN_VALUE)return super.get(key,defaultValue);
134            return get(index,defaultValue);
135        }
136    
137            /**
138             * @see railo.runtime.type.Array#get(int, java.lang.Object)
139             */
140            public Object get(int index, Object defaultValue) {
141                    return array.get(index,defaultValue);
142            }
143    
144        /**
145         *
146         * @see railo.runtime.text.xml.struct.XMLNodeStruct#setEL(railo.runtime.type.Collection.Key, java.lang.Object)
147         */
148        public Object setEL(Collection.Key key, Object value) {
149            try {
150                            return set(key,value);
151                    } catch (PageException e1) {
152                            return null;
153                    }
154        }
155    
156            /**
157             * @param index
158             * @param value
159             * @return
160             */
161            public Object setEL(int index, Object value) {
162                    try {
163                            return set(index, value);
164                    } catch (PageException e) {
165                            return null;
166                    }
167            }
168    
169            /**
170             * @see railo.runtime.text.xml.struct.XMLNodeStruct#set(railo.runtime.type.Collection.Key, java.lang.Object)
171             */
172            public Object set(Collection.Key key, Object value) throws PageException {
173            int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
174            if(index==Integer.MIN_VALUE){
175                    return super.set (key,value);
176            }
177            return set(index,value);
178        }
179    
180            /**
181             * @see railo.runtime.type.Array#setE(int, java.lang.Object)
182             */
183            public Object set(int index, Object value) throws PageException {
184                    Element element=XMLCaster.toElement(getOwnerDocument(),value);
185            Object obj = array.get(index,null);
186            
187            if(obj instanceof Element) {
188                    Element el = ((Element)obj);
189                    el.getParentNode().replaceChild(XMLCaster.toRawNode(element), XMLCaster.toRawNode(el));
190            }
191            else if(array.size()+1==index) {
192                    getParentNode().appendChild(XMLCaster.toRawNode(element));
193            }
194            else {
195                    throw new ExpressionException("the index for child node is out of range","valid range is from 1 to "+(array.size()+1));
196            }
197            return array.setE(index,element);
198            }
199        
200    
201        /**
202         *
203         * @see railo.runtime.text.xml.struct.XMLNodeStruct#containsKey(railo.runtime.type.Collection.Key)
204         */
205        public boolean containsKey(Collection.Key key) {
206            return get(key,null)!=null;
207        }
208    
209            Array getInnerArray() {
210                    return array;
211            }
212            
213    
214        public Collection duplicate(boolean deepCopy) {
215            try {
216                return new XMLMultiElementStruct((Array) array.duplicate(deepCopy),getCaseSensitive());
217            } catch (PageException e) {
218                return null;
219            }
220        }
221    
222            /**
223             * @see org.w3c.dom.Node#cloneNode(boolean)
224             */
225            public Node cloneNode(boolean deep) {
226                    try {
227                return new XMLMultiElementStruct((Array) array.duplicate(deep),getCaseSensitive());
228            } catch (PageException e) {
229                return null;
230            }
231            }
232    }