1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/task3/solution14/build.xml Wed Oct 08 13:24:54 2008 +0200
1.3 @@ -0,0 +1,69 @@
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 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/task3/solution14/nbproject/build-impl.xml Wed Oct 08 13:24:54 2008 +0200
2.3 @@ -0,0 +1,642 @@
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_14-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 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/task3/solution14/nbproject/genfiles.properties Wed Oct 08 13:24:54 2008 +0200
3.3 @@ -0,0 +1,8 @@
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=1d0fd5f2
3.10 +nbproject/build-impl.xml.script.CRC32=951643da
3.11 +nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/task3/solution14/nbproject/project.properties Wed Oct 08 13:24:54 2008 +0200
4.3 @@ -0,0 +1,68 @@
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 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/task3/solution14/nbproject/project.xml Wed Oct 08 13:24:54 2008 +0200
5.3 @@ -0,0 +1,16 @@
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 14</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 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/task3/solution14/src/org/apidesign/apifest08/currency/Convertor.java Wed Oct 08 13:24:54 2008 +0200
6.3 @@ -0,0 +1,201 @@
6.4 +package org.apidesign.apifest08.currency;
6.5 +
6.6 +import java.util.ArrayList;
6.7 +import java.util.Collection;
6.8 +import java.util.Collections;
6.9 +import java.util.HashSet;
6.10 +import java.util.List;
6.11 +import java.util.Set;
6.12 +
6.13 +/** This is the skeleton class for your API. You need to make it public, so
6.14 + * it is accessible to your client code (currently in Task1Test.java) file.
6.15 + * <p>
6.16 + * Feel free to create additional classes or rename this one, just keep all
6.17 + * the API and its implementation in this package. Do not spread it outside
6.18 + * to other packages.
6.19 + */
6.20 +public final class Convertor {
6.21 + //version 1 fields
6.22 +
6.23 + private String currency1 = null;
6.24 + private String currency2 = null;
6.25 + private Rate rate = null;
6.26 +
6.27 + //version 2 field
6.28 + private List<CurrencyRate> currencyRates = null;
6.29 +
6.30 + //version - for compatible mode
6.31 + private int instanceVersion = 0; //compatible mode because of problem with empty currency and CZE -> CZE (1:2) rate
6.32 +
6.33 + Convertor(String currency1, String currency2, Rate rate) {
6.34 + instanceVersion = 1;
6.35 + if ((currency1 == null) || (currency2 == null) || (rate == null)) {
6.36 + throw new IllegalArgumentException("All arguments have to be non-null.");
6.37 + }
6.38 + this.currency1 = currency1;
6.39 + this.currency2 = currency2;
6.40 + this.rate = rate;
6.41 + }
6.42 +
6.43 + Convertor(final CurrencyRate ... currencyRate) {
6.44 + instanceVersion = 2;
6.45 +
6.46 + if (currencyRate == null) {
6.47 + throw new IllegalArgumentException("Parameter cannot be null.");
6.48 + }
6.49 + if (currencyRate.length == 0) {
6.50 + throw new IllegalArgumentException("CurrencyRates cannot be empty.");
6.51 + }
6.52 + Set<Pair<String,String>> currencies = new HashSet<Pair<String,String>>();
6.53 + List<CurrencyRate> curRates = new ArrayList<CurrencyRate>();
6.54 + for (int i = 0; i < currencyRate.length; i++) {
6.55 + CurrencyRate curRat = currencyRate[i];
6.56 + if (curRat == null) {
6.57 + throw new IllegalArgumentException("Parameter cannot be null.");
6.58 + }
6.59 + //check that currencyRate is not defined twice
6.60 + Pair<String, String> curPair= new Pair<String, String>(curRat.getCurrency1(), curRat.getCurrency2());
6.61 + if (currencies.contains(curPair)) {
6.62 + throw new IllegalArgumentException("Pair of currencies in a currency rate cannot be defined twice");
6.63 + }
6.64 + currencies.add(curPair);
6.65 +
6.66 + curRates.add(curRat);
6.67 + }
6.68 + this.currencyRates = Collections.unmodifiableList(curRates);
6.69 + }
6.70 +
6.71 + public double convert(String fromCurrency, String toCurrency, int amount) {
6.72 + if (instanceVersion == 1) {
6.73 + if ((fromCurrency == null) || (toCurrency == null)) {
6.74 + throw new IllegalArgumentException("All arguments have to be non-null.");
6.75 + }
6.76 +
6.77 + if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) {
6.78 + return rate.convertAtoB(amount);
6.79 + } else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) {
6.80 + return rate.convertBtoA(amount);
6.81 + } else {
6.82 + throw new IllegalArgumentException("Convertor " + this.toString() +
6.83 + " cannot work with currencies " + fromCurrency + " and " + toCurrency + ".");
6.84 + }
6.85 + } else { //instanceVersion == 2
6.86 + //find suitable convertor
6.87 + for (CurrencyRate curRate : currencyRates) {
6.88 + if ((curRate.getCurrency1().equals(fromCurrency))&&
6.89 + (curRate.getCurrency2().equals(toCurrency)))
6.90 + {
6.91 + return curRate.getRate().convertAtoB(amount);
6.92 + }
6.93 + }
6.94 + //suitable convertor not found, try to find inverse convertor
6.95 + for (CurrencyRate curRate : currencyRates) {
6.96 + if ((curRate.getCurrency2().equals(fromCurrency))&&
6.97 + (curRate.getCurrency1().equals(toCurrency)))
6.98 + {
6.99 + return curRate.getRate().convertBtoA(amount);
6.100 + }
6.101 + }
6.102 + //even inverse convertor not found
6.103 + throw new IllegalArgumentException("Cannot work with selected currencies.");
6.104 + }
6.105 + }
6.106 +
6.107 + public double convert(String fromCurrency, String toCurrency, double amount) {
6.108 + if (instanceVersion == 1) {
6.109 + if ((fromCurrency == null) || (toCurrency == null)) {
6.110 + throw new IllegalArgumentException("All arguments have to be non-null.");
6.111 + }
6.112 +
6.113 + if (currency1.equals(fromCurrency) && currency2.equals(toCurrency)) {
6.114 + return rate.convertAtoB(amount);
6.115 + } else if (currency2.equals(fromCurrency) && currency1.equals(toCurrency)) {
6.116 + return rate.convertBtoA(amount);
6.117 + } else {
6.118 + throw new IllegalArgumentException("Convertor " + this.toString() +
6.119 + " cannot work with currencies " + fromCurrency + " and " + toCurrency + ".");
6.120 + }
6.121 + } else { //instanceVersion == 2
6.122 + //find suitable convertor
6.123 + for (CurrencyRate curRate : currencyRates) {
6.124 + if ((curRate.getCurrency1().equals(fromCurrency))&&
6.125 + (curRate.getCurrency2().equals(toCurrency)))
6.126 + {
6.127 + return curRate.getRate().convertAtoB(amount);
6.128 + }
6.129 + }
6.130 + //suitable convertor not found, try to find inverse convertor
6.131 + for (CurrencyRate curRate : currencyRates) {
6.132 + if ((curRate.getCurrency2().equals(fromCurrency))&&
6.133 + (curRate.getCurrency1().equals(toCurrency)))
6.134 + {
6.135 + return curRate.getRate().convertBtoA(amount);
6.136 + }
6.137 + }
6.138 + //even inverse convertor not found
6.139 + throw new IllegalArgumentException("Cannot work with selected currencies.");
6.140 + }
6.141 + }
6.142 +
6.143 + /**
6.144 + * Returns currency rates. If instantiated with constructor from vesion 1
6.145 + * it creates new collection with one CurrencyRate.
6.146 + * Note, it can cause exception because of empty currencies or same currencies.
6.147 + */
6.148 + public Collection<CurrencyRate> getCurrencyRates() {
6.149 + if (instanceVersion == 1) {
6.150 + List<CurrencyRate> ret = new ArrayList<CurrencyRate>();
6.151 + ret.add(new CurrencyRateImpl(currency1, currency2, rate));
6.152 + return Collections.unmodifiableCollection(ret);
6.153 + } else { //instanceVersion == 2
6.154 + return currencyRates;
6.155 + }
6.156 + }
6.157 +
6.158 + @Override
6.159 + public String toString() {
6.160 + if (instanceVersion == 1) {
6.161 + return currency1 + currency2;
6.162 + } else { //instanceVersion == 2
6.163 + return super.toString(); //better be compatible in future :-)
6.164 + }
6.165 + }
6.166 +
6.167 + @Override
6.168 + public boolean equals(Object obj) {
6.169 + if (instanceVersion == 1) {
6.170 + if (obj == null) {
6.171 + return false;
6.172 + }
6.173 + if (getClass() != obj.getClass()) {
6.174 + return false;
6.175 + }
6.176 + final Convertor other = (Convertor) obj;
6.177 + if (this.currency1 != other.currency1 && (this.currency1 == null || !this.currency1.equals(other.currency1))) {
6.178 + return false;
6.179 + }
6.180 + if (this.currency2 != other.currency2 && (this.currency2 == null || !this.currency2.equals(other.currency2))) {
6.181 + return false;
6.182 + }
6.183 + if (this.rate != other.rate && (this.rate == null || !this.rate.equals(other.rate))) {
6.184 + return false;
6.185 + }
6.186 + return true;
6.187 + } else { //instanceVersion == 2
6.188 + return super.equals(obj); //better be compatible in future :-)
6.189 + }
6.190 + }
6.191 +
6.192 + @Override
6.193 + public int hashCode() {
6.194 + if (instanceVersion == 1) {
6.195 + int hash = 5;
6.196 + hash = 67 * hash + (this.currency1 != null ? this.currency1.hashCode() : 0);
6.197 + hash = 67 * hash + (this.currency2 != null ? this.currency2.hashCode() : 0);
6.198 + hash = 67 * hash + (this.rate != null ? this.rate.hashCode() : 0);
6.199 + return hash;
6.200 + } else { //instanceVersion == 2
6.201 + return super.hashCode(); //better be compatible in future :-)
6.202 + }
6.203 + }
6.204 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/task3/solution14/src/org/apidesign/apifest08/currency/ConvertorFactory.java Wed Oct 08 13:24:54 2008 +0200
7.3 @@ -0,0 +1,66 @@
7.4 +
7.5 +package org.apidesign.apifest08.currency;
7.6 +
7.7 +import java.util.ArrayList;
7.8 +import java.util.List;
7.9 +
7.10 +public final class ConvertorFactory {
7.11 +
7.12 + //Singleton
7.13 + private static ConvertorFactory thisFactory = new ConvertorFactory();
7.14 + private ConvertorFactory() {};
7.15 + public static ConvertorFactory newInstance() { //ehm, mistake - it should be named getInstance
7.16 + return thisFactory;
7.17 + }
7.18 +
7.19 + public Convertor createConvertor(String currency1, String currency2, Rate rate) {
7.20 + return new Convertor(currency1, currency2, rate);
7.21 + }
7.22 +
7.23 + public Convertor createConvertor(String currency1, String currency2, int amount1, int amount2) {
7.24 + return new Convertor(currency1, currency2, new Rate(amount1, amount2));
7.25 + }
7.26 +
7.27 + public Convertor createConvertor(String currency1, String currency2, double amount1, double amount2) {
7.28 + return new Convertor(currency1, currency2, new Rate(amount1, amount2));
7.29 + }
7.30 +
7.31 + public Convertor createConvertor(String currency1, String currency2, double rate) {
7.32 + return new Convertor(currency1, currency2, new Rate(rate));
7.33 + }
7.34 +
7.35 + public Convertor createConvertor(CurrencyRate currencyRate) {
7.36 + return new Convertor(currencyRate);
7.37 + }
7.38 +
7.39 + public Convertor createConvertor(CurrencyRate ... currencyRates) {
7.40 + return new Convertor(currencyRates);
7.41 + }
7.42 +
7.43 + public Convertor mergeConvertors(Convertor ... convertors) {
7.44 + if (convertors == null) {
7.45 + throw new IllegalArgumentException("Parameter cannot be null.");
7.46 + }
7.47 + if (convertors.length == 0) {
7.48 + throw new IllegalArgumentException("Convertors cannot be empty.");
7.49 + }
7.50 + List<CurrencyRate> currRates = new ArrayList<CurrencyRate>();
7.51 + List<Pair<String,String>> currPairs = new ArrayList<Pair<String,String>>();
7.52 + for (Convertor convertor : convertors) {
7.53 + if (convertor == null) {
7.54 + throw new IllegalArgumentException("Parameter cannot be null.");
7.55 + }
7.56 + for (CurrencyRate currRate : convertor.getCurrencyRates()) {
7.57 + Pair<String,String> currPair = new Pair<String,String>(currRate.getCurrency1(), currRate.getCurrency2());
7.58 + if (currPairs.contains(currPair)) {
7.59 + throw new IllegalArgumentException("Cannot merge - convertors contain same currency rates.");
7.60 + }
7.61 + currPairs.add(currPair);
7.62 + currRates.add(currRate);
7.63 + }
7.64 + }
7.65 +
7.66 + return new Convertor(currRates.toArray(new CurrencyRate[0]));
7.67 + }
7.68 +
7.69 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/task3/solution14/src/org/apidesign/apifest08/currency/CurrencyRate.java Wed Oct 08 13:24:54 2008 +0200
8.3 @@ -0,0 +1,8 @@
8.4 +package org.apidesign.apifest08.currency;
8.5 +
8.6 +
8.7 +public interface CurrencyRate {
8.8 + public String getCurrency1();
8.9 + public String getCurrency2();
8.10 + public Rate getRate();
8.11 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/task3/solution14/src/org/apidesign/apifest08/currency/CurrencyRateFactory.java Wed Oct 08 13:24:54 2008 +0200
9.3 @@ -0,0 +1,25 @@
9.4 +package org.apidesign.apifest08.currency;
9.5 +
9.6 +
9.7 +public final class CurrencyRateFactory {
9.8 +
9.9 + //Singleton
9.10 + private static CurrencyRateFactory thisFactory = new CurrencyRateFactory();
9.11 + private CurrencyRateFactory() {};
9.12 + public static CurrencyRateFactory getInstance() {
9.13 + return thisFactory;
9.14 + }
9.15 +
9.16 + public CurrencyRate createCurrencyRate(final String currency1, final String currency2, final Rate rate) {
9.17 + return new CurrencyRateImpl(currency1, currency2, rate);
9.18 + }
9.19 +
9.20 + public CurrencyRate createCurrencyRate(final String currency1, final String currency2, int amount1, int amount2) {
9.21 + return new CurrencyRateImpl(currency1, currency2, new Rate(amount1, amount2));
9.22 + }
9.23 +
9.24 + public CurrencyRate createCurrencyRate(final String currency1, final String currency2, double amount1, double amount2) {
9.25 + return new CurrencyRateImpl(currency1, currency2, new Rate(amount1, amount2));
9.26 + }
9.27 +
9.28 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/task3/solution14/src/org/apidesign/apifest08/currency/CurrencyRateImpl.java Wed Oct 08 13:24:54 2008 +0200
10.3 @@ -0,0 +1,37 @@
10.4 +
10.5 +package org.apidesign.apifest08.currency;
10.6 +
10.7 +public final class CurrencyRateImpl implements CurrencyRate {
10.8 + private String currency1;
10.9 + private String currency2;
10.10 + private Rate rate;
10.11 +
10.12 + CurrencyRateImpl(final String currency1, final String currency2, final Rate rate) {
10.13 + if ((currency1 == null)||(currency2 == null) || (rate == null)) {
10.14 + throw new IllegalArgumentException("Argument cannot be null.");
10.15 + }
10.16 + if ("".equals(currency1) || "".equals(currency2)) {
10.17 + throw new IllegalArgumentException("Name of currency cannot be empty string");
10.18 + }
10.19 + if (currency1.equals(currency2)) {
10.20 + throw new IllegalArgumentException("Currencies in rate cannot be the same");
10.21 + }
10.22 +
10.23 + this.currency1 = currency1;
10.24 + this.currency2 = currency2;
10.25 + this.rate = rate;
10.26 + }
10.27 +
10.28 + public String getCurrency1() {
10.29 + return currency1;
10.30 + }
10.31 +
10.32 + public String getCurrency2() {
10.33 + return currency2;
10.34 + }
10.35 +
10.36 + public Rate getRate(){
10.37 + return rate;
10.38 + }
10.39 +
10.40 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/task3/solution14/src/org/apidesign/apifest08/currency/Pair.java Wed Oct 08 13:24:54 2008 +0200
11.3 @@ -0,0 +1,53 @@
11.4 +
11.5 +package org.apidesign.apifest08.currency;
11.6 +
11.7 +
11.8 +public final class Pair<A,B> {
11.9 +
11.10 + private final A first;
11.11 + private final B second;
11.12 +
11.13 + public Pair(A first, B second) {
11.14 + this.first = first;
11.15 + this.second = second;
11.16 + }
11.17 +
11.18 + public A getFirst() { return first; }
11.19 + public B getSecond() { return second; }
11.20 +
11.21 + @Override
11.22 + public String toString() {
11.23 + return "(" + first + ", " + second + ")";
11.24 + }
11.25 +
11.26 + private static boolean equals(Object x, Object y) {
11.27 + return (x == null && y == null) || (x != null && x.equals(y));
11.28 + }
11.29 +
11.30 + @Override
11.31 + public int hashCode() {
11.32 + int hash = 5;
11.33 + hash = 59 * hash + (this.first != null ? this.first.hashCode() : 0);
11.34 + hash = 59 * hash + (this.second != null ? this.second.hashCode() : 0);
11.35 + return hash;
11.36 + }
11.37 +
11.38 + @Override
11.39 + public boolean equals(Object obj) {
11.40 + if (obj == null) {
11.41 + return false;
11.42 + }
11.43 + if (getClass() != obj.getClass()) {
11.44 + return false;
11.45 + }
11.46 + final Pair<A, B> other = (Pair<A, B>) obj;
11.47 + if (this.first != other.first && (this.first == null || !this.first.equals(other.first))) {
11.48 + return false;
11.49 + }
11.50 + if (this.second != other.second && (this.second == null || !this.second.equals(other.second))) {
11.51 + return false;
11.52 + }
11.53 + return true;
11.54 + }
11.55 +
11.56 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/task3/solution14/src/org/apidesign/apifest08/currency/Rate.java Wed Oct 08 13:24:54 2008 +0200
12.3 @@ -0,0 +1,68 @@
12.4 +
12.5 +package org.apidesign.apifest08.currency;
12.6 +
12.7 +public final class Rate {
12.8 +
12.9 + private double rate;
12.10 +
12.11 + public Rate(int amountA, int amountB) {
12.12 + rate = amountA / (double)amountB;
12.13 + if (rate <= 0) {
12.14 + throw new IllegalArgumentException("Exchange rate must be positive.");
12.15 + }
12.16 + }
12.17 +
12.18 + public Rate(double amountA, double amountB) {
12.19 + rate = amountA / amountB;
12.20 + if (rate <= 0) {
12.21 + throw new IllegalArgumentException("Exchange rate must be positive.");
12.22 + }
12.23 + }
12.24 +
12.25 + public Rate(double rate) {
12.26 + this.rate = rate;
12.27 + if (this.rate <= 0) {
12.28 + throw new IllegalArgumentException("Exchange rate must be positive.");
12.29 + }
12.30 + }
12.31 +
12.32 + public double convertAtoB(int a) {
12.33 + return a / rate;
12.34 + }
12.35 +
12.36 + public double convertAtoB(double a) {
12.37 + return a / rate;
12.38 + }
12.39 +
12.40 + public double convertBtoA(int b) {
12.41 + return b * rate;
12.42 + }
12.43 +
12.44 + public double convertBtoA(double b) {
12.45 + return b * rate;
12.46 + }
12.47 +
12.48 +
12.49 + @Override
12.50 + public boolean equals(Object obj) {
12.51 + if (obj == null) {
12.52 + return false;
12.53 + }
12.54 + if (getClass() != obj.getClass()) {
12.55 + return false;
12.56 + }
12.57 + final Rate other = (Rate) obj;
12.58 + return true;
12.59 + }
12.60 +
12.61 + @Override
12.62 + public int hashCode() {
12.63 + int hash = 5;
12.64 + return hash;
12.65 + }
12.66 +
12.67 + @Override
12.68 + public String toString() {
12.69 + return ""+rate;
12.70 + }
12.71 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/task3/solution14/test/org/apidesign/apifest08/test/Task1Test.java Wed Oct 08 13:24:54 2008 +0200
13.3 @@ -0,0 +1,144 @@
13.4 +package org.apidesign.apifest08.test;
13.5 +
13.6 +import junit.framework.TestCase;
13.7 +import org.apidesign.apifest08.currency.Convertor;
13.8 +import org.apidesign.apifest08.currency.ConvertorFactory;
13.9 +
13.10 +/** Finish the Convertor API, and then write bodies of methods inside
13.11 + * of this class to match the given tasks. To fullfil your task, use the
13.12 + * API define in the <code>org.apidesign.apifest08.currency</code> package.
13.13 + * Do not you reflection, or other hacks as your code
13.14 + * shall run without any runtime permissions.
13.15 + */
13.16 +public class Task1Test extends TestCase {
13.17 + public Task1Test(String testName) {
13.18 + super(testName);
13.19 + }
13.20 +
13.21 + @Override
13.22 + protected void setUp() throws Exception {
13.23 + }
13.24 +
13.25 + @Override
13.26 + protected void tearDown() throws Exception {
13.27 + }
13.28 +
13.29 + //
13.30 + // Imagine that there are three parts of the whole system:
13.31 + // 1. there is someone who knows the current exchange rate
13.32 + // 2. there is someone who wants to do the conversion
13.33 + // 3. there is the API between 1. and 2. which allows them to communicate
13.34 + // Please design such API
13.35 + //
13.36 +
13.37 + /** Create convertor that understands two currencies, CZK and
13.38 + * USD. Make 1 USD == 17 CZK. This is a method provided for #1 group -
13.39 + * e.g. those that know the exchange rate. They somehow need to create
13.40 + * the objects from the API and tell them the exchange rate. The API itself
13.41 + * knows nothing about any rates, before the createCZKtoUSD method is called.
13.42 + *
13.43 + * Creation of the convertor shall not require subclassing of any class
13.44 + * or interface on the client side.
13.45 + *
13.46 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
13.47 + */
13.48 + public static Convertor createCZKtoUSD() {
13.49 + return ConvertorFactory.newInstance().createConvertor("CZK", "USD", 17, 1);
13.50 + }
13.51 +
13.52 + /** Create convertor that understands two currencies, CZK and
13.53 + * SKK. Make 100 SKK == 80 CZK. Again this is method for the #1 group -
13.54 + * it knows the exchange rate, and needs to use the API to create objects
13.55 + * with the exchange rate. Anyone shall be ready to call this method without
13.56 + * any other method being called previously. The API itself shall know
13.57 + * nothing about any rates, before this method is called.
13.58 + *
13.59 + * Creation of the convertor shall not require subclassing of any class
13.60 + * or interface on the client side.
13.61 + *
13.62 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
13.63 + */
13.64 + public static Convertor createSKKtoCZK() {
13.65 + return ConvertorFactory.newInstance().createConvertor("SKK", "CZK", 100, 80);
13.66 + }
13.67 +
13.68 + //
13.69 + // now the methods for group #2 follow:
13.70 + // this group knows nothing about exchange rates, but knows how to use
13.71 + // the API to do conversions. It somehow (by calling one of the factory
13.72 + // methods) gets objects from the API and uses them to do the conversions.
13.73 + //
13.74 +
13.75 + /** Use the convertor from <code>createCZKtoUSD</code> method and do few conversions
13.76 + * with it.
13.77 + */
13.78 + public void testCurrencyCZKUSD() throws Exception {
13.79 + Convertor c = createCZKtoUSD();
13.80 + // convert $5 to CZK using c:
13.81 + assertEquals("Result is 85 CZK", 85.0, c.convert("USD", "CZK", 5));
13.82 +
13.83 + // convert $8 to CZK
13.84 + assertEquals("Result is 136 CZK", 136.0, c.convert("USD", "CZK", 8));
13.85 +
13.86 + // convert 1003CZK to USD
13.87 + assertEquals("Result is 59 CZK", 59.0, c.convert("CZK", "USD", 1003));
13.88 + }
13.89 +
13.90 + /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
13.91 + * with it.
13.92 + */
13.93 + public void testCurrencySKKCZK() throws Exception {
13.94 + Convertor c = createSKKtoCZK();
13.95 + // convert 16CZK using c:
13.96 + // assertEquals("Result is 20 SKK");
13.97 + assertEquals("Result is 20 SKK", 20.0, c.convert("CZK", "SKK", 16));
13.98 +
13.99 + // convert 500SKK to CZK
13.100 + // assertEquals("Result is 400 CZK");
13.101 + assertEquals("Result is 400 SKK", 400.0, c.convert("SKK", "CZK", 500));
13.102 + }
13.103 +
13.104 + /** Verify that the CZK to USD convertor knows nothing about SKK.
13.105 + */
13.106 + public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
13.107 + Convertor c = createCZKtoUSD();
13.108 + // convert $5 to SKK, the API shall say this is not possible
13.109 + try {
13.110 + c.convert("USD", "SKK", 5);
13.111 + fail("Converting SKK with CZKUSD convertor is impossible");
13.112 + } catch (IllegalArgumentException e){
13.113 + //ok
13.114 + }
13.115 +
13.116 + // convert 500 SKK to CZK, the API shall say this is not possible
13.117 + try {
13.118 + c.convert("SKK", "CZK", 500);
13.119 + fail("Converting SKK with CZKUSD convertor is impossible");
13.120 + } catch (IllegalArgumentException e){
13.121 + //ok
13.122 + }
13.123 +
13.124 + }
13.125 +
13.126 + /** Verify that the CZK to SKK convertor knows nothing about USD.
13.127 + */
13.128 + public void testCannotConvertToUSDwithCZKSKKConvertor() throws Exception {
13.129 + Convertor c = createSKKtoCZK();
13.130 + // convert $5 to SKK, the API shall say this is not possible
13.131 + try {
13.132 + c.convert("USD", "SKK", 5);
13.133 + fail("Converting SKK with SKKCZK convertor is impossible");
13.134 + } catch (IllegalArgumentException e){
13.135 + //ok
13.136 + }
13.137 +
13.138 + // convert 500 CZK to USD, the API shall say this is not possible
13.139 + try {
13.140 + c.convert("CZK", "USD", 500);
13.141 + fail("Converting USD with SKKCZK convertor is impossible");
13.142 + } catch (IllegalArgumentException e){
13.143 + //ok
13.144 + }
13.145 +
13.146 + }
13.147 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/task3/solution14/test/org/apidesign/apifest08/test/Task2Test.java Wed Oct 08 13:24:54 2008 +0200
14.3 @@ -0,0 +1,169 @@
14.4 +package org.apidesign.apifest08.test;
14.5 +
14.6 +import junit.framework.TestCase;
14.7 +import org.apidesign.apifest08.currency.Convertor;
14.8 +import org.apidesign.apifest08.currency.ConvertorFactory;
14.9 +import org.apidesign.apifest08.currency.CurrencyRate;
14.10 +import org.apidesign.apifest08.currency.CurrencyRateFactory;
14.11 +
14.12 +/** There are many currencies around the world and many banks manipulate
14.13 + * with more than one or two at the same time. As banks are usually the
14.14 + * best paying clients, which is true even in case of your Convertor API,
14.15 + * it is reasonable to listen to their requests.
14.16 + * <p>
14.17 + * The quest for today is to enhance your existing convertor API to hold
14.18 + * information about many currencies and allow conversions between any of them.
14.19 + * Also, as conversion rates for diferent currencies usually arise from various
14.20 + * bank departments, there is another important need. There is a need to
14.21 + * compose two convertors into one by merging all the information about
14.22 + * currencies they know about.
14.23 + */
14.24 +public class Task2Test extends TestCase {
14.25 + public Task2Test(String testName) {
14.26 + super(testName);
14.27 + }
14.28 +
14.29 + @Override
14.30 + protected void setUp() throws Exception {
14.31 + }
14.32 +
14.33 + @Override
14.34 + protected void tearDown() throws Exception {
14.35 + }
14.36 +
14.37 + // As in Task1Test, keep in mind, that there are three parts
14.38 + // of the whole system:
14.39 + // 1. there is someone who knows the current exchange rate
14.40 + // 2. there is someone who wants to do the conversion
14.41 + // 3. there is the API between 1. and 2. which allows them to communicate
14.42 + //
14.43 + // Please backward compatibly enhance your existing API to support following
14.44 + // usecases:
14.45 + //
14.46 +
14.47 + /** Create convertor that understands two currencies, CZK and
14.48 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
14.49 + * knows the exchange rate, and needs to use the API to create objects
14.50 + * with the exchange rate. Anyone shall be ready to call this method without
14.51 + * any other method being called previously. The API itself shall know
14.52 + * nothing about any rates, before this method is called.
14.53 + */
14.54 + public static Convertor createTripleConvertor() {
14.55 + // Rates: 1USD = 15CZK
14.56 + // Rates: 1USD = 20SKK
14.57 + // Rates: 75CZK = 100SKK
14.58 + CurrencyRate usdCzk = CurrencyRateFactory.getInstance().createCurrencyRate("USD", "CZK", 1, 15);
14.59 + CurrencyRate usdSkk = CurrencyRateFactory.getInstance().createCurrencyRate("USD", "SKK", 1, 20);
14.60 + CurrencyRate czkSkk = CurrencyRateFactory.getInstance().createCurrencyRate("CZK", "SKK", 75, 100);
14.61 + return ConvertorFactory.newInstance().createConvertor(usdCzk, usdSkk, czkSkk);
14.62 + }
14.63 +
14.64 + /** Define convertor that understands three currencies. Use it.
14.65 + */
14.66 + public void testConvertorForUSDandCZKandSKK() throws Exception {
14.67 + Convertor c = createTripleConvertor();
14.68 +
14.69 + // convert $5 to CZK using c:
14.70 + // assertEquals("Result is 75 CZK");
14.71 + assertEquals("Result is 75 CZK", 75.0, c.convert("USD", "CZK", 5));
14.72 +
14.73 + // convert $5 to SKK using c:
14.74 + // assertEquals("Result is 100 SKK");
14.75 + assertEquals("Result is 100 SKK", 100.0, c.convert("USD", "SKK", 5));
14.76 +
14.77 + // convert 200SKK to CZK using c:
14.78 + // assertEquals("Result is 150 CZK");
14.79 + assertEquals("Result is 150 CZK", 150.0, c.convert("SKK", "CZK", 200));
14.80 +
14.81 + // convert 200SKK to USD using c:
14.82 + // assertEquals("Result is 10 USD");
14.83 + assertEquals("Result is 10 USD", 10.0, c.convert("SKK", "USD", 200));
14.84 + }
14.85 +
14.86 + /** Merge all currency rates of convertor 1 with convertor 2.
14.87 + * Implement this using your API, preferably this method just delegates
14.88 + * into some API method which does the actual work, without requiring
14.89 + * API clients to code anything complex.
14.90 + */
14.91 + public static Convertor merge(Convertor one, Convertor two) {
14.92 + return ConvertorFactory.newInstance().mergeConvertors(one,two);
14.93 + }
14.94 +
14.95 + /** Join the convertors from previous task, Task1Test and show that it
14.96 + * can be used to do reasonable conversions.
14.97 + */
14.98 + public void testConvertorComposition() throws Exception {
14.99 + Convertor c = merge(
14.100 + Task1Test.createCZKtoUSD(),
14.101 + Task1Test.createSKKtoCZK()
14.102 + );
14.103 +
14.104 + // convert $5 to CZK using c:
14.105 + // assertEquals("Result is 85 CZK");
14.106 + assertEquals("Result is 85 CZK", 85.0, c.convert("USD", "CZK", 5));
14.107 +
14.108 + // convert $8 to CZK using c:
14.109 + // assertEquals("Result is 136 CZK");
14.110 + assertEquals("Result is 136 CZK", 136.0, c.convert("USD", "CZK", 8));
14.111 +
14.112 + // convert 1003CZK to USD using c:
14.113 + // assertEquals("Result is 59 USD");
14.114 + assertEquals("Result is 59 USD", 59.0, c.convert("CZK", "USD", 1003));
14.115 +
14.116 + // convert 16CZK using c:
14.117 + // assertEquals("Result is 20 SKK");
14.118 + assertEquals("Result is 20 SKK", 20.0, c.convert("CZK", "SKK", 16));
14.119 +
14.120 + // convert 500SKK to CZK using c:
14.121 + // assertEquals("Result is 400 CZK");
14.122 + assertEquals("Result is 400 CZK", 400.0, c.convert("SKK", "CZK", 500));
14.123 +
14.124 + //test exceptions
14.125 + Convertor one = Task1Test.createCZKtoUSD();
14.126 + Convertor two = Task1Test.createSKKtoCZK();
14.127 + Convertor three = Task1Test.createSKKtoCZK();
14.128 + try {
14.129 + ConvertorFactory.newInstance().mergeConvertors(one,two,three);
14.130 + fail();
14.131 + } catch (IllegalArgumentException e) {
14.132 + //ok
14.133 + }
14.134 +
14.135 + //test exceptions
14.136 + try {
14.137 + ConvertorFactory.newInstance().mergeConvertors(c, two);
14.138 + fail();
14.139 + } catch (IllegalArgumentException e) {
14.140 + //ok
14.141 + }
14.142 +
14.143 + //try convertors from version 1
14.144 + Convertor v1one = ConvertorFactory.newInstance().createConvertor("CZE", "CZE", 1, 2);
14.145 + assertEquals("CZE->CZE 1:2 10 expects 20", 20.0, v1one.convert("CZE", "CZE", 10));
14.146 + try {
14.147 + ConvertorFactory.newInstance().mergeConvertors(v1one, two);
14.148 + fail();
14.149 + } catch (IllegalArgumentException e) {
14.150 + //ok
14.151 + }
14.152 +
14.153 + Convertor v1two = ConvertorFactory.newInstance().createConvertor("EUR", "", 1, 2);
14.154 + assertEquals("EUR->'' 1:2 10 expects 20", 20.0, v1two.convert("EUR", "", 10));
14.155 + try {
14.156 + ConvertorFactory.newInstance().mergeConvertors(v1two, two);
14.157 + fail();
14.158 + } catch (IllegalArgumentException e) {
14.159 + //ok
14.160 + }
14.161 +
14.162 + Convertor v1three = ConvertorFactory.newInstance().createConvertor("EUR", "", 1, 2);
14.163 + assertEquals("''->EUR 1:2 10 expects 5", 5.0, v1three.convert("", "EUR", 10));
14.164 + try {
14.165 + ConvertorFactory.newInstance().mergeConvertors(v1three, two);
14.166 + fail();
14.167 + } catch (IllegalArgumentException e) {
14.168 + //ok
14.169 + }
14.170 +
14.171 + }
14.172 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/task3/solution14/test/org/apidesign/apifest08/test/Task3Test.java Wed Oct 08 13:24:54 2008 +0200
15.3 @@ -0,0 +1,104 @@
15.4 +package org.apidesign.apifest08.test;
15.5 +
15.6 +import junit.framework.TestCase;
15.7 +import org.apidesign.apifest08.currency.Convertor;
15.8 +
15.9 +/** The exchange rates are not always the same. They are changing. Day by day,
15.10 + * hour by hour, minute by minute. For every bank it is important to always
15.11 + * have the actual exchange rate available in the system. That is why let's
15.12 + * create a pluggable convertor that will always have up to date value of its
15.13 + * exchange rate.
15.14 + * <p>
15.15 + * The quest for today is to allow 3rd party developer to write a convertor
15.16 + * that adjusts its exchange rate everytime it is queried. This convertor is
15.17 + * written by independent vendor, the vendor knows only your Convertor API,
15.18 + * he does not know how the whole system looks and how the convertor is supposed
15.19 + * to be used.
15.20 + */
15.21 +public class Task3Test extends TestCase {
15.22 + public Task3Test(String testName) {
15.23 + super(testName);
15.24 + }
15.25 +
15.26 + @Override
15.27 + protected void setUp() throws Exception {
15.28 + }
15.29 +
15.30 + @Override
15.31 + protected void tearDown() throws Exception {
15.32 + }
15.33 +
15.34 + // Backward compatibly enhance your existing API to support following
15.35 + // usecases:
15.36 + //
15.37 +
15.38 +
15.39 + /** Without knowing anything about the surrounding system, write an
15.40 + * implementation of convertor that will return different rates everytime
15.41 + * it is queried. Convert USD to CZK and vice versa. Start with the rate of
15.42 + * 1USD = 16CZK and adjust it in favor of CZK by 0.01 CZK with every query.
15.43 + * As soon as you reach 1USD = 15CZK adjust it by 0.01 CZK in favor of USD
15.44 + * until you reach 1USD = 16CZK
15.45 + *
15.46 + * @return new instance of "online" USD and CZK convertor starting with rate 1USD = 16CZK
15.47 + */
15.48 + public static Convertor createOnlineCZKUSDConvertor() {
15.49 + // initial rate: 1USD = 16CZK
15.50 + // 2nd query 1USD = 15.99CZK
15.51 + // 3rd query 1USD = 15.98CZK
15.52 + // until 1USD = 15.00CZK
15.53 + // then 1USD = 15.01CZK
15.54 + // then 1USD = 15.02CZK
15.55 + // and so on and on up to 1USD = 16CZK
15.56 + // and then another round to 15, etc.
15.57 + return null;
15.58 + }
15.59 +
15.60 + public void testFewQueriesForOnlineConvertor() {
15.61 + if (Boolean.getBoolean("ignore.failing")) {
15.62 + // implement me!
15.63 + return;
15.64 + }
15.65 +
15.66 + Convertor c = createOnlineCZKUSDConvertor();
15.67 + doFewQueriesForOnlineConvertor(c);
15.68 + }
15.69 +
15.70 + static void doFewQueriesForOnlineConvertor(Convertor c) {
15.71 + // convert $5 to CZK using c:
15.72 + //assertEquals("Result is 80 CZK");
15.73 +
15.74 + // convert $8 to CZK using c:
15.75 + //assertEquals("Result is 127.92 CZK");
15.76 +
15.77 + // convert $1 to CZK using c:
15.78 + //assertEquals("Result is 15.98 CZK");
15.79 +
15.80 + // convert 15.97CZK to USD using c:
15.81 + //assertEquals("Result is 1$");
15.82 +
15.83 + fail("Implement me!");
15.84 + }
15.85 +
15.86 + /** Join the convertors and show they behave sane.
15.87 + */
15.88 + public void testOnlineConvertorComposition() throws Exception {
15.89 + if (Boolean.getBoolean("ignore.failing")) {
15.90 + // implement me!
15.91 + return;
15.92 + }
15.93 +
15.94 + Convertor c = Task2Test.merge(
15.95 + createOnlineCZKUSDConvertor(),
15.96 + Task1Test.createSKKtoCZK()
15.97 + );
15.98 +
15.99 + // convert 16CZK to SKK using c:
15.100 + // assertEquals("Result is 20 SKK");
15.101 +
15.102 + // convert 500SKK to CZK using c:
15.103 + // assertEquals("Result is 400 CZK");
15.104 +
15.105 + doFewQueriesForOnlineConvertor(c);
15.106 + }
15.107 +}