View Javadoc

1   /*
2    * Copyright 2005,2009 Ivan SZKIBA
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.ini4j.tutorial;
17  
18  import org.ini4j.Options;
19  
20  import org.ini4j.sample.Dwarf;
21  
22  import org.ini4j.test.DwarfsData;
23  import org.ini4j.test.Helper;
24  
25  import static org.junit.Assert.*;
26  
27  import java.io.File;
28  import java.io.FileReader;
29  import java.io.IOException;
30  
31  import java.util.Set;
32  
33  //<editor-fold defaultstate="collapsed" desc="apt documentation">
34  //|
35  //|                ----------------
36  //|                Options Tutorial
37  //|
38  //|Options Tutorial - java.util.Properties replacement
39  //|
40  //| Options (org.ini4j.Options) is a java.util.Properties replacement with
41  //| several useful features, like:
42  //|
43  //|  * variable/macro substitution. You may refer to other property's value with
44  //|  $\{NAME\} expression, where NAME is the name of the referred property.
45  //|  ofcourse you can use more than one property reference per property, and
46  //|  you can mix constant text and property references:
47  //|
48  //|+-------------------+
49  //|player.name = Joe
50  //|player.greetings = Hi ${player.name}!
51  //|player.domain = foo.bar
52  //|player.email = ${player.name}@${player.domain}
53  //|+-------------------+
54  //|
55  //|  * multiply property values. You can refer to multi value properties with
56  //| integer indexes. Ofcource it is also works in macro/variable substitutions:
57  //| $\{user.fortuneNumber\[2\]\}
58  //|
59  //|+-------------------+
60  //|player.fortuneNumber = 33
61  //|player.fortuneNumber = 44
62  //|player.fortuneNumber = 55
63  //|player.fortuneNumber = 66
64  //|
65  //|magicNumber = ${player.foruneNumber[1]}
66  //|+--------------------+
67  //|
68  //|  The magicNumber property will have value: <<<44>>>
69  //|
70  //|  * as Java class, Options is basicly map of Strings indexed with Strings. It
71  //|  is standard Collection API (ok, it is a bit enhanced to deal with multi
72  //|  values, but in general it is a Map\<String,String\>).
73  //|
74  //|  * Java Beans api. You can read/write properties in type safe way. To do it
75  //|  you just define an interface, call Options#as() method. This method will
76  //|  provide an implementation of given interface on top of Options. Property
77  //|  types are mapped automatically between Java type and String.
78  //|
79  //|* Why need Options
80  //|
81  //| With standard Properties class there is several small problem. Most of them
82  //| came from backward compatibility.
83  //|
84  //|  * not implements Map\<String,String\>, but Map\<Object,Object\>. If you
85  //|    want to use Collections api, it is a bit unconfortable.
86  //|
87  //|  * only single property values allowed. Probably you already see ugly
88  //|    workarounds: index number in property names, like: file.1, file.2 ...
89  //|
90  //|  * no macro/variable substitution. In some environment, like
91  //|    Apache Ant, you can use ${name} like references, but with standard
92  //|    java.util.Properties you can't.
93  //|
94  //| As side effect of \[ini4j\] development, there is a solution for aboves.
95  //| This is the org.ini4j.Options class, which is basicly a feature rich
96  //| replacement for java.util.Properties.
97  //|
98  //| Code sniplets in this tutorial tested with the following .opt file:
99  //| {{{../sample/dwarfs.opt.html}dwarfs.opt}}
100 //|
101 //</editor-fold>
102 public class OptTutorial extends AbstractTutorial
103 {
104     public static final String FILENAME = "../sample/dwarfs.opt";
105 
106     public static void main(String[] args) throws Exception
107     {
108         new OptTutorial().run(filearg(args));
109     }
110 
111     protected void run(File arg) throws Exception
112     {
113         Options opt = new Options(arg.toURI().toURL());
114 
115         sample01(arg);
116         sample02(opt);
117     }
118 
119 //|
120 //|* Instantiating
121 //|
122 //| There is nothing special with instantiating Options object, but there is a
123 //| few constructor, to simplify loading data. These constructors simply call
124 //| the <<<load()>>> method on newly created instance. Ofcource these
125 //| constructors are throws IOException.
126 //{
127     void sample01(File file) throws IOException
128     {
129         Options opt = new Options();
130 
131         //
132         // or instantiate and load data:
133         //
134         opt = new Options(new FileReader(file));
135 
136 //}
137         assertFalse(opt.keySet().isEmpty());
138     }
139 
140 //|
141 //|* Map of String
142 //{
143     void sample02(Options opt)
144     {
145         Set<String> optionNames = opt.keySet();
146 
147         //
148         String age = opt.get("age");
149         String weight = opt.fetch("weight");
150         String height = opt.fetch("height");
151 
152 //}
153 //|
154 //| The Options is a MultiMap\<String,String\>, that is, a map that assigns
155 //| String values to String keys. So the <<<get>>> method is used to get values
156 //| inside the options. To get a value, besides <<<get()>>> you can also
157 //| use <<<fetch()>>> which resolves any occurrent $\{option\} format
158 //| variable references in the needed value.
159         Helper.assertEquals(DwarfsData.dopey, opt.as(Dwarf.class));
160     }
161 }