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 }