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 }