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

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

AbstractConfiguration

94% | 223/236

97% | 63/65

2.9482758620689653;2,948

AbstractConfiguration$1

100% | 3/3

100% | 1/1

2.9482758620689653;2,948

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.math.BigDecimal;

21

     import java.math.BigInteger;

22

     import java.util.ArrayList;

23

     import java.util.Iterator;

24

     import java.util.List;

25

     import java.util.NoSuchElementException;

26

     import java.util.Properties;

27

28

     import org.apache.commons.collections.Predicate;

29

     import org.apache.commons.collections.iterators.FilterIterator;

30

     import org.apache.commons.configuration.event.EventSource;

31

     import org.apache.commons.lang.BooleanUtils;

32

33

     /**

34

      * <p>Abstract configuration class. Provides basic functionality but does not

35

      * store any data.</p>

36

      * <p>If you want to write your own Configuration class then you should

37

      * implement only abstract methods from this class. A lot of functionality

38

      * needed by typical implementations of the <code>Configuration</conde>

39

      * interface is already provided by this base class. Following is a list of

40

      * feauters implemented here:

41

      * <ul><li>Data conversion support. The various data types required by the

42

      * <code>Configuration</code> interface are already handled by this base class.

43

      * A concrete sub class only needs to provide a generic <code>getProperty()</code>

44

      * method.</li>

45

      * <li>Support for variable interpolation. Property values containing special

46

      * variable tokens (like <code>${var}</code>) will be replaced by their

47

      * corresponding values.</li>

48

      * <li>Support for string lists. The values of properties to be added to this

49

      * configuration are checked whether they contain a list delimiter character. If

50

      * this is the case and if list splitting is enabled, the string is splitted and

51

      * multiple values are added for this property.</li>

52

      * <li>Basic event support. Whenever this configuration is modified registered

53

      * event listeners are notified. Refer to the various <code>EVENT_XXX</code>

54

      * constants to get an impression about which event types are supported.</li>

55

      * </ul></p>

56

      *

57

      * @author <a href="mailto:ksh@scand.com">Konstantin Shaposhnikov </a>

58

      * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger </a>

59

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

60

      * @version $Id: AbstractConfiguration.java,v 1.29 2004/12/02 22:05:52 ebourg

61

      * Exp $

62

      */

63

4494

     public abstract class AbstractConfiguration extends EventSource implements Configuration

64

     {

65

         /** Constant for the add property event type.*/

66

         public static final int EVENT_ADD_PROPERTY = 1;

67

68

         /** Constant for the clear property event type.*/

69

         public static final int EVENT_CLEAR_PROPERTY = 2;

70

71

         /** Constant for the set property event type.*/

72

         public static final int EVENT_SET_PROPERTY = 3;

73

74

         /** Constant for the clear configuration event type.*/

75

         public static final int EVENT_CLEAR = 4;

76

77

         /** start token */

78

         protected static final String START_TOKEN = "${";

79

80

         /** end token */

81

         protected static final String END_TOKEN = "}";

82

83

         /** The default value for listDelimiter */

84

54

         private static char defaultListDelimiter = ',';

85

86

         /** Delimiter used to convert single values to lists */

87

2247

         private char listDelimiter = defaultListDelimiter;

88

89

         /**

90

          * When set to true the given configuration delimiter will not be used

91

          * while parsing for this configuration.

92

          */

93

         private boolean delimiterParsingDisabled;

94

95

         /**

96

          * Whether the configuration should throw NoSuchElementExceptions or simply

97

          * return null when a property does not exist. Defaults to return null.

98

          */

99

         private boolean throwExceptionOnMissing;

100

101

         /**

102

          * For configurations extending AbstractConfiguration, allow them to change

103

          * the listDelimiter from the default comma (","). This value will be used

104

          * only when creating new configurations. Those already created will not be

105

          * affected by this change

106

          *

107

          * @param delimiter The new listDelimiter

108

          */

109

         public static void setDefaultListDelimiter(char delimiter)

110

         {

111

2

             AbstractConfiguration.defaultListDelimiter = delimiter;

112

2

         }

113

114

         /**

115

          * Sets the default list delimiter.

116

          *

117

          * @param delimiter the delimiter character

118

          * @deprecated Use AbstractConfiguration.setDefaultListDelimiter(char)

119

          * instead

120

          */

121

         public static void setDelimiter(char delimiter)

122

         {

123

0

             setDefaultListDelimiter(delimiter);

124

0

         }

125

126

         /**

127

          * Retrieve the current delimiter. By default this is a comma (",").

128

          *

129

          * @return The delimiter in use

130

          */

131

         public static char getDefaultListDelimiter()

132

         {

133

50

             return AbstractConfiguration.defaultListDelimiter;

134

         }

135

136

         /**

137

          * Returns the default list delimiter.

138

          *

139

          * @return the default list delimiter

140

          * @deprecated Use AbstractConfiguration.getDefaultListDelimiter() instead

141

          */

142

         public static char getDelimiter()

143

         {

144

0

             return getDefaultListDelimiter();

145

         }

146

147

         /**

148

          * Change the list delimiter for this configuration.

149

          *

150

          * Note: this change will only be effective for new parsings. If you

151

          * want it to take effect for all loaded properties use the no arg constructor

152

          * and call this method before setting the source.

153

          *

154

          * @param listDelimiter The new listDelimiter

155

          */

156

         public void setListDelimiter(char listDelimiter)

157

         {

158

194

             this.listDelimiter = listDelimiter;

159

194

         }

160

161

         /**

162

          * Retrieve the delimiter for this configuration. The default

163

          * is the value of defaultListDelimiter.

164

          *

165

          * @return The listDelimiter in use

166

          */

167

         public char getListDelimiter()

168

         {

169

46862

             return listDelimiter;

170

         }

171

172

         /**

173

          * Determine if this configuration is using delimiters when parsing

174

          * property values to convert them to lists of values. Defaults to false

175

          * @return true if delimiters are not being used

176

          */

177

         public boolean isDelimiterParsingDisabled()

178

         {

179

45973

             return delimiterParsingDisabled;

180

         }

181

182

         /**

183

          * Set whether this configuration should use delimiters when parsing

184

          * property values to convert them to lists of values. By default delimiter

185

          * parsing is enabled

186

          *

187

          * Note: this change will only be effective for new parsings. If you

188

          * want it to take effect for all loaded properties use the no arg constructor

189

          * and call this method before setting source.

190

          * @param delimiterParsingDisabled a flag whether delimiter parsing should

191

          * be disabled

192

          */

193

         public void setDelimiterParsingDisabled(boolean delimiterParsingDisabled)

194

         {

195

197

             this.delimiterParsingDisabled = delimiterParsingDisabled;

196

197

         }

197

198

         /**

199

          * Allows to set the <code>throwExceptionOnMissing</code> flag. This

200

          * flag controls the behavior of property getter methods that return

201

          * objects if the requested property is missing. If the flag is set to

202

          * <b>false</b> (which is the default value), these methods will return

203

          * <b>null</b>. If set to <b>true</b>, they will throw a

204

          * <code>NoSuchElementException</code> exception. Note that getter methods

205

          * for primitive data types are not affected by this flag.

206

          *

207

          * @param throwExceptionOnMissing The new value for the property

208

          */

209

         public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)

210

         {

211

683

             this.throwExceptionOnMissing = throwExceptionOnMissing;

212

683

         }

213

214

         /**

215

          * Returns true if missing values throw Exceptions.

216

          *

217

          * @return true if missing values throw Exceptions

218

          */

219

         public boolean isThrowExceptionOnMissing()

220

         {

221

662

             return throwExceptionOnMissing;

222

         }

223

224

         /**

225

          * {@inheritDoc}

226

          */

227

         public void addProperty(String key, Object value)

228

         {

229

36265

             fireEvent(EVENT_ADD_PROPERTY, key, value, true);

230

231

36265

             if (!isDelimiterParsingDisabled())

232

             {

233

36213

                 Iterator it = PropertyConverter.toIterator(value, getListDelimiter());

234

112164

                 while (it.hasNext())

235

                 {

236

39739

                     addPropertyDirect(key, it.next());

237

                 }

238

             }

239

             else

240

             {

241

52

                 addPropertyDirect(key, value);

242

             }

243

244

36264

             fireEvent(EVENT_ADD_PROPERTY, key, value, false);

245

36264

         }

246

247

         /**

248

          * Adds a key/value pair to the Configuration. Override this method to

249

          * provide write acces to underlying Configuration store.

250

          *

251

          * @param key key to use for mapping

252

          * @param value object to store

253

          */

254

         protected abstract void addPropertyDirect(String key, Object value);

255

256

         /**

257

          * interpolate key names to handle ${key} stuff

258

          *

259

          * @param base string to interpolate

260

          *

261

          * @return returns the key name with the ${key} substituted

262

          */

263

         protected String interpolate(String base)

264

         {

265

682

             Object result = interpolate((Object) base);

266

680

             return (result == null) ? null : result.toString();

267

         }

268

269

         /**

270

          * Returns the interpolated value. Non String values are returned without change.

271

          *

272

          * @param value the value to interpolate

273

          *

274

          * @return returns the value with variables substituted

275

          */

276

         protected Object interpolate(Object value)

277

         {

278

2093

             return PropertyConverter.interpolate(value, this);

279

         }

280

281

         /**

282

          * Recursive handler for multple levels of interpolation.

283

          *

284

          * When called the first time, priorVariables should be null.

285

          *

286

          * @param base string with the ${key} variables

287

          * @param priorVariables serves two purposes: to allow checking for loops,

288

          * and creating a meaningful exception message should a loop occur. It's

289

          * 0'th element will be set to the value of base from the first call. All

290

          * subsequent interpolated variables are added afterward.

291

          *

292

          * @return the string with the interpolation taken care of

293

          * @deprecated Interpolation is now handled by

294

          * <code>{@link PropertyConverter}</code>; this method will no longer be

295

          * called

296

          */

297

         protected String interpolateHelper(String base, List priorVariables)

298

         {

299

0

             return base; // just a dummy implementation

300

         }

301

302

         /**

303

          * {@inheritDoc}

304

          */

305

         public Configuration subset(String prefix)

306

         {

307

40

             return new SubsetConfiguration(this, prefix, ".");

308

         }

309

310

         /**

311

          * {@inheritDoc}

312

          */

313

         public abstract boolean isEmpty();

314

315

         /**

316

          * {@inheritDoc}

317

          */

318

         public abstract boolean containsKey(String key);

319

320

         /**

321

          * {@inheritDoc}

322

          */

323

         public void setProperty(String key, Object value)

324

         {

325

781

             fireEvent(EVENT_SET_PROPERTY, key, value, true);

326

781

             setDetailEvents(false);

327

             try

328

             {

329

781

                 clearProperty(key);

330

781

                 addProperty(key, value);

331

781

             }

332

             finally

333

             {

334

0

                 setDetailEvents(true);

335

             }

336

781

             fireEvent(EVENT_SET_PROPERTY, key, value, false);

337

781

         }

338

339

         /**

340

          * Removes the specified property from this configuration. This

341

          * implementation performs some preparations and then delegates to

342

          * <code>clearPropertyDirect()</code>, which will do the real work.

343

          *

344

          * @param key the key to be removed

345

          */

346

         public void clearProperty(String key)

347

         {

348

816

             fireEvent(EVENT_CLEAR_PROPERTY, key, null, true);

349

816

             clearPropertyDirect(key);

350

816

             fireEvent(EVENT_CLEAR_PROPERTY, key, null, false);

351

816

         }

352

353

         /**

354

          * Removes the specified property from this configuration. This method is

355

          * called by <code>clearProperty()</code> after it has done some

356

          * preparations. It should be overriden in sub classes. This base

357

          * implementation is just left empty.

358

          *

359

          * @param key the key to be removed

360

          */

361

         protected void clearPropertyDirect(String key)

362

         {

363

             // override in sub classes

364

0

         }

365

366

         /**

367

          * {@inheritDoc}

368

          */

369

         public void clear()

370

         {

371

15

             fireEvent(EVENT_CLEAR, null, null, true);

372

15

             setDetailEvents(false);

373

             try

374

             {

375

15

                 Iterator it = getKeys();

376

213

                 while (it.hasNext())

377

                 {

378

183

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

379

183

                     it.remove();

380

381

183

                     if (containsKey(key))

382

                     {

383

                         // workaround for Iterators that do not remove the property on calling remove()

384

180

                         clearProperty(key);

385

                     }

386

                 }

387

15

             }

388

             finally

389

             {

390

0

                 setDetailEvents(true);

391

             }

392

15

             fireEvent(EVENT_CLEAR, null, null, false);

393

15

         }

394

395

         /**

396

          * {@inheritDoc}

397

          */

398

         public abstract Iterator getKeys();

399

400

         /**

401

          * {@inheritDoc}

402

          */

403

         public Iterator getKeys(final String prefix)

404

         {

405

37

             return new FilterIterator(getKeys(), new Predicate()

406

             {

407

37

                 public boolean evaluate(Object obj)

408

                 {

409

426

                     String key = (String) obj;

410

426

                     return key.startsWith(prefix + ".") || key.equals(prefix);

411

                 }

412

             });

413

         }

414

415

         /**

416

          * {@inheritDoc}

417

          */

418

         public Properties getProperties(String key)

419

         {

420

4

             return getProperties(key, null);

421

         }

422

423

         /**

424

          * Get a list of properties associated with the given configuration key.

425

          *

426

          * @param key The configuration key.

427

          * @param defaults Any default values for the returned

428

          * <code>Properties</code> object. Ignored if <code>null</code>.

429

          *

430

          * @return The associated properties if key is found.

431

          *

432

          * @throws ConversionException is thrown if the key maps to an object that

433

          * is not a String/List of Strings.

434

          *

435

          * @throws IllegalArgumentException if one of the tokens is malformed (does

436

          * not contain an equals sign).

437

          */

438

         public Properties getProperties(String key, Properties defaults)

439

         {

440

             /*

441

              * Grab an array of the tokens for this key.

442

              */

443

4

             String[] tokens = getStringArray(key);

444

445

             /*

446

              * Each token is of the form 'key=value'.

447

              */

448

4

             Properties props = defaults == null ? new Properties() : new Properties(defaults);

449

10

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

450

             {

451

8

                 String token = tokens[i];

452

8

                 int equalSign = token.indexOf('=');

453

8

                 if (equalSign > 0)

454

                 {

455

6

                     String pkey = token.substring(0, equalSign).trim();

456

6

                     String pvalue = token.substring(equalSign + 1).trim();

457

6

                     props.put(pkey, pvalue);

458

                 }

459

2

                 else if (tokens.length == 1 && "".equals(token))

460

                 {

461

                     // Semantically equivalent to an empty Properties

462

                     // object.

463

2

                     break;

464

                 }

465

                 else

466

                 {

467

0

                     throw new IllegalArgumentException('\'' + token + "' does not contain an equals sign");

468

                 }

469

             }

470

4

             return props;

471

         }

472

473

         /**

474

          * {@inheritDoc}

475

          * @see PropertyConverter#toBoolean(Object)

476

          */

477

         public boolean getBoolean(String key)

478

         {

479

58

             Boolean b = getBoolean(key, null);

480

56

             if (b != null)

481

             {

482

54

                 return b.booleanValue();

483

             }

484

             else

485

             {

486

2

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

487

             }

488

         }

489

490

         /**

491

          * {@inheritDoc}

492

          * @see PropertyConverter#toBoolean(Object)

493

          */

494

         public boolean getBoolean(String key, boolean defaultValue)

495

         {

496

11

             return getBoolean(key, BooleanUtils.toBooleanObject(defaultValue)).booleanValue();

497

         }

498

499

         /**

500

          * Obtains the value of the specified key and tries to convert it into a

501

          * <code>Boolean</code> object. If the property has no value, the passed

502

          * in default value will be used.

503

          *

504

          * @param key the key of the property

505

          * @param defaultValue the default value

506

          * @return the value of this key converted to a <code>Boolean</code>

507

          * @throws ConversionException if the value cannot be converted to a

508

          * <code>Boolean</code>

509

          * @see PropertyConverter#toBoolean(Object)

510

          */

511

         public Boolean getBoolean(String key, Boolean defaultValue)

512

         {

513

100

             Object value = resolveContainerStore(key);

514

515

100

             if (value == null)

516

             {

517

27

                 return defaultValue;

518

             }

519

             else

520

             {

521

                 try

522

                 {

523

73

                     return PropertyConverter.toBoolean(interpolate(value));

524

                 }

525

                 catch (ConversionException e)

526

                 {

527

3

                     throw new ConversionException('\'' + key + "' doesn't map to a Boolean object", e);

528

                 }

529

             }

530

         }

531

532

         /**

533

          * {@inheritDoc}

534

          */

535

         public byte getByte(String key)

536

         {

537

15

             Byte b = getByte(key, null);

538

13

             if (b != null)

539

             {

540

11

                 return b.byteValue();

541

             }

542

             else

543

             {

544

2

                 throw new NoSuchElementException('\'' + key + " doesn't map to an existing object");

545

             }

546

         }

547

548

         /**

549

          * {@inheritDoc}

550

          */

551

         public byte getByte(String key, byte defaultValue)

552

         {

553

4

             return getByte(key, new Byte(defaultValue)).byteValue();

554

         }

555

556

         /**

557

          * {@inheritDoc}

558

          */

559

         public Byte getByte(String key, Byte defaultValue)

560

         {

561

22

             Object value = resolveContainerStore(key);

562

563

22

             if (value == null)

564

             {

565

4

                 return defaultValue;

566

             }

567

             else

568

             {

569

                 try

570

                 {

571

18

                     return PropertyConverter.toByte(interpolate(value));

572

                 }

573

                 catch (ConversionException e)

574

                 {

575

2

                     throw new ConversionException('\'' + key + "' doesn't map to a Byte object", e);

576

                 }

577

             }

578

         }

579

580

         /**

581

          * {@inheritDoc}

582

          */

583

         public double getDouble(String key)

584

         {

585

15

             Double d = getDouble(key, null);

586

13

             if (d != null)

587

             {

588

11

                 return d.doubleValue();

589

             }

590

             else

591

             {

592

2

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

593

             }

594

         }

595

596

         /**

597

          * {@inheritDoc}

598

          */

599

         public double getDouble(String key, double defaultValue)

600

         {

601

11

             return getDouble(key, new Double(defaultValue)).doubleValue();

602

         }

603

604

         /**

605

          * {@inheritDoc}

606

          */

607

         public Double getDouble(String key, Double defaultValue)

608

         {

609

29

             Object value = resolveContainerStore(key);

610

611

29

             if (value == null)

612

             {

613

11

                 return defaultValue;

614

             }

615

             else

616

             {

617

                 try

618

                 {

619

18

                     return PropertyConverter.toDouble(interpolate(value));

620

                 }

621

                 catch (ConversionException e)

622

                 {

623

2

                     throw new ConversionException('\'' + key + "' doesn't map to a Double object", e);

624

                 }

625

             }

626

         }

627

628

         /**

629

          * {@inheritDoc}

630

          */

631

         public float getFloat(String key)

632

         {

633

14

             Float f = getFloat(key, null);

634

12

             if (f != null)

635

             {

636

10

                 return f.floatValue();

637

             }

638

             else

639

             {

640

2

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

641

             }

642

         }

643

644

         /**

645

          * {@inheritDoc}

646

          */

647

         public float getFloat(String key, float defaultValue)

648

         {

649

7

             return getFloat(key, new Float(defaultValue)).floatValue();

650

         }

651

652

         /**

653

          * {@inheritDoc}

654

          */

655

         public Float getFloat(String key, Float defaultValue)

656

         {

657

24

             Object value = resolveContainerStore(key);

658

659

24

             if (value == null)

660

             {

661

7

                 return defaultValue;

662

             }

663

             else

664

             {

665

                 try

666

                 {

667

17

                     return PropertyConverter.toFloat(interpolate(value));

668

                 }

669

                 catch (ConversionException e)

670

                 {

671

2

                     throw new ConversionException('\'' + key + "' doesn't map to a Float object", e);

672

                 }

673

             }

674

         }

675

676

         /**

677

          * {@inheritDoc}

678

          */

679

         public int getInt(String key)

680

         {

681

39

             Integer i = getInteger(key, null);

682

39

             if (i != null)

683

             {

684

39

                 return i.intValue();

685

             }

686

             else

687

             {

688

0

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

689

             }

690

         }

691

692

         /**

693

          * {@inheritDoc}

694

          */

695

         public int getInt(String key, int defaultValue)

696

         {

697

3

             Integer i = getInteger(key, null);

698

699

3

             if (i == null)

700

             {

701

3

                 return defaultValue;

702

             }

703

704

0

             return i.intValue();

705

         }

706

707

         /**

708

          * {@inheritDoc}

709

          */

710

         public Integer getInteger(String key, Integer defaultValue)

711

         {

712

43

             Object value = resolveContainerStore(key);

713

714

43

             if (value == null)

715

             {

716

3

                 return defaultValue;

717

             }

718

             else

719

             {

720

                 try

721

                 {

722

40

                     return PropertyConverter.toInteger(interpolate(value));

723

                 }

724

                 catch (ConversionException e)

725

                 {

726

0

                     throw new ConversionException('\'' + key + "' doesn't map to an Integer object", e);

727

                 }

728

             }

729

         }

730

731

         /**

732

          * {@inheritDoc}

733

          */

734

         public long getLong(String key)

735

         {

736

15

             Long l = getLong(key, null);

737

13

             if (l != null)

738

             {

739

11

                 return l.longValue();

740

             }

741

             else

742

             {

743

2

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

744

             }

745

         }

746

747

         /**

748

          * {@inheritDoc}

749

          */

750

         public long getLong(String key, long defaultValue)

751

         {

752

7

             return getLong(key, new Long(defaultValue)).longValue();

753

         }

754

755

         /**

756

          * {@inheritDoc}

757

          */

758

         public Long getLong(String key, Long defaultValue)

759

         {

760

26

             Object value = resolveContainerStore(key);

761

762

26

             if (value == null)

763

             {

764

7

                 return defaultValue;

765

             }

766

             else

767

             {

768

                 try

769

                 {

770

19

                     return PropertyConverter.toLong(interpolate(value));

771

                 }

772

                 catch (ConversionException e)

773

                 {

774

2

                     throw new ConversionException('\'' + key + "' doesn't map to a Long object", e);

775

                 }

776

             }

777

         }

778

779

         /**

780

          * {@inheritDoc}

781

          */

782

         public short getShort(String key)

783

         {

784

17

             Short s = getShort(key, null);

785

15

             if (s != null)

786

             {

787

13

                 return s.shortValue();

788

             }

789

             else

790

             {

791

2

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

792

             }

793

         }

794

795

         /**

796

          * {@inheritDoc}

797

          */

798

         public short getShort(String key, short defaultValue)

799

         {

800

7

             return getShort(key, new Short(defaultValue)).shortValue();

801

         }

802

803

         /**

804

          * {@inheritDoc}

805

          */

806

         public Short getShort(String key, Short defaultValue)

807

         {

808

31

             Object value = resolveContainerStore(key);

809

810

31

             if (value == null)

811

             {

812

9

                 return defaultValue;

813

             }

814

             else

815

             {

816

                 try

817

                 {

818

22

                     return PropertyConverter.toShort(interpolate(value));

819

                 }

820

                 catch (ConversionException e)

821

                 {

822

2

                     throw new ConversionException('\'' + key + "' doesn't map to a Short object", e);

823

                 }

824

             }

825

         }

826

827

         /**

828

          * {@inheritDoc}

829

          */

830

         public BigDecimal getBigDecimal(String key)

831

         {

832

7

             BigDecimal number = getBigDecimal(key, null);

833

5

             if (number != null)

834

             {

835

3

                 return number;

836

             }

837

2

             else if (isThrowExceptionOnMissing())

838

             {

839

1

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

840

             }

841

             else

842

             {

843

1

                 return null;

844

             }

845

         }

846

847

         /**

848

          * {@inheritDoc}

849

          */

850

         public BigDecimal getBigDecimal(String key, BigDecimal defaultValue)

851

         {

852

12

             Object value = resolveContainerStore(key);

853

854

12

             if (value == null)

855

             {

856

4

                 return defaultValue;

857

             }

858

             else

859

             {

860

                 try

861

                 {

862

8

                     return PropertyConverter.toBigDecimal(interpolate(value));

863

                 }

864

                 catch (ConversionException e)

865

                 {

866

2

                     throw new ConversionException('\'' + key + "' doesn't map to a BigDecimal object", e);

867

                 }

868

             }

869

         }

870

871

         /**

872

          * {@inheritDoc}

873

          */

874

         public BigInteger getBigInteger(String key)

875

         {

876

8

             BigInteger number = getBigInteger(key, null);

877

6

             if (number != null)

878

             {

879

4

                 return number;

880

             }

881

2

             else if (isThrowExceptionOnMissing())

882

             {

883

1

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

884

             }

885

             else

886

             {

887

1

                 return null;

888

             }

889

         }

890

891

         /**

892

          * {@inheritDoc}

893

          */

894

         public BigInteger getBigInteger(String key, BigInteger defaultValue)

895

         {

896

13

             Object value = resolveContainerStore(key);

897

898

13

             if (value == null)

899

             {

900

4

                 return defaultValue;

901

             }

902

             else

903

             {

904

                 try

905

                 {

906

9

                     return PropertyConverter.toBigInteger(interpolate(value));

907

                 }

908

                 catch (ConversionException e)

909

                 {

910

2

                     throw new ConversionException('\'' + key + "' doesn't map to a BigDecimal object", e);

911

                 }

912

             }

913

         }

914

915

         /**

916

          * {@inheritDoc}

917

          */

918

         public String getString(String key)

919

         {

920

511

             String s = getString(key, null);

921

509

             if (s != null)

922

             {

923

309

                 return s;

924

             }

925

200

             else if (isThrowExceptionOnMissing())

926

             {

927

7

                 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");

928

             }

929

             else

930

             {

931

193

                 return null;

932

             }

933

         }

934

935

         /**

936

          * {@inheritDoc}

937

          */

938

         public String getString(String key, String defaultValue)

939

         {

940

587

             Object value = resolveContainerStore(key);

941

942

587

             if (value instanceof String)

943

             {

944

379

                 return interpolate((String) value);

945

             }

946

208

             else if (value == null)

947

             {

948

208

                 return interpolate(defaultValue);

949

             }

950

             else

951

             {

952

0

                 throw new ConversionException('\'' + key + "' doesn't map to a String object");

953

             }

954

         }

955

956

         /**

957

          * {@inheritDoc}

958

          */

959

         public String[] getStringArray(String key)

960

         {

961

18

             Object value = getProperty(key);

962

963

             String[] array;

964

965

18

             if (value instanceof String)

966

             {

967

10

                 array = new String[1];

968

969

10

                 array[0] = interpolate((String) value);

970

             }

971

8

             else if (value instanceof List)

972

             {

973

6

                 List list = (List) value;

974

6

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

975

976

22

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

977

                 {

978

16

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

979

                 }

980

             }

981

2

             else if (value == null)

982

             {

983

2

                 array = new String[0];

984

             }

985

             else

986

             {

987

0

                 throw new ConversionException('\'' + key + "' doesn't map to a String/List object");

988

             }

989

18

             return array;

990

         }

991

992

         /**

993

          * {@inheritDoc}

994

          */

995

         public List getList(String key)

996

         {

997

247

             return getList(key, new ArrayList());

998

         }

999

1000

         /**

1001

          * {@inheritDoc}

1002

          */

1003

         public List getList(String key, List defaultValue)

1004

         {

1005

207

             Object value = getProperty(key);

1006

             List list;

1007

1008

207

             if (value instanceof String)

1009

             {

1010

49

                 list = new ArrayList(1);

1011

49

                 list.add(interpolate((String) value));

1012

             }

1013

158

             else if (value instanceof List)

1014

             {

1015

106

                 list = new ArrayList();

1016

106

                 List l = (List) value;

1017

1018

                 // add the interpolated elements in the new list

1019

106

                 Iterator it = l.iterator();

1020

581

                 while (it.hasNext())

1021

                 {

1022

369

                     list.add(interpolate(it.next()));

1023

                 }

1024

1025

             }

1026

52

             else if (value == null)

1027

             {

1028

51

                 list = defaultValue;

1029

             }

1030

             else

1031

             {

1032

1

                 throw new ConversionException('\'' + key + "' doesn't map to a List object: " + value + ", a "

1033

                         + value.getClass().getName());

1034

             }

1035

206

             return list;

1036

         }

1037

1038

         /**

1039

          * Returns an object from the store described by the key. If the value is a

1040

          * List object, replace it with the first object in the list.

1041

          *

1042

          * @param key The property key.

1043

          *

1044

          * @return value Value, transparently resolving a possible List dependency.

1045

          */

1046

         protected Object resolveContainerStore(String key)

1047

         {

1048

1030

             Object value = getProperty(key);

1049

1030

             if (value != null)

1050

             {

1051

733

                 if (value instanceof List)

1052

                 {

1053

11

                     List list = (List) value;

1054

11

                     value = list.isEmpty() ? null : list.get(0);

1055

                 }

1056

722

                 else if (value instanceof Object[])

1057

                 {

1058

1

                     Object[] array = (Object[]) value;

1059

1

                     value = array.length == 0 ? null : array[0];

1060

                 }

1061

721

                 else if (value instanceof boolean[])

1062

                 {

1063

1

                     boolean[] array = (boolean[]) value;

1064

1

                     value = array.length == 0 ? null : array[0] ? Boolean.TRUE : Boolean.FALSE;

1065

                 }

1066

720

                 else if (value instanceof byte[])

1067

                 {

1068

1

                     byte[] array = (byte[]) value;

1069

1

                     value = array.length == 0 ? null : new Byte(array[0]);

1070

                 }

1071

719

                 else if (value instanceof short[])

1072

                 {

1073

1

                     short[] array = (short[]) value;

1074

1

                     value = array.length == 0 ? null : new Short(array[0]);

1075

                 }

1076

718

                 else if (value instanceof int[])

1077

                 {

1078

1

                     int[] array = (int[]) value;

1079

1

                     value = array.length == 0 ? null : new Integer(array[0]);

1080

                 }

1081

717

                 else if (value instanceof long[])

1082

                 {

1083

1

                     long[] array = (long[]) value;

1084

1

                     value = array.length == 0 ? null : new Long(array[0]);

1085

                 }

1086

716

                 else if (value instanceof float[])

1087

                 {

1088

1

                     float[] array = (float[]) value;

1089

1

                     value = array.length == 0 ? null : new Float(array[0]);

1090

                 }

1091

715

                 else if (value instanceof double[])

1092

                 {

1093

1

                     double[] array = (double[]) value;

1094

1

                     value = array.length == 0 ? null : new Double(array[0]);

1095

                 }

1096

             }

1097

1098

1030

             return value;

1099

         }

1100

1101

     }