001/*
002 * Copyright 2005,2009 Ivan SZKIBA
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of 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,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.ini4j.tutorial;
017
018import org.ini4j.Ini;
019
020import org.ini4j.sample.Dwarf;
021import org.ini4j.sample.Dwarfs;
022
023import org.ini4j.test.DwarfsData;
024import org.ini4j.test.Helper;
025
026import static org.junit.Assert.assertEquals;
027import static org.junit.Assert.assertNotNull;
028
029import java.io.File;
030import java.io.FileReader;
031import java.io.IOException;
032
033import java.util.Map;
034import java.util.Set;
035
036//<editor-fold defaultstate="collapsed" desc="apt documentation">
037//|
038//|                -------------
039//|                Ini Tutorial
040//|
041//|Ini Tutorial - How to use \[ini4j\] api
042//|
043//| This tutorial familiarize the reader with the usage of
044//| the [ini4j] library's natural interface.
045//|
046//| Code sniplets in this tutorial tested with the following .ini file:
047//| {{{../sample/dwarfs.ini.html}dwarfs.ini}}
048//|
049//</editor-fold>
050public class IniTutorial extends AbstractTutorial
051{
052    public static void main(String[] args) throws Exception
053    {
054        new IniTutorial().run(filearg(args));
055    }
056
057    @Override protected void run(File arg) throws Exception
058    {
059        Ini ini = new Ini(arg.toURI().toURL());
060
061        sample01(ini);
062        sample02(arg);
063        sample03(ini);
064        sample04(ini);
065    }
066
067//|* Data model
068//|
069//| Data model for .ini files is represented by org.ini4j.Ini class. This class
070//| implements Map\<String,Section\>. It mean you can access sections using
071//| java.util.Map collection API interface. The Section is also a map, which is
072//| implements Map\<String,String\>.
073//{
074    void sample01(Ini ini)
075    {
076        Ini.Section section = ini.get("happy");
077
078        //
079        // read some values
080        //
081        String age = section.get("age");
082        String weight = section.get("weight");
083        String homeDir = section.get("homeDir");
084
085        //
086        // .. or just use java.util.Map interface...
087        //
088        Map<String, String> map = ini.get("happy");
089
090        age = map.get("age");
091        weight = map.get("weight");
092        homeDir = map.get("homeDir");
093
094        // get all section names
095        Set<String> sectionNames = ini.keySet();
096
097//}
098        Helper.assertEquals(DwarfsData.happy, section.as(Dwarf.class));
099    }
100
101//|
102//|* Loading and storing data
103//|
104//| There is several way to load data into Ini object. It can be done by using
105//| <<<load>>> methods or overloaded constructors. Data can be load from
106//| InputStream, Reader, URL or File.
107//|
108//| You can store data using <<<store>>> methods. Data can store to OutputStream,
109//| Writer, or File.
110//{
111    void sample02(File file) throws IOException
112    {
113        Ini ini = new Ini();
114
115        ini.load(new FileReader(file));
116
117        //
118        // or instantiate and load data:
119        //
120        ini = new Ini(new FileReader(file));
121        File copy = File.createTempFile("sample", ".ini");
122
123        ini.store(copy);
124//}
125        ini = new Ini(copy);
126        Helper.assertEquals(DwarfsData.dwarfs, ini.as(Dwarfs.class));
127        copy.delete();
128    }
129
130//|
131//|* Macro/variable substitution
132//|
133//| To get a value, besides <<<get()>>> you can also
134//| use <<<fetch()>>> which resolves any occurrent $\{section/option\} format
135//| variable references in the needed value.
136//|
137//{
138    void sample03(Ini ini)
139    {
140        Ini.Section dopey = ini.get("dopey");
141
142        // get method doesn't resolve variable references
143        String weightRaw = dopey.get("weight");  // = ${bashful/weight}
144        String heightRaw = dopey.get("height");  // = ${doc/height}
145
146        // to resolve references, you should use fetch method
147        String weight = dopey.fetch("weight");  // = 45.7
148        String height = dopey.fetch("height");  // = 87.7
149
150//}
151//| Assuming we have an .ini file with the following sections:
152//|
153//|+--------------+
154//| [dopey]
155//| weight = ${bashful/weight}
156//| height = ${doc/height}
157//|
158//|[bashful]
159//| weight = 45.7
160//| height = 98.8
161//|
162//| [doc]
163//| weight = 49.5
164//| height = 87.7
165//|+--------------+
166//|
167        assertEquals(DwarfsData.INI_DOPEY_WEIGHT, weightRaw);
168        assertEquals(DwarfsData.INI_DOPEY_HEIGHT, heightRaw);
169        assertEquals(String.valueOf(DwarfsData.dopey.weight), weight);
170        assertEquals(String.valueOf(DwarfsData.dopey.height), height);
171    }
172
173//|
174//|* Multi values
175//|
176//| \[ini4j\] library introduces MultiMap interface, which is extends normal
177//| Map, but allows multiply values per keys. You can simply index values for
178//| a given key, similar to indexed properties in JavaBeans api.
179//|
180//{
181    void sample04(Ini ini)
182    {
183        Ini.Section sneezy = ini.get("sneezy");
184        String n1 = sneezy.get("fortuneNumber", 0);  // = 11
185        String n2 = sneezy.get("fortuneNumber", 1);  // = 22
186        String n3 = sneezy.get("fortuneNumber", 2);  // = 33
187        String n4 = sneezy.get("fortuneNumber", 3);  // = 44
188
189        // ok, lets do in it easier...
190        int[] n = sneezy.getAll("fortuneNumber", int[].class);
191//}
192        // #2817399
193
194        assertEquals("11", n1);
195        assertEquals("22", n2);
196        assertEquals("33", n3);
197        assertEquals("44", n4);
198        assertEquals(4, n.length);
199        assertEquals(11, n[0]);
200        assertEquals(22, n[1]);
201        assertEquals(33, n[2]);
202        assertEquals(44, n[3]);
203    }
204
205//|
206//|* Tree model
207//|
208//| Beyond two level map model, Ini class provides tree model. You can access
209//| Sections as tree. It means that section names becomes path names, with a
210//| path separator character ('/' and '\' on Wini and Reg).
211//|
212//{
213    void sample05()
214    {
215        Ini ini = new Ini();
216
217        // lets add a section, it will create needed intermediate sections as well
218        ini.add("root/child/sub");
219
220        //
221        Ini.Section root;
222        Ini.Section sec;
223
224        root = ini.get("root");
225        sec = root.getChild("child").getChild("sub");
226
227        // or...
228        sec = root.lookup("child", "sub");
229
230        // or...
231        sec = root.lookup("child/sub");
232
233        // or even...
234        sec = ini.get("root/child/sub");
235
236//}
237//| If you are using Wini instead of Ini class, the path separator become '\'.
238//|
239        assertNotNull(root.lookup("child", "sub"));
240        assertNotNull(ini.get("root/child"));
241    }
242}