001    /*
002     * Copyright 2002-2004 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.settings.xml;
017    
018    import java.io.IOException;
019    import java.util.ArrayList;
020    import java.util.HashMap;
021    import java.util.List;
022    import java.util.Map;
023    
024    import org.springframework.richclient.settings.AbstractSettings;
025    import org.springframework.richclient.settings.Settings;
026    import org.springframework.util.Assert;
027    import org.w3c.dom.Element;
028    import org.w3c.dom.Node;
029    import org.w3c.dom.NodeList;
030    
031    /**
032     * @author Peter De Bruycker
033     */
034    public class XmlSettings extends AbstractSettings {
035        private Element element;
036    
037        private boolean entriesLoaded;
038    
039        private Map values = new HashMap();
040    
041        public XmlSettings(Settings parent, Element element) {
042            super(parent, getName(element));
043            this.element = element;
044        }
045    
046        public XmlSettings(Element element) {
047            this(null, element);
048        }
049    
050        private static String getName(Element element) {
051            verifyElement(element);
052    
053            return element.getAttribute("name");
054        }
055    
056        private static void verifyElement(Element element) {
057            Assert.notNull(element, "element cannot be null");
058            Assert.isTrue(element.getNodeName().equals("settings"), "element must be settings");
059            Assert.isTrue(element.hasAttribute("name"), "element must have name attribute");
060        }
061    
062        protected Settings internalCreateChild(String key) {
063            loadChildrenIfNecessary();
064    
065            Element childElement = null;
066    
067            NodeList childNodes = element.getChildNodes();
068            for (int i = 0; i < childNodes.getLength(); i++) {
069                Node node = childNodes.item(i);
070                if (node instanceof Element) {
071                    Element tmp = (Element) node;
072                    if (tmp.getNodeName().equals("settings") && tmp.getAttribute("name").equals(key)) {
073                        childElement = tmp;
074                    }
075                }
076            }
077    
078            if (childElement == null) {
079                childElement = element.getOwnerDocument().createElement("settings");
080                childElement.setAttribute("name", key);
081                element.appendChild(childElement);
082            }
083    
084            return new XmlSettings(this, childElement);
085        }
086    
087        protected boolean internalContains(String key) {
088            loadChildrenIfNecessary();
089    
090            return values.containsKey(key);
091        }
092    
093        protected void internalSet(String key, String value) {
094            loadChildrenIfNecessary();
095    
096            Element entry = findOrCreateEntry(key);
097            entry.setAttribute("value", value);
098    
099            values.put(key, value);
100        }
101    
102        private Element findEntry(String key) {
103            NodeList childNodes = element.getChildNodes();
104            for (int i = 0; i < childNodes.getLength(); i++) {
105                Node node = childNodes.item(i);
106                if (node instanceof Element && node.getNodeName().equals("entry")) {
107                    Element tmp = (Element) node;
108                    if (tmp.getAttribute("key").equals(key)) {
109                        return tmp;
110                    }
111                }
112            }
113    
114            return null;
115        }
116    
117        private Element findOrCreateEntry(String key) {
118            Element entry = findEntry(key);
119            if (entry == null) {
120                entry = element.getOwnerDocument().createElement("entry");
121                entry.setAttribute("key", key);
122                element.appendChild(entry);
123            }
124    
125            return entry;
126        }
127    
128        protected String internalGet(String key) {
129            loadChildrenIfNecessary();
130    
131            return (String) values.get(key);
132        }
133    
134        public String[] getKeys() {
135            loadChildrenIfNecessary();
136    
137            return (String[]) values.keySet().toArray(new String[values.size()]);
138        }
139    
140        public void save() throws IOException {
141            getParent().save();
142        }
143    
144        private void loadChildrenIfNecessary() {
145            if (!entriesLoaded) {
146                NodeList childNodes = element.getChildNodes();
147                for (int i = 0; i < childNodes.getLength(); i++) {
148                    Node node = childNodes.item(i);
149                    if (node instanceof Element) {
150                        Element el = (Element) node;
151                        if (el.getNodeName().equals("entry")) {
152                            // entry
153                            values.put(el.getAttribute("key"), el.getAttribute("value"));
154                        }
155                    }
156                }
157    
158                entriesLoaded = true;
159            }
160        }
161    
162        public void load() throws IOException {
163            loadChildrenIfNecessary();
164        }
165    
166        protected void internalRemove(String key) {
167            loadChildrenIfNecessary();
168    
169            Element entry = findEntry(key);
170            if (entry != null) {
171                element.removeChild(entry);
172            }
173    
174            values.remove(key);
175        }
176    
177        public Element getElement() {
178            return element;
179        }
180    
181        protected String[] internalGetChildSettings() {
182            List childSettingsNames = new ArrayList();
183    
184            NodeList childNodes = element.getChildNodes();
185            for (int i = 0; i < childNodes.getLength(); i++) {
186                Node node = childNodes.item(i);
187                if (node instanceof Element) {
188                    Element el = (Element) node;
189                    if (el.getNodeName().equals("settings")) {
190                        childSettingsNames.add(el.getAttribute("name"));
191                    }
192                }
193            }
194    
195            return (String[]) childSettingsNames.toArray(new String[childSettingsNames.size()]);
196        }
197    
198        public void internalRemoveSettings() {
199            element.getParentNode().removeChild(element);
200        }
201    }