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 }