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.Config;
19 import org.ini4j.Ini;
20 import org.ini4j.Options;
21
22 import org.ini4j.sample.Dwarf;
23 import org.ini4j.sample.DwarfBean;
24 import org.ini4j.sample.Dwarfs;
25
26 import org.ini4j.test.DwarfsData;
27
28 import static org.junit.Assert.*;
29
30 import java.io.File;
31 import java.io.IOException;
32
33 import java.net.URI;
34 import java.net.URL;
35
36 //<editor-fold defaultstate="collapsed" desc="apt documentation">
37 //|
38 //| -------------
39 //| Bean Tutorial
40 //|
41 //|Bean Tutorial - Using your own API !
42 //|
43 //| Yes, it can be done! To access the contents of sections you can use any of
44 //| your self-defined Java Beans compatible API.
45 //| In order to do this you only have to create a Java Beans-style interface or class.
46 //|
47 //| Source code for beans: {{{../sample/Dwarf.java.html}Dwarf}},
48 //| {{{../sample/DwarfBean.java.html}DwarfBean}}
49 //|
50 //| Code sniplets in this tutorial tested with the following .ini file:
51 //| {{{../sample/dwarfs.ini.html}dwarfs.ini}}
52 //|
53 //</editor-fold>
54 public class BeanTutorial extends AbstractTutorial
55 {
56 public static void main(String[] args) throws Exception
57 {
58 new BeanTutorial().run(filearg(args));
59 }
60
61 @Override protected void run(File arg) throws Exception
62 {
63 Ini ini = new Ini(arg.toURI().toURL());
64
65 sample01(ini);
66 sample02(ini);
67 sample03(ini);
68 sample04(arg.toURI().toURL());
69 Options opts = new Options();
70
71 opts.putAll(ini.get(Dwarfs.PROP_BASHFUL));
72 sample05(opts);
73
74 //
75 File optFile = new File(arg.getParentFile(), OptTutorial.FILENAME);
76
77 sample06(optFile.toURI().toURL());
78 }
79
80 //|
81 //|* Accessing sections as beans
82 //|
83 //| While writing a program we usually know the type of the section's values,
84 //| so we can define one or more java interfaces to access them. An advantage of
85 //| this solution is that the programmer doesn't have to convert the values
86 //| because they are converted automatically to the type defined in the
87 //| interface.
88 //|
89 //| Ofcourse you may use setters as well, not just getters. In this way you can
90 //| change values type safe way.
91 //{
92 void sample01(Ini ini)
93 {
94 Ini.Section sec = ini.get("happy");
95 Dwarf happy = sec.as(Dwarf.class);
96 int age = happy.getAge();
97 URI homePage = happy.getHomePage();
98
99 happy.setWeight(45.55);
100
101 //}
102 //|
103 //| The <<<happy instanceof Dwarf>>> relation is of course fulfilled in the
104 //| example above.
105 //|
106 assertEquals(DwarfsData.happy.homePage.toString(), homePage.toString());
107 assertEquals(DwarfsData.happy.age, age);
108 assertEquals(45.55, happy.getWeight(), 0.01);
109 }
110
111 //|
112 //|* Marshalling beans
113 //|
114 //| Sometimes we want to store existing java beans in text file. This operation
115 //| usually called marshalling.
116 //|
117 //| With [ini4j] it is easy to store bean properties in a section. You simply
118 //| create a section, and call the sections's <<<from()>>> method. Thats it.
119 //{
120 void sample02(Ini ini)
121 {
122 DwarfBean sleepy = new DwarfBean();
123
124 sleepy.setAge(87);
125 sleepy.setWeight(44.3);
126 Ini.Section sec = ini.add("sleepy");
127
128 sec.from(sleepy);
129
130 //}
131 //|
132 assertTrue(sec.containsKey(Dwarf.PROP_AGE));
133 assertTrue(sec.containsKey(Dwarf.PROP_WEIGHT));
134 }
135
136 //|
137 //|* Unmarshalling beans
138 //|
139 //| If you have a marshalled bean in text file then you may want to read it
140 //| into bean. This operation usually called unmarshalling.
141 //|
142 //| With [ini4j] it is easy to load bean properties from a section. You simply
143 //| instantiate a bean, and call the sections's <<<to()>>> method. Thats it.
144 //{
145 void sample03(Ini ini)
146 {
147 DwarfBean grumpy = new DwarfBean();
148
149 ini.get("grumpy").to(grumpy);
150
151 //}
152 //|
153 assertEquals(DwarfsData.grumpy.age, grumpy.getAge());
154 assertEquals(DwarfsData.grumpy.homeDir, grumpy.getHomeDir());
155 }
156
157 //|
158 //|* Indexed properties
159 //|
160 //| For handling indexed properties, you should allow mulpti option value
161 //| handling in configuration. After enabling this feature, option may contains
162 //| multiply values (multi line in file). These values can mapped to indexed
163 //| bean property.
164 //{
165 void sample04(URL location) throws IOException
166 {
167 Config cfg = new Config();
168
169 cfg.setMultiOption(true);
170 Ini ini = new Ini();
171
172 ini.setConfig(cfg);
173 ini.load(location);
174 Ini.Section sec = ini.get("sneezy");
175 Dwarf sneezy = sec.as(Dwarf.class);
176 int[] numbers = sneezy.getFortuneNumber();
177
178 //
179 // same as above but with unmarshalling...
180 //
181 DwarfBean sneezyBean = new DwarfBean();
182
183 sec.to(sneezyBean);
184 numbers = sneezyBean.getFortuneNumber();
185
186 //}
187 assertArrayEquals(DwarfsData.sneezy.fortuneNumber, numbers);
188 assertEquals(DwarfsData.sneezy.fortuneNumber.length, sec.length("fortuneNumber"));
189 assertArrayEquals(DwarfsData.sneezy.fortuneNumber, sneezy.getFortuneNumber());
190 assertArrayEquals(DwarfsData.sneezy.fortuneNumber, sneezyBean.getFortuneNumber());
191 }
192
193 //|
194 //|* Options
195 //|
196 //| Not only Ini and Ini.Section has bean interface. There is a bean interface
197 //| for OptionMap class and each derived class for example for Options.
198 //| Options is an improved java.util.Properties replacement.
199 //{
200 void sample05(Options opts)
201 {
202 Dwarf dwarf = opts.as(Dwarf.class);
203 int age = dwarf.getAge();
204
205 //
206 // same as above but with unmarshalling
207 //
208 DwarfBean dwarfBean = new DwarfBean();
209
210 opts.to(dwarfBean);
211 age = dwarfBean.getAge();
212
213 //}
214 //|
215 //| In sample above the top level properties (like "age") mapped to bean
216 //| properties.
217 //|
218 assertEquals(DwarfsData.bashful.age, dwarf.getAge());
219 assertEquals(DwarfsData.bashful.age, dwarfBean.getAge());
220 }
221
222 //|
223 //|* Prefixed mapping
224 //|
225 //| Both Ini.Section and Options has possibility to add a prefix to property
226 //| names while mapping from bean property name to Ini.Section or Options
227 //| key.
228 //{
229 void sample06(URL optPath) throws IOException
230 {
231 Options opt = new Options(optPath);
232 Dwarf dwarf = opt.as(Dwarf.class, "happy.");
233 DwarfBean bean = new DwarfBean();
234
235 opt.to(bean, "dopey.");
236
237 //}
238 //|
239 //| In the above example, <<<dwarf>>> bean will contain properties starts with
240 //| <<<happy.>>> while <<<bean>>> will contain properties starts with
241 //| <<<dopey.>>>
242 assertEquals(DwarfsData.happy.age, dwarf.getAge());
243 assertEquals(DwarfsData.dopey.age, bean.getAge());
244 }
245 //}
246 }