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     */
016    package org.ini4j.tutorial;
017    
018    import org.ini4j.Ini;
019    
020    import org.ini4j.sample.Dwarf;
021    import org.ini4j.sample.Dwarfs;
022    
023    import org.ini4j.test.DwarfsData;
024    import org.ini4j.test.Helper;
025    
026    import static org.junit.Assert.assertEquals;
027    import static org.junit.Assert.assertNotNull;
028    
029    import java.io.File;
030    import java.io.FileReader;
031    import java.io.IOException;
032    
033    import java.util.Map;
034    import 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>
050    public 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    }