I need to remove solution 12 as it did not allow to query a history with one convertor. There was no way to provide arbitrary date, one could query only about the present state. As such the API was quite simplified and it would be unfair for others if this solution advanced to the final round. Sorry.
1.1 --- a/task4/solution12/build.xml Fri Oct 17 17:54:38 2008 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,69 +0,0 @@
1.4 -<?xml version="1.0" encoding="UTF-8"?>
1.5 -<!-- You may freely edit this file. See commented blocks below for -->
1.6 -<!-- some examples of how to customize the build. -->
1.7 -<!-- (If you delete it and reopen the project it will be recreated.) -->
1.8 -<project name="currency" default="default" basedir=".">
1.9 - <description>Builds, tests, and runs the project.</description>
1.10 - <import file="nbproject/build-impl.xml"/>
1.11 - <!--
1.12 -
1.13 - There exist several targets which are by default empty and which can be
1.14 - used for execution of your tasks. These targets are usually executed
1.15 - before and after some main targets. They are:
1.16 -
1.17 - -pre-init: called before initialization of project properties
1.18 - -post-init: called after initialization of project properties
1.19 - -pre-compile: called before javac compilation
1.20 - -post-compile: called after javac compilation
1.21 - -pre-compile-single: called before javac compilation of single file
1.22 - -post-compile-single: called after javac compilation of single file
1.23 - -pre-compile-test: called before javac compilation of JUnit tests
1.24 - -post-compile-test: called after javac compilation of JUnit tests
1.25 - -pre-compile-test-single: called before javac compilation of single JUnit test
1.26 - -post-compile-test-single: called after javac compilation of single JUunit test
1.27 - -pre-jar: called before JAR building
1.28 - -post-jar: called after JAR building
1.29 - -post-clean: called after cleaning build products
1.30 -
1.31 - (Targets beginning with '-' are not intended to be called on their own.)
1.32 -
1.33 - Example of inserting an obfuscator after compilation could look like this:
1.34 -
1.35 - <target name="-post-compile">
1.36 - <obfuscate>
1.37 - <fileset dir="${build.classes.dir}"/>
1.38 - </obfuscate>
1.39 - </target>
1.40 -
1.41 - For list of available properties check the imported
1.42 - nbproject/build-impl.xml file.
1.43 -
1.44 -
1.45 - Another way to customize the build is by overriding existing main targets.
1.46 - The targets of interest are:
1.47 -
1.48 - -init-macrodef-javac: defines macro for javac compilation
1.49 - -init-macrodef-junit: defines macro for junit execution
1.50 - -init-macrodef-debug: defines macro for class debugging
1.51 - -init-macrodef-java: defines macro for class execution
1.52 - -do-jar-with-manifest: JAR building (if you are using a manifest)
1.53 - -do-jar-without-manifest: JAR building (if you are not using a manifest)
1.54 - run: execution of project
1.55 - -javadoc-build: Javadoc generation
1.56 - test-report: JUnit report generation
1.57 -
1.58 - An example of overriding the target for project execution could look like this:
1.59 -
1.60 - <target name="run" depends="currency-impl.jar">
1.61 - <exec dir="bin" executable="launcher.exe">
1.62 - <arg file="${dist.jar}"/>
1.63 - </exec>
1.64 - </target>
1.65 -
1.66 - Notice that the overridden target depends on the jar target and not only on
1.67 - the compile target as the regular run target does. Again, for a list of available
1.68 - properties which you can use, check the target you are overriding in the
1.69 - nbproject/build-impl.xml file.
1.70 -
1.71 - -->
1.72 -</project>
2.1 --- a/task4/solution12/nbproject/build-impl.xml Fri Oct 17 17:54:38 2008 +0200
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,642 +0,0 @@
2.4 -<?xml version="1.0" encoding="UTF-8"?>
2.5 -<!--
2.6 -*** GENERATED FROM project.xml - DO NOT EDIT ***
2.7 -*** EDIT ../build.xml INSTEAD ***
2.8 -
2.9 -For the purpose of easier reading the script
2.10 -is divided into following sections:
2.11 -
2.12 - - initialization
2.13 - - compilation
2.14 - - jar
2.15 - - execution
2.16 - - debugging
2.17 - - javadoc
2.18 - - junit compilation
2.19 - - junit execution
2.20 - - junit debugging
2.21 - - applet
2.22 - - cleanup
2.23 -
2.24 - -->
2.25 -<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Currency_Convertor_Solution_12-impl">
2.26 - <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
2.27 - <!--
2.28 - ======================
2.29 - INITIALIZATION SECTION
2.30 - ======================
2.31 - -->
2.32 - <target name="-pre-init">
2.33 - <!-- Empty placeholder for easier customization. -->
2.34 - <!-- You can override this target in the ../build.xml file. -->
2.35 - </target>
2.36 - <target depends="-pre-init" name="-init-private">
2.37 - <property file="nbproject/private/config.properties"/>
2.38 - <property file="nbproject/private/configs/${config}.properties"/>
2.39 - <property file="nbproject/private/private.properties"/>
2.40 - </target>
2.41 - <target depends="-pre-init,-init-private" name="-init-user">
2.42 - <property file="${user.properties.file}"/>
2.43 - <!-- The two properties below are usually overridden -->
2.44 - <!-- by the active platform. Just a fallback. -->
2.45 - <property name="default.javac.source" value="1.4"/>
2.46 - <property name="default.javac.target" value="1.4"/>
2.47 - </target>
2.48 - <target depends="-pre-init,-init-private,-init-user" name="-init-project">
2.49 - <property file="nbproject/configs/${config}.properties"/>
2.50 - <property file="nbproject/project.properties"/>
2.51 - </target>
2.52 - <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
2.53 - <available file="${manifest.file}" property="manifest.available"/>
2.54 - <condition property="manifest.available+main.class">
2.55 - <and>
2.56 - <isset property="manifest.available"/>
2.57 - <isset property="main.class"/>
2.58 - <not>
2.59 - <equals arg1="${main.class}" arg2="" trim="true"/>
2.60 - </not>
2.61 - </and>
2.62 - </condition>
2.63 - <condition property="manifest.available+main.class+mkdist.available">
2.64 - <and>
2.65 - <istrue value="${manifest.available+main.class}"/>
2.66 - <isset property="libs.CopyLibs.classpath"/>
2.67 - </and>
2.68 - </condition>
2.69 - <condition property="have.tests">
2.70 - <or>
2.71 - <available file="${test.src.dir}"/>
2.72 - </or>
2.73 - </condition>
2.74 - <condition property="have.sources">
2.75 - <or>
2.76 - <available file="${src.dir}"/>
2.77 - </or>
2.78 - </condition>
2.79 - <condition property="netbeans.home+have.tests">
2.80 - <and>
2.81 - <isset property="netbeans.home"/>
2.82 - <isset property="have.tests"/>
2.83 - </and>
2.84 - </condition>
2.85 - <condition property="no.javadoc.preview">
2.86 - <and>
2.87 - <isset property="javadoc.preview"/>
2.88 - <isfalse value="${javadoc.preview}"/>
2.89 - </and>
2.90 - </condition>
2.91 - <property name="run.jvmargs" value=""/>
2.92 - <property name="javac.compilerargs" value=""/>
2.93 - <property name="work.dir" value="${basedir}"/>
2.94 - <condition property="no.deps">
2.95 - <and>
2.96 - <istrue value="${no.dependencies}"/>
2.97 - </and>
2.98 - </condition>
2.99 - <property name="javac.debug" value="true"/>
2.100 - <property name="javadoc.preview" value="true"/>
2.101 - <property name="application.args" value=""/>
2.102 - <property name="source.encoding" value="${file.encoding}"/>
2.103 - <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
2.104 - <and>
2.105 - <isset property="javadoc.encoding"/>
2.106 - <not>
2.107 - <equals arg1="${javadoc.encoding}" arg2=""/>
2.108 - </not>
2.109 - </and>
2.110 - </condition>
2.111 - <property name="javadoc.encoding.used" value="${source.encoding}"/>
2.112 - <property name="includes" value="**"/>
2.113 - <property name="excludes" value=""/>
2.114 - <property name="do.depend" value="false"/>
2.115 - <condition property="do.depend.true">
2.116 - <istrue value="${do.depend}"/>
2.117 - </condition>
2.118 - <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
2.119 - <and>
2.120 - <isset property="jaxws.endorsed.dir"/>
2.121 - <available file="nbproject/jaxws-build.xml"/>
2.122 - </and>
2.123 - </condition>
2.124 - </target>
2.125 - <target name="-post-init">
2.126 - <!-- Empty placeholder for easier customization. -->
2.127 - <!-- You can override this target in the ../build.xml file. -->
2.128 - </target>
2.129 - <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
2.130 - <fail unless="src.dir">Must set src.dir</fail>
2.131 - <fail unless="test.src.dir">Must set test.src.dir</fail>
2.132 - <fail unless="build.dir">Must set build.dir</fail>
2.133 - <fail unless="dist.dir">Must set dist.dir</fail>
2.134 - <fail unless="build.classes.dir">Must set build.classes.dir</fail>
2.135 - <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
2.136 - <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
2.137 - <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
2.138 - <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
2.139 - <fail unless="dist.jar">Must set dist.jar</fail>
2.140 - </target>
2.141 - <target name="-init-macrodef-property">
2.142 - <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
2.143 - <attribute name="name"/>
2.144 - <attribute name="value"/>
2.145 - <sequential>
2.146 - <property name="@{name}" value="${@{value}}"/>
2.147 - </sequential>
2.148 - </macrodef>
2.149 - </target>
2.150 - <target name="-init-macrodef-javac">
2.151 - <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
2.152 - <attribute default="${src.dir}" name="srcdir"/>
2.153 - <attribute default="${build.classes.dir}" name="destdir"/>
2.154 - <attribute default="${javac.classpath}" name="classpath"/>
2.155 - <attribute default="${includes}" name="includes"/>
2.156 - <attribute default="${excludes}" name="excludes"/>
2.157 - <attribute default="${javac.debug}" name="debug"/>
2.158 - <attribute default="" name="sourcepath"/>
2.159 - <element name="customize" optional="true"/>
2.160 - <sequential>
2.161 - <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
2.162 - <classpath>
2.163 - <path path="@{classpath}"/>
2.164 - </classpath>
2.165 - <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
2.166 - <customize/>
2.167 - </javac>
2.168 - </sequential>
2.169 - </macrodef>
2.170 - <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
2.171 - <attribute default="${src.dir}" name="srcdir"/>
2.172 - <attribute default="${build.classes.dir}" name="destdir"/>
2.173 - <attribute default="${javac.classpath}" name="classpath"/>
2.174 - <sequential>
2.175 - <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
2.176 - <classpath>
2.177 - <path path="@{classpath}"/>
2.178 - </classpath>
2.179 - </depend>
2.180 - </sequential>
2.181 - </macrodef>
2.182 - <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
2.183 - <attribute default="${build.classes.dir}" name="destdir"/>
2.184 - <sequential>
2.185 - <fail unless="javac.includes">Must set javac.includes</fail>
2.186 - <pathconvert pathsep="," property="javac.includes.binary">
2.187 - <path>
2.188 - <filelist dir="@{destdir}" files="${javac.includes}"/>
2.189 - </path>
2.190 - <globmapper from="*.java" to="*.class"/>
2.191 - </pathconvert>
2.192 - <delete>
2.193 - <files includes="${javac.includes.binary}"/>
2.194 - </delete>
2.195 - </sequential>
2.196 - </macrodef>
2.197 - </target>
2.198 - <target name="-init-macrodef-junit">
2.199 - <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
2.200 - <attribute default="${includes}" name="includes"/>
2.201 - <attribute default="${excludes}" name="excludes"/>
2.202 - <attribute default="**" name="testincludes"/>
2.203 - <sequential>
2.204 - <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
2.205 - <batchtest todir="${build.test.results.dir}">
2.206 - <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
2.207 - <filename name="@{testincludes}"/>
2.208 - </fileset>
2.209 - </batchtest>
2.210 - <classpath>
2.211 - <path path="${run.test.classpath}"/>
2.212 - </classpath>
2.213 - <syspropertyset>
2.214 - <propertyref prefix="test-sys-prop."/>
2.215 - <mapper from="test-sys-prop.*" to="*" type="glob"/>
2.216 - </syspropertyset>
2.217 - <formatter type="brief" usefile="false"/>
2.218 - <formatter type="xml"/>
2.219 - <jvmarg line="${run.jvmargs}"/>
2.220 - </junit>
2.221 - </sequential>
2.222 - </macrodef>
2.223 - </target>
2.224 - <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
2.225 - <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
2.226 - <attribute default="${main.class}" name="name"/>
2.227 - <attribute default="${debug.classpath}" name="classpath"/>
2.228 - <attribute default="" name="stopclassname"/>
2.229 - <sequential>
2.230 - <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
2.231 - <classpath>
2.232 - <path path="@{classpath}"/>
2.233 - </classpath>
2.234 - </nbjpdastart>
2.235 - </sequential>
2.236 - </macrodef>
2.237 - <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
2.238 - <attribute default="${build.classes.dir}" name="dir"/>
2.239 - <sequential>
2.240 - <nbjpdareload>
2.241 - <fileset dir="@{dir}" includes="${fix.classes}">
2.242 - <include name="${fix.includes}*.class"/>
2.243 - </fileset>
2.244 - </nbjpdareload>
2.245 - </sequential>
2.246 - </macrodef>
2.247 - </target>
2.248 - <target name="-init-debug-args">
2.249 - <property name="version-output" value="java version "${ant.java.version}"/>
2.250 - <condition property="have-jdk-older-than-1.4">
2.251 - <or>
2.252 - <contains string="${version-output}" substring="java version "1.0"/>
2.253 - <contains string="${version-output}" substring="java version "1.1"/>
2.254 - <contains string="${version-output}" substring="java version "1.2"/>
2.255 - <contains string="${version-output}" substring="java version "1.3"/>
2.256 - </or>
2.257 - </condition>
2.258 - <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
2.259 - <istrue value="${have-jdk-older-than-1.4}"/>
2.260 - </condition>
2.261 - <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
2.262 - <os family="windows"/>
2.263 - </condition>
2.264 - <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
2.265 - <isset property="debug.transport"/>
2.266 - </condition>
2.267 - </target>
2.268 - <target depends="-init-debug-args" name="-init-macrodef-debug">
2.269 - <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
2.270 - <attribute default="${main.class}" name="classname"/>
2.271 - <attribute default="${debug.classpath}" name="classpath"/>
2.272 - <element name="customize" optional="true"/>
2.273 - <sequential>
2.274 - <java classname="@{classname}" dir="${work.dir}" fork="true">
2.275 - <jvmarg line="${debug-args-line}"/>
2.276 - <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
2.277 - <jvmarg line="${run.jvmargs}"/>
2.278 - <classpath>
2.279 - <path path="@{classpath}"/>
2.280 - </classpath>
2.281 - <syspropertyset>
2.282 - <propertyref prefix="run-sys-prop."/>
2.283 - <mapper from="run-sys-prop.*" to="*" type="glob"/>
2.284 - </syspropertyset>
2.285 - <customize/>
2.286 - </java>
2.287 - </sequential>
2.288 - </macrodef>
2.289 - </target>
2.290 - <target name="-init-macrodef-java">
2.291 - <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
2.292 - <attribute default="${main.class}" name="classname"/>
2.293 - <element name="customize" optional="true"/>
2.294 - <sequential>
2.295 - <java classname="@{classname}" dir="${work.dir}" fork="true">
2.296 - <jvmarg line="${run.jvmargs}"/>
2.297 - <classpath>
2.298 - <path path="${run.classpath}"/>
2.299 - </classpath>
2.300 - <syspropertyset>
2.301 - <propertyref prefix="run-sys-prop."/>
2.302 - <mapper from="run-sys-prop.*" to="*" type="glob"/>
2.303 - </syspropertyset>
2.304 - <customize/>
2.305 - </java>
2.306 - </sequential>
2.307 - </macrodef>
2.308 - </target>
2.309 - <target name="-init-presetdef-jar">
2.310 - <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
2.311 - <jar compress="${jar.compress}" jarfile="${dist.jar}">
2.312 - <j2seproject1:fileset dir="${build.classes.dir}"/>
2.313 - </jar>
2.314 - </presetdef>
2.315 - </target>
2.316 - <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
2.317 - <!--
2.318 - ===================
2.319 - COMPILATION SECTION
2.320 - ===================
2.321 - -->
2.322 - <target depends="init" name="deps-jar" unless="no.deps"/>
2.323 - <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
2.324 - <target depends="init" name="-check-automatic-build">
2.325 - <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
2.326 - </target>
2.327 - <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
2.328 - <antcall target="clean"/>
2.329 - </target>
2.330 - <target depends="init,deps-jar" name="-pre-pre-compile">
2.331 - <mkdir dir="${build.classes.dir}"/>
2.332 - </target>
2.333 - <target name="-pre-compile">
2.334 - <!-- Empty placeholder for easier customization. -->
2.335 - <!-- You can override this target in the ../build.xml file. -->
2.336 - </target>
2.337 - <target if="do.depend.true" name="-compile-depend">
2.338 - <j2seproject3:depend/>
2.339 - </target>
2.340 - <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
2.341 - <j2seproject3:javac/>
2.342 - <copy todir="${build.classes.dir}">
2.343 - <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
2.344 - </copy>
2.345 - </target>
2.346 - <target name="-post-compile">
2.347 - <!-- Empty placeholder for easier customization. -->
2.348 - <!-- You can override this target in the ../build.xml file. -->
2.349 - </target>
2.350 - <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
2.351 - <target name="-pre-compile-single">
2.352 - <!-- Empty placeholder for easier customization. -->
2.353 - <!-- You can override this target in the ../build.xml file. -->
2.354 - </target>
2.355 - <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
2.356 - <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
2.357 - <j2seproject3:force-recompile/>
2.358 - <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
2.359 - </target>
2.360 - <target name="-post-compile-single">
2.361 - <!-- Empty placeholder for easier customization. -->
2.362 - <!-- You can override this target in the ../build.xml file. -->
2.363 - </target>
2.364 - <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
2.365 - <!--
2.366 - ====================
2.367 - JAR BUILDING SECTION
2.368 - ====================
2.369 - -->
2.370 - <target depends="init" name="-pre-pre-jar">
2.371 - <dirname file="${dist.jar}" property="dist.jar.dir"/>
2.372 - <mkdir dir="${dist.jar.dir}"/>
2.373 - </target>
2.374 - <target name="-pre-jar">
2.375 - <!-- Empty placeholder for easier customization. -->
2.376 - <!-- You can override this target in the ../build.xml file. -->
2.377 - </target>
2.378 - <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
2.379 - <j2seproject1:jar/>
2.380 - </target>
2.381 - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
2.382 - <j2seproject1:jar manifest="${manifest.file}"/>
2.383 - </target>
2.384 - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
2.385 - <j2seproject1:jar manifest="${manifest.file}">
2.386 - <j2seproject1:manifest>
2.387 - <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
2.388 - </j2seproject1:manifest>
2.389 - </j2seproject1:jar>
2.390 - <echo>To run this application from the command line without Ant, try:</echo>
2.391 - <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
2.392 - <property location="${dist.jar}" name="dist.jar.resolved"/>
2.393 - <pathconvert property="run.classpath.with.dist.jar">
2.394 - <path path="${run.classpath}"/>
2.395 - <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
2.396 - </pathconvert>
2.397 - <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
2.398 - </target>
2.399 - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
2.400 - <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
2.401 - <pathconvert property="run.classpath.without.build.classes.dir">
2.402 - <path path="${run.classpath}"/>
2.403 - <map from="${build.classes.dir.resolved}" to=""/>
2.404 - </pathconvert>
2.405 - <pathconvert pathsep=" " property="jar.classpath">
2.406 - <path path="${run.classpath.without.build.classes.dir}"/>
2.407 - <chainedmapper>
2.408 - <flattenmapper/>
2.409 - <globmapper from="*" to="lib/*"/>
2.410 - </chainedmapper>
2.411 - </pathconvert>
2.412 - <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
2.413 - <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
2.414 - <fileset dir="${build.classes.dir}"/>
2.415 - <manifest>
2.416 - <attribute name="Main-Class" value="${main.class}"/>
2.417 - <attribute name="Class-Path" value="${jar.classpath}"/>
2.418 - </manifest>
2.419 - </copylibs>
2.420 - <echo>To run this application from the command line without Ant, try:</echo>
2.421 - <property location="${dist.jar}" name="dist.jar.resolved"/>
2.422 - <echo>java -jar "${dist.jar.resolved}"</echo>
2.423 - </target>
2.424 - <target name="-post-jar">
2.425 - <!-- Empty placeholder for easier customization. -->
2.426 - <!-- You can override this target in the ../build.xml file. -->
2.427 - </target>
2.428 - <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
2.429 - <!--
2.430 - =================
2.431 - EXECUTION SECTION
2.432 - =================
2.433 - -->
2.434 - <target depends="init,compile" description="Run a main class." name="run">
2.435 - <j2seproject1:java>
2.436 - <customize>
2.437 - <arg line="${application.args}"/>
2.438 - </customize>
2.439 - </j2seproject1:java>
2.440 - </target>
2.441 - <target name="-do-not-recompile">
2.442 - <property name="javac.includes.binary" value=""/>
2.443 - </target>
2.444 - <target depends="init,-do-not-recompile,compile-single" name="run-single">
2.445 - <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
2.446 - <j2seproject1:java classname="${run.class}"/>
2.447 - </target>
2.448 - <!--
2.449 - =================
2.450 - DEBUGGING SECTION
2.451 - =================
2.452 - -->
2.453 - <target depends="init" if="netbeans.home" name="-debug-start-debugger">
2.454 - <j2seproject1:nbjpdastart name="${debug.class}"/>
2.455 - </target>
2.456 - <target depends="init,compile" name="-debug-start-debuggee">
2.457 - <j2seproject3:debug>
2.458 - <customize>
2.459 - <arg line="${application.args}"/>
2.460 - </customize>
2.461 - </j2seproject3:debug>
2.462 - </target>
2.463 - <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
2.464 - <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
2.465 - <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
2.466 - </target>
2.467 - <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
2.468 - <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
2.469 - <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
2.470 - <j2seproject3:debug classname="${debug.class}"/>
2.471 - </target>
2.472 - <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
2.473 - <target depends="init" name="-pre-debug-fix">
2.474 - <fail unless="fix.includes">Must set fix.includes</fail>
2.475 - <property name="javac.includes" value="${fix.includes}.java"/>
2.476 - </target>
2.477 - <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
2.478 - <j2seproject1:nbjpdareload/>
2.479 - </target>
2.480 - <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
2.481 - <!--
2.482 - ===============
2.483 - JAVADOC SECTION
2.484 - ===============
2.485 - -->
2.486 - <target depends="init" name="-javadoc-build">
2.487 - <mkdir dir="${dist.javadoc.dir}"/>
2.488 - <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
2.489 - <classpath>
2.490 - <path path="${javac.classpath}"/>
2.491 - </classpath>
2.492 - <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
2.493 - <filename name="**/*.java"/>
2.494 - </fileset>
2.495 - </javadoc>
2.496 - </target>
2.497 - <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
2.498 - <nbbrowse file="${dist.javadoc.dir}/index.html"/>
2.499 - </target>
2.500 - <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
2.501 - <!--
2.502 - =========================
2.503 - JUNIT COMPILATION SECTION
2.504 - =========================
2.505 - -->
2.506 - <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
2.507 - <mkdir dir="${build.test.classes.dir}"/>
2.508 - </target>
2.509 - <target name="-pre-compile-test">
2.510 - <!-- Empty placeholder for easier customization. -->
2.511 - <!-- You can override this target in the ../build.xml file. -->
2.512 - </target>
2.513 - <target if="do.depend.true" name="-compile-test-depend">
2.514 - <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
2.515 - </target>
2.516 - <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
2.517 - <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
2.518 - <copy todir="${build.test.classes.dir}">
2.519 - <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
2.520 - </copy>
2.521 - </target>
2.522 - <target name="-post-compile-test">
2.523 - <!-- Empty placeholder for easier customization. -->
2.524 - <!-- You can override this target in the ../build.xml file. -->
2.525 - </target>
2.526 - <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
2.527 - <target name="-pre-compile-test-single">
2.528 - <!-- Empty placeholder for easier customization. -->
2.529 - <!-- You can override this target in the ../build.xml file. -->
2.530 - </target>
2.531 - <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
2.532 - <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
2.533 - <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
2.534 - <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
2.535 - <copy todir="${build.test.classes.dir}">
2.536 - <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
2.537 - </copy>
2.538 - </target>
2.539 - <target name="-post-compile-test-single">
2.540 - <!-- Empty placeholder for easier customization. -->
2.541 - <!-- You can override this target in the ../build.xml file. -->
2.542 - </target>
2.543 - <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
2.544 - <!--
2.545 - =======================
2.546 - JUNIT EXECUTION SECTION
2.547 - =======================
2.548 - -->
2.549 - <target depends="init" if="have.tests" name="-pre-test-run">
2.550 - <mkdir dir="${build.test.results.dir}"/>
2.551 - </target>
2.552 - <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
2.553 - <j2seproject3:junit testincludes="**/*Test.java"/>
2.554 - </target>
2.555 - <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
2.556 - <fail if="tests.failed">Some tests failed; see details above.</fail>
2.557 - </target>
2.558 - <target depends="init" if="have.tests" name="test-report"/>
2.559 - <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
2.560 - <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
2.561 - <target depends="init" if="have.tests" name="-pre-test-run-single">
2.562 - <mkdir dir="${build.test.results.dir}"/>
2.563 - </target>
2.564 - <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
2.565 - <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
2.566 - <j2seproject3:junit excludes="" includes="${test.includes}"/>
2.567 - </target>
2.568 - <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
2.569 - <fail if="tests.failed">Some tests failed; see details above.</fail>
2.570 - </target>
2.571 - <target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
2.572 - <!--
2.573 - =======================
2.574 - JUNIT DEBUGGING SECTION
2.575 - =======================
2.576 - -->
2.577 - <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
2.578 - <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
2.579 - <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
2.580 - <delete file="${test.report.file}"/>
2.581 - <mkdir dir="${build.test.results.dir}"/>
2.582 - <j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
2.583 - <customize>
2.584 - <syspropertyset>
2.585 - <propertyref prefix="test-sys-prop."/>
2.586 - <mapper from="test-sys-prop.*" to="*" type="glob"/>
2.587 - </syspropertyset>
2.588 - <arg value="${test.class}"/>
2.589 - <arg value="showoutput=true"/>
2.590 - <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
2.591 - <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
2.592 - </customize>
2.593 - </j2seproject3:debug>
2.594 - </target>
2.595 - <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
2.596 - <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
2.597 - </target>
2.598 - <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
2.599 - <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
2.600 - <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
2.601 - </target>
2.602 - <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
2.603 - <!--
2.604 - =========================
2.605 - APPLET EXECUTION SECTION
2.606 - =========================
2.607 - -->
2.608 - <target depends="init,compile-single" name="run-applet">
2.609 - <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
2.610 - <j2seproject1:java classname="sun.applet.AppletViewer">
2.611 - <customize>
2.612 - <arg value="${applet.url}"/>
2.613 - </customize>
2.614 - </j2seproject1:java>
2.615 - </target>
2.616 - <!--
2.617 - =========================
2.618 - APPLET DEBUGGING SECTION
2.619 - =========================
2.620 - -->
2.621 - <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
2.622 - <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
2.623 - <j2seproject3:debug classname="sun.applet.AppletViewer">
2.624 - <customize>
2.625 - <arg value="${applet.url}"/>
2.626 - </customize>
2.627 - </j2seproject3:debug>
2.628 - </target>
2.629 - <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
2.630 - <!--
2.631 - ===============
2.632 - CLEANUP SECTION
2.633 - ===============
2.634 - -->
2.635 - <target depends="init" name="deps-clean" unless="no.deps"/>
2.636 - <target depends="init" name="-do-clean">
2.637 - <delete dir="${build.dir}"/>
2.638 - <delete dir="${dist.dir}"/>
2.639 - </target>
2.640 - <target name="-post-clean">
2.641 - <!-- Empty placeholder for easier customization. -->
2.642 - <!-- You can override this target in the ../build.xml file. -->
2.643 - </target>
2.644 - <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
2.645 -</project>
3.1 --- a/task4/solution12/nbproject/genfiles.properties Fri Oct 17 17:54:38 2008 +0200
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,8 +0,0 @@
3.4 -build.xml.data.CRC32=2ab820eb
3.5 -build.xml.script.CRC32=58a52595
3.6 -build.xml.stylesheet.CRC32=be360661
3.7 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
3.8 -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
3.9 -nbproject/build-impl.xml.data.CRC32=b63e115b
3.10 -nbproject/build-impl.xml.script.CRC32=3bdfc4fa
3.11 -nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
4.1 --- a/task4/solution12/nbproject/project.properties Fri Oct 17 17:54:38 2008 +0200
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,68 +0,0 @@
4.4 -application.title=currency
4.5 -application.vendor=apidesign.org
4.6 -auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
4.7 -auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
4.8 -auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
4.9 -build.classes.dir=${build.dir}/classes
4.10 -build.classes.excludes=**/*.java,**/*.form
4.11 -# This directory is removed when the project is cleaned:
4.12 -build.dir=build
4.13 -build.generated.dir=${build.dir}/generated
4.14 -# Only compile against the classpath explicitly listed here:
4.15 -build.sysclasspath=ignore
4.16 -build.test.classes.dir=${build.dir}/test/classes
4.17 -build.test.results.dir=${build.dir}/test/results
4.18 -debug.classpath=\
4.19 - ${run.classpath}
4.20 -debug.test.classpath=\
4.21 - ${run.test.classpath}
4.22 -# This directory is removed when the project is cleaned:
4.23 -dist.dir=dist
4.24 -dist.jar=${dist.dir}/currency.jar
4.25 -dist.javadoc.dir=${dist.dir}/javadoc
4.26 -excludes=
4.27 -file.reference.junit-4.4.jar=../../libs/junit-4.4.jar
4.28 -file.reference.src-apifest08=..
4.29 -includes=**
4.30 -jar.compress=false
4.31 -javac.classpath=
4.32 -# Space-separated list of extra javac options
4.33 -javac.compilerargs=
4.34 -javac.deprecation=false
4.35 -javac.source=1.5
4.36 -javac.target=1.5
4.37 -javac.test.classpath=\
4.38 - ${javac.classpath}:\
4.39 - ${build.classes.dir}:\
4.40 - ${file.reference.junit-4.4.jar}
4.41 -javadoc.additionalparam=
4.42 -javadoc.author=false
4.43 -javadoc.encoding=
4.44 -javadoc.noindex=false
4.45 -javadoc.nonavbar=false
4.46 -javadoc.notree=false
4.47 -javadoc.private=false
4.48 -javadoc.splitindex=true
4.49 -javadoc.use=true
4.50 -javadoc.version=false
4.51 -javadoc.windowtitle=
4.52 -jnlp.codebase.type=local
4.53 -jnlp.codebase.url=file:/home/jarda/src/apifest08/currency/dist
4.54 -jnlp.descriptor=application
4.55 -jnlp.enabled=false
4.56 -jnlp.offline-allowed=false
4.57 -jnlp.signed=false
4.58 -meta.inf.dir=${src.dir}/META-INF
4.59 -platform.active=default_platform
4.60 -run.classpath=\
4.61 - ${javac.classpath}:\
4.62 - ${build.classes.dir}
4.63 -# Space-separated list of JVM arguments used when running the project
4.64 -# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
4.65 -# or test-sys-prop.name=value to set system properties for unit tests):
4.66 -run.jvmargs=
4.67 -run.test.classpath=\
4.68 - ${javac.test.classpath}:\
4.69 - ${build.test.classes.dir}
4.70 -src.dir=src
4.71 -test.src.dir=test
5.1 --- a/task4/solution12/nbproject/project.xml Fri Oct 17 17:54:38 2008 +0200
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,16 +0,0 @@
5.4 -<?xml version="1.0" encoding="UTF-8"?>
5.5 -<project xmlns="http://www.netbeans.org/ns/project/1">
5.6 - <type>org.netbeans.modules.java.j2seproject</type>
5.7 - <configuration>
5.8 - <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
5.9 - <name>Currency Convertor Solution 12</name>
5.10 - <minimum-ant-version>1.6.5</minimum-ant-version>
5.11 - <source-roots>
5.12 - <root id="src.dir"/>
5.13 - </source-roots>
5.14 - <test-roots>
5.15 - <root id="test.src.dir"/>
5.16 - </test-roots>
5.17 - </data>
5.18 - </configuration>
5.19 -</project>
6.1 --- a/task4/solution12/src/org/apidesign/apifest08/currency/Convertor.java Fri Oct 17 17:54:38 2008 +0200
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,297 +0,0 @@
6.4 -package org.apidesign.apifest08.currency;
6.5 -
6.6 -import java.util.ArrayList;
6.7 -import java.util.Calendar;
6.8 -import java.util.Currency;
6.9 -import java.util.Date;
6.10 -import java.util.Hashtable;
6.11 -import java.util.List;
6.12 -
6.13 -import org.apidesign.apifest08.currency.exceptions.ConvertorException;
6.14 -import org.apidesign.apifest08.currency.exceptions.InvalidCurrencyException;
6.15 -import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
6.16 -
6.17 -/**
6.18 - * This is the skeleton class for your API. You need to make it public, so it is accessible to your client code
6.19 - * (currently in Task1Test.java) file.
6.20 - * <p>
6.21 - * Feel free to create additional classes or rename this one, just keep all the API and its implementation in this
6.22 - * package. Do not spread it outside to other packages.
6.23 - */
6.24 -public class Convertor {
6.25 -
6.26 - private static Hashtable<String, List<ExchangeRate>> exchangeRates;
6.27 -
6.28 - private List<ExchangeRateInstance> exchangeRateInstances;
6.29 -
6.30 - /**
6.31 - * Constructor. Checks if all selected currencies are not null and has defined exchange rates for both
6.32 - * directions.
6.33 - * @param currencies currencies for new instance of convertor
6.34 - * @throws UnknownConvertorException if there are not defined exchange rates for both directions for each
6.35 - * pair of currencies
6.36 - */
6.37 - private Convertor(Currency[] currencies) throws UnknownConvertorException {
6.38 - exchangeRateInstances = new ArrayList<ExchangeRateInstance>();
6.39 -
6.40 - for (Currency currency1 : currencies) {
6.41 - for (Currency currency2 : currencies) {
6.42 - if(currency1 == null || currency2 == null) {
6.43 - throw new ConvertorException("None of the currencies should be null!!!");
6.44 - }
6.45 -
6.46 - if(!currency1.getCurrencyCode().equals(currency2.getCurrencyCode())) {
6.47 - String key = currency1.getCurrencyCode() + currency2.getCurrencyCode();
6.48 - if (!exchangeRates.containsKey(key)) {
6.49 - throw new UnknownConvertorException("Selected convertor (" + currency1.getCurrencyCode() + "->"
6.50 - + currency2.getCurrencyCode() + ") has not defined exchange rates!!!");
6.51 - }
6.52 -
6.53 - exchangeRateInstances.add(new ExchangeRateInstance(key, null, null));
6.54 - }
6.55 - }
6.56 - }
6.57 - }
6.58 -
6.59 - /**
6.60 - * Sets convertor rate for selected currencies.
6.61 - * @param currency1
6.62 - * one of the currencies we want to convert to/from
6.63 - * @param currency2
6.64 - * the other currency
6.65 - * @param rate
6.66 - * exchange rate from currency1 to currency2
6.67 - * @param unit
6.68 - * unit of exchangeRate (USD->CZK - unit=1, you exchange one dollar, SKK->CZK unit=100, exchange rate is for
6.69 - * 100SKK)
6.70 - */
6.71 - public static void setConvertorRates(Currency currency1, Currency currency2, double rate, double unit) {
6.72 - if (currency1 == null || currency2 == null) {
6.73 - throw new ConvertorException("None of the currencies should be null!!!");
6.74 - }
6.75 -
6.76 - if (rate <= 0 || unit <= 0) {
6.77 - throw new ConvertorException("Rate(" + rate + ") and unit(" + unit + ") has to be grater then zero!!!");
6.78 - }
6.79 -
6.80 - if (exchangeRates == null) {
6.81 - exchangeRates = new Hashtable<String, List<ExchangeRate>>();
6.82 - }
6.83 -
6.84 - String key12 = currency1.getCurrencyCode() + currency2.getCurrencyCode();
6.85 - String key21 = currency2.getCurrencyCode() + currency1.getCurrencyCode();
6.86 - double recountedRate = (unit / rate) * unit;
6.87 -
6.88 - exchangeRates.put(key12, addNewExchangeRate(key12, currency1, currency2, rate, unit, null, null));
6.89 - exchangeRates.put(key21, addNewExchangeRate(key21, currency2, currency1, recountedRate, unit, null, null));
6.90 - }
6.91 -
6.92 - public static Convertor limitExchangeRatesValidity(Convertor convertor, Date validFrom, Date validTo) {
6.93 - if(convertor == null || validFrom == null || validTo == null) {
6.94 - throw new ConvertorException("None of parameters of method limitExchangeRatesValidity should be null!!!");
6.95 - }
6.96 -
6.97 - List<ExchangeRateInstance> exchangeRateInstances = convertor.getExchangeRateInstances();
6.98 - for (ExchangeRateInstance exchangeRateInstance : exchangeRateInstances) {
6.99 - // get actual convertor rates for actual validity
6.100 - ExchangeRate actualExchangeRate = getExchangeRate(exchangeRateInstance.getKey(), exchangeRateInstance.getValidFrom(), exchangeRateInstance.getValidTo());
6.101 - // set new validity for theese rates
6.102 - actualExchangeRate.setValidFrom(validFrom);
6.103 - actualExchangeRate.setValidTo(validTo);
6.104 - // and for selected currency convertor
6.105 - exchangeRateInstance.setValidFrom(validFrom);
6.106 - exchangeRateInstance.setValidTo(substractSecond(validTo));
6.107 - }
6.108 -
6.109 - return convertor;
6.110 - }
6.111 -
6.112 - /**
6.113 - * Merge exchange rates of actual convertor with exchange rates from selected
6.114 - * convertor. If there are same currencies in both convertors, these from selected
6.115 - * convertor rewrites these in actual convertor.
6.116 - * @param convertor convertor to merge with actual one
6.117 - * @return convertor with merged exchange rates
6.118 - */
6.119 - public Convertor merge(Convertor convertor) {
6.120 - if(convertor == null) {
6.121 - throw new ConvertorException("It's impossible to merge with null convertor!!!");
6.122 - }
6.123 -
6.124 - exchangeRateInstances.addAll(convertor.getExchangeRateInstances());
6.125 - return this;
6.126 - }
6.127 -
6.128 - /**
6.129 - * Creates new instance of convertor.
6.130 - * @param currency1
6.131 - * one of the currencies we want to convert to/from
6.132 - * @param currency2
6.133 - * the other currency
6.134 - * @return new instance of convertor
6.135 - * @throws UnknownConvertorException
6.136 - * thrown if convertor for selected currencies has not been defined
6.137 - */
6.138 - public static Convertor getConvertorInstance(Currency... currencies) throws UnknownConvertorException {
6.139 - if(currencies.length < 2) {
6.140 - throw new ConvertorException("To get convertor instance, you have to select at least two currencies!!!");
6.141 - }
6.142 -
6.143 - return new Convertor(currencies);
6.144 - }
6.145 -
6.146 - /**
6.147 - * Converts selected amout of selected currency to other currency of this convertor instance.
6.148 - * @param amount
6.149 - * amount to convert
6.150 - * @param originalCurrency
6.151 - * currency of this amount
6.152 - * @param newCurrency
6.153 - * currency to which we want convert
6.154 - * @return converted amount
6.155 - * @throws InvalidCurrencyException
6.156 - * while one or both currencies doesn't fit for this convertor
6.157 - */
6.158 - public double convert(double amount, Currency originalCurrency, Currency newCurrency) throws InvalidCurrencyException {
6.159 - ExchangeRate actualyUsedExchangeRate = null;
6.160 -
6.161 - if (originalCurrency == null) {
6.162 - throw new ConvertorException("Original currency is null!!!");
6.163 - }
6.164 -
6.165 - if (newCurrency == null) {
6.166 - throw new ConvertorException("Destination currency is null!!!");
6.167 - }
6.168 -
6.169 - actualyUsedExchangeRate = getExchangeRate(originalCurrency, newCurrency);
6.170 -
6.171 - return countResult(actualyUsedExchangeRate, amount);
6.172 - }
6.173 -
6.174 - private double countResult(ExchangeRate actualyUsedExchangeRate, double amount) {
6.175 - return amount * actualyUsedExchangeRate.getRate() / actualyUsedExchangeRate.getUnit();
6.176 - }
6.177 -
6.178 - /**
6.179 - * Decides the direction of conversion and returns actual exchange rate
6.180 - * for selected currencies and actual moment.
6.181 - * @param actualCurrency
6.182 - * actual currency we want to convert
6.183 - * @return actual exchange rate of this convertor for selected currency
6.184 - */
6.185 - private ExchangeRate getExchangeRate(Currency originalCurrency, Currency newCurrency) throws InvalidCurrencyException {
6.186 - ExchangeRate actualyUsedExchangeRate = null;
6.187 -
6.188 - String key = originalCurrency.getCurrencyCode() + newCurrency.getCurrencyCode();
6.189 -
6.190 - ExchangeRateInstance exchangeRateInstance = findExchangeRateInstance(key);
6.191 - if(exchangeRateInstance != null) {
6.192 - actualyUsedExchangeRate = getExchangeRate(exchangeRateInstance.getKey(), exchangeRateInstance.getValidFrom(), exchangeRateInstance.getValidTo());
6.193 - } else {
6.194 - throw new InvalidCurrencyException("This convertor could not be used for converting selected currencies (" + originalCurrency.getCurrencyCode() + "->"
6.195 - + newCurrency.getCurrencyCode() + ") !!!");
6.196 - }
6.197 -
6.198 - return actualyUsedExchangeRate;
6.199 - }
6.200 -
6.201 - /**
6.202 - * Finds instance of exchange rate for actual instance of convertor and actual moment.
6.203 - * @param key exchange rate instance key
6.204 - * @return exchange rate instance
6.205 - */
6.206 - private ExchangeRateInstance findExchangeRateInstance(String key) {
6.207 - ExchangeRateInstance instance = null;
6.208 -
6.209 - Date now = new Date();
6.210 - for (ExchangeRateInstance item : exchangeRateInstances) {
6.211 - if(item.getKey().equals(key) && item.getValidFrom() == null && item.getValidTo() == null) {
6.212 - instance = item;
6.213 - break;
6.214 - } else if(item.getKey().equals(key) && item.getValidFrom().compareTo(now) <= 0 && item.getValidTo().compareTo(now) >= 0) {
6.215 - instance = item;
6.216 - break;
6.217 - }
6.218 - }
6.219 -
6.220 - return instance;
6.221 - }
6.222 -
6.223 -
6.224 - /**
6.225 - * Returns currency convertors for actual instance of convertor.
6.226 - * @return currency convertors for actual instance of convertor
6.227 - */
6.228 - private List<ExchangeRateInstance> getExchangeRateInstances() {
6.229 - return exchangeRateInstances;
6.230 - }
6.231 -
6.232 - private static ExchangeRate getExchangeRate(String key, Date validFrom, Date validTo) {
6.233 - ExchangeRate exchangeRate = null;
6.234 -
6.235 - List<ExchangeRate> currencyExchangeRates = exchangeRates.get(key);
6.236 - for (ExchangeRate currencyExchangeRate : currencyExchangeRates) {
6.237 - Date actValidFrom = currencyExchangeRate.getValidFrom();
6.238 - Date actValidTo = currencyExchangeRate.getValidTo();
6.239 -
6.240 - if(actValidFrom == null && validFrom == null && actValidTo == null && validTo == null) {
6.241 - exchangeRate = currencyExchangeRate;
6.242 - break;
6.243 - } else if(actValidFrom != null && validFrom != null && actValidTo != null && validTo != null && actValidFrom.compareTo(validFrom) <= 0 && actValidTo.compareTo(validTo) > 0) {
6.244 - exchangeRate = currencyExchangeRate;
6.245 - break;
6.246 - }
6.247 - }
6.248 -
6.249 - if(exchangeRate == null) {
6.250 - throw new ConvertorException("Exchange rate for actual exchange rate instance not found!!!");
6.251 - }
6.252 -
6.253 - return exchangeRate;
6.254 - }
6.255 -
6.256 - private static List<ExchangeRate> addNewExchangeRate(String key, Currency currency1, Currency currency2, double rate, double unit, Date validFrom, Date validTo) {
6.257 - List<ExchangeRate> actualExchangeRates = new ArrayList<ExchangeRate>();
6.258 - ExchangeRate newExchangeRate = null;
6.259 -
6.260 - if(exchangeRates.containsKey(key)) {
6.261 - List<ExchangeRate> rates = exchangeRates.get(key);
6.262 - for (ExchangeRate exchangeRate : rates) {
6.263 - if(exchangeRate.getValidFrom() == null && exchangeRate.getValidTo() == null && validFrom == null && validTo == null) {
6.264 - newExchangeRate = exchangeRate;
6.265 - break;
6.266 - } else if(exchangeRate.getValidFrom() != null && exchangeRate.getValidTo() != null && validFrom != null && validTo != null) {
6.267 - if(exchangeRate.getValidFrom().compareTo(validFrom) == 0 && exchangeRate.getValidTo().compareTo(validTo) == 0) {
6.268 - newExchangeRate = exchangeRate;
6.269 - break;
6.270 - }
6.271 - }
6.272 - }
6.273 - actualExchangeRates.addAll(rates);
6.274 - }
6.275 -
6.276 - if(newExchangeRate == null) {
6.277 - actualExchangeRates.add(new ExchangeRate(currency1, currency2, rate, unit, validFrom, validTo));
6.278 - } else {
6.279 - newExchangeRate.setRate(rate);
6.280 - newExchangeRate.setUnit(unit);
6.281 - actualExchangeRates.add(newExchangeRate);
6.282 - }
6.283 -
6.284 - return actualExchangeRates;
6.285 - }
6.286 -
6.287 - /**
6.288 - * Substracts one second from selected date.
6.289 - * @param date date
6.290 - * @return date -1s
6.291 - */
6.292 - private static Date substractSecond(Date date) {
6.293 - Calendar calendar = Calendar.getInstance();
6.294 - calendar.setTime(date);
6.295 - calendar.set(Calendar.SECOND, -1);
6.296 -
6.297 - return calendar.getTime();
6.298 - }
6.299 -
6.300 -}
7.1 --- a/task4/solution12/src/org/apidesign/apifest08/currency/ExchangeRate.java Fri Oct 17 17:54:38 2008 +0200
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,101 +0,0 @@
7.4 -package org.apidesign.apifest08.currency;
7.5 -
7.6 -import java.util.Currency;
7.7 -import java.util.Date;
7.8 -
7.9 -public class ExchangeRate {
7.10 -
7.11 - private Currency originalCurrency;
7.12 - private Currency newCurrency;
7.13 - private double unit;
7.14 - private double rate;
7.15 - private Date validFrom;
7.16 - private Date validTo;
7.17 -
7.18 - public ExchangeRate(Currency originalCurrency, Currency newCurrency, double rate, double unit) {
7.19 - this.newCurrency = newCurrency;
7.20 - this.originalCurrency = originalCurrency;
7.21 - this.rate = rate;
7.22 - this.unit = unit;
7.23 - }
7.24 -
7.25 - public ExchangeRate(Currency originalCurrency, Currency newCurrency, double rate, double unit, Date validFrom, Date validTo) {
7.26 - this.newCurrency = newCurrency;
7.27 - this.originalCurrency = originalCurrency;
7.28 - this.rate = rate;
7.29 - this.unit = unit;
7.30 - this.validFrom = validFrom;
7.31 - this.validTo = validTo;
7.32 - }
7.33 -
7.34 - /**
7.35 - * @return the originalCurrency
7.36 - */
7.37 - public Currency getOriginalCurrency() {
7.38 - return originalCurrency;
7.39 - }
7.40 -
7.41 - /**
7.42 - * @return the newCurrency
7.43 - */
7.44 - public Currency getNewCurrency() {
7.45 - return newCurrency;
7.46 - }
7.47 -
7.48 - /**
7.49 - * @return the unit
7.50 - */
7.51 - public double getUnit() {
7.52 - return unit;
7.53 - }
7.54 -
7.55 - /**
7.56 - * @param unit the unit to set
7.57 - */
7.58 - public void setUnit(double unit) {
7.59 - this.unit = unit;
7.60 - }
7.61 -
7.62 - /**
7.63 - * @return the rate
7.64 - */
7.65 - public double getRate() {
7.66 - return rate;
7.67 - }
7.68 -
7.69 - /**
7.70 - * @param rate the rate to set
7.71 - */
7.72 - public void setRate(double rate) {
7.73 - this.rate = rate;
7.74 - }
7.75 -
7.76 - /**
7.77 - * @return the validFrom
7.78 - */
7.79 - public Date getValidFrom() {
7.80 - return validFrom;
7.81 - }
7.82 -
7.83 - /**
7.84 - * @param validFrom the validFrom to set
7.85 - */
7.86 - public void setValidFrom(Date validFrom) {
7.87 - this.validFrom = validFrom;
7.88 - }
7.89 -
7.90 - /**
7.91 - * @return the validTo
7.92 - */
7.93 - public Date getValidTo() {
7.94 - return validTo;
7.95 - }
7.96 -
7.97 - /**
7.98 - * @param validTo the validTo to set
7.99 - */
7.100 - public void setValidTo(Date validTo) {
7.101 - this.validTo = validTo;
7.102 - }
7.103 -
7.104 -}
8.1 --- a/task4/solution12/src/org/apidesign/apifest08/currency/ExchangeRateInstance.java Fri Oct 17 17:54:38 2008 +0200
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,53 +0,0 @@
8.4 -package org.apidesign.apifest08.currency;
8.5 -
8.6 -import java.util.Date;
8.7 -
8.8 -public class ExchangeRateInstance {
8.9 -
8.10 - private String key;
8.11 - private Date validFrom;
8.12 - private Date validTo;
8.13 -
8.14 - public ExchangeRateInstance(String key, Date validFrom, Date validTo) {
8.15 - super();
8.16 - this.key = key;
8.17 - this.validFrom = validFrom;
8.18 - this.validTo = validTo;
8.19 - }
8.20 -
8.21 - /**
8.22 - * @return the validFrom
8.23 - */
8.24 - public Date getValidFrom() {
8.25 - return validFrom;
8.26 - }
8.27 -
8.28 - /**
8.29 - * @param validFrom the validFrom to set
8.30 - */
8.31 - public void setValidFrom(Date validFrom) {
8.32 - this.validFrom = validFrom;
8.33 - }
8.34 -
8.35 - /**
8.36 - * @return the validTo
8.37 - */
8.38 - public Date getValidTo() {
8.39 - return validTo;
8.40 - }
8.41 -
8.42 - /**
8.43 - * @param validTo the validTo to set
8.44 - */
8.45 - public void setValidTo(Date validTo) {
8.46 - this.validTo = validTo;
8.47 - }
8.48 -
8.49 - /**
8.50 - * @return the key
8.51 - */
8.52 - public String getKey() {
8.53 - return key;
8.54 - }
8.55 -
8.56 -}
9.1 --- a/task4/solution12/src/org/apidesign/apifest08/currency/exceptions/ConvertorException.java Fri Oct 17 17:54:38 2008 +0200
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,20 +0,0 @@
9.4 -package org.apidesign.apifest08.currency.exceptions;
9.5 -
9.6 -public class ConvertorException extends RuntimeException {
9.7 -
9.8 - public ConvertorException() {
9.9 - }
9.10 -
9.11 - public ConvertorException(String message) {
9.12 - super(message);
9.13 - }
9.14 -
9.15 - public ConvertorException(Throwable cause) {
9.16 - super(cause);
9.17 - }
9.18 -
9.19 - public ConvertorException(String message, Throwable cause) {
9.20 - super(message, cause);
9.21 - }
9.22 -
9.23 -}
10.1 --- a/task4/solution12/src/org/apidesign/apifest08/currency/exceptions/InvalidCurrencyException.java Fri Oct 17 17:54:38 2008 +0200
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,20 +0,0 @@
10.4 -package org.apidesign.apifest08.currency.exceptions;
10.5 -
10.6 -public class InvalidCurrencyException extends Exception {
10.7 -
10.8 - public InvalidCurrencyException() {
10.9 - }
10.10 -
10.11 - public InvalidCurrencyException(String message) {
10.12 - super(message);
10.13 - }
10.14 -
10.15 - public InvalidCurrencyException(Throwable cause) {
10.16 - super(cause);
10.17 - }
10.18 -
10.19 - public InvalidCurrencyException(String message, Throwable cause) {
10.20 - super(message, cause);
10.21 - }
10.22 -
10.23 -}
11.1 --- a/task4/solution12/src/org/apidesign/apifest08/currency/exceptions/UnknownConvertorException.java Fri Oct 17 17:54:38 2008 +0200
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,20 +0,0 @@
11.4 -package org.apidesign.apifest08.currency.exceptions;
11.5 -
11.6 -public class UnknownConvertorException extends Exception {
11.7 -
11.8 - public UnknownConvertorException() {
11.9 - }
11.10 -
11.11 - public UnknownConvertorException(String message) {
11.12 - super(message);
11.13 - }
11.14 -
11.15 - public UnknownConvertorException(Throwable cause) {
11.16 - super(cause);
11.17 - }
11.18 -
11.19 - public UnknownConvertorException(String message, Throwable cause) {
11.20 - super(message, cause);
11.21 - }
11.22 -
11.23 -}
12.1 --- a/task4/solution12/test/org/apidesign/apifest08/test/Task1Test.java Fri Oct 17 17:54:38 2008 +0200
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,174 +0,0 @@
12.4 -package org.apidesign.apifest08.test;
12.5 -
12.6 -import java.util.Currency;
12.7 -
12.8 -import junit.framework.TestCase;
12.9 -
12.10 -import org.apidesign.apifest08.currency.Convertor;
12.11 -import org.apidesign.apifest08.currency.exceptions.InvalidCurrencyException;
12.12 -import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
12.13 -
12.14 -/**
12.15 - * Finish the Convertor API, and then write bodies of methods inside of this class to match the given tasks. To fullfil
12.16 - * your task, use the API define in the <code>org.apidesign.apifest08.currency</code> package. Do not you reflection, or
12.17 - * other hacks as your code shall run without any runtime permissions.
12.18 - */
12.19 -public class Task1Test extends TestCase {
12.20 - public Task1Test(String testName) {
12.21 - super(testName);
12.22 - }
12.23 -
12.24 - @Override
12.25 - protected void setUp() throws Exception {
12.26 - }
12.27 -
12.28 - @Override
12.29 - protected void tearDown() throws Exception {
12.30 - }
12.31 -
12.32 - //
12.33 - // Imagine that there are three parts of the whole system:
12.34 - // 1. there is someone who knows the current exchange rate
12.35 - // 2. there is someone who wants to do the conversion
12.36 - // 3. there is the API between 1. and 2. which allows them to communicate
12.37 - // Please design such API
12.38 - //
12.39 -
12.40 - /**
12.41 - * Create convertor that understands two currencies, CZK and USD. Make 1 USD == 17 CZK. This is a method provided for
12.42 - * #1 group - e.g. those that know the exchange rate. They somehow need to create the objects from the API and tell
12.43 - * them the exchange rate. The API itself knows nothing about any rates, before the createCZKtoUSD method is called.
12.44 - * Creation of the convertor shall not require subclassing of any class or interface on the client side.
12.45 - * @return prepared convertor ready for converting USD to CZK and CZK to USD
12.46 - */
12.47 - public static Convertor createCZKtoUSD() {
12.48 - // set exchange rates
12.49 - Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("CZK"), 17d, 1d);
12.50 -
12.51 - // create new instance
12.52 - Convertor convertor = null;
12.53 - try {
12.54 - convertor = Convertor.getConvertorInstance(Currency.getInstance("USD"), Currency.getInstance("CZK"));
12.55 - } catch (UnknownConvertorException e) {
12.56 - e.printStackTrace();
12.57 - }
12.58 -
12.59 - return convertor;
12.60 - }
12.61 -
12.62 - /**
12.63 - * Create convertor that understands two currencies, CZK and SKK. Make 100 SKK == 80 CZK. Again this is method for the
12.64 - * #1 group - it knows the exchange rate, and needs to use the API to create objects with the exchange rate. Anyone
12.65 - * shall be ready to call this method without any other method being called previously. The API itself shall know
12.66 - * nothing about any rates, before this method is called. Creation of the convertor shall not require subclassing of
12.67 - * any class or interface on the client side.
12.68 - * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
12.69 - */
12.70 - public static Convertor createSKKtoCZK() {
12.71 - // set exchange rates
12.72 - Convertor.setConvertorRates(Currency.getInstance("SKK"), Currency.getInstance("CZK"), 80d, 100d);
12.73 -
12.74 - // create new instance
12.75 - Convertor convertor = null;
12.76 - try {
12.77 - convertor = Convertor.getConvertorInstance(Currency.getInstance("SKK"), Currency.getInstance("CZK"));
12.78 - } catch (UnknownConvertorException e) {
12.79 - e.printStackTrace();
12.80 - }
12.81 -
12.82 - return convertor;
12.83 - }
12.84 -
12.85 - //
12.86 - // now the methods for group #2 follow:
12.87 - // this group knows nothing about exchange rates, but knows how to use
12.88 - // the API to do conversions. It somehow (by calling one of the factory
12.89 - // methods) gets objects from the API and uses them to do the conversions.
12.90 - //
12.91 -
12.92 - /**
12.93 - * Use the convertor from <code>createCZKtoUSD</code> method and do few conversions with it.
12.94 - */
12.95 - public void testCurrencyCZKUSD() throws Exception {
12.96 - Convertor c = createCZKtoUSD();
12.97 - // convert $5 to CZK using c:
12.98 - double result = c.convert(5, Currency.getInstance("USD"), Currency.getInstance("CZK"));
12.99 - assertEquals("Result is not 85 CZK", 85.0, result);
12.100 -
12.101 - // convert $8 to CZK
12.102 - result = c.convert(8, Currency.getInstance("USD"), Currency.getInstance("CZK"));
12.103 - assertEquals("Result is not 136 CZK", 136.0, result);
12.104 -
12.105 - // convert 1003CZK to USD
12.106 - result = c.convert(1003, Currency.getInstance("CZK"), Currency.getInstance("USD"));
12.107 - assertEquals("Result is not 59 USD", 59.0, result);
12.108 - }
12.109 -
12.110 - /**
12.111 - * Use the convertor from <code>createSKKtoCZK</code> method and do few conversions with it.
12.112 - */
12.113 - public void testCurrencySKKCZK() throws Exception {
12.114 - Convertor c = createSKKtoCZK();
12.115 -
12.116 - // convert 16CZK using c:
12.117 - double result = c.convert(16, Currency.getInstance("CZK"), Currency.getInstance("SKK"));
12.118 - assertEquals("Result is not 20 SKK", 20.0, result);
12.119 -
12.120 - // convert 500SKK to CZK
12.121 - result = c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
12.122 - assertEquals("Result is not 400 CZK", 400.0, result);
12.123 - }
12.124 -
12.125 - /**
12.126 - * Verify that the CZK to USD convertor knows nothing about SKK.
12.127 - */
12.128 - public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
12.129 - Convertor c = createCZKtoUSD();
12.130 - boolean exceptionThrown = false;
12.131 -
12.132 - // convert $5 to SKK, the API shall say this is not possible
12.133 - try {
12.134 - c.convert(5, Currency.getInstance("USD"), Currency.getInstance("SKK"));
12.135 - exceptionThrown = false;
12.136 - } catch (InvalidCurrencyException e) {
12.137 - exceptionThrown = true;
12.138 - }
12.139 - assertEquals("It should be impossible to convert to SKK with USD->CZK convertor", true, exceptionThrown);
12.140 -
12.141 - // convert 500 SKK to CZK, the API shall say this is not possible
12.142 - try {
12.143 - c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
12.144 - exceptionThrown = false;
12.145 - } catch (InvalidCurrencyException e) {
12.146 - exceptionThrown = true;
12.147 - }
12.148 - assertEquals("It should be impossible to convert from SKK with USD->CZK convertor", true, exceptionThrown);
12.149 -
12.150 - }
12.151 -
12.152 - /**
12.153 - * Verify that the CZK to SKK convertor knows nothing about USD.
12.154 - */
12.155 - public void testCannotConvertToSKKwithSKKCZKConvertor() throws Exception {
12.156 - Convertor c = createSKKtoCZK();
12.157 - boolean exceptionThrown = false;
12.158 -
12.159 - // convert $5 to SKK, the API shall say this is not possible
12.160 - try {
12.161 - c.convert(5, Currency.getInstance("USD"), Currency.getInstance("SKK"));
12.162 - exceptionThrown = false;
12.163 - } catch (InvalidCurrencyException e) {
12.164 - exceptionThrown = true;
12.165 - }
12.166 - assertEquals("It should be impossible to convert form USD with SKK->CZK convertor", true, exceptionThrown);
12.167 -
12.168 - // convert 500 CZK to USD, the API shall say this is not possible
12.169 - try {
12.170 - c.convert(500, Currency.getInstance("CZK"), Currency.getInstance("USD"));
12.171 - exceptionThrown = false;
12.172 - } catch (InvalidCurrencyException e) {
12.173 - exceptionThrown = true;
12.174 - }
12.175 - assertEquals("It should be impossible to convert to USD with SKK->CZK convertor", true, exceptionThrown);
12.176 - }
12.177 -}
13.1 --- a/task4/solution12/test/org/apidesign/apifest08/test/Task2Test.java Fri Oct 17 17:54:38 2008 +0200
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,132 +0,0 @@
13.4 -package org.apidesign.apifest08.test;
13.5 -
13.6 -import java.util.Currency;
13.7 -
13.8 -import junit.framework.TestCase;
13.9 -
13.10 -import org.apidesign.apifest08.currency.Convertor;
13.11 -import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
13.12 -
13.13 -/** There are many currencies around the world and many banks manipulate
13.14 - * with more than one or two at the same time. As banks are usually the
13.15 - * best paying clients, which is true even in case of your Convertor API,
13.16 - * it is reasonable to listen to their requests.
13.17 - * <p>
13.18 - * The quest for today is to enhance your existing convertor API to hold
13.19 - * information about many currencies and allow conversions between any of them.
13.20 - * Also, as conversion rates for diferent currencies usually arise from various
13.21 - * bank departments, there is another important need. There is a need to
13.22 - * compose two convertors into one by merging all the information about
13.23 - * currencies they know about.
13.24 - */
13.25 -public class Task2Test extends TestCase {
13.26 - public Task2Test(String testName) {
13.27 - super(testName);
13.28 - }
13.29 -
13.30 - @Override
13.31 - protected void setUp() throws Exception {
13.32 - }
13.33 -
13.34 - @Override
13.35 - protected void tearDown() throws Exception {
13.36 - }
13.37 -
13.38 - // As in Task1Test, keep in mind, that there are three parts
13.39 - // of the whole system:
13.40 - // 1. there is someone who knows the current exchange rate
13.41 - // 2. there is someone who wants to do the conversion
13.42 - // 3. there is the API between 1. and 2. which allows them to communicate
13.43 - //
13.44 - // Please backward compatibly enhance your existing API to support following
13.45 - // usecases:
13.46 - //
13.47 -
13.48 - /** Create convertor that understands two currencies, CZK and
13.49 - * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
13.50 - * knows the exchange rate, and needs to use the API to create objects
13.51 - * with the exchange rate. Anyone shall be ready to call this method without
13.52 - * any other method being called previously. The API itself shall know
13.53 - * nothing about any rates, before this method is called.
13.54 - */
13.55 - public static Convertor createTripleConvertor() {
13.56 - // Rates: 1USD = 15CZK
13.57 - // Rates: 1USD = 20SKK
13.58 - // Rates: 75CZK = 100SKK
13.59 - // set exchange rates
13.60 - Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("CZK"), 15, 1);
13.61 - Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("SKK"), 20, 1);
13.62 - Convertor.setConvertorRates(Currency.getInstance("SKK"), Currency.getInstance("CZK"), 75, 100);
13.63 -
13.64 - // create new instance
13.65 - Convertor convertor = null;
13.66 - try {
13.67 - convertor = Convertor.getConvertorInstance(Currency.getInstance("USD"), Currency.getInstance("SKK"), Currency.getInstance("CZK"));
13.68 - } catch (UnknownConvertorException e) {
13.69 - e.printStackTrace();
13.70 - }
13.71 - return convertor;
13.72 - }
13.73 -
13.74 - /** Define convertor that understands three currencies. Use it.
13.75 - */
13.76 - public void testConvertorForUSDandCZKandSKK() throws Exception {
13.77 - Convertor c = createTripleConvertor();
13.78 -
13.79 - // convert $5 to CZK using c:
13.80 - double result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
13.81 - assertEquals("Result is not 75 CZK", 75.0, result);
13.82 -
13.83 - // convert $5 to SKK using c:
13.84 - result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("SKK"));
13.85 - assertEquals("Result is not 100 SKK", 100.0, result);
13.86 -
13.87 - // convert 200SKK to CZK using c:
13.88 - result = c.convert(200d, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
13.89 - assertEquals("Result is not 150 CZK", 150.0, result);
13.90 -
13.91 - // convert 200SKK to USK using c:
13.92 - result = c.convert(200d, Currency.getInstance("SKK"), Currency.getInstance("USD"));
13.93 - assertEquals("Result is not 10 USD", 10.0, result);
13.94 - }
13.95 -
13.96 - /** Merge all currency rates of convertor 1 with convertor 2.
13.97 - * Implement this using your API, preferably this method just delegates
13.98 - * into some API method which does the actual work, without requiring
13.99 - * API clients to code anything complex.
13.100 - */
13.101 - public static Convertor merge(Convertor one, Convertor two) {
13.102 - return one.merge(two);
13.103 - }
13.104 -
13.105 - /** Join the convertors from previous task, Task1Test and show that it
13.106 - * can be used to do reasonable conversions.
13.107 - */
13.108 - public void testConvertorComposition() throws Exception {
13.109 - Convertor c = merge(
13.110 - Task1Test.createCZKtoUSD(),
13.111 - Task1Test.createSKKtoCZK()
13.112 - );
13.113 -
13.114 - // convert $5 to CZK using c:
13.115 - double result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
13.116 - assertEquals("Result is not 85 CZK", 85.0, result);
13.117 -
13.118 - // convert $8 to CZK using c:
13.119 - result = c.convert(8d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
13.120 - assertEquals("Result is not 136 CZK", 136.0, result);
13.121 -
13.122 - // convert 1003CZK to USD using c:
13.123 - result = c.convert(1003d, Currency.getInstance("CZK"), Currency.getInstance("USD"));
13.124 - assertEquals("Result is not 59 USD", 59.0, result);
13.125 -
13.126 - // convert 16CZK using c:
13.127 - result = c.convert(16d, Currency.getInstance("CZK"), Currency.getInstance("SKK"));
13.128 - assertEquals("Result is not 20 SKK", 20.0, result);
13.129 -
13.130 - // convert 500SKK to CZK using c:
13.131 - result = c.convert(500d, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
13.132 - assertEquals("Result is not 400 CZK", 400.0, result);
13.133 -
13.134 - }
13.135 -}
14.1 --- a/task4/solution12/test/org/apidesign/apifest08/test/Task3Test.java Fri Oct 17 17:54:38 2008 +0200
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,145 +0,0 @@
14.4 -package org.apidesign.apifest08.test;
14.5 -
14.6 -import java.util.Currency;
14.7 -
14.8 -import junit.framework.TestCase;
14.9 -import org.apidesign.apifest08.currency.Convertor;
14.10 -import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
14.11 -
14.12 -/** The exchange rates are not always the same. They are changing. Day by day,
14.13 - * hour by hour, minute by minute. For every bank it is important to always
14.14 - * have the actual exchange rate available in the system. That is why let's
14.15 - * create a pluggable convertor that will always have up to date value of its
14.16 - * exchange rate.
14.17 - * <p>
14.18 - * The quest for today is to allow 3rd party developer to write a convertor
14.19 - * that adjusts its exchange rate everytime it is queried. This convertor is
14.20 - * written by independent vendor, the vendor knows only your Convertor API,
14.21 - * he does not know how the whole system looks and how the convertor is supposed
14.22 - * to be used.
14.23 - */
14.24 -public class Task3Test extends TestCase {
14.25 -
14.26 - private static double actualRate;
14.27 - private static boolean increasing;
14.28 -
14.29 - private static final double EXCHANGE_RATE_MAX = 16.0;
14.30 - private static final double EXCHANGE_RATE_MIN = 15.0;
14.31 -
14.32 - public Task3Test(String testName) {
14.33 - super(testName);
14.34 - }
14.35 -
14.36 - @Override
14.37 - protected void setUp() throws Exception {
14.38 - }
14.39 -
14.40 - @Override
14.41 - protected void tearDown() throws Exception {
14.42 - }
14.43 -
14.44 - // Backward compatibly enhance your existing API to support following
14.45 - // usecases:
14.46 - //
14.47 -
14.48 -
14.49 - /** Without knowing anything about the surrounding system, write an
14.50 - * implementation of convertor that will return different rates everytime
14.51 - * it is queried. Convert USD to CZK and vice versa. Start with the rate of
14.52 - * 1USD = 16CZK and adjust it in favor of CZK by 0.01 CZK with every query.
14.53 - * As soon as you reach 1USD = 15CZK adjust it by 0.01 CZK in favor of USD
14.54 - * until you reach 1USD = 16CZK
14.55 - *
14.56 - * @return new instance of "online" USD and CZK convertor starting with rate 1USD = 16CZK
14.57 - */
14.58 - public static Convertor createOnlineCZKUSDConvertor() {
14.59 - actualRate = 16.01;
14.60 - increasing = false;
14.61 -
14.62 - // sets actual exchange rates
14.63 - setRates();
14.64 -
14.65 - // create new instance
14.66 - Convertor convertor = null;
14.67 - try {
14.68 - convertor = Convertor.getConvertorInstance(Currency.getInstance("USD"), Currency.getInstance("CZK"));
14.69 - } catch (UnknownConvertorException e) {
14.70 - e.printStackTrace();
14.71 - }
14.72 -
14.73 - return convertor;
14.74 - }
14.75 -
14.76 - public void testFewQueriesForOnlineConvertor() throws Exception {
14.77 - Convertor c = createOnlineCZKUSDConvertor();
14.78 - doFewQueriesForOnlineConvertor(c);
14.79 - }
14.80 -
14.81 - static void doFewQueriesForOnlineConvertor(Convertor c) throws Exception {
14.82 - // convert $5 to CZK using c:
14.83 - double result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
14.84 - double expectedResult = actualRate * 5;
14.85 - assertEquals("Result is not " + expectedResult + " CZK", expectedResult, result);
14.86 -
14.87 - // change exchange rates
14.88 - setRates();
14.89 -
14.90 - // convert $8 to CZK using c:
14.91 - result = c.convert(8d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
14.92 - expectedResult = actualRate * 8;
14.93 - assertEquals("Result is not " + expectedResult + " CZK", expectedResult, result);
14.94 -
14.95 - // change exchange rates
14.96 - setRates();
14.97 -
14.98 - // convert $1 to CZK using c:
14.99 - result = c.convert(1d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
14.100 - expectedResult = actualRate * 1;
14.101 - assertEquals("Result is not " + expectedResult + " CZK", expectedResult, result);
14.102 -
14.103 - // change exchange rates
14.104 - setRates();
14.105 -
14.106 - // convert 15.97CZK to USD using c:
14.107 - result = c.convert(15.97d, Currency.getInstance("CZK"), Currency.getInstance("USD"));
14.108 - expectedResult = 15.97 / actualRate ;
14.109 - assertEquals("Result is not " + expectedResult + " USD", expectedResult, result);
14.110 - }
14.111 -
14.112 - /** Join the convertors and show they behave sane.
14.113 - */
14.114 - public void testOnlineConvertorComposition() throws Exception {
14.115 - Convertor c = Task2Test.merge(
14.116 - createOnlineCZKUSDConvertor(),
14.117 - Task1Test.createSKKtoCZK()
14.118 - );
14.119 -
14.120 - // convert 16CZK to SKK using c:
14.121 - double result = c.convert(16d, Currency.getInstance("CZK"), Currency.getInstance("SKK"));
14.122 - assertEquals("Result is not 20 SKK", 20d, result);
14.123 -
14.124 - // convert 500SKK to CZK using c:
14.125 - result = c.convert(500d, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
14.126 - assertEquals("Result is not 400 CZK", 400d, result);
14.127 -
14.128 - doFewQueriesForOnlineConvertor(c);
14.129 - }
14.130 -
14.131 - private static void setRates() {
14.132 - // logic for change of actual exchange rate
14.133 - if(increasing) {
14.134 - actualRate += 0.01;
14.135 - if(actualRate == EXCHANGE_RATE_MAX){
14.136 - increasing = false;
14.137 - }
14.138 - } else {
14.139 - actualRate -= 0.01;
14.140 - if(actualRate == EXCHANGE_RATE_MIN){
14.141 - increasing = true;
14.142 - }
14.143 - }
14.144 -
14.145 - // set exchange rates
14.146 - Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("CZK"), actualRate, 1d);
14.147 - }
14.148 -}
15.1 --- a/task4/solution12/test/org/apidesign/apifest08/test/Task4Test.java Fri Oct 17 17:54:38 2008 +0200
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,211 +0,0 @@
15.4 -package org.apidesign.apifest08.test;
15.5 -
15.6 -import java.text.SimpleDateFormat;
15.7 -import java.util.Currency;
15.8 -import java.util.Date;
15.9 -import junit.framework.TestCase;
15.10 -import org.apidesign.apifest08.currency.Convertor;
15.11 -import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
15.12 -
15.13 -/** The exchange rates are not always the same. They are changing. However
15.14 - * as in order to predict the future, one needs to understand own past. That is
15.15 - * why it is important to know the exchange rate as it was at any time during
15.16 - * the past.
15.17 - * <p>
15.18 - * Today's quest is to enhance the convertor API to deal with dates.
15.19 - * One shall be able to convert a currency at any date. Each currencies rate shall
15.20 - * be associated with a range between two Date objects. In order
15.21 - * to keep compatibility with old API that knew nothing about dates, the
15.22 - * rates associated then are applicable "for eternity". Any use of existing
15.23 - * convert methods that do not accept a Date argument, uses the current
15.24 - * System.currentTimeMillis() as default date.
15.25 - */
15.26 -public class Task4Test extends TestCase {
15.27 - public Task4Test(String testName) {
15.28 - super(testName);
15.29 - }
15.30 -
15.31 - @Override
15.32 - protected void setUp() throws Exception {
15.33 - }
15.34 -
15.35 - @Override
15.36 - protected void tearDown() throws Exception {
15.37 - }
15.38 -
15.39 - // Backward compatibly enhance your existing API to support following
15.40 - // usecases:
15.41 - //
15.42 -
15.43 - /** Takes a convertor with any rates associated and creates new convertor
15.44 - * that returns the same values as the old one for time between from to till.
15.45 - * Otherwise it returns no results. This is just a helper method that
15.46 - * shall call some real one in the API.
15.47 - *
15.48 - * @param old existing convertor
15.49 - * @param from initial date (inclusive)
15.50 - * @param till final date (exclusive)
15.51 - * @return new convertor
15.52 - */
15.53 - public static Convertor limitTo(Convertor old, Date from, Date till) {
15.54 - return Convertor.limitExchangeRatesValidity(old, from, till);
15.55 - }
15.56 -
15.57 -
15.58 - public void testCompositionOfLimitedConvertors() throws Exception {
15.59 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm zzz");
15.60 - Date d1 = format.parse("2008-10-01 00:00 GMT"); // 2008-10-01 0:00 GMT
15.61 - Date d2 = format.parse("2008-10-02 00:00 GMT"); // 2008-10-02 0:00 GMT
15.62 - Date d3 = format.parse("2008-10-03 00:00 GMT"); // 2008-10-03 0:00 GMT
15.63 -
15.64 - Convertor c = Task2Test.merge(
15.65 - limitTo(Task1Test.createCZKtoUSD(), d1, d2),
15.66 - limitTo(Task1Test.createSKKtoCZK(), d2, d3)
15.67 - );
15.68 -
15.69 - Date now = new Date();
15.70 -
15.71 - // convert $5 to CZK using c:
15.72 - double result = 0;
15.73 - boolean exceptionThrown = false;
15.74 - try {
15.75 - result = c.convert(5, Currency.getInstance("USD"), Currency.getInstance("CZK"));
15.76 - } catch (Exception e) {
15.77 - exceptionThrown = true;
15.78 - }
15.79 -
15.80 - if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) {
15.81 - System.out.println("Result.");
15.82 - assertEquals("Result is not 85 CZK.", 85d, result);
15.83 - } else {
15.84 - System.out.println("Exception.");
15.85 - assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown);
15.86 - }
15.87 -
15.88 - // convert $8 to CZK using c:
15.89 - exceptionThrown = false;
15.90 - try {
15.91 - result = c.convert(8, Currency.getInstance("USD"), Currency.getInstance("CZK"));
15.92 - } catch (Exception e) {
15.93 - exceptionThrown = true;
15.94 - }
15.95 -
15.96 - if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) {
15.97 - System.out.println("Result.");
15.98 - assertEquals("Result is not 136 CZK.", 136d, result);
15.99 - } else {
15.100 - System.out.println("Exception.");
15.101 - assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown);
15.102 - }
15.103 -
15.104 - // convert 1003CZK to USD using c:
15.105 - exceptionThrown = false;
15.106 - try {
15.107 - result = c.convert(1003, Currency.getInstance("CZK"), Currency.getInstance("USD"));
15.108 - } catch (Exception e) {
15.109 - exceptionThrown = true;
15.110 - }
15.111 -
15.112 - if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) {
15.113 - System.out.println("Result.");
15.114 - assertEquals("Result is not 59 USD.", 59d, result);
15.115 - } else {
15.116 - System.out.println("Exception.");
15.117 - assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown);
15.118 - }
15.119 -
15.120 - // convert 16CZK using c:
15.121 - exceptionThrown = false;
15.122 - try {
15.123 - result = c.convert(16, Currency.getInstance("CZK"), Currency.getInstance("SKK"));
15.124 - } catch (Exception e) {
15.125 - exceptionThrown = true;
15.126 - }
15.127 -
15.128 - if(d2.compareTo(now) <= 0 && d3.compareTo(now) > 0) {
15.129 - System.out.println("Result.");
15.130 - assertEquals("Result is not 20 SKK.", 20d, result);
15.131 - } else {
15.132 - System.out.println("Exception.");
15.133 - assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown);
15.134 - }
15.135 -
15.136 - // convert 500SKK to CZK using c:
15.137 - exceptionThrown = false;
15.138 - try {
15.139 - result = c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
15.140 - } catch (Exception e) {
15.141 - exceptionThrown = true;
15.142 - }
15.143 -
15.144 - if(d2.compareTo(now) <= 0 && d3.compareTo(now) > 0) {
15.145 - System.out.println("Result.");
15.146 - assertEquals("Result is not 400 CZK.", 400d, result);
15.147 - } else {
15.148 - System.out.println("Exception.");
15.149 - assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown);
15.150 - }
15.151 -
15.152 - }
15.153 -
15.154 - /** Create convertor that understands two currencies, CZK and
15.155 - * SKK. Make 100 SKK == 90 CZK.
15.156 - *
15.157 - * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
15.158 - */
15.159 - public static Convertor createSKKtoCZK2() {
15.160 - // set exchange rates
15.161 - Convertor.setConvertorRates(Currency.getInstance("SKK"), Currency.getInstance("CZK"), 90d, 100d);
15.162 -
15.163 - // create new instance
15.164 - Convertor convertor = null;
15.165 - try {
15.166 - convertor = Convertor.getConvertorInstance(Currency.getInstance("SKK"), Currency.getInstance("CZK"));
15.167 - } catch (UnknownConvertorException e) {
15.168 - e.printStackTrace();
15.169 - }
15.170 -
15.171 - return convertor;
15.172 - }
15.173 -
15.174 - public void testDateConvetorWithTwoDifferentRates() throws Exception {
15.175 -
15.176 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm zzz");
15.177 - Date d1 = format.parse("2008-10-01 00:00 GMT"); // 2008-10-01 0:00 GMT
15.178 - Date d2 = format.parse("2008-10-02 00:00 GMT"); // 2008-10-02 0:00 GMT
15.179 - Date d3 = format.parse("2008-10-03 00:00 GMT"); // 2008-10-03 0:00 GMT
15.180 -
15.181 - Convertor c = Task2Test.merge(
15.182 - limitTo(createSKKtoCZK2(), d1, d2),
15.183 - limitTo(Task1Test.createSKKtoCZK(), d2, d3)
15.184 - );
15.185 -
15.186 - // convert 500SKK to CZK using c at 2008-10-02 9:00 GMT:
15.187 - // assertEquals("Result is 400 CZK");
15.188 -
15.189 - // convert 500SKK to CZK using c at 2008-10-01 6:00 GMT:
15.190 - // assertEquals("Result is 450 CZK");
15.191 - Date now = new Date();
15.192 -
15.193 - // convert 500SKK to CZK using c:
15.194 - double result = 0;
15.195 - boolean exceptionThrown = false;
15.196 - try {
15.197 - result = c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
15.198 - } catch (Exception e) {
15.199 - exceptionThrown = true;
15.200 - }
15.201 -
15.202 - if(d1.compareTo(now) <= 0 && d2.compareTo(now) > 0) {
15.203 - System.out.println("\nResult");
15.204 - assertEquals("Result is not 450 CZK.", 450d, result);
15.205 - } else if(d2.compareTo(now) <= 0 && d3.compareTo(now) > 0) {
15.206 - System.out.println("\nResult");
15.207 - assertEquals("Result is not 400 CZK.", 400d, result);
15.208 - } else {
15.209 - System.out.println("\nException");
15.210 - assertEquals("There is no Exception while using convertor at wrong day!", true, exceptionThrown);
15.211 - }
15.212 - }
15.213 -
15.214 -}