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.Options;
019    
020    import org.ini4j.sample.Dwarf;
021    
022    import org.ini4j.test.DwarfsData;
023    import org.ini4j.test.Helper;
024    
025    import static org.junit.Assert.*;
026    
027    import java.io.File;
028    import java.io.FileReader;
029    import java.io.IOException;
030    
031    import java.util.Set;
032    
033    //<editor-fold defaultstate="collapsed" desc="apt documentation">
034    //|
035    //|                ----------------
036    //|                Options Tutorial
037    //|
038    //|Options Tutorial - java.util.Properties replacement
039    //|
040    //| Options (org.ini4j.Options) is a java.util.Properties replacement with
041    //| several useful features, like:
042    //|
043    //|  * variable/macro substitution. You may refer to other property's value with
044    //|  $\{NAME\} expression, where NAME is the name of the referred property.
045    //|  ofcourse you can use more than one property reference per property, and
046    //|  you can mix constant text and property references:
047    //|
048    //|+-------------------+
049    //|player.name = Joe
050    //|player.greetings = Hi ${player.name}!
051    //|player.domain = foo.bar
052    //|player.email = ${player.name}@${player.domain}
053    //|+-------------------+
054    //|
055    //|  * multiply property values. You can refer to multi value properties with
056    //| integer indexes. Ofcource it is also works in macro/variable substitutions:
057    //| $\{user.fortuneNumber\[2\]\}
058    //|
059    //|+-------------------+
060    //|player.fortuneNumber = 33
061    //|player.fortuneNumber = 44
062    //|player.fortuneNumber = 55
063    //|player.fortuneNumber = 66
064    //|
065    //|magicNumber = ${player.foruneNumber[1]}
066    //|+--------------------+
067    //|
068    //|  The magicNumber property will have value: <<<44>>>
069    //|
070    //|  * as Java class, Options is basicly map of Strings indexed with Strings. It
071    //|  is standard Collection API (ok, it is a bit enhanced to deal with multi
072    //|  values, but in general it is a Map\<String,String\>).
073    //|
074    //|  * Java Beans api. You can read/write properties in type safe way. To do it
075    //|  you just define an interface, call Options#as() method. This method will
076    //|  provide an implementation of given interface on top of Options. Property
077    //|  types are mapped automatically between Java type and String.
078    //|
079    //|* Why need Options
080    //|
081    //| With standard Properties class there is several small problem. Most of them
082    //| came from backward compatibility.
083    //|
084    //|  * not implements Map\<String,String\>, but Map\<Object,Object\>. If you
085    //|    want to use Collections api, it is a bit unconfortable.
086    //|
087    //|  * only single property values allowed. Probably you already see ugly
088    //|    workarounds: index number in property names, like: file.1, file.2 ...
089    //|
090    //|  * no macro/variable substitution. In some environment, like
091    //|    Apache Ant, you can use ${name} like references, but with standard
092    //|    java.util.Properties you can't.
093    //|
094    //| As side effect of \[ini4j\] development, there is a solution for aboves.
095    //| This is the org.ini4j.Options class, which is basicly a feature rich
096    //| replacement for java.util.Properties.
097    //|
098    //| Code sniplets in this tutorial tested with the following .opt file:
099    //| {{{../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    }