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}