001 /*
002 * Copyright 2002-2006 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.jdbc;
017
018 import java.io.IOException;
019 import java.util.HashMap;
020 import java.util.HashSet;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Map;
024 import java.util.Set;
025
026 import javax.sql.DataSource;
027
028 import org.springframework.jdbc.core.JdbcTemplate;
029 import org.springframework.richclient.settings.AbstractSettings;
030 import org.springframework.richclient.settings.Settings;
031
032 /**
033 *
034 * @author Peter De Bruycker
035 */
036 public class JdbcSettings extends AbstractSettings {
037 private DataSource dataSource;
038
039 private Integer id;
040 private String user;
041
042 private Map values = new HashMap();
043 private Set remove = new HashSet();
044 private Set add = new HashSet();
045 private Set update = new HashSet();
046
047 private String[] childKeys;
048
049 public JdbcSettings( DataSource ds, String user, Integer id, String key ) {
050 this( null, ds, user, id, key );
051 }
052
053 public JdbcSettings( JdbcSettings parent, DataSource ds, String user, Integer id, String key ) {
054 super( parent, key );
055 this.id = id;
056
057 // TODO assert dataSource not null
058 dataSource = ds;
059
060 // TODO assert user not empty
061 this.user = user;
062 }
063
064 protected boolean internalContains( String key ) {
065 return values.containsKey( key );
066 }
067
068 protected String[] internalGetChildSettings() {
069 if( childKeys == null ) {
070 loadChildKeys();
071 }
072 return childKeys;
073 }
074
075 protected Settings internalCreateChild( String key ) {
076 return new JdbcSettings( this, dataSource, user, null, key );
077 }
078
079 protected void internalSet( String key, String value ) {
080 boolean isNew = !values.containsKey( key ) || add.contains( key );
081
082 values.put( key, value );
083
084 if( isNew ) {
085 add.add( key );
086 } else {
087 update.add( key );
088 }
089 remove.remove( key );
090 }
091
092 protected String internalGet( String key ) {
093 return (String) values.get( key );
094 }
095
096 protected void internalRemove( String key ) {
097 values.remove( key );
098
099 if( !add.contains( key ) ) {
100 remove.add( key );
101 }
102
103 update.remove( key );
104 add.remove( key );
105 }
106
107 public String[] getKeys() {
108 return (String[]) values.keySet().toArray( new String[0] );
109 }
110
111 public Integer getId() {
112 return id;
113 }
114
115 public void save() throws IOException {
116 if( getParent() != null ) {
117 getParent().save();
118 }
119
120 JdbcTemplate template = new JdbcTemplate( dataSource );
121
122 // if this is a new node, insert it
123 if( id == null ) {
124 JdbcSettings parent = (JdbcSettings) getParent();
125 template.update( "INSERT INTO SETTINGS (KEY, PARENT, USER) VALUES (?, ?, ?)", new Object[] { getName(),
126 parent == null ? null : parent.getId(), user } );
127 id = Integer.valueOf( template.queryForInt( "SELECT MAX(ID) FROM SETTINGS" ) );
128 } else {
129 for( Iterator iter = remove.iterator(); iter.hasNext(); ) {
130 String key = (String) iter.next();
131 template.update( "REMOVE FROM SETTINGS_VALUES WHERE SETTINGS_ID=? AND KEY=?", new Object[] { id, key } );
132 }
133 for( Iterator iter = update.iterator(); iter.hasNext(); ) {
134 String key = (String) iter.next();
135 template.update( "UPDATE SETTINGS_VALUES SET VALUE=? WHERE SETTINGS_ID=? AND KEY=?", new Object[] {
136 values.get( key ), id, key } );
137 }
138 }
139
140 for( Iterator iter = add.iterator(); iter.hasNext(); ) {
141 String key = (String) iter.next();
142 template.update( "INSERT INTO SETTINGS_VALUES (SETTINGS_ID, KEY, VALUE) VALUES (?, ?, ?)", new Object[] {
143 id, key, values.get( key ) } );
144 }
145
146 remove.clear();
147 update.clear();
148 add.clear();
149 }
150
151 public void load() throws IOException {
152 if( id == null ) {
153 return;
154 }
155
156 JdbcTemplate template = new JdbcTemplate( dataSource );
157 List entries = template.queryForList( "SELECT KEY, VALUE FROM SETTINGS_VALUES WHERE SETTINGS_ID=?",
158 new Object[] { id } );
159 for( Iterator iter = entries.iterator(); iter.hasNext(); ) {
160 Map entry = (Map) iter.next();
161 values.put(entry.get( "KEY" ), entry.get( "VALUE" ));
162 }
163 }
164
165 private void loadChildKeys() {
166 JdbcTemplate template = new JdbcTemplate( dataSource );
167 List keys = template.queryForList( "SELECT KEY FROM SETTINGS WHERE PARENT=" + id, String.class );
168
169 childKeys = (String[]) keys.toArray( new String[keys.size()] );
170 }
171
172 public String getUser() {
173 return user;
174 }
175
176 public void internalRemoveSettings() {
177 if( id != null ) {
178 // first delete all children
179 for( int i = 0; i < childKeys.length; i++ ) {
180 getSettings(childKeys[i]).removeSettings();
181 }
182
183 // now delete all values
184 JdbcTemplate template = new JdbcTemplate( dataSource );
185 template.update( "DELETE FROM SETTINGS_VALUES WHERE SETTINGS_ID=?", new Object[] { id } );
186
187 // now delete our own record
188 template.update( "DELETE FROM SETTINGS WHERE ID=?", new Object[] { id } );
189
190 id = null;
191 }
192
193 values.clear();
194 remove.clear();
195 add.clear();
196 update.clear();
197 }
198 }