##### Coverage Report - org.apache.commons.configuration.CompositeConfiguration

Classes in this File | Line Coverage | Branch Coverage | Complexity

CompositeConfiguration

98% | 101/103

100% | 25/25

2.6;2,6

1

     /*

2

      * Licensed to the Apache Software Foundation (ASF) under one or more

3

      * contributor license agreements.  See the NOTICE file distributed with

4

      * this work for additional information regarding copyright ownership.

5

      * The ASF licenses this file to You under the Apache License, Version 2.0

6

      * (the "License"); you may not use this file except in compliance with

7

      * the License.  You may obtain a copy of the License at

8

      *

9

      *     http://www.apache.org/licenses/LICENSE-2.0

10

      *

11

      * Unless required by applicable law or agreed to in writing, software

12

      * distributed under the License is distributed on an "AS IS" BASIS,

13

      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

14

      * See the License for the specific language governing permissions and

15

      * limitations under the License.

16

      */

17

18

     package org.apache.commons.configuration;

19

20

     import java.util.ArrayList;

21

     import java.util.Collection;

22

     import java.util.Iterator;

23

     import java.util.LinkedList;

24

     import java.util.List;

25

26

     /**

27

      * This Configuration class allows you to add multiple different types of Configuration

28

      * to this CompositeConfiguration.  If you add Configuration1, and then Configuration2,

29

      * any properties shared will mean that Configuration1 will be returned.

30

      * You can add multiple different types or the same type of properties file.

31

      * If Configuration1 doesn't have the property, then Configuration2 will be checked.

32

      *

33

      * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>

34

      * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>

35

      * @version $Id: CompositeConfiguration.java 439648 2006-09-02 20:42:10Z oheger $

36

      */

37

     public class CompositeConfiguration extends AbstractConfiguration

38

     implements Cloneable

39

     {

40

         /** List holding all the configuration */

41

109

         private List configList = new LinkedList();

42

43

         /**

44

          * Configuration that holds in memory stuff.  Inserted as first so any

45

          * setProperty() override anything else added.

46

          */

47

         private Configuration inMemoryConfiguration;

48

49

         /**

50

          * Creates an empty CompositeConfiguration object which can then

51

          * be added some other Configuration files

52

          */

53

         public CompositeConfiguration()

54

104

         {

55

104

             clear();

56

104

         }

57

58

         /**

59

          * Creates a CompositeConfiguration object with a specified in memory

60

          * configuration. This configuration will store any changes made to

61

          * the CompositeConfiguration.

62

          *

63

          * @param inMemoryConfiguration the in memory configuration to use

64

          */

65

         public CompositeConfiguration(Configuration inMemoryConfiguration)

66

5

         {

67

5

             configList.clear();

68

5

             this.inMemoryConfiguration = inMemoryConfiguration;

69

5

             configList.add(inMemoryConfiguration);

70

5

         }

71

72

         /**

73

          * Create a CompositeConfiguration with an empty in memory configuration

74

          * and adds the collection of configurations specified.

75

          *

76

          * @param configurations the collection of configurations to add

77

          */

78

         public CompositeConfiguration(Collection configurations)

79

         {

80

1

             this(new BaseConfiguration(), configurations);

81

1

         }

82

83

         /**

84

          * Creates a CompositeConfiguration with a specified in memory

85

          * configuration, and then adds the given collection of configurations.

86

          *

87

          * @param inMemoryConfiguration the in memory configuration to use

88

          * @param configurations        the collection of configurations to add

89

          */

90

         public CompositeConfiguration(Configuration inMemoryConfiguration, Collection configurations)

91

         {

92

1

             this(inMemoryConfiguration);

93

94

1

             if (configurations != null)

95

             {

96

1

                 Iterator it = configurations.iterator();

97

5

                 while (it.hasNext())

98

                 {

99

3

                     addConfiguration((Configuration) it.next());

100

                 }

101

             }

102

1

         }

103

104

         /**

105

          * Add a configuration.

106

          *

107

          * @param config the configuration to add

108

          */

109

         public void addConfiguration(Configuration config)

110

         {

111

149

             if (!configList.contains(config))

112

             {

113

                 // As the inMemoryConfiguration contains all manually added keys,

114

                 // we must make sure that it is always last. "Normal", non composed

115

                 // configuration add their keys at the end of the configuration and

116

                 // we want to mimic this behaviour.

117

147

                 configList.add(configList.indexOf(inMemoryConfiguration), config);

118

119

147

                 if (config instanceof AbstractConfiguration)

120

                 {

121

147

                     ((AbstractConfiguration) config).setThrowExceptionOnMissing(isThrowExceptionOnMissing());

122

                 }

123

             }

124

149

         }

125

126

         /**

127

          * Remove a configuration. The in memory configuration cannot be removed.

128

          *

129

          * @param config The configuration to remove

130

          */

131

         public void removeConfiguration(Configuration config)

132

         {

133

             // Make sure that you can't remove the inMemoryConfiguration from

134

             // the CompositeConfiguration object

135

4

             if (!config.equals(inMemoryConfiguration))

136

             {

137

2

                 configList.remove(config);

138

             }

139

4

         }

140

141

         /**

142

          * Return the number of configurations.

143

          *

144

          * @return the number of configuration

145

          */

146

         public int getNumberOfConfigurations()

147

         {

148

31

             return configList.size();

149

         }

150

151

         /**

152

          * Remove all configuration reinitialize the in memory configuration.

153

          */

154

         public void clear()

155

         {

156

112

             configList.clear();

157

             // recreate the in memory configuration

158

112

             inMemoryConfiguration = new BaseConfiguration();

159

112

             ((BaseConfiguration) inMemoryConfiguration).setThrowExceptionOnMissing(isThrowExceptionOnMissing());

160

112

             configList.add(inMemoryConfiguration);

161

112

         }

162

163

         /**

164

          * Add this property to the inmemory Configuration.

165

          *

166

          * @param key The Key to add the property to.

167

          * @param token The Value to add.

168

          */

169

         protected void addPropertyDirect(String key, Object token)

170

         {

171

21

             inMemoryConfiguration.addProperty(key, token);

172

21

         }

173

174

         /**

175

          * Read property from underlying composite

176

          *

177

          * @param key key to use for mapping

178

          *

179

          * @return object associated with the given configuration key.

180

          */

181

         public Object getProperty(String key)

182

         {

183

122

             Configuration firstMatchingConfiguration = null;

184

334

             for (Iterator i = configList.iterator(); i.hasNext();)

185

             {

186

187

                 Configuration config = (Configuration) i.next();

187

187

                 if (config.containsKey(key))

188

                 {

189

97

                     firstMatchingConfiguration = config;

190

97

                     break;

191

                 }

192

             }

193

194

122

             if (firstMatchingConfiguration != null)

195

             {

196

97

                 return firstMatchingConfiguration.getProperty(key);

197

             }

198

             else

199

             {

200

25

                 return null;

201

             }

202

         }

203

204

         /**

205

          * {@inheritDoc}

206

          */

207

         public Iterator getKeys()

208

         {

209

14

             List keys = new ArrayList();

210

52

             for (Iterator i = configList.iterator(); i.hasNext();)

211

             {

212

24

                 Configuration config = (Configuration) i.next();

213

214

24

                 Iterator j = config.getKeys();

215

174

                 while (j.hasNext())

216

                 {

217

126

                     String key = (String) j.next();

218

126

                     if (!keys.contains(key))

219

                     {

220

125

                         keys.add(key);

221

                     }

222

                 }

223

             }

224

225

14

             return keys.iterator();

226

         }

227

228

         /**

229

          * {@inheritDoc}

230

          */

231

         public Iterator getKeys(String key)

232

         {

233

9

             List keys = new ArrayList();

234

40

             for (Iterator i = configList.iterator(); i.hasNext();)

235

             {

236

22

                 Configuration config = (Configuration) i.next();

237

238

22

                 Iterator j = config.getKeys(key);

239

240

                 while (j.hasNext())

240

                 {

241

196

                     String newKey = (String) j.next();

242

196

                     if (!keys.contains(newKey))

243

                     {

244

194

                         keys.add(newKey);

245

                     }

246

                 }

247

             }

248

249

9

             return keys.iterator();

250

         }

251

252

         /**

253

          * {@inheritDoc}

254

          */

255

         public boolean isEmpty()

256

         {

257

4

             boolean isEmpty = true;

258

8

             for (Iterator i = configList.iterator(); i.hasNext();)

259

             {

260

4

                 Configuration config = (Configuration) i.next();

261

4

                 if (!config.isEmpty())

262

                 {

263

4

                     return false;

264

                 }

265

             }

266

267

0

             return isEmpty;

268

         }

269

270

         /**

271

          * {@inheritDoc}

272

          */

273

         public void clearProperty(String key)

274

         {

275

60

             for (Iterator i = configList.iterator(); i.hasNext();)

276

             {

277

32

                 Configuration config = (Configuration) i.next();

278

32

                 config.clearProperty(key);

279

             }

280

14

         }

281

282

         /**

283

          * {@inheritDoc}

284

          */

285

         public boolean containsKey(String key)

286

         {

287

134

             for (Iterator i = configList.iterator(); i.hasNext();)

288

             {

289

70

                 Configuration config = (Configuration) i.next();

290

70

                 if (config.containsKey(key))

291

                 {

292

44

                     return true;

293

                 }

294

             }

295

10

             return false;

296

         }

297

298

         /**

299

          * {@inheritDoc}

300

          */

301

         public List getList(String key, List defaultValue)

302

         {

303

43

             List list = new ArrayList();

304

305

             // add all elements from the first configuration containing the requested key

306

43

             Iterator it = configList.iterator();

307

144

             while (it.hasNext() && list.isEmpty())

308

             {

309

58

                 Configuration config = (Configuration) it.next();

310

58

                 if (config != inMemoryConfiguration && config.containsKey(key))

311

                 {

312

31

                     list.addAll(config.getList(key));

313

                 }

314

             }

315

316

             // add all elements from the in memory configuration

317

43

             list.addAll(inMemoryConfiguration.getList(key));

318

319

43

             if (list.isEmpty())

320

             {

321

5

                 return defaultValue;

322

             }

323

324

38

             return list;

325

         }

326

327

         /**

328

          * {@inheritDoc}

329

          */

330

         public String[] getStringArray(String key)

331

         {

332

13

             List list = getList(key);

333

334

             // interpolate the strings

335

13

             String[] tokens = new String[list.size()];

336

337

33

             for (int i = 0; i < tokens.length; i++)

338

             {

339

20

                 tokens[i] = interpolate(String.valueOf(list.get(i)));

340

             }

341

342

13

             return tokens;

343

         }

344

345

         /**

346

          * Return the configuration at the specified index.

347

          *

348

          * @param index The index of the configuration to retrieve

349

          * @return the configuration at this index

350

          */

351

         public Configuration getConfiguration(int index)

352

         {

353

28

             return (Configuration) configList.get(index);

354

         }

355

356

         /**

357

          * Returns the &quot;in memory configuration&quot;. In this configuration

358

          * changes are stored.

359

          *

360

          * @return the in memory configuration

361

          */

362

         public Configuration getInMemoryConfiguration()

363

         {

364

7

             return inMemoryConfiguration;

365

         }

366

367

         /**

368

          * Returns a copy of this object. This implementation will create a deep

369

          * clone, i.e. all configurations contained in this composite will also be

370

          * cloned. This only works if all contained configurations support cloning;

371

          * otherwise a runtime exception will be thrown. Registered event handlers

372

          * won't get cloned.

373

          *

374

          * @return the copy

375

          * @since 1.3

376

          */

377

         public Object clone()

378

         {

379

             try

380

             {

381

3

                 CompositeConfiguration copy = (CompositeConfiguration) super

382

                         .clone();

383

3

                 copy.clearConfigurationListeners();

384

3

                 copy.configList = new LinkedList();

385

3

                 copy.inMemoryConfiguration = ConfigurationUtils

386

                         .cloneConfiguration(getInMemoryConfiguration());

387

3

                 copy.configList.add(copy.inMemoryConfiguration);

388

389

5

                 for (int i = 0; i < getNumberOfConfigurations(); i++)

390

                 {

391

3

                     Configuration config = getConfiguration(i);

392

3

                     if (config != getInMemoryConfiguration())

393

                     {

394

1

                         copy.addConfiguration(ConfigurationUtils

395

                                 .cloneConfiguration(config));

396

                     }

397

                 }

398

399

2

                 return copy;

400

             }

401

             catch (CloneNotSupportedException cnex)

402

             {

403

                 // cannot happen

404

0

                 throw new ConfigurationRuntimeException(cnex);

405

             }

406

         }

407

     }