1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/task3/solution02/build.xml Tue Oct 07 11:05:34 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/solution02/nbproject/build-impl.xml Tue Oct 07 11:05:34 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_02-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/solution02/nbproject/genfiles.properties Tue Oct 07 11:05:34 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=848e6267
3.10 +nbproject/build-impl.xml.script.CRC32=6be86987
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/solution02/nbproject/project.properties Tue Oct 07 11:05:34 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/solution02/nbproject/project.xml Tue Oct 07 11:05:34 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 02</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/solution02/src/org/apidesign/apifest08/currency/CompositeConvertor.java Tue Oct 07 11:05:34 2008 +0200
6.3 @@ -0,0 +1,75 @@
6.4 +package org.apidesign.apifest08.currency;
6.5 +
6.6 +import java.io.Serializable;
6.7 +import java.util.Arrays;
6.8 +import java.util.Currency;
6.9 +
6.10 +/**
6.11 + * Convertor that is composed from other convertors.
6.12 + * @author lukas
6.13 + *
6.14 + */
6.15 +class CompositeConvertor implements ExtendedConvertor, Serializable {
6.16 +
6.17 + private static final long serialVersionUID = -2702026568249130055L;
6.18 +
6.19 + private final ExtendedConvertor[] convertors;
6.20 +
6.21 +
6.22 + public CompositeConvertor(ExtendedConvertor... convertors) {
6.23 + this.convertors = convertors.clone();
6.24 + for (ExtendedConvertor convertor: this.convertors)
6.25 + {
6.26 + if (convertor==null)
6.27 + {
6.28 + throw new NullPointerException("One of the convertors to be merged is null");
6.29 + }
6.30 + }
6.31 + }
6.32 +
6.33 + /**
6.34 + * Returns true if the composite contains convertor that supports given conversion.
6.35 + */
6.36 + public boolean isConversionSupported(Currency from, Currency to) {
6.37 + return findConvertorFor(from, to)!=null;
6.38 + }
6.39 +
6.40 +
6.41 + /**
6.42 + * If the composite contains convertor that supports given conversion, delegates to its convert method.
6.43 + * Throws {@link IllegalArgumentException} convertor supporting given conversion is not found.
6.44 + */
6.45 + public Money convert(Money amount, Currency destinationCurrency) throws IllegalArgumentException {
6.46 + ExtendedConvertor convertor = findConvertorFor(amount.getCurrency(), destinationCurrency);
6.47 + if (convertor!=null)
6.48 + {
6.49 + return convertor.convert(amount, destinationCurrency);
6.50 + }
6.51 + throw new IllegalArgumentException("Conversion not supported. Can not convert to "+destinationCurrency+".");
6.52 + }
6.53 +
6.54 + /**
6.55 + * Finds convertor for given currencies. If not found, returns null.
6.56 + * @param from
6.57 + * @param to
6.58 + * @return
6.59 + */
6.60 + ExtendedConvertor findConvertorFor(Currency from, Currency to) {
6.61 + //does linear search, in the future can cache the results.
6.62 + for (ExtendedConvertor convertor:convertors)
6.63 + {
6.64 + if (convertor.isConversionSupported(from, to))
6.65 + {
6.66 + return convertor;
6.67 + }
6.68 + }
6.69 + return null;
6.70 + }
6.71 +
6.72 +
6.73 + @Override
6.74 + public String toString() {
6.75 + return getClass().getName()+" converts "+Arrays.toString(convertors);
6.76 + }
6.77 +
6.78 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/task3/solution02/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 11:05:34 2008 +0200
7.3 @@ -0,0 +1,18 @@
7.4 +package org.apidesign.apifest08.currency;
7.5 +
7.6 +import java.util.Currency;
7.7 +
7.8 +
7.9 +/**
7.10 + * Converts currencies. To create an instance call {@link ConvertorFactory#createConvertor(Money, Money)}.
7.11 + */
7.12 +public interface Convertor {
7.13 + /**
7.14 + * Converts amount to its equivalent in the destination currency.
7.15 + * @param amount
7.16 + * @param destinationCurrency
7.17 + * @return
7.18 + * @throws IllegalArgumentException if currency of the amount is not supported or if it is not possible to convert it to the destination currency.
7.19 + */
7.20 + public Money convert(Money amount, Currency destinationCurrency) throws IllegalArgumentException;
7.21 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/task3/solution02/src/org/apidesign/apifest08/currency/ConvertorFactory.java Tue Oct 07 11:05:34 2008 +0200
8.3 @@ -0,0 +1,46 @@
8.4 +package org.apidesign.apifest08.currency;
8.5 +
8.6 +
8.7 +
8.8 +/**
8.9 + * Creates {@link Convertor} implementations.
8.10 + * @author lukas
8.11 + *
8.12 + */
8.13 +public class ConvertorFactory {
8.14 + private ConvertorFactory()
8.15 + {
8.16 + //nothing
8.17 + }
8.18 +
8.19 + /**
8.20 + * Creates {@link Convertor} that converts from sourceEquivalent.currency to destinationEquivalent.currency.
8.21 + * Exchange rate is set as equivalents. It means if you want to create USD to CZK convertor where USD1 = CZK17
8.22 + * call createConvertor(new MoneyImpl(1, USD), new MoneyImpl(17, CZK)). Convertor created by this method
8.23 + * rounds the result to two decimal places.
8.24 + * @param sourceEquivalent
8.25 + * @param destinationEquivalent
8.26 + * @return
8.27 + */
8.28 + public static final ExtendedConvertor createConvertor(Money sourceEquivalent, Money destinationEquivalent)
8.29 + {
8.30 + return mergeConvertors(
8.31 + new DefaultConvertor(sourceEquivalent, destinationEquivalent),
8.32 + new DefaultConvertor(destinationEquivalent ,sourceEquivalent)
8.33 + );
8.34 + }
8.35 +
8.36 + /**
8.37 + * Merges convertors. The resulting convertor has ability to do all conversions that its underlying
8.38 + * convertors could do. No consistency validation is done, inconsistent input will result in a convertor with
8.39 + * inconsistent behavior.
8.40 + * @param convertors
8.41 + * @return
8.42 + */
8.43 + public static final ExtendedConvertor mergeConvertors(ExtendedConvertor... convertors)
8.44 + {
8.45 + return new CompositeConvertor(convertors);
8.46 + }
8.47 +
8.48 +
8.49 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/task3/solution02/src/org/apidesign/apifest08/currency/DefaultConvertor.java Tue Oct 07 11:05:34 2008 +0200
9.3 @@ -0,0 +1,95 @@
9.4 +package org.apidesign.apifest08.currency;
9.5 +
9.6 +import java.io.Serializable;
9.7 +import java.math.BigDecimal;
9.8 +import java.math.RoundingMode;
9.9 +import java.util.Currency;
9.10 +
9.11 +/**
9.12 + * Default {@link Convertor} implementation. Exchange rate is stored as equivalents. It means if we have USD to CZK convertor and USD1 = CZK17
9.13 + * we store 1 in sourceEquivalent and 17 in destinationEquivalent. This class is immutable.
9.14 + * @author lukas
9.15 + *
9.16 + */
9.17 +class DefaultConvertor implements ExtendedConvertor, Serializable {
9.18 +
9.19 + private static final long serialVersionUID = 6660014633685135034L;
9.20 +
9.21 + /**
9.22 + * Equivalent in source currency.
9.23 + */
9.24 + private final BigDecimal sourceEquivalent;
9.25 +
9.26 + /**
9.27 + * Equivalent in destination currency.
9.28 + */
9.29 + private final BigDecimal destinationEquivalent;
9.30 +
9.31 + private final Currency sourceCurrency;
9.32 +
9.33 + private final Currency destinationCurrency;
9.34 +
9.35 + public DefaultConvertor(Money sourceEquivalent, Money destinationEquivalent) {
9.36 + super();
9.37 + if (BigDecimal.ZERO.compareTo(sourceEquivalent.getAmount())==0)
9.38 + {
9.39 + throw new IllegalArgumentException("Source equivalent amount can not be 0.");
9.40 + }
9.41 + if (BigDecimal.ZERO.compareTo(destinationEquivalent.getAmount())==0)
9.42 + {
9.43 + throw new IllegalArgumentException("Destination equivalent amount can not be 0.");
9.44 + }
9.45 + this.sourceEquivalent = sourceEquivalent.getAmount();
9.46 + this.destinationEquivalent = destinationEquivalent.getAmount();
9.47 + this.sourceCurrency = sourceEquivalent.getCurrency();
9.48 + this.destinationCurrency = destinationEquivalent.getCurrency();
9.49 + }
9.50 +
9.51 + public Money convert(Money amount, Currency destinationCurrency) {
9.52 + if (amount==null)
9.53 + {
9.54 + throw new NullPointerException("Money is null");
9.55 + }
9.56 + if (destinationCurrency==null)
9.57 + {
9.58 + throw new NullPointerException("destionationCurrency is null");
9.59 + }
9.60 + if (!amount.getCurrency().equals(getSourceCurrency()))
9.61 + {
9.62 + throw new IllegalArgumentException("Can not convert from "+amount.getCurrency()+". Converts between "+getSourceCurrency()+" and "+getDestinationCurrency());
9.63 + }
9.64 + if (!getDestinationCurrency().equals(destinationCurrency))
9.65 + {
9.66 + throw new IllegalArgumentException("Can not convert to "+destinationCurrency+". Converts between "+getSourceCurrency()+" and "+getDestinationCurrency());
9.67 + }
9.68 + BigDecimal sourceAmount = amount.getAmount();
9.69 + BigDecimal destinationAmount = sourceAmount.multiply(destinationEquivalent).divide(sourceEquivalent, 2, RoundingMode.HALF_UP);
9.70 + return new MoneyImpl(destinationAmount, getDestinationCurrency());
9.71 + }
9.72 +
9.73 + public boolean isConversionSupported(Currency from, Currency to) {
9.74 + return sourceCurrency.equals(from) && destinationCurrency.equals(to);
9.75 + }
9.76 +
9.77 + public BigDecimal getSourceEquivalent() {
9.78 + return sourceEquivalent;
9.79 + }
9.80 +
9.81 + public BigDecimal getDestinationEquivalent() {
9.82 + return destinationEquivalent;
9.83 + }
9.84 +
9.85 + public Currency getSourceCurrency() {
9.86 + return sourceCurrency;
9.87 + }
9.88 +
9.89 + public Currency getDestinationCurrency() {
9.90 + return destinationCurrency;
9.91 + }
9.92 +
9.93 + @Override
9.94 + public String toString() {
9.95 + return getClass().getName()+" converts "+getSourceCurrency()+" to "+getDestinationCurrency()+" "
9.96 + +getSourceCurrency()+getSourceEquivalent()+"="+getDestinationCurrency()+getDestinationEquivalent();
9.97 + }
9.98 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/task3/solution02/src/org/apidesign/apifest08/currency/ExtendedConvertor.java Tue Oct 07 11:05:34 2008 +0200
10.3 @@ -0,0 +1,18 @@
10.4 +package org.apidesign.apifest08.currency;
10.5 +
10.6 +import java.util.Currency;
10.7 +
10.8 +/**
10.9 + * Extended convertor interface.
10.10 + * @author lukas
10.11 + *
10.12 + */
10.13 +public interface ExtendedConvertor extends Convertor {
10.14 + /**
10.15 + * Returns true if given conversion is supported.
10.16 + * @param from
10.17 + * @param to
10.18 + * @return
10.19 + */
10.20 + public boolean isConversionSupported(Currency from, Currency to);
10.21 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/task3/solution02/src/org/apidesign/apifest08/currency/Money.java Tue Oct 07 11:05:34 2008 +0200
11.3 @@ -0,0 +1,29 @@
11.4 +package org.apidesign.apifest08.currency;
11.5 +
11.6 +import java.math.BigDecimal;
11.7 +import java.util.Currency;
11.8 +
11.9 +/**
11.10 + * Money representation. Default implementation {@link MoneyImpl} is provided. This interface can
11.11 + * be implemented by a DTO used in client application.
11.12 + * @author lukas
11.13 + *
11.14 + */
11.15 +/*
11.16 + * Whether we need such interface depends on the context. I can imagine than in a desktop application this interface
11.17 + * would be useless, Money could be a class. In J2EE environment it can be useful.
11.18 + */
11.19 +public interface Money {
11.20 +
11.21 + /**
11.22 + * Returns amount.
11.23 + * @return
11.24 + */
11.25 + public BigDecimal getAmount();
11.26 +
11.27 + /**
11.28 + * Returns currency.
11.29 + */
11.30 + public Currency getCurrency();
11.31 +
11.32 +}
11.33 \ No newline at end of file
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/task3/solution02/src/org/apidesign/apifest08/currency/MoneyImpl.java Tue Oct 07 11:05:34 2008 +0200
12.3 @@ -0,0 +1,121 @@
12.4 +package org.apidesign.apifest08.currency;
12.5 +
12.6 +import java.io.Serializable;
12.7 +import java.math.BigDecimal;
12.8 +import java.util.Currency;
12.9 +
12.10 +/**
12.11 + * Default implementation of {@link Money} interface. This class is immutable.
12.12 + * @author lukas
12.13 + *
12.14 + */
12.15 +public final class MoneyImpl implements Serializable, Money{
12.16 + private static final long serialVersionUID = -6091808475616516136L;
12.17 +
12.18 + private final BigDecimal amount;
12.19 +
12.20 + private final Currency currency;
12.21 +
12.22 + public MoneyImpl(BigDecimal amount, Currency currency) {
12.23 + if (amount==null) throw new NullPointerException("Amount is null");
12.24 + if (currency==null) throw new NullPointerException("Currency is null"+currency);
12.25 + this.amount = amount;
12.26 + this.currency = currency;
12.27 + }
12.28 +
12.29 +
12.30 +
12.31 + public MoneyImpl(long amount, Currency currency) {
12.32 + this(BigDecimal.valueOf(amount), currency);
12.33 + }
12.34 +
12.35 + public MoneyImpl(double amount, Currency currency) {
12.36 + this(BigDecimal.valueOf(amount), currency);
12.37 + }
12.38 +
12.39 + /**
12.40 + * Factory method.
12.41 + * @param amount
12.42 + * @param currency
12.43 + * @return
12.44 + */
12.45 + public static final Money money(BigDecimal amount, Currency currency)
12.46 + {
12.47 + return new MoneyImpl(amount, currency);
12.48 + }
12.49 + /**
12.50 + * Factory method.
12.51 + * @param amount
12.52 + * @param currency
12.53 + * @return
12.54 + */
12.55 + public static final Money money(long amount, Currency currency)
12.56 + {
12.57 + return new MoneyImpl(amount, currency);
12.58 + }
12.59 + /**
12.60 + * Factory method.
12.61 + * @param amount
12.62 + * @param currency
12.63 + * @return
12.64 + */
12.65 + public static final Money money(double amount, Currency currency)
12.66 + {
12.67 + return new MoneyImpl(amount, currency);
12.68 + }
12.69 +
12.70 + /**
12.71 + * Returns amount.
12.72 + * @return
12.73 + */
12.74 + public BigDecimal getAmount() {
12.75 + return amount;
12.76 + }
12.77 +
12.78 + /**
12.79 + * Returns currency.
12.80 + */
12.81 + public Currency getCurrency() {
12.82 + return currency;
12.83 + }
12.84 +
12.85 + @Override
12.86 + public int hashCode() {
12.87 + final int prime = 31;
12.88 + int result = 1;
12.89 + result = prime * result + ((amount == null) ? 0 : amount.hashCode());
12.90 + result = prime * result
12.91 + + ((currency == null) ? 0 : currency.hashCode());
12.92 + return result;
12.93 + }
12.94 +
12.95 + @Override
12.96 + public boolean equals(Object obj) {
12.97 + if (this == obj)
12.98 + return true;
12.99 + if (obj == null)
12.100 + return false;
12.101 + if (!(obj instanceof MoneyImpl))
12.102 + return false;
12.103 + MoneyImpl other = (MoneyImpl) obj;
12.104 + if (amount == null) {
12.105 + if (other.amount != null)
12.106 + return false;
12.107 + } else if (amount.compareTo(other.amount)!=0)
12.108 + return false;
12.109 + if (currency == null) {
12.110 + if (other.currency != null)
12.111 + return false;
12.112 + } else if (!currency.equals(other.currency))
12.113 + return false;
12.114 + return true;
12.115 + }
12.116 +
12.117 + @Override
12.118 + public String toString() {
12.119 + return getClass().getName()+"["+currency+amount+"]";
12.120 + }
12.121 +
12.122 +
12.123 +
12.124 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/task3/solution02/test/org/apidesign/apifest08/currency/CompositeConvertorTest.java Tue Oct 07 11:05:34 2008 +0200
13.3 @@ -0,0 +1,56 @@
13.4 +package org.apidesign.apifest08.currency;
13.5 +
13.6 +import static junit.framework.Assert.assertEquals;
13.7 +import static junit.framework.Assert.assertFalse;
13.8 +import static junit.framework.Assert.assertTrue;
13.9 +import static junit.framework.Assert.fail;
13.10 +import static org.apidesign.apifest08.test.Task1Test.CZK;
13.11 +import static org.apidesign.apifest08.test.Task1Test.SKK;
13.12 +import static org.apidesign.apifest08.test.Task1Test.USD;
13.13 +
13.14 +import org.junit.Test;
13.15 +
13.16 +public class CompositeConvertorTest {
13.17 + private static final ExtendedConvertor USD_CZK_CONVERTOR = ConvertorFactory.createConvertor(new MoneyImpl(1,USD), new MoneyImpl(17,CZK));
13.18 + private static final ExtendedConvertor SKK_CZK_CONVERTOR = ConvertorFactory.createConvertor(new MoneyImpl(100,SKK), new MoneyImpl(80,CZK));
13.19 +
13.20 + @Test
13.21 + public void testCompose()
13.22 + {
13.23 + ExtendedConvertor convertor = new CompositeConvertor(USD_CZK_CONVERTOR, SKK_CZK_CONVERTOR);
13.24 + assertTrue(convertor.isConversionSupported(CZK, SKK));
13.25 + assertTrue(convertor.isConversionSupported(CZK, USD));
13.26 + assertFalse(convertor.isConversionSupported(SKK, USD));
13.27 + assertEquals(new MoneyImpl(10,SKK), convertor.convert(new MoneyImpl(8,CZK), SKK));
13.28 + assertEquals(new MoneyImpl(2,USD), convertor.convert(new MoneyImpl(34,CZK), USD));
13.29 + try
13.30 + {
13.31 + convertor.convert(new MoneyImpl(34,SKK), USD);
13.32 + fail("Exception expected");
13.33 + }
13.34 + catch(IllegalArgumentException e)
13.35 + {
13.36 + assertTrue("Ok", true);
13.37 + }
13.38 + }
13.39 + @Test
13.40 + public void testEmpty()
13.41 + {
13.42 + ExtendedConvertor convertor = new CompositeConvertor();
13.43 + assertFalse(convertor.isConversionSupported(SKK, USD));
13.44 + try
13.45 + {
13.46 + convertor.convert(new MoneyImpl(34,SKK), USD);
13.47 + fail("Exception expected");
13.48 + }
13.49 + catch(IllegalArgumentException e)
13.50 + {
13.51 + assertTrue("Ok", true);
13.52 + }
13.53 + }
13.54 + @Test(expected=NullPointerException.class)
13.55 + public void testCreateNull()
13.56 + {
13.57 + new CompositeConvertor(USD_CZK_CONVERTOR, null);
13.58 + }
13.59 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/task3/solution02/test/org/apidesign/apifest08/test/ConvertorFactoryTest.java Tue Oct 07 11:05:34 2008 +0200
14.3 @@ -0,0 +1,52 @@
14.4 +package org.apidesign.apifest08.test;
14.5 +
14.6 +import static junit.framework.Assert.assertNotNull;
14.7 +import static org.apidesign.apifest08.test.Task1Test.CZK;
14.8 +import static org.apidesign.apifest08.test.Task1Test.USD;
14.9 +import static org.junit.Assert.assertEquals;
14.10 +import static org.junit.Assert.assertTrue;
14.11 +import static org.junit.Assert.fail;
14.12 +
14.13 +import org.apidesign.apifest08.currency.Convertor;
14.14 +import org.apidesign.apifest08.currency.ConvertorFactory;
14.15 +import org.apidesign.apifest08.currency.MoneyImpl;
14.16 +import org.junit.Test;
14.17 +
14.18 +
14.19 +public class ConvertorFactoryTest {
14.20 + @Test(expected=NullPointerException.class)
14.21 + public void testNullSource()
14.22 + {
14.23 + ConvertorFactory.createConvertor(null, new MoneyImpl(1,USD));
14.24 + }
14.25 + @Test(expected=NullPointerException.class)
14.26 + public void testNullDestination()
14.27 + {
14.28 + ConvertorFactory.createConvertor(new MoneyImpl(17,CZK), null);
14.29 + }
14.30 + @Test
14.31 + public void testOk()
14.32 + {
14.33 + assertNotNull(ConvertorFactory.createConvertor(new MoneyImpl(17,CZK), new MoneyImpl(1,USD)));
14.34 + }
14.35 + @Test
14.36 + public void testOkDecimalRate()
14.37 + {
14.38 + Convertor c = ConvertorFactory.createConvertor(new MoneyImpl(1,CZK), new MoneyImpl(1d/17d,USD));
14.39 + assertNotNull(c);
14.40 + assertEquals(new MoneyImpl(17,CZK),c.convert(new MoneyImpl(1,USD), CZK));
14.41 + }
14.42 + @Test
14.43 + public void testZeroEquivalentRate()
14.44 + {
14.45 + try
14.46 + {
14.47 + ConvertorFactory.createConvertor(new MoneyImpl(1,CZK), new MoneyImpl(0,USD));
14.48 + fail("Exception expected");
14.49 + }
14.50 + catch(IllegalArgumentException e)
14.51 + {
14.52 + assertTrue("OK",true);
14.53 + }
14.54 + }
14.55 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/task3/solution02/test/org/apidesign/apifest08/test/ConvertorTest.java Tue Oct 07 11:05:34 2008 +0200
15.3 @@ -0,0 +1,44 @@
15.4 +package org.apidesign.apifest08.test;
15.5 +
15.6 +import static junit.framework.Assert.assertEquals;
15.7 +import static junit.framework.Assert.assertFalse;
15.8 +import static junit.framework.Assert.assertTrue;
15.9 +import static org.apidesign.apifest08.test.Task1Test.CZK;
15.10 +import static org.apidesign.apifest08.test.Task1Test.SKK;
15.11 +import static org.apidesign.apifest08.test.Task1Test.USD;
15.12 +
15.13 +import java.math.BigDecimal;
15.14 +
15.15 +import org.apidesign.apifest08.currency.ConvertorFactory;
15.16 +import org.apidesign.apifest08.currency.ExtendedConvertor;
15.17 +import org.apidesign.apifest08.currency.Money;
15.18 +import org.apidesign.apifest08.currency.MoneyImpl;
15.19 +import org.junit.Test;
15.20 +
15.21 +
15.22 +public class ConvertorTest {
15.23 +
15.24 + private static final ExtendedConvertor CZK_TO_USD_CONVERTOR = ConvertorFactory.createConvertor(new MoneyImpl(17,CZK), new MoneyImpl(1,USD));
15.25 + @Test
15.26 + public void testConvertSmall()
15.27 + {
15.28 + Money converted = CZK_TO_USD_CONVERTOR.convert(new MoneyImpl(0.17,CZK),USD);
15.29 + assertEquals(new MoneyImpl(new BigDecimal("0.01"),USD),converted);
15.30 + assertEquals(USD,converted.getCurrency());
15.31 + }
15.32 + @Test
15.33 + public void testConvertSmallReverse()
15.34 + {
15.35 + Money converted = CZK_TO_USD_CONVERTOR.convert(new MoneyImpl(0.01,USD),CZK);
15.36 + assertEquals(new MoneyImpl(new BigDecimal("0.17"),CZK),converted);
15.37 + }
15.38 + @Test
15.39 + public void testSupports()
15.40 + {
15.41 + assertTrue(CZK_TO_USD_CONVERTOR.isConversionSupported(USD,CZK));
15.42 + assertTrue(CZK_TO_USD_CONVERTOR.isConversionSupported(CZK,USD));
15.43 + assertFalse(CZK_TO_USD_CONVERTOR.isConversionSupported(CZK,CZK));
15.44 + assertFalse(CZK_TO_USD_CONVERTOR.isConversionSupported(CZK,SKK));
15.45 +
15.46 + }
15.47 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/task3/solution02/test/org/apidesign/apifest08/test/MoneyTest.java Tue Oct 07 11:05:34 2008 +0200
16.3 @@ -0,0 +1,24 @@
16.4 +package org.apidesign.apifest08.test;
16.5 +
16.6 +import static junit.framework.Assert.assertEquals;
16.7 +import static org.apidesign.apifest08.test.Task1Test.CZK;
16.8 +
16.9 +import java.math.BigDecimal;
16.10 +
16.11 +import org.apidesign.apifest08.currency.MoneyImpl;
16.12 +import org.junit.Test;
16.13 +
16.14 +public class MoneyTest {
16.15 + @Test(expected=NullPointerException.class)
16.16 + public void testNullAmount(){
16.17 + new MoneyImpl(null,CZK);
16.18 + }
16.19 + @Test(expected=NullPointerException.class)
16.20 + public void testNullCurrency(){
16.21 + new MoneyImpl(1,null);
16.22 + }
16.23 + @Test
16.24 + public void testOk(){
16.25 + assertEquals(0,new MoneyImpl(123,CZK).getAmount().compareTo(new BigDecimal("123")));
16.26 + }
16.27 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/task3/solution02/test/org/apidesign/apifest08/test/Task1Test.java Tue Oct 07 11:05:34 2008 +0200
17.3 @@ -0,0 +1,160 @@
17.4 +package org.apidesign.apifest08.test;
17.5 +
17.6 +import java.util.Currency;
17.7 +
17.8 +import junit.framework.TestCase;
17.9 +
17.10 +import org.apidesign.apifest08.currency.Convertor;
17.11 +import org.apidesign.apifest08.currency.ConvertorFactory;
17.12 +import org.apidesign.apifest08.currency.MoneyImpl;
17.13 +
17.14 +/** Finish the Convertor API, and then write bodies of methods inside
17.15 + * of this class to match the given tasks. To fullfil your task, use the
17.16 + * API define in the <code>org.apidesign.apifest08.currency</code> package.
17.17 + * Do not you reflection, or other hacks as your code
17.18 + * shall run without any runtime permissions.
17.19 + */
17.20 +public class Task1Test extends TestCase {
17.21 +
17.22 + public static final Currency USD = Currency.getInstance("USD");
17.23 + public static final Currency CZK = Currency.getInstance("CZK");
17.24 + public static final Currency SKK = Currency.getInstance("SKK");
17.25 +
17.26 + public Task1Test(String testName) {
17.27 + super(testName);
17.28 + }
17.29 +
17.30 + @Override
17.31 + protected void setUp() throws Exception {
17.32 + }
17.33 +
17.34 + @Override
17.35 + protected void tearDown() throws Exception {
17.36 + }
17.37 +
17.38 + //
17.39 + // Imagine that there are three parts of the whole system:
17.40 + // 1. there is someone who knows the current exchange rate
17.41 + // 2. there is someone who wants to do the conversion
17.42 + // 3. there is the API between 1. and 2. which allows them to communicate
17.43 + // Please design such API
17.44 + //
17.45 +
17.46 + /** Create convertor that understands two currencies, CZK and
17.47 + * USD. Make 1 USD == 17 CZK. This is a method provided for #1 group -
17.48 + * e.g. those that know the exchange rate. They somehow need to create
17.49 + * the objects from the API and tell them the exchange rate. The API itself
17.50 + * knows nothing about any rates, before the createCZKtoUSD method is called.
17.51 + *
17.52 + * Creation of the convertor shall not require subclassing of any class
17.53 + * or interface on the client side.
17.54 + *
17.55 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
17.56 + */
17.57 + public static Convertor createCZKtoUSD() {
17.58 + return ConvertorFactory.createConvertor(new MoneyImpl(17,CZK), new MoneyImpl(1,USD));
17.59 + }
17.60 +
17.61 + /** Create convertor that understands two currencies, CZK and
17.62 + * SKK. Make 100 SKK == 80 CZK. Again this is method for the #1 group -
17.63 + * it knows the exchange rate, and needs to use the API to create objects
17.64 + * with the exchange rate. Anyone shall be ready to call this method without
17.65 + * any other method being called previously. The API itself shall know
17.66 + * nothing about any rates, before this method is called.
17.67 + *
17.68 + * Creation of the convertor shall not require subclassing of any class
17.69 + * or interface on the client side.
17.70 + *
17.71 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
17.72 + */
17.73 + public static Convertor createSKKtoCZK() {
17.74 + return ConvertorFactory.createConvertor(new MoneyImpl(100,SKK), new MoneyImpl(80,CZK));
17.75 + }
17.76 +
17.77 + //
17.78 + // now the methods for group #2 follow:
17.79 + // this group knows nothing about exchange rates, but knows how to use
17.80 + // the API to do conversions. It somehow (by calling one of the factory
17.81 + // methods) gets objects from the API and uses them to do the conversions.
17.82 + //
17.83 +
17.84 + /** Use the convertor from <code>createCZKtoUSD</code> method and do few conversions
17.85 + * with it.
17.86 + */
17.87 + public void testCurrencyCZKUSD() throws Exception {
17.88 + Convertor c = createCZKtoUSD();
17.89 + // convert $5 to CZK using c:
17.90 + assertEquals("Result is 85 CZK",new MoneyImpl(85,CZK), c.convert(new MoneyImpl(5,USD),CZK));
17.91 +
17.92 + // convert $8 to CZK
17.93 + assertEquals("Result is 136 CZK",new MoneyImpl(136,CZK), c.convert(new MoneyImpl(8,USD),CZK));
17.94 +
17.95 + // convert 1003CZK to USD
17.96 + assertEquals("Result is 59 USD", new MoneyImpl(59,USD), c.convert(new MoneyImpl(1003,CZK),USD));
17.97 +
17.98 + }
17.99 +
17.100 + /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
17.101 + * with it.
17.102 + */
17.103 + public void testCurrencySKKCZK() throws Exception {
17.104 + Convertor c = createSKKtoCZK();
17.105 + // convert 16CZK using c:
17.106 + assertEquals("Result is 20 SKK", new MoneyImpl(20,SKK), c.convert(new MoneyImpl(16,CZK),SKK));
17.107 +
17.108 + // convert 500SKK to CZK
17.109 + assertEquals("Result is 400 CZK", new MoneyImpl(400,CZK), c.convert(new MoneyImpl(500,SKK),CZK));
17.110 + }
17.111 +
17.112 + /** Verify that the CZK to USD convertor knows nothing about SKK.
17.113 + */
17.114 + public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
17.115 + Convertor c = createCZKtoUSD();
17.116 + // convert $5 to SKK, the API shall say this is not possible
17.117 + try
17.118 + {
17.119 + c.convert(new MoneyImpl(5, USD), SKK);
17.120 + fail("Exception expected");
17.121 + }
17.122 + catch(IllegalArgumentException e)
17.123 + {
17.124 + assertTrue("Ok",true);
17.125 + }
17.126 + // convert 500 SKK to CZK, the API shall say this is not possible
17.127 + try
17.128 + {
17.129 + c.convert(new MoneyImpl(500, SKK), CZK);
17.130 + fail("Exception expected");
17.131 + }
17.132 + catch(IllegalArgumentException e)
17.133 + {
17.134 + assertTrue("Ok",true);
17.135 + }
17.136 + }
17.137 +
17.138 + /** Verify that the CZK to SKK convertor knows nothing about USD.
17.139 + */
17.140 + public void testCannotConvertToUSDwithCZKSKKConvertor() throws Exception {
17.141 + Convertor c = createSKKtoCZK();
17.142 + // convert $5 to SKK, the API shall say this is not possible
17.143 + try
17.144 + {
17.145 + c.convert(new MoneyImpl(5, USD), SKK);
17.146 + fail("Exception expected");
17.147 + }
17.148 + catch(IllegalArgumentException e)
17.149 + {
17.150 + assertTrue("Ok",true);
17.151 + }
17.152 + // convert 500 CZK to USD, the API shall say this is not possible
17.153 + try
17.154 + {
17.155 + c.convert(new MoneyImpl(500, CZK), USD);
17.156 + fail("Exception expected");
17.157 + }
17.158 + catch(IllegalArgumentException e)
17.159 + {
17.160 + assertTrue("Ok",true);
17.161 + }
17.162 + }
17.163 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/task3/solution02/test/org/apidesign/apifest08/test/Task2Test.java Tue Oct 07 11:05:34 2008 +0200
18.3 @@ -0,0 +1,119 @@
18.4 +package org.apidesign.apifest08.test;
18.5 +
18.6 +import static org.apidesign.apifest08.currency.ConvertorFactory.createConvertor;
18.7 +import static org.apidesign.apifest08.currency.ConvertorFactory.mergeConvertors;
18.8 +import static org.apidesign.apifest08.currency.MoneyImpl.money;
18.9 +import static org.apidesign.apifest08.test.Task1Test.CZK;
18.10 +import static org.apidesign.apifest08.test.Task1Test.SKK;
18.11 +import static org.apidesign.apifest08.test.Task1Test.USD;
18.12 +import junit.framework.TestCase;
18.13 +
18.14 +import org.apidesign.apifest08.currency.Convertor;
18.15 +import org.apidesign.apifest08.currency.ExtendedConvertor;
18.16 +
18.17 +/** There are many currencies around the world and many banks manipulate
18.18 + * with more than one or two at the same time. As banks are usually the
18.19 + * best paying clients, which is true even in case of your Convertor API,
18.20 + * it is reasonable to listen to their requests.
18.21 + * <p>
18.22 + * The quest for today is to enhance your existing convertor API to hold
18.23 + * information about many currencies and allow conversions between any of them.
18.24 + * Also, as conversion rates for diferent currencies usually arise from various
18.25 + * bank departments, there is another important need. There is a need to
18.26 + * compose two convertors into one by merging all the information about
18.27 + * currencies they know about.
18.28 + */
18.29 +public class Task2Test extends TestCase {
18.30 + public Task2Test(String testName) {
18.31 + super(testName);
18.32 + }
18.33 +
18.34 + @Override
18.35 + protected void setUp() throws Exception {
18.36 + }
18.37 +
18.38 + @Override
18.39 + protected void tearDown() throws Exception {
18.40 + }
18.41 +
18.42 + // As in Task1Test, keep in mind, that there are three parts
18.43 + // of the whole system:
18.44 + // 1. there is someone who knows the current exchange rate
18.45 + // 2. there is someone who wants to do the conversion
18.46 + // 3. there is the API between 1. and 2. which allows them to communicate
18.47 + //
18.48 + // Please backward compatibly enhance your existing API to support following
18.49 + // usecases:
18.50 + //
18.51 +
18.52 + /** Create convertor that understands two currencies, CZK and
18.53 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
18.54 + * knows the exchange rate, and needs to use the API to create objects
18.55 + * with the exchange rate. Anyone shall be ready to call this method without
18.56 + * any other method being called previously. The API itself shall know
18.57 + * nothing about any rates, before this method is called.
18.58 + */
18.59 + public static Convertor createTripleConvertor() {
18.60 + // Rates: 1USD = 15CZK
18.61 + // Rates: 1USD = 20SKK
18.62 + // Rates: 75CZK = 100SKK
18.63 + return mergeConvertors(
18.64 + createConvertor(money(1, USD), money(15, CZK)),
18.65 + createConvertor(money(1, USD), money(20, SKK)),
18.66 + createConvertor(money(75, CZK), money(100, SKK))
18.67 + );
18.68 + }
18.69 +
18.70 + /** Define convertor that understands three currencies. Use it.
18.71 + */
18.72 + public void testConvertorForUSDandCZKandSKK() throws Exception {
18.73 + Convertor c = createTripleConvertor();
18.74 +
18.75 + // convert $5 to CZK using c:
18.76 + assertEquals("Result is 75 CZK", money(75, CZK),c.convert(money(5,USD), CZK));
18.77 +
18.78 + // convert $5 to SKK using c:
18.79 + assertEquals("Result is 100 SKK", money(100, SKK),c.convert(money(5,USD), SKK));
18.80 +
18.81 + // convert 200SKK to CZK using c:
18.82 + assertEquals("Result is 150 CZK", money(150, CZK),c.convert(money(200,SKK), CZK));
18.83 +
18.84 + // convert 200SKK to USK using c:
18.85 + assertEquals("Result is 10 USD", money(10, USD),c.convert(money(200,SKK), USD));
18.86 + }
18.87 +
18.88 + /** Merge all currency rates of convertor 1 with convertor 2.
18.89 + * Implement this using your API, preferably this method just delegates
18.90 + * into some API method which does the actual work, without requiring
18.91 + * API clients to code anything complex.
18.92 + */
18.93 + public static Convertor merge(Convertor one, Convertor two) {
18.94 + return mergeConvertors((ExtendedConvertor)one, (ExtendedConvertor)two);
18.95 + }
18.96 +
18.97 + /** Join the convertors from previous task, Task1Test and show that it
18.98 + * can be used to do reasonable conversions.
18.99 + */
18.100 + public void testConvertorComposition() throws Exception {
18.101 + Convertor c = merge(
18.102 + Task1Test.createCZKtoUSD(),
18.103 + Task1Test.createSKKtoCZK()
18.104 + );
18.105 +
18.106 + // convert $5 to CZK using c:
18.107 + assertEquals("Result is 85 CZK", money(85, CZK),c.convert(money(5,USD), CZK));
18.108 +
18.109 + // convert $8 to CZK using c:
18.110 + assertEquals("Result is 136 CZK", money(136, CZK),c.convert(money(8,USD), CZK));
18.111 +
18.112 + // convert 1003CZK to USD using c:
18.113 + assertEquals("Result is 59 USD", money(59, USD),c.convert(money(1003,CZK), USD));
18.114 +
18.115 + // convert 16CZK using c:
18.116 + assertEquals("Result is 20 SKK", money(20, SKK),c.convert(money(16,CZK), SKK));
18.117 +
18.118 + // convert 500SKK to CZK using c:
18.119 + assertEquals("Result is 400 CZK", money(400, CZK),c.convert(money(500,SKK), CZK));
18.120 +
18.121 + }
18.122 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/task3/solution04/build.xml Tue Oct 07 11:05:34 2008 +0200
19.3 @@ -0,0 +1,69 @@
19.4 +<?xml version="1.0" encoding="UTF-8"?>
19.5 +<!-- You may freely edit this file. See commented blocks below for -->
19.6 +<!-- some examples of how to customize the build. -->
19.7 +<!-- (If you delete it and reopen the project it will be recreated.) -->
19.8 +<project name="currency" default="default" basedir=".">
19.9 + <description>Builds, tests, and runs the project.</description>
19.10 + <import file="nbproject/build-impl.xml"/>
19.11 + <!--
19.12 +
19.13 + There exist several targets which are by default empty and which can be
19.14 + used for execution of your tasks. These targets are usually executed
19.15 + before and after some main targets. They are:
19.16 +
19.17 + -pre-init: called before initialization of project properties
19.18 + -post-init: called after initialization of project properties
19.19 + -pre-compile: called before javac compilation
19.20 + -post-compile: called after javac compilation
19.21 + -pre-compile-single: called before javac compilation of single file
19.22 + -post-compile-single: called after javac compilation of single file
19.23 + -pre-compile-test: called before javac compilation of JUnit tests
19.24 + -post-compile-test: called after javac compilation of JUnit tests
19.25 + -pre-compile-test-single: called before javac compilation of single JUnit test
19.26 + -post-compile-test-single: called after javac compilation of single JUunit test
19.27 + -pre-jar: called before JAR building
19.28 + -post-jar: called after JAR building
19.29 + -post-clean: called after cleaning build products
19.30 +
19.31 + (Targets beginning with '-' are not intended to be called on their own.)
19.32 +
19.33 + Example of inserting an obfuscator after compilation could look like this:
19.34 +
19.35 + <target name="-post-compile">
19.36 + <obfuscate>
19.37 + <fileset dir="${build.classes.dir}"/>
19.38 + </obfuscate>
19.39 + </target>
19.40 +
19.41 + For list of available properties check the imported
19.42 + nbproject/build-impl.xml file.
19.43 +
19.44 +
19.45 + Another way to customize the build is by overriding existing main targets.
19.46 + The targets of interest are:
19.47 +
19.48 + -init-macrodef-javac: defines macro for javac compilation
19.49 + -init-macrodef-junit: defines macro for junit execution
19.50 + -init-macrodef-debug: defines macro for class debugging
19.51 + -init-macrodef-java: defines macro for class execution
19.52 + -do-jar-with-manifest: JAR building (if you are using a manifest)
19.53 + -do-jar-without-manifest: JAR building (if you are not using a manifest)
19.54 + run: execution of project
19.55 + -javadoc-build: Javadoc generation
19.56 + test-report: JUnit report generation
19.57 +
19.58 + An example of overriding the target for project execution could look like this:
19.59 +
19.60 + <target name="run" depends="currency-impl.jar">
19.61 + <exec dir="bin" executable="launcher.exe">
19.62 + <arg file="${dist.jar}"/>
19.63 + </exec>
19.64 + </target>
19.65 +
19.66 + Notice that the overridden target depends on the jar target and not only on
19.67 + the compile target as the regular run target does. Again, for a list of available
19.68 + properties which you can use, check the target you are overriding in the
19.69 + nbproject/build-impl.xml file.
19.70 +
19.71 + -->
19.72 +</project>
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/task3/solution04/nbproject/build-impl.xml Tue Oct 07 11:05:34 2008 +0200
20.3 @@ -0,0 +1,642 @@
20.4 +<?xml version="1.0" encoding="UTF-8"?>
20.5 +<!--
20.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
20.7 +*** EDIT ../build.xml INSTEAD ***
20.8 +
20.9 +For the purpose of easier reading the script
20.10 +is divided into following sections:
20.11 +
20.12 + - initialization
20.13 + - compilation
20.14 + - jar
20.15 + - execution
20.16 + - debugging
20.17 + - javadoc
20.18 + - junit compilation
20.19 + - junit execution
20.20 + - junit debugging
20.21 + - applet
20.22 + - cleanup
20.23 +
20.24 + -->
20.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_04-impl">
20.26 + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
20.27 + <!--
20.28 + ======================
20.29 + INITIALIZATION SECTION
20.30 + ======================
20.31 + -->
20.32 + <target name="-pre-init">
20.33 + <!-- Empty placeholder for easier customization. -->
20.34 + <!-- You can override this target in the ../build.xml file. -->
20.35 + </target>
20.36 + <target depends="-pre-init" name="-init-private">
20.37 + <property file="nbproject/private/config.properties"/>
20.38 + <property file="nbproject/private/configs/${config}.properties"/>
20.39 + <property file="nbproject/private/private.properties"/>
20.40 + </target>
20.41 + <target depends="-pre-init,-init-private" name="-init-user">
20.42 + <property file="${user.properties.file}"/>
20.43 + <!-- The two properties below are usually overridden -->
20.44 + <!-- by the active platform. Just a fallback. -->
20.45 + <property name="default.javac.source" value="1.4"/>
20.46 + <property name="default.javac.target" value="1.4"/>
20.47 + </target>
20.48 + <target depends="-pre-init,-init-private,-init-user" name="-init-project">
20.49 + <property file="nbproject/configs/${config}.properties"/>
20.50 + <property file="nbproject/project.properties"/>
20.51 + </target>
20.52 + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
20.53 + <available file="${manifest.file}" property="manifest.available"/>
20.54 + <condition property="manifest.available+main.class">
20.55 + <and>
20.56 + <isset property="manifest.available"/>
20.57 + <isset property="main.class"/>
20.58 + <not>
20.59 + <equals arg1="${main.class}" arg2="" trim="true"/>
20.60 + </not>
20.61 + </and>
20.62 + </condition>
20.63 + <condition property="manifest.available+main.class+mkdist.available">
20.64 + <and>
20.65 + <istrue value="${manifest.available+main.class}"/>
20.66 + <isset property="libs.CopyLibs.classpath"/>
20.67 + </and>
20.68 + </condition>
20.69 + <condition property="have.tests">
20.70 + <or>
20.71 + <available file="${test.src.dir}"/>
20.72 + </or>
20.73 + </condition>
20.74 + <condition property="have.sources">
20.75 + <or>
20.76 + <available file="${src.dir}"/>
20.77 + </or>
20.78 + </condition>
20.79 + <condition property="netbeans.home+have.tests">
20.80 + <and>
20.81 + <isset property="netbeans.home"/>
20.82 + <isset property="have.tests"/>
20.83 + </and>
20.84 + </condition>
20.85 + <condition property="no.javadoc.preview">
20.86 + <and>
20.87 + <isset property="javadoc.preview"/>
20.88 + <isfalse value="${javadoc.preview}"/>
20.89 + </and>
20.90 + </condition>
20.91 + <property name="run.jvmargs" value=""/>
20.92 + <property name="javac.compilerargs" value=""/>
20.93 + <property name="work.dir" value="${basedir}"/>
20.94 + <condition property="no.deps">
20.95 + <and>
20.96 + <istrue value="${no.dependencies}"/>
20.97 + </and>
20.98 + </condition>
20.99 + <property name="javac.debug" value="true"/>
20.100 + <property name="javadoc.preview" value="true"/>
20.101 + <property name="application.args" value=""/>
20.102 + <property name="source.encoding" value="${file.encoding}"/>
20.103 + <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
20.104 + <and>
20.105 + <isset property="javadoc.encoding"/>
20.106 + <not>
20.107 + <equals arg1="${javadoc.encoding}" arg2=""/>
20.108 + </not>
20.109 + </and>
20.110 + </condition>
20.111 + <property name="javadoc.encoding.used" value="${source.encoding}"/>
20.112 + <property name="includes" value="**"/>
20.113 + <property name="excludes" value=""/>
20.114 + <property name="do.depend" value="false"/>
20.115 + <condition property="do.depend.true">
20.116 + <istrue value="${do.depend}"/>
20.117 + </condition>
20.118 + <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
20.119 + <and>
20.120 + <isset property="jaxws.endorsed.dir"/>
20.121 + <available file="nbproject/jaxws-build.xml"/>
20.122 + </and>
20.123 + </condition>
20.124 + </target>
20.125 + <target name="-post-init">
20.126 + <!-- Empty placeholder for easier customization. -->
20.127 + <!-- You can override this target in the ../build.xml file. -->
20.128 + </target>
20.129 + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
20.130 + <fail unless="src.dir">Must set src.dir</fail>
20.131 + <fail unless="test.src.dir">Must set test.src.dir</fail>
20.132 + <fail unless="build.dir">Must set build.dir</fail>
20.133 + <fail unless="dist.dir">Must set dist.dir</fail>
20.134 + <fail unless="build.classes.dir">Must set build.classes.dir</fail>
20.135 + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
20.136 + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
20.137 + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
20.138 + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
20.139 + <fail unless="dist.jar">Must set dist.jar</fail>
20.140 + </target>
20.141 + <target name="-init-macrodef-property">
20.142 + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
20.143 + <attribute name="name"/>
20.144 + <attribute name="value"/>
20.145 + <sequential>
20.146 + <property name="@{name}" value="${@{value}}"/>
20.147 + </sequential>
20.148 + </macrodef>
20.149 + </target>
20.150 + <target name="-init-macrodef-javac">
20.151 + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
20.152 + <attribute default="${src.dir}" name="srcdir"/>
20.153 + <attribute default="${build.classes.dir}" name="destdir"/>
20.154 + <attribute default="${javac.classpath}" name="classpath"/>
20.155 + <attribute default="${includes}" name="includes"/>
20.156 + <attribute default="${excludes}" name="excludes"/>
20.157 + <attribute default="${javac.debug}" name="debug"/>
20.158 + <attribute default="" name="sourcepath"/>
20.159 + <element name="customize" optional="true"/>
20.160 + <sequential>
20.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}">
20.162 + <classpath>
20.163 + <path path="@{classpath}"/>
20.164 + </classpath>
20.165 + <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
20.166 + <customize/>
20.167 + </javac>
20.168 + </sequential>
20.169 + </macrodef>
20.170 + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
20.171 + <attribute default="${src.dir}" name="srcdir"/>
20.172 + <attribute default="${build.classes.dir}" name="destdir"/>
20.173 + <attribute default="${javac.classpath}" name="classpath"/>
20.174 + <sequential>
20.175 + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
20.176 + <classpath>
20.177 + <path path="@{classpath}"/>
20.178 + </classpath>
20.179 + </depend>
20.180 + </sequential>
20.181 + </macrodef>
20.182 + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
20.183 + <attribute default="${build.classes.dir}" name="destdir"/>
20.184 + <sequential>
20.185 + <fail unless="javac.includes">Must set javac.includes</fail>
20.186 + <pathconvert pathsep="," property="javac.includes.binary">
20.187 + <path>
20.188 + <filelist dir="@{destdir}" files="${javac.includes}"/>
20.189 + </path>
20.190 + <globmapper from="*.java" to="*.class"/>
20.191 + </pathconvert>
20.192 + <delete>
20.193 + <files includes="${javac.includes.binary}"/>
20.194 + </delete>
20.195 + </sequential>
20.196 + </macrodef>
20.197 + </target>
20.198 + <target name="-init-macrodef-junit">
20.199 + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
20.200 + <attribute default="${includes}" name="includes"/>
20.201 + <attribute default="${excludes}" name="excludes"/>
20.202 + <attribute default="**" name="testincludes"/>
20.203 + <sequential>
20.204 + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
20.205 + <batchtest todir="${build.test.results.dir}">
20.206 + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
20.207 + <filename name="@{testincludes}"/>
20.208 + </fileset>
20.209 + </batchtest>
20.210 + <classpath>
20.211 + <path path="${run.test.classpath}"/>
20.212 + </classpath>
20.213 + <syspropertyset>
20.214 + <propertyref prefix="test-sys-prop."/>
20.215 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
20.216 + </syspropertyset>
20.217 + <formatter type="brief" usefile="false"/>
20.218 + <formatter type="xml"/>
20.219 + <jvmarg line="${run.jvmargs}"/>
20.220 + </junit>
20.221 + </sequential>
20.222 + </macrodef>
20.223 + </target>
20.224 + <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
20.225 + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
20.226 + <attribute default="${main.class}" name="name"/>
20.227 + <attribute default="${debug.classpath}" name="classpath"/>
20.228 + <attribute default="" name="stopclassname"/>
20.229 + <sequential>
20.230 + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
20.231 + <classpath>
20.232 + <path path="@{classpath}"/>
20.233 + </classpath>
20.234 + </nbjpdastart>
20.235 + </sequential>
20.236 + </macrodef>
20.237 + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
20.238 + <attribute default="${build.classes.dir}" name="dir"/>
20.239 + <sequential>
20.240 + <nbjpdareload>
20.241 + <fileset dir="@{dir}" includes="${fix.classes}">
20.242 + <include name="${fix.includes}*.class"/>
20.243 + </fileset>
20.244 + </nbjpdareload>
20.245 + </sequential>
20.246 + </macrodef>
20.247 + </target>
20.248 + <target name="-init-debug-args">
20.249 + <property name="version-output" value="java version "${ant.java.version}"/>
20.250 + <condition property="have-jdk-older-than-1.4">
20.251 + <or>
20.252 + <contains string="${version-output}" substring="java version "1.0"/>
20.253 + <contains string="${version-output}" substring="java version "1.1"/>
20.254 + <contains string="${version-output}" substring="java version "1.2"/>
20.255 + <contains string="${version-output}" substring="java version "1.3"/>
20.256 + </or>
20.257 + </condition>
20.258 + <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
20.259 + <istrue value="${have-jdk-older-than-1.4}"/>
20.260 + </condition>
20.261 + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
20.262 + <os family="windows"/>
20.263 + </condition>
20.264 + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
20.265 + <isset property="debug.transport"/>
20.266 + </condition>
20.267 + </target>
20.268 + <target depends="-init-debug-args" name="-init-macrodef-debug">
20.269 + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
20.270 + <attribute default="${main.class}" name="classname"/>
20.271 + <attribute default="${debug.classpath}" name="classpath"/>
20.272 + <element name="customize" optional="true"/>
20.273 + <sequential>
20.274 + <java classname="@{classname}" dir="${work.dir}" fork="true">
20.275 + <jvmarg line="${debug-args-line}"/>
20.276 + <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
20.277 + <jvmarg line="${run.jvmargs}"/>
20.278 + <classpath>
20.279 + <path path="@{classpath}"/>
20.280 + </classpath>
20.281 + <syspropertyset>
20.282 + <propertyref prefix="run-sys-prop."/>
20.283 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
20.284 + </syspropertyset>
20.285 + <customize/>
20.286 + </java>
20.287 + </sequential>
20.288 + </macrodef>
20.289 + </target>
20.290 + <target name="-init-macrodef-java">
20.291 + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
20.292 + <attribute default="${main.class}" name="classname"/>
20.293 + <element name="customize" optional="true"/>
20.294 + <sequential>
20.295 + <java classname="@{classname}" dir="${work.dir}" fork="true">
20.296 + <jvmarg line="${run.jvmargs}"/>
20.297 + <classpath>
20.298 + <path path="${run.classpath}"/>
20.299 + </classpath>
20.300 + <syspropertyset>
20.301 + <propertyref prefix="run-sys-prop."/>
20.302 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
20.303 + </syspropertyset>
20.304 + <customize/>
20.305 + </java>
20.306 + </sequential>
20.307 + </macrodef>
20.308 + </target>
20.309 + <target name="-init-presetdef-jar">
20.310 + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
20.311 + <jar compress="${jar.compress}" jarfile="${dist.jar}">
20.312 + <j2seproject1:fileset dir="${build.classes.dir}"/>
20.313 + </jar>
20.314 + </presetdef>
20.315 + </target>
20.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"/>
20.317 + <!--
20.318 + ===================
20.319 + COMPILATION SECTION
20.320 + ===================
20.321 + -->
20.322 + <target depends="init" name="deps-jar" unless="no.deps"/>
20.323 + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
20.324 + <target depends="init" name="-check-automatic-build">
20.325 + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
20.326 + </target>
20.327 + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
20.328 + <antcall target="clean"/>
20.329 + </target>
20.330 + <target depends="init,deps-jar" name="-pre-pre-compile">
20.331 + <mkdir dir="${build.classes.dir}"/>
20.332 + </target>
20.333 + <target name="-pre-compile">
20.334 + <!-- Empty placeholder for easier customization. -->
20.335 + <!-- You can override this target in the ../build.xml file. -->
20.336 + </target>
20.337 + <target if="do.depend.true" name="-compile-depend">
20.338 + <j2seproject3:depend/>
20.339 + </target>
20.340 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
20.341 + <j2seproject3:javac/>
20.342 + <copy todir="${build.classes.dir}">
20.343 + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
20.344 + </copy>
20.345 + </target>
20.346 + <target name="-post-compile">
20.347 + <!-- Empty placeholder for easier customization. -->
20.348 + <!-- You can override this target in the ../build.xml file. -->
20.349 + </target>
20.350 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
20.351 + <target name="-pre-compile-single">
20.352 + <!-- Empty placeholder for easier customization. -->
20.353 + <!-- You can override this target in the ../build.xml file. -->
20.354 + </target>
20.355 + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
20.356 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
20.357 + <j2seproject3:force-recompile/>
20.358 + <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
20.359 + </target>
20.360 + <target name="-post-compile-single">
20.361 + <!-- Empty placeholder for easier customization. -->
20.362 + <!-- You can override this target in the ../build.xml file. -->
20.363 + </target>
20.364 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
20.365 + <!--
20.366 + ====================
20.367 + JAR BUILDING SECTION
20.368 + ====================
20.369 + -->
20.370 + <target depends="init" name="-pre-pre-jar">
20.371 + <dirname file="${dist.jar}" property="dist.jar.dir"/>
20.372 + <mkdir dir="${dist.jar.dir}"/>
20.373 + </target>
20.374 + <target name="-pre-jar">
20.375 + <!-- Empty placeholder for easier customization. -->
20.376 + <!-- You can override this target in the ../build.xml file. -->
20.377 + </target>
20.378 + <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
20.379 + <j2seproject1:jar/>
20.380 + </target>
20.381 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
20.382 + <j2seproject1:jar manifest="${manifest.file}"/>
20.383 + </target>
20.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">
20.385 + <j2seproject1:jar manifest="${manifest.file}">
20.386 + <j2seproject1:manifest>
20.387 + <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
20.388 + </j2seproject1:manifest>
20.389 + </j2seproject1:jar>
20.390 + <echo>To run this application from the command line without Ant, try:</echo>
20.391 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
20.392 + <property location="${dist.jar}" name="dist.jar.resolved"/>
20.393 + <pathconvert property="run.classpath.with.dist.jar">
20.394 + <path path="${run.classpath}"/>
20.395 + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
20.396 + </pathconvert>
20.397 + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
20.398 + </target>
20.399 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
20.400 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
20.401 + <pathconvert property="run.classpath.without.build.classes.dir">
20.402 + <path path="${run.classpath}"/>
20.403 + <map from="${build.classes.dir.resolved}" to=""/>
20.404 + </pathconvert>
20.405 + <pathconvert pathsep=" " property="jar.classpath">
20.406 + <path path="${run.classpath.without.build.classes.dir}"/>
20.407 + <chainedmapper>
20.408 + <flattenmapper/>
20.409 + <globmapper from="*" to="lib/*"/>
20.410 + </chainedmapper>
20.411 + </pathconvert>
20.412 + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
20.413 + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
20.414 + <fileset dir="${build.classes.dir}"/>
20.415 + <manifest>
20.416 + <attribute name="Main-Class" value="${main.class}"/>
20.417 + <attribute name="Class-Path" value="${jar.classpath}"/>
20.418 + </manifest>
20.419 + </copylibs>
20.420 + <echo>To run this application from the command line without Ant, try:</echo>
20.421 + <property location="${dist.jar}" name="dist.jar.resolved"/>
20.422 + <echo>java -jar "${dist.jar.resolved}"</echo>
20.423 + </target>
20.424 + <target name="-post-jar">
20.425 + <!-- Empty placeholder for easier customization. -->
20.426 + <!-- You can override this target in the ../build.xml file. -->
20.427 + </target>
20.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"/>
20.429 + <!--
20.430 + =================
20.431 + EXECUTION SECTION
20.432 + =================
20.433 + -->
20.434 + <target depends="init,compile" description="Run a main class." name="run">
20.435 + <j2seproject1:java>
20.436 + <customize>
20.437 + <arg line="${application.args}"/>
20.438 + </customize>
20.439 + </j2seproject1:java>
20.440 + </target>
20.441 + <target name="-do-not-recompile">
20.442 + <property name="javac.includes.binary" value=""/>
20.443 + </target>
20.444 + <target depends="init,-do-not-recompile,compile-single" name="run-single">
20.445 + <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
20.446 + <j2seproject1:java classname="${run.class}"/>
20.447 + </target>
20.448 + <!--
20.449 + =================
20.450 + DEBUGGING SECTION
20.451 + =================
20.452 + -->
20.453 + <target depends="init" if="netbeans.home" name="-debug-start-debugger">
20.454 + <j2seproject1:nbjpdastart name="${debug.class}"/>
20.455 + </target>
20.456 + <target depends="init,compile" name="-debug-start-debuggee">
20.457 + <j2seproject3:debug>
20.458 + <customize>
20.459 + <arg line="${application.args}"/>
20.460 + </customize>
20.461 + </j2seproject3:debug>
20.462 + </target>
20.463 + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
20.464 + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
20.465 + <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
20.466 + </target>
20.467 + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
20.468 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
20.469 + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
20.470 + <j2seproject3:debug classname="${debug.class}"/>
20.471 + </target>
20.472 + <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
20.473 + <target depends="init" name="-pre-debug-fix">
20.474 + <fail unless="fix.includes">Must set fix.includes</fail>
20.475 + <property name="javac.includes" value="${fix.includes}.java"/>
20.476 + </target>
20.477 + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
20.478 + <j2seproject1:nbjpdareload/>
20.479 + </target>
20.480 + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
20.481 + <!--
20.482 + ===============
20.483 + JAVADOC SECTION
20.484 + ===============
20.485 + -->
20.486 + <target depends="init" name="-javadoc-build">
20.487 + <mkdir dir="${dist.javadoc.dir}"/>
20.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}">
20.489 + <classpath>
20.490 + <path path="${javac.classpath}"/>
20.491 + </classpath>
20.492 + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
20.493 + <filename name="**/*.java"/>
20.494 + </fileset>
20.495 + </javadoc>
20.496 + </target>
20.497 + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
20.498 + <nbbrowse file="${dist.javadoc.dir}/index.html"/>
20.499 + </target>
20.500 + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
20.501 + <!--
20.502 + =========================
20.503 + JUNIT COMPILATION SECTION
20.504 + =========================
20.505 + -->
20.506 + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
20.507 + <mkdir dir="${build.test.classes.dir}"/>
20.508 + </target>
20.509 + <target name="-pre-compile-test">
20.510 + <!-- Empty placeholder for easier customization. -->
20.511 + <!-- You can override this target in the ../build.xml file. -->
20.512 + </target>
20.513 + <target if="do.depend.true" name="-compile-test-depend">
20.514 + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
20.515 + </target>
20.516 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
20.517 + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
20.518 + <copy todir="${build.test.classes.dir}">
20.519 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
20.520 + </copy>
20.521 + </target>
20.522 + <target name="-post-compile-test">
20.523 + <!-- Empty placeholder for easier customization. -->
20.524 + <!-- You can override this target in the ../build.xml file. -->
20.525 + </target>
20.526 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
20.527 + <target name="-pre-compile-test-single">
20.528 + <!-- Empty placeholder for easier customization. -->
20.529 + <!-- You can override this target in the ../build.xml file. -->
20.530 + </target>
20.531 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
20.532 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
20.533 + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
20.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}"/>
20.535 + <copy todir="${build.test.classes.dir}">
20.536 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
20.537 + </copy>
20.538 + </target>
20.539 + <target name="-post-compile-test-single">
20.540 + <!-- Empty placeholder for easier customization. -->
20.541 + <!-- You can override this target in the ../build.xml file. -->
20.542 + </target>
20.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"/>
20.544 + <!--
20.545 + =======================
20.546 + JUNIT EXECUTION SECTION
20.547 + =======================
20.548 + -->
20.549 + <target depends="init" if="have.tests" name="-pre-test-run">
20.550 + <mkdir dir="${build.test.results.dir}"/>
20.551 + </target>
20.552 + <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
20.553 + <j2seproject3:junit testincludes="**/*Test.java"/>
20.554 + </target>
20.555 + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
20.556 + <fail if="tests.failed">Some tests failed; see details above.</fail>
20.557 + </target>
20.558 + <target depends="init" if="have.tests" name="test-report"/>
20.559 + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
20.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"/>
20.561 + <target depends="init" if="have.tests" name="-pre-test-run-single">
20.562 + <mkdir dir="${build.test.results.dir}"/>
20.563 + </target>
20.564 + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
20.565 + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
20.566 + <j2seproject3:junit excludes="" includes="${test.includes}"/>
20.567 + </target>
20.568 + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
20.569 + <fail if="tests.failed">Some tests failed; see details above.</fail>
20.570 + </target>
20.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"/>
20.572 + <!--
20.573 + =======================
20.574 + JUNIT DEBUGGING SECTION
20.575 + =======================
20.576 + -->
20.577 + <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
20.578 + <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
20.579 + <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
20.580 + <delete file="${test.report.file}"/>
20.581 + <mkdir dir="${build.test.results.dir}"/>
20.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}">
20.583 + <customize>
20.584 + <syspropertyset>
20.585 + <propertyref prefix="test-sys-prop."/>
20.586 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
20.587 + </syspropertyset>
20.588 + <arg value="${test.class}"/>
20.589 + <arg value="showoutput=true"/>
20.590 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
20.591 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
20.592 + </customize>
20.593 + </j2seproject3:debug>
20.594 + </target>
20.595 + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
20.596 + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
20.597 + </target>
20.598 + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
20.599 + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
20.600 + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
20.601 + </target>
20.602 + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
20.603 + <!--
20.604 + =========================
20.605 + APPLET EXECUTION SECTION
20.606 + =========================
20.607 + -->
20.608 + <target depends="init,compile-single" name="run-applet">
20.609 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
20.610 + <j2seproject1:java classname="sun.applet.AppletViewer">
20.611 + <customize>
20.612 + <arg value="${applet.url}"/>
20.613 + </customize>
20.614 + </j2seproject1:java>
20.615 + </target>
20.616 + <!--
20.617 + =========================
20.618 + APPLET DEBUGGING SECTION
20.619 + =========================
20.620 + -->
20.621 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
20.622 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
20.623 + <j2seproject3:debug classname="sun.applet.AppletViewer">
20.624 + <customize>
20.625 + <arg value="${applet.url}"/>
20.626 + </customize>
20.627 + </j2seproject3:debug>
20.628 + </target>
20.629 + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
20.630 + <!--
20.631 + ===============
20.632 + CLEANUP SECTION
20.633 + ===============
20.634 + -->
20.635 + <target depends="init" name="deps-clean" unless="no.deps"/>
20.636 + <target depends="init" name="-do-clean">
20.637 + <delete dir="${build.dir}"/>
20.638 + <delete dir="${dist.dir}"/>
20.639 + </target>
20.640 + <target name="-post-clean">
20.641 + <!-- Empty placeholder for easier customization. -->
20.642 + <!-- You can override this target in the ../build.xml file. -->
20.643 + </target>
20.644 + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
20.645 +</project>
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/task3/solution04/nbproject/genfiles.properties Tue Oct 07 11:05:34 2008 +0200
21.3 @@ -0,0 +1,8 @@
21.4 +build.xml.data.CRC32=2ab820eb
21.5 +build.xml.script.CRC32=58a52595
21.6 +build.xml.stylesheet.CRC32=be360661
21.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
21.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
21.9 +nbproject/build-impl.xml.data.CRC32=2fbfa6ce
21.10 +nbproject/build-impl.xml.script.CRC32=c521eea7
21.11 +nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/task3/solution04/nbproject/project.properties Tue Oct 07 11:05:34 2008 +0200
22.3 @@ -0,0 +1,68 @@
22.4 +application.title=currency
22.5 +application.vendor=apidesign.org
22.6 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
22.7 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
22.8 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
22.9 +build.classes.dir=${build.dir}/classes
22.10 +build.classes.excludes=**/*.java,**/*.form
22.11 +# This directory is removed when the project is cleaned:
22.12 +build.dir=build
22.13 +build.generated.dir=${build.dir}/generated
22.14 +# Only compile against the classpath explicitly listed here:
22.15 +build.sysclasspath=ignore
22.16 +build.test.classes.dir=${build.dir}/test/classes
22.17 +build.test.results.dir=${build.dir}/test/results
22.18 +debug.classpath=\
22.19 + ${run.classpath}
22.20 +debug.test.classpath=\
22.21 + ${run.test.classpath}
22.22 +# This directory is removed when the project is cleaned:
22.23 +dist.dir=dist
22.24 +dist.jar=${dist.dir}/currency.jar
22.25 +dist.javadoc.dir=${dist.dir}/javadoc
22.26 +excludes=
22.27 +file.reference.junit-4.4.jar=../../libs/junit-4.4.jar
22.28 +file.reference.src-apifest08=..
22.29 +includes=**
22.30 +jar.compress=false
22.31 +javac.classpath=
22.32 +# Space-separated list of extra javac options
22.33 +javac.compilerargs=
22.34 +javac.deprecation=false
22.35 +javac.source=1.5
22.36 +javac.target=1.5
22.37 +javac.test.classpath=\
22.38 + ${javac.classpath}:\
22.39 + ${build.classes.dir}:\
22.40 + ${file.reference.junit-4.4.jar}
22.41 +javadoc.additionalparam=
22.42 +javadoc.author=false
22.43 +javadoc.encoding=
22.44 +javadoc.noindex=false
22.45 +javadoc.nonavbar=false
22.46 +javadoc.notree=false
22.47 +javadoc.private=false
22.48 +javadoc.splitindex=true
22.49 +javadoc.use=true
22.50 +javadoc.version=false
22.51 +javadoc.windowtitle=
22.52 +jnlp.codebase.type=local
22.53 +jnlp.codebase.url=file:/home/jarda/src/apifest08/currency/dist
22.54 +jnlp.descriptor=application
22.55 +jnlp.enabled=false
22.56 +jnlp.offline-allowed=false
22.57 +jnlp.signed=false
22.58 +meta.inf.dir=${src.dir}/META-INF
22.59 +platform.active=default_platform
22.60 +run.classpath=\
22.61 + ${javac.classpath}:\
22.62 + ${build.classes.dir}
22.63 +# Space-separated list of JVM arguments used when running the project
22.64 +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
22.65 +# or test-sys-prop.name=value to set system properties for unit tests):
22.66 +run.jvmargs=
22.67 +run.test.classpath=\
22.68 + ${javac.test.classpath}:\
22.69 + ${build.test.classes.dir}
22.70 +src.dir=src
22.71 +test.src.dir=test
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/task3/solution04/nbproject/project.xml Tue Oct 07 11:05:34 2008 +0200
23.3 @@ -0,0 +1,16 @@
23.4 +<?xml version="1.0" encoding="UTF-8"?>
23.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
23.6 + <type>org.netbeans.modules.java.j2seproject</type>
23.7 + <configuration>
23.8 + <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
23.9 + <name>Currency Convertor Solution 04</name>
23.10 + <minimum-ant-version>1.6.5</minimum-ant-version>
23.11 + <source-roots>
23.12 + <root id="src.dir"/>
23.13 + </source-roots>
23.14 + <test-roots>
23.15 + <root id="test.src.dir"/>
23.16 + </test-roots>
23.17 + </data>
23.18 + </configuration>
23.19 +</project>
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/task3/solution04/src/org/apidesign/apifest08/currency/CompositeConvertorImpl.java Tue Oct 07 11:05:34 2008 +0200
24.3 @@ -0,0 +1,314 @@
24.4 +package org.apidesign.apifest08.currency;
24.5 +
24.6 +
24.7 +import java.math.BigDecimal;
24.8 +import java.math.RoundingMode;
24.9 +import java.util.Collections;
24.10 +import java.util.Currency;
24.11 +import java.util.HashMap;
24.12 +import java.util.HashSet;
24.13 +import java.util.Map;
24.14 +import java.util.Set;
24.15 +
24.16 +
24.17 +/**
24.18 + * A composite convertor allows conversions between many currencies by forwarding conversion requests to stored convertors.
24.19 + * A composite convertor will build all possible conversions that are allowed by the underlying set of convertors.
24.20 + *
24.21 + * @author D'Arcy Smith
24.22 + * @verson 1.0
24.23 + */
24.24 +final class CompositeConvertorImpl
24.25 + implements Convertor
24.26 +{
24.27 + /**
24.28 + * The convertors that are supported.
24.29 + */
24.30 + private final Convertor[] convertors;
24.31 +
24.32 + /**
24.33 + * Keeps track of what convertors to use to convert between currencies.
24.34 + */
24.35 + private final Map<Currency, Map<Currency, Convertor>> possibleConversions;
24.36 +
24.37 + {
24.38 + possibleConversions = new HashMap<Currency, Map<Currency, Convertor>>();
24.39 + }
24.40 +
24.41 + /**
24.42 + * Construct a ComositeConvertorImpl with the specified convertors.
24.43 + * This will result in all possible conversions between the supplied currencies being made.
24.44 + *
24.45 + * @param cs the convertors to use.
24.46 + * @throws IllegalArgumentException if any of the items in cs are null.
24.47 + */
24.48 + CompositeConvertorImpl(Convertor ... cs)
24.49 + {
24.50 + int newConvertors;
24.51 +
24.52 + convertors = cs;
24.53 +
24.54 + // track all of the known conversion
24.55 + for(final Convertor convertor : convertors)
24.56 + {
24.57 + final Set<Currency> currencies;
24.58 + Map<Currency, Convertor> possible;
24.59 +
24.60 + if(convertor == null)
24.61 + {
24.62 + throw new IllegalArgumentException("cs cannot contain null");
24.63 + }
24.64 +
24.65 + currencies = convertor.getCurrencies();
24.66 +
24.67 + for(final Currency currency : currencies)
24.68 + {
24.69 + possible = possibleConversions.get(currency);
24.70 +
24.71 + if(possible == null)
24.72 + {
24.73 + possible = new HashMap<Currency, Convertor>();
24.74 + possibleConversions.put(currency, possible);
24.75 + }
24.76 +
24.77 + for(final Currency c : currencies)
24.78 + {
24.79 + possible.put(c, convertor);
24.80 + }
24.81 + }
24.82 + }
24.83 +
24.84 + // make up conversions that can be derived... eg:
24.85 + // we have:
24.86 + // USD <-> CAD
24.87 + // CAD <-> CZK
24.88 + // SSK <-> GBP
24.89 + // we can derive:
24.90 + // USD <-> CZK
24.91 + // we cannot derive:
24.92 + // USD <-> GBP
24.93 + // CAD <-> GBP
24.94 + // CZK <-> GBP
24.95 + do
24.96 + {
24.97 + newConvertors = 0;
24.98 +
24.99 + // todo... need to loop this until all the ones that can be handled are done.
24.100 + for(final Currency from : getCurrencies())
24.101 + {
24.102 + for(final Currency to : getCurrencies())
24.103 + {
24.104 + if(!(canConvert(from, to)))
24.105 + {
24.106 + final Set<Currency> fromCurrencies;
24.107 + final Set<Currency> toCurrencies;
24.108 + final Set<Currency> common;
24.109 +
24.110 + fromCurrencies = possibleConversions.get(from).keySet();
24.111 + toCurrencies = possibleConversions.get(to).keySet();
24.112 + common = new HashSet<Currency>();
24.113 +
24.114 + for(final Currency currency : fromCurrencies)
24.115 + {
24.116 + if(toCurrencies.contains(currency))
24.117 + {
24.118 + common.add(currency);
24.119 + }
24.120 + }
24.121 +
24.122 + for(final Currency currency : common)
24.123 + {
24.124 + final Convertor convertor;
24.125 +
24.126 + convertor = createConvertor(from, to, currency);
24.127 + possibleConversions.get(from).put(to, convertor);
24.128 + possibleConversions.get(to).put(from, convertor);
24.129 + newConvertors++;
24.130 + }
24.131 + }
24.132 + }
24.133 + }
24.134 + }
24.135 + while(newConvertors > 0);
24.136 + }
24.137 +
24.138 + /**
24.139 + * Check to see if converting between the two currencies is possible.
24.140 + *
24.141 + * @param from the currency to convert from.
24.142 + * @param to the currency to convert to.
24.143 + * @return true if the conversion is possible.
24.144 + * @throws IllegalArgumentException if either from or to are null.
24.145 + */
24.146 + public boolean canConvert(final Currency from, final Currency to)
24.147 + {
24.148 + final Map<Currency, Convertor> possible;
24.149 +
24.150 + if(from == null)
24.151 + {
24.152 + throw new IllegalArgumentException("from cannot be null");
24.153 + }
24.154 +
24.155 + if(to == null)
24.156 + {
24.157 + throw new IllegalArgumentException("to cannot be null");
24.158 + }
24.159 +
24.160 + possible = possibleConversions.get(from);
24.161 +
24.162 + if(possible.containsKey(to))
24.163 + {
24.164 + return (true);
24.165 + }
24.166 +
24.167 + return (false);
24.168 + }
24.169 +
24.170 + /**
24.171 + * Get the currencies that the convertor supports. Just because a currency is
24.172 + * supported does not mean that canConvert will return true.
24.173 + *
24.174 + * @return the supported currencies.
24.175 + */
24.176 + public Set<Currency> getCurrencies()
24.177 + {
24.178 + final Set<Currency> currencies;
24.179 +
24.180 + currencies = possibleConversions.keySet();
24.181 +
24.182 + return (Collections.unmodifiableSet(currencies));
24.183 + }
24.184 +
24.185 + /**
24.186 + * Get the conversion rate between two currencies.
24.187 + *
24.188 + * @param from the currency to convert from.
24.189 + * @param to the currency to convert to.
24.190 + * @return the conversion rate between the two currencies.
24.191 + * @throws IllegalArgumentException if either from or to is null.
24.192 + * @throws InvalidConversionException if canConvert would return false.
24.193 + */
24.194 + public BigDecimal getConversionRate(final Currency from, final Currency to)
24.195 + throws InvalidConversionException
24.196 + {
24.197 + final Map<Currency, Convertor> possible;
24.198 + Convertor convertor;
24.199 +
24.200 + if(from == null)
24.201 + {
24.202 + throw new IllegalArgumentException("from cannot be null");
24.203 + }
24.204 +
24.205 + if(to == null)
24.206 + {
24.207 + throw new IllegalArgumentException("to cannot be null");
24.208 + }
24.209 +
24.210 + if(!(canConvert(from, to)))
24.211 + {
24.212 + throw new InvalidConversionException("cannot convert", to);
24.213 + }
24.214 +
24.215 + possible = possibleConversions.get(from);
24.216 + convertor = possible.get(to);
24.217 +
24.218 + if(convertor == null)
24.219 + {
24.220 + throw new Error();
24.221 + }
24.222 +
24.223 + return (convertor.getConversionRate(from, to));
24.224 + }
24.225 +
24.226 + /**
24.227 + * Convert an amount from one currency to another.
24.228 + *
24.229 + * @param from the currency to convert from.
24.230 + * @param to the currency to convert to.
24.231 + * @param amount the amount to convert.
24.232 + * @return the converted amount.
24.233 + * @throws IllegalArgumentException if any of the arguments are null.
24.234 + * @throws InvalidConversionException if either from or to are not valid for the convertor.
24.235 + */
24.236 + public BigDecimal convert(final Currency from,
24.237 + final Currency to,
24.238 + final BigDecimal amount)
24.239 + throws InvalidConversionException
24.240 + {
24.241 + final BigDecimal result;
24.242 +
24.243 + if(amount == null)
24.244 + {
24.245 + throw new IllegalArgumentException("amount cannot be null");
24.246 + }
24.247 +
24.248 + if(from == null)
24.249 + {
24.250 + throw new IllegalArgumentException("from cannot be null");
24.251 + }
24.252 +
24.253 + if(to == null)
24.254 + {
24.255 + throw new IllegalArgumentException("to cannot be null");
24.256 + }
24.257 +
24.258 + result = amount.multiply(getConversionRate(from, to));
24.259 +
24.260 + return (result.setScale(2, RoundingMode.HALF_DOWN));
24.261 + }
24.262 +
24.263 + /**
24.264 + * Create a convertor between two currencies using another currency that is able to convert between both.
24.265 + *
24.266 + * @param from the currency to convert from.
24.267 + * @param to the currency to convert to.
24.268 + * @param intermediary the currency to use as a go-between.
24.269 + * @return a Convertor that is able to convert between from an to.
24.270 + * @throws IllegalArgumentException if any of the arguments are null.
24.271 + */
24.272 + private Convertor createConvertor(final Currency from,
24.273 + final Currency to,
24.274 + final Currency intermediary)
24.275 + {
24.276 + final Convertor fromIntermediary;
24.277 + final Convertor toIntermediary;
24.278 +
24.279 + if(from == null)
24.280 + {
24.281 + throw new IllegalArgumentException("from cannot be null");
24.282 + }
24.283 +
24.284 + if(to == null)
24.285 + {
24.286 + throw new IllegalArgumentException("to cannot be null");
24.287 + }
24.288 +
24.289 + if(intermediary == null)
24.290 + {
24.291 + throw new IllegalArgumentException("intermediary cannot be null");
24.292 + }
24.293 +
24.294 + fromIntermediary = possibleConversions.get(from).get(intermediary);
24.295 + toIntermediary = possibleConversions.get(to).get(intermediary);
24.296 +
24.297 + try
24.298 + {
24.299 + final BigDecimal fromRate;
24.300 + final BigDecimal toRate;
24.301 + final BigDecimal rate;
24.302 + final Convertor convertor;
24.303 +
24.304 + fromRate = fromIntermediary.getConversionRate(from, intermediary);
24.305 + toRate = toIntermediary.getConversionRate(intermediary, to);
24.306 + rate = fromRate.multiply(toRate);
24.307 +
24.308 + convertor = ConvertorFactory.getConvertor(from, BigDecimal.ONE, to, rate);
24.309 +
24.310 + return (convertor);
24.311 + }
24.312 + catch (InvalidConversionException ex)
24.313 + {
24.314 + throw new Error();
24.315 + }
24.316 + }
24.317 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/task3/solution04/src/org/apidesign/apifest08/currency/ConverterImpl.java Tue Oct 07 11:05:34 2008 +0200
25.3 @@ -0,0 +1,282 @@
25.4 +package org.apidesign.apifest08.currency;
25.5 +
25.6 +
25.7 +import java.math.BigDecimal;
25.8 +import java.math.MathContext;
25.9 +import java.math.RoundingMode;
25.10 +import java.util.Collections;
25.11 +import java.util.Currency;
25.12 +import java.util.HashSet;
25.13 +import java.util.Set;
25.14 +
25.15 +
25.16 +/**
25.17 + * Convert between two currencies.
25.18 + *
25.19 + * @author D'Arcy Smith
25.20 + * @version 1.0
25.21 + */
25.22 +final class ConvertorImpl
25.23 + implements Convertor
25.24 +{
25.25 + /**
25.26 + * The currency to cvonvert from.
25.27 + */
25.28 + private final Currency currencyA;
25.29 +
25.30 + /**
25.31 + * The currency to cvonvert from.
25.32 + */
25.33 + private final Currency currencyB;
25.34 +
25.35 + /**
25.36 + * The echange rate between a and b.
25.37 + */
25.38 + private final BigDecimal currencyARate;
25.39 +
25.40 + /**
25.41 + * The echange rate between b and a.
25.42 + */
25.43 + private final BigDecimal currencyBRate;
25.44 +
25.45 + /**
25.46 + * Constructs a convertor with the specified currencies.
25.47 + *
25.48 + * @param a the currency to convert from.
25.49 + * @param aRate the exchage rage between from and to.
25.50 + * @param b the currency to convert to.
25.51 + * @param bRate the exchage rage between to and from.
25.52 + * @throws IllegalArgumentException if either any of the arguments are null or if either rate <= 0.
25.53 + */
25.54 + public ConvertorImpl(final Currency a,
25.55 + final BigDecimal aRate,
25.56 + final Currency b,
25.57 + final BigDecimal bRate)
25.58 + {
25.59 + if(a == null)
25.60 + {
25.61 + throw new IllegalArgumentException("a cannot be null");
25.62 + }
25.63 +
25.64 + if(b == null)
25.65 + {
25.66 + throw new IllegalArgumentException("b cannot be null");
25.67 + }
25.68 +
25.69 + if(aRate == null)
25.70 + {
25.71 + throw new IllegalArgumentException("aRate cannot be null");
25.72 + }
25.73 +
25.74 + if(bRate == null)
25.75 + {
25.76 + throw new IllegalArgumentException("bRate cannot be null");
25.77 + }
25.78 +
25.79 + if(aRate.compareTo(BigDecimal.ZERO) <= 0)
25.80 + {
25.81 + throw new IllegalArgumentException("aRate must be > 0, was: " + aRate);
25.82 + }
25.83 +
25.84 + if(bRate.compareTo(BigDecimal.ZERO) <= 0)
25.85 + {
25.86 + throw new IllegalArgumentException("bRate must be > 0, was: " + bRate);
25.87 + }
25.88 +
25.89 + currencyA = a;
25.90 + currencyB = b;
25.91 + currencyARate = aRate;
25.92 + currencyBRate = bRate;
25.93 + }
25.94 +
25.95 + /**
25.96 + * Convert an amount from one currency to another.
25.97 + *
25.98 + * @param from the currency to convert from.
25.99 + * @param to the currency to convert to.
25.100 + * @param amount the amount to convert.
25.101 + * @return the converted amount.
25.102 + * @throws IllegalArgumentException if any of the arguments are null.
25.103 + * @throws InvalidConversionException if either from or to are not equal to the currencies passed to the constructor.
25.104 + */
25.105 + public BigDecimal convert(final Currency from,
25.106 + final Currency to,
25.107 + final BigDecimal amount)
25.108 + throws InvalidConversionException
25.109 + {
25.110 + final BigDecimal result;
25.111 +
25.112 + if(amount == null)
25.113 + {
25.114 + throw new IllegalArgumentException("amount cannot be null");
25.115 + }
25.116 +
25.117 + if(from == null)
25.118 + {
25.119 + throw new IllegalArgumentException("from cannot be null");
25.120 + }
25.121 +
25.122 + if(to == null)
25.123 + {
25.124 + throw new IllegalArgumentException("to cannot be null");
25.125 + }
25.126 +
25.127 + if(!(from.equals(currencyA)) && (!(from.equals(currencyB))))
25.128 + {
25.129 + throw new InvalidConversionException("cannot convert from: " + from.getCurrencyCode(), from, currencyA, currencyB);
25.130 + }
25.131 +
25.132 + if(!(to.equals(currencyA)) && (!(to.equals(currencyB))))
25.133 + {
25.134 + throw new InvalidConversionException("cannot convert to: " + to.getCurrencyCode(), to, currencyA, currencyB);
25.135 + }
25.136 +
25.137 + result = amount.multiply(getConversionRate(from, to));
25.138 +
25.139 + return (result.setScale(2, RoundingMode.HALF_DOWN));
25.140 + }
25.141 +
25.142 + /**
25.143 + * Check to see if converting between the two currencies is possible.
25.144 + *
25.145 + * @param from the currency to convert from.
25.146 + * @param to the currency to convert to.
25.147 + * @return true if the conversion is possible.
25.148 + */
25.149 + public boolean canConvert(final Currency from, final Currency to)
25.150 + {
25.151 + return ((from.equals(currencyA) || from.equals(currencyB)) &&
25.152 + (to.equals(currencyA) || to.equals(currencyB)));
25.153 + }
25.154 +
25.155 + /**
25.156 + * Get the currencies that the convertor supports.
25.157 + *
25.158 + * @return the supported currencies.
25.159 + */
25.160 + public Set<Currency> getCurrencies()
25.161 + {
25.162 + final Set<Currency> currencies;
25.163 +
25.164 + currencies = new HashSet<Currency>();
25.165 + currencies.add(currencyA);
25.166 + currencies.add(currencyB);
25.167 +
25.168 + return (Collections.unmodifiableSet(currencies));
25.169 + }
25.170 +
25.171 + /**
25.172 + * Get the conversion rate between two currencies.
25.173 + *
25.174 + * @param from the currency to convert from.
25.175 + * @param to the currency to convert to.
25.176 + * @return the conversion rate between the two currencies.
25.177 + * @throws InvalidConversionException if canConvert would return false.
25.178 + */
25.179 + public BigDecimal getConversionRate(final Currency from,
25.180 + final Currency to)
25.181 + throws InvalidConversionException
25.182 + {
25.183 + final BigDecimal rate;
25.184 +
25.185 + if(from.equals(to))
25.186 + {
25.187 + rate = BigDecimal.ONE;
25.188 + }
25.189 + else
25.190 + {
25.191 + final BigDecimal rateX;
25.192 + final BigDecimal rateY;
25.193 + final BigDecimal temp;
25.194 +
25.195 + if(from.equals(currencyA))
25.196 + {
25.197 + rateX = currencyARate;
25.198 + rateY = currencyBRate;
25.199 + }
25.200 + else
25.201 + {
25.202 + rateX = currencyBRate;
25.203 + rateY = currencyARate;
25.204 + }
25.205 +
25.206 + temp = BigDecimal.ONE.divide(rateX, MathContext.DECIMAL64);
25.207 + rate = temp.multiply(rateY);
25.208 + }
25.209 +
25.210 + return (rate.setScale(20, RoundingMode.HALF_EVEN));
25.211 + }
25.212 +
25.213 + /**
25.214 + * Check to see if two ConvertorImpls are equal.
25.215 + *
25.216 + * @param obj the object to check
25.217 + * @return if the ConvertorImpls are not the same (cuyrrencies and rates).
25.218 + */
25.219 + @Override
25.220 + public boolean equals(Object obj)
25.221 + {
25.222 + if (obj == null)
25.223 + {
25.224 + return false;
25.225 + }
25.226 +
25.227 + if (getClass() != obj.getClass())
25.228 + {
25.229 + return false;
25.230 + }
25.231 +
25.232 + final ConvertorImpl other = (ConvertorImpl) obj;
25.233 +
25.234 + // it would be nice if NetBeans could chck to see if the variable is final and guaranteed not to be null... but that
25.235 + // would likely be tricky... but in a NetBeans engineer reads that see if you can do it :-)
25.236 + if (this.currencyA != other.currencyA && (this.currencyA == null || !this.currencyA.equals(other.currencyA)))
25.237 + {
25.238 + return false;
25.239 + }
25.240 +
25.241 + if (this.currencyB != other.currencyB && (this.currencyB == null || !this.currencyB.equals(other.currencyB)))
25.242 + {
25.243 + return false;
25.244 + }
25.245 +
25.246 + if (this.currencyARate != other.currencyARate && (this.currencyARate == null || !this.currencyARate.equals(other.currencyARate)))
25.247 + {
25.248 + return false;
25.249 + }
25.250 +
25.251 + if (this.currencyBRate != other.currencyBRate && (this.currencyBRate == null || !this.currencyBRate.equals(other.currencyBRate)))
25.252 + {
25.253 + return false;
25.254 + }
25.255 +
25.256 + return true;
25.257 + }
25.258 +
25.259 + /**
25.260 + * Get the hashCode of the Convertor.
25.261 + *
25.262 + * @return the hashCode of the convertor.
25.263 + */
25.264 + @Override
25.265 + public int hashCode()
25.266 + {
25.267 + int hash = 7;
25.268 + hash = 37 * hash + (this.currencyA != null ? this.currencyA.hashCode() : 0);
25.269 + hash = 37 * hash + (this.currencyB != null ? this.currencyB.hashCode() : 0);
25.270 + hash = 37 * hash + (this.currencyARate != null ? this.currencyARate.hashCode() : 0);
25.271 + hash = 37 * hash + (this.currencyBRate != null ? this.currencyBRate.hashCode() : 0);
25.272 + return hash;
25.273 + }
25.274 +
25.275 + /**
25.276 + * Get the currencyCode of both currencies.
25.277 + *
25.278 + * @return the currency codes of both currencies.
25.279 + */
25.280 + @Override
25.281 + public String toString()
25.282 + {
25.283 + return (currencyA.getCurrencyCode() + " to " + currencyB.getCurrencyCode());
25.284 + }
25.285 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/task3/solution04/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 11:05:34 2008 +0200
26.3 @@ -0,0 +1,59 @@
26.4 +package org.apidesign.apifest08.currency;
26.5 +
26.6 +
26.7 +import java.math.BigDecimal;
26.8 +import java.util.Currency;
26.9 +import java.util.Set;
26.10 +
26.11 +
26.12 +/**
26.13 + * Convert between two currencies.
26.14 + *
26.15 + * @author D'Arcy Smith
26.16 + * @version 1.0
26.17 + */
26.18 +public interface Convertor
26.19 +{
26.20 + /**
26.21 + * Convert an amount from one currency to another.
26.22 + *
26.23 + * @param from the currency to convert from.
26.24 + * @param to the currency to convert to.
26.25 + * @param amount the amount to convert.
26.26 + * @return the converted amount.
26.27 + * @throws IllegalArgumentException if any of the arguments are null.
26.28 + * @throws InvalidConversionException if either from or to are not valid for the convertor.
26.29 + */
26.30 + BigDecimal convert(Currency from,
26.31 + Currency to,
26.32 + BigDecimal amount)
26.33 + throws InvalidConversionException;
26.34 +
26.35 + /**
26.36 + * Check to see if converting between the two currencies is possible.
26.37 + *
26.38 + * @param from the currency to convert from.
26.39 + * @param to the currency to convert to.
26.40 + * @return true if the conversion is possible.
26.41 + */
26.42 + boolean canConvert(Currency from, Currency to);
26.43 +
26.44 + /**
26.45 + * Get the currencies that the convertor supports. Just because a currency is
26.46 + * supported does not mean that canConvert will return true.
26.47 + *
26.48 + * @return the supported currencies.
26.49 + */
26.50 + Set<Currency> getCurrencies();
26.51 +
26.52 + /**
26.53 + * Get the conversion rate between two currencies.
26.54 + *
26.55 + * @param from the currency to convert from.
26.56 + * @param to the currency to convert to.
26.57 + * @return the conversion rate between the two currencies.
26.58 + * @throws InvalidConversionException if canConvert would return false.
26.59 + */
26.60 + BigDecimal getConversionRate(final Currency from, final Currency to)
26.61 + throws InvalidConversionException;
26.62 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/task3/solution04/src/org/apidesign/apifest08/currency/ConvertorFactory.java Tue Oct 07 11:05:34 2008 +0200
27.3 @@ -0,0 +1,172 @@
27.4 +package org.apidesign.apifest08.currency;
27.5 +
27.6 +import java.math.BigDecimal;
27.7 +import java.util.Currency;
27.8 +
27.9 +
27.10 +/**
27.11 + * Create convertors using a flyweight to reduce the number of repetative creations of the same convertor.
27.12 + *
27.13 + * @author D'Arcy Smith
27.14 + * @version 1.0
27.15 + */
27.16 +public final class ConvertorFactory
27.17 +{
27.18 + /*
27.19 + * flyweight so that only one vestion of each converter is created at a time.
27.20 + private final static Map<String, WeakReference<Convertor>> convertors;
27.21 +
27.22 + static
27.23 + {
27.24 + convertors = new WeakHashMap<String, WeakReference<Convertor>>();
27.25 + }
27.26 + */
27.27 +
27.28 + /**
27.29 + * Prevent accidental construction.
27.30 + */
27.31 + private ConvertorFactory()
27.32 + {
27.33 + }
27.34 +
27.35 + /**
27.36 + * Get the convertor for the specified currencies. The currency name format
27.37 + * must be acceptable to java.util.Currency.getInstance(String)
27.38 + *
27.39 + * @param a the currency to convert from.
27.40 + * @param aRate the exchange rate for a to b.
27.41 + * @param b the currency to convert to.
27.42 + * @param bRate the echante rate for b to a.
27.43 + * @return the convertor for the specified currencies.
27.44 + * @throws IllegalArgumentException if any of the arguments are null.
27.45 + */
27.46 + public static Convertor getConvertor(final String a,
27.47 + final BigDecimal aRate,
27.48 + final String b,
27.49 + final BigDecimal bRate)
27.50 + {
27.51 + final Currency currencyA;
27.52 + final Currency currencyB;
27.53 + final Convertor convertor;
27.54 +
27.55 + currencyA = Currency.getInstance(a);
27.56 + currencyB = Currency.getInstance(b);
27.57 + convertor = getConvertor(currencyA, aRate, currencyB, bRate);
27.58 +
27.59 + return (convertor);
27.60 + }
27.61 +
27.62 + /**
27.63 + * Get the convertor for the specified currencies.
27.64 + *
27.65 + * @param a the currency to convert from.
27.66 + * @param aRate the exchange rate for a to b.
27.67 + * @param b the currency to convert to.
27.68 + * @param bRate the echante rate for b to a.
27.69 + * @return the convertor for the specified currencies.
27.70 + * @throws IllegalArgumentException if either any of the arguments are null or if either rate <= 0.
27.71 + */
27.72 + public static Convertor getConvertor(final Currency a,
27.73 + final BigDecimal aRate,
27.74 + final Currency b,
27.75 + final BigDecimal bRate)
27.76 + {
27.77 + // final String key;
27.78 + Convertor convertor;
27.79 +
27.80 + if(a == null)
27.81 + {
27.82 + throw new IllegalArgumentException("a cannot be null");
27.83 + }
27.84 +
27.85 + if(b == null)
27.86 + {
27.87 + throw new IllegalArgumentException("b cannot be null");
27.88 + }
27.89 +
27.90 + if(aRate == null)
27.91 + {
27.92 + throw new IllegalArgumentException("aRate cannot be null");
27.93 + }
27.94 +
27.95 + if(bRate == null)
27.96 + {
27.97 + throw new IllegalArgumentException("bRate cannot be null");
27.98 + }
27.99 +
27.100 + /*
27.101 + key = a.getCurrencyCode() + aRate + b.getCurrencyCode() + bRate;
27.102 +
27.103 + // make sure that we don't try to overwrite one
27.104 + synchronized(convertors)
27.105 + {
27.106 + if(!(convertors.containsKey(key)))
27.107 + {
27.108 + convertor = new ConvertorImpl(a, aRate, b, bRate);
27.109 + convertors.put(key, new WeakReference(convertor));
27.110 + }
27.111 +
27.112 + convertor = convertors.get(key).get();
27.113 + }
27.114 + */
27.115 +
27.116 + convertor = new ConvertorImpl(a, aRate, b, bRate);
27.117 +
27.118 + return (convertor);
27.119 + }
27.120 +
27.121 + public static Convertor mergeConvertors(final Convertor ... cs)
27.122 + {
27.123 + Convertor convertor;
27.124 +
27.125 + /*
27.126 + final String key;
27.127 +
27.128 + // ISSUE: only takes into account the names... not the rates...
27.129 + key = getKey(cs);
27.130 +
27.131 + // make sure that we don't try to overwrite one
27.132 + synchronized(convertors)
27.133 + {
27.134 + if(!(convertors.containsKey(key)))
27.135 + {
27.136 + convertor = new CompositeConvertorImpl(cs);
27.137 + convertors.put(key, new WeakReference(convertor));
27.138 + }
27.139 +
27.140 + convertor = convertors.get(key).get();
27.141 + }
27.142 + */
27.143 +
27.144 + convertor = new CompositeConvertorImpl(cs);
27.145 +
27.146 + return (convertor);
27.147 + }
27.148 +
27.149 + /*
27.150 + private static String getKey(final Convertor ... cs)
27.151 + {
27.152 + final Set<Currency> currencies;
27.153 + final StringBuilder builder;
27.154 +
27.155 + currencies = new HashSet<Currency>();
27.156 +
27.157 + for(final Convertor convertor : cs)
27.158 + {
27.159 + final Set<Currency> c;
27.160 +
27.161 + c = convertor.getCurrencies();
27.162 + currencies.addAll(c);
27.163 + }
27.164 +
27.165 + builder = new StringBuilder();
27.166 +
27.167 + for(final Currency currency : currencies)
27.168 + {
27.169 + builder.append(currency.getCurrencyCode());
27.170 + }
27.171 +
27.172 + return (builder.toString());
27.173 + }
27.174 + */
27.175 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/task3/solution04/src/org/apidesign/apifest08/currency/InvalidConversionException.java Tue Oct 07 11:05:34 2008 +0200
28.3 @@ -0,0 +1,95 @@
28.4 +package org.apidesign.apifest08.currency;
28.5 +
28.6 +
28.7 +import java.util.Currency;
28.8 +
28.9 +
28.10 +/**
28.11 + * Thrown when a currency is invalid for a given Convertor.
28.12 + *
28.13 + * @author D'Arcy Smith
28.14 + * @version 1.0
28.15 + */
28.16 +public class InvalidConversionException
28.17 + extends Exception
28.18 +{
28.19 + /**
28.20 + * The currency that was tried.
28.21 + */
28.22 + private final Currency badCurrency;
28.23 +
28.24 + /**
28.25 + * A currency that is valid for the Convertor.
28.26 + */
28.27 + private final Currency currencyA;
28.28 +
28.29 + /**
28.30 + * A currency that is valid for the Convertor.
28.31 + */
28.32 + private final Currency currencyB;
28.33 +
28.34 +
28.35 + /**
28.36 + * Construct a new InvalidConversionException with the specified message.
28.37 + *
28.38 + * @param msg the message for getMessage.
28.39 + * @param bad the currency that is not valid.
28.40 + */
28.41 + public InvalidConversionException(final String msg,
28.42 + final Currency bad)
28.43 + {
28.44 + this(msg, bad, null, null);
28.45 + }
28.46 +
28.47 + /**
28.48 + * Construct a new InvalidConversionException with the specified message.
28.49 + *
28.50 + * @param msg the message for getMessage.
28.51 + * @param bad the currency that is not valid.
28.52 + * @param a a valid currency.
28.53 + * @param b a valid currency.
28.54 + */
28.55 + public InvalidConversionException(final String msg,
28.56 + final Currency bad,
28.57 + final Currency a,
28.58 + final Currency b)
28.59 + {
28.60 + super(msg);
28.61 +
28.62 + badCurrency = bad;
28.63 + currencyA = a;
28.64 + currencyB = b;
28.65 + }
28.66 +
28.67 + /**
28.68 + * Get the currency that is not valid.
28.69 + *
28.70 + * @return the badCurrency
28.71 + */
28.72 + public Currency getBadCurrency()
28.73 + {
28.74 + return (badCurrency);
28.75 + }
28.76 +
28.77 + /**
28.78 + * Get a currency that is valid.
28.79 + *
28.80 + * @return the currencyA passed to the constructor.
28.81 + */
28.82 + public Currency getCurrencyA()
28.83 + {
28.84 + return (currencyA);
28.85 + }
28.86 +
28.87 + /**
28.88 + * Get a currency that is valid.
28.89 + *
28.90 + * @return the currencyB passed to the constructor.
28.91 + */
28.92 + public Currency getCurrencyB()
28.93 + {
28.94 + return (currencyB);
28.95 + }
28.96 +
28.97 +
28.98 +}
28.99 \ No newline at end of file
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/task3/solution04/test/org/apidesign/apifest08/test/Task1Test.java Tue Oct 07 11:05:34 2008 +0200
29.3 @@ -0,0 +1,223 @@
29.4 +package org.apidesign.apifest08.test;
29.5 +
29.6 +
29.7 +import java.math.BigDecimal;
29.8 +import java.util.Currency;
29.9 +import java.util.Set;
29.10 +import junit.framework.TestCase;
29.11 +import org.apidesign.apifest08.currency.Convertor;
29.12 +import org.apidesign.apifest08.currency.ConvertorFactory;
29.13 +import org.apidesign.apifest08.currency.InvalidConversionException;
29.14 +
29.15 +
29.16 +/** Finish the Convertor API, and then write bodies of methods inside
29.17 + * of this class to match the given tasks. To fullfil your task, use the
29.18 + * API define in the <code>org.apidesign.apifest08.currency</code> package.
29.19 + * Do not you reflection, or other hacks as your code
29.20 + * shall run without any runtime permissions.
29.21 + */
29.22 +public class Task1Test extends TestCase {
29.23 +
29.24 + private final static Currency CZK;
29.25 + private final static Currency SKK;
29.26 + private final static Currency USD;
29.27 +
29.28 + static
29.29 + {
29.30 + CZK = Currency.getInstance("CZK");
29.31 + SKK = Currency.getInstance("SKK");
29.32 + USD = Currency.getInstance("USD");
29.33 + }
29.34 +
29.35 + public Task1Test(String testName) {
29.36 + super(testName);
29.37 + }
29.38 +
29.39 + @Override
29.40 + protected void setUp() throws Exception {
29.41 + }
29.42 +
29.43 + @Override
29.44 + protected void tearDown() throws Exception {
29.45 + }
29.46 +
29.47 + /** Create convertor that understands two currencies, CZK and
29.48 + * USD. Make 1 USD == 17 CZK.
29.49 + *
29.50 + * Creation of the convertor shall not require subclassing of any class
29.51 + * or interface on the client side.
29.52 + *
29.53 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
29.54 + */
29.55 + public static Convertor createCZKtoUSD()
29.56 + {
29.57 + return (ConvertorFactory.getConvertor("CZK", BigDecimal.valueOf(17.0),
29.58 + "USD", BigDecimal.valueOf(1)));
29.59 + }
29.60 +
29.61 + /** Create convertor that understands two currencies, CZK and
29.62 + * SKK. Make 100 SKK == 80 CZK.
29.63 + *
29.64 + * Creation of the convertor shall not require subclassing of any class
29.65 + * or interface on the client side.
29.66 + *
29.67 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
29.68 + */
29.69 + public static Convertor createSKKtoCZK()
29.70 + {
29.71 + return (ConvertorFactory.getConvertor(Currency.getInstance("SKK"), BigDecimal.valueOf(100),
29.72 + Currency.getInstance("CZK"), BigDecimal.valueOf(80)));
29.73 + }
29.74 +
29.75 + /** Use the convertor from <code>createCZKtoUSD</code> method and do few conversions
29.76 + * with it.
29.77 + */
29.78 + public void testCurrencyCZKUSD() throws Exception {
29.79 + Convertor c = createCZKtoUSD();
29.80 + BigDecimal result;
29.81 +
29.82 + // convert $5 to CZK using c:
29.83 + // assertEquals("Result is 85 CZK");
29.84 + result = c.convert(USD, CZK, BigDecimal.valueOf(5));
29.85 + assertEquals(new BigDecimal("85.00"), result);
29.86 +
29.87 + // convert $8 to CZK
29.88 + // assertEquals("Result is 136 CZK");
29.89 + result = c.convert(USD, CZK, BigDecimal.valueOf(8));
29.90 + assertEquals(new BigDecimal("136.00"), result);
29.91 +
29.92 + // convert 1003CZK to USD
29.93 + // assertEquals("Result is 59 USD");
29.94 + result = c.convert(CZK, USD, BigDecimal.valueOf(1003));
29.95 + assertEquals(new BigDecimal("59.00"), result);
29.96 + }
29.97 +
29.98 + /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
29.99 + * with it.
29.100 + */
29.101 + public void testCurrencySKKCZK() throws Exception {
29.102 + Convertor c = createSKKtoCZK();
29.103 + BigDecimal result;
29.104 +
29.105 + // convert 16CZK using c:
29.106 + // assertEquals("Result is 20 SKK");
29.107 + result = c.convert(CZK, SKK, BigDecimal.valueOf(16));
29.108 + assertEquals(new BigDecimal("20.00"), result);
29.109 +
29.110 + // convert 500SKK to CZK
29.111 + // assertEquals("Result is 400 CZK");
29.112 + result = c.convert(SKK, CZK, BigDecimal.valueOf(500));
29.113 + assertEquals(new BigDecimal("400.00"), result);
29.114 + }
29.115 +
29.116 + /**
29.117 + * Verify that the CZK to USD convertor knows nothing about SKK.
29.118 + */
29.119 + public void testCannotConvertToSKKwithCZKUSDConvertor()
29.120 + throws Exception
29.121 + {
29.122 + Convertor c = createCZKtoUSD();
29.123 +
29.124 + try
29.125 + {
29.126 + // convert $5 to SKK, the API shall say this is not possible
29.127 + c.convert(USD, SKK, BigDecimal.valueOf(5));
29.128 + fail("cannot use the CZKtoUSD converter to convert to SKK");
29.129 + }
29.130 + catch(InvalidConversionException ex)
29.131 + {
29.132 + assertEquals("cannot convert to: SKK", ex.getMessage());
29.133 + assertEquals(SKK, ex.getBadCurrency());
29.134 + assertEquals(CZK, ex.getCurrencyA());
29.135 + assertEquals(USD, ex.getCurrencyB());
29.136 + }
29.137 +
29.138 + try
29.139 + {
29.140 + // convert 500 SKK to CZK, the API shall say this is not possible
29.141 + c.convert(SKK, CZK, BigDecimal.valueOf(5));
29.142 + fail("cannot use the CZKtoUSD converter to convert from SKK");
29.143 + }
29.144 + catch(InvalidConversionException ex)
29.145 + {
29.146 + assertEquals("cannot convert from: SKK", ex.getMessage());
29.147 + assertEquals(SKK, ex.getBadCurrency());
29.148 + assertEquals(CZK, ex.getCurrencyA());
29.149 + assertEquals(USD, ex.getCurrencyB());
29.150 + }
29.151 + }
29.152 +
29.153 + /**
29.154 + * Verify that the CZK to SKK convertor knows nothing about USD.
29.155 + */
29.156 + public void testCannotConvertToUSDwithSKKCZKConvertor()
29.157 + throws Exception
29.158 + {
29.159 + Convertor c = createSKKtoCZK();
29.160 +
29.161 + try
29.162 + {
29.163 + // convert $5 to SKK, the API shall say this is not possible
29.164 + c.convert(USD, SKK, BigDecimal.valueOf(5));
29.165 + fail("cannot use the CZKtoUSD converter to convert to SKK");
29.166 + }
29.167 + catch(InvalidConversionException ex)
29.168 + {
29.169 + assertEquals("cannot convert from: USD", ex.getMessage());
29.170 + assertEquals(USD, ex.getBadCurrency());
29.171 + assertEquals(SKK, ex.getCurrencyA());
29.172 + assertEquals(CZK, ex.getCurrencyB());
29.173 + }
29.174 +
29.175 + try
29.176 + {
29.177 + // convert 500 CZK to USD, the API shall say this is not possible
29.178 + c.convert(CZK, USD, BigDecimal.valueOf(500));
29.179 + fail("cannot use the CZKtoUSD converter to convert from SKK");
29.180 + }
29.181 + catch(InvalidConversionException ex)
29.182 + {
29.183 + assertEquals("cannot convert to: USD", ex.getMessage());
29.184 + assertEquals(USD, ex.getBadCurrency());
29.185 + assertEquals(SKK, ex.getCurrencyA());
29.186 + assertEquals(CZK, ex.getCurrencyB());
29.187 + }
29.188 + }
29.189 +
29.190 + public void testGetCurrencies()
29.191 + {
29.192 + Convertor c;
29.193 + Set<Currency> currencies;
29.194 +
29.195 + c = createSKKtoCZK();
29.196 + currencies = c.getCurrencies();
29.197 + assertEquals(2, currencies.size());
29.198 + assertTrue(currencies.contains(Currency.getInstance("SKK")));
29.199 + assertTrue(currencies.contains(Currency.getInstance("CZK")));
29.200 +
29.201 + c = createCZKtoUSD();
29.202 + currencies = c.getCurrencies();
29.203 + assertEquals(2, currencies.size());
29.204 + assertTrue(currencies.contains(Currency.getInstance("USD")));
29.205 + assertTrue(currencies.contains(Currency.getInstance("CZK")));
29.206 + }
29.207 +
29.208 + public void testGetConverstionRate()
29.209 + throws InvalidConversionException
29.210 + {
29.211 + Convertor c;
29.212 +
29.213 + c = createSKKtoCZK();
29.214 + assertEquals(1.0, c.getConversionRate(Currency.getInstance("CZK"), Currency.getInstance("CZK")).doubleValue());
29.215 + assertEquals(1.0, c.getConversionRate(Currency.getInstance("SKK"), Currency.getInstance("SKK")).doubleValue());
29.216 + assertEquals(0.80, c.getConversionRate(Currency.getInstance("SKK"), Currency.getInstance("CZK")).doubleValue());
29.217 + assertEquals(1.25, c.getConversionRate(Currency.getInstance("CZK"), Currency.getInstance("SKK")).doubleValue());
29.218 +
29.219 + c = createCZKtoUSD();
29.220 + assertEquals(1.0, c.getConversionRate(Currency.getInstance("CZK"), Currency.getInstance("CZK")).doubleValue());
29.221 + assertEquals(1.0, c.getConversionRate(Currency.getInstance("USD"), Currency.getInstance("USD")).doubleValue());
29.222 + assertEquals(1.0/17.0, c.getConversionRate(Currency.getInstance("CZK"), Currency.getInstance("USD")).doubleValue(), 0.00000000000000001);
29.223 + assertEquals(17.0, c.getConversionRate(Currency.getInstance("USD"), Currency.getInstance("CZK")).doubleValue(), 0.00000000000000001);
29.224 + }
29.225 +}
29.226 +
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/task3/solution04/test/org/apidesign/apifest08/test/Task2Test.java Tue Oct 07 11:05:34 2008 +0200
30.3 @@ -0,0 +1,179 @@
30.4 +package org.apidesign.apifest08.test;
30.5 +
30.6 +import java.math.BigDecimal;
30.7 +import java.util.Currency;
30.8 +import java.util.Set;
30.9 +import junit.framework.TestCase;
30.10 +import org.apidesign.apifest08.currency.Convertor;
30.11 +import org.apidesign.apifest08.currency.ConvertorFactory;
30.12 +import org.apidesign.apifest08.currency.InvalidConversionException;
30.13 +
30.14 +
30.15 +/** There are many currencies around the world and many banks manipulate
30.16 + * with more than one or two at the same time. As banks are usually the
30.17 + * best paying clients, which is true even in case of your Convertor API,
30.18 + * it is reasonable to listen to their requests.
30.19 + * <p>
30.20 + * The quest for today is to enhance your existing convertor API to hold
30.21 + * information about many currencies and allow conversions between any of them.
30.22 + * Also, as conversion rates for diferent currencies usually arise from various
30.23 + * bank departments, there is another important need. There is a need to
30.24 + * compose two convertors into one by merging all the information about
30.25 + * currencies they know about.
30.26 + */
30.27 +public class Task2Test extends TestCase
30.28 +{
30.29 + private final static Currency CZK;
30.30 + private final static Currency SKK;
30.31 + private final static Currency USD;
30.32 +
30.33 + static
30.34 + {
30.35 + CZK = Currency.getInstance("CZK");
30.36 + SKK = Currency.getInstance("SKK");
30.37 + USD = Currency.getInstance("USD");
30.38 + }
30.39 +
30.40 + public Task2Test(String testName)
30.41 + {
30.42 + super(testName);
30.43 + }
30.44 +
30.45 + @Override
30.46 + protected void setUp()
30.47 + throws Exception
30.48 + {
30.49 + }
30.50 +
30.51 + @Override
30.52 + protected void tearDown()
30.53 + throws Exception
30.54 + {
30.55 + }
30.56 +
30.57 + // As in Task1Test, keep in mind, that there are three parts
30.58 + // of the whole system:
30.59 + // 1. there is someone who knows the current exchange rate
30.60 + // 2. there is someone who wants to do the conversion
30.61 + // 3. there is the API between 1. and 2. which allows them to communicate
30.62 + //
30.63 + // Please backward compatibly enhance your existing API to support following
30.64 + // usecases:
30.65 + //
30.66 +
30.67 + /** Create convertor that understands two currencies, CZK and
30.68 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
30.69 + * knows the exchange rate, and needs to use the API to create objects
30.70 + * with the exchange rate. Anyone shall be ready to call this method without
30.71 + * any other method being called previously. The API itself shall know
30.72 + * nothing about any rates, before this method is called.
30.73 + */
30.74 + public static Convertor createTripleConvertor() {
30.75 + // Rates: 1USD = 15CZK
30.76 + // Rates: 1USD = 20SKK
30.77 + // Rates: 75CZK = 100SKK
30.78 + Convertor c = ConvertorFactory.mergeConvertors(
30.79 + ConvertorFactory.getConvertor(USD, BigDecimal.ONE, CZK, BigDecimal.valueOf(15.00)),
30.80 + ConvertorFactory.getConvertor(USD, BigDecimal.ONE, SKK, BigDecimal.valueOf(20.00))
30.81 + );
30.82 +
30.83 + return c;
30.84 + }
30.85 +
30.86 + /** Define convertor that understands three currencies. Use it.
30.87 + */
30.88 + public void testConvertorForUSDandCZKandSKK() throws Exception {
30.89 + Convertor c = createTripleConvertor();
30.90 +
30.91 + // convert $5 to CZK using c:
30.92 + // assertEquals("Result is 75 CZK");
30.93 + assertEquals(new BigDecimal("75.00"), c.convert(USD, CZK, BigDecimal.valueOf(5.00)));
30.94 +
30.95 + // convert $5 to SKK using c:
30.96 + // assertEquals("Result is 100 SKK");
30.97 + assertEquals(new BigDecimal("100.00"), c.convert(USD, SKK, BigDecimal.valueOf(5.00)));
30.98 +
30.99 + // convert 200SKK to CZK using c:
30.100 + // assertEquals("Result is 150 CZK");
30.101 + assertEquals(new BigDecimal("150.00"), c.convert(SKK, CZK, BigDecimal.valueOf(200.00)));
30.102 +
30.103 + // convert 200SKK to USK using c:
30.104 + // assertEquals("Result is 10 USD");
30.105 + assertEquals(new BigDecimal("10.00"), c.convert(SKK, USD, BigDecimal.valueOf(200.00)));
30.106 + }
30.107 +
30.108 + /** Merge all currency rates of convertor 1 with convertor 2.
30.109 + * Implement this using your API, preferably this method just delegates
30.110 + * into some API method which does the actual work, without requiring
30.111 + * API clients to code anything complex.
30.112 + */
30.113 + public static Convertor merge(Convertor one, Convertor two) {
30.114 + return ConvertorFactory.mergeConvertors(one, two);
30.115 + }
30.116 +
30.117 + /** Join the convertors from previous task, Task1Test and show that it
30.118 + * can be used to do reasonable conversions.
30.119 + */
30.120 + public void testConvertorComposition() throws Exception {
30.121 + Convertor c = merge(
30.122 + Task1Test.createCZKtoUSD(),
30.123 + Task1Test.createSKKtoCZK()
30.124 + );
30.125 +
30.126 + // convert $5 to CZK using c:
30.127 + // assertEquals("Result is 85 CZK");
30.128 + assertEquals(new BigDecimal("85.00"), c.convert(USD, CZK, BigDecimal.valueOf(5.00)));
30.129 +
30.130 + // convert $8 to CZK using c:
30.131 + // assertEquals("Result is 136 CZK");
30.132 + assertEquals(new BigDecimal("136.00"), c.convert(USD, CZK, BigDecimal.valueOf(8.00)));
30.133 +
30.134 + // convert 1003CZK to USD using c:
30.135 + // assertEquals("Result is 59 USD");
30.136 + assertEquals(new BigDecimal("59.00"), c.convert(CZK, USD, BigDecimal.valueOf(1003.00)));
30.137 +
30.138 + // convert 16CZK using c:
30.139 + // assertEquals("Result is 20 SKK");
30.140 + assertEquals(new BigDecimal("20.00"), c.convert(CZK, SKK, BigDecimal.valueOf(16.00)));
30.141 +
30.142 + // convert 500SKK to CZK using c:
30.143 + // assertEquals("Result is 400 CZK");
30.144 + assertEquals(new BigDecimal("400.00"), c.convert(SKK, CZK, BigDecimal.valueOf(500.00)));
30.145 + }
30.146 +
30.147 + public void testGetCurrencies()
30.148 + {
30.149 + Convertor c = merge(
30.150 + Task1Test.createCZKtoUSD(),
30.151 + Task1Test.createSKKtoCZK()
30.152 + );
30.153 + Set<Currency> currencies;
30.154 +
30.155 + currencies = c.getCurrencies();
30.156 + assertEquals(3, currencies.size());
30.157 + assertTrue(currencies.contains(Currency.getInstance("SKK")));
30.158 + assertTrue(currencies.contains(Currency.getInstance("CZK")));
30.159 + assertTrue(currencies.contains(Currency.getInstance("USD")));
30.160 + }
30.161 +
30.162 + public void testGetConverstionRate()
30.163 + throws InvalidConversionException
30.164 + {
30.165 + Convertor c = merge(
30.166 + Task1Test.createCZKtoUSD(),
30.167 + Task1Test.createSKKtoCZK()
30.168 + );
30.169 +
30.170 + assertEquals(1.0, c.getConversionRate(USD, USD).doubleValue(), 0.0000000000000001);
30.171 + assertEquals(17.0, c.getConversionRate(USD, CZK).doubleValue(), 0.0000000000000001);
30.172 + assertEquals(21.25, c.getConversionRate(USD, SKK).doubleValue(), 0.0000000000000001);
30.173 +
30.174 + assertEquals(1.0 / 17.0, c.getConversionRate(CZK, USD).doubleValue(), 0.0000000000000001);
30.175 + assertEquals(1.0, c.getConversionRate(CZK, CZK).doubleValue(), 0.0000000000000001);
30.176 + assertEquals(1.25, c.getConversionRate(CZK, SKK).doubleValue(), 0.0000000000000001);
30.177 +
30.178 + assertEquals(0.04705882352941176, c.getConversionRate(SKK, USD).doubleValue(), 0.0000000000000001);
30.179 + assertEquals(0.8, c.getConversionRate(SKK, CZK).doubleValue(), 0.0000000000000001);
30.180 + assertEquals(1.0, c.getConversionRate(SKK, SKK).doubleValue(), 0.0000000000000001);
30.181 + }
30.182 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/task3/solution06/build.xml Tue Oct 07 11:05:34 2008 +0200
31.3 @@ -0,0 +1,69 @@
31.4 +<?xml version="1.0" encoding="UTF-8"?>
31.5 +<!-- You may freely edit this file. See commented blocks below for -->
31.6 +<!-- some examples of how to customize the build. -->
31.7 +<!-- (If you delete it and reopen the project it will be recreated.) -->
31.8 +<project name="currency" default="default" basedir=".">
31.9 + <description>Builds, tests, and runs the project.</description>
31.10 + <import file="nbproject/build-impl.xml"/>
31.11 + <!--
31.12 +
31.13 + There exist several targets which are by default empty and which can be
31.14 + used for execution of your tasks. These targets are usually executed
31.15 + before and after some main targets. They are:
31.16 +
31.17 + -pre-init: called before initialization of project properties
31.18 + -post-init: called after initialization of project properties
31.19 + -pre-compile: called before javac compilation
31.20 + -post-compile: called after javac compilation
31.21 + -pre-compile-single: called before javac compilation of single file
31.22 + -post-compile-single: called after javac compilation of single file
31.23 + -pre-compile-test: called before javac compilation of JUnit tests
31.24 + -post-compile-test: called after javac compilation of JUnit tests
31.25 + -pre-compile-test-single: called before javac compilation of single JUnit test
31.26 + -post-compile-test-single: called after javac compilation of single JUunit test
31.27 + -pre-jar: called before JAR building
31.28 + -post-jar: called after JAR building
31.29 + -post-clean: called after cleaning build products
31.30 +
31.31 + (Targets beginning with '-' are not intended to be called on their own.)
31.32 +
31.33 + Example of inserting an obfuscator after compilation could look like this:
31.34 +
31.35 + <target name="-post-compile">
31.36 + <obfuscate>
31.37 + <fileset dir="${build.classes.dir}"/>
31.38 + </obfuscate>
31.39 + </target>
31.40 +
31.41 + For list of available properties check the imported
31.42 + nbproject/build-impl.xml file.
31.43 +
31.44 +
31.45 + Another way to customize the build is by overriding existing main targets.
31.46 + The targets of interest are:
31.47 +
31.48 + -init-macrodef-javac: defines macro for javac compilation
31.49 + -init-macrodef-junit: defines macro for junit execution
31.50 + -init-macrodef-debug: defines macro for class debugging
31.51 + -init-macrodef-java: defines macro for class execution
31.52 + -do-jar-with-manifest: JAR building (if you are using a manifest)
31.53 + -do-jar-without-manifest: JAR building (if you are not using a manifest)
31.54 + run: execution of project
31.55 + -javadoc-build: Javadoc generation
31.56 + test-report: JUnit report generation
31.57 +
31.58 + An example of overriding the target for project execution could look like this:
31.59 +
31.60 + <target name="run" depends="currency-impl.jar">
31.61 + <exec dir="bin" executable="launcher.exe">
31.62 + <arg file="${dist.jar}"/>
31.63 + </exec>
31.64 + </target>
31.65 +
31.66 + Notice that the overridden target depends on the jar target and not only on
31.67 + the compile target as the regular run target does. Again, for a list of available
31.68 + properties which you can use, check the target you are overriding in the
31.69 + nbproject/build-impl.xml file.
31.70 +
31.71 + -->
31.72 +</project>
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/task3/solution06/nbproject/build-impl.xml Tue Oct 07 11:05:34 2008 +0200
32.3 @@ -0,0 +1,642 @@
32.4 +<?xml version="1.0" encoding="UTF-8"?>
32.5 +<!--
32.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
32.7 +*** EDIT ../build.xml INSTEAD ***
32.8 +
32.9 +For the purpose of easier reading the script
32.10 +is divided into following sections:
32.11 +
32.12 + - initialization
32.13 + - compilation
32.14 + - jar
32.15 + - execution
32.16 + - debugging
32.17 + - javadoc
32.18 + - junit compilation
32.19 + - junit execution
32.20 + - junit debugging
32.21 + - applet
32.22 + - cleanup
32.23 +
32.24 + -->
32.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_06-impl">
32.26 + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
32.27 + <!--
32.28 + ======================
32.29 + INITIALIZATION SECTION
32.30 + ======================
32.31 + -->
32.32 + <target name="-pre-init">
32.33 + <!-- Empty placeholder for easier customization. -->
32.34 + <!-- You can override this target in the ../build.xml file. -->
32.35 + </target>
32.36 + <target depends="-pre-init" name="-init-private">
32.37 + <property file="nbproject/private/config.properties"/>
32.38 + <property file="nbproject/private/configs/${config}.properties"/>
32.39 + <property file="nbproject/private/private.properties"/>
32.40 + </target>
32.41 + <target depends="-pre-init,-init-private" name="-init-user">
32.42 + <property file="${user.properties.file}"/>
32.43 + <!-- The two properties below are usually overridden -->
32.44 + <!-- by the active platform. Just a fallback. -->
32.45 + <property name="default.javac.source" value="1.4"/>
32.46 + <property name="default.javac.target" value="1.4"/>
32.47 + </target>
32.48 + <target depends="-pre-init,-init-private,-init-user" name="-init-project">
32.49 + <property file="nbproject/configs/${config}.properties"/>
32.50 + <property file="nbproject/project.properties"/>
32.51 + </target>
32.52 + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
32.53 + <available file="${manifest.file}" property="manifest.available"/>
32.54 + <condition property="manifest.available+main.class">
32.55 + <and>
32.56 + <isset property="manifest.available"/>
32.57 + <isset property="main.class"/>
32.58 + <not>
32.59 + <equals arg1="${main.class}" arg2="" trim="true"/>
32.60 + </not>
32.61 + </and>
32.62 + </condition>
32.63 + <condition property="manifest.available+main.class+mkdist.available">
32.64 + <and>
32.65 + <istrue value="${manifest.available+main.class}"/>
32.66 + <isset property="libs.CopyLibs.classpath"/>
32.67 + </and>
32.68 + </condition>
32.69 + <condition property="have.tests">
32.70 + <or>
32.71 + <available file="${test.src.dir}"/>
32.72 + </or>
32.73 + </condition>
32.74 + <condition property="have.sources">
32.75 + <or>
32.76 + <available file="${src.dir}"/>
32.77 + </or>
32.78 + </condition>
32.79 + <condition property="netbeans.home+have.tests">
32.80 + <and>
32.81 + <isset property="netbeans.home"/>
32.82 + <isset property="have.tests"/>
32.83 + </and>
32.84 + </condition>
32.85 + <condition property="no.javadoc.preview">
32.86 + <and>
32.87 + <isset property="javadoc.preview"/>
32.88 + <isfalse value="${javadoc.preview}"/>
32.89 + </and>
32.90 + </condition>
32.91 + <property name="run.jvmargs" value=""/>
32.92 + <property name="javac.compilerargs" value=""/>
32.93 + <property name="work.dir" value="${basedir}"/>
32.94 + <condition property="no.deps">
32.95 + <and>
32.96 + <istrue value="${no.dependencies}"/>
32.97 + </and>
32.98 + </condition>
32.99 + <property name="javac.debug" value="true"/>
32.100 + <property name="javadoc.preview" value="true"/>
32.101 + <property name="application.args" value=""/>
32.102 + <property name="source.encoding" value="${file.encoding}"/>
32.103 + <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
32.104 + <and>
32.105 + <isset property="javadoc.encoding"/>
32.106 + <not>
32.107 + <equals arg1="${javadoc.encoding}" arg2=""/>
32.108 + </not>
32.109 + </and>
32.110 + </condition>
32.111 + <property name="javadoc.encoding.used" value="${source.encoding}"/>
32.112 + <property name="includes" value="**"/>
32.113 + <property name="excludes" value=""/>
32.114 + <property name="do.depend" value="false"/>
32.115 + <condition property="do.depend.true">
32.116 + <istrue value="${do.depend}"/>
32.117 + </condition>
32.118 + <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
32.119 + <and>
32.120 + <isset property="jaxws.endorsed.dir"/>
32.121 + <available file="nbproject/jaxws-build.xml"/>
32.122 + </and>
32.123 + </condition>
32.124 + </target>
32.125 + <target name="-post-init">
32.126 + <!-- Empty placeholder for easier customization. -->
32.127 + <!-- You can override this target in the ../build.xml file. -->
32.128 + </target>
32.129 + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
32.130 + <fail unless="src.dir">Must set src.dir</fail>
32.131 + <fail unless="test.src.dir">Must set test.src.dir</fail>
32.132 + <fail unless="build.dir">Must set build.dir</fail>
32.133 + <fail unless="dist.dir">Must set dist.dir</fail>
32.134 + <fail unless="build.classes.dir">Must set build.classes.dir</fail>
32.135 + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
32.136 + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
32.137 + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
32.138 + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
32.139 + <fail unless="dist.jar">Must set dist.jar</fail>
32.140 + </target>
32.141 + <target name="-init-macrodef-property">
32.142 + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
32.143 + <attribute name="name"/>
32.144 + <attribute name="value"/>
32.145 + <sequential>
32.146 + <property name="@{name}" value="${@{value}}"/>
32.147 + </sequential>
32.148 + </macrodef>
32.149 + </target>
32.150 + <target name="-init-macrodef-javac">
32.151 + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
32.152 + <attribute default="${src.dir}" name="srcdir"/>
32.153 + <attribute default="${build.classes.dir}" name="destdir"/>
32.154 + <attribute default="${javac.classpath}" name="classpath"/>
32.155 + <attribute default="${includes}" name="includes"/>
32.156 + <attribute default="${excludes}" name="excludes"/>
32.157 + <attribute default="${javac.debug}" name="debug"/>
32.158 + <attribute default="" name="sourcepath"/>
32.159 + <element name="customize" optional="true"/>
32.160 + <sequential>
32.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}">
32.162 + <classpath>
32.163 + <path path="@{classpath}"/>
32.164 + </classpath>
32.165 + <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
32.166 + <customize/>
32.167 + </javac>
32.168 + </sequential>
32.169 + </macrodef>
32.170 + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
32.171 + <attribute default="${src.dir}" name="srcdir"/>
32.172 + <attribute default="${build.classes.dir}" name="destdir"/>
32.173 + <attribute default="${javac.classpath}" name="classpath"/>
32.174 + <sequential>
32.175 + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
32.176 + <classpath>
32.177 + <path path="@{classpath}"/>
32.178 + </classpath>
32.179 + </depend>
32.180 + </sequential>
32.181 + </macrodef>
32.182 + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
32.183 + <attribute default="${build.classes.dir}" name="destdir"/>
32.184 + <sequential>
32.185 + <fail unless="javac.includes">Must set javac.includes</fail>
32.186 + <pathconvert pathsep="," property="javac.includes.binary">
32.187 + <path>
32.188 + <filelist dir="@{destdir}" files="${javac.includes}"/>
32.189 + </path>
32.190 + <globmapper from="*.java" to="*.class"/>
32.191 + </pathconvert>
32.192 + <delete>
32.193 + <files includes="${javac.includes.binary}"/>
32.194 + </delete>
32.195 + </sequential>
32.196 + </macrodef>
32.197 + </target>
32.198 + <target name="-init-macrodef-junit">
32.199 + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
32.200 + <attribute default="${includes}" name="includes"/>
32.201 + <attribute default="${excludes}" name="excludes"/>
32.202 + <attribute default="**" name="testincludes"/>
32.203 + <sequential>
32.204 + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
32.205 + <batchtest todir="${build.test.results.dir}">
32.206 + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
32.207 + <filename name="@{testincludes}"/>
32.208 + </fileset>
32.209 + </batchtest>
32.210 + <classpath>
32.211 + <path path="${run.test.classpath}"/>
32.212 + </classpath>
32.213 + <syspropertyset>
32.214 + <propertyref prefix="test-sys-prop."/>
32.215 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
32.216 + </syspropertyset>
32.217 + <formatter type="brief" usefile="false"/>
32.218 + <formatter type="xml"/>
32.219 + <jvmarg line="${run.jvmargs}"/>
32.220 + </junit>
32.221 + </sequential>
32.222 + </macrodef>
32.223 + </target>
32.224 + <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
32.225 + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
32.226 + <attribute default="${main.class}" name="name"/>
32.227 + <attribute default="${debug.classpath}" name="classpath"/>
32.228 + <attribute default="" name="stopclassname"/>
32.229 + <sequential>
32.230 + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
32.231 + <classpath>
32.232 + <path path="@{classpath}"/>
32.233 + </classpath>
32.234 + </nbjpdastart>
32.235 + </sequential>
32.236 + </macrodef>
32.237 + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
32.238 + <attribute default="${build.classes.dir}" name="dir"/>
32.239 + <sequential>
32.240 + <nbjpdareload>
32.241 + <fileset dir="@{dir}" includes="${fix.classes}">
32.242 + <include name="${fix.includes}*.class"/>
32.243 + </fileset>
32.244 + </nbjpdareload>
32.245 + </sequential>
32.246 + </macrodef>
32.247 + </target>
32.248 + <target name="-init-debug-args">
32.249 + <property name="version-output" value="java version "${ant.java.version}"/>
32.250 + <condition property="have-jdk-older-than-1.4">
32.251 + <or>
32.252 + <contains string="${version-output}" substring="java version "1.0"/>
32.253 + <contains string="${version-output}" substring="java version "1.1"/>
32.254 + <contains string="${version-output}" substring="java version "1.2"/>
32.255 + <contains string="${version-output}" substring="java version "1.3"/>
32.256 + </or>
32.257 + </condition>
32.258 + <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
32.259 + <istrue value="${have-jdk-older-than-1.4}"/>
32.260 + </condition>
32.261 + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
32.262 + <os family="windows"/>
32.263 + </condition>
32.264 + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
32.265 + <isset property="debug.transport"/>
32.266 + </condition>
32.267 + </target>
32.268 + <target depends="-init-debug-args" name="-init-macrodef-debug">
32.269 + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
32.270 + <attribute default="${main.class}" name="classname"/>
32.271 + <attribute default="${debug.classpath}" name="classpath"/>
32.272 + <element name="customize" optional="true"/>
32.273 + <sequential>
32.274 + <java classname="@{classname}" dir="${work.dir}" fork="true">
32.275 + <jvmarg line="${debug-args-line}"/>
32.276 + <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
32.277 + <jvmarg line="${run.jvmargs}"/>
32.278 + <classpath>
32.279 + <path path="@{classpath}"/>
32.280 + </classpath>
32.281 + <syspropertyset>
32.282 + <propertyref prefix="run-sys-prop."/>
32.283 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
32.284 + </syspropertyset>
32.285 + <customize/>
32.286 + </java>
32.287 + </sequential>
32.288 + </macrodef>
32.289 + </target>
32.290 + <target name="-init-macrodef-java">
32.291 + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
32.292 + <attribute default="${main.class}" name="classname"/>
32.293 + <element name="customize" optional="true"/>
32.294 + <sequential>
32.295 + <java classname="@{classname}" dir="${work.dir}" fork="true">
32.296 + <jvmarg line="${run.jvmargs}"/>
32.297 + <classpath>
32.298 + <path path="${run.classpath}"/>
32.299 + </classpath>
32.300 + <syspropertyset>
32.301 + <propertyref prefix="run-sys-prop."/>
32.302 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
32.303 + </syspropertyset>
32.304 + <customize/>
32.305 + </java>
32.306 + </sequential>
32.307 + </macrodef>
32.308 + </target>
32.309 + <target name="-init-presetdef-jar">
32.310 + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
32.311 + <jar compress="${jar.compress}" jarfile="${dist.jar}">
32.312 + <j2seproject1:fileset dir="${build.classes.dir}"/>
32.313 + </jar>
32.314 + </presetdef>
32.315 + </target>
32.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"/>
32.317 + <!--
32.318 + ===================
32.319 + COMPILATION SECTION
32.320 + ===================
32.321 + -->
32.322 + <target depends="init" name="deps-jar" unless="no.deps"/>
32.323 + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
32.324 + <target depends="init" name="-check-automatic-build">
32.325 + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
32.326 + </target>
32.327 + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
32.328 + <antcall target="clean"/>
32.329 + </target>
32.330 + <target depends="init,deps-jar" name="-pre-pre-compile">
32.331 + <mkdir dir="${build.classes.dir}"/>
32.332 + </target>
32.333 + <target name="-pre-compile">
32.334 + <!-- Empty placeholder for easier customization. -->
32.335 + <!-- You can override this target in the ../build.xml file. -->
32.336 + </target>
32.337 + <target if="do.depend.true" name="-compile-depend">
32.338 + <j2seproject3:depend/>
32.339 + </target>
32.340 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
32.341 + <j2seproject3:javac/>
32.342 + <copy todir="${build.classes.dir}">
32.343 + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
32.344 + </copy>
32.345 + </target>
32.346 + <target name="-post-compile">
32.347 + <!-- Empty placeholder for easier customization. -->
32.348 + <!-- You can override this target in the ../build.xml file. -->
32.349 + </target>
32.350 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
32.351 + <target name="-pre-compile-single">
32.352 + <!-- Empty placeholder for easier customization. -->
32.353 + <!-- You can override this target in the ../build.xml file. -->
32.354 + </target>
32.355 + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
32.356 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
32.357 + <j2seproject3:force-recompile/>
32.358 + <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
32.359 + </target>
32.360 + <target name="-post-compile-single">
32.361 + <!-- Empty placeholder for easier customization. -->
32.362 + <!-- You can override this target in the ../build.xml file. -->
32.363 + </target>
32.364 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
32.365 + <!--
32.366 + ====================
32.367 + JAR BUILDING SECTION
32.368 + ====================
32.369 + -->
32.370 + <target depends="init" name="-pre-pre-jar">
32.371 + <dirname file="${dist.jar}" property="dist.jar.dir"/>
32.372 + <mkdir dir="${dist.jar.dir}"/>
32.373 + </target>
32.374 + <target name="-pre-jar">
32.375 + <!-- Empty placeholder for easier customization. -->
32.376 + <!-- You can override this target in the ../build.xml file. -->
32.377 + </target>
32.378 + <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
32.379 + <j2seproject1:jar/>
32.380 + </target>
32.381 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
32.382 + <j2seproject1:jar manifest="${manifest.file}"/>
32.383 + </target>
32.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">
32.385 + <j2seproject1:jar manifest="${manifest.file}">
32.386 + <j2seproject1:manifest>
32.387 + <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
32.388 + </j2seproject1:manifest>
32.389 + </j2seproject1:jar>
32.390 + <echo>To run this application from the command line without Ant, try:</echo>
32.391 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
32.392 + <property location="${dist.jar}" name="dist.jar.resolved"/>
32.393 + <pathconvert property="run.classpath.with.dist.jar">
32.394 + <path path="${run.classpath}"/>
32.395 + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
32.396 + </pathconvert>
32.397 + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
32.398 + </target>
32.399 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
32.400 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
32.401 + <pathconvert property="run.classpath.without.build.classes.dir">
32.402 + <path path="${run.classpath}"/>
32.403 + <map from="${build.classes.dir.resolved}" to=""/>
32.404 + </pathconvert>
32.405 + <pathconvert pathsep=" " property="jar.classpath">
32.406 + <path path="${run.classpath.without.build.classes.dir}"/>
32.407 + <chainedmapper>
32.408 + <flattenmapper/>
32.409 + <globmapper from="*" to="lib/*"/>
32.410 + </chainedmapper>
32.411 + </pathconvert>
32.412 + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
32.413 + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
32.414 + <fileset dir="${build.classes.dir}"/>
32.415 + <manifest>
32.416 + <attribute name="Main-Class" value="${main.class}"/>
32.417 + <attribute name="Class-Path" value="${jar.classpath}"/>
32.418 + </manifest>
32.419 + </copylibs>
32.420 + <echo>To run this application from the command line without Ant, try:</echo>
32.421 + <property location="${dist.jar}" name="dist.jar.resolved"/>
32.422 + <echo>java -jar "${dist.jar.resolved}"</echo>
32.423 + </target>
32.424 + <target name="-post-jar">
32.425 + <!-- Empty placeholder for easier customization. -->
32.426 + <!-- You can override this target in the ../build.xml file. -->
32.427 + </target>
32.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"/>
32.429 + <!--
32.430 + =================
32.431 + EXECUTION SECTION
32.432 + =================
32.433 + -->
32.434 + <target depends="init,compile" description="Run a main class." name="run">
32.435 + <j2seproject1:java>
32.436 + <customize>
32.437 + <arg line="${application.args}"/>
32.438 + </customize>
32.439 + </j2seproject1:java>
32.440 + </target>
32.441 + <target name="-do-not-recompile">
32.442 + <property name="javac.includes.binary" value=""/>
32.443 + </target>
32.444 + <target depends="init,-do-not-recompile,compile-single" name="run-single">
32.445 + <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
32.446 + <j2seproject1:java classname="${run.class}"/>
32.447 + </target>
32.448 + <!--
32.449 + =================
32.450 + DEBUGGING SECTION
32.451 + =================
32.452 + -->
32.453 + <target depends="init" if="netbeans.home" name="-debug-start-debugger">
32.454 + <j2seproject1:nbjpdastart name="${debug.class}"/>
32.455 + </target>
32.456 + <target depends="init,compile" name="-debug-start-debuggee">
32.457 + <j2seproject3:debug>
32.458 + <customize>
32.459 + <arg line="${application.args}"/>
32.460 + </customize>
32.461 + </j2seproject3:debug>
32.462 + </target>
32.463 + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
32.464 + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
32.465 + <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
32.466 + </target>
32.467 + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
32.468 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
32.469 + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
32.470 + <j2seproject3:debug classname="${debug.class}"/>
32.471 + </target>
32.472 + <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
32.473 + <target depends="init" name="-pre-debug-fix">
32.474 + <fail unless="fix.includes">Must set fix.includes</fail>
32.475 + <property name="javac.includes" value="${fix.includes}.java"/>
32.476 + </target>
32.477 + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
32.478 + <j2seproject1:nbjpdareload/>
32.479 + </target>
32.480 + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
32.481 + <!--
32.482 + ===============
32.483 + JAVADOC SECTION
32.484 + ===============
32.485 + -->
32.486 + <target depends="init" name="-javadoc-build">
32.487 + <mkdir dir="${dist.javadoc.dir}"/>
32.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}">
32.489 + <classpath>
32.490 + <path path="${javac.classpath}"/>
32.491 + </classpath>
32.492 + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
32.493 + <filename name="**/*.java"/>
32.494 + </fileset>
32.495 + </javadoc>
32.496 + </target>
32.497 + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
32.498 + <nbbrowse file="${dist.javadoc.dir}/index.html"/>
32.499 + </target>
32.500 + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
32.501 + <!--
32.502 + =========================
32.503 + JUNIT COMPILATION SECTION
32.504 + =========================
32.505 + -->
32.506 + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
32.507 + <mkdir dir="${build.test.classes.dir}"/>
32.508 + </target>
32.509 + <target name="-pre-compile-test">
32.510 + <!-- Empty placeholder for easier customization. -->
32.511 + <!-- You can override this target in the ../build.xml file. -->
32.512 + </target>
32.513 + <target if="do.depend.true" name="-compile-test-depend">
32.514 + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
32.515 + </target>
32.516 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
32.517 + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
32.518 + <copy todir="${build.test.classes.dir}">
32.519 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
32.520 + </copy>
32.521 + </target>
32.522 + <target name="-post-compile-test">
32.523 + <!-- Empty placeholder for easier customization. -->
32.524 + <!-- You can override this target in the ../build.xml file. -->
32.525 + </target>
32.526 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
32.527 + <target name="-pre-compile-test-single">
32.528 + <!-- Empty placeholder for easier customization. -->
32.529 + <!-- You can override this target in the ../build.xml file. -->
32.530 + </target>
32.531 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
32.532 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
32.533 + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
32.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}"/>
32.535 + <copy todir="${build.test.classes.dir}">
32.536 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
32.537 + </copy>
32.538 + </target>
32.539 + <target name="-post-compile-test-single">
32.540 + <!-- Empty placeholder for easier customization. -->
32.541 + <!-- You can override this target in the ../build.xml file. -->
32.542 + </target>
32.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"/>
32.544 + <!--
32.545 + =======================
32.546 + JUNIT EXECUTION SECTION
32.547 + =======================
32.548 + -->
32.549 + <target depends="init" if="have.tests" name="-pre-test-run">
32.550 + <mkdir dir="${build.test.results.dir}"/>
32.551 + </target>
32.552 + <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
32.553 + <j2seproject3:junit testincludes="**/*Test.java"/>
32.554 + </target>
32.555 + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
32.556 + <fail if="tests.failed">Some tests failed; see details above.</fail>
32.557 + </target>
32.558 + <target depends="init" if="have.tests" name="test-report"/>
32.559 + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
32.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"/>
32.561 + <target depends="init" if="have.tests" name="-pre-test-run-single">
32.562 + <mkdir dir="${build.test.results.dir}"/>
32.563 + </target>
32.564 + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
32.565 + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
32.566 + <j2seproject3:junit excludes="" includes="${test.includes}"/>
32.567 + </target>
32.568 + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
32.569 + <fail if="tests.failed">Some tests failed; see details above.</fail>
32.570 + </target>
32.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"/>
32.572 + <!--
32.573 + =======================
32.574 + JUNIT DEBUGGING SECTION
32.575 + =======================
32.576 + -->
32.577 + <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
32.578 + <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
32.579 + <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
32.580 + <delete file="${test.report.file}"/>
32.581 + <mkdir dir="${build.test.results.dir}"/>
32.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}">
32.583 + <customize>
32.584 + <syspropertyset>
32.585 + <propertyref prefix="test-sys-prop."/>
32.586 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
32.587 + </syspropertyset>
32.588 + <arg value="${test.class}"/>
32.589 + <arg value="showoutput=true"/>
32.590 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
32.591 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
32.592 + </customize>
32.593 + </j2seproject3:debug>
32.594 + </target>
32.595 + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
32.596 + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
32.597 + </target>
32.598 + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
32.599 + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
32.600 + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
32.601 + </target>
32.602 + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
32.603 + <!--
32.604 + =========================
32.605 + APPLET EXECUTION SECTION
32.606 + =========================
32.607 + -->
32.608 + <target depends="init,compile-single" name="run-applet">
32.609 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
32.610 + <j2seproject1:java classname="sun.applet.AppletViewer">
32.611 + <customize>
32.612 + <arg value="${applet.url}"/>
32.613 + </customize>
32.614 + </j2seproject1:java>
32.615 + </target>
32.616 + <!--
32.617 + =========================
32.618 + APPLET DEBUGGING SECTION
32.619 + =========================
32.620 + -->
32.621 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
32.622 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
32.623 + <j2seproject3:debug classname="sun.applet.AppletViewer">
32.624 + <customize>
32.625 + <arg value="${applet.url}"/>
32.626 + </customize>
32.627 + </j2seproject3:debug>
32.628 + </target>
32.629 + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
32.630 + <!--
32.631 + ===============
32.632 + CLEANUP SECTION
32.633 + ===============
32.634 + -->
32.635 + <target depends="init" name="deps-clean" unless="no.deps"/>
32.636 + <target depends="init" name="-do-clean">
32.637 + <delete dir="${build.dir}"/>
32.638 + <delete dir="${dist.dir}"/>
32.639 + </target>
32.640 + <target name="-post-clean">
32.641 + <!-- Empty placeholder for easier customization. -->
32.642 + <!-- You can override this target in the ../build.xml file. -->
32.643 + </target>
32.644 + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
32.645 +</project>
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/task3/solution06/nbproject/genfiles.properties Tue Oct 07 11:05:34 2008 +0200
33.3 @@ -0,0 +1,8 @@
33.4 +build.xml.data.CRC32=2ab820eb
33.5 +build.xml.script.CRC32=58a52595
33.6 +build.xml.stylesheet.CRC32=be360661
33.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
33.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
33.9 +nbproject/build-impl.xml.data.CRC32=ff801896
33.10 +nbproject/build-impl.xml.script.CRC32=a0996c47
33.11 +nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/task3/solution06/nbproject/project.properties Tue Oct 07 11:05:34 2008 +0200
34.3 @@ -0,0 +1,68 @@
34.4 +application.title=currency
34.5 +application.vendor=apidesign.org
34.6 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
34.7 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
34.8 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
34.9 +build.classes.dir=${build.dir}/classes
34.10 +build.classes.excludes=**/*.java,**/*.form
34.11 +# This directory is removed when the project is cleaned:
34.12 +build.dir=build
34.13 +build.generated.dir=${build.dir}/generated
34.14 +# Only compile against the classpath explicitly listed here:
34.15 +build.sysclasspath=ignore
34.16 +build.test.classes.dir=${build.dir}/test/classes
34.17 +build.test.results.dir=${build.dir}/test/results
34.18 +debug.classpath=\
34.19 + ${run.classpath}
34.20 +debug.test.classpath=\
34.21 + ${run.test.classpath}
34.22 +# This directory is removed when the project is cleaned:
34.23 +dist.dir=dist
34.24 +dist.jar=${dist.dir}/currency.jar
34.25 +dist.javadoc.dir=${dist.dir}/javadoc
34.26 +excludes=
34.27 +file.reference.junit-4.4.jar=../../libs/junit-4.4.jar
34.28 +file.reference.src-apifest08=..
34.29 +includes=**
34.30 +jar.compress=false
34.31 +javac.classpath=
34.32 +# Space-separated list of extra javac options
34.33 +javac.compilerargs=
34.34 +javac.deprecation=false
34.35 +javac.source=1.5
34.36 +javac.target=1.5
34.37 +javac.test.classpath=\
34.38 + ${javac.classpath}:\
34.39 + ${build.classes.dir}:\
34.40 + ${file.reference.junit-4.4.jar}
34.41 +javadoc.additionalparam=
34.42 +javadoc.author=false
34.43 +javadoc.encoding=
34.44 +javadoc.noindex=false
34.45 +javadoc.nonavbar=false
34.46 +javadoc.notree=false
34.47 +javadoc.private=false
34.48 +javadoc.splitindex=true
34.49 +javadoc.use=true
34.50 +javadoc.version=false
34.51 +javadoc.windowtitle=
34.52 +jnlp.codebase.type=local
34.53 +jnlp.codebase.url=file:/home/jarda/src/apifest08/currency/dist
34.54 +jnlp.descriptor=application
34.55 +jnlp.enabled=false
34.56 +jnlp.offline-allowed=false
34.57 +jnlp.signed=false
34.58 +meta.inf.dir=${src.dir}/META-INF
34.59 +platform.active=default_platform
34.60 +run.classpath=\
34.61 + ${javac.classpath}:\
34.62 + ${build.classes.dir}
34.63 +# Space-separated list of JVM arguments used when running the project
34.64 +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
34.65 +# or test-sys-prop.name=value to set system properties for unit tests):
34.66 +run.jvmargs=
34.67 +run.test.classpath=\
34.68 + ${javac.test.classpath}:\
34.69 + ${build.test.classes.dir}
34.70 +src.dir=src
34.71 +test.src.dir=test
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/task3/solution06/nbproject/project.xml Tue Oct 07 11:05:34 2008 +0200
35.3 @@ -0,0 +1,16 @@
35.4 +<?xml version="1.0" encoding="UTF-8"?>
35.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
35.6 + <type>org.netbeans.modules.java.j2seproject</type>
35.7 + <configuration>
35.8 + <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
35.9 + <name>Currency Convertor Solution 06</name>
35.10 + <minimum-ant-version>1.6.5</minimum-ant-version>
35.11 + <source-roots>
35.12 + <root id="src.dir"/>
35.13 + </source-roots>
35.14 + <test-roots>
35.15 + <root id="test.src.dir"/>
35.16 + </test-roots>
35.17 + </data>
35.18 + </configuration>
35.19 +</project>
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/task3/solution06/src/org/apidesign/apifest08/currency/Amount.java Tue Oct 07 11:05:34 2008 +0200
36.3 @@ -0,0 +1,81 @@
36.4 +package org.apidesign.apifest08.currency;
36.5 +
36.6 +import static org.apidesign.apifest08.currency.Assert.notNull;
36.7 +
36.8 +import java.math.BigDecimal;
36.9 +import java.math.RoundingMode;
36.10 +import java.util.Currency;
36.11 +
36.12 +/**
36.13 + * An amount representation. Amount is represented as composition of a value and
36.14 + * a currency.
36.15 + */
36.16 +public final class Amount {
36.17 +
36.18 + private final BigDecimal value;
36.19 + private final Currency currency;
36.20 + private final int scale;
36.21 + private final RoundingMode roundingMode;
36.22 +
36.23 + public static final RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_EVEN;
36.24 +
36.25 + public Amount(final BigDecimal value, final Currency currency) {
36.26 + notNull(value, "value");
36.27 + notNull(currency, "currency");
36.28 + this.value = value;
36.29 + this.currency = currency;
36.30 + this.scale = currency.getDefaultFractionDigits();
36.31 + this.roundingMode = DEFAULT_ROUNDING;
36.32 + }
36.33 +
36.34 + public Amount(final BigDecimal value, final Currency currency, final RoundingMode roundingMode) {
36.35 + notNull(value, "value");
36.36 + notNull(currency, "currency");
36.37 + notNull(roundingMode, "roundingMode");
36.38 +
36.39 + this.value = value;
36.40 + this.currency = currency;
36.41 + this.scale = currency.getDefaultFractionDigits();
36.42 + this.roundingMode = roundingMode;
36.43 + }
36.44 +
36.45 + public Amount(final long value, final Currency currency) {
36.46 + this(BigDecimal.valueOf(value), currency);
36.47 + }
36.48 +
36.49 + public Amount(final String value, final Currency currency) {
36.50 + this(new BigDecimal(value), currency);
36.51 + }
36.52 +
36.53 + /**
36.54 + * @return the value with scale of the associated currency and rounded by
36.55 + * the rounding mode.
36.56 + */
36.57 + public BigDecimal getValue() {
36.58 + return value.setScale(scale, roundingMode);
36.59 + }
36.60 +
36.61 + /**
36.62 + * @return the raw (no explicit scale, no explicit rounding) value
36.63 + */
36.64 + public BigDecimal getRawValue() {
36.65 + return value;
36.66 + }
36.67 +
36.68 + public Currency getCurrency() {
36.69 + return currency;
36.70 + }
36.71 +
36.72 + public int getScale() {
36.73 + return scale;
36.74 + }
36.75 +
36.76 + public RoundingMode getRoundingMode() {
36.77 + return roundingMode;
36.78 + }
36.79 +
36.80 + @Override
36.81 + public String toString() {
36.82 + return value + ",- " + currency.toString();
36.83 + }
36.84 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/task3/solution06/src/org/apidesign/apifest08/currency/Assert.java Tue Oct 07 11:05:34 2008 +0200
37.3 @@ -0,0 +1,11 @@
37.4 +package org.apidesign.apifest08.currency;
37.5 +
37.6 +public final class Assert {
37.7 + static void notNull(Object value, String argumentName) {
37.8 + if(value == null) {
37.9 + throw new IllegalArgumentException("The argument '" + argumentName + "' connot not be null");
37.10 + }
37.11 + }
37.12 +}
37.13 +
37.14 +
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/task3/solution06/src/org/apidesign/apifest08/currency/ConversionException.java Tue Oct 07 11:05:34 2008 +0200
38.3 @@ -0,0 +1,26 @@
38.4 +package org.apidesign.apifest08.currency;
38.5 +
38.6 +/**
38.7 + * Indicates that a desired conversion cannot be performed.
38.8 + */
38.9 +public class ConversionException extends CurrencyException {
38.10 +
38.11 + private static final long serialVersionUID = 1L;
38.12 +
38.13 + public ConversionException() {
38.14 + super();
38.15 + }
38.16 +
38.17 + public ConversionException(String message, Throwable cause) {
38.18 + super(message, cause);
38.19 + }
38.20 +
38.21 + public ConversionException(String message) {
38.22 + super(message);
38.23 + }
38.24 +
38.25 + public ConversionException(Throwable cause) {
38.26 + super(cause);
38.27 + }
38.28 +
38.29 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/task3/solution06/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 11:05:34 2008 +0200
39.3 @@ -0,0 +1,124 @@
39.4 +package org.apidesign.apifest08.currency;
39.5 +
39.6 +import static org.apidesign.apifest08.currency.Assert.notNull;
39.7 +
39.8 +import java.math.BigDecimal;
39.9 +import java.math.RoundingMode;
39.10 +import java.util.ArrayList;
39.11 +import java.util.Currency;
39.12 +import java.util.List;
39.13 +
39.14 +public final class Convertor {
39.15 +
39.16 + private List<ConvertorDelegate> convertorDelegates = new ArrayList<ConvertorDelegate>();
39.17 +
39.18 +
39.19 + /**
39.20 + * Create new instance of the converter for the given currencies and its rate.
39.21 + *
39.22 + * @param rateValue the rate between the first and the second currency
39.23 + * @param currencyFirst the first currency
39.24 + * @param currencySecond the second currency
39.25 + */
39.26 + public Convertor(BigDecimal rateValue, Currency currencyFirst, Currency currencySecond) {
39.27 + notNull(currencyFirst, "currencyFirst");
39.28 + notNull(currencySecond, "currencySecond");
39.29 + notNull(rateValue, "rateValue");
39.30 + convertorDelegates.add(new ConvertorDelegate(rateValue, currencyFirst, currencySecond));
39.31 + }
39.32 +
39.33 + /**
39.34 + * Create new instance of the convertor from the given convertors.
39.35 + * @param convertors the convertors
39.36 + */
39.37 + public Convertor(Convertor... convertors) {
39.38 + notNull(convertors, "convertors");
39.39 + if(convertors.length == 0) {
39.40 + throw new IllegalArgumentException("There must be at least one converter.");
39.41 + }
39.42 +
39.43 + for(Convertor convertor: convertors) {
39.44 + if(convertor != null) {
39.45 + convertorDelegates.addAll(convertor.convertorDelegates);
39.46 + }
39.47 + }
39.48 + }
39.49 +
39.50 + /**
39.51 + * Converts an amount value between the two currencies of this converter.
39.52 + *
39.53 + * @param amount an amount
39.54 + * @param fromCurrency an amount currency
39.55 + * @param toCurrency to a target currency
39.56 + * @return a converted amount value
39.57 + *
39.58 + * @throws ConversionException if the conversion fails
39.59 + * @throws UnsupportedConversionException if the conversion between a given currencies is not supported.
39.60 + */
39.61 + public Amount convert(BigDecimal amount, Currency fromCurrency, Currency toCurrency) throws ConversionException {
39.62 + notNull(amount, "amount");
39.63 + notNull(fromCurrency, "fromCurrency");
39.64 + notNull(toCurrency, "toCurrency");
39.65 + ConvertorDelegate appropriateDelegate = null;
39.66 +
39.67 + //try find an appropriate delegate for conversion
39.68 + for(ConvertorDelegate delegate : convertorDelegates) {
39.69 + if(delegate.isConversionSupported(fromCurrency, toCurrency)) {
39.70 + appropriateDelegate = delegate;
39.71 + break;
39.72 + }
39.73 + }
39.74 +
39.75 + if(appropriateDelegate == null) {
39.76 + throw new UnsupportedConversionException(fromCurrency, toCurrency);
39.77 + }
39.78 +
39.79 + return appropriateDelegate.convert(amount, fromCurrency, toCurrency);
39.80 + }
39.81 +
39.82 + /**
39.83 + * Internal delegate implements a logic for conversion between two currencies
39.84 + * and vice versa.
39.85 + * @see #isConversionSupported(Currency, Currency)
39.86 + */
39.87 + private static class ConvertorDelegate {
39.88 + private final Currency first;
39.89 + private final Currency second;
39.90 + private final BigDecimal rateValue; // a rate between the first currency and the second currency
39.91 + public static final BigDecimal one = new BigDecimal(1);
39.92 +
39.93 + private ConvertorDelegate(BigDecimal rateValue, Currency currencyFirst, Currency currencySecond) {
39.94 + this.rateValue = rateValue;
39.95 + this.first = currencyFirst;
39.96 + this.second = currencySecond;
39.97 + }
39.98 +
39.99 + private Amount convert(BigDecimal amount, Currency fromCurrency, Currency toCurrency) throws ConversionException {
39.100 + BigDecimal rateValue = getRateValue(fromCurrency, toCurrency);
39.101 + BigDecimal result = rateValue.multiply(amount);
39.102 + return new Amount(result, toCurrency);
39.103 + }
39.104 +
39.105 + private BigDecimal getRateValue(Currency fromCurrency, Currency toCurrency) {
39.106 +
39.107 + BigDecimal retVal;
39.108 +
39.109 + if(first == fromCurrency) {
39.110 + retVal = rateValue;
39.111 + } else {
39.112 + //reverse rate
39.113 + retVal = one.divide(rateValue, 10 ,RoundingMode.HALF_UP);
39.114 + }
39.115 +
39.116 + return retVal;
39.117 + }
39.118 +
39.119 + /**
39.120 + * @return <code>true</code> if the delegate is able to convert from the given currency
39.121 + * to the given currency and vice versa otherwise <code>false</code>.
39.122 + */
39.123 + private boolean isConversionSupported(Currency fromCurrency, Currency toCurrency) {
39.124 + return ((fromCurrency == first || fromCurrency == second) && (toCurrency == first || toCurrency == second));
39.125 + }
39.126 + }
39.127 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/task3/solution06/src/org/apidesign/apifest08/currency/CurrencyException.java Tue Oct 07 11:05:34 2008 +0200
40.3 @@ -0,0 +1,25 @@
40.4 +package org.apidesign.apifest08.currency;
40.5 +
40.6 +/**
40.7 + * Top level runtime exception for 'currency' API.
40.8 + */
40.9 +public class CurrencyException extends RuntimeException{
40.10 +
40.11 + private static final long serialVersionUID = 1L;
40.12 +
40.13 + public CurrencyException() {
40.14 + super();
40.15 + }
40.16 +
40.17 + public CurrencyException(String message, Throwable cause) {
40.18 + super(message, cause);
40.19 + }
40.20 +
40.21 + public CurrencyException(String message) {
40.22 + super(message);
40.23 + }
40.24 +
40.25 + public CurrencyException(Throwable cause) {
40.26 + super(cause);
40.27 + }
40.28 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/task3/solution06/src/org/apidesign/apifest08/currency/UnsupportedConversionException.java Tue Oct 07 11:05:34 2008 +0200
41.3 @@ -0,0 +1,27 @@
41.4 +package org.apidesign.apifest08.currency;
41.5 +
41.6 +import java.util.Currency;
41.7 +
41.8 +public final class UnsupportedConversionException extends ConversionException{
41.9 +
41.10 + private static final long serialVersionUID = 1L;
41.11 +
41.12 + private Currency from;
41.13 + private Currency to;
41.14 +
41.15 + public UnsupportedConversionException(Currency from, Currency to) {
41.16 + super("Conversion from the currency " + from + " to the currency " + to + " or vice versa in not supported.");
41.17 + this.from = from;
41.18 + this.to = to;
41.19 + }
41.20 +
41.21 + public Currency getFrom() {
41.22 + return from;
41.23 + }
41.24 +
41.25 + public Currency getTo() {
41.26 + return to;
41.27 + }
41.28 +
41.29 +
41.30 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/task3/solution06/test/org/apidesign/apifest08/test/Currencies.java Tue Oct 07 11:05:34 2008 +0200
42.3 @@ -0,0 +1,9 @@
42.4 +package org.apidesign.apifest08.test;
42.5 +
42.6 +import java.util.Currency;
42.7 +
42.8 +public class Currencies {
42.9 + public static final Currency CZK = Currency.getInstance("CZK");
42.10 + public static final Currency SKK = Currency.getInstance("SKK");
42.11 + public static final Currency USD = Currency.getInstance("USD");
42.12 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/task3/solution06/test/org/apidesign/apifest08/test/Task1Test.java Tue Oct 07 11:05:34 2008 +0200
43.3 @@ -0,0 +1,136 @@
43.4 +package org.apidesign.apifest08.test;
43.5 +
43.6 +import static org.apidesign.apifest08.test.Currencies.CZK;
43.7 +import static org.apidesign.apifest08.test.Currencies.SKK;
43.8 +import static org.apidesign.apifest08.test.Currencies.USD;
43.9 +
43.10 +import java.math.BigDecimal;
43.11 +
43.12 +import junit.framework.TestCase;
43.13 +
43.14 +import org.apidesign.apifest08.currency.Amount;
43.15 +import org.apidesign.apifest08.currency.ConversionException;
43.16 +import org.apidesign.apifest08.currency.Convertor;
43.17 +import org.apidesign.apifest08.currency.UnsupportedConversionException;
43.18 +
43.19 +/** Finish the Convertor API, and then write bodies of methods inside
43.20 + * of this class to match the given tasks. To fullfil your task, use the
43.21 + * API define in the <code>org.apidesign.apifest08.currency</code> package.
43.22 + * Do not you reflection, or other hacks as your code
43.23 + * shall run without any runtime permissions.
43.24 + */
43.25 +public class Task1Test extends TestCase {
43.26 + public Task1Test(String testName) {
43.27 + super(testName);
43.28 + }
43.29 +
43.30 + @Override
43.31 + protected void setUp() throws Exception {
43.32 + }
43.33 +
43.34 + @Override
43.35 + protected void tearDown() throws Exception {
43.36 + }
43.37 +
43.38 + /** Create convertor that understands two currencies, CZK and
43.39 + * USD. Make 1 USD == 17 CZK.
43.40 + *
43.41 + * Creation of the convertor shall not require subclassing of any class
43.42 + * or interface on the client side.
43.43 + *
43.44 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
43.45 + */
43.46 + public static Convertor createCZKtoUSD() {
43.47 + return new Convertor(new BigDecimal(17), USD, CZK);
43.48 + }
43.49 +
43.50 + /** Create convertor that understands two currencies, CZK and
43.51 + * SKK. Make 100 SKK == 80 CZK.
43.52 + *
43.53 + * Creation of the convertor shall not require subclassing of any class
43.54 + * or interface on the client side.
43.55 + *
43.56 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
43.57 + */
43.58 + public static Convertor createSKKtoCZK() {
43.59 + return new Convertor(new BigDecimal("0.8"), SKK, CZK);
43.60 + }
43.61 +
43.62 + /** Use the convertor from <code>createCZKtoUSD</code> method and do few conversions
43.63 + * with it.
43.64 + */
43.65 + public void testCurrencyCZKUSD() throws Exception {
43.66 + Convertor c = createCZKtoUSD();
43.67 + // convert $5 to CZK using c:
43.68 + Amount result = c.convert(new BigDecimal(5), USD, CZK);
43.69 + assertEquals("Result is 85 CZK", 85, result.getValue().intValue());
43.70 +
43.71 + // convert $8 to CZK
43.72 + result = c.convert(new BigDecimal(8), USD, CZK);
43.73 + assertEquals("Result is 136 CZK", 136, result.getValue().intValue());
43.74 +
43.75 + // convert 1003CZK to USD
43.76 + result = c.convert(new BigDecimal(1003), CZK, USD);
43.77 + assertEquals("Result is 59 USD", 59, result.getValue().intValue());
43.78 + }
43.79 +
43.80 + /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
43.81 + * with it.
43.82 + */
43.83 + public void testCurrencySKKCZK() throws Exception {
43.84 + Convertor c = createSKKtoCZK();
43.85 + // convert 16CZK using c:
43.86 + Amount result = c.convert(new BigDecimal(16), CZK, SKK);
43.87 + assertEquals("Result is 20 SKK", 20, result.getValue().intValue());
43.88 +
43.89 + // convert 500SKK to CZK
43.90 + result = c.convert(new BigDecimal(500), SKK, CZK);
43.91 + assertEquals("Result is 400 CZK", 400, result.getValue().intValue());
43.92 + }
43.93 +
43.94 +
43.95 + /**
43.96 + * Verify that the CZK to USD convertor knows nothing about SKK.
43.97 + */
43.98 + public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
43.99 + Convertor c = createCZKtoUSD();
43.100 + // convert $5 to SKK, the API shall say this is not possible
43.101 + try {
43.102 + c.convert(new BigDecimal(5), USD, SKK);
43.103 + fail("convert $5 to SKK, the API shall say this is not possible");
43.104 + } catch (ConversionException e) {
43.105 + //expected
43.106 + }
43.107 +
43.108 + // convert 500 SKK to CZK, the API shall say this is not possible
43.109 +
43.110 + try {
43.111 + c.convert(new BigDecimal("500"), SKK, CZK);
43.112 + fail("convert 500 SKK to CZK, the API shall say this is not possible");
43.113 + } catch (ConversionException e) {
43.114 + //expected
43.115 + }
43.116 + }
43.117 +
43.118 + /**
43.119 + * Verify that the CZK to SKK convertor knows nothing about USD.
43.120 + */
43.121 + public void testCannotConvertToSKKwithCZKSKKConvertor() throws Exception {
43.122 + Convertor c = createSKKtoCZK();
43.123 + // convert $5 to SKK, the API shall say this is not possible
43.124 + try {
43.125 + c.convert(new BigDecimal(5), USD, SKK);
43.126 + fail("convert $5 to SKK, the API shall say this is not possible");
43.127 + } catch(ConversionException e) {
43.128 + //expected
43.129 + }
43.130 +
43.131 + try {
43.132 + c.convert(new BigDecimal(500), CZK, USD);
43.133 + fail("convert 500 CZK to USD, the API shall say this is not possible");
43.134 + } catch(ConversionException e) {
43.135 + //expected
43.136 + }
43.137 + }
43.138 +}
43.139 +
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/task3/solution06/test/org/apidesign/apifest08/test/Task2Test.java Tue Oct 07 11:05:34 2008 +0200
44.3 @@ -0,0 +1,117 @@
44.4 +package org.apidesign.apifest08.test;
44.5 +
44.6 +import static org.apidesign.apifest08.test.Currencies.CZK;
44.7 +import static org.apidesign.apifest08.test.Currencies.USD;
44.8 +import static org.apidesign.apifest08.test.Currencies.SKK;
44.9 +
44.10 +import java.math.BigDecimal;
44.11 +
44.12 +import junit.framework.TestCase;
44.13 +import org.apidesign.apifest08.currency.Convertor;
44.14 +import org.apidesign.apifest08.test.Task1Test;
44.15 +
44.16 +/** There are many currencies around the world and many banks manipulate
44.17 + * with more than one or two at the same time. As banks are usually the
44.18 + * best paying clients, which is true even in case of your Convertor API,
44.19 + * it is reasonable to listen to their requests.
44.20 + * <p>
44.21 + * The quest for today is to enhance your existing convertor API to hold
44.22 + * information about many currencies and allow conversions between any of them.
44.23 + * Also, as conversion rates for diferent currencies usually arise from various
44.24 + * bank departments, there is another important need. There is a need to
44.25 + * compose two convertors into one by merging all the information about
44.26 + * currencies they know about.
44.27 + */
44.28 +public class Task2Test extends TestCase {
44.29 + public Task2Test(String testName) {
44.30 + super(testName);
44.31 + }
44.32 +
44.33 + @Override
44.34 + protected void setUp() throws Exception {
44.35 + }
44.36 +
44.37 + @Override
44.38 + protected void tearDown() throws Exception {
44.39 + }
44.40 +
44.41 + // As in Task1Test, keep in mind, that there are three parts
44.42 + // of the whole system:
44.43 + // 1. there is someone who knows the current exchange rate
44.44 + // 2. there is someone who wants to do the conversion
44.45 + // 3. there is the API between 1. and 2. which allows them to communicate
44.46 + //
44.47 + // Please backward compatibly enhance your existing API to support following
44.48 + // usecases:
44.49 + //
44.50 +
44.51 + /** Create convertor that understands two currencies, CZK and
44.52 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
44.53 + * knows the exchange rate, and needs to use the API to create objects
44.54 + * with the exchange rate. Anyone shall be ready to call this method without
44.55 + * any other method being called previously. The API itself shall know
44.56 + * nothing about any rates, before this method is called.
44.57 + */
44.58 + public static Convertor createTripleConvertor() {
44.59 + // Rates: 1USD = 15CZK
44.60 + // Rates: 1USD = 20SKK
44.61 + // Rates: 75CZK = 100SKK
44.62 + Convertor usdCzk = new Convertor(new BigDecimal(15), USD, CZK);
44.63 + Convertor usdSkk = new Convertor(new BigDecimal(20), USD, SKK);
44.64 + Convertor skkCzk = new Convertor(new BigDecimal("0.75"), SKK, CZK);
44.65 + return new Convertor(new Convertor[]{usdCzk, usdSkk, skkCzk});
44.66 + }
44.67 +
44.68 + /** Define convertor that understands three currencies. Use it.
44.69 + */
44.70 + public void testConvertorForUSDandCZKandSKK() throws Exception {
44.71 + Convertor c = createTripleConvertor();
44.72 +
44.73 + // convert $5 to CZK using c:
44.74 + assertEquals("Result is 75 CZK", 75 ,c.convert(new BigDecimal(5), USD, CZK).getValue().intValue());
44.75 +
44.76 + // convert $5 to SKK using c:
44.77 + assertEquals("Result is 100 SKK", 100, c.convert(new BigDecimal(5), USD, SKK).getValue().intValue());
44.78 +
44.79 + // convert 200SKK to CZK using c:
44.80 + assertEquals("Result is 150 CZK", 150, c.convert(new BigDecimal(200), SKK, CZK).getValue().intValue());
44.81 +
44.82 + // convert 200SKK to USK using c:
44.83 + assertEquals("Result is 10 USD", 10, c.convert(new BigDecimal(200), SKK, USD).getValue().intValue());
44.84 + }
44.85 +
44.86 + /** Merge all currency rates of convertor 1 with convertor 2.
44.87 + * Implement this using your API, preferably this method just delegates
44.88 + * into some API method which does the actual work, without requiring
44.89 + * API clients to code anything complex.
44.90 + */
44.91 + public static Convertor merge(Convertor one, Convertor two) {
44.92 + return new Convertor(new Convertor[]{one, two});
44.93 + }
44.94 +
44.95 + /** Join the convertors from previous task, Task1Test and show that it
44.96 + * can be used to do reasonable conversions.
44.97 + */
44.98 + public void testConvertorComposition() throws Exception {
44.99 + Convertor c = merge(
44.100 + Task1Test.createCZKtoUSD(),
44.101 + Task1Test.createSKKtoCZK()
44.102 + );
44.103 +
44.104 + // convert $5 to CZK using c:
44.105 + assertEquals("Result is 85 CZK", 85, c.convert(new BigDecimal(5), USD, CZK).getValue().intValue());
44.106 +
44.107 + // convert $8 to CZK using c:
44.108 + assertEquals("Result is 136 CZK", 136, c.convert(new BigDecimal(8), USD, CZK).getValue().intValue());
44.109 +
44.110 + // convert 1003CZK to USD using c:
44.111 + assertEquals("Result is 59 USD", 59, c.convert(new BigDecimal(1003), CZK, USD).getValue().intValue());
44.112 +
44.113 + // convert 16CZK using c:
44.114 + assertEquals("Result is 20 SKK", 20, c.convert(new BigDecimal(16), CZK, SKK).getValue().intValue());
44.115 +
44.116 + // convert 500SKK to CZK using c:
44.117 + assertEquals("Result is 400 CZK", 400, c.convert(new BigDecimal(500), SKK, CZK).getValue().intValue());
44.118 +
44.119 + }
44.120 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/task3/solution07/build.xml Tue Oct 07 11:05:34 2008 +0200
45.3 @@ -0,0 +1,69 @@
45.4 +<?xml version="1.0" encoding="UTF-8"?>
45.5 +<!-- You may freely edit this file. See commented blocks below for -->
45.6 +<!-- some examples of how to customize the build. -->
45.7 +<!-- (If you delete it and reopen the project it will be recreated.) -->
45.8 +<project name="currency" default="default" basedir=".">
45.9 + <description>Builds, tests, and runs the project.</description>
45.10 + <import file="nbproject/build-impl.xml"/>
45.11 + <!--
45.12 +
45.13 + There exist several targets which are by default empty and which can be
45.14 + used for execution of your tasks. These targets are usually executed
45.15 + before and after some main targets. They are:
45.16 +
45.17 + -pre-init: called before initialization of project properties
45.18 + -post-init: called after initialization of project properties
45.19 + -pre-compile: called before javac compilation
45.20 + -post-compile: called after javac compilation
45.21 + -pre-compile-single: called before javac compilation of single file
45.22 + -post-compile-single: called after javac compilation of single file
45.23 + -pre-compile-test: called before javac compilation of JUnit tests
45.24 + -post-compile-test: called after javac compilation of JUnit tests
45.25 + -pre-compile-test-single: called before javac compilation of single JUnit test
45.26 + -post-compile-test-single: called after javac compilation of single JUunit test
45.27 + -pre-jar: called before JAR building
45.28 + -post-jar: called after JAR building
45.29 + -post-clean: called after cleaning build products
45.30 +
45.31 + (Targets beginning with '-' are not intended to be called on their own.)
45.32 +
45.33 + Example of inserting an obfuscator after compilation could look like this:
45.34 +
45.35 + <target name="-post-compile">
45.36 + <obfuscate>
45.37 + <fileset dir="${build.classes.dir}"/>
45.38 + </obfuscate>
45.39 + </target>
45.40 +
45.41 + For list of available properties check the imported
45.42 + nbproject/build-impl.xml file.
45.43 +
45.44 +
45.45 + Another way to customize the build is by overriding existing main targets.
45.46 + The targets of interest are:
45.47 +
45.48 + -init-macrodef-javac: defines macro for javac compilation
45.49 + -init-macrodef-junit: defines macro for junit execution
45.50 + -init-macrodef-debug: defines macro for class debugging
45.51 + -init-macrodef-java: defines macro for class execution
45.52 + -do-jar-with-manifest: JAR building (if you are using a manifest)
45.53 + -do-jar-without-manifest: JAR building (if you are not using a manifest)
45.54 + run: execution of project
45.55 + -javadoc-build: Javadoc generation
45.56 + test-report: JUnit report generation
45.57 +
45.58 + An example of overriding the target for project execution could look like this:
45.59 +
45.60 + <target name="run" depends="currency-impl.jar">
45.61 + <exec dir="bin" executable="launcher.exe">
45.62 + <arg file="${dist.jar}"/>
45.63 + </exec>
45.64 + </target>
45.65 +
45.66 + Notice that the overridden target depends on the jar target and not only on
45.67 + the compile target as the regular run target does. Again, for a list of available
45.68 + properties which you can use, check the target you are overriding in the
45.69 + nbproject/build-impl.xml file.
45.70 +
45.71 + -->
45.72 +</project>
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/task3/solution07/nbproject/build-impl.xml Tue Oct 07 11:05:34 2008 +0200
46.3 @@ -0,0 +1,642 @@
46.4 +<?xml version="1.0" encoding="UTF-8"?>
46.5 +<!--
46.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
46.7 +*** EDIT ../build.xml INSTEAD ***
46.8 +
46.9 +For the purpose of easier reading the script
46.10 +is divided into following sections:
46.11 +
46.12 + - initialization
46.13 + - compilation
46.14 + - jar
46.15 + - execution
46.16 + - debugging
46.17 + - javadoc
46.18 + - junit compilation
46.19 + - junit execution
46.20 + - junit debugging
46.21 + - applet
46.22 + - cleanup
46.23 +
46.24 + -->
46.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_07-impl">
46.26 + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
46.27 + <!--
46.28 + ======================
46.29 + INITIALIZATION SECTION
46.30 + ======================
46.31 + -->
46.32 + <target name="-pre-init">
46.33 + <!-- Empty placeholder for easier customization. -->
46.34 + <!-- You can override this target in the ../build.xml file. -->
46.35 + </target>
46.36 + <target depends="-pre-init" name="-init-private">
46.37 + <property file="nbproject/private/config.properties"/>
46.38 + <property file="nbproject/private/configs/${config}.properties"/>
46.39 + <property file="nbproject/private/private.properties"/>
46.40 + </target>
46.41 + <target depends="-pre-init,-init-private" name="-init-user">
46.42 + <property file="${user.properties.file}"/>
46.43 + <!-- The two properties below are usually overridden -->
46.44 + <!-- by the active platform. Just a fallback. -->
46.45 + <property name="default.javac.source" value="1.4"/>
46.46 + <property name="default.javac.target" value="1.4"/>
46.47 + </target>
46.48 + <target depends="-pre-init,-init-private,-init-user" name="-init-project">
46.49 + <property file="nbproject/configs/${config}.properties"/>
46.50 + <property file="nbproject/project.properties"/>
46.51 + </target>
46.52 + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
46.53 + <available file="${manifest.file}" property="manifest.available"/>
46.54 + <condition property="manifest.available+main.class">
46.55 + <and>
46.56 + <isset property="manifest.available"/>
46.57 + <isset property="main.class"/>
46.58 + <not>
46.59 + <equals arg1="${main.class}" arg2="" trim="true"/>
46.60 + </not>
46.61 + </and>
46.62 + </condition>
46.63 + <condition property="manifest.available+main.class+mkdist.available">
46.64 + <and>
46.65 + <istrue value="${manifest.available+main.class}"/>
46.66 + <isset property="libs.CopyLibs.classpath"/>
46.67 + </and>
46.68 + </condition>
46.69 + <condition property="have.tests">
46.70 + <or>
46.71 + <available file="${test.src.dir}"/>
46.72 + </or>
46.73 + </condition>
46.74 + <condition property="have.sources">
46.75 + <or>
46.76 + <available file="${src.dir}"/>
46.77 + </or>
46.78 + </condition>
46.79 + <condition property="netbeans.home+have.tests">
46.80 + <and>
46.81 + <isset property="netbeans.home"/>
46.82 + <isset property="have.tests"/>
46.83 + </and>
46.84 + </condition>
46.85 + <condition property="no.javadoc.preview">
46.86 + <and>
46.87 + <isset property="javadoc.preview"/>
46.88 + <isfalse value="${javadoc.preview}"/>
46.89 + </and>
46.90 + </condition>
46.91 + <property name="run.jvmargs" value=""/>
46.92 + <property name="javac.compilerargs" value=""/>
46.93 + <property name="work.dir" value="${basedir}"/>
46.94 + <condition property="no.deps">
46.95 + <and>
46.96 + <istrue value="${no.dependencies}"/>
46.97 + </and>
46.98 + </condition>
46.99 + <property name="javac.debug" value="true"/>
46.100 + <property name="javadoc.preview" value="true"/>
46.101 + <property name="application.args" value=""/>
46.102 + <property name="source.encoding" value="${file.encoding}"/>
46.103 + <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
46.104 + <and>
46.105 + <isset property="javadoc.encoding"/>
46.106 + <not>
46.107 + <equals arg1="${javadoc.encoding}" arg2=""/>
46.108 + </not>
46.109 + </and>
46.110 + </condition>
46.111 + <property name="javadoc.encoding.used" value="${source.encoding}"/>
46.112 + <property name="includes" value="**"/>
46.113 + <property name="excludes" value=""/>
46.114 + <property name="do.depend" value="false"/>
46.115 + <condition property="do.depend.true">
46.116 + <istrue value="${do.depend}"/>
46.117 + </condition>
46.118 + <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
46.119 + <and>
46.120 + <isset property="jaxws.endorsed.dir"/>
46.121 + <available file="nbproject/jaxws-build.xml"/>
46.122 + </and>
46.123 + </condition>
46.124 + </target>
46.125 + <target name="-post-init">
46.126 + <!-- Empty placeholder for easier customization. -->
46.127 + <!-- You can override this target in the ../build.xml file. -->
46.128 + </target>
46.129 + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
46.130 + <fail unless="src.dir">Must set src.dir</fail>
46.131 + <fail unless="test.src.dir">Must set test.src.dir</fail>
46.132 + <fail unless="build.dir">Must set build.dir</fail>
46.133 + <fail unless="dist.dir">Must set dist.dir</fail>
46.134 + <fail unless="build.classes.dir">Must set build.classes.dir</fail>
46.135 + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
46.136 + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
46.137 + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
46.138 + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
46.139 + <fail unless="dist.jar">Must set dist.jar</fail>
46.140 + </target>
46.141 + <target name="-init-macrodef-property">
46.142 + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
46.143 + <attribute name="name"/>
46.144 + <attribute name="value"/>
46.145 + <sequential>
46.146 + <property name="@{name}" value="${@{value}}"/>
46.147 + </sequential>
46.148 + </macrodef>
46.149 + </target>
46.150 + <target name="-init-macrodef-javac">
46.151 + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
46.152 + <attribute default="${src.dir}" name="srcdir"/>
46.153 + <attribute default="${build.classes.dir}" name="destdir"/>
46.154 + <attribute default="${javac.classpath}" name="classpath"/>
46.155 + <attribute default="${includes}" name="includes"/>
46.156 + <attribute default="${excludes}" name="excludes"/>
46.157 + <attribute default="${javac.debug}" name="debug"/>
46.158 + <attribute default="" name="sourcepath"/>
46.159 + <element name="customize" optional="true"/>
46.160 + <sequential>
46.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}">
46.162 + <classpath>
46.163 + <path path="@{classpath}"/>
46.164 + </classpath>
46.165 + <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
46.166 + <customize/>
46.167 + </javac>
46.168 + </sequential>
46.169 + </macrodef>
46.170 + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
46.171 + <attribute default="${src.dir}" name="srcdir"/>
46.172 + <attribute default="${build.classes.dir}" name="destdir"/>
46.173 + <attribute default="${javac.classpath}" name="classpath"/>
46.174 + <sequential>
46.175 + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
46.176 + <classpath>
46.177 + <path path="@{classpath}"/>
46.178 + </classpath>
46.179 + </depend>
46.180 + </sequential>
46.181 + </macrodef>
46.182 + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
46.183 + <attribute default="${build.classes.dir}" name="destdir"/>
46.184 + <sequential>
46.185 + <fail unless="javac.includes">Must set javac.includes</fail>
46.186 + <pathconvert pathsep="," property="javac.includes.binary">
46.187 + <path>
46.188 + <filelist dir="@{destdir}" files="${javac.includes}"/>
46.189 + </path>
46.190 + <globmapper from="*.java" to="*.class"/>
46.191 + </pathconvert>
46.192 + <delete>
46.193 + <files includes="${javac.includes.binary}"/>
46.194 + </delete>
46.195 + </sequential>
46.196 + </macrodef>
46.197 + </target>
46.198 + <target name="-init-macrodef-junit">
46.199 + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
46.200 + <attribute default="${includes}" name="includes"/>
46.201 + <attribute default="${excludes}" name="excludes"/>
46.202 + <attribute default="**" name="testincludes"/>
46.203 + <sequential>
46.204 + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
46.205 + <batchtest todir="${build.test.results.dir}">
46.206 + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
46.207 + <filename name="@{testincludes}"/>
46.208 + </fileset>
46.209 + </batchtest>
46.210 + <classpath>
46.211 + <path path="${run.test.classpath}"/>
46.212 + </classpath>
46.213 + <syspropertyset>
46.214 + <propertyref prefix="test-sys-prop."/>
46.215 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
46.216 + </syspropertyset>
46.217 + <formatter type="brief" usefile="false"/>
46.218 + <formatter type="xml"/>
46.219 + <jvmarg line="${run.jvmargs}"/>
46.220 + </junit>
46.221 + </sequential>
46.222 + </macrodef>
46.223 + </target>
46.224 + <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
46.225 + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
46.226 + <attribute default="${main.class}" name="name"/>
46.227 + <attribute default="${debug.classpath}" name="classpath"/>
46.228 + <attribute default="" name="stopclassname"/>
46.229 + <sequential>
46.230 + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
46.231 + <classpath>
46.232 + <path path="@{classpath}"/>
46.233 + </classpath>
46.234 + </nbjpdastart>
46.235 + </sequential>
46.236 + </macrodef>
46.237 + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
46.238 + <attribute default="${build.classes.dir}" name="dir"/>
46.239 + <sequential>
46.240 + <nbjpdareload>
46.241 + <fileset dir="@{dir}" includes="${fix.classes}">
46.242 + <include name="${fix.includes}*.class"/>
46.243 + </fileset>
46.244 + </nbjpdareload>
46.245 + </sequential>
46.246 + </macrodef>
46.247 + </target>
46.248 + <target name="-init-debug-args">
46.249 + <property name="version-output" value="java version "${ant.java.version}"/>
46.250 + <condition property="have-jdk-older-than-1.4">
46.251 + <or>
46.252 + <contains string="${version-output}" substring="java version "1.0"/>
46.253 + <contains string="${version-output}" substring="java version "1.1"/>
46.254 + <contains string="${version-output}" substring="java version "1.2"/>
46.255 + <contains string="${version-output}" substring="java version "1.3"/>
46.256 + </or>
46.257 + </condition>
46.258 + <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
46.259 + <istrue value="${have-jdk-older-than-1.4}"/>
46.260 + </condition>
46.261 + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
46.262 + <os family="windows"/>
46.263 + </condition>
46.264 + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
46.265 + <isset property="debug.transport"/>
46.266 + </condition>
46.267 + </target>
46.268 + <target depends="-init-debug-args" name="-init-macrodef-debug">
46.269 + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
46.270 + <attribute default="${main.class}" name="classname"/>
46.271 + <attribute default="${debug.classpath}" name="classpath"/>
46.272 + <element name="customize" optional="true"/>
46.273 + <sequential>
46.274 + <java classname="@{classname}" dir="${work.dir}" fork="true">
46.275 + <jvmarg line="${debug-args-line}"/>
46.276 + <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
46.277 + <jvmarg line="${run.jvmargs}"/>
46.278 + <classpath>
46.279 + <path path="@{classpath}"/>
46.280 + </classpath>
46.281 + <syspropertyset>
46.282 + <propertyref prefix="run-sys-prop."/>
46.283 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
46.284 + </syspropertyset>
46.285 + <customize/>
46.286 + </java>
46.287 + </sequential>
46.288 + </macrodef>
46.289 + </target>
46.290 + <target name="-init-macrodef-java">
46.291 + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
46.292 + <attribute default="${main.class}" name="classname"/>
46.293 + <element name="customize" optional="true"/>
46.294 + <sequential>
46.295 + <java classname="@{classname}" dir="${work.dir}" fork="true">
46.296 + <jvmarg line="${run.jvmargs}"/>
46.297 + <classpath>
46.298 + <path path="${run.classpath}"/>
46.299 + </classpath>
46.300 + <syspropertyset>
46.301 + <propertyref prefix="run-sys-prop."/>
46.302 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
46.303 + </syspropertyset>
46.304 + <customize/>
46.305 + </java>
46.306 + </sequential>
46.307 + </macrodef>
46.308 + </target>
46.309 + <target name="-init-presetdef-jar">
46.310 + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
46.311 + <jar compress="${jar.compress}" jarfile="${dist.jar}">
46.312 + <j2seproject1:fileset dir="${build.classes.dir}"/>
46.313 + </jar>
46.314 + </presetdef>
46.315 + </target>
46.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"/>
46.317 + <!--
46.318 + ===================
46.319 + COMPILATION SECTION
46.320 + ===================
46.321 + -->
46.322 + <target depends="init" name="deps-jar" unless="no.deps"/>
46.323 + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
46.324 + <target depends="init" name="-check-automatic-build">
46.325 + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
46.326 + </target>
46.327 + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
46.328 + <antcall target="clean"/>
46.329 + </target>
46.330 + <target depends="init,deps-jar" name="-pre-pre-compile">
46.331 + <mkdir dir="${build.classes.dir}"/>
46.332 + </target>
46.333 + <target name="-pre-compile">
46.334 + <!-- Empty placeholder for easier customization. -->
46.335 + <!-- You can override this target in the ../build.xml file. -->
46.336 + </target>
46.337 + <target if="do.depend.true" name="-compile-depend">
46.338 + <j2seproject3:depend/>
46.339 + </target>
46.340 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
46.341 + <j2seproject3:javac/>
46.342 + <copy todir="${build.classes.dir}">
46.343 + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
46.344 + </copy>
46.345 + </target>
46.346 + <target name="-post-compile">
46.347 + <!-- Empty placeholder for easier customization. -->
46.348 + <!-- You can override this target in the ../build.xml file. -->
46.349 + </target>
46.350 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
46.351 + <target name="-pre-compile-single">
46.352 + <!-- Empty placeholder for easier customization. -->
46.353 + <!-- You can override this target in the ../build.xml file. -->
46.354 + </target>
46.355 + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
46.356 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
46.357 + <j2seproject3:force-recompile/>
46.358 + <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
46.359 + </target>
46.360 + <target name="-post-compile-single">
46.361 + <!-- Empty placeholder for easier customization. -->
46.362 + <!-- You can override this target in the ../build.xml file. -->
46.363 + </target>
46.364 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
46.365 + <!--
46.366 + ====================
46.367 + JAR BUILDING SECTION
46.368 + ====================
46.369 + -->
46.370 + <target depends="init" name="-pre-pre-jar">
46.371 + <dirname file="${dist.jar}" property="dist.jar.dir"/>
46.372 + <mkdir dir="${dist.jar.dir}"/>
46.373 + </target>
46.374 + <target name="-pre-jar">
46.375 + <!-- Empty placeholder for easier customization. -->
46.376 + <!-- You can override this target in the ../build.xml file. -->
46.377 + </target>
46.378 + <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
46.379 + <j2seproject1:jar/>
46.380 + </target>
46.381 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
46.382 + <j2seproject1:jar manifest="${manifest.file}"/>
46.383 + </target>
46.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">
46.385 + <j2seproject1:jar manifest="${manifest.file}">
46.386 + <j2seproject1:manifest>
46.387 + <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
46.388 + </j2seproject1:manifest>
46.389 + </j2seproject1:jar>
46.390 + <echo>To run this application from the command line without Ant, try:</echo>
46.391 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
46.392 + <property location="${dist.jar}" name="dist.jar.resolved"/>
46.393 + <pathconvert property="run.classpath.with.dist.jar">
46.394 + <path path="${run.classpath}"/>
46.395 + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
46.396 + </pathconvert>
46.397 + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
46.398 + </target>
46.399 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
46.400 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
46.401 + <pathconvert property="run.classpath.without.build.classes.dir">
46.402 + <path path="${run.classpath}"/>
46.403 + <map from="${build.classes.dir.resolved}" to=""/>
46.404 + </pathconvert>
46.405 + <pathconvert pathsep=" " property="jar.classpath">
46.406 + <path path="${run.classpath.without.build.classes.dir}"/>
46.407 + <chainedmapper>
46.408 + <flattenmapper/>
46.409 + <globmapper from="*" to="lib/*"/>
46.410 + </chainedmapper>
46.411 + </pathconvert>
46.412 + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
46.413 + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
46.414 + <fileset dir="${build.classes.dir}"/>
46.415 + <manifest>
46.416 + <attribute name="Main-Class" value="${main.class}"/>
46.417 + <attribute name="Class-Path" value="${jar.classpath}"/>
46.418 + </manifest>
46.419 + </copylibs>
46.420 + <echo>To run this application from the command line without Ant, try:</echo>
46.421 + <property location="${dist.jar}" name="dist.jar.resolved"/>
46.422 + <echo>java -jar "${dist.jar.resolved}"</echo>
46.423 + </target>
46.424 + <target name="-post-jar">
46.425 + <!-- Empty placeholder for easier customization. -->
46.426 + <!-- You can override this target in the ../build.xml file. -->
46.427 + </target>
46.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"/>
46.429 + <!--
46.430 + =================
46.431 + EXECUTION SECTION
46.432 + =================
46.433 + -->
46.434 + <target depends="init,compile" description="Run a main class." name="run">
46.435 + <j2seproject1:java>
46.436 + <customize>
46.437 + <arg line="${application.args}"/>
46.438 + </customize>
46.439 + </j2seproject1:java>
46.440 + </target>
46.441 + <target name="-do-not-recompile">
46.442 + <property name="javac.includes.binary" value=""/>
46.443 + </target>
46.444 + <target depends="init,-do-not-recompile,compile-single" name="run-single">
46.445 + <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
46.446 + <j2seproject1:java classname="${run.class}"/>
46.447 + </target>
46.448 + <!--
46.449 + =================
46.450 + DEBUGGING SECTION
46.451 + =================
46.452 + -->
46.453 + <target depends="init" if="netbeans.home" name="-debug-start-debugger">
46.454 + <j2seproject1:nbjpdastart name="${debug.class}"/>
46.455 + </target>
46.456 + <target depends="init,compile" name="-debug-start-debuggee">
46.457 + <j2seproject3:debug>
46.458 + <customize>
46.459 + <arg line="${application.args}"/>
46.460 + </customize>
46.461 + </j2seproject3:debug>
46.462 + </target>
46.463 + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
46.464 + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
46.465 + <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
46.466 + </target>
46.467 + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
46.468 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
46.469 + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
46.470 + <j2seproject3:debug classname="${debug.class}"/>
46.471 + </target>
46.472 + <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
46.473 + <target depends="init" name="-pre-debug-fix">
46.474 + <fail unless="fix.includes">Must set fix.includes</fail>
46.475 + <property name="javac.includes" value="${fix.includes}.java"/>
46.476 + </target>
46.477 + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
46.478 + <j2seproject1:nbjpdareload/>
46.479 + </target>
46.480 + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
46.481 + <!--
46.482 + ===============
46.483 + JAVADOC SECTION
46.484 + ===============
46.485 + -->
46.486 + <target depends="init" name="-javadoc-build">
46.487 + <mkdir dir="${dist.javadoc.dir}"/>
46.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}">
46.489 + <classpath>
46.490 + <path path="${javac.classpath}"/>
46.491 + </classpath>
46.492 + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
46.493 + <filename name="**/*.java"/>
46.494 + </fileset>
46.495 + </javadoc>
46.496 + </target>
46.497 + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
46.498 + <nbbrowse file="${dist.javadoc.dir}/index.html"/>
46.499 + </target>
46.500 + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
46.501 + <!--
46.502 + =========================
46.503 + JUNIT COMPILATION SECTION
46.504 + =========================
46.505 + -->
46.506 + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
46.507 + <mkdir dir="${build.test.classes.dir}"/>
46.508 + </target>
46.509 + <target name="-pre-compile-test">
46.510 + <!-- Empty placeholder for easier customization. -->
46.511 + <!-- You can override this target in the ../build.xml file. -->
46.512 + </target>
46.513 + <target if="do.depend.true" name="-compile-test-depend">
46.514 + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
46.515 + </target>
46.516 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
46.517 + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
46.518 + <copy todir="${build.test.classes.dir}">
46.519 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
46.520 + </copy>
46.521 + </target>
46.522 + <target name="-post-compile-test">
46.523 + <!-- Empty placeholder for easier customization. -->
46.524 + <!-- You can override this target in the ../build.xml file. -->
46.525 + </target>
46.526 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
46.527 + <target name="-pre-compile-test-single">
46.528 + <!-- Empty placeholder for easier customization. -->
46.529 + <!-- You can override this target in the ../build.xml file. -->
46.530 + </target>
46.531 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
46.532 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
46.533 + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
46.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}"/>
46.535 + <copy todir="${build.test.classes.dir}">
46.536 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
46.537 + </copy>
46.538 + </target>
46.539 + <target name="-post-compile-test-single">
46.540 + <!-- Empty placeholder for easier customization. -->
46.541 + <!-- You can override this target in the ../build.xml file. -->
46.542 + </target>
46.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"/>
46.544 + <!--
46.545 + =======================
46.546 + JUNIT EXECUTION SECTION
46.547 + =======================
46.548 + -->
46.549 + <target depends="init" if="have.tests" name="-pre-test-run">
46.550 + <mkdir dir="${build.test.results.dir}"/>
46.551 + </target>
46.552 + <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
46.553 + <j2seproject3:junit testincludes="**/*Test.java"/>
46.554 + </target>
46.555 + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
46.556 + <fail if="tests.failed">Some tests failed; see details above.</fail>
46.557 + </target>
46.558 + <target depends="init" if="have.tests" name="test-report"/>
46.559 + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
46.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"/>
46.561 + <target depends="init" if="have.tests" name="-pre-test-run-single">
46.562 + <mkdir dir="${build.test.results.dir}"/>
46.563 + </target>
46.564 + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
46.565 + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
46.566 + <j2seproject3:junit excludes="" includes="${test.includes}"/>
46.567 + </target>
46.568 + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
46.569 + <fail if="tests.failed">Some tests failed; see details above.</fail>
46.570 + </target>
46.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"/>
46.572 + <!--
46.573 + =======================
46.574 + JUNIT DEBUGGING SECTION
46.575 + =======================
46.576 + -->
46.577 + <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
46.578 + <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
46.579 + <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
46.580 + <delete file="${test.report.file}"/>
46.581 + <mkdir dir="${build.test.results.dir}"/>
46.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}">
46.583 + <customize>
46.584 + <syspropertyset>
46.585 + <propertyref prefix="test-sys-prop."/>
46.586 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
46.587 + </syspropertyset>
46.588 + <arg value="${test.class}"/>
46.589 + <arg value="showoutput=true"/>
46.590 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
46.591 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
46.592 + </customize>
46.593 + </j2seproject3:debug>
46.594 + </target>
46.595 + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
46.596 + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
46.597 + </target>
46.598 + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
46.599 + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
46.600 + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
46.601 + </target>
46.602 + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
46.603 + <!--
46.604 + =========================
46.605 + APPLET EXECUTION SECTION
46.606 + =========================
46.607 + -->
46.608 + <target depends="init,compile-single" name="run-applet">
46.609 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
46.610 + <j2seproject1:java classname="sun.applet.AppletViewer">
46.611 + <customize>
46.612 + <arg value="${applet.url}"/>
46.613 + </customize>
46.614 + </j2seproject1:java>
46.615 + </target>
46.616 + <!--
46.617 + =========================
46.618 + APPLET DEBUGGING SECTION
46.619 + =========================
46.620 + -->
46.621 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
46.622 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
46.623 + <j2seproject3:debug classname="sun.applet.AppletViewer">
46.624 + <customize>
46.625 + <arg value="${applet.url}"/>
46.626 + </customize>
46.627 + </j2seproject3:debug>
46.628 + </target>
46.629 + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
46.630 + <!--
46.631 + ===============
46.632 + CLEANUP SECTION
46.633 + ===============
46.634 + -->
46.635 + <target depends="init" name="deps-clean" unless="no.deps"/>
46.636 + <target depends="init" name="-do-clean">
46.637 + <delete dir="${build.dir}"/>
46.638 + <delete dir="${dist.dir}"/>
46.639 + </target>
46.640 + <target name="-post-clean">
46.641 + <!-- Empty placeholder for easier customization. -->
46.642 + <!-- You can override this target in the ../build.xml file. -->
46.643 + </target>
46.644 + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
46.645 +</project>
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/task3/solution07/nbproject/genfiles.properties Tue Oct 07 11:05:34 2008 +0200
47.3 @@ -0,0 +1,8 @@
47.4 +build.xml.data.CRC32=2ab820eb
47.5 +build.xml.script.CRC32=58a52595
47.6 +build.xml.stylesheet.CRC32=be360661
47.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
47.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
47.9 +nbproject/build-impl.xml.data.CRC32=979fc7ba
47.10 +nbproject/build-impl.xml.script.CRC32=92452d37
47.11 +nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/task3/solution07/nbproject/project.properties Tue Oct 07 11:05:34 2008 +0200
48.3 @@ -0,0 +1,68 @@
48.4 +application.title=currency
48.5 +application.vendor=apidesign.org
48.6 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
48.7 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
48.8 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
48.9 +build.classes.dir=${build.dir}/classes
48.10 +build.classes.excludes=**/*.java,**/*.form
48.11 +# This directory is removed when the project is cleaned:
48.12 +build.dir=build
48.13 +build.generated.dir=${build.dir}/generated
48.14 +# Only compile against the classpath explicitly listed here:
48.15 +build.sysclasspath=ignore
48.16 +build.test.classes.dir=${build.dir}/test/classes
48.17 +build.test.results.dir=${build.dir}/test/results
48.18 +debug.classpath=\
48.19 + ${run.classpath}
48.20 +debug.test.classpath=\
48.21 + ${run.test.classpath}
48.22 +# This directory is removed when the project is cleaned:
48.23 +dist.dir=dist
48.24 +dist.jar=${dist.dir}/currency.jar
48.25 +dist.javadoc.dir=${dist.dir}/javadoc
48.26 +excludes=
48.27 +file.reference.junit-4.4.jar=../../libs/junit-4.4.jar
48.28 +file.reference.src-apifest08=..
48.29 +includes=**
48.30 +jar.compress=false
48.31 +javac.classpath=
48.32 +# Space-separated list of extra javac options
48.33 +javac.compilerargs=
48.34 +javac.deprecation=false
48.35 +javac.source=1.5
48.36 +javac.target=1.5
48.37 +javac.test.classpath=\
48.38 + ${javac.classpath}:\
48.39 + ${build.classes.dir}:\
48.40 + ${file.reference.junit-4.4.jar}
48.41 +javadoc.additionalparam=
48.42 +javadoc.author=false
48.43 +javadoc.encoding=
48.44 +javadoc.noindex=false
48.45 +javadoc.nonavbar=false
48.46 +javadoc.notree=false
48.47 +javadoc.private=false
48.48 +javadoc.splitindex=true
48.49 +javadoc.use=true
48.50 +javadoc.version=false
48.51 +javadoc.windowtitle=
48.52 +jnlp.codebase.type=local
48.53 +jnlp.codebase.url=file:/home/jarda/src/apifest08/currency/dist
48.54 +jnlp.descriptor=application
48.55 +jnlp.enabled=false
48.56 +jnlp.offline-allowed=false
48.57 +jnlp.signed=false
48.58 +meta.inf.dir=${src.dir}/META-INF
48.59 +platform.active=default_platform
48.60 +run.classpath=\
48.61 + ${javac.classpath}:\
48.62 + ${build.classes.dir}
48.63 +# Space-separated list of JVM arguments used when running the project
48.64 +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
48.65 +# or test-sys-prop.name=value to set system properties for unit tests):
48.66 +run.jvmargs=
48.67 +run.test.classpath=\
48.68 + ${javac.test.classpath}:\
48.69 + ${build.test.classes.dir}
48.70 +src.dir=src
48.71 +test.src.dir=test
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/task3/solution07/nbproject/project.xml Tue Oct 07 11:05:34 2008 +0200
49.3 @@ -0,0 +1,16 @@
49.4 +<?xml version="1.0" encoding="UTF-8"?>
49.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
49.6 + <type>org.netbeans.modules.java.j2seproject</type>
49.7 + <configuration>
49.8 + <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
49.9 + <name>Currency Convertor Solution 07</name>
49.10 + <minimum-ant-version>1.6.5</minimum-ant-version>
49.11 + <source-roots>
49.12 + <root id="src.dir"/>
49.13 + </source-roots>
49.14 + <test-roots>
49.15 + <root id="test.src.dir"/>
49.16 + </test-roots>
49.17 + </data>
49.18 + </configuration>
49.19 +</project>
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/task3/solution07/src/org/apidesign/apifest08/currency/ConversionRate.java Tue Oct 07 11:05:34 2008 +0200
50.3 @@ -0,0 +1,91 @@
50.4 +package org.apidesign.apifest08.currency;
50.5 +
50.6 +import java.math.BigDecimal;
50.7 +import java.math.RoundingMode;
50.8 +
50.9 +/**
50.10 + * A rate of conversion from one currency to another.
50.11 + * @author jdvorak
50.12 + */
50.13 +public class ConversionRate {
50.14 +
50.15 + private final MonetaryAmount srcUnitAmount;
50.16 + private final MonetaryAmount tgtUnitAmount;
50.17 + private final int tgtScale;
50.18 + private final RoundingMode roundingMode;
50.19 +
50.20 + /**
50.21 + * A new conversion rate that gives tgtUnitAmount per every srcUnitAmount.
50.22 + * @param srcUnitAmount the amount of source currency
50.23 + * @param tgtUnitAmount the corresponding amount of target currency
50.24 + * @param tgtScale the scale of the target amounts
50.25 + * @param roundingMode the rounding mode to use when producing the target amounts
50.26 + */
50.27 + public ConversionRate( final MonetaryAmount srcUnitAmount, final MonetaryAmount tgtUnitAmount, final int targetScale, final RoundingMode roundingMode ) {
50.28 + this.srcUnitAmount = srcUnitAmount;
50.29 + this.tgtUnitAmount = tgtUnitAmount;
50.30 + this.tgtScale = targetScale;
50.31 + this.roundingMode = roundingMode;
50.32 + }
50.33 +
50.34 + /**
50.35 + * A new conversion rate that gives tgtUnitAmount per every srcUnitAmount, default number of fraction digits and the given rounding mode.
50.36 + * @param srcUnitAmount the amount of source currency
50.37 + * @param tgtUnitAmount the corresponding amount of target currency
50.38 + * @param roundingMode the rounding mode to use
50.39 + */
50.40 + public ConversionRate( final MonetaryAmount srcUnitAmount, final MonetaryAmount tgtUnitAmount, final RoundingMode roundingMode ) {
50.41 + this( srcUnitAmount, tgtUnitAmount, tgtUnitAmount.getCurrency().getDefaultFractionDigits(), roundingMode );
50.42 + }
50.43 +
50.44 + /**
50.45 + * A new conversion rate that gives tgtUnitAmount per every srcUnitAmount, default number of fraction digits and {@link RoundingMode#HALF_EVEN}.
50.46 + * @param srcUnitAmount the amount of source currency
50.47 + * @param tgtUnitAmount the corresponding amount of target currency
50.48 + */
50.49 + public ConversionRate( final MonetaryAmount srcUnitAmount, final MonetaryAmount tgtUnitAmount ) {
50.50 + this( srcUnitAmount, tgtUnitAmount, RoundingMode.HALF_EVEN );
50.51 + }
50.52 +
50.53 + public RoundingMode getRoundingMode() {
50.54 + return roundingMode;
50.55 + }
50.56 +
50.57 + public MonetaryAmount getSrcUnitAmount() {
50.58 + return srcUnitAmount;
50.59 + }
50.60 +
50.61 + public int getTgtScale() {
50.62 + return tgtScale;
50.63 + }
50.64 +
50.65 + public MonetaryAmount getTgtUnitAmount() {
50.66 + return tgtUnitAmount;
50.67 + }
50.68 +
50.69 + /**
50.70 + * Multiplies the given amount with the given rate.
50.71 + * @param srcAmount
50.72 + * @return
50.73 + */
50.74 + public BigDecimal convert( final BigDecimal srcAmount ) {
50.75 + return srcAmount
50.76 + .multiply( tgtUnitAmount.getAmount() )
50.77 + .divide( srcUnitAmount.getAmount(), tgtScale, roundingMode );
50.78 + }
50.79 +
50.80 + /**
50.81 + * Creates a monetary amount that corresponds to the given source amount multiplied by the rate.
50.82 + * @param srcAmount the source amount
50.83 + * @return the monetary amount in the target currency
50.84 + * @throws IllegalArgumentException if the currency of srcAmount is not equal to the source currency of this rate
50.85 + */
50.86 + public MonetaryAmount convert( final MonetaryAmount srcAmount ) {
50.87 + if ( srcUnitAmount.getCurrency().equals( srcAmount.getCurrency() ) ) {
50.88 + return new MonetaryAmount( convert( srcAmount.getAmount() ), tgtUnitAmount.getCurrency() );
50.89 + } else {
50.90 + throw new IllegalArgumentException( "This rate converts from " + srcUnitAmount.getCurrency() + ", but a conversion from " + srcAmount.getCurrency() + " is attempted" );
50.91 + }
50.92 + }
50.93 +
50.94 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/task3/solution07/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 11:05:34 2008 +0200
51.3 @@ -0,0 +1,109 @@
51.4 +package org.apidesign.apifest08.currency;
51.5 +
51.6 +import java.util.Currency;
51.7 +
51.8 +/** This is the skeleton class for your API. You need to make it public, so
51.9 + * it is accessible to your client code (currently in Task1Test.java) file.
51.10 + * <p>
51.11 + * Feel free to create additional classes or rename this one, just keep all
51.12 + * the API and its implementation in this package. Do not spread it outside
51.13 + * to other packages.
51.14 + */
51.15 +public interface Convertor {
51.16 +
51.17 + /**
51.18 + * Converts by taking a request and producing a response.
51.19 + * If a convertor finds it cannot perform the requested conversion,
51.20 + * it should return a non-null {@link ConversionResult} that has null {@link ConversionResult#getNetAmount()}.
51.21 + * A convertor must not convert to a different currency than the one specified in the request.
51.22 + * <p>
51.23 + * When the need comes to extend the semantics, one subclasses the ConversionRequest and/or ConversionResult classes.
51.24 + * <p>
51.25 + * This method can be called as many times as you like.
51.26 + * A {@link Convertor} shall be considered immutable wrt calls to {@link #convert(org.apidesign.apifest08.currency.Convertor.ConversionRequest).
51.27 + * This method of a single {@link Convertor} can be called from many threads concurrently.
51.28 + * @param req the conversion request; mustn't be null
51.29 + * @return the result of carrying out the conversion request; never null
51.30 + * @throws IllegalRequestSubtypeException when the particular implementation cannot handle a specific ConversionRequest type
51.31 + */
51.32 + public ConversionResult convert( final ConversionRequest req ) throws IllegalRequestSubtypeException;
51.33 +
51.34 + /**
51.35 + * The request for converting a monetary amout into another currency.
51.36 + * Immutable.
51.37 + */
51.38 + public class ConversionRequest {
51.39 +
51.40 + private final MonetaryAmount srcAmount;
51.41 + private final Currency tgtCurrency;
51.42 +
51.43 + /**
51.44 + * A request to convert srcAmount into tgtCurrency.
51.45 + * @param srcAmount the source amount; must not be null
51.46 + * @param tgtCurrency the currency we want it in afterwards; must not be null
51.47 + */
51.48 + public ConversionRequest( final MonetaryAmount srcAmount, final Currency tgtCurrency ) {
51.49 + this.srcAmount = srcAmount;
51.50 + this.tgtCurrency = tgtCurrency;
51.51 + if ( srcAmount == null ) {
51.52 + throw new NullPointerException( "The source amount" );
51.53 + }
51.54 + if ( tgtCurrency == null ) {
51.55 + throw new NullPointerException( "The target currency" );
51.56 + }
51.57 + if ( srcAmount.getCurrency().equals( tgtCurrency ) ) {
51.58 + throw new IllegalArgumentException( "Cannot request conversion from " + srcAmount.getCurrency() + " to " + tgtCurrency );
51.59 + }
51.60 + }
51.61 +
51.62 + /**
51.63 + * The source amount.
51.64 + */
51.65 + public MonetaryAmount getSrcAmount() {
51.66 + return srcAmount;
51.67 + }
51.68 +
51.69 + /**
51.70 + * The target currency.
51.71 + */
51.72 + public Currency getTgtCurrency() {
51.73 + return tgtCurrency;
51.74 + }
51.75 +
51.76 + }
51.77 +
51.78 + /**
51.79 + * The result of converting a monetary amount into another currency.
51.80 + * For now it records just the net amount one recieves from the conversion.
51.81 + * Immutable.
51.82 + * <p>
51.83 + * <b>Extension note:</b>
51.84 + * Other items can be added further down the road, as the need for them arises.
51.85 + * These items might provide info on other aspects of the conversion,
51.86 + * such as the fee or a reason why the conversion might not be admissible.
51.87 + */
51.88 + public class ConversionResult {
51.89 +
51.90 + private final MonetaryAmount netAmount;
51.91 +
51.92 + /**
51.93 + * A new conversion result.
51.94 + * @param netAmount the amount one recieves from the conversion;
51.95 + * null means the conversion was not admissible
51.96 + */
51.97 + public ConversionResult( final MonetaryAmount netAmount ) {
51.98 + this.netAmount = netAmount;
51.99 + }
51.100 +
51.101 + /**
51.102 + * The amount one recieves from the conversion.
51.103 + * If null, the conversion is not admissible.
51.104 + * @return the amount
51.105 + */
51.106 + public MonetaryAmount getNetAmount() {
51.107 + return netAmount;
51.108 + }
51.109 +
51.110 + }
51.111 +
51.112 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/task3/solution07/src/org/apidesign/apifest08/currency/DelegatingConvertor.java Tue Oct 07 11:05:34 2008 +0200
52.3 @@ -0,0 +1,28 @@
52.4 +/*
52.5 + * To change this template, choose Tools | Templates
52.6 + * and open the template in the editor.
52.7 + */
52.8 +
52.9 +package org.apidesign.apifest08.currency;
52.10 +
52.11 +/**
52.12 + *
52.13 + * @author jdvorak
52.14 + */
52.15 +public class DelegatingConvertor implements Convertor {
52.16 +
52.17 + private final Convertor underlyingConvertor;
52.18 +
52.19 + public DelegatingConvertor( final Convertor underlyingConvertor ) {
52.20 + this.underlyingConvertor = underlyingConvertor;
52.21 + }
52.22 +
52.23 + protected Convertor getUnderlyingConvertor() {
52.24 + return underlyingConvertor;
52.25 + }
52.26 +
52.27 + public ConversionResult convert( final ConversionRequest req ) {
52.28 + return underlyingConvertor.convert( req );
52.29 + }
52.30 +
52.31 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/task3/solution07/src/org/apidesign/apifest08/currency/IllegalRequestSubtypeException.java Tue Oct 07 11:05:34 2008 +0200
53.3 @@ -0,0 +1,30 @@
53.4 +/*
53.5 + * To change this template, choose Tools | Templates
53.6 + * and open the template in the editor.
53.7 + */
53.8 +
53.9 +package org.apidesign.apifest08.currency;
53.10 +
53.11 +/**
53.12 + * Rised when a {@link Convertor} implementation cannot handle a particular subtype of {@link Convertor.ConversionRequest}.
53.13 + * @author jdvorak
53.14 + */
53.15 +public class IllegalRequestSubtypeException extends IllegalArgumentException {
53.16 +
53.17 + public IllegalRequestSubtypeException() {
53.18 + super();
53.19 + }
53.20 +
53.21 + public IllegalRequestSubtypeException( final String msg ) {
53.22 + super( msg );
53.23 + }
53.24 +
53.25 + public IllegalRequestSubtypeException( final Throwable cause ) {
53.26 + super( cause );
53.27 + }
53.28 +
53.29 + public IllegalRequestSubtypeException( final String msg, final Throwable cause ) {
53.30 + super( msg, cause );
53.31 + }
53.32 +
53.33 +}
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/task3/solution07/src/org/apidesign/apifest08/currency/MonetaryAmount.java Tue Oct 07 11:05:34 2008 +0200
54.3 @@ -0,0 +1,89 @@
54.4 +package org.apidesign.apifest08.currency;
54.5 +
54.6 +import java.math.BigDecimal;
54.7 +import java.util.Currency;
54.8 +
54.9 +/**
54.10 + * An amount of a currency.
54.11 + * Immutable.
54.12 + * @author jdvorak
54.13 + */
54.14 +public class MonetaryAmount {
54.15 +
54.16 + private final BigDecimal amount;
54.17 + private final Currency currency;
54.18 +
54.19 + /**
54.20 + * A new amount.
54.21 + * @param amount the quantity of the currency; must not be null
54.22 + * @param currency the currency; must not be null
54.23 + */
54.24 + public MonetaryAmount( final BigDecimal amount, final Currency currency ) {
54.25 + this.amount = amount;
54.26 + this.currency = currency;
54.27 + if ( amount == null ) {
54.28 + throw new NullPointerException( "The amount" );
54.29 + }
54.30 + if ( currency == null ) {
54.31 + throw new NullPointerException( "The currency" );
54.32 + }
54.33 + }
54.34 +
54.35 + /**
54.36 + * A new amount.
54.37 + * @param amount the quantity of the currency; must not be null
54.38 + * @param currency the currency; must not be null
54.39 + */
54.40 + public MonetaryAmount( final double amount, final Currency currency ) {
54.41 + this( new BigDecimal( amount ), currency );
54.42 + }
54.43 +
54.44 + /**
54.45 + * The amount.
54.46 + * @return the amount
54.47 + */
54.48 + public BigDecimal getAmount() {
54.49 + return amount;
54.50 + }
54.51 +
54.52 + /**
54.53 + * The currency.
54.54 + * @return the currency
54.55 + */
54.56 + public Currency getCurrency() {
54.57 + return currency;
54.58 + }
54.59 +
54.60 + /**
54.61 + * The string representation of the monetary amount.
54.62 + * @return the amount, a non-breakable space, the currency
54.63 + */
54.64 + @Override
54.65 + public String toString() {
54.66 + return amount.toPlainString() + "\u00a0" + currency.toString();
54.67 + }
54.68 +
54.69 + /**
54.70 + * Two monetary amounts are equal to each other iff they have equal amounts of equal currencies.
54.71 + * @param other the other object
54.72 + * @return equality
54.73 + */
54.74 + @Override
54.75 + public boolean equals( final Object other ) {
54.76 + if ( other instanceof MonetaryAmount ) {
54.77 + final MonetaryAmount otherMonetaryAmount = (MonetaryAmount) other;
54.78 + return getAmount().equals( otherMonetaryAmount.getAmount() ) && getCurrency().equals( otherMonetaryAmount.getCurrency() );
54.79 + }
54.80 + return false;
54.81 + }
54.82 +
54.83 + /**
54.84 + * The hash code combines the hash codes of the amount and of the currency.
54.85 + * @return hash code
54.86 + */
54.87 + @Override
54.88 + public int hashCode() {
54.89 + return amount.hashCode() * 37 + currency.hashCode();
54.90 + }
54.91 +
54.92 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/task3/solution07/src/org/apidesign/apifest08/currency/TableConvertor.java Tue Oct 07 11:05:34 2008 +0200
55.3 @@ -0,0 +1,71 @@
55.4 +package org.apidesign.apifest08.currency;
55.5 +
55.6 +import java.util.Currency;
55.7 +import java.util.HashMap;
55.8 +import java.util.Map;
55.9 +
55.10 +/**
55.11 + * A {@link Convertor} that works from a pre-set conversion table.
55.12 + * First use {@link #putIntoTable(org.apidesign.apifest08.currency.ConversionRate)} to set the conversion table.
55.13 + * Then invoke the {@link #convert(org.apidesign.apifest08.currency.Convertor.ConversionRequest)} method as many times as you wish.
55.14 + * @author jdvorak
55.15 + */
55.16 +public class TableConvertor implements Convertor {
55.17 +
55.18 + private final Map<Currency, Map<Currency, ConversionRate>> conversionTable = new HashMap<Currency, Map<Currency, ConversionRate>>();
55.19 +
55.20 + public TableConvertor() {
55.21 + }
55.22 +
55.23 + /**
55.24 + * Puts a rate into the table.
55.25 + * @param rate
55.26 + */
55.27 + public void putIntoTable( final ConversionRate rate ) {
55.28 + final Currency srcCurrency = rate.getSrcUnitAmount().getCurrency();
55.29 + final Currency tgtCurrency = rate.getTgtUnitAmount().getCurrency();
55.30 + synchronized ( conversionTable ) {
55.31 + Map<Currency, ConversionRate> targetTable = conversionTable.get( srcCurrency );
55.32 + if ( targetTable == null ) {
55.33 + targetTable = new HashMap<Currency, ConversionRate>();
55.34 + conversionTable.put( srcCurrency, targetTable );
55.35 + }
55.36 + targetTable.put( tgtCurrency, rate );
55.37 + }
55.38 + }
55.39 +
55.40 + /**
55.41 + * Carries out the conversion.
55.42 + * If the table does not contain a conversion from the source currency to the target one,
55.43 + * a {@link ConversionResult} is returned that has null netAmount.
55.44 + * This implementation works with any {@link ConversionRequest}, it won't throw {@link IllegalRequestSubtypeException}.
55.45 + * @param req the conversion request
55.46 + * @return the conversion result
55.47 + */
55.48 + public ConversionResult convert( final ConversionRequest req ) {
55.49 + final Currency srcCurrency = req.getSrcAmount().getCurrency();
55.50 + final Currency tgtCurrency = req.getTgtCurrency();
55.51 + final ConversionRate rate = findConversionRate( srcCurrency, tgtCurrency );
55.52 + if ( rate != null ) {
55.53 + final MonetaryAmount tgtAmount = rate.convert( req.getSrcAmount() );
55.54 + return new ConversionResult( tgtAmount );
55.55 + } else {
55.56 + return new ConversionResult( null ); // did not find the pair of currencies in the table
55.57 + }
55.58 + }
55.59 +
55.60 + /**
55.61 + * Looks up the conversion between the given currencies in the table.
55.62 + * @param srcCurrency the source currency
55.63 + * @param tgtCurrency the target currency
55.64 + * @return the conversion rate; null means no conversion between the currencies was found in the table
55.65 + */
55.66 + protected ConversionRate findConversionRate( final Currency srcCurrency, final Currency tgtCurrency ) {
55.67 + synchronized ( conversionTable ) {
55.68 + final Map<Currency, ConversionRate> targetTable = conversionTable.get(srcCurrency);
55.69 + final ConversionRate rate = (targetTable != null) ? targetTable.get(tgtCurrency) : null;
55.70 + return rate;
55.71 + }
55.72 + }
55.73 +
55.74 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/task3/solution07/test/org/apidesign/apifest08/test/ContractImposingDelegatingConvertor.java Tue Oct 07 11:05:34 2008 +0200
56.3 @@ -0,0 +1,53 @@
56.4 +/*
56.5 + * To change this template, choose Tools | Templates
56.6 + * and open the template in the editor.
56.7 + */
56.8 +
56.9 +package org.apidesign.apifest08.test;
56.10 +
56.11 +import java.math.BigDecimal;
56.12 +import java.util.Currency;
56.13 +import junit.framework.Assert;
56.14 +import org.apidesign.apifest08.currency.Convertor;
56.15 +import org.apidesign.apifest08.currency.DelegatingConvertor;
56.16 +import org.apidesign.apifest08.currency.MonetaryAmount;
56.17 +
56.18 +/**
56.19 + * A delegating convertor that checks preconditions and postconditions.
56.20 + * Useful for testing.
56.21 + * @author jdvorak
56.22 + */
56.23 +public class ContractImposingDelegatingConvertor extends DelegatingConvertor {
56.24 +
56.25 + public ContractImposingDelegatingConvertor( final Convertor underlyingConvertor ) {
56.26 + super( underlyingConvertor );
56.27 + }
56.28 +
56.29 + @Override
56.30 + public ConversionResult convert( final ConversionRequest req ) {
56.31 + Assert.assertNotNull( "The request", req );
56.32 + final ConversionResult result = super.convert( req );
56.33 + Assert.assertNotNull( "Result of the convert() call", result );
56.34 + final MonetaryAmount netAmount = result.getNetAmount();
56.35 + if ( netAmount != null ) {
56.36 + Assert.assertEquals( "Converted to a different currency than specified in the request", req.getTgtCurrency(), netAmount.getCurrency() );
56.37 + }
56.38 + return result;
56.39 + }
56.40 +
56.41 + /**
56.42 + * Do some tests on our own.
56.43 + * @return this
56.44 + */
56.45 + public Convertor test() {
56.46 + try {
56.47 + final Currency aCurrency = Currency.getInstance( "EUR" );
56.48 + new ConversionRequest( new MonetaryAmount( BigDecimal.ONE, aCurrency ), aCurrency );
56.49 + Assert.fail( "Should have thrown an IllegalArgumentException" );
56.50 + } catch ( final IllegalArgumentException e ) {
56.51 + Assert.assertEquals( "Cannot request conversion from EUR to EUR", e.getMessage() );
56.52 + }
56.53 + return this;
56.54 + }
56.55 +
56.56 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/task3/solution07/test/org/apidesign/apifest08/test/Task1Test.java Tue Oct 07 11:05:34 2008 +0200
57.3 @@ -0,0 +1,177 @@
57.4 +package org.apidesign.apifest08.test;
57.5 +
57.6 +import java.util.Currency;
57.7 +import junit.framework.TestCase;
57.8 +import org.apidesign.apifest08.currency.ConversionRate;
57.9 +import org.apidesign.apifest08.currency.Convertor;
57.10 +import org.apidesign.apifest08.currency.MonetaryAmount;
57.11 +import org.apidesign.apifest08.currency.TableConvertor;
57.12 +
57.13 +/** Finish the Convertor API, and then write bodies of methods inside
57.14 + * of this class to match the given tasks. To fullfil your task, use the
57.15 + * API define in the <code>org.apidesign.apifest08.currency</code> package.
57.16 + * Do not you reflection, or other hacks as your code
57.17 + * shall run without any runtime permissions.
57.18 + */
57.19 +public class Task1Test extends TestCase {
57.20 + public Task1Test(String testName) {
57.21 + super(testName);
57.22 + }
57.23 +
57.24 + @Override
57.25 + protected void setUp() throws Exception {
57.26 + }
57.27 +
57.28 + @Override
57.29 + protected void tearDown() throws Exception {
57.30 + }
57.31 +
57.32 + //
57.33 + // Imagine that there are three parts of the whole system:
57.34 + // 1. there is someone who knows the current exchange rate
57.35 + // 2. there is someone who wants to do the conversion
57.36 + // 3. there is the API between 1. and 2. which allows them to communicate
57.37 + // Please design such API
57.38 + //
57.39 +
57.40 + protected static final Currency CZK = Currency.getInstance( "CZK" );
57.41 + protected static final Currency SKK = Currency.getInstance( "SKK" );
57.42 + protected static final Currency USD = Currency.getInstance( "USD" );
57.43 +
57.44 + /** Create convertor that understands two currencies, CZK and
57.45 + * USD. Make 1 USD == 17 CZK.
57.46 + * USD. Make 1 USD == 17 CZK. This is a method provided for #1 group -
57.47 + * e.g. those that know the exchange rate. They somehow need to create
57.48 + * the objects from the API and tell them the exchange rate. The API itself
57.49 + * knows nothing about any rates, before the createCZKtoUSD method is called.
57.50 + *
57.51 + * Creation of the convertor shall not require subclassing of any class
57.52 + * or interface on the client side.
57.53 + *
57.54 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
57.55 + */
57.56 + public static Convertor createCZKtoUSD() {
57.57 + final TableConvertor convertor = new TableConvertor();
57.58 + final MonetaryAmount amountInCZK = new MonetaryAmount( 17, CZK );
57.59 + final MonetaryAmount amountInUSD = new MonetaryAmount( 1, USD );
57.60 + convertor.putIntoTable( new ConversionRate( amountInCZK, amountInUSD ) );
57.61 + convertor.putIntoTable( new ConversionRate( amountInUSD, amountInCZK ) );
57.62 + return new ContractImposingDelegatingConvertor( convertor ).test();
57.63 + }
57.64 +
57.65 + /** Create convertor that understands two currencies, CZK and
57.66 + * SKK. Make 100 SKK == 80 CZK. Again this is method for the #1 group -
57.67 + * it knows the exchange rate, and needs to use the API to create objects
57.68 + * with the exchange rate. Anyone shall be ready to call this method without
57.69 + * any other method being called previously. The API itself shall know
57.70 + * nothing about any rates, before this method is called.
57.71 + *
57.72 + * Creation of the convertor shall not require subclassing of any class
57.73 + * or interface on the client side.
57.74 + *
57.75 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
57.76 + */
57.77 + public static Convertor createSKKtoCZK() {
57.78 + final TableConvertor convertor = new TableConvertor();
57.79 + final MonetaryAmount amountInSKK = new MonetaryAmount( 100, SKK );
57.80 + final MonetaryAmount amountInCZK = new MonetaryAmount( 80, CZK );
57.81 + convertor.putIntoTable( new ConversionRate( amountInSKK, amountInCZK ) );
57.82 + convertor.putIntoTable( new ConversionRate( amountInCZK, amountInSKK ) );
57.83 + return new ContractImposingDelegatingConvertor( convertor ).test();
57.84 + }
57.85 +
57.86 + //
57.87 + // now the methods for group #2 follow:
57.88 + // this group knows nothing about exchange rates, but knows how to use
57.89 + // the API to do conversions. It somehow (by calling one of the factory
57.90 + // methods) gets objects from the API and uses them to do the conversions.
57.91 + //
57.92 +
57.93 + /** Use the convertor from <code>createCZKtoUSD</code> method and do few conversions
57.94 + * with it.
57.95 + */
57.96 + public void testCurrencyCZKUSD() throws Exception {
57.97 + final Convertor c = createCZKtoUSD();
57.98 +
57.99 + // convert $5 to CZK using c:
57.100 + final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), CZK ) );
57.101 + final MonetaryAmount a1 = r1.getNetAmount();
57.102 + // assertEquals("Result is 85 CZK");
57.103 + assertNotNull( a1 );
57.104 + assertEquals( 85.0, a1.getAmount().doubleValue() );
57.105 + assertEquals( CZK, a1.getCurrency() );
57.106 +
57.107 + // convert $8 to CZK
57.108 + final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 8, USD ), CZK ) );
57.109 + final MonetaryAmount a2 = r2.getNetAmount();
57.110 + // assertEquals("Result is 136 CZK");
57.111 + assertNotNull( a2 );
57.112 + assertEquals( 136.0, a2.getAmount().doubleValue() );
57.113 + assertEquals( CZK, a2.getCurrency() );
57.114 +
57.115 + // convert 1003CZK to USD
57.116 + final Convertor.ConversionResult r3 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 1003, CZK ), USD ) );
57.117 + final MonetaryAmount a3 = r3.getNetAmount();
57.118 + // assertEquals("Result is 59 USD");
57.119 + assertNotNull( a3 );
57.120 + assertEquals( 59.0, a3.getAmount().doubleValue() );
57.121 + assertEquals( USD, a3.getCurrency() );
57.122 + }
57.123 +
57.124 + /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
57.125 + * with it.
57.126 + */
57.127 + public void testCurrencySKKCZK() throws Exception {
57.128 + final Convertor c = createSKKtoCZK();
57.129 +
57.130 + // convert 16CZK using c:
57.131 + final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 16, CZK ), SKK ) );
57.132 + final MonetaryAmount a1 = r1.getNetAmount();
57.133 + // assertEquals("Result is 20 SKK");
57.134 + assertNotNull( a1 );
57.135 + assertEquals( 20.0, a1.getAmount().doubleValue() );
57.136 + assertEquals( SKK, a1.getCurrency() );
57.137 +
57.138 + // convert 500SKK to CZK
57.139 + final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 500, SKK ), CZK ) );
57.140 + final MonetaryAmount a2 = r2.getNetAmount();
57.141 + // assertEquals("Result is 400 CZK");
57.142 + assertNotNull( a2 );
57.143 + assertEquals( 400.0, a2.getAmount().doubleValue() );
57.144 + assertEquals( CZK, a2.getCurrency() );
57.145 + }
57.146 +
57.147 + /** Verify that the CZK to USD convertor knows nothing about SKK.
57.148 + */
57.149 + public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
57.150 + final Convertor c = createCZKtoUSD();
57.151 +
57.152 + // convert $5 to SKK, the API shall say this is not possible
57.153 + final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), SKK ) );
57.154 + final MonetaryAmount a1 = r1.getNetAmount();
57.155 + assertNull( a1 );
57.156 +
57.157 + // convert 500 SKK to CZK, the API shall say this is not possible
57.158 + final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, SKK ), CZK ) );
57.159 + final MonetaryAmount a2 = r2.getNetAmount();
57.160 + assertNull( a2 );
57.161 + }
57.162 +
57.163 + /** Verify that the CZK to SKK convertor knows nothing about USD.
57.164 + */
57.165 + public void testCannotConvertToUSDwithCZKSKKConvertor() throws Exception {
57.166 + final Convertor c = createSKKtoCZK();
57.167 +
57.168 + // convert $5 to SKK, the API shall say this is not possible
57.169 + final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), SKK ) );
57.170 + final MonetaryAmount a1 = r1.getNetAmount();
57.171 + assertNull( a1 );
57.172 +
57.173 + // convert 500 CZK to USD, the API shall say this is not possible
57.174 + final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, CZK ), USD ) );
57.175 + final MonetaryAmount a2 = r2.getNetAmount();
57.176 + assertNull( a2 );
57.177 + }
57.178 +
57.179 +}
57.180 +
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/task3/solution07/test/org/apidesign/apifest08/test/Task2Test.java Tue Oct 07 11:05:34 2008 +0200
58.3 @@ -0,0 +1,192 @@
58.4 +package org.apidesign.apifest08.test;
58.5 +
58.6 +import java.util.Currency;
58.7 +import junit.framework.TestCase;
58.8 +import org.apidesign.apifest08.currency.ConversionRate;
58.9 +import org.apidesign.apifest08.currency.Convertor;
58.10 +import org.apidesign.apifest08.currency.IllegalRequestSubtypeException;
58.11 +import org.apidesign.apifest08.currency.MonetaryAmount;
58.12 +import org.apidesign.apifest08.currency.TableConvertor;
58.13 +
58.14 +/** There are many currencies around the world and many banks manipulate
58.15 + * with more than one or two at the same time. As banks are usually the
58.16 + * best paying clients, which is true even in case of your Convertor API,
58.17 + * it is reasonable to listen to their requests.
58.18 + * <p>
58.19 + * The quest for today is to enhance your existing convertor API to hold
58.20 + * information about many currencies and allow conversions between any of them.
58.21 + * Also, as conversion rates for diferent currencies usually arise from various
58.22 + * bank departments, there is another important need. There is a need to
58.23 + * compose two convertors into one by merging all the information about
58.24 + * currencies they know about.
58.25 + */
58.26 +public class Task2Test extends TestCase {
58.27 + public Task2Test(String testName) {
58.28 + super(testName);
58.29 + }
58.30 +
58.31 + @Override
58.32 + protected void setUp() throws Exception {
58.33 + }
58.34 +
58.35 + @Override
58.36 + protected void tearDown() throws Exception {
58.37 + }
58.38 +
58.39 + protected static final Currency CZK = Currency.getInstance( "CZK" );
58.40 + protected static final Currency SKK = Currency.getInstance( "SKK" );
58.41 + protected static final Currency USD = Currency.getInstance( "USD" );
58.42 +
58.43 + // As in Task1Test, keep in mind, that there are three parts
58.44 + // of the whole system:
58.45 + // 1. there is someone who knows the current exchange rate
58.46 + // 2. there is someone who wants to do the conversion
58.47 + // 3. there is the API between 1. and 2. which allows them to communicate
58.48 + //
58.49 + // Please backward compatibly enhance your existing API to support following
58.50 + // usecases:
58.51 + //
58.52 +
58.53 + /** Create convertor that understands two currencies, CZK and
58.54 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
58.55 + * knows the exchange rate, and needs to use the API to create objects
58.56 + * with the exchange rate. Anyone shall be ready to call this method without
58.57 + * any other method being called previously. The API itself shall know
58.58 + * nothing about any rates, before this method is called.
58.59 + */
58.60 + public static Convertor createTripleConvertor() {
58.61 + // Rates: 1USD = 15CZK
58.62 + // Rates: 1USD = 20SKK
58.63 + // Rates: 75CZK = 100SKK
58.64 + final TableConvertor convertor = new TableConvertor();
58.65 + final MonetaryAmount amountInUSD = new MonetaryAmount( 1, USD );
58.66 + final MonetaryAmount amountInCZK = new MonetaryAmount( 15, CZK );
58.67 + final MonetaryAmount amountInSKK = new MonetaryAmount( 20, SKK );
58.68 + convertor.putIntoTable( new ConversionRate( amountInCZK, amountInUSD ) );
58.69 + convertor.putIntoTable( new ConversionRate( amountInUSD, amountInCZK ) );
58.70 + convertor.putIntoTable( new ConversionRate( amountInSKK, amountInUSD ) );
58.71 + convertor.putIntoTable( new ConversionRate( amountInUSD, amountInSKK ) );
58.72 + convertor.putIntoTable( new ConversionRate( amountInSKK, amountInCZK ) );
58.73 + convertor.putIntoTable( new ConversionRate( amountInCZK, amountInSKK ) );
58.74 + return new ContractImposingDelegatingConvertor( convertor ).test();
58.75 + }
58.76 +
58.77 + /** Define convertor that understands three currencies. Use it.
58.78 + */
58.79 + public void testConvertorForUSDandCZKandSKK() throws Exception {
58.80 + final Convertor c = createTripleConvertor();
58.81 +
58.82 + // convert $5 to CZK using c:
58.83 + final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), CZK ) );
58.84 + final MonetaryAmount a1 = r1.getNetAmount();
58.85 + // assertEquals("Result is 75 CZK");
58.86 + assertNotNull( a1 );
58.87 + assertEquals( 75.0, a1.getAmount().doubleValue() );
58.88 + assertEquals( CZK, a1.getCurrency() );
58.89 +
58.90 + // convert $5 to SKK using c:
58.91 + final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), SKK ) );
58.92 + final MonetaryAmount a2 = r2.getNetAmount();
58.93 + // assertEquals("Result is 100 SKK");
58.94 + assertNotNull( a2 );
58.95 + assertEquals( 100.0, a2.getAmount().doubleValue() );
58.96 + assertEquals( SKK, a2.getCurrency() );
58.97 +
58.98 + // convert 200SKK to CZK using c:
58.99 + final Convertor.ConversionResult r3 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 200, SKK ), CZK ) );
58.100 + final MonetaryAmount a3 = r3.getNetAmount();
58.101 + // assertEquals("Result is 150 CZK");
58.102 + assertNotNull( a3 );
58.103 + assertEquals( 150.0, a3.getAmount().doubleValue() );
58.104 + assertEquals( CZK, a3.getCurrency() );
58.105 +
58.106 + // convert 200SKK to USK using c:
58.107 + final Convertor.ConversionResult r4 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 200, SKK ), USD ) );
58.108 + final MonetaryAmount a4 = r4.getNetAmount();
58.109 + // assertEquals("Result is 10 USD");
58.110 + assertNotNull( a4 );
58.111 + assertEquals( 10.0, a4.getAmount().doubleValue() );
58.112 + assertEquals( USD, a4.getCurrency() );
58.113 + }
58.114 +
58.115 + /** Merge all currency rates of convertor 1 with convertor 2.
58.116 + * Implement this using your API, preferably this method just delegates
58.117 + * into some API method which does the actual work, without requiring
58.118 + * API clients to code anything complex.
58.119 + */
58.120 + public static Convertor merge( final Convertor one, final Convertor two ) {
58.121 + return new Convertor() {
58.122 +
58.123 + public ConversionResult convert( ConversionRequest req ) throws IllegalRequestSubtypeException {
58.124 + final ConversionResult res1 = one.convert( req );
58.125 + final ConversionResult res2 = two.convert( req );
58.126 + if ( res1.getNetAmount() != null ) {
58.127 + if ( res2.getNetAmount() != null ) {
58.128 + // TODO check if they arrive at the same thing
58.129 + return res1;
58.130 + } else {
58.131 + return res1;
58.132 + }
58.133 + } else {
58.134 + if ( res2.getNetAmount() != null ) {
58.135 + return res2;
58.136 + } else {
58.137 + // neither converts
58.138 + return new ConversionResult( null );
58.139 + }
58.140 + }
58.141 + }
58.142 +
58.143 + };
58.144 + }
58.145 +
58.146 + /** Join the convertors from previous task, Task1Test and show that it
58.147 + * can be used to do reasonable conversions.
58.148 + */
58.149 + public void testConvertorComposition() throws Exception {
58.150 + final Convertor c = merge(
58.151 + Task1Test.createCZKtoUSD(),
58.152 + Task1Test.createSKKtoCZK()
58.153 + );
58.154 +
58.155 + // convert $5 to CZK using c:
58.156 + final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), CZK ) );
58.157 + final MonetaryAmount a1 = r1.getNetAmount();
58.158 + // assertEquals("Result is 85 CZK");
58.159 + assertNotNull( a1 );
58.160 + assertEquals( 85.0, a1.getAmount().doubleValue() );
58.161 + assertEquals( CZK, a1.getCurrency() );
58.162 +
58.163 + // convert $8 to CZK
58.164 + final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 8, USD ), CZK ) );
58.165 + final MonetaryAmount a2 = r2.getNetAmount();
58.166 + // assertEquals("Result is 136 CZK");
58.167 + assertNotNull( a2 );
58.168 + assertEquals( 136.0, a2.getAmount().doubleValue() );
58.169 + assertEquals( CZK, a2.getCurrency() );
58.170 +
58.171 + // convert 1003CZK to USD
58.172 + final Convertor.ConversionResult r3 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 1003, CZK ), USD ) );
58.173 + final MonetaryAmount a3 = r3.getNetAmount();
58.174 + // assertEquals("Result is 59 USD");
58.175 + assertNotNull( a3 );
58.176 + assertEquals( 59.0, a3.getAmount().doubleValue() );
58.177 + assertEquals( USD, a3.getCurrency() );
58.178 +
58.179 + // convert 16CZK using c:
58.180 + final Convertor.ConversionResult r4 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 16, CZK ), SKK ) );
58.181 + final MonetaryAmount a4 = r4.getNetAmount();
58.182 + // assertEquals("Result is 20 SKK");
58.183 + assertNotNull( a4 );
58.184 + assertEquals( 20.0, a4.getAmount().doubleValue() );
58.185 + assertEquals( SKK, a4.getCurrency() );
58.186 +
58.187 + // convert 500SKK to CZK using c:
58.188 + final Convertor.ConversionResult r5 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 500, SKK ), CZK ) );
58.189 + final MonetaryAmount a5 = r5.getNetAmount();
58.190 + // assertEquals("Result is 400 CZK");
58.191 + assertNotNull( a5 );
58.192 + assertEquals( 400.0, a5.getAmount().doubleValue() );
58.193 + assertEquals( CZK, a5.getCurrency() );
58.194 + }
58.195 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/task3/solution11/build.xml Tue Oct 07 11:05:34 2008 +0200
59.3 @@ -0,0 +1,69 @@
59.4 +<?xml version="1.0" encoding="UTF-8"?>
59.5 +<!-- You may freely edit this file. See commented blocks below for -->
59.6 +<!-- some examples of how to customize the build. -->
59.7 +<!-- (If you delete it and reopen the project it will be recreated.) -->
59.8 +<project name="currency" default="default" basedir=".">
59.9 + <description>Builds, tests, and runs the project.</description>
59.10 + <import file="nbproject/build-impl.xml"/>
59.11 + <!--
59.12 +
59.13 + There exist several targets which are by default empty and which can be
59.14 + used for execution of your tasks. These targets are usually executed
59.15 + before and after some main targets. They are:
59.16 +
59.17 + -pre-init: called before initialization of project properties
59.18 + -post-init: called after initialization of project properties
59.19 + -pre-compile: called before javac compilation
59.20 + -post-compile: called after javac compilation
59.21 + -pre-compile-single: called before javac compilation of single file
59.22 + -post-compile-single: called after javac compilation of single file
59.23 + -pre-compile-test: called before javac compilation of JUnit tests
59.24 + -post-compile-test: called after javac compilation of JUnit tests
59.25 + -pre-compile-test-single: called before javac compilation of single JUnit test
59.26 + -post-compile-test-single: called after javac compilation of single JUunit test
59.27 + -pre-jar: called before JAR building
59.28 + -post-jar: called after JAR building
59.29 + -post-clean: called after cleaning build products
59.30 +
59.31 + (Targets beginning with '-' are not intended to be called on their own.)
59.32 +
59.33 + Example of inserting an obfuscator after compilation could look like this:
59.34 +
59.35 + <target name="-post-compile">
59.36 + <obfuscate>
59.37 + <fileset dir="${build.classes.dir}"/>
59.38 + </obfuscate>
59.39 + </target>
59.40 +
59.41 + For list of available properties check the imported
59.42 + nbproject/build-impl.xml file.
59.43 +
59.44 +
59.45 + Another way to customize the build is by overriding existing main targets.
59.46 + The targets of interest are:
59.47 +
59.48 + -init-macrodef-javac: defines macro for javac compilation
59.49 + -init-macrodef-junit: defines macro for junit execution
59.50 + -init-macrodef-debug: defines macro for class debugging
59.51 + -init-macrodef-java: defines macro for class execution
59.52 + -do-jar-with-manifest: JAR building (if you are using a manifest)
59.53 + -do-jar-without-manifest: JAR building (if you are not using a manifest)
59.54 + run: execution of project
59.55 + -javadoc-build: Javadoc generation
59.56 + test-report: JUnit report generation
59.57 +
59.58 + An example of overriding the target for project execution could look like this:
59.59 +
59.60 + <target name="run" depends="currency-impl.jar">
59.61 + <exec dir="bin" executable="launcher.exe">
59.62 + <arg file="${dist.jar}"/>
59.63 + </exec>
59.64 + </target>
59.65 +
59.66 + Notice that the overridden target depends on the jar target and not only on
59.67 + the compile target as the regular run target does. Again, for a list of available
59.68 + properties which you can use, check the target you are overriding in the
59.69 + nbproject/build-impl.xml file.
59.70 +
59.71 + -->
59.72 +</project>
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/task3/solution11/nbproject/build-impl.xml Tue Oct 07 11:05:34 2008 +0200
60.3 @@ -0,0 +1,629 @@
60.4 +<?xml version="1.0" encoding="UTF-8"?>
60.5 +<!--
60.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
60.7 +*** EDIT ../build.xml INSTEAD ***
60.8 +
60.9 +For the purpose of easier reading the script
60.10 +is divided into following sections:
60.11 +
60.12 + - initialization
60.13 + - compilation
60.14 + - jar
60.15 + - execution
60.16 + - debugging
60.17 + - javadoc
60.18 + - junit compilation
60.19 + - junit execution
60.20 + - junit debugging
60.21 + - applet
60.22 + - cleanup
60.23 +
60.24 + -->
60.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_11-impl">
60.26 + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
60.27 + <!--
60.28 + ======================
60.29 + INITIALIZATION SECTION
60.30 + ======================
60.31 + -->
60.32 + <target name="-pre-init">
60.33 + <!-- Empty placeholder for easier customization. -->
60.34 + <!-- You can override this target in the ../build.xml file. -->
60.35 + </target>
60.36 + <target depends="-pre-init" name="-init-private">
60.37 + <property file="nbproject/private/config.properties"/>
60.38 + <property file="nbproject/private/configs/${config}.properties"/>
60.39 + <property file="nbproject/private/private.properties"/>
60.40 + </target>
60.41 + <target depends="-pre-init,-init-private" name="-init-user">
60.42 + <property file="${user.properties.file}"/>
60.43 + <!-- The two properties below are usually overridden -->
60.44 + <!-- by the active platform. Just a fallback. -->
60.45 + <property name="default.javac.source" value="1.4"/>
60.46 + <property name="default.javac.target" value="1.4"/>
60.47 + </target>
60.48 + <target depends="-pre-init,-init-private,-init-user" name="-init-project">
60.49 + <property file="nbproject/configs/${config}.properties"/>
60.50 + <property file="nbproject/project.properties"/>
60.51 + </target>
60.52 + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
60.53 + <available file="${manifest.file}" property="manifest.available"/>
60.54 + <condition property="manifest.available+main.class">
60.55 + <and>
60.56 + <isset property="manifest.available"/>
60.57 + <isset property="main.class"/>
60.58 + <not>
60.59 + <equals arg1="${main.class}" arg2="" trim="true"/>
60.60 + </not>
60.61 + </and>
60.62 + </condition>
60.63 + <condition property="manifest.available+main.class+mkdist.available">
60.64 + <and>
60.65 + <istrue value="${manifest.available+main.class}"/>
60.66 + <isset property="libs.CopyLibs.classpath"/>
60.67 + </and>
60.68 + </condition>
60.69 + <condition property="have.tests">
60.70 + <or>
60.71 + <available file="${test.src.dir}"/>
60.72 + </or>
60.73 + </condition>
60.74 + <condition property="have.sources">
60.75 + <or>
60.76 + <available file="${src.dir}"/>
60.77 + </or>
60.78 + </condition>
60.79 + <condition property="netbeans.home+have.tests">
60.80 + <and>
60.81 + <isset property="netbeans.home"/>
60.82 + <isset property="have.tests"/>
60.83 + </and>
60.84 + </condition>
60.85 + <condition property="no.javadoc.preview">
60.86 + <and>
60.87 + <isset property="javadoc.preview"/>
60.88 + <isfalse value="${javadoc.preview}"/>
60.89 + </and>
60.90 + </condition>
60.91 + <property name="run.jvmargs" value=""/>
60.92 + <property name="javac.compilerargs" value=""/>
60.93 + <property name="work.dir" value="${basedir}"/>
60.94 + <condition property="no.deps">
60.95 + <and>
60.96 + <istrue value="${no.dependencies}"/>
60.97 + </and>
60.98 + </condition>
60.99 + <property name="javac.debug" value="true"/>
60.100 + <property name="javadoc.preview" value="true"/>
60.101 + <property name="application.args" value=""/>
60.102 + <property name="source.encoding" value="${file.encoding}"/>
60.103 + <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
60.104 + <and>
60.105 + <isset property="javadoc.encoding"/>
60.106 + <not>
60.107 + <equals arg1="${javadoc.encoding}" arg2=""/>
60.108 + </not>
60.109 + </and>
60.110 + </condition>
60.111 + <property name="javadoc.encoding.used" value="${source.encoding}"/>
60.112 + <property name="includes" value="**"/>
60.113 + <property name="excludes" value=""/>
60.114 + <property name="do.depend" value="false"/>
60.115 + <condition property="do.depend.true">
60.116 + <istrue value="${do.depend}"/>
60.117 + </condition>
60.118 + <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
60.119 + <and>
60.120 + <isset property="jaxws.endorsed.dir"/>
60.121 + <available file="nbproject/jaxws-build.xml"/>
60.122 + </and>
60.123 + </condition>
60.124 + </target>
60.125 + <target name="-post-init">
60.126 + <!-- Empty placeholder for easier customization. -->
60.127 + <!-- You can override this target in the ../build.xml file. -->
60.128 + </target>
60.129 + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
60.130 + <fail unless="src.dir">Must set src.dir</fail>
60.131 + <fail unless="test.src.dir">Must set test.src.dir</fail>
60.132 + <fail unless="build.dir">Must set build.dir</fail>
60.133 + <fail unless="dist.dir">Must set dist.dir</fail>
60.134 + <fail unless="build.classes.dir">Must set build.classes.dir</fail>
60.135 + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
60.136 + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
60.137 + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
60.138 + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
60.139 + <fail unless="dist.jar">Must set dist.jar</fail>
60.140 + </target>
60.141 + <target name="-init-macrodef-property">
60.142 + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
60.143 + <attribute name="name"/>
60.144 + <attribute name="value"/>
60.145 + <sequential>
60.146 + <property name="@{name}" value="${@{value}}"/>
60.147 + </sequential>
60.148 + </macrodef>
60.149 + </target>
60.150 + <target name="-init-macrodef-javac">
60.151 + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
60.152 + <attribute default="${src.dir}" name="srcdir"/>
60.153 + <attribute default="${build.classes.dir}" name="destdir"/>
60.154 + <attribute default="${javac.classpath}" name="classpath"/>
60.155 + <attribute default="${includes}" name="includes"/>
60.156 + <attribute default="${excludes}" name="excludes"/>
60.157 + <attribute default="${javac.debug}" name="debug"/>
60.158 + <attribute default="" name="sourcepath"/>
60.159 + <element name="customize" optional="true"/>
60.160 + <sequential>
60.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}">
60.162 + <classpath>
60.163 + <path path="@{classpath}"/>
60.164 + </classpath>
60.165 + <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
60.166 + <customize/>
60.167 + </javac>
60.168 + </sequential>
60.169 + </macrodef>
60.170 + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
60.171 + <attribute default="${src.dir}" name="srcdir"/>
60.172 + <attribute default="${build.classes.dir}" name="destdir"/>
60.173 + <attribute default="${javac.classpath}" name="classpath"/>
60.174 + <sequential>
60.175 + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
60.176 + <classpath>
60.177 + <path path="@{classpath}"/>
60.178 + </classpath>
60.179 + </depend>
60.180 + </sequential>
60.181 + </macrodef>
60.182 + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
60.183 + <attribute default="${build.classes.dir}" name="destdir"/>
60.184 + <sequential>
60.185 + <fail unless="javac.includes">Must set javac.includes</fail>
60.186 + <pathconvert pathsep="," property="javac.includes.binary">
60.187 + <path>
60.188 + <filelist dir="@{destdir}" files="${javac.includes}"/>
60.189 + </path>
60.190 + <globmapper from="*.java" to="*.class"/>
60.191 + </pathconvert>
60.192 + <delete>
60.193 + <files includes="${javac.includes.binary}"/>
60.194 + </delete>
60.195 + </sequential>
60.196 + </macrodef>
60.197 + </target>
60.198 + <target name="-init-macrodef-junit">
60.199 + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
60.200 + <attribute default="${includes}" name="includes"/>
60.201 + <attribute default="${excludes}" name="excludes"/>
60.202 + <attribute default="**" name="testincludes"/>
60.203 + <sequential>
60.204 + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
60.205 + <batchtest todir="${build.test.results.dir}">
60.206 + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
60.207 + <filename name="@{testincludes}"/>
60.208 + </fileset>
60.209 + </batchtest>
60.210 + <classpath>
60.211 + <path path="${run.test.classpath}"/>
60.212 + </classpath>
60.213 + <syspropertyset>
60.214 + <propertyref prefix="test-sys-prop."/>
60.215 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
60.216 + </syspropertyset>
60.217 + <formatter type="brief" usefile="false"/>
60.218 + <formatter type="xml"/>
60.219 + <jvmarg line="${run.jvmargs}"/>
60.220 + </junit>
60.221 + </sequential>
60.222 + </macrodef>
60.223 + </target>
60.224 + <target name="-init-macrodef-nbjpda">
60.225 + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
60.226 + <attribute default="${main.class}" name="name"/>
60.227 + <attribute default="${debug.classpath}" name="classpath"/>
60.228 + <attribute default="" name="stopclassname"/>
60.229 + <sequential>
60.230 + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="dt_socket">
60.231 + <classpath>
60.232 + <path path="@{classpath}"/>
60.233 + </classpath>
60.234 + </nbjpdastart>
60.235 + </sequential>
60.236 + </macrodef>
60.237 + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
60.238 + <attribute default="${build.classes.dir}" name="dir"/>
60.239 + <sequential>
60.240 + <nbjpdareload>
60.241 + <fileset dir="@{dir}" includes="${fix.classes}">
60.242 + <include name="${fix.includes}*.class"/>
60.243 + </fileset>
60.244 + </nbjpdareload>
60.245 + </sequential>
60.246 + </macrodef>
60.247 + </target>
60.248 + <target name="-init-debug-args">
60.249 + <property name="version-output" value="java version "${ant.java.version}"/>
60.250 + <condition property="have-jdk-older-than-1.4">
60.251 + <or>
60.252 + <contains string="${version-output}" substring="java version "1.0"/>
60.253 + <contains string="${version-output}" substring="java version "1.1"/>
60.254 + <contains string="${version-output}" substring="java version "1.2"/>
60.255 + <contains string="${version-output}" substring="java version "1.3"/>
60.256 + </or>
60.257 + </condition>
60.258 + <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
60.259 + <istrue value="${have-jdk-older-than-1.4}"/>
60.260 + </condition>
60.261 + </target>
60.262 + <target depends="-init-debug-args" name="-init-macrodef-debug">
60.263 + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
60.264 + <attribute default="${main.class}" name="classname"/>
60.265 + <attribute default="${debug.classpath}" name="classpath"/>
60.266 + <element name="customize" optional="true"/>
60.267 + <sequential>
60.268 + <java classname="@{classname}" dir="${work.dir}" fork="true">
60.269 + <jvmarg line="${debug-args-line}"/>
60.270 + <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
60.271 + <jvmarg line="${run.jvmargs}"/>
60.272 + <classpath>
60.273 + <path path="@{classpath}"/>
60.274 + </classpath>
60.275 + <syspropertyset>
60.276 + <propertyref prefix="run-sys-prop."/>
60.277 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
60.278 + </syspropertyset>
60.279 + <customize/>
60.280 + </java>
60.281 + </sequential>
60.282 + </macrodef>
60.283 + </target>
60.284 + <target name="-init-macrodef-java">
60.285 + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
60.286 + <attribute default="${main.class}" name="classname"/>
60.287 + <element name="customize" optional="true"/>
60.288 + <sequential>
60.289 + <java classname="@{classname}" dir="${work.dir}" fork="true">
60.290 + <jvmarg line="${run.jvmargs}"/>
60.291 + <classpath>
60.292 + <path path="${run.classpath}"/>
60.293 + </classpath>
60.294 + <syspropertyset>
60.295 + <propertyref prefix="run-sys-prop."/>
60.296 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
60.297 + </syspropertyset>
60.298 + <customize/>
60.299 + </java>
60.300 + </sequential>
60.301 + </macrodef>
60.302 + </target>
60.303 + <target name="-init-presetdef-jar">
60.304 + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
60.305 + <jar compress="${jar.compress}" jarfile="${dist.jar}">
60.306 + <j2seproject1:fileset dir="${build.classes.dir}"/>
60.307 + </jar>
60.308 + </presetdef>
60.309 + </target>
60.310 + <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"/>
60.311 + <!--
60.312 + ===================
60.313 + COMPILATION SECTION
60.314 + ===================
60.315 + -->
60.316 + <target depends="init" name="deps-jar" unless="no.deps"/>
60.317 + <target depends="init,deps-jar" name="-pre-pre-compile">
60.318 + <mkdir dir="${build.classes.dir}"/>
60.319 + </target>
60.320 + <target name="-pre-compile">
60.321 + <!-- Empty placeholder for easier customization. -->
60.322 + <!-- You can override this target in the ../build.xml file. -->
60.323 + </target>
60.324 + <target if="do.depend.true" name="-compile-depend">
60.325 + <j2seproject3:depend/>
60.326 + </target>
60.327 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
60.328 + <j2seproject3:javac/>
60.329 + <copy todir="${build.classes.dir}">
60.330 + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
60.331 + </copy>
60.332 + </target>
60.333 + <target name="-post-compile">
60.334 + <!-- Empty placeholder for easier customization. -->
60.335 + <!-- You can override this target in the ../build.xml file. -->
60.336 + </target>
60.337 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
60.338 + <target name="-pre-compile-single">
60.339 + <!-- Empty placeholder for easier customization. -->
60.340 + <!-- You can override this target in the ../build.xml file. -->
60.341 + </target>
60.342 + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
60.343 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
60.344 + <j2seproject3:force-recompile/>
60.345 + <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
60.346 + </target>
60.347 + <target name="-post-compile-single">
60.348 + <!-- Empty placeholder for easier customization. -->
60.349 + <!-- You can override this target in the ../build.xml file. -->
60.350 + </target>
60.351 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
60.352 + <!--
60.353 + ====================
60.354 + JAR BUILDING SECTION
60.355 + ====================
60.356 + -->
60.357 + <target depends="init" name="-pre-pre-jar">
60.358 + <dirname file="${dist.jar}" property="dist.jar.dir"/>
60.359 + <mkdir dir="${dist.jar.dir}"/>
60.360 + </target>
60.361 + <target name="-pre-jar">
60.362 + <!-- Empty placeholder for easier customization. -->
60.363 + <!-- You can override this target in the ../build.xml file. -->
60.364 + </target>
60.365 + <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
60.366 + <j2seproject1:jar/>
60.367 + </target>
60.368 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
60.369 + <j2seproject1:jar manifest="${manifest.file}"/>
60.370 + </target>
60.371 + <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">
60.372 + <j2seproject1:jar manifest="${manifest.file}">
60.373 + <j2seproject1:manifest>
60.374 + <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
60.375 + </j2seproject1:manifest>
60.376 + </j2seproject1:jar>
60.377 + <echo>To run this application from the command line without Ant, try:</echo>
60.378 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
60.379 + <property location="${dist.jar}" name="dist.jar.resolved"/>
60.380 + <pathconvert property="run.classpath.with.dist.jar">
60.381 + <path path="${run.classpath}"/>
60.382 + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
60.383 + </pathconvert>
60.384 + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
60.385 + </target>
60.386 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
60.387 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
60.388 + <pathconvert property="run.classpath.without.build.classes.dir">
60.389 + <path path="${run.classpath}"/>
60.390 + <map from="${build.classes.dir.resolved}" to=""/>
60.391 + </pathconvert>
60.392 + <pathconvert pathsep=" " property="jar.classpath">
60.393 + <path path="${run.classpath.without.build.classes.dir}"/>
60.394 + <chainedmapper>
60.395 + <flattenmapper/>
60.396 + <globmapper from="*" to="lib/*"/>
60.397 + </chainedmapper>
60.398 + </pathconvert>
60.399 + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
60.400 + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
60.401 + <fileset dir="${build.classes.dir}"/>
60.402 + <manifest>
60.403 + <attribute name="Main-Class" value="${main.class}"/>
60.404 + <attribute name="Class-Path" value="${jar.classpath}"/>
60.405 + </manifest>
60.406 + </copylibs>
60.407 + <echo>To run this application from the command line without Ant, try:</echo>
60.408 + <property location="${dist.jar}" name="dist.jar.resolved"/>
60.409 + <echo>java -jar "${dist.jar.resolved}"</echo>
60.410 + </target>
60.411 + <target name="-post-jar">
60.412 + <!-- Empty placeholder for easier customization. -->
60.413 + <!-- You can override this target in the ../build.xml file. -->
60.414 + </target>
60.415 + <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"/>
60.416 + <!--
60.417 + =================
60.418 + EXECUTION SECTION
60.419 + =================
60.420 + -->
60.421 + <target depends="init,compile" description="Run a main class." name="run">
60.422 + <j2seproject1:java>
60.423 + <customize>
60.424 + <arg line="${application.args}"/>
60.425 + </customize>
60.426 + </j2seproject1:java>
60.427 + </target>
60.428 + <target name="-do-not-recompile">
60.429 + <property name="javac.includes.binary" value=""/>
60.430 + </target>
60.431 + <target depends="init,-do-not-recompile,compile-single" name="run-single">
60.432 + <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
60.433 + <j2seproject1:java classname="${run.class}"/>
60.434 + </target>
60.435 + <!--
60.436 + =================
60.437 + DEBUGGING SECTION
60.438 + =================
60.439 + -->
60.440 + <target depends="init" if="netbeans.home" name="-debug-start-debugger">
60.441 + <j2seproject1:nbjpdastart name="${debug.class}"/>
60.442 + </target>
60.443 + <target depends="init,compile" name="-debug-start-debuggee">
60.444 + <j2seproject3:debug>
60.445 + <customize>
60.446 + <arg line="${application.args}"/>
60.447 + </customize>
60.448 + </j2seproject3:debug>
60.449 + </target>
60.450 + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
60.451 + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
60.452 + <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
60.453 + </target>
60.454 + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
60.455 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
60.456 + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
60.457 + <j2seproject3:debug classname="${debug.class}"/>
60.458 + </target>
60.459 + <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
60.460 + <target depends="init" name="-pre-debug-fix">
60.461 + <fail unless="fix.includes">Must set fix.includes</fail>
60.462 + <property name="javac.includes" value="${fix.includes}.java"/>
60.463 + </target>
60.464 + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
60.465 + <j2seproject1:nbjpdareload/>
60.466 + </target>
60.467 + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
60.468 + <!--
60.469 + ===============
60.470 + JAVADOC SECTION
60.471 + ===============
60.472 + -->
60.473 + <target depends="init" name="-javadoc-build">
60.474 + <mkdir dir="${dist.javadoc.dir}"/>
60.475 + <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}">
60.476 + <classpath>
60.477 + <path path="${javac.classpath}"/>
60.478 + </classpath>
60.479 + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
60.480 + <filename name="**/*.java"/>
60.481 + </fileset>
60.482 + </javadoc>
60.483 + </target>
60.484 + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
60.485 + <nbbrowse file="${dist.javadoc.dir}/index.html"/>
60.486 + </target>
60.487 + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
60.488 + <!--
60.489 + =========================
60.490 + JUNIT COMPILATION SECTION
60.491 + =========================
60.492 + -->
60.493 + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
60.494 + <mkdir dir="${build.test.classes.dir}"/>
60.495 + </target>
60.496 + <target name="-pre-compile-test">
60.497 + <!-- Empty placeholder for easier customization. -->
60.498 + <!-- You can override this target in the ../build.xml file. -->
60.499 + </target>
60.500 + <target if="do.depend.true" name="-compile-test-depend">
60.501 + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
60.502 + </target>
60.503 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
60.504 + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
60.505 + <copy todir="${build.test.classes.dir}">
60.506 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
60.507 + </copy>
60.508 + </target>
60.509 + <target name="-post-compile-test">
60.510 + <!-- Empty placeholder for easier customization. -->
60.511 + <!-- You can override this target in the ../build.xml file. -->
60.512 + </target>
60.513 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
60.514 + <target name="-pre-compile-test-single">
60.515 + <!-- Empty placeholder for easier customization. -->
60.516 + <!-- You can override this target in the ../build.xml file. -->
60.517 + </target>
60.518 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
60.519 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
60.520 + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
60.521 + <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}"/>
60.522 + <copy todir="${build.test.classes.dir}">
60.523 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
60.524 + </copy>
60.525 + </target>
60.526 + <target name="-post-compile-test-single">
60.527 + <!-- Empty placeholder for easier customization. -->
60.528 + <!-- You can override this target in the ../build.xml file. -->
60.529 + </target>
60.530 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
60.531 + <!--
60.532 + =======================
60.533 + JUNIT EXECUTION SECTION
60.534 + =======================
60.535 + -->
60.536 + <target depends="init" if="have.tests" name="-pre-test-run">
60.537 + <mkdir dir="${build.test.results.dir}"/>
60.538 + </target>
60.539 + <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
60.540 + <j2seproject3:junit testincludes="**/*Test.java"/>
60.541 + </target>
60.542 + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
60.543 + <fail if="tests.failed">Some tests failed; see details above.</fail>
60.544 + </target>
60.545 + <target depends="init" if="have.tests" name="test-report"/>
60.546 + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
60.547 + <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
60.548 + <target depends="init" if="have.tests" name="-pre-test-run-single">
60.549 + <mkdir dir="${build.test.results.dir}"/>
60.550 + </target>
60.551 + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
60.552 + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
60.553 + <j2seproject3:junit excludes="" includes="${test.includes}"/>
60.554 + </target>
60.555 + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
60.556 + <fail if="tests.failed">Some tests failed; see details above.</fail>
60.557 + </target>
60.558 + <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"/>
60.559 + <!--
60.560 + =======================
60.561 + JUNIT DEBUGGING SECTION
60.562 + =======================
60.563 + -->
60.564 + <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
60.565 + <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
60.566 + <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
60.567 + <delete file="${test.report.file}"/>
60.568 + <mkdir dir="${build.test.results.dir}"/>
60.569 + <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}">
60.570 + <customize>
60.571 + <syspropertyset>
60.572 + <propertyref prefix="test-sys-prop."/>
60.573 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
60.574 + </syspropertyset>
60.575 + <arg value="${test.class}"/>
60.576 + <arg value="showoutput=true"/>
60.577 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
60.578 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
60.579 + </customize>
60.580 + </j2seproject3:debug>
60.581 + </target>
60.582 + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
60.583 + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
60.584 + </target>
60.585 + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
60.586 + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
60.587 + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
60.588 + </target>
60.589 + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
60.590 + <!--
60.591 + =========================
60.592 + APPLET EXECUTION SECTION
60.593 + =========================
60.594 + -->
60.595 + <target depends="init,compile-single" name="run-applet">
60.596 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
60.597 + <j2seproject1:java classname="sun.applet.AppletViewer">
60.598 + <customize>
60.599 + <arg value="${applet.url}"/>
60.600 + </customize>
60.601 + </j2seproject1:java>
60.602 + </target>
60.603 + <!--
60.604 + =========================
60.605 + APPLET DEBUGGING SECTION
60.606 + =========================
60.607 + -->
60.608 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
60.609 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
60.610 + <j2seproject3:debug classname="sun.applet.AppletViewer">
60.611 + <customize>
60.612 + <arg value="${applet.url}"/>
60.613 + </customize>
60.614 + </j2seproject3:debug>
60.615 + </target>
60.616 + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
60.617 + <!--
60.618 + ===============
60.619 + CLEANUP SECTION
60.620 + ===============
60.621 + -->
60.622 + <target depends="init" name="deps-clean" unless="no.deps"/>
60.623 + <target depends="init" name="-do-clean">
60.624 + <delete dir="${build.dir}"/>
60.625 + <delete dir="${dist.dir}"/>
60.626 + </target>
60.627 + <target name="-post-clean">
60.628 + <!-- Empty placeholder for easier customization. -->
60.629 + <!-- You can override this target in the ../build.xml file. -->
60.630 + </target>
60.631 + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
60.632 +</project>
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/task3/solution11/nbproject/genfiles.properties Tue Oct 07 11:05:34 2008 +0200
61.3 @@ -0,0 +1,8 @@
61.4 +build.xml.data.CRC32=2ab820eb
61.5 +build.xml.script.CRC32=58a52595
61.6 +build.xml.stylesheet.CRC32=be360661
61.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
61.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
61.9 +nbproject/build-impl.xml.data.CRC32=0e1e702f
61.10 +nbproject/build-impl.xml.script.CRC32=c899f2cf
61.11 +nbproject/build-impl.xml.stylesheet.CRC32=487672f9
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/task3/solution11/nbproject/project.properties Tue Oct 07 11:05:34 2008 +0200
62.3 @@ -0,0 +1,68 @@
62.4 +application.title=currency
62.5 +application.vendor=apidesign.org
62.6 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
62.7 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
62.8 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
62.9 +build.classes.dir=${build.dir}/classes
62.10 +build.classes.excludes=**/*.java,**/*.form
62.11 +# This directory is removed when the project is cleaned:
62.12 +build.dir=build
62.13 +build.generated.dir=${build.dir}/generated
62.14 +# Only compile against the classpath explicitly listed here:
62.15 +build.sysclasspath=ignore
62.16 +build.test.classes.dir=${build.dir}/test/classes
62.17 +build.test.results.dir=${build.dir}/test/results
62.18 +debug.classpath=\
62.19 + ${run.classpath}
62.20 +debug.test.classpath=\
62.21 + ${run.test.classpath}
62.22 +# This directory is removed when the project is cleaned:
62.23 +dist.dir=dist
62.24 +dist.jar=${dist.dir}/currency.jar
62.25 +dist.javadoc.dir=${dist.dir}/javadoc
62.26 +excludes=
62.27 +file.reference.junit-4.4.jar=../../libs/junit-4.4.jar
62.28 +file.reference.src-apifest08=..
62.29 +includes=**
62.30 +jar.compress=false
62.31 +javac.classpath=
62.32 +# Space-separated list of extra javac options
62.33 +javac.compilerargs=-Xlint:unchecked
62.34 +javac.deprecation=false
62.35 +javac.source=1.5
62.36 +javac.target=1.5
62.37 +javac.test.classpath=\
62.38 + ${javac.classpath}:\
62.39 + ${build.classes.dir}:\
62.40 + ${file.reference.junit-4.4.jar}
62.41 +javadoc.additionalparam=
62.42 +javadoc.author=false
62.43 +javadoc.encoding=
62.44 +javadoc.noindex=false
62.45 +javadoc.nonavbar=false
62.46 +javadoc.notree=false
62.47 +javadoc.private=false
62.48 +javadoc.splitindex=true
62.49 +javadoc.use=true
62.50 +javadoc.version=false
62.51 +javadoc.windowtitle=
62.52 +jnlp.codebase.type=local
62.53 +jnlp.codebase.url=file:/home/jarda/src/apifest08/currency/dist
62.54 +jnlp.descriptor=application
62.55 +jnlp.enabled=false
62.56 +jnlp.offline-allowed=false
62.57 +jnlp.signed=false
62.58 +meta.inf.dir=${src.dir}/META-INF
62.59 +platform.active=default_platform
62.60 +run.classpath=\
62.61 + ${javac.classpath}:\
62.62 + ${build.classes.dir}
62.63 +# Space-separated list of JVM arguments used when running the project
62.64 +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
62.65 +# or test-sys-prop.name=value to set system properties for unit tests):
62.66 +run.jvmargs=
62.67 +run.test.classpath=\
62.68 + ${javac.test.classpath}:\
62.69 + ${build.test.classes.dir}
62.70 +src.dir=src
62.71 +test.src.dir=test
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/task3/solution11/nbproject/project.xml Tue Oct 07 11:05:34 2008 +0200
63.3 @@ -0,0 +1,16 @@
63.4 +<?xml version="1.0" encoding="UTF-8"?>
63.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
63.6 + <type>org.netbeans.modules.java.j2seproject</type>
63.7 + <configuration>
63.8 + <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
63.9 + <name>Currency Convertor Solution 11</name>
63.10 + <minimum-ant-version>1.6.5</minimum-ant-version>
63.11 + <source-roots>
63.12 + <root id="src.dir"/>
63.13 + </source-roots>
63.14 + <test-roots>
63.15 + <root id="test.src.dir"/>
63.16 + </test-roots>
63.17 + </data>
63.18 + </configuration>
63.19 +</project>
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/Computer.java Tue Oct 07 11:05:34 2008 +0200
64.3 @@ -0,0 +1,65 @@
64.4 +package org.apidesign.apifest08.currency;
64.5 +
64.6 +/**
64.7 + * Interface declaring method for computing conversion.
64.8 + *
64.9 + * Because of a vague definition of currency amount's type,
64.10 + * the interface has a generic type.
64.11 + *
64.12 + * @author ked
64.13 + * @see http://wiki.apidesign.org/wiki/APIDesignPatterns:ResponseReply
64.14 + */
64.15 +interface Computer<AmountType> {
64.16 +
64.17 + ComputerResponse<AmountType> compute(ComputerRequest<AmountType> request);
64.18 +
64.19 + /**
64.20 + *
64.21 + * @param <AmountType>
64.22 + */
64.23 + final class ComputerRequest<AmountType> {
64.24 +
64.25 + private AmountType input;
64.26 + private AmountType inputCurrencyRatio;
64.27 + private AmountType outputCurrencyRatio;
64.28 +
64.29 + AmountType getInput() {
64.30 + return input;
64.31 + }
64.32 +
64.33 + void setInput(AmountType input) {
64.34 + this.input = input;
64.35 + }
64.36 +
64.37 + AmountType getInputCurrencyRatio() {
64.38 + return inputCurrencyRatio;
64.39 + }
64.40 +
64.41 + void setInputCurrencyRatio(AmountType inputCurrencyRatio) {
64.42 + this.inputCurrencyRatio = inputCurrencyRatio;
64.43 + }
64.44 +
64.45 + AmountType getOutputCurrencyRatio() {
64.46 + return outputCurrencyRatio;
64.47 + }
64.48 +
64.49 + void setOutputCurrencyRatio(AmountType outputCurrencyRatio) {
64.50 + this.outputCurrencyRatio = outputCurrencyRatio;
64.51 + }
64.52 + }
64.53 +
64.54 + final class ComputerResponse<AmountType> {
64.55 +
64.56 + private AmountType result;
64.57 +
64.58 + AmountType getResult() {
64.59 + return result;
64.60 + }
64.61 +
64.62 + void setResult(AmountType result) {
64.63 + this.result = result;
64.64 + }
64.65 + }
64.66 +
64.67 +
64.68 +}
64.69 \ No newline at end of file
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 11:05:34 2008 +0200
65.3 @@ -0,0 +1,228 @@
65.4 +package org.apidesign.apifest08.currency;
65.5 +
65.6 +import java.util.ArrayList;
65.7 +import java.util.Collection;
65.8 +import java.util.HashSet;
65.9 +import java.util.List;
65.10 +import java.util.Set;
65.11 +import org.apidesign.apifest08.currency.Computer.ComputerRequest;
65.12 +import org.apidesign.apifest08.currency.Computer.ComputerResponse;
65.13 +
65.14 +/**
65.15 + * Convertor.
65.16 + *
65.17 + * In Task 1's version provides conversion between currency values
65.18 + * with amount stored in integer or double, that are identified
65.19 + * with string value. Exchange rates are immutable.
65.20 + *
65.21 + * In Task2's version provides support for multiple exchange rates
65.22 + * between different currencies & merging exchange rates from
65.23 + * existing convertors into new convertor's instance.
65.24 + * No time for javadoc these features, sorry.
65.25 + *
65.26 + * @author ked
65.27 + */
65.28 +public final class Convertor<AmountType, IdentifierType> {
65.29 +
65.30 + Computer<AmountType> computer;
65.31 + List<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates = new ArrayList<ExchangeRateValue<AmountType, IdentifierType>>();
65.32 +
65.33 + Convertor(
65.34 + Computer<AmountType> computer,
65.35 + Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates) {
65.36 + this.computer = computer;
65.37 +
65.38 + for (ExchangeRateValue<AmountType, IdentifierType> exchangeRate : exchangeRates) {
65.39 + if (findExchangeRate(
65.40 + this.exchangeRates,
65.41 + exchangeRate.getCurrencyA().getIdentifier(),
65.42 + exchangeRate.getCurrencyB().getIdentifier()) != null) {
65.43 + throw new IllegalArgumentException("Duplicate exchange rate!");
65.44 + }
65.45 + this.exchangeRates.add(exchangeRate);
65.46 + }
65.47 + }
65.48 +
65.49 + private ExchangeRateValue<AmountType, IdentifierType> findExchangeRate(
65.50 + Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates,
65.51 + IdentifierType currencyA,
65.52 + IdentifierType currencyB) {
65.53 + for (ExchangeRateValue<AmountType, IdentifierType> exchangeRate : exchangeRates) {
65.54 + if ((exchangeRate.getCurrencyA().getIdentifier().equals(currencyA) && exchangeRate.getCurrencyB().getIdentifier().equals(currencyB)) ||
65.55 + (exchangeRate.getCurrencyA().getIdentifier().equals(currencyB) && exchangeRate.getCurrencyB().getIdentifier().equals(currencyA))) {
65.56 + return exchangeRate;
65.57 + }
65.58 + }
65.59 + return null;
65.60 + }
65.61 +
65.62 + /**
65.63 + * Convert an amount of the one currency to an amount of the another one currency
65.64 + * with respect to previously specified exchange rates.
65.65 + *
65.66 + * @param targetCurrency an identifier of the requested currency
65.67 + * @param currencyValue an amount of the another one currency
65.68 + * @return an amount of the requested currency
65.69 + */
65.70 + public CurrencyValue<AmountType, IdentifierType> convert(
65.71 + IdentifierType targetCurrency,
65.72 + CurrencyValue<AmountType, IdentifierType> currencyValue) {
65.73 + ExchangeRateValue<AmountType, IdentifierType> exchangeRate =
65.74 + findExchangeRate(exchangeRates, currencyValue.getIdentifier(), targetCurrency);
65.75 + if (exchangeRate == null) {
65.76 + throw new IllegalArgumentException("Inappropriate currencies to convert!");
65.77 + }
65.78 +
65.79 + ComputerRequest<AmountType> computerRequest = new ComputerRequest<AmountType>();
65.80 + computerRequest.setInput(currencyValue.getAmount());
65.81 +
65.82 + IdentifierType targetCurrencyRef; // just for backward compatibility :-(
65.83 + if (exchangeRate.getCurrencyA().getIdentifier().equals(targetCurrency)) {
65.84 + computerRequest.setInputCurrencyRatio(exchangeRate.getCurrencyB().getAmount());
65.85 + computerRequest.setOutputCurrencyRatio(exchangeRate.getCurrencyA().getAmount());
65.86 + targetCurrencyRef = exchangeRate.getCurrencyA().getIdentifier();
65.87 + } else {
65.88 + computerRequest.setInputCurrencyRatio(exchangeRate.getCurrencyA().getAmount());
65.89 + computerRequest.setOutputCurrencyRatio(exchangeRate.getCurrencyB().getAmount());
65.90 + targetCurrencyRef = exchangeRate.getCurrencyB().getIdentifier();
65.91 + }
65.92 +
65.93 + ComputerResponse<AmountType> computerResponse = computer.compute(computerRequest);
65.94 + return CurrencyValue.getCurrencyValue(
65.95 + computerResponse.getResult(),
65.96 + targetCurrencyRef);
65.97 + }
65.98 +
65.99 + // ---
65.100 + // MERGING
65.101 + // ---
65.102 + static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> mergeConvertors(
65.103 + Computer<AmountType> computer,
65.104 + Collection<Convertor<AmountType, IdentifierType>> convertors) {
65.105 + Set<ExchangeRateValue<AmountType, IdentifierType>> exchangeRatesSet = new HashSet<ExchangeRateValue<AmountType, IdentifierType>>();
65.106 + for (Convertor<AmountType, IdentifierType> convertor : convertors) {
65.107 + exchangeRatesSet.addAll(convertor.exchangeRates);
65.108 + }
65.109 + return getConvertor(computer, exchangeRatesSet);
65.110 + }
65.111 +
65.112 + static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> mergeConvertors(
65.113 + Computer<AmountType> computer,
65.114 + Convertor<AmountType, IdentifierType> convertorA,
65.115 + Convertor<AmountType, IdentifierType> convertorB) {
65.116 + Collection<Convertor<AmountType, IdentifierType>> convertors =
65.117 + new ArrayList<Convertor<AmountType, IdentifierType>>();
65.118 + convertors.add(convertorA);
65.119 + convertors.add(convertorB);
65.120 + return mergeConvertors(computer, convertors);
65.121 + }
65.122 +
65.123 + public static Convertor<Double, String> mergeConvertorsDoubleString(
65.124 + Collection<Convertor<Double, String>> convertors) {
65.125 + return mergeConvertors(DoubleComputer, convertors);
65.126 + }
65.127 +
65.128 + public static Convertor<Double, String> mergeConvertorsDoubleString(
65.129 + Convertor<Double, String> convertorA,
65.130 + Convertor<Double, String> convertorB) {
65.131 + return mergeConvertors(DoubleComputer, convertorA, convertorB);
65.132 + }
65.133 +
65.134 + public static Convertor<Integer, String> mergeConvertorsIntegerString(
65.135 + Collection<Convertor<Integer, String>> convertors) {
65.136 + return mergeConvertors(IntegerComputer, convertors);
65.137 + }
65.138 +
65.139 + public static Convertor<Integer, String> mergeConvertorsIntegerString(
65.140 + Convertor<Integer, String> convertorA,
65.141 + Convertor<Integer, String> convertorB) {
65.142 + return mergeConvertors(IntegerComputer, convertorA, convertorB);
65.143 + }
65.144 +
65.145 + // ---
65.146 + // CREATION
65.147 + // ---
65.148 + static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertor(
65.149 + Computer<AmountType> computer, Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates) {
65.150 + return new Convertor<AmountType, IdentifierType>(computer, exchangeRates);
65.151 + }
65.152 +
65.153 + static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertor(
65.154 + Computer<AmountType> computer, ExchangeRateValue<AmountType, IdentifierType> exchangeRate) {
65.155 + Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates =
65.156 + new ArrayList<ExchangeRateValue<AmountType, IdentifierType>>();
65.157 + exchangeRates.add(exchangeRate);
65.158 + return getConvertor(computer, exchangeRates);
65.159 + }
65.160 +
65.161 + public static Convertor<Double, String> getConvertorDoubleString(
65.162 + Collection<ExchangeRateValue<Double, String>> exchangeRates) {
65.163 + return getConvertor(DoubleComputer, exchangeRates);
65.164 + }
65.165 +
65.166 + public static Convertor<Double, String> getConvertorDoubleString(
65.167 + ExchangeRateValue<Double, String> exchangeRate) {
65.168 + return getConvertor(DoubleComputer, exchangeRate);
65.169 + }
65.170 +
65.171 + public static Convertor<Integer, String> getConvertorIntegerString(
65.172 + Collection<ExchangeRateValue<Integer, String>> exchangeRates) {
65.173 + return getConvertor(IntegerComputer, exchangeRates);
65.174 + }
65.175 +
65.176 + public static Convertor<Integer, String> getConvertorIntegerString(
65.177 + ExchangeRateValue<Integer, String> exchangeRate) {
65.178 + return getConvertor(IntegerComputer, exchangeRate);
65.179 + }
65.180 +
65.181 + // ---
65.182 + // BACKWARD COMPATIBILITY - CREATION
65.183 + // ---
65.184 + /**
65.185 + * Creates convertor for Double|String values with specified exchange rate
65.186 + * between two currencies.
65.187 + *
65.188 + * @param firstCurrencyExchangeRate first currency
65.189 + * @param secondCurrencyExchangeRate second currency
65.190 + * @return convertor
65.191 + */
65.192 + public static Convertor<Double, String> getConvertorDoubleString(
65.193 + CurrencyValue<Double, String> firstCurrencyExchangeRate,
65.194 + CurrencyValue<Double, String> secondCurrencyExchangeRate) {
65.195 + return getConvertorDoubleString(ExchangeRateValue.getExchangeRate(firstCurrencyExchangeRate, secondCurrencyExchangeRate));
65.196 + }
65.197 +
65.198 + /**
65.199 + * Creates convertor for Integer|String values with specified exchange rate
65.200 + * between two currencies.
65.201 + *
65.202 + * @param firstCurrencyExchangeRate first currency
65.203 + * @param secondCurrencyExchangeRate second currency
65.204 + * @return convertor
65.205 + */
65.206 + public static Convertor<Integer, String> getConvertorIntegerString(
65.207 + CurrencyValue<Integer, String> firstCurrencyExchangeRate,
65.208 + CurrencyValue<Integer, String> secondCurrencyExchangeRate) {
65.209 + return getConvertorIntegerString(ExchangeRateValue.getExchangeRate(firstCurrencyExchangeRate, secondCurrencyExchangeRate));
65.210 + }
65.211 +
65.212 + // ---
65.213 + // COMPUTERS
65.214 + // ---
65.215 + static final Computer<Double> DoubleComputer = new Computer<Double>() {
65.216 +
65.217 + public ComputerResponse<Double> compute(ComputerRequest<Double> request) {
65.218 + ComputerResponse<Double> response = new ComputerResponse<Double>();
65.219 + response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
65.220 + return response;
65.221 + }
65.222 + };
65.223 + static final Computer<Integer> IntegerComputer = new Computer<Integer>() {
65.224 +
65.225 + public ComputerResponse<Integer> compute(ComputerRequest<Integer> request) {
65.226 + ComputerResponse<Integer> response = new ComputerResponse<Integer>();
65.227 + response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
65.228 + return response;
65.229 + }
65.230 + };
65.231 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/CurrencyValue.java Tue Oct 07 11:05:34 2008 +0200
66.3 @@ -0,0 +1,72 @@
66.4 +package org.apidesign.apifest08.currency;
66.5 +
66.6 +import java.io.Serializable;
66.7 +
66.8 +/**
66.9 + * Value class, holding an amount of the currency & an identifier of the currency.
66.10 + * Designed to be an immutable.
66.11 + *
66.12 + * Because of a vague definition of types of the both fields,
66.13 + * the class has generic types, used as types of the fields.
66.14 + * These types should be immutable classes, too.
66.15 + *
66.16 + * @author ked
66.17 + */
66.18 +public final class CurrencyValue<AmountType, IdentifierType> implements Serializable {
66.19 +
66.20 + private final AmountType amount;
66.21 + private final IdentifierType identifier;
66.22 +
66.23 + private CurrencyValue(AmountType amount, IdentifierType identifier) {
66.24 + this.amount = amount;
66.25 + this.identifier = identifier;
66.26 + }
66.27 +
66.28 + public AmountType getAmount() {
66.29 + return amount;
66.30 + }
66.31 +
66.32 + public IdentifierType getIdentifier() {
66.33 + return identifier;
66.34 + }
66.35 +
66.36 + @Override
66.37 + public boolean equals(Object obj) {
66.38 + if (obj == null) {
66.39 + return false;
66.40 + }
66.41 + if (getClass() != obj.getClass()) {
66.42 + return false;
66.43 + }
66.44 + final CurrencyValue other = (CurrencyValue) obj;
66.45 + if (this.amount != other.amount && (this.amount == null || !this.amount.equals(other.amount))) {
66.46 + return false;
66.47 + }
66.48 + if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) {
66.49 + return false;
66.50 + }
66.51 + return true;
66.52 + }
66.53 +
66.54 + @Override
66.55 + public int hashCode() {
66.56 + int hash = 7;
66.57 + hash = 97 * hash + (this.amount != null ? this.amount.hashCode() : 0);
66.58 + hash = 97 * hash + (this.identifier != null ? this.identifier.hashCode() : 0);
66.59 + return hash;
66.60 + }
66.61 +
66.62 + /**
66.63 + * Creates new instance.
66.64 + * Generic types of the new instance are derived from types of the parameters.
66.65 + *
66.66 + * @param <AmountType> type of the currency amount
66.67 + * @param <IdentifierType> type of the currency identifier
66.68 + * @param amount currency amount
66.69 + * @param identifier currency identifier
66.70 + * @return new instance
66.71 + */
66.72 + public static <AmountType, IdentifierType> CurrencyValue<AmountType, IdentifierType> getCurrencyValue(AmountType amount, IdentifierType identifier) {
66.73 + return new CurrencyValue<AmountType, IdentifierType>(amount, identifier);
66.74 + }
66.75 +}
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/ExchangeRateValue.java Tue Oct 07 11:05:34 2008 +0200
67.3 @@ -0,0 +1,78 @@
67.4 +package org.apidesign.apifest08.currency;
67.5 +
67.6 +import java.io.Serializable;
67.7 +
67.8 +/**
67.9 + * Value class, holding an exchange rate between two currencies.
67.10 + * Designed to be an immutable.
67.11 + *
67.12 + * @author ked
67.13 + */
67.14 +public final class ExchangeRateValue<AmountType, IdentifierType> implements Serializable {
67.15 +
67.16 + private final CurrencyValue<AmountType, IdentifierType> currencyA;
67.17 + private final CurrencyValue<AmountType, IdentifierType> currencyB;
67.18 +
67.19 + private ExchangeRateValue(
67.20 + CurrencyValue<AmountType, IdentifierType> currencyA,
67.21 + CurrencyValue<AmountType, IdentifierType> currencyB) {
67.22 + if (currencyA.getIdentifier() == null ||
67.23 + currencyB.getIdentifier() == null ||
67.24 + currencyA.getIdentifier().equals(currencyB)) {
67.25 + throw new IllegalArgumentException("Inappropriate exchange rates' identifiers!");
67.26 + }
67.27 +
67.28 + this.currencyA = currencyA;
67.29 + this.currencyB = currencyB;
67.30 + }
67.31 +
67.32 + public CurrencyValue<AmountType, IdentifierType> getCurrencyA() {
67.33 + return currencyA;
67.34 + }
67.35 +
67.36 + public CurrencyValue<AmountType, IdentifierType> getCurrencyB() {
67.37 + return currencyB;
67.38 + }
67.39 +
67.40 + @Override
67.41 + public boolean equals(Object obj) {
67.42 + if (obj == null) {
67.43 + return false;
67.44 + }
67.45 + if (getClass() != obj.getClass()) {
67.46 + return false;
67.47 + }
67.48 + final ExchangeRateValue other = (ExchangeRateValue) obj;
67.49 + if (this.currencyA != other.currencyA && (this.currencyA == null || !this.currencyA.equals(other.currencyA))) {
67.50 + return false;
67.51 + }
67.52 + if (this.currencyB != other.currencyB && (this.currencyB == null || !this.currencyB.equals(other.currencyB))) {
67.53 + return false;
67.54 + }
67.55 + return true;
67.56 + }
67.57 +
67.58 + @Override
67.59 + public int hashCode() {
67.60 + int hash = 3;
67.61 + hash = 71 * hash + (this.currencyA != null ? this.currencyA.hashCode() : 0);
67.62 + hash = 71 * hash + (this.currencyB != null ? this.currencyB.hashCode() : 0);
67.63 + return hash;
67.64 + }
67.65 +
67.66 + /**
67.67 + * Creates new instance.
67.68 + * Generic types of the new instance are derived from types of the parameters.
67.69 + *
67.70 + * @param <AmountType> type of the currency amount
67.71 + * @param <IdentifierType> type of the currency identifier
67.72 + * @param currencyA one currency of the exchange rate
67.73 + * @param currencyB another currency of the exchange rate
67.74 + * @return new instance
67.75 + */
67.76 + public static <AmountType, IdentifierType> ExchangeRateValue<AmountType, IdentifierType> getExchangeRate(
67.77 + CurrencyValue<AmountType, IdentifierType> currencyA,
67.78 + CurrencyValue<AmountType, IdentifierType> currencyB) {
67.79 + return new ExchangeRateValue<AmountType, IdentifierType>(currencyA, currencyB);
67.80 + }
67.81 +}
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/task3/solution11/test/org/apidesign/apifest08/test/Task1Test.java Tue Oct 07 11:05:34 2008 +0200
68.3 @@ -0,0 +1,161 @@
68.4 +package org.apidesign.apifest08.test;
68.5 +
68.6 +import junit.framework.TestCase;
68.7 +import org.apidesign.apifest08.currency.Convertor;
68.8 +import org.apidesign.apifest08.currency.CurrencyValue;
68.9 +
68.10 +/** Finish the Convertor API, and then write bodies of methods inside
68.11 + * of this class to match the given tasks. To fullfil your task, use the
68.12 + * API define in the <code>org.apidesign.apifest08.currency</code> package.
68.13 + * Do not you reflection, or other hacks as your code
68.14 + * shall run without any runtime permissions.
68.15 + */
68.16 +public class Task1Test extends TestCase {
68.17 + public Task1Test(String testName) {
68.18 + super(testName);
68.19 + }
68.20 +
68.21 + @Override
68.22 + protected void setUp() throws Exception {
68.23 + }
68.24 +
68.25 + @Override
68.26 + protected void tearDown() throws Exception {
68.27 + }
68.28 +
68.29 + //
68.30 + // Imagine that there are three parts of the whole system:
68.31 + // 1. there is someone who knows the current exchange rate
68.32 + // 2. there is someone who wants to do the conversion
68.33 + // 3. there is the API between 1. and 2. which allows them to communicate
68.34 + // Please design such API
68.35 + //
68.36 +
68.37 + /** Create convertor that understands two currencies, CZK and
68.38 + * USD. Make 1 USD == 17 CZK. This is a method provided for #1 group -
68.39 + * e.g. those that know the exchange rate. They somehow need to create
68.40 + * the objects from the API and tell them the exchange rate. The API itself
68.41 + * knows nothing about any rates, before the createCZKtoUSD method is called.
68.42 + *
68.43 + * Creation of the convertor shall not require subclassing of any class
68.44 + * or interface on the client side.
68.45 + *
68.46 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
68.47 + */
68.48 + public static Convertor<Integer, String> createCZKtoUSD() {
68.49 + return Convertor.getConvertorIntegerString(
68.50 + CurrencyValue.getCurrencyValue(1, "USD"),
68.51 + CurrencyValue.getCurrencyValue(17, "CZK")
68.52 + );
68.53 + }
68.54 +
68.55 + /** Create convertor that understands two currencies, CZK and
68.56 + * SKK. Make 100 SKK == 80 CZK. Again this is method for the #1 group -
68.57 + * it knows the exchange rate, and needs to use the API to create objects
68.58 + * with the exchange rate. Anyone shall be ready to call this method without
68.59 + * any other method being called previously. The API itself shall know
68.60 + * nothing about any rates, before this method is called.
68.61 + *
68.62 + * Creation of the convertor shall not require subclassing of any class
68.63 + * or interface on the client side.
68.64 + *
68.65 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
68.66 + */
68.67 + public static Convertor<Integer, String> createSKKtoCZK() {
68.68 + return Convertor.getConvertorIntegerString(
68.69 + CurrencyValue.getCurrencyValue(100, "SKK"),
68.70 + CurrencyValue.getCurrencyValue(80, "CZK")
68.71 + );
68.72 + }
68.73 +
68.74 + //
68.75 + // now the methods for group #2 follow:
68.76 + // this group knows nothing about exchange rates, but knows how to use
68.77 + // the API to do conversions. It somehow (by calling one of the factory
68.78 + // methods) gets objects from the API and uses them to do the conversions.
68.79 + //
68.80 +
68.81 + /** Use the convertor from <code>createCZKtoUSD</code> method and do few conversions
68.82 + * with it.
68.83 + */
68.84 + public void testCurrencyCZKUSD() throws Exception {
68.85 + Convertor<Integer, String> c = createCZKtoUSD();
68.86 +
68.87 + CurrencyValue<Integer, String> result;
68.88 +
68.89 + // convert $5 to CZK using c:
68.90 + // assertEquals("Result is 85 CZK");
68.91 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(5, "USD"));
68.92 + assertEquals(CurrencyValue.getCurrencyValue(85, "CZK"), result);
68.93 +
68.94 + // convert $8 to CZK
68.95 + // assertEquals("Result is 136 CZK");
68.96 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(8, "USD"));
68.97 + assertEquals(CurrencyValue.getCurrencyValue(136, "CZK"), result);
68.98 +
68.99 + // convert 1003CZK to USD
68.100 + // assertEquals("Result is 59 USD");
68.101 + result = c.convert("USD", CurrencyValue.getCurrencyValue(1003, "CZK"));
68.102 + assertEquals(CurrencyValue.getCurrencyValue(59, "USD"), result);
68.103 + }
68.104 +
68.105 + /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
68.106 + * with it.
68.107 + */
68.108 + public void testCurrencySKKCZK() throws Exception {
68.109 + Convertor<Integer, String> c = createSKKtoCZK();
68.110 +
68.111 + CurrencyValue<Integer, String> result;
68.112 +
68.113 + // convert 16CZK using c:
68.114 + // assertEquals("Result is 20 SKK");
68.115 + result = c.convert("SKK", CurrencyValue.getCurrencyValue(16, "CZK"));
68.116 + assertEquals(CurrencyValue.getCurrencyValue(20, "SKK"), result);
68.117 +
68.118 + // convert 500SKK to CZK
68.119 + // assertEquals("Result is 400 CZK");
68.120 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(500, "SKK"));
68.121 + assertEquals(CurrencyValue.getCurrencyValue(400, "CZK"), result);
68.122 + }
68.123 +
68.124 + /** Verify that the CZK to USD convertor knows nothing about SKK.
68.125 + */
68.126 + public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
68.127 + Convertor<Integer, String> c = createCZKtoUSD();
68.128 + try {
68.129 + // convert $5 to SKK, the API shall say this is not possible
68.130 + c.convert("SKK", CurrencyValue.getCurrencyValue(16, "CZK"));
68.131 + assertTrue("Should not convert", false);
68.132 + } catch (Exception e) {
68.133 + assertTrue(true);
68.134 + }
68.135 + try {
68.136 + // convert 500 SKK to CZK, the API shall say this is not possible
68.137 + c.convert("CZK", CurrencyValue.getCurrencyValue(500, "SKK"));
68.138 + assertTrue("Should not convert", false);
68.139 + } catch (Exception e) {
68.140 + assertTrue(true);
68.141 + }
68.142 +
68.143 + }
68.144 +
68.145 + /** Verify that the CZK to SKK convertor knows nothing about USD.
68.146 + */
68.147 + public void testCannotConvertToUSDwithSKKCZKConvertor() throws Exception {
68.148 + Convertor<Integer, String> c = createSKKtoCZK();
68.149 + try {
68.150 + // convert $5 to SKK, the API shall say this is not possible
68.151 + c.convert("SKK", CurrencyValue.getCurrencyValue(5, "USD"));
68.152 + assertTrue("Should not convert", false);
68.153 + } catch (Exception e) {
68.154 + assertTrue(true);
68.155 + }
68.156 + try {
68.157 + // convert 500 CZK to USD, the API shall say this is not possible
68.158 + c.convert("USD", CurrencyValue.getCurrencyValue(500, "CZK"));
68.159 + assertTrue("Should not convert", false);
68.160 + } catch (Exception e) {
68.161 + assertTrue(true);
68.162 + }
68.163 + }
68.164 +}
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/task3/solution11/test/org/apidesign/apifest08/test/Task2Test.java Tue Oct 07 11:05:34 2008 +0200
69.3 @@ -0,0 +1,140 @@
69.4 +package org.apidesign.apifest08.test;
69.5 +
69.6 +import java.util.ArrayList;
69.7 +import java.util.Collection;
69.8 +import junit.framework.TestCase;
69.9 +import org.apidesign.apifest08.currency.Convertor;
69.10 +import org.apidesign.apifest08.currency.CurrencyValue;
69.11 +import org.apidesign.apifest08.currency.ExchangeRateValue;
69.12 +
69.13 +/** There are many currencies around the world and many banks manipulate
69.14 + * with more than one or two at the same time. As banks are usually the
69.15 + * best paying clients, which is true even in case of your Convertor API,
69.16 + * it is reasonable to listen to their requests.
69.17 + * <p>
69.18 + * The quest for today is to enhance your existing convertor API to hold
69.19 + * information about many currencies and allow conversions between any of them.
69.20 + * Also, as conversion rates for diferent currencies usually arise from various
69.21 + * bank departments, there is another important need. There is a need to
69.22 + * compose two convertors into one by merging all the information about
69.23 + * currencies they know about.
69.24 + */
69.25 +public class Task2Test extends TestCase {
69.26 +
69.27 + public Task2Test(String testName) {
69.28 + super(testName);
69.29 + }
69.30 +
69.31 + @Override
69.32 + protected void setUp() throws Exception {
69.33 + }
69.34 +
69.35 + @Override
69.36 + protected void tearDown() throws Exception {
69.37 + }
69.38 +
69.39 + // As in Task1Test, keep in mind, that there are three parts
69.40 + // of the whole system:
69.41 + // 1. there is someone who knows the current exchange rate
69.42 + // 2. there is someone who wants to do the conversion
69.43 + // 3. there is the API between 1. and 2. which allows them to communicate
69.44 + //
69.45 + // Please backward compatibly enhance your existing API to support following
69.46 + // usecases:
69.47 + //
69.48 + /** Create convertor that understands two currencies, CZK and
69.49 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
69.50 + * knows the exchange rate, and needs to use the API to create objects
69.51 + * with the exchange rate. Anyone shall be ready to call this method without
69.52 + * any other method being called previously. The API itself shall know
69.53 + * nothing about any rates, before this method is called.
69.54 + */
69.55 + public static Convertor<Integer, String> createTripleConvertor() {
69.56 + // Rates: 1USD = 15CZK
69.57 + // Rates: 1USD = 20SKK
69.58 + // Rates: 75CZK = 100SKK
69.59 + Collection<ExchangeRateValue<Integer, String>> exchangeRates =
69.60 + new ArrayList<ExchangeRateValue<Integer, String>>();
69.61 + exchangeRates.add(ExchangeRateValue.getExchangeRate(
69.62 + CurrencyValue.getCurrencyValue(1, "USD"),
69.63 + CurrencyValue.getCurrencyValue(15, "CZK")));
69.64 + exchangeRates.add(ExchangeRateValue.getExchangeRate(
69.65 + CurrencyValue.getCurrencyValue(1, "USD"),
69.66 + CurrencyValue.getCurrencyValue(20, "SKK")));
69.67 + exchangeRates.add(ExchangeRateValue.getExchangeRate(
69.68 + CurrencyValue.getCurrencyValue(75, "CZK"),
69.69 + CurrencyValue.getCurrencyValue(100, "SKK")));
69.70 + return Convertor.getConvertorIntegerString(exchangeRates);
69.71 + }
69.72 +
69.73 + /** Define convertor that understands three currencies. Use it.
69.74 + */
69.75 + public void testConvertorForUSDandCZKandSKK() throws Exception {
69.76 + Convertor<Integer, String> c = createTripleConvertor();
69.77 +
69.78 + CurrencyValue<Integer, String> result;
69.79 + // convert $5 to CZK using c:
69.80 + // assertEquals("Result is 75 CZK");
69.81 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(5, "USD"));
69.82 + assertEquals(CurrencyValue.getCurrencyValue(75, "CZK"), result);
69.83 +
69.84 + // convert $5 to SKK using c:
69.85 + // assertEquals("Result is 100 SKK");
69.86 + result = c.convert("SKK", CurrencyValue.getCurrencyValue(5, "USD"));
69.87 + assertEquals(CurrencyValue.getCurrencyValue(100, "SKK"), result);
69.88 +
69.89 + // convert 200SKK to CZK using c:
69.90 + // assertEquals("Result is 150 CZK");
69.91 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(200, "SKK"));
69.92 + assertEquals(CurrencyValue.getCurrencyValue(150, "CZK"), result);
69.93 +
69.94 + // convert 200SKK to USK using c:
69.95 + // assertEquals("Result is 10 USD");
69.96 + result = c.convert("USD", CurrencyValue.getCurrencyValue(200, "SKK"));
69.97 + assertEquals(CurrencyValue.getCurrencyValue(10, "USD"), result);
69.98 + }
69.99 +
69.100 + /** Merge all currency rates of convertor 1 with convertor 2.
69.101 + * Implement this using your API, preferably this method just delegates
69.102 + * into some API method which does the actual work, without requiring
69.103 + * API clients to code anything complex.
69.104 + */
69.105 + public static Convertor<Integer, String> merge(Convertor<Integer, String> one, Convertor<Integer, String> two) {
69.106 + return Convertor.mergeConvertorsIntegerString(one, two);
69.107 + }
69.108 +
69.109 + /** Join the convertors from previous task, Task1Test and show that it
69.110 + * can be used to do reasonable conversions.
69.111 + */
69.112 + public void testConvertorComposition() throws Exception {
69.113 + Convertor<Integer, String> c = merge(
69.114 + Task1Test.createCZKtoUSD(),
69.115 + Task1Test.createSKKtoCZK());
69.116 +
69.117 + CurrencyValue<Integer, String> result;
69.118 + // convert $5 to CZK using c:
69.119 + // assertEquals("Result is 85 CZK");
69.120 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(5, "USD"));
69.121 + assertEquals(CurrencyValue.getCurrencyValue(85, "CZK"), result);
69.122 +
69.123 + // convert $8 to CZK using c:
69.124 + // assertEquals("Result is 136 CZK");
69.125 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(8, "USD"));
69.126 + assertEquals(CurrencyValue.getCurrencyValue(136, "CZK"), result);
69.127 +
69.128 + // convert 1003CZK to USD using c:
69.129 + // assertEquals("Result is 59 USD");
69.130 + result = c.convert("USD", CurrencyValue.getCurrencyValue(1003, "CZK"));
69.131 + assertEquals(CurrencyValue.getCurrencyValue(59, "USD"), result);
69.132 +
69.133 + // convert 16CZK using c:
69.134 + // assertEquals("Result is 20 SKK");
69.135 + result = c.convert("SKK", CurrencyValue.getCurrencyValue(16, "CZK"));
69.136 + assertEquals(CurrencyValue.getCurrencyValue(20, "SKK"), result);
69.137 +
69.138 + // convert 500SKK to CZK using c:
69.139 + // assertEquals("Result is 400 CZK");
69.140 + result = c.convert("CZK", CurrencyValue.getCurrencyValue(500, "SKK"));
69.141 + assertEquals(CurrencyValue.getCurrencyValue(400, "CZK"), result);
69.142 + }
69.143 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/task3/solution12/build.xml Tue Oct 07 11:05:34 2008 +0200
70.3 @@ -0,0 +1,69 @@
70.4 +<?xml version="1.0" encoding="UTF-8"?>
70.5 +<!-- You may freely edit this file. See commented blocks below for -->
70.6 +<!-- some examples of how to customize the build. -->
70.7 +<!-- (If you delete it and reopen the project it will be recreated.) -->
70.8 +<project name="currency" default="default" basedir=".">
70.9 + <description>Builds, tests, and runs the project.</description>
70.10 + <import file="nbproject/build-impl.xml"/>
70.11 + <!--
70.12 +
70.13 + There exist several targets which are by default empty and which can be
70.14 + used for execution of your tasks. These targets are usually executed
70.15 + before and after some main targets. They are:
70.16 +
70.17 + -pre-init: called before initialization of project properties
70.18 + -post-init: called after initialization of project properties
70.19 + -pre-compile: called before javac compilation
70.20 + -post-compile: called after javac compilation
70.21 + -pre-compile-single: called before javac compilation of single file
70.22 + -post-compile-single: called after javac compilation of single file
70.23 + -pre-compile-test: called before javac compilation of JUnit tests
70.24 + -post-compile-test: called after javac compilation of JUnit tests
70.25 + -pre-compile-test-single: called before javac compilation of single JUnit test
70.26 + -post-compile-test-single: called after javac compilation of single JUunit test
70.27 + -pre-jar: called before JAR building
70.28 + -post-jar: called after JAR building
70.29 + -post-clean: called after cleaning build products
70.30 +
70.31 + (Targets beginning with '-' are not intended to be called on their own.)
70.32 +
70.33 + Example of inserting an obfuscator after compilation could look like this:
70.34 +
70.35 + <target name="-post-compile">
70.36 + <obfuscate>
70.37 + <fileset dir="${build.classes.dir}"/>
70.38 + </obfuscate>
70.39 + </target>
70.40 +
70.41 + For list of available properties check the imported
70.42 + nbproject/build-impl.xml file.
70.43 +
70.44 +
70.45 + Another way to customize the build is by overriding existing main targets.
70.46 + The targets of interest are:
70.47 +
70.48 + -init-macrodef-javac: defines macro for javac compilation
70.49 + -init-macrodef-junit: defines macro for junit execution
70.50 + -init-macrodef-debug: defines macro for class debugging
70.51 + -init-macrodef-java: defines macro for class execution
70.52 + -do-jar-with-manifest: JAR building (if you are using a manifest)
70.53 + -do-jar-without-manifest: JAR building (if you are not using a manifest)
70.54 + run: execution of project
70.55 + -javadoc-build: Javadoc generation
70.56 + test-report: JUnit report generation
70.57 +
70.58 + An example of overriding the target for project execution could look like this:
70.59 +
70.60 + <target name="run" depends="currency-impl.jar">
70.61 + <exec dir="bin" executable="launcher.exe">
70.62 + <arg file="${dist.jar}"/>
70.63 + </exec>
70.64 + </target>
70.65 +
70.66 + Notice that the overridden target depends on the jar target and not only on
70.67 + the compile target as the regular run target does. Again, for a list of available
70.68 + properties which you can use, check the target you are overriding in the
70.69 + nbproject/build-impl.xml file.
70.70 +
70.71 + -->
70.72 +</project>
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/task3/solution12/nbproject/build-impl.xml Tue Oct 07 11:05:34 2008 +0200
71.3 @@ -0,0 +1,642 @@
71.4 +<?xml version="1.0" encoding="UTF-8"?>
71.5 +<!--
71.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
71.7 +*** EDIT ../build.xml INSTEAD ***
71.8 +
71.9 +For the purpose of easier reading the script
71.10 +is divided into following sections:
71.11 +
71.12 + - initialization
71.13 + - compilation
71.14 + - jar
71.15 + - execution
71.16 + - debugging
71.17 + - javadoc
71.18 + - junit compilation
71.19 + - junit execution
71.20 + - junit debugging
71.21 + - applet
71.22 + - cleanup
71.23 +
71.24 + -->
71.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">
71.26 + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
71.27 + <!--
71.28 + ======================
71.29 + INITIALIZATION SECTION
71.30 + ======================
71.31 + -->
71.32 + <target name="-pre-init">
71.33 + <!-- Empty placeholder for easier customization. -->
71.34 + <!-- You can override this target in the ../build.xml file. -->
71.35 + </target>
71.36 + <target depends="-pre-init" name="-init-private">
71.37 + <property file="nbproject/private/config.properties"/>
71.38 + <property file="nbproject/private/configs/${config}.properties"/>
71.39 + <property file="nbproject/private/private.properties"/>
71.40 + </target>
71.41 + <target depends="-pre-init,-init-private" name="-init-user">
71.42 + <property file="${user.properties.file}"/>
71.43 + <!-- The two properties below are usually overridden -->
71.44 + <!-- by the active platform. Just a fallback. -->
71.45 + <property name="default.javac.source" value="1.4"/>
71.46 + <property name="default.javac.target" value="1.4"/>
71.47 + </target>
71.48 + <target depends="-pre-init,-init-private,-init-user" name="-init-project">
71.49 + <property file="nbproject/configs/${config}.properties"/>
71.50 + <property file="nbproject/project.properties"/>
71.51 + </target>
71.52 + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
71.53 + <available file="${manifest.file}" property="manifest.available"/>
71.54 + <condition property="manifest.available+main.class">
71.55 + <and>
71.56 + <isset property="manifest.available"/>
71.57 + <isset property="main.class"/>
71.58 + <not>
71.59 + <equals arg1="${main.class}" arg2="" trim="true"/>
71.60 + </not>
71.61 + </and>
71.62 + </condition>
71.63 + <condition property="manifest.available+main.class+mkdist.available">
71.64 + <and>
71.65 + <istrue value="${manifest.available+main.class}"/>
71.66 + <isset property="libs.CopyLibs.classpath"/>
71.67 + </and>
71.68 + </condition>
71.69 + <condition property="have.tests">
71.70 + <or>
71.71 + <available file="${test.src.dir}"/>
71.72 + </or>
71.73 + </condition>
71.74 + <condition property="have.sources">
71.75 + <or>
71.76 + <available file="${src.dir}"/>
71.77 + </or>
71.78 + </condition>
71.79 + <condition property="netbeans.home+have.tests">
71.80 + <and>
71.81 + <isset property="netbeans.home"/>
71.82 + <isset property="have.tests"/>
71.83 + </and>
71.84 + </condition>
71.85 + <condition property="no.javadoc.preview">
71.86 + <and>
71.87 + <isset property="javadoc.preview"/>
71.88 + <isfalse value="${javadoc.preview}"/>
71.89 + </and>
71.90 + </condition>
71.91 + <property name="run.jvmargs" value=""/>
71.92 + <property name="javac.compilerargs" value=""/>
71.93 + <property name="work.dir" value="${basedir}"/>
71.94 + <condition property="no.deps">
71.95 + <and>
71.96 + <istrue value="${no.dependencies}"/>
71.97 + </and>
71.98 + </condition>
71.99 + <property name="javac.debug" value="true"/>
71.100 + <property name="javadoc.preview" value="true"/>
71.101 + <property name="application.args" value=""/>
71.102 + <property name="source.encoding" value="${file.encoding}"/>
71.103 + <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
71.104 + <and>
71.105 + <isset property="javadoc.encoding"/>
71.106 + <not>
71.107 + <equals arg1="${javadoc.encoding}" arg2=""/>
71.108 + </not>
71.109 + </and>
71.110 + </condition>
71.111 + <property name="javadoc.encoding.used" value="${source.encoding}"/>
71.112 + <property name="includes" value="**"/>
71.113 + <property name="excludes" value=""/>
71.114 + <property name="do.depend" value="false"/>
71.115 + <condition property="do.depend.true">
71.116 + <istrue value="${do.depend}"/>
71.117 + </condition>
71.118 + <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
71.119 + <and>
71.120 + <isset property="jaxws.endorsed.dir"/>
71.121 + <available file="nbproject/jaxws-build.xml"/>
71.122 + </and>
71.123 + </condition>
71.124 + </target>
71.125 + <target name="-post-init">
71.126 + <!-- Empty placeholder for easier customization. -->
71.127 + <!-- You can override this target in the ../build.xml file. -->
71.128 + </target>
71.129 + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
71.130 + <fail unless="src.dir">Must set src.dir</fail>
71.131 + <fail unless="test.src.dir">Must set test.src.dir</fail>
71.132 + <fail unless="build.dir">Must set build.dir</fail>
71.133 + <fail unless="dist.dir">Must set dist.dir</fail>
71.134 + <fail unless="build.classes.dir">Must set build.classes.dir</fail>
71.135 + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
71.136 + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
71.137 + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
71.138 + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
71.139 + <fail unless="dist.jar">Must set dist.jar</fail>
71.140 + </target>
71.141 + <target name="-init-macrodef-property">
71.142 + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
71.143 + <attribute name="name"/>
71.144 + <attribute name="value"/>
71.145 + <sequential>
71.146 + <property name="@{name}" value="${@{value}}"/>
71.147 + </sequential>
71.148 + </macrodef>
71.149 + </target>
71.150 + <target name="-init-macrodef-javac">
71.151 + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
71.152 + <attribute default="${src.dir}" name="srcdir"/>
71.153 + <attribute default="${build.classes.dir}" name="destdir"/>
71.154 + <attribute default="${javac.classpath}" name="classpath"/>
71.155 + <attribute default="${includes}" name="includes"/>
71.156 + <attribute default="${excludes}" name="excludes"/>
71.157 + <attribute default="${javac.debug}" name="debug"/>
71.158 + <attribute default="" name="sourcepath"/>
71.159 + <element name="customize" optional="true"/>
71.160 + <sequential>
71.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}">
71.162 + <classpath>
71.163 + <path path="@{classpath}"/>
71.164 + </classpath>
71.165 + <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
71.166 + <customize/>
71.167 + </javac>
71.168 + </sequential>
71.169 + </macrodef>
71.170 + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
71.171 + <attribute default="${src.dir}" name="srcdir"/>
71.172 + <attribute default="${build.classes.dir}" name="destdir"/>
71.173 + <attribute default="${javac.classpath}" name="classpath"/>
71.174 + <sequential>
71.175 + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
71.176 + <classpath>
71.177 + <path path="@{classpath}"/>
71.178 + </classpath>
71.179 + </depend>
71.180 + </sequential>
71.181 + </macrodef>
71.182 + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
71.183 + <attribute default="${build.classes.dir}" name="destdir"/>
71.184 + <sequential>
71.185 + <fail unless="javac.includes">Must set javac.includes</fail>
71.186 + <pathconvert pathsep="," property="javac.includes.binary">
71.187 + <path>
71.188 + <filelist dir="@{destdir}" files="${javac.includes}"/>
71.189 + </path>
71.190 + <globmapper from="*.java" to="*.class"/>
71.191 + </pathconvert>
71.192 + <delete>
71.193 + <files includes="${javac.includes.binary}"/>
71.194 + </delete>
71.195 + </sequential>
71.196 + </macrodef>
71.197 + </target>
71.198 + <target name="-init-macrodef-junit">
71.199 + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
71.200 + <attribute default="${includes}" name="includes"/>
71.201 + <attribute default="${excludes}" name="excludes"/>
71.202 + <attribute default="**" name="testincludes"/>
71.203 + <sequential>
71.204 + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
71.205 + <batchtest todir="${build.test.results.dir}">
71.206 + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
71.207 + <filename name="@{testincludes}"/>
71.208 + </fileset>
71.209 + </batchtest>
71.210 + <classpath>
71.211 + <path path="${run.test.classpath}"/>
71.212 + </classpath>
71.213 + <syspropertyset>
71.214 + <propertyref prefix="test-sys-prop."/>
71.215 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
71.216 + </syspropertyset>
71.217 + <formatter type="brief" usefile="false"/>
71.218 + <formatter type="xml"/>
71.219 + <jvmarg line="${run.jvmargs}"/>
71.220 + </junit>
71.221 + </sequential>
71.222 + </macrodef>
71.223 + </target>
71.224 + <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
71.225 + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
71.226 + <attribute default="${main.class}" name="name"/>
71.227 + <attribute default="${debug.classpath}" name="classpath"/>
71.228 + <attribute default="" name="stopclassname"/>
71.229 + <sequential>
71.230 + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
71.231 + <classpath>
71.232 + <path path="@{classpath}"/>
71.233 + </classpath>
71.234 + </nbjpdastart>
71.235 + </sequential>
71.236 + </macrodef>
71.237 + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
71.238 + <attribute default="${build.classes.dir}" name="dir"/>
71.239 + <sequential>
71.240 + <nbjpdareload>
71.241 + <fileset dir="@{dir}" includes="${fix.classes}">
71.242 + <include name="${fix.includes}*.class"/>
71.243 + </fileset>
71.244 + </nbjpdareload>
71.245 + </sequential>
71.246 + </macrodef>
71.247 + </target>
71.248 + <target name="-init-debug-args">
71.249 + <property name="version-output" value="java version "${ant.java.version}"/>
71.250 + <condition property="have-jdk-older-than-1.4">
71.251 + <or>
71.252 + <contains string="${version-output}" substring="java version "1.0"/>
71.253 + <contains string="${version-output}" substring="java version "1.1"/>
71.254 + <contains string="${version-output}" substring="java version "1.2"/>
71.255 + <contains string="${version-output}" substring="java version "1.3"/>
71.256 + </or>
71.257 + </condition>
71.258 + <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
71.259 + <istrue value="${have-jdk-older-than-1.4}"/>
71.260 + </condition>
71.261 + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
71.262 + <os family="windows"/>
71.263 + </condition>
71.264 + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
71.265 + <isset property="debug.transport"/>
71.266 + </condition>
71.267 + </target>
71.268 + <target depends="-init-debug-args" name="-init-macrodef-debug">
71.269 + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
71.270 + <attribute default="${main.class}" name="classname"/>
71.271 + <attribute default="${debug.classpath}" name="classpath"/>
71.272 + <element name="customize" optional="true"/>
71.273 + <sequential>
71.274 + <java classname="@{classname}" dir="${work.dir}" fork="true">
71.275 + <jvmarg line="${debug-args-line}"/>
71.276 + <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
71.277 + <jvmarg line="${run.jvmargs}"/>
71.278 + <classpath>
71.279 + <path path="@{classpath}"/>
71.280 + </classpath>
71.281 + <syspropertyset>
71.282 + <propertyref prefix="run-sys-prop."/>
71.283 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
71.284 + </syspropertyset>
71.285 + <customize/>
71.286 + </java>
71.287 + </sequential>
71.288 + </macrodef>
71.289 + </target>
71.290 + <target name="-init-macrodef-java">
71.291 + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
71.292 + <attribute default="${main.class}" name="classname"/>
71.293 + <element name="customize" optional="true"/>
71.294 + <sequential>
71.295 + <java classname="@{classname}" dir="${work.dir}" fork="true">
71.296 + <jvmarg line="${run.jvmargs}"/>
71.297 + <classpath>
71.298 + <path path="${run.classpath}"/>
71.299 + </classpath>
71.300 + <syspropertyset>
71.301 + <propertyref prefix="run-sys-prop."/>
71.302 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
71.303 + </syspropertyset>
71.304 + <customize/>
71.305 + </java>
71.306 + </sequential>
71.307 + </macrodef>
71.308 + </target>
71.309 + <target name="-init-presetdef-jar">
71.310 + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
71.311 + <jar compress="${jar.compress}" jarfile="${dist.jar}">
71.312 + <j2seproject1:fileset dir="${build.classes.dir}"/>
71.313 + </jar>
71.314 + </presetdef>
71.315 + </target>
71.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"/>
71.317 + <!--
71.318 + ===================
71.319 + COMPILATION SECTION
71.320 + ===================
71.321 + -->
71.322 + <target depends="init" name="deps-jar" unless="no.deps"/>
71.323 + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
71.324 + <target depends="init" name="-check-automatic-build">
71.325 + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
71.326 + </target>
71.327 + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
71.328 + <antcall target="clean"/>
71.329 + </target>
71.330 + <target depends="init,deps-jar" name="-pre-pre-compile">
71.331 + <mkdir dir="${build.classes.dir}"/>
71.332 + </target>
71.333 + <target name="-pre-compile">
71.334 + <!-- Empty placeholder for easier customization. -->
71.335 + <!-- You can override this target in the ../build.xml file. -->
71.336 + </target>
71.337 + <target if="do.depend.true" name="-compile-depend">
71.338 + <j2seproject3:depend/>
71.339 + </target>
71.340 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
71.341 + <j2seproject3:javac/>
71.342 + <copy todir="${build.classes.dir}">
71.343 + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
71.344 + </copy>
71.345 + </target>
71.346 + <target name="-post-compile">
71.347 + <!-- Empty placeholder for easier customization. -->
71.348 + <!-- You can override this target in the ../build.xml file. -->
71.349 + </target>
71.350 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
71.351 + <target name="-pre-compile-single">
71.352 + <!-- Empty placeholder for easier customization. -->
71.353 + <!-- You can override this target in the ../build.xml file. -->
71.354 + </target>
71.355 + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
71.356 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
71.357 + <j2seproject3:force-recompile/>
71.358 + <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
71.359 + </target>
71.360 + <target name="-post-compile-single">
71.361 + <!-- Empty placeholder for easier customization. -->
71.362 + <!-- You can override this target in the ../build.xml file. -->
71.363 + </target>
71.364 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
71.365 + <!--
71.366 + ====================
71.367 + JAR BUILDING SECTION
71.368 + ====================
71.369 + -->
71.370 + <target depends="init" name="-pre-pre-jar">
71.371 + <dirname file="${dist.jar}" property="dist.jar.dir"/>
71.372 + <mkdir dir="${dist.jar.dir}"/>
71.373 + </target>
71.374 + <target name="-pre-jar">
71.375 + <!-- Empty placeholder for easier customization. -->
71.376 + <!-- You can override this target in the ../build.xml file. -->
71.377 + </target>
71.378 + <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
71.379 + <j2seproject1:jar/>
71.380 + </target>
71.381 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
71.382 + <j2seproject1:jar manifest="${manifest.file}"/>
71.383 + </target>
71.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">
71.385 + <j2seproject1:jar manifest="${manifest.file}">
71.386 + <j2seproject1:manifest>
71.387 + <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
71.388 + </j2seproject1:manifest>
71.389 + </j2seproject1:jar>
71.390 + <echo>To run this application from the command line without Ant, try:</echo>
71.391 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
71.392 + <property location="${dist.jar}" name="dist.jar.resolved"/>
71.393 + <pathconvert property="run.classpath.with.dist.jar">
71.394 + <path path="${run.classpath}"/>
71.395 + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
71.396 + </pathconvert>
71.397 + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
71.398 + </target>
71.399 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
71.400 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
71.401 + <pathconvert property="run.classpath.without.build.classes.dir">
71.402 + <path path="${run.classpath}"/>
71.403 + <map from="${build.classes.dir.resolved}" to=""/>
71.404 + </pathconvert>
71.405 + <pathconvert pathsep=" " property="jar.classpath">
71.406 + <path path="${run.classpath.without.build.classes.dir}"/>
71.407 + <chainedmapper>
71.408 + <flattenmapper/>
71.409 + <globmapper from="*" to="lib/*"/>
71.410 + </chainedmapper>
71.411 + </pathconvert>
71.412 + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
71.413 + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
71.414 + <fileset dir="${build.classes.dir}"/>
71.415 + <manifest>
71.416 + <attribute name="Main-Class" value="${main.class}"/>
71.417 + <attribute name="Class-Path" value="${jar.classpath}"/>
71.418 + </manifest>
71.419 + </copylibs>
71.420 + <echo>To run this application from the command line without Ant, try:</echo>
71.421 + <property location="${dist.jar}" name="dist.jar.resolved"/>
71.422 + <echo>java -jar "${dist.jar.resolved}"</echo>
71.423 + </target>
71.424 + <target name="-post-jar">
71.425 + <!-- Empty placeholder for easier customization. -->
71.426 + <!-- You can override this target in the ../build.xml file. -->
71.427 + </target>
71.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"/>
71.429 + <!--
71.430 + =================
71.431 + EXECUTION SECTION
71.432 + =================
71.433 + -->
71.434 + <target depends="init,compile" description="Run a main class." name="run">
71.435 + <j2seproject1:java>
71.436 + <customize>
71.437 + <arg line="${application.args}"/>
71.438 + </customize>
71.439 + </j2seproject1:java>
71.440 + </target>
71.441 + <target name="-do-not-recompile">
71.442 + <property name="javac.includes.binary" value=""/>
71.443 + </target>
71.444 + <target depends="init,-do-not-recompile,compile-single" name="run-single">
71.445 + <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
71.446 + <j2seproject1:java classname="${run.class}"/>
71.447 + </target>
71.448 + <!--
71.449 + =================
71.450 + DEBUGGING SECTION
71.451 + =================
71.452 + -->
71.453 + <target depends="init" if="netbeans.home" name="-debug-start-debugger">
71.454 + <j2seproject1:nbjpdastart name="${debug.class}"/>
71.455 + </target>
71.456 + <target depends="init,compile" name="-debug-start-debuggee">
71.457 + <j2seproject3:debug>
71.458 + <customize>
71.459 + <arg line="${application.args}"/>
71.460 + </customize>
71.461 + </j2seproject3:debug>
71.462 + </target>
71.463 + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
71.464 + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
71.465 + <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
71.466 + </target>
71.467 + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
71.468 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
71.469 + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
71.470 + <j2seproject3:debug classname="${debug.class}"/>
71.471 + </target>
71.472 + <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
71.473 + <target depends="init" name="-pre-debug-fix">
71.474 + <fail unless="fix.includes">Must set fix.includes</fail>
71.475 + <property name="javac.includes" value="${fix.includes}.java"/>
71.476 + </target>
71.477 + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
71.478 + <j2seproject1:nbjpdareload/>
71.479 + </target>
71.480 + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
71.481 + <!--
71.482 + ===============
71.483 + JAVADOC SECTION
71.484 + ===============
71.485 + -->
71.486 + <target depends="init" name="-javadoc-build">
71.487 + <mkdir dir="${dist.javadoc.dir}"/>
71.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}">
71.489 + <classpath>
71.490 + <path path="${javac.classpath}"/>
71.491 + </classpath>
71.492 + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
71.493 + <filename name="**/*.java"/>
71.494 + </fileset>
71.495 + </javadoc>
71.496 + </target>
71.497 + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
71.498 + <nbbrowse file="${dist.javadoc.dir}/index.html"/>
71.499 + </target>
71.500 + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
71.501 + <!--
71.502 + =========================
71.503 + JUNIT COMPILATION SECTION
71.504 + =========================
71.505 + -->
71.506 + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
71.507 + <mkdir dir="${build.test.classes.dir}"/>
71.508 + </target>
71.509 + <target name="-pre-compile-test">
71.510 + <!-- Empty placeholder for easier customization. -->
71.511 + <!-- You can override this target in the ../build.xml file. -->
71.512 + </target>
71.513 + <target if="do.depend.true" name="-compile-test-depend">
71.514 + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
71.515 + </target>
71.516 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
71.517 + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
71.518 + <copy todir="${build.test.classes.dir}">
71.519 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
71.520 + </copy>
71.521 + </target>
71.522 + <target name="-post-compile-test">
71.523 + <!-- Empty placeholder for easier customization. -->
71.524 + <!-- You can override this target in the ../build.xml file. -->
71.525 + </target>
71.526 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
71.527 + <target name="-pre-compile-test-single">
71.528 + <!-- Empty placeholder for easier customization. -->
71.529 + <!-- You can override this target in the ../build.xml file. -->
71.530 + </target>
71.531 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
71.532 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
71.533 + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
71.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}"/>
71.535 + <copy todir="${build.test.classes.dir}">
71.536 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
71.537 + </copy>
71.538 + </target>
71.539 + <target name="-post-compile-test-single">
71.540 + <!-- Empty placeholder for easier customization. -->
71.541 + <!-- You can override this target in the ../build.xml file. -->
71.542 + </target>
71.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"/>
71.544 + <!--
71.545 + =======================
71.546 + JUNIT EXECUTION SECTION
71.547 + =======================
71.548 + -->
71.549 + <target depends="init" if="have.tests" name="-pre-test-run">
71.550 + <mkdir dir="${build.test.results.dir}"/>
71.551 + </target>
71.552 + <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
71.553 + <j2seproject3:junit testincludes="**/*Test.java"/>
71.554 + </target>
71.555 + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
71.556 + <fail if="tests.failed">Some tests failed; see details above.</fail>
71.557 + </target>
71.558 + <target depends="init" if="have.tests" name="test-report"/>
71.559 + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
71.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"/>
71.561 + <target depends="init" if="have.tests" name="-pre-test-run-single">
71.562 + <mkdir dir="${build.test.results.dir}"/>
71.563 + </target>
71.564 + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
71.565 + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
71.566 + <j2seproject3:junit excludes="" includes="${test.includes}"/>
71.567 + </target>
71.568 + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
71.569 + <fail if="tests.failed">Some tests failed; see details above.</fail>
71.570 + </target>
71.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"/>
71.572 + <!--
71.573 + =======================
71.574 + JUNIT DEBUGGING SECTION
71.575 + =======================
71.576 + -->
71.577 + <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
71.578 + <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
71.579 + <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
71.580 + <delete file="${test.report.file}"/>
71.581 + <mkdir dir="${build.test.results.dir}"/>
71.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}">
71.583 + <customize>
71.584 + <syspropertyset>
71.585 + <propertyref prefix="test-sys-prop."/>
71.586 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
71.587 + </syspropertyset>
71.588 + <arg value="${test.class}"/>
71.589 + <arg value="showoutput=true"/>
71.590 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
71.591 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
71.592 + </customize>
71.593 + </j2seproject3:debug>
71.594 + </target>
71.595 + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
71.596 + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
71.597 + </target>
71.598 + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
71.599 + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
71.600 + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
71.601 + </target>
71.602 + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
71.603 + <!--
71.604 + =========================
71.605 + APPLET EXECUTION SECTION
71.606 + =========================
71.607 + -->
71.608 + <target depends="init,compile-single" name="run-applet">
71.609 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
71.610 + <j2seproject1:java classname="sun.applet.AppletViewer">
71.611 + <customize>
71.612 + <arg value="${applet.url}"/>
71.613 + </customize>
71.614 + </j2seproject1:java>
71.615 + </target>
71.616 + <!--
71.617 + =========================
71.618 + APPLET DEBUGGING SECTION
71.619 + =========================
71.620 + -->
71.621 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
71.622 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
71.623 + <j2seproject3:debug classname="sun.applet.AppletViewer">
71.624 + <customize>
71.625 + <arg value="${applet.url}"/>
71.626 + </customize>
71.627 + </j2seproject3:debug>
71.628 + </target>
71.629 + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
71.630 + <!--
71.631 + ===============
71.632 + CLEANUP SECTION
71.633 + ===============
71.634 + -->
71.635 + <target depends="init" name="deps-clean" unless="no.deps"/>
71.636 + <target depends="init" name="-do-clean">
71.637 + <delete dir="${build.dir}"/>
71.638 + <delete dir="${dist.dir}"/>
71.639 + </target>
71.640 + <target name="-post-clean">
71.641 + <!-- Empty placeholder for easier customization. -->
71.642 + <!-- You can override this target in the ../build.xml file. -->
71.643 + </target>
71.644 + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
71.645 +</project>
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/task3/solution12/nbproject/genfiles.properties Tue Oct 07 11:05:34 2008 +0200
72.3 @@ -0,0 +1,8 @@
72.4 +build.xml.data.CRC32=2ab820eb
72.5 +build.xml.script.CRC32=58a52595
72.6 +build.xml.stylesheet.CRC32=be360661
72.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
72.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
72.9 +nbproject/build-impl.xml.data.CRC32=b63e115b
72.10 +nbproject/build-impl.xml.script.CRC32=3bdfc4fa
72.11 +nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/task3/solution12/nbproject/project.properties Tue Oct 07 11:05:34 2008 +0200
73.3 @@ -0,0 +1,68 @@
73.4 +application.title=currency
73.5 +application.vendor=apidesign.org
73.6 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
73.7 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
73.8 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
73.9 +build.classes.dir=${build.dir}/classes
73.10 +build.classes.excludes=**/*.java,**/*.form
73.11 +# This directory is removed when the project is cleaned:
73.12 +build.dir=build
73.13 +build.generated.dir=${build.dir}/generated
73.14 +# Only compile against the classpath explicitly listed here:
73.15 +build.sysclasspath=ignore
73.16 +build.test.classes.dir=${build.dir}/test/classes
73.17 +build.test.results.dir=${build.dir}/test/results
73.18 +debug.classpath=\
73.19 + ${run.classpath}
73.20 +debug.test.classpath=\
73.21 + ${run.test.classpath}
73.22 +# This directory is removed when the project is cleaned:
73.23 +dist.dir=dist
73.24 +dist.jar=${dist.dir}/currency.jar
73.25 +dist.javadoc.dir=${dist.dir}/javadoc
73.26 +excludes=
73.27 +file.reference.junit-4.4.jar=../../libs/junit-4.4.jar
73.28 +file.reference.src-apifest08=..
73.29 +includes=**
73.30 +jar.compress=false
73.31 +javac.classpath=
73.32 +# Space-separated list of extra javac options
73.33 +javac.compilerargs=
73.34 +javac.deprecation=false
73.35 +javac.source=1.5
73.36 +javac.target=1.5
73.37 +javac.test.classpath=\
73.38 + ${javac.classpath}:\
73.39 + ${build.classes.dir}:\
73.40 + ${file.reference.junit-4.4.jar}
73.41 +javadoc.additionalparam=
73.42 +javadoc.author=false
73.43 +javadoc.encoding=
73.44 +javadoc.noindex=false
73.45 +javadoc.nonavbar=false
73.46 +javadoc.notree=false
73.47 +javadoc.private=false
73.48 +javadoc.splitindex=true
73.49 +javadoc.use=true
73.50 +javadoc.version=false
73.51 +javadoc.windowtitle=
73.52 +jnlp.codebase.type=local
73.53 +jnlp.codebase.url=file:/home/jarda/src/apifest08/currency/dist
73.54 +jnlp.descriptor=application
73.55 +jnlp.enabled=false
73.56 +jnlp.offline-allowed=false
73.57 +jnlp.signed=false
73.58 +meta.inf.dir=${src.dir}/META-INF
73.59 +platform.active=default_platform
73.60 +run.classpath=\
73.61 + ${javac.classpath}:\
73.62 + ${build.classes.dir}
73.63 +# Space-separated list of JVM arguments used when running the project
73.64 +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
73.65 +# or test-sys-prop.name=value to set system properties for unit tests):
73.66 +run.jvmargs=
73.67 +run.test.classpath=\
73.68 + ${javac.test.classpath}:\
73.69 + ${build.test.classes.dir}
73.70 +src.dir=src
73.71 +test.src.dir=test
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/task3/solution12/nbproject/project.xml Tue Oct 07 11:05:34 2008 +0200
74.3 @@ -0,0 +1,16 @@
74.4 +<?xml version="1.0" encoding="UTF-8"?>
74.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
74.6 + <type>org.netbeans.modules.java.j2seproject</type>
74.7 + <configuration>
74.8 + <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
74.9 + <name>Currency Convertor Solution 12</name>
74.10 + <minimum-ant-version>1.6.5</minimum-ant-version>
74.11 + <source-roots>
74.12 + <root id="src.dir"/>
74.13 + </source-roots>
74.14 + <test-roots>
74.15 + <root id="test.src.dir"/>
74.16 + </test-roots>
74.17 + </data>
74.18 + </configuration>
74.19 +</project>
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/task3/solution12/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 11:05:34 2008 +0200
75.3 @@ -0,0 +1,184 @@
75.4 +package org.apidesign.apifest08.currency;
75.5 +
75.6 +import java.util.ArrayList;
75.7 +import java.util.Currency;
75.8 +import java.util.Hashtable;
75.9 +import java.util.List;
75.10 +
75.11 +import org.apidesign.apifest08.currency.exceptions.ConvertorException;
75.12 +import org.apidesign.apifest08.currency.exceptions.InvalidCurrencyException;
75.13 +import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
75.14 +
75.15 +/**
75.16 + * This is the skeleton class for your API. You need to make it public, so it is accessible to your client code
75.17 + * (currently in Task1Test.java) file.
75.18 + * <p>
75.19 + * Feel free to create additional classes or rename this one, just keep all the API and its implementation in this
75.20 + * package. Do not spread it outside to other packages.
75.21 + */
75.22 +public class Convertor {
75.23 +
75.24 + private static Hashtable<String, ExchangeRate> exchangeRates;
75.25 +
75.26 + private Hashtable<String, ExchangeRate> convertorInstanceExchangeRates;
75.27 +
75.28 + private Convertor(List<Currency> currencies) throws UnknownConvertorException {
75.29 + convertorInstanceExchangeRates = new Hashtable<String, ExchangeRate>();
75.30 + for (Currency currency1 : currencies) {
75.31 + for (Currency currency2 : currencies) {
75.32 + if(!currency1.getCurrencyCode().equals(currency2.getCurrencyCode())) {
75.33 + String key = currency1.getCurrencyCode() + currency2.getCurrencyCode();
75.34 + ExchangeRate exchangeRate = exchangeRates.get(key);
75.35 + convertorInstanceExchangeRates.put(key, exchangeRate);
75.36 + }
75.37 + }
75.38 + }
75.39 + }
75.40 +
75.41 + /**
75.42 + * Sets convertor rate for selected currencies.
75.43 + * @param currency1
75.44 + * one of the currencies we want to convert to/from
75.45 + * @param currency2
75.46 + * the other currency
75.47 + * @param rate
75.48 + * exchange rate from currency1 to currency2
75.49 + * @param unit
75.50 + * unit of exchangeRate (USD->CZK - unit=1, you exchange one dollar, SKK->CZK unit=100, exchange rate is for
75.51 + * 100SKK)
75.52 + */
75.53 + public static void setConvertorRates(Currency currency1, Currency currency2, double rate, double unit) {
75.54 + if (currency1 == null || currency2 == null) {
75.55 + throw new ConvertorException("None of the currencies should be null!!!");
75.56 + }
75.57 +
75.58 + if (rate <= 0 || unit <= 0) {
75.59 + throw new ConvertorException("Rate(" + rate + ") and unit(" + unit + ") has to be grater then zero!!!");
75.60 + }
75.61 +
75.62 + if (exchangeRates == null) {
75.63 + exchangeRates = new Hashtable<String, ExchangeRate>();
75.64 + }
75.65 +
75.66 + String key12 = currency1.getCurrencyCode() + currency2.getCurrencyCode();
75.67 + String key21 = currency2.getCurrencyCode() + currency1.getCurrencyCode();
75.68 + double recountedRate = (unit / rate) * unit;
75.69 +
75.70 + exchangeRates.put(key12, new ExchangeRate(currency1, currency2, rate, unit));
75.71 + exchangeRates.put(key21, new ExchangeRate(currency2, currency1, recountedRate, unit));
75.72 +
75.73 + }
75.74 +
75.75 + /**
75.76 + * Merge exchange rates of actual convertor with exchange rates from selected
75.77 + * convertor. If there are same currencies in both convertors, these from selected
75.78 + * convertor rewrites these in actual convertor.
75.79 + * @param convertor convertor to merge with actual one
75.80 + * @return convertor with merged exchange rates
75.81 + */
75.82 + public Convertor merge(Convertor convertor) {
75.83 + convertorInstanceExchangeRates.putAll(convertor.getInstanceExchangeRates());
75.84 + return this;
75.85 + }
75.86 +
75.87 + /**
75.88 + * Creates new instance of convertor.
75.89 + * @param currency1
75.90 + * one of the currencies we want to convert to/from
75.91 + * @param currency2
75.92 + * the other currency
75.93 + * @return new instance of convertor
75.94 + * @throws UnknownConvertorException
75.95 + * thrown if convertor for selected currencies has not been defined
75.96 + */
75.97 + public static Convertor getConvertorInstance(Currency... currencies) throws UnknownConvertorException {
75.98 + List<Currency> currencyList = new ArrayList<Currency>();
75.99 +
75.100 + if(currencies.length < 2) {
75.101 + throw new ConvertorException("To get convertor instance, you have to select at least two currencies!!!");
75.102 + }
75.103 +
75.104 + for (Currency currency1 : currencies) {
75.105 + for (Currency currency2 : currencies) {
75.106 + if(currency1 == null || currency2 == null) {
75.107 + throw new ConvertorException("None of the currencies should be null!!!");
75.108 + }
75.109 +
75.110 + if(!currency1.getCurrencyCode().equals(currency2.getCurrencyCode())) {
75.111 + String key12 = currency1.getCurrencyCode() + currency2.getCurrencyCode();
75.112 + String key21 = currency2.getCurrencyCode() + currency1.getCurrencyCode();
75.113 + if (!(exchangeRates.containsKey(key12) && exchangeRates.containsKey(key21))) {
75.114 + throw new UnknownConvertorException("Selected convertor (" + currency1.getCurrencyCode() + "<->"
75.115 + + currency2.getCurrencyCode() + ") has not defined exchange rates!!!");
75.116 + }
75.117 + }
75.118 + }
75.119 +
75.120 + currencyList.add(currency1);
75.121 + }
75.122 +
75.123 + return new Convertor(currencyList);
75.124 + }
75.125 +
75.126 + /**
75.127 + * Converts selected amout of selected currency to other currency of this convertor instance.
75.128 + * @param amount
75.129 + * amount to convert
75.130 + * @param originalCurrency
75.131 + * currency of this amount
75.132 + * @param newCurrency
75.133 + * currency to which we want convert
75.134 + * @return converted amount
75.135 + * @throws InvalidCurrencyException
75.136 + * while one or both currencies doesn't fit for this convertor
75.137 + */
75.138 + public double convert(double amount, Currency originalCurrency, Currency newCurrency) throws InvalidCurrencyException {
75.139 + ExchangeRate actualyUsedExchangeRate = null;
75.140 +
75.141 + if (originalCurrency == null) {
75.142 + throw new ConvertorException("Original currency is null!!!");
75.143 + }
75.144 +
75.145 + if (newCurrency == null) {
75.146 + throw new ConvertorException("Destination currency is null!!!");
75.147 + }
75.148 +
75.149 + actualyUsedExchangeRate = getExchangeRate(originalCurrency, newCurrency);
75.150 +
75.151 + return countResult(actualyUsedExchangeRate, amount);
75.152 + }
75.153 +
75.154 + private double countResult(ExchangeRate actualyUsedExchangeRate, double amount) {
75.155 + return amount * actualyUsedExchangeRate.getRate() / actualyUsedExchangeRate.getUnit();
75.156 + }
75.157 +
75.158 + /**
75.159 + * Decides the direction of conversion and returns instance of actual exchange rate.
75.160 + * @param actualCurrency
75.161 + * actual currency we want to convert
75.162 + * @return actual exchange rate of this convertor for selected currency
75.163 + */
75.164 + private ExchangeRate getExchangeRate(Currency originalCurrency, Currency newCurrency) throws InvalidCurrencyException {
75.165 + ExchangeRate actualyUsedExchangeRate = null;
75.166 +
75.167 + String key = originalCurrency.getCurrencyCode() + newCurrency.getCurrencyCode();
75.168 +
75.169 + if(convertorInstanceExchangeRates.containsKey(key)) {
75.170 + actualyUsedExchangeRate = convertorInstanceExchangeRates.get(key);
75.171 + } else {
75.172 + throw new InvalidCurrencyException("This convertor could not be used for converting selected currencies (" + originalCurrency.getCurrencyCode() + "->"
75.173 + + newCurrency.getCurrencyCode() + ") !!!");
75.174 + }
75.175 +
75.176 + return actualyUsedExchangeRate;
75.177 + }
75.178 +
75.179 + /**
75.180 + * Returns exchange rates for actual instance of convertor.
75.181 + * @return exchange rates for actual instance of convertor
75.182 + */
75.183 + Hashtable<String, ExchangeRate> getInstanceExchangeRates() {
75.184 + return convertorInstanceExchangeRates;
75.185 + }
75.186 +
75.187 +}
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/task3/solution12/src/org/apidesign/apifest08/currency/ExchangeRate.java Tue Oct 07 11:05:34 2008 +0200
76.3 @@ -0,0 +1,35 @@
76.4 +package org.apidesign.apifest08.currency;
76.5 +
76.6 +import java.util.Currency;
76.7 +
76.8 +public class ExchangeRate {
76.9 +
76.10 + private Currency originalCurrency;
76.11 + private Currency newCurrency;
76.12 + private double unit;
76.13 + private double rate;
76.14 +
76.15 + public ExchangeRate(Currency originalCurrency, Currency newCurrency, double rate, double unit) {
76.16 + this.newCurrency = newCurrency;
76.17 + this.originalCurrency = originalCurrency;
76.18 + this.rate = rate;
76.19 + this.unit = unit;
76.20 + }
76.21 +
76.22 + public Currency getOriginalCurrency() {
76.23 + return originalCurrency;
76.24 + }
76.25 +
76.26 + public Currency getNewCurrency() {
76.27 + return newCurrency;
76.28 + }
76.29 +
76.30 + public double getUnit() {
76.31 + return unit;
76.32 + }
76.33 +
76.34 + public double getRate() {
76.35 + return rate;
76.36 + }
76.37 +
76.38 +}
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/task3/solution12/src/org/apidesign/apifest08/currency/exceptions/ConvertorException.java Tue Oct 07 11:05:34 2008 +0200
77.3 @@ -0,0 +1,20 @@
77.4 +package org.apidesign.apifest08.currency.exceptions;
77.5 +
77.6 +public class ConvertorException extends RuntimeException {
77.7 +
77.8 + public ConvertorException() {
77.9 + }
77.10 +
77.11 + public ConvertorException(String message) {
77.12 + super(message);
77.13 + }
77.14 +
77.15 + public ConvertorException(Throwable cause) {
77.16 + super(cause);
77.17 + }
77.18 +
77.19 + public ConvertorException(String message, Throwable cause) {
77.20 + super(message, cause);
77.21 + }
77.22 +
77.23 +}
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/task3/solution12/src/org/apidesign/apifest08/currency/exceptions/InvalidCurrencyException.java Tue Oct 07 11:05:34 2008 +0200
78.3 @@ -0,0 +1,20 @@
78.4 +package org.apidesign.apifest08.currency.exceptions;
78.5 +
78.6 +public class InvalidCurrencyException extends Exception {
78.7 +
78.8 + public InvalidCurrencyException() {
78.9 + }
78.10 +
78.11 + public InvalidCurrencyException(String message) {
78.12 + super(message);
78.13 + }
78.14 +
78.15 + public InvalidCurrencyException(Throwable cause) {
78.16 + super(cause);
78.17 + }
78.18 +
78.19 + public InvalidCurrencyException(String message, Throwable cause) {
78.20 + super(message, cause);
78.21 + }
78.22 +
78.23 +}
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/task3/solution12/src/org/apidesign/apifest08/currency/exceptions/UnknownConvertorException.java Tue Oct 07 11:05:34 2008 +0200
79.3 @@ -0,0 +1,20 @@
79.4 +package org.apidesign.apifest08.currency.exceptions;
79.5 +
79.6 +public class UnknownConvertorException extends Exception {
79.7 +
79.8 + public UnknownConvertorException() {
79.9 + }
79.10 +
79.11 + public UnknownConvertorException(String message) {
79.12 + super(message);
79.13 + }
79.14 +
79.15 + public UnknownConvertorException(Throwable cause) {
79.16 + super(cause);
79.17 + }
79.18 +
79.19 + public UnknownConvertorException(String message, Throwable cause) {
79.20 + super(message, cause);
79.21 + }
79.22 +
79.23 +}
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/task3/solution12/test/org/apidesign/apifest08/test/Task1Test.java Tue Oct 07 11:05:34 2008 +0200
80.3 @@ -0,0 +1,174 @@
80.4 +package org.apidesign.apifest08.test;
80.5 +
80.6 +import java.util.Currency;
80.7 +
80.8 +import junit.framework.TestCase;
80.9 +
80.10 +import org.apidesign.apifest08.currency.Convertor;
80.11 +import org.apidesign.apifest08.currency.exceptions.InvalidCurrencyException;
80.12 +import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
80.13 +
80.14 +/**
80.15 + * Finish the Convertor API, and then write bodies of methods inside of this class to match the given tasks. To fullfil
80.16 + * your task, use the API define in the <code>org.apidesign.apifest08.currency</code> package. Do not you reflection, or
80.17 + * other hacks as your code shall run without any runtime permissions.
80.18 + */
80.19 +public class Task1Test extends TestCase {
80.20 + public Task1Test(String testName) {
80.21 + super(testName);
80.22 + }
80.23 +
80.24 + @Override
80.25 + protected void setUp() throws Exception {
80.26 + }
80.27 +
80.28 + @Override
80.29 + protected void tearDown() throws Exception {
80.30 + }
80.31 +
80.32 + //
80.33 + // Imagine that there are three parts of the whole system:
80.34 + // 1. there is someone who knows the current exchange rate
80.35 + // 2. there is someone who wants to do the conversion
80.36 + // 3. there is the API between 1. and 2. which allows them to communicate
80.37 + // Please design such API
80.38 + //
80.39 +
80.40 + /**
80.41 + * Create convertor that understands two currencies, CZK and USD. Make 1 USD == 17 CZK. This is a method provided for
80.42 + * #1 group - e.g. those that know the exchange rate. They somehow need to create the objects from the API and tell
80.43 + * them the exchange rate. The API itself knows nothing about any rates, before the createCZKtoUSD method is called.
80.44 + * Creation of the convertor shall not require subclassing of any class or interface on the client side.
80.45 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
80.46 + */
80.47 + public static Convertor createCZKtoUSD() {
80.48 + // set exchange rates
80.49 + Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("CZK"), 17d, 1d);
80.50 +
80.51 + // create new instance
80.52 + Convertor convertor = null;
80.53 + try {
80.54 + convertor = Convertor.getConvertorInstance(Currency.getInstance("USD"), Currency.getInstance("CZK"));
80.55 + } catch (UnknownConvertorException e) {
80.56 + e.printStackTrace();
80.57 + }
80.58 +
80.59 + return convertor;
80.60 + }
80.61 +
80.62 + /**
80.63 + * Create convertor that understands two currencies, CZK and SKK. Make 100 SKK == 80 CZK. Again this is method for the
80.64 + * #1 group - it knows the exchange rate, and needs to use the API to create objects with the exchange rate. Anyone
80.65 + * shall be ready to call this method without any other method being called previously. The API itself shall know
80.66 + * nothing about any rates, before this method is called. Creation of the convertor shall not require subclassing of
80.67 + * any class or interface on the client side.
80.68 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
80.69 + */
80.70 + public static Convertor createSKKtoCZK() {
80.71 + // set exchange rates
80.72 + Convertor.setConvertorRates(Currency.getInstance("SKK"), Currency.getInstance("CZK"), 80d, 100d);
80.73 +
80.74 + // create new instance
80.75 + Convertor convertor = null;
80.76 + try {
80.77 + convertor = Convertor.getConvertorInstance(Currency.getInstance("SKK"), Currency.getInstance("CZK"));
80.78 + } catch (UnknownConvertorException e) {
80.79 + e.printStackTrace();
80.80 + }
80.81 +
80.82 + return convertor;
80.83 + }
80.84 +
80.85 + //
80.86 + // now the methods for group #2 follow:
80.87 + // this group knows nothing about exchange rates, but knows how to use
80.88 + // the API to do conversions. It somehow (by calling one of the factory
80.89 + // methods) gets objects from the API and uses them to do the conversions.
80.90 + //
80.91 +
80.92 + /**
80.93 + * Use the convertor from <code>createCZKtoUSD</code> method and do few conversions with it.
80.94 + */
80.95 + public void testCurrencyCZKUSD() throws Exception {
80.96 + Convertor c = createCZKtoUSD();
80.97 + // convert $5 to CZK using c:
80.98 + double result = c.convert(5, Currency.getInstance("USD"), Currency.getInstance("CZK"));
80.99 + assertEquals("Result is not 85 CZK", 85.0, result);
80.100 +
80.101 + // convert $8 to CZK
80.102 + result = c.convert(8, Currency.getInstance("USD"), Currency.getInstance("CZK"));
80.103 + assertEquals("Result is not 136 CZK", 136.0, result);
80.104 +
80.105 + // convert 1003CZK to USD
80.106 + result = c.convert(1003, Currency.getInstance("CZK"), Currency.getInstance("USD"));
80.107 + assertEquals("Result is not 59 USD", 59.0, result);
80.108 + }
80.109 +
80.110 + /**
80.111 + * Use the convertor from <code>createSKKtoCZK</code> method and do few conversions with it.
80.112 + */
80.113 + public void testCurrencySKKCZK() throws Exception {
80.114 + Convertor c = createSKKtoCZK();
80.115 +
80.116 + // convert 16CZK using c:
80.117 + double result = c.convert(16, Currency.getInstance("CZK"), Currency.getInstance("SKK"));
80.118 + assertEquals("Result is not 20 SKK", 20.0, result);
80.119 +
80.120 + // convert 500SKK to CZK
80.121 + result = c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
80.122 + assertEquals("Result is not 400 CZK", 400.0, result);
80.123 + }
80.124 +
80.125 + /**
80.126 + * Verify that the CZK to USD convertor knows nothing about SKK.
80.127 + */
80.128 + public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
80.129 + Convertor c = createCZKtoUSD();
80.130 + boolean exceptionThrown = false;
80.131 +
80.132 + // convert $5 to SKK, the API shall say this is not possible
80.133 + try {
80.134 + c.convert(5, Currency.getInstance("USD"), Currency.getInstance("SKK"));
80.135 + exceptionThrown = false;
80.136 + } catch (InvalidCurrencyException e) {
80.137 + exceptionThrown = true;
80.138 + }
80.139 + assertEquals("It should be impossible to convert to SKK with USD->CZK convertor", true, exceptionThrown);
80.140 +
80.141 + // convert 500 SKK to CZK, the API shall say this is not possible
80.142 + try {
80.143 + c.convert(500, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
80.144 + exceptionThrown = false;
80.145 + } catch (InvalidCurrencyException e) {
80.146 + exceptionThrown = true;
80.147 + }
80.148 + assertEquals("It should be impossible to convert from SKK with USD->CZK convertor", true, exceptionThrown);
80.149 +
80.150 + }
80.151 +
80.152 + /**
80.153 + * Verify that the CZK to SKK convertor knows nothing about USD.
80.154 + */
80.155 + public void testCannotConvertToSKKwithSKKCZKConvertor() throws Exception {
80.156 + Convertor c = createSKKtoCZK();
80.157 + boolean exceptionThrown = false;
80.158 +
80.159 + // convert $5 to SKK, the API shall say this is not possible
80.160 + try {
80.161 + c.convert(5, Currency.getInstance("USD"), Currency.getInstance("SKK"));
80.162 + exceptionThrown = false;
80.163 + } catch (InvalidCurrencyException e) {
80.164 + exceptionThrown = true;
80.165 + }
80.166 + assertEquals("It should be impossible to convert form USD with SKK->CZK convertor", true, exceptionThrown);
80.167 +
80.168 + // convert 500 CZK to USD, the API shall say this is not possible
80.169 + try {
80.170 + c.convert(500, Currency.getInstance("CZK"), Currency.getInstance("USD"));
80.171 + exceptionThrown = false;
80.172 + } catch (InvalidCurrencyException e) {
80.173 + exceptionThrown = true;
80.174 + }
80.175 + assertEquals("It should be impossible to convert to USD with SKK->CZK convertor", true, exceptionThrown);
80.176 + }
80.177 +}
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
81.2 +++ b/task3/solution12/test/org/apidesign/apifest08/test/Task2Test.java Tue Oct 07 11:05:34 2008 +0200
81.3 @@ -0,0 +1,132 @@
81.4 +package org.apidesign.apifest08.test;
81.5 +
81.6 +import java.util.Currency;
81.7 +
81.8 +import junit.framework.TestCase;
81.9 +
81.10 +import org.apidesign.apifest08.currency.Convertor;
81.11 +import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
81.12 +
81.13 +/** There are many currencies around the world and many banks manipulate
81.14 + * with more than one or two at the same time. As banks are usually the
81.15 + * best paying clients, which is true even in case of your Convertor API,
81.16 + * it is reasonable to listen to their requests.
81.17 + * <p>
81.18 + * The quest for today is to enhance your existing convertor API to hold
81.19 + * information about many currencies and allow conversions between any of them.
81.20 + * Also, as conversion rates for diferent currencies usually arise from various
81.21 + * bank departments, there is another important need. There is a need to
81.22 + * compose two convertors into one by merging all the information about
81.23 + * currencies they know about.
81.24 + */
81.25 +public class Task2Test extends TestCase {
81.26 + public Task2Test(String testName) {
81.27 + super(testName);
81.28 + }
81.29 +
81.30 + @Override
81.31 + protected void setUp() throws Exception {
81.32 + }
81.33 +
81.34 + @Override
81.35 + protected void tearDown() throws Exception {
81.36 + }
81.37 +
81.38 + // As in Task1Test, keep in mind, that there are three parts
81.39 + // of the whole system:
81.40 + // 1. there is someone who knows the current exchange rate
81.41 + // 2. there is someone who wants to do the conversion
81.42 + // 3. there is the API between 1. and 2. which allows them to communicate
81.43 + //
81.44 + // Please backward compatibly enhance your existing API to support following
81.45 + // usecases:
81.46 + //
81.47 +
81.48 + /** Create convertor that understands two currencies, CZK and
81.49 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
81.50 + * knows the exchange rate, and needs to use the API to create objects
81.51 + * with the exchange rate. Anyone shall be ready to call this method without
81.52 + * any other method being called previously. The API itself shall know
81.53 + * nothing about any rates, before this method is called.
81.54 + */
81.55 + public static Convertor createTripleConvertor() {
81.56 + // Rates: 1USD = 15CZK
81.57 + // Rates: 1USD = 20SKK
81.58 + // Rates: 75CZK = 100SKK
81.59 + // set exchange rates
81.60 + Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("CZK"), 15, 1);
81.61 + Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("SKK"), 20, 1);
81.62 + Convertor.setConvertorRates(Currency.getInstance("SKK"), Currency.getInstance("CZK"), 75, 100);
81.63 +
81.64 + // create new instance
81.65 + Convertor convertor = null;
81.66 + try {
81.67 + convertor = Convertor.getConvertorInstance(Currency.getInstance("USD"), Currency.getInstance("SKK"), Currency.getInstance("CZK"));
81.68 + } catch (UnknownConvertorException e) {
81.69 + e.printStackTrace();
81.70 + }
81.71 + return convertor;
81.72 + }
81.73 +
81.74 + /** Define convertor that understands three currencies. Use it.
81.75 + */
81.76 + public void testConvertorForUSDandCZKandSKK() throws Exception {
81.77 + Convertor c = createTripleConvertor();
81.78 +
81.79 + // convert $5 to CZK using c:
81.80 + double result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
81.81 + assertEquals("Result is not 75 CZK", 75.0, result);
81.82 +
81.83 + // convert $5 to SKK using c:
81.84 + result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("SKK"));
81.85 + assertEquals("Result is not 100 SKK", 100.0, result);
81.86 +
81.87 + // convert 200SKK to CZK using c:
81.88 + result = c.convert(200d, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
81.89 + assertEquals("Result is not 150 CZK", 150.0, result);
81.90 +
81.91 + // convert 200SKK to USK using c:
81.92 + result = c.convert(200d, Currency.getInstance("SKK"), Currency.getInstance("USD"));
81.93 + assertEquals("Result is not 10 USD", 10.0, result);
81.94 + }
81.95 +
81.96 + /** Merge all currency rates of convertor 1 with convertor 2.
81.97 + * Implement this using your API, preferably this method just delegates
81.98 + * into some API method which does the actual work, without requiring
81.99 + * API clients to code anything complex.
81.100 + */
81.101 + public static Convertor merge(Convertor one, Convertor two) {
81.102 + return one.merge(two);
81.103 + }
81.104 +
81.105 + /** Join the convertors from previous task, Task1Test and show that it
81.106 + * can be used to do reasonable conversions.
81.107 + */
81.108 + public void testConvertorComposition() throws Exception {
81.109 + Convertor c = merge(
81.110 + Task1Test.createCZKtoUSD(),
81.111 + Task1Test.createSKKtoCZK()
81.112 + );
81.113 +
81.114 + // convert $5 to CZK using c:
81.115 + double result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
81.116 + assertEquals("Result is not 85 CZK", 85.0, result);
81.117 +
81.118 + // convert $8 to CZK using c:
81.119 + result = c.convert(8d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
81.120 + assertEquals("Result is not 136 CZK", 136.0, result);
81.121 +
81.122 + // convert 1003CZK to USD using c:
81.123 + result = c.convert(1003d, Currency.getInstance("CZK"), Currency.getInstance("USD"));
81.124 + assertEquals("Result is not 59 USD", 59.0, result);
81.125 +
81.126 + // convert 16CZK using c:
81.127 + result = c.convert(16d, Currency.getInstance("CZK"), Currency.getInstance("SKK"));
81.128 + assertEquals("Result is not 20 SKK", 20.0, result);
81.129 +
81.130 + // convert 500SKK to CZK using c:
81.131 + result = c.convert(500d, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
81.132 + assertEquals("Result is not 400 CZK", 400.0, result);
81.133 +
81.134 + }
81.135 +}
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/task3/solution13/build.xml Tue Oct 07 11:05:34 2008 +0200
82.3 @@ -0,0 +1,69 @@
82.4 +<?xml version="1.0" encoding="UTF-8"?>
82.5 +<!-- You may freely edit this file. See commented blocks below for -->
82.6 +<!-- some examples of how to customize the build. -->
82.7 +<!-- (If you delete it and reopen the project it will be recreated.) -->
82.8 +<project name="currency" default="default" basedir=".">
82.9 + <description>Builds, tests, and runs the project.</description>
82.10 + <import file="nbproject/build-impl.xml"/>
82.11 + <!--
82.12 +
82.13 + There exist several targets which are by default empty and which can be
82.14 + used for execution of your tasks. These targets are usually executed
82.15 + before and after some main targets. They are:
82.16 +
82.17 + -pre-init: called before initialization of project properties
82.18 + -post-init: called after initialization of project properties
82.19 + -pre-compile: called before javac compilation
82.20 + -post-compile: called after javac compilation
82.21 + -pre-compile-single: called before javac compilation of single file
82.22 + -post-compile-single: called after javac compilation of single file
82.23 + -pre-compile-test: called before javac compilation of JUnit tests
82.24 + -post-compile-test: called after javac compilation of JUnit tests
82.25 + -pre-compile-test-single: called before javac compilation of single JUnit test
82.26 + -post-compile-test-single: called after javac compilation of single JUunit test
82.27 + -pre-jar: called before JAR building
82.28 + -post-jar: called after JAR building
82.29 + -post-clean: called after cleaning build products
82.30 +
82.31 + (Targets beginning with '-' are not intended to be called on their own.)
82.32 +
82.33 + Example of inserting an obfuscator after compilation could look like this:
82.34 +
82.35 + <target name="-post-compile">
82.36 + <obfuscate>
82.37 + <fileset dir="${build.classes.dir}"/>
82.38 + </obfuscate>
82.39 + </target>
82.40 +
82.41 + For list of available properties check the imported
82.42 + nbproject/build-impl.xml file.
82.43 +
82.44 +
82.45 + Another way to customize the build is by overriding existing main targets.
82.46 + The targets of interest are:
82.47 +
82.48 + -init-macrodef-javac: defines macro for javac compilation
82.49 + -init-macrodef-junit: defines macro for junit execution
82.50 + -init-macrodef-debug: defines macro for class debugging
82.51 + -init-macrodef-java: defines macro for class execution
82.52 + -do-jar-with-manifest: JAR building (if you are using a manifest)
82.53 + -do-jar-without-manifest: JAR building (if you are not using a manifest)
82.54 + run: execution of project
82.55 + -javadoc-build: Javadoc generation
82.56 + test-report: JUnit report generation
82.57 +
82.58 + An example of overriding the target for project execution could look like this:
82.59 +
82.60 + <target name="run" depends="currency-impl.jar">
82.61 + <exec dir="bin" executable="launcher.exe">
82.62 + <arg file="${dist.jar}"/>
82.63 + </exec>
82.64 + </target>
82.65 +
82.66 + Notice that the overridden target depends on the jar target and not only on
82.67 + the compile target as the regular run target does. Again, for a list of available
82.68 + properties which you can use, check the target you are overriding in the
82.69 + nbproject/build-impl.xml file.
82.70 +
82.71 + -->
82.72 +</project>
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/task3/solution13/nbproject/build-impl.xml Tue Oct 07 11:05:34 2008 +0200
83.3 @@ -0,0 +1,642 @@
83.4 +<?xml version="1.0" encoding="UTF-8"?>
83.5 +<!--
83.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
83.7 +*** EDIT ../build.xml INSTEAD ***
83.8 +
83.9 +For the purpose of easier reading the script
83.10 +is divided into following sections:
83.11 +
83.12 + - initialization
83.13 + - compilation
83.14 + - jar
83.15 + - execution
83.16 + - debugging
83.17 + - javadoc
83.18 + - junit compilation
83.19 + - junit execution
83.20 + - junit debugging
83.21 + - applet
83.22 + - cleanup
83.23 +
83.24 + -->
83.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_13-impl">
83.26 + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
83.27 + <!--
83.28 + ======================
83.29 + INITIALIZATION SECTION
83.30 + ======================
83.31 + -->
83.32 + <target name="-pre-init">
83.33 + <!-- Empty placeholder for easier customization. -->
83.34 + <!-- You can override this target in the ../build.xml file. -->
83.35 + </target>
83.36 + <target depends="-pre-init" name="-init-private">
83.37 + <property file="nbproject/private/config.properties"/>
83.38 + <property file="nbproject/private/configs/${config}.properties"/>
83.39 + <property file="nbproject/private/private.properties"/>
83.40 + </target>
83.41 + <target depends="-pre-init,-init-private" name="-init-user">
83.42 + <property file="${user.properties.file}"/>
83.43 + <!-- The two properties below are usually overridden -->
83.44 + <!-- by the active platform. Just a fallback. -->
83.45 + <property name="default.javac.source" value="1.4"/>
83.46 + <property name="default.javac.target" value="1.4"/>
83.47 + </target>
83.48 + <target depends="-pre-init,-init-private,-init-user" name="-init-project">
83.49 + <property file="nbproject/configs/${config}.properties"/>
83.50 + <property file="nbproject/project.properties"/>
83.51 + </target>
83.52 + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
83.53 + <available file="${manifest.file}" property="manifest.available"/>
83.54 + <condition property="manifest.available+main.class">
83.55 + <and>
83.56 + <isset property="manifest.available"/>
83.57 + <isset property="main.class"/>
83.58 + <not>
83.59 + <equals arg1="${main.class}" arg2="" trim="true"/>
83.60 + </not>
83.61 + </and>
83.62 + </condition>
83.63 + <condition property="manifest.available+main.class+mkdist.available">
83.64 + <and>
83.65 + <istrue value="${manifest.available+main.class}"/>
83.66 + <isset property="libs.CopyLibs.classpath"/>
83.67 + </and>
83.68 + </condition>
83.69 + <condition property="have.tests">
83.70 + <or>
83.71 + <available file="${test.src.dir}"/>
83.72 + </or>
83.73 + </condition>
83.74 + <condition property="have.sources">
83.75 + <or>
83.76 + <available file="${src.dir}"/>
83.77 + </or>
83.78 + </condition>
83.79 + <condition property="netbeans.home+have.tests">
83.80 + <and>
83.81 + <isset property="netbeans.home"/>
83.82 + <isset property="have.tests"/>
83.83 + </and>
83.84 + </condition>
83.85 + <condition property="no.javadoc.preview">
83.86 + <and>
83.87 + <isset property="javadoc.preview"/>
83.88 + <isfalse value="${javadoc.preview}"/>
83.89 + </and>
83.90 + </condition>
83.91 + <property name="run.jvmargs" value=""/>
83.92 + <property name="javac.compilerargs" value=""/>
83.93 + <property name="work.dir" value="${basedir}"/>
83.94 + <condition property="no.deps">
83.95 + <and>
83.96 + <istrue value="${no.dependencies}"/>
83.97 + </and>
83.98 + </condition>
83.99 + <property name="javac.debug" value="true"/>
83.100 + <property name="javadoc.preview" value="true"/>
83.101 + <property name="application.args" value=""/>
83.102 + <property name="source.encoding" value="${file.encoding}"/>
83.103 + <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
83.104 + <and>
83.105 + <isset property="javadoc.encoding"/>
83.106 + <not>
83.107 + <equals arg1="${javadoc.encoding}" arg2=""/>
83.108 + </not>
83.109 + </and>
83.110 + </condition>
83.111 + <property name="javadoc.encoding.used" value="${source.encoding}"/>
83.112 + <property name="includes" value="**"/>
83.113 + <property name="excludes" value=""/>
83.114 + <property name="do.depend" value="false"/>
83.115 + <condition property="do.depend.true">
83.116 + <istrue value="${do.depend}"/>
83.117 + </condition>
83.118 + <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
83.119 + <and>
83.120 + <isset property="jaxws.endorsed.dir"/>
83.121 + <available file="nbproject/jaxws-build.xml"/>
83.122 + </and>
83.123 + </condition>
83.124 + </target>
83.125 + <target name="-post-init">
83.126 + <!-- Empty placeholder for easier customization. -->
83.127 + <!-- You can override this target in the ../build.xml file. -->
83.128 + </target>
83.129 + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
83.130 + <fail unless="src.dir">Must set src.dir</fail>
83.131 + <fail unless="test.src.dir">Must set test.src.dir</fail>
83.132 + <fail unless="build.dir">Must set build.dir</fail>
83.133 + <fail unless="dist.dir">Must set dist.dir</fail>
83.134 + <fail unless="build.classes.dir">Must set build.classes.dir</fail>
83.135 + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
83.136 + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
83.137 + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
83.138 + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
83.139 + <fail unless="dist.jar">Must set dist.jar</fail>
83.140 + </target>
83.141 + <target name="-init-macrodef-property">
83.142 + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
83.143 + <attribute name="name"/>
83.144 + <attribute name="value"/>
83.145 + <sequential>
83.146 + <property name="@{name}" value="${@{value}}"/>
83.147 + </sequential>
83.148 + </macrodef>
83.149 + </target>
83.150 + <target name="-init-macrodef-javac">
83.151 + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
83.152 + <attribute default="${src.dir}" name="srcdir"/>
83.153 + <attribute default="${build.classes.dir}" name="destdir"/>
83.154 + <attribute default="${javac.classpath}" name="classpath"/>
83.155 + <attribute default="${includes}" name="includes"/>
83.156 + <attribute default="${excludes}" name="excludes"/>
83.157 + <attribute default="${javac.debug}" name="debug"/>
83.158 + <attribute default="" name="sourcepath"/>
83.159 + <element name="customize" optional="true"/>
83.160 + <sequential>
83.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}">
83.162 + <classpath>
83.163 + <path path="@{classpath}"/>
83.164 + </classpath>
83.165 + <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
83.166 + <customize/>
83.167 + </javac>
83.168 + </sequential>
83.169 + </macrodef>
83.170 + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
83.171 + <attribute default="${src.dir}" name="srcdir"/>
83.172 + <attribute default="${build.classes.dir}" name="destdir"/>
83.173 + <attribute default="${javac.classpath}" name="classpath"/>
83.174 + <sequential>
83.175 + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
83.176 + <classpath>
83.177 + <path path="@{classpath}"/>
83.178 + </classpath>
83.179 + </depend>
83.180 + </sequential>
83.181 + </macrodef>
83.182 + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
83.183 + <attribute default="${build.classes.dir}" name="destdir"/>
83.184 + <sequential>
83.185 + <fail unless="javac.includes">Must set javac.includes</fail>
83.186 + <pathconvert pathsep="," property="javac.includes.binary">
83.187 + <path>
83.188 + <filelist dir="@{destdir}" files="${javac.includes}"/>
83.189 + </path>
83.190 + <globmapper from="*.java" to="*.class"/>
83.191 + </pathconvert>
83.192 + <delete>
83.193 + <files includes="${javac.includes.binary}"/>
83.194 + </delete>
83.195 + </sequential>
83.196 + </macrodef>
83.197 + </target>
83.198 + <target name="-init-macrodef-junit">
83.199 + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
83.200 + <attribute default="${includes}" name="includes"/>
83.201 + <attribute default="${excludes}" name="excludes"/>
83.202 + <attribute default="**" name="testincludes"/>
83.203 + <sequential>
83.204 + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
83.205 + <batchtest todir="${build.test.results.dir}">
83.206 + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
83.207 + <filename name="@{testincludes}"/>
83.208 + </fileset>
83.209 + </batchtest>
83.210 + <classpath>
83.211 + <path path="${run.test.classpath}"/>
83.212 + </classpath>
83.213 + <syspropertyset>
83.214 + <propertyref prefix="test-sys-prop."/>
83.215 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
83.216 + </syspropertyset>
83.217 + <formatter type="brief" usefile="false"/>
83.218 + <formatter type="xml"/>
83.219 + <jvmarg line="${run.jvmargs}"/>
83.220 + </junit>
83.221 + </sequential>
83.222 + </macrodef>
83.223 + </target>
83.224 + <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
83.225 + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
83.226 + <attribute default="${main.class}" name="name"/>
83.227 + <attribute default="${debug.classpath}" name="classpath"/>
83.228 + <attribute default="" name="stopclassname"/>
83.229 + <sequential>
83.230 + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
83.231 + <classpath>
83.232 + <path path="@{classpath}"/>
83.233 + </classpath>
83.234 + </nbjpdastart>
83.235 + </sequential>
83.236 + </macrodef>
83.237 + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
83.238 + <attribute default="${build.classes.dir}" name="dir"/>
83.239 + <sequential>
83.240 + <nbjpdareload>
83.241 + <fileset dir="@{dir}" includes="${fix.classes}">
83.242 + <include name="${fix.includes}*.class"/>
83.243 + </fileset>
83.244 + </nbjpdareload>
83.245 + </sequential>
83.246 + </macrodef>
83.247 + </target>
83.248 + <target name="-init-debug-args">
83.249 + <property name="version-output" value="java version "${ant.java.version}"/>
83.250 + <condition property="have-jdk-older-than-1.4">
83.251 + <or>
83.252 + <contains string="${version-output}" substring="java version "1.0"/>
83.253 + <contains string="${version-output}" substring="java version "1.1"/>
83.254 + <contains string="${version-output}" substring="java version "1.2"/>
83.255 + <contains string="${version-output}" substring="java version "1.3"/>
83.256 + </or>
83.257 + </condition>
83.258 + <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
83.259 + <istrue value="${have-jdk-older-than-1.4}"/>
83.260 + </condition>
83.261 + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
83.262 + <os family="windows"/>
83.263 + </condition>
83.264 + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
83.265 + <isset property="debug.transport"/>
83.266 + </condition>
83.267 + </target>
83.268 + <target depends="-init-debug-args" name="-init-macrodef-debug">
83.269 + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
83.270 + <attribute default="${main.class}" name="classname"/>
83.271 + <attribute default="${debug.classpath}" name="classpath"/>
83.272 + <element name="customize" optional="true"/>
83.273 + <sequential>
83.274 + <java classname="@{classname}" dir="${work.dir}" fork="true">
83.275 + <jvmarg line="${debug-args-line}"/>
83.276 + <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
83.277 + <jvmarg line="${run.jvmargs}"/>
83.278 + <classpath>
83.279 + <path path="@{classpath}"/>
83.280 + </classpath>
83.281 + <syspropertyset>
83.282 + <propertyref prefix="run-sys-prop."/>
83.283 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
83.284 + </syspropertyset>
83.285 + <customize/>
83.286 + </java>
83.287 + </sequential>
83.288 + </macrodef>
83.289 + </target>
83.290 + <target name="-init-macrodef-java">
83.291 + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
83.292 + <attribute default="${main.class}" name="classname"/>
83.293 + <element name="customize" optional="true"/>
83.294 + <sequential>
83.295 + <java classname="@{classname}" dir="${work.dir}" fork="true">
83.296 + <jvmarg line="${run.jvmargs}"/>
83.297 + <classpath>
83.298 + <path path="${run.classpath}"/>
83.299 + </classpath>
83.300 + <syspropertyset>
83.301 + <propertyref prefix="run-sys-prop."/>
83.302 + <mapper from="run-sys-prop.*" to="*" type="glob"/>
83.303 + </syspropertyset>
83.304 + <customize/>
83.305 + </java>
83.306 + </sequential>
83.307 + </macrodef>
83.308 + </target>
83.309 + <target name="-init-presetdef-jar">
83.310 + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
83.311 + <jar compress="${jar.compress}" jarfile="${dist.jar}">
83.312 + <j2seproject1:fileset dir="${build.classes.dir}"/>
83.313 + </jar>
83.314 + </presetdef>
83.315 + </target>
83.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"/>
83.317 + <!--
83.318 + ===================
83.319 + COMPILATION SECTION
83.320 + ===================
83.321 + -->
83.322 + <target depends="init" name="deps-jar" unless="no.deps"/>
83.323 + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
83.324 + <target depends="init" name="-check-automatic-build">
83.325 + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
83.326 + </target>
83.327 + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
83.328 + <antcall target="clean"/>
83.329 + </target>
83.330 + <target depends="init,deps-jar" name="-pre-pre-compile">
83.331 + <mkdir dir="${build.classes.dir}"/>
83.332 + </target>
83.333 + <target name="-pre-compile">
83.334 + <!-- Empty placeholder for easier customization. -->
83.335 + <!-- You can override this target in the ../build.xml file. -->
83.336 + </target>
83.337 + <target if="do.depend.true" name="-compile-depend">
83.338 + <j2seproject3:depend/>
83.339 + </target>
83.340 + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
83.341 + <j2seproject3:javac/>
83.342 + <copy todir="${build.classes.dir}">
83.343 + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
83.344 + </copy>
83.345 + </target>
83.346 + <target name="-post-compile">
83.347 + <!-- Empty placeholder for easier customization. -->
83.348 + <!-- You can override this target in the ../build.xml file. -->
83.349 + </target>
83.350 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
83.351 + <target name="-pre-compile-single">
83.352 + <!-- Empty placeholder for easier customization. -->
83.353 + <!-- You can override this target in the ../build.xml file. -->
83.354 + </target>
83.355 + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
83.356 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
83.357 + <j2seproject3:force-recompile/>
83.358 + <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
83.359 + </target>
83.360 + <target name="-post-compile-single">
83.361 + <!-- Empty placeholder for easier customization. -->
83.362 + <!-- You can override this target in the ../build.xml file. -->
83.363 + </target>
83.364 + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
83.365 + <!--
83.366 + ====================
83.367 + JAR BUILDING SECTION
83.368 + ====================
83.369 + -->
83.370 + <target depends="init" name="-pre-pre-jar">
83.371 + <dirname file="${dist.jar}" property="dist.jar.dir"/>
83.372 + <mkdir dir="${dist.jar.dir}"/>
83.373 + </target>
83.374 + <target name="-pre-jar">
83.375 + <!-- Empty placeholder for easier customization. -->
83.376 + <!-- You can override this target in the ../build.xml file. -->
83.377 + </target>
83.378 + <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
83.379 + <j2seproject1:jar/>
83.380 + </target>
83.381 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
83.382 + <j2seproject1:jar manifest="${manifest.file}"/>
83.383 + </target>
83.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">
83.385 + <j2seproject1:jar manifest="${manifest.file}">
83.386 + <j2seproject1:manifest>
83.387 + <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
83.388 + </j2seproject1:manifest>
83.389 + </j2seproject1:jar>
83.390 + <echo>To run this application from the command line without Ant, try:</echo>
83.391 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
83.392 + <property location="${dist.jar}" name="dist.jar.resolved"/>
83.393 + <pathconvert property="run.classpath.with.dist.jar">
83.394 + <path path="${run.classpath}"/>
83.395 + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
83.396 + </pathconvert>
83.397 + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
83.398 + </target>
83.399 + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
83.400 + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
83.401 + <pathconvert property="run.classpath.without.build.classes.dir">
83.402 + <path path="${run.classpath}"/>
83.403 + <map from="${build.classes.dir.resolved}" to=""/>
83.404 + </pathconvert>
83.405 + <pathconvert pathsep=" " property="jar.classpath">
83.406 + <path path="${run.classpath.without.build.classes.dir}"/>
83.407 + <chainedmapper>
83.408 + <flattenmapper/>
83.409 + <globmapper from="*" to="lib/*"/>
83.410 + </chainedmapper>
83.411 + </pathconvert>
83.412 + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
83.413 + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
83.414 + <fileset dir="${build.classes.dir}"/>
83.415 + <manifest>
83.416 + <attribute name="Main-Class" value="${main.class}"/>
83.417 + <attribute name="Class-Path" value="${jar.classpath}"/>
83.418 + </manifest>
83.419 + </copylibs>
83.420 + <echo>To run this application from the command line without Ant, try:</echo>
83.421 + <property location="${dist.jar}" name="dist.jar.resolved"/>
83.422 + <echo>java -jar "${dist.jar.resolved}"</echo>
83.423 + </target>
83.424 + <target name="-post-jar">
83.425 + <!-- Empty placeholder for easier customization. -->
83.426 + <!-- You can override this target in the ../build.xml file. -->
83.427 + </target>
83.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"/>
83.429 + <!--
83.430 + =================
83.431 + EXECUTION SECTION
83.432 + =================
83.433 + -->
83.434 + <target depends="init,compile" description="Run a main class." name="run">
83.435 + <j2seproject1:java>
83.436 + <customize>
83.437 + <arg line="${application.args}"/>
83.438 + </customize>
83.439 + </j2seproject1:java>
83.440 + </target>
83.441 + <target name="-do-not-recompile">
83.442 + <property name="javac.includes.binary" value=""/>
83.443 + </target>
83.444 + <target depends="init,-do-not-recompile,compile-single" name="run-single">
83.445 + <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
83.446 + <j2seproject1:java classname="${run.class}"/>
83.447 + </target>
83.448 + <!--
83.449 + =================
83.450 + DEBUGGING SECTION
83.451 + =================
83.452 + -->
83.453 + <target depends="init" if="netbeans.home" name="-debug-start-debugger">
83.454 + <j2seproject1:nbjpdastart name="${debug.class}"/>
83.455 + </target>
83.456 + <target depends="init,compile" name="-debug-start-debuggee">
83.457 + <j2seproject3:debug>
83.458 + <customize>
83.459 + <arg line="${application.args}"/>
83.460 + </customize>
83.461 + </j2seproject3:debug>
83.462 + </target>
83.463 + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
83.464 + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
83.465 + <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
83.466 + </target>
83.467 + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
83.468 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
83.469 + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
83.470 + <j2seproject3:debug classname="${debug.class}"/>
83.471 + </target>
83.472 + <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
83.473 + <target depends="init" name="-pre-debug-fix">
83.474 + <fail unless="fix.includes">Must set fix.includes</fail>
83.475 + <property name="javac.includes" value="${fix.includes}.java"/>
83.476 + </target>
83.477 + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
83.478 + <j2seproject1:nbjpdareload/>
83.479 + </target>
83.480 + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
83.481 + <!--
83.482 + ===============
83.483 + JAVADOC SECTION
83.484 + ===============
83.485 + -->
83.486 + <target depends="init" name="-javadoc-build">
83.487 + <mkdir dir="${dist.javadoc.dir}"/>
83.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}">
83.489 + <classpath>
83.490 + <path path="${javac.classpath}"/>
83.491 + </classpath>
83.492 + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
83.493 + <filename name="**/*.java"/>
83.494 + </fileset>
83.495 + </javadoc>
83.496 + </target>
83.497 + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
83.498 + <nbbrowse file="${dist.javadoc.dir}/index.html"/>
83.499 + </target>
83.500 + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
83.501 + <!--
83.502 + =========================
83.503 + JUNIT COMPILATION SECTION
83.504 + =========================
83.505 + -->
83.506 + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
83.507 + <mkdir dir="${build.test.classes.dir}"/>
83.508 + </target>
83.509 + <target name="-pre-compile-test">
83.510 + <!-- Empty placeholder for easier customization. -->
83.511 + <!-- You can override this target in the ../build.xml file. -->
83.512 + </target>
83.513 + <target if="do.depend.true" name="-compile-test-depend">
83.514 + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
83.515 + </target>
83.516 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
83.517 + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
83.518 + <copy todir="${build.test.classes.dir}">
83.519 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
83.520 + </copy>
83.521 + </target>
83.522 + <target name="-post-compile-test">
83.523 + <!-- Empty placeholder for easier customization. -->
83.524 + <!-- You can override this target in the ../build.xml file. -->
83.525 + </target>
83.526 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
83.527 + <target name="-pre-compile-test-single">
83.528 + <!-- Empty placeholder for easier customization. -->
83.529 + <!-- You can override this target in the ../build.xml file. -->
83.530 + </target>
83.531 + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
83.532 + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
83.533 + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
83.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}"/>
83.535 + <copy todir="${build.test.classes.dir}">
83.536 + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
83.537 + </copy>
83.538 + </target>
83.539 + <target name="-post-compile-test-single">
83.540 + <!-- Empty placeholder for easier customization. -->
83.541 + <!-- You can override this target in the ../build.xml file. -->
83.542 + </target>
83.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"/>
83.544 + <!--
83.545 + =======================
83.546 + JUNIT EXECUTION SECTION
83.547 + =======================
83.548 + -->
83.549 + <target depends="init" if="have.tests" name="-pre-test-run">
83.550 + <mkdir dir="${build.test.results.dir}"/>
83.551 + </target>
83.552 + <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
83.553 + <j2seproject3:junit testincludes="**/*Test.java"/>
83.554 + </target>
83.555 + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
83.556 + <fail if="tests.failed">Some tests failed; see details above.</fail>
83.557 + </target>
83.558 + <target depends="init" if="have.tests" name="test-report"/>
83.559 + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
83.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"/>
83.561 + <target depends="init" if="have.tests" name="-pre-test-run-single">
83.562 + <mkdir dir="${build.test.results.dir}"/>
83.563 + </target>
83.564 + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
83.565 + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
83.566 + <j2seproject3:junit excludes="" includes="${test.includes}"/>
83.567 + </target>
83.568 + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
83.569 + <fail if="tests.failed">Some tests failed; see details above.</fail>
83.570 + </target>
83.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"/>
83.572 + <!--
83.573 + =======================
83.574 + JUNIT DEBUGGING SECTION
83.575 + =======================
83.576 + -->
83.577 + <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
83.578 + <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
83.579 + <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
83.580 + <delete file="${test.report.file}"/>
83.581 + <mkdir dir="${build.test.results.dir}"/>
83.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}">
83.583 + <customize>
83.584 + <syspropertyset>
83.585 + <propertyref prefix="test-sys-prop."/>
83.586 + <mapper from="test-sys-prop.*" to="*" type="glob"/>
83.587 + </syspropertyset>
83.588 + <arg value="${test.class}"/>
83.589 + <arg value="showoutput=true"/>
83.590 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
83.591 + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
83.592 + </customize>
83.593 + </j2seproject3:debug>
83.594 + </target>
83.595 + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
83.596 + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
83.597 + </target>
83.598 + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
83.599 + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
83.600 + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
83.601 + </target>
83.602 + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
83.603 + <!--
83.604 + =========================
83.605 + APPLET EXECUTION SECTION
83.606 + =========================
83.607 + -->
83.608 + <target depends="init,compile-single" name="run-applet">
83.609 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
83.610 + <j2seproject1:java classname="sun.applet.AppletViewer">
83.611 + <customize>
83.612 + <arg value="${applet.url}"/>
83.613 + </customize>
83.614 + </j2seproject1:java>
83.615 + </target>
83.616 + <!--
83.617 + =========================
83.618 + APPLET DEBUGGING SECTION
83.619 + =========================
83.620 + -->
83.621 + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
83.622 + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
83.623 + <j2seproject3:debug classname="sun.applet.AppletViewer">
83.624 + <customize>
83.625 + <arg value="${applet.url}"/>
83.626 + </customize>
83.627 + </j2seproject3:debug>
83.628 + </target>
83.629 + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
83.630 + <!--
83.631 + ===============
83.632 + CLEANUP SECTION
83.633 + ===============
83.634 + -->
83.635 + <target depends="init" name="deps-clean" unless="no.deps"/>
83.636 + <target depends="init" name="-do-clean">
83.637 + <delete dir="${build.dir}"/>
83.638 + <delete dir="${dist.dir}"/>
83.639 + </target>
83.640 + <target name="-post-clean">
83.641 + <!-- Empty placeholder for easier customization. -->
83.642 + <!-- You can override this target in the ../build.xml file. -->
83.643 + </target>
83.644 + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
83.645 +</project>
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/task3/solution13/nbproject/genfiles.properties Tue Oct 07 11:05:34 2008 +0200
84.3 @@ -0,0 +1,8 @@
84.4 +build.xml.data.CRC32=2ab820eb
84.5 +build.xml.script.CRC32=58a52595
84.6 +build.xml.stylesheet.CRC32=be360661
84.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
84.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
84.9 +nbproject/build-impl.xml.data.CRC32=de21ce77
84.10 +nbproject/build-impl.xml.script.CRC32=0903858a
84.11 +nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/task3/solution13/nbproject/project.properties Tue Oct 07 11:05:34 2008 +0200
85.3 @@ -0,0 +1,68 @@
85.4 +application.title=currency
85.5 +application.vendor=apidesign.org
85.6 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
85.7 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
85.8 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
85.9 +build.classes.dir=${build.dir}/classes
85.10 +build.classes.excludes=**/*.java,**/*.form
85.11 +# This directory is removed when the project is cleaned:
85.12 +build.dir=build
85.13 +build.generated.dir=${build.dir}/generated
85.14 +# Only compile against the classpath explicitly listed here:
85.15 +build.sysclasspath=ignore
85.16 +build.test.classes.dir=${build.dir}/test/classes
85.17 +build.test.results.dir=${build.dir}/test/results
85.18 +debug.classpath=\
85.19 + ${run.classpath}
85.20 +debug.test.classpath=\
85.21 + ${run.test.classpath}
85.22 +# This directory is removed when the project is cleaned:
85.23 +dist.dir=dist
85.24 +dist.jar=${dist.dir}/currency.jar
85.25 +dist.javadoc.dir=${dist.dir}/javadoc
85.26 +excludes=
85.27 +file.reference.junit-4.4.jar=../../libs/junit-4.4.jar
85.28 +file.reference.src-apifest08=..
85.29 +includes=**
85.30 +jar.compress=false
85.31 +javac.classpath=
85.32 +# Space-separated list of extra javac options
85.33 +javac.compilerargs=
85.34 +javac.deprecation=false
85.35 +javac.source=1.5
85.36 +javac.target=1.5
85.37 +javac.test.classpath=\
85.38 + ${javac.classpath}:\
85.39 + ${build.classes.dir}:\
85.40 + ${file.reference.junit-4.4.jar}
85.41 +javadoc.additionalparam=
85.42 +javadoc.author=false
85.43 +javadoc.encoding=
85.44 +javadoc.noindex=false
85.45 +javadoc.nonavbar=false
85.46 +javadoc.notree=false
85.47 +javadoc.private=false
85.48 +javadoc.splitindex=true
85.49 +javadoc.use=true
85.50 +javadoc.version=false
85.51 +javadoc.windowtitle=
85.52 +jnlp.codebase.type=local
85.53 +jnlp.codebase.url=file:/home/jarda/src/apifest08/currency/dist
85.54 +jnlp.descriptor=application
85.55 +jnlp.enabled=false
85.56 +jnlp.offline-allowed=false
85.57 +jnlp.signed=false
85.58 +meta.inf.dir=${src.dir}/META-INF
85.59 +platform.active=default_platform
85.60 +run.classpath=\
85.61 + ${javac.classpath}:\
85.62 + ${build.classes.dir}
85.63 +# Space-separated list of JVM arguments used when running the project
85.64 +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
85.65 +# or test-sys-prop.name=value to set system properties for unit tests):
85.66 +run.jvmargs=
85.67 +run.test.classpath=\
85.68 + ${javac.test.classpath}:\
85.69 + ${build.test.classes.dir}
85.70 +src.dir=src
85.71 +test.src.dir=test
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/task3/solution13/nbproject/project.xml Tue Oct 07 11:05:34 2008 +0200
86.3 @@ -0,0 +1,16 @@
86.4 +<?xml version="1.0" encoding="UTF-8"?>
86.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
86.6 + <type>org.netbeans.modules.java.j2seproject</type>
86.7 + <configuration>
86.8 + <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
86.9 + <name>Currency Convertor Solution 13</name>
86.10 + <minimum-ant-version>1.6.5</minimum-ant-version>
86.11 + <source-roots>
86.12 + <root id="src.dir"/>
86.13 + </source-roots>
86.14 + <test-roots>
86.15 + <root id="test.src.dir"/>
86.16 + </test-roots>
86.17 + </data>
86.18 + </configuration>
86.19 +</project>
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/task3/solution13/src/org/apidesign/apifest08/currency/ConversionNotSupportedException.java Tue Oct 07 11:05:34 2008 +0200
87.3 @@ -0,0 +1,85 @@
87.4 +package org.apidesign.apifest08.currency;
87.5 +
87.6 +/**
87.7 + * Conversion not suported exception. This expecption may optionaly describe which conversion was required and failed.
87.8 + * Required conversion can be found in {@link #getFromCurrecyCode() } and {@link #getToCurrecyCode() }.
87.9 + *
87.10 + * @author arnostvalicek
87.11 + * @since version2
87.12 + */
87.13 +public class ConversionNotSupportedException extends ConvertorException {
87.14 + String from;
87.15 + String to;
87.16 + boolean reversed;
87.17 +
87.18 + public ConversionNotSupportedException() {
87.19 + super();
87.20 + }
87.21 +
87.22 + public ConversionNotSupportedException(String message) {
87.23 + super(message);
87.24 + }
87.25 +
87.26 + public ConversionNotSupportedException(String message, Throwable cause) {
87.27 + super(message, cause);
87.28 + }
87.29 +
87.30 + public ConversionNotSupportedException(Throwable cause) {
87.31 + super(cause);
87.32 + }
87.33 +
87.34 + /**
87.35 + * Create exception witd additional information about currencies which are not supported in coversion.
87.36 + * @param from Code of source currency.
87.37 + * @param to Code of target currency.
87.38 + * @param twoWay Set to <code>false</code> if <em>From->To</em> is not supported.
87.39 + * Set to <code>true</code> if both ways <em>From->To</em> and <em>To->From</em> conversions are not supported.
87.40 + *
87.41 + */
87.42 + public ConversionNotSupportedException(String from, String to, boolean twoWay) {
87.43 + this.from = from;
87.44 + this.to = to;
87.45 + this.reversed = true;
87.46 + }
87.47 +
87.48 + @Override
87.49 + public String toString() {
87.50 + if (from!=null && to !=null) {
87.51 + if (reversed) {
87.52 + return "Neither onversion nor reverted conversion from " + from + " to " + to + " is not supported,";
87.53 + } else {
87.54 + return "Conversion from " + from + " to " + to + " is not supported,";
87.55 + }
87.56 + } else {
87.57 + return super.toString();
87.58 + }
87.59 + }
87.60 +
87.61 + /**
87.62 + * Returns code of source currency. This value may be null.
87.63 + * @return Returns code of source currency.
87.64 + */
87.65 + public String getFromCurrecyCode() {
87.66 + return from;
87.67 + }
87.68 +
87.69 + /**
87.70 + * Returns code of target currency. This value may be null.
87.71 + * @return Returns code of target currency.
87.72 + */ public String getToCurrecyCode() {
87.73 + return to;
87.74 + }
87.75 +
87.76 + /**
87.77 + * Returns if one way of two way conversion is not supported.
87.78 + *
87.79 + * Value <code>false</code> means one way conversion is not supported. Value <code>true</code> means
87.80 + * that two way conversio is not supported.
87.81 + *
87.82 + * @return Returs <code>false</code> for one way conversion, <code>true</code> for two way conversion.
87.83 + */
87.84 + public boolean getTwoWayConversion() {
87.85 + return reversed;
87.86 + }
87.87 +
87.88 +}
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/task3/solution13/src/org/apidesign/apifest08/currency/ConversionResult.java Tue Oct 07 11:05:34 2008 +0200
88.3 @@ -0,0 +1,49 @@
88.4 +
88.5 +package org.apidesign.apifest08.currency;
88.6 +
88.7 +import java.math.BigDecimal;
88.8 +
88.9 +/**
88.10 + * Result of currency conversion. Holds converted value and remainder.
88.11 + * <p>
88.12 + * <em>Converted</em> describes value converted to <em>target</em> currenty. <em>Remainder</em> describes
88.13 + * how much from original <em>amount</em> was not possible to convert. Convertor never loses any (small) money
88.14 + * in conversion error (rounding), but instead of rounding is converts only as much as possible and keeps rest as remainder.
88.15 + *
88.16 + * @author arnostvalicek
88.17 + */
88.18 +public class ConversionResult {
88.19 + private BigDecimal converted;
88.20 + private BigDecimal remainder;
88.21 +
88.22 + /**
88.23 + * Get converted value.
88.24 + * @return Returns converted value.
88.25 + */
88.26 + public BigDecimal getConverted() {
88.27 + return converted;
88.28 + }
88.29 +
88.30 + void setConverted(BigDecimal converted) {
88.31 + this.converted = converted;
88.32 + }
88.33 +
88.34 +
88.35 + /**
88.36 + * Get remainder of conversion. Remainder is set if part of converted amount which can't be converted
88.37 + * because this target currency precision can't handle small numbers. Remainder value is in <em>from currency</em>
88.38 + * <p>
88.39 + * Converter never loses any precision in conversion. Remainer describes how much of amount can't be converted.
88.40 + * If we substract <em>remainder</em> from <em>amount</em> we will be able to get exact conversion.
88.41 + *
88.42 + * @return Returns remainder of conversion.
88.43 + */
88.44 + public BigDecimal getRemainder() {
88.45 + return remainder;
88.46 + }
88.47 +
88.48 + void setRemainder(BigDecimal remainder) {
88.49 + this.remainder = remainder;
88.50 + }
88.51 +
88.52 +}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/task3/solution13/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 11:05:34 2008 +0200
89.3 @@ -0,0 +1,213 @@
89.4 +package org.apidesign.apifest08.currency;
89.5 +
89.6 +import java.math.BigDecimal;
89.7 +import java.math.MathContext;
89.8 +import java.math.RoundingMode;
89.9 +
89.10 +/** Convertor able to convert amount from one currency to other currency.
89.11 + * <p>
89.12 + * Conversion method are:
89.13 + * <ul>
89.14 + * <li>{@link #convert(ConvertorCurrency, ConvertorCurrency, BigDecimal)} - convert using exchange rate specified in exchange rate provide. <em>Do not try use reverted excahnage rate</em>.
89.15 + * <li>{@link #convertWithReversibleRates(ConvertorCurrency, ConvertorCurrency, BigDecimal)} - convert using exchange rate specified in exchange rate provide. <em>Try use reverted excahnage rate</em>.
89.16 + * </ul>
89.17 + *
89.18 + * Exchange rate is provided by {@link ExchangeRateProvider}.
89.19 + */
89.20 +public class Convertor {
89.21 + private Convertor[] convertors;
89.22 +
89.23 + /** Create new <code>Convertor</code> as merge of provided convertors. Merged convertor will use
89.24 + * provided convertors to convert between currencies.
89.25 + * <p>
89.26 + * Only one should be able to provide conversion between currencies. If more than one convertos
89.27 + * are able to convert currency, one of conversions will be used (it is not defined which).
89.28 + *
89.29 + * @since version 2
89.30 + * @param convertors Convertor used to create merge-convertor.
89.31 + * @return Returns new convertor instance.
89.32 + */
89.33 + public static Convertor createConvertorAsMerge(Convertor[] convertors) {
89.34 + return new Convertor(convertors);
89.35 + }
89.36 +
89.37 + boolean remainderAllowed = true; //if false, remained is not allowed (should be true ideally, but can't handle it now)
89.38 + ExchangeRateProvider exchangeRateProvider;
89.39 +
89.40 + /** Create simle convertor.
89.41 + */
89.42 + private Convertor() {
89.43 + this.convertors=new Convertor[0];
89.44 + }
89.45 +
89.46 + /** Create merge convertor.
89.47 + */
89.48 + private Convertor(Convertor[] convertors) {
89.49 + this.convertors = convertors;
89.50 + }
89.51 +
89.52 + /**
89.53 + * Create new <code>Convertor</code> using <code>ExchangeRateProvider</code>.
89.54 + *
89.55 + * @param exchangeRateProvider {@link ExchangeRateProvider} used to get exchange rate.
89.56 + *
89.57 + * @return Returns <code>Convertor</code> which can be used to convert money.
89.58 + * @since version1
89.59 + */
89.60 + public static Convertor createConvertor(ExchangeRateProvider exchangeRateProvider) {
89.61 + Convertor c = new Convertor();
89.62 +
89.63 + c.exchangeRateProvider = exchangeRateProvider;
89.64 + return c;
89.65 + }
89.66 +
89.67 + /**
89.68 + * Convert <code>amount</code> from <code>fromCurrency</code> to <code>toCurrency</code> as specified
89.69 + * in <code>ExchangeRateProvider</code>.
89.70 + *
89.71 + * @param amount Amount which should be converted. Can't be negative value (can be zero or positive).
89.72 + * @return Return <code>ConversionResult</code> which holds conversion result.
89.73 + * @since version1
89.74 + * @deprecated since version2. Use {@link #convert(ConvertorCurrency, ConvertorCurrency, BigDecimal) } - explicitly specify conversion currencies.
89.75 + */
89.76 + public ConversionResult convert(BigDecimal amount) {
89.77 + return convertValue(exchangeRateProvider.getFromCurrency(), exchangeRateProvider.getToCurrency(),amount, false,false);
89.78 + }
89.79 +
89.80 + /**
89.81 + * Convert <code>amount</code> from <code>toCurrency</code> to <code>fromCurrency</code> as specified
89.82 + * in <code>ExchangeRateProvider</code>. This is <em>reverted</em> order than suggested by names of currency fields in <code>ExchangeRate</code>.
89.83 + *
89.84 + * @param amount Amount which should be converted. Can't be negative value (can be zero or positive).
89.85 + * @return Return <code>ConversionResult</code> which holds conversion result.
89.86 + * @since version1
89.87 + * @deprecated since version2. Use {@link #convert(ConvertorCurrency, ConvertorCurrency, BigDecimal) } - explicitly specify conversion currencies.
89.88 + */
89.89 + public ConversionResult convertBack(BigDecimal amount) {
89.90 + return convertValue(exchangeRateProvider.getFromCurrency(), exchangeRateProvider.getToCurrency(),amount, true,false);
89.91 + }
89.92 +
89.93 + private ConversionResult convertUsingSimpleConvertor(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency, boolean reversibleExRate, BigDecimal amount, boolean convertBack) throws ConversionNotSupportedException, RuntimeException {
89.94 + ConversionResult result = new ConversionResult();
89.95 +
89.96 + //ExchangeRate rate = exchangeRateProvider.getExchangeRate();
89.97 + ExchangeRate rate;
89.98 + if (reversibleExRate) {
89.99 + rate = exchangeRateProvider.getReversibleExchangeRate(fromCurrency, toCurrency);
89.100 + } else {
89.101 + rate = exchangeRateProvider.getExchangeRate(fromCurrency, toCurrency);
89.102 + }
89.103 + if (rate == null) {
89.104 + return null;
89.105 + }
89.106 +
89.107 + int fromFranctionDigits = fromCurrency.getDefaultFractionDigits();
89.108 + int toFractionDigits = toCurrency.getDefaultFractionDigits();
89.109 +
89.110 + if (toFractionDigits != 2) {
89.111 + throw new ConvertorException("Can't process currency with defaultFractionDigits!=2, " + exchangeRateProvider.getToCurrency() + " has " + toFractionDigits + " defaultFractionDigits");
89.112 + }
89.113 + if (fromFranctionDigits != 2) {
89.114 + throw new ConvertorException("Can't process currency with defaultFractionDigits!=2, " + exchangeRateProvider.getFromCurrency() + " has " + fromFranctionDigits + " defaultFractionDigits");
89.115 + }
89.116 +
89.117 + if (amount.signum() == -1) {
89.118 + throw new RuntimeException("Can convert only non-negative value, current value is " + amount);
89.119 + }
89.120 +
89.121 +
89.122 + MathContext context = new MathContext(0, RoundingMode.DOWN);
89.123 +
89.124 + BigDecimal from;
89.125 + BigDecimal to;
89.126 + if (convertBack) {
89.127 + //converting in reverted way
89.128 + to = rate.getFromValue();
89.129 + from = rate.getToValue();
89.130 + } else {
89.131 + //converting in normal way
89.132 + from = rate.getFromValue();
89.133 + to = rate.getToValue();
89.134 + }
89.135 +
89.136 + BigDecimal amountCent = amount.movePointRight(2);
89.137 +
89.138 + final BigDecimal multiplied = amountCent.multiply(to, context);
89.139 + BigDecimal[] division = multiplied.divideAndRemainder(from, context);
89.140 +
89.141 + if (!remainderAllowed && !(BigDecimal.ZERO.equals(division[1]))) {
89.142 + throw new RuntimeException("Remained is not allowed - remaining amount is " + division[1] + " cents");
89.143 + } else {
89.144 + result.setRemainder(BigDecimal.ZERO);
89.145 + }
89.146 +
89.147 + final BigDecimal converted = division[0].movePointLeft(2);
89.148 + result.setConverted(converted);
89.149 + //result.setRemainder(...);
89.150 + return result;
89.151 + }
89.152 +
89.153 +
89.154 + private ConversionResult convertValue(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency,BigDecimal amount, boolean convertBack,boolean reversibleExRate) throws RuntimeException {
89.155 + //result.setRemainder(...);
89.156 + if (convertors.length==0) {
89.157 + return convertUsingSimpleConvertor(fromCurrency, toCurrency, reversibleExRate, amount, convertBack);
89.158 + } else {
89.159 + ConversionResult result = null;
89.160 + for (int i = 0;i<convertors.length;i++) {
89.161 + Convertor subConvertor = convertors[i];
89.162 + result = subConvertor.convertValue(fromCurrency, toCurrency, amount, convertBack, reversibleExRate);
89.163 + if (result!=null) {
89.164 + break;
89.165 + }
89.166 + }
89.167 + return result;
89.168 + }
89.169 + }
89.170 +
89.171 + /**
89.172 + * Convert <code>value</code> from <code>fromCurrency</code> to <code>toCurrency</code>.
89.173 + * <p>
89.174 + * Exchange rate is provided by exchange rate provider which was specified when Convertor was created.
89.175 + * This method is using only exchange rate from->to and not trying to use reverted excange rate to->from.
89.176 + *
89.177 + * @param fromCurrency Source currency to convert from.
89.178 + * @param toCurrency Target currency to convert to.
89.179 + * @param value Value in source currency which should be converted.
89.180 + * @return Return conversion result.
89.181 + * @since version2
89.182 + * @throws ConversionNotSupportedException If conversion from <code>fromCurrency</code> to <code>toCurrency</code> is not supported.
89.183 + */
89.184 + public ConversionResult convert(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency, BigDecimal value) {
89.185 + ConversionResult result = convertValue(fromCurrency, toCurrency, value, false,false);
89.186 + if (result==null) {
89.187 + //throw new ConversionNotSupportedException("Conversion from " + fromCurrency + " to " + toCurrency + " is not supported");
89.188 + throw new ConversionNotSupportedException(fromCurrency.getCurrencyCode(),toCurrency.getCurrencyCode(),false);
89.189 + }
89.190 + return result;
89.191 + }
89.192 +
89.193 + /**
89.194 + * Convert <code>value</code> from <code>fromCurrency</code> to <code>toCurrency</code>.
89.195 + * Exchange rate is provided by exchange rate provider which was specified when Convertor was created.
89.196 + * <p>
89.197 + * This method is using only exchange rate from->to and if not found, it is trying to use reverted excange rate to->from.
89.198 + *
89.199 + * @param fromCurrency Source currency to convert from.
89.200 + * @param toCurrency Target currency to convert to.
89.201 + * @param value Value in source currency which should be converted.
89.202 + * @return Return conversion result.
89.203 + * @since version2
89.204 + * @throws ConversionNotSupportedException If conversion from <code>fromCurrency</code> to <code>toCurrency</code>
89.205 + * is not supported and neither conversion from <code>toCurrency</code> to <code>fromCurrency</code> is not supported.
89.206 + */
89.207 + public ConversionResult convertWithReversibleRates(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency, BigDecimal value) {
89.208 + ConversionResult result = convertValue(fromCurrency, toCurrency, value, false,true);
89.209 + if (result==null) {
89.210 + //throw new ConversionNotSupportedException("Neither onversion nor reverted conversion from " + fromCurrency + " to " + toCurrency + " is not supported,");
89.211 + throw new ConversionNotSupportedException(fromCurrency.getCurrencyCode(),toCurrency.getCurrencyCode(),true);
89.212 + }
89.213 + return result;
89.214 + }
89.215 +
89.216 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/task3/solution13/src/org/apidesign/apifest08/currency/ConvertorCurrency.java Tue Oct 07 11:05:34 2008 +0200
90.3 @@ -0,0 +1,63 @@
90.4 +
90.5 +package org.apidesign.apifest08.currency;
90.6 +
90.7 +import java.util.Currency;
90.8 +
90.9 +/**
90.10 + * Desription of currency.
90.11 + *
90.12 + * Java has similar class {@link java.util.Currency}, but original class is not flexible
90.13 + * enough, we use our own implementation of currency.
90.14 + *
90.15 + * @author arnostvalicek
90.16 + */
90.17 +public class ConvertorCurrency {
90.18 +
90.19 + private Currency currency;
90.20 +
90.21 + private void setJavaCurrency(Currency javaCurrency) {
90.22 + this.currency = javaCurrency;
90.23 + }
90.24 +
90.25 + /**
90.26 + * Static method providing instance of <code>ConvertorCurrency</code> base of currency code.
90.27 + *
90.28 + * @param currencyCode Code of required currency.
90.29 + * @return Returns required <code>ConvertorCurrency</code>
90.30 + */
90.31 + public static ConvertorCurrency getInstance(String currencyCode) {
90.32 + ConvertorCurrency convertorCurrency = new ConvertorCurrency();
90.33 + convertorCurrency.setJavaCurrency(Currency.getInstance(currencyCode));
90.34 + return convertorCurrency;
90.35 + }
90.36 +
90.37 + /**
90.38 + * Gets the default number of fraction digits used with this currency. For example, the default number of fraction digits for the Euro is 2, while for the Japanese Yen it's 0.
90.39 + * @return Returns the default number of fraction digits used with this currency.
90.40 + */
90.41 + public int getDefaultFractionDigits() {
90.42 + return currency.getDefaultFractionDigits();
90.43 + }
90.44 +
90.45 + @Override
90.46 + public boolean equals(Object obj) {
90.47 + boolean result;
90.48 + if (obj instanceof ConvertorCurrency) {
90.49 + ConvertorCurrency that = (ConvertorCurrency) obj;
90.50 + result = currency.equals(that.currency);
90.51 + } else {
90.52 + result = false;
90.53 + }
90.54 + return result;
90.55 + }
90.56 +
90.57 +
90.58 + @Override
90.59 + public String toString() {
90.60 + return "ConvertorCurrency[" + (currency != null ? currency.toString() : "NO-BASE-CURRENCY")+"]";
90.61 + }
90.62 +
90.63 + String getCurrencyCode() {
90.64 + return currency.getCurrencyCode();
90.65 + }
90.66 +}
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/task3/solution13/src/org/apidesign/apifest08/currency/ConvertorException.java Tue Oct 07 11:05:34 2008 +0200
91.3 @@ -0,0 +1,25 @@
91.4 +package org.apidesign.apifest08.currency;
91.5 +
91.6 +/**
91.7 + * Common Convertor exception.
91.8 + *
91.9 + * @author arnostvalicek
91.10 + */
91.11 +public class ConvertorException extends RuntimeException {
91.12 +
91.13 + public ConvertorException(Throwable cause) {
91.14 + super(cause);
91.15 + }
91.16 +
91.17 + public ConvertorException(String message, Throwable cause) {
91.18 + super(message, cause);
91.19 + }
91.20 +
91.21 + public ConvertorException(String message) {
91.22 + super(message);
91.23 + }
91.24 +
91.25 + public ConvertorException() {
91.26 + }
91.27 +
91.28 +}
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92.2 +++ b/task3/solution13/src/org/apidesign/apifest08/currency/ExchangeRate.java Tue Oct 07 11:05:34 2008 +0200
92.3 @@ -0,0 +1,68 @@
92.4 +
92.5 +package org.apidesign.apifest08.currency;
92.6 +
92.7 +import java.math.BigDecimal;
92.8 +
92.9 +/**
92.10 + * Exchange rate value. Contains <code>from</code> and <code>to</code> value.
92.11 + *
92.12 + * @author arnostvalicek
92.13 + */
92.14 +public class ExchangeRate {
92.15 + private BigDecimal numberFor;
92.16 + private BigDecimal numberGet;
92.17 +
92.18 + /**
92.19 + * Constructor for new exchange rate holding two values - <em>from value</em> and <em>to value</em>
92.20 + * @param fromValue Exchange rate <em>from value</em>
92.21 + * @param toValue Exchange rate <em>to value</em>
92.22 + */
92.23 + public ExchangeRate(BigDecimal fromValue, BigDecimal toValue) {
92.24 + this.numberFor = fromValue;
92.25 + this.numberGet = toValue;
92.26 + }
92.27 +
92.28 + /**
92.29 + * Create new instance of <code>ExchangeRate</code> based on provided exchange rate, but swapping its
92.30 + * <em>from</em> and <em>to</em> value.
92.31 + * <p>
92.32 + * Provided exchange rate is not chaged, this method returns different instance describing reverted exchange rate.
92.33 + *
92.34 + * @param rate Exchange rate which describes rate to be reverted.
92.35 + * @return Instance of reverted rate.
92.36 + */
92.37 + public static ExchangeRate createRevertedRate(ExchangeRate rate) {
92.38 + ExchangeRate reverted = new ExchangeRate(rate.getToValue(), rate.getFromValue());
92.39 + return reverted;
92.40 + }
92.41 +
92.42 + @Override
92.43 + public String toString() {
92.44 + return "for "+numberFor+" recieve "+numberGet+" @"+getClass().getName();
92.45 + }
92.46 +
92.47 + /**
92.48 + * Return exchange rate <em>from</em> value stored in this object.
92.49 + * @return Returns <em>from</em> value for this exchange rate.
92.50 + */
92.51 + public BigDecimal getFromValue() {
92.52 + return numberFor;
92.53 + }
92.54 +
92.55 + /**
92.56 + * Return exchange rate <em>to</em> value stored in this object.
92.57 + * @return Returns <em>to</em> value for this exchange rate.
92.58 + */
92.59 + public BigDecimal getToValue() {
92.60 + return numberGet;
92.61 + }
92.62 +
92.63 +
92.64 +// public ExchangeRate createExchangeRate(BigDecimal forValue, BigDecimal getValue) {
92.65 +// ExchangeRate rate = new ExchangeRate(forValue, getValue);
92.66 +// return rate;
92.67 +// }
92.68 +
92.69 +
92.70 +
92.71 +}
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
93.2 +++ b/task3/solution13/src/org/apidesign/apifest08/currency/ExchangeRateProvider.java Tue Oct 07 11:05:34 2008 +0200
93.3 @@ -0,0 +1,152 @@
93.4 +
93.5 +package org.apidesign.apifest08.currency;
93.6 +
93.7 +import java.math.BigDecimal;
93.8 +import java.util.Date;
93.9 +import java.util.HashMap;
93.10 +import java.util.Map;
93.11 +
93.12 +/**
93.13 + * Exchange rate provider. Provides fixed exchange rate which does not depend
93.14 + * on date (method {@link #getExchangeRate()} ).
93.15 + *
93.16 + * Date dependend exchange rate to be implemented.
93.17 + *
93.18 + * @author arnostvalicek
93.19 + */
93.20 +public class ExchangeRateProvider {
93.21 + BigDecimal fromValue, toValue;
93.22 + ConvertorCurrency fromCurrency, toCurrency;
93.23 +
93.24 + Map exchangeRateMap = new HashMap();
93.25 +
93.26 + /**
93.27 + * Simple constructor for <code>ExchangeRateProviderM</code> which can provide fixed exchange rate.
93.28 + *
93.29 + * Describes conversion <em>from ONE</em> to <em>to ONE</em> currency.
93.30 + *
93.31 + * @param fromValue From value. BigDecimal value, precision should be set to currency precision.
93.32 + * @param fromCurrency From currency.
93.33 + * @param toValue To value. BigDecimal value, precision should be set to currency precision.
93.34 + * @param toCurrency To currency.
93.35 + * @deprecated deprecated since task2. Use {@link #createExchangeRateProvider() } instead of this constructor.
93.36 + */
93.37 + public ExchangeRateProvider(BigDecimal fromValue, ConvertorCurrency fromCurrency, BigDecimal toValue, ConvertorCurrency toCurrency) {
93.38 + this.fromValue = fromValue;
93.39 + this.toValue = toValue;
93.40 + this.fromCurrency = fromCurrency;
93.41 + this.toCurrency = toCurrency;
93.42 + }
93.43 +
93.44 + private ExchangeRateProvider() {
93.45 +
93.46 + }
93.47 +
93.48 + /**
93.49 + * Static method to create new exchange rate provider. This exchange rate provider does not contain
93.50 + * any exchange rates (this is difference to public constructor).
93.51 + * @return New <code>ExchangeRateProvider</code>
93.52 + */
93.53 + public static ExchangeRateProvider createExchangeRateProvider() {
93.54 + ExchangeRateProvider provider = new ExchangeRateProvider();
93.55 + return provider;
93.56 + }
93.57 +
93.58 + /**
93.59 + * Add new exchange rate to <code></code> to this exchange rate provider.
93.60 + * <p>
93.61 + * Example of specifiing conversion rate: 100 SKK == 80 CZK:<br>
93.62 + * <code>addFixedCurencyRate(ConvertorCurrency.getInstance("SKK"), new BigDecimal(100), ConvertorCurrency.getInstance("CZK"), new BigDecimal(80));</code>
93.63 + * <p>
93.64 + *
93.65 + * @param fromCurrency Source currency.
93.66 + * @param fromValue Valye for from currency.
93.67 + * @param toCurrency Target currency.
93.68 + * @param toValue Value for target currency.
93.69 + */
93.70 + public synchronized void addFixedCurencyRate(ConvertorCurrency fromCurrency, BigDecimal fromValue, ConvertorCurrency toCurrency, BigDecimal toValue) {
93.71 + if (fromValue==null) {
93.72 + throw new NullPointerException("fromValue can't be null");
93.73 + }
93.74 + if (toValue==null) {
93.75 + throw new NullPointerException("toValue can't be null");
93.76 + }
93.77 + Map map2 = (Map) exchangeRateMap.get(fromCurrency);
93.78 + if (map2==null) {
93.79 + map2 = new HashMap();
93.80 + exchangeRateMap.put(fromCurrency, map2);
93.81 + }
93.82 +
93.83 + ExchangeRate rate = new ExchangeRate(fromValue, toValue);
93.84 + map2.put(toCurrency, rate);
93.85 + }
93.86 +
93.87 + /**
93.88 + * Get fixed exange rate for currencies (from->to).
93.89 + * @return Returns exchange rate.
93.90 + * @deprecated deprecated since task2. Use {@link #getExchangeRate(ConvertorCurrency, ConvertorCurrency) }
93.91 + */
93.92 + public ExchangeRate getExchangeRate() {
93.93 + return new ExchangeRate(fromValue, toValue);
93.94 + }
93.95 +
93.96 +
93.97 + /**
93.98 + * Get fixed exange rate for currencies (from->to).
93.99 + * @return Returns exchange rate or <code>null</code> if exchange rate not found.
93.100 + */
93.101 + public ExchangeRate getExchangeRate(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
93.102 + return getExchangeRateImpl(fromCurrency, toCurrency);
93.103 + }
93.104 +
93.105 + /**
93.106 + * Get fixed exange rate for currencies (from->to) or reversed exchange rate (to->from).
93.107 + * @return Returns exchange rate or <code>null</code> if exchange rate not found.
93.108 + */
93.109 + public ExchangeRate getReversibleExchangeRate(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
93.110 + ExchangeRate rate = getExchangeRateImpl(fromCurrency, toCurrency);
93.111 + if (rate==null) {
93.112 + ExchangeRate revertedRate = getExchangeRateImpl(toCurrency, fromCurrency);
93.113 + if (revertedRate!=null) {
93.114 + rate = ExchangeRate.createRevertedRate(revertedRate);
93.115 + }
93.116 + }
93.117 + return rate;
93.118 + }
93.119 +
93.120 +
93.121 +
93.122 + /**
93.123 + * Get exchange rate for currencies (from->to) based on provided date.
93.124 + * @param date Date for which exchange rate should be provided.
93.125 + * @return Returns exchange rate
93.126 + * @deprecated deprecated since task2. No real implementation in version2.
93.127 + */
93.128 + public ExchangeRate getExchangeRate(Date date) {
93.129 + return new ExchangeRate(fromValue, toValue);
93.130 + }
93.131 +
93.132 +
93.133 + ConvertorCurrency getFromCurrency() {
93.134 + return fromCurrency;
93.135 + }
93.136 +
93.137 + ConvertorCurrency getToCurrency() {
93.138 + return toCurrency;
93.139 + }
93.140 +
93.141 + private ExchangeRate getExchangeRateImpl(ConvertorCurrency fromCurrency, ConvertorCurrency toCurrency) {
93.142 + if (fromValue != null && toValue != null && fromCurrency.equals(this.fromCurrency) && toCurrency.equals(this.toCurrency)) {
93.143 + return new ExchangeRate(fromValue, toValue);
93.144 + }
93.145 + //return new ExchangeRate(fromValue, toValue);
93.146 + Map map2 = (Map) exchangeRateMap.get(fromCurrency);
93.147 + if (map2 == null) {
93.148 + return null;
93.149 + }
93.150 + ExchangeRate result = (ExchangeRate) map2.get(toCurrency);
93.151 + return result;
93.152 + }
93.153 +
93.154 +
93.155 +}
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94.2 +++ b/task3/solution13/test/org/apidesign/apifest08/test/Task1Test.java Tue Oct 07 11:05:34 2008 +0200
94.3 @@ -0,0 +1,223 @@
94.4 +package org.apidesign.apifest08.test;
94.5 +
94.6 +import java.math.BigDecimal;
94.7 +import junit.framework.TestCase;
94.8 +import org.apidesign.apifest08.currency.ConversionResult;
94.9 +import org.apidesign.apifest08.currency.Convertor;
94.10 +import org.apidesign.apifest08.currency.ConvertorCurrency;
94.11 +import org.apidesign.apifest08.currency.ExchangeRateProvider;
94.12 +import org.apidesign.apifest08.currency.ConversionNotSupportedException;
94.13 +
94.14 +/** Finish the Convertor API, and then write bodies of methods inside
94.15 + * of this class to match the given tasks. To fullfil your task, use the
94.16 + * API define in the <code>org.apidesign.apifest08.currency</code> package.
94.17 + * Do not you reflection, or other hacks as your code
94.18 + * shall run without any runtime permissions.
94.19 + */
94.20 +public class Task1Test extends TestCase {
94.21 + public Task1Test(String testName) {
94.22 + super(testName);
94.23 + }
94.24 +
94.25 + @Override
94.26 + protected void setUp() throws Exception {
94.27 + }
94.28 +
94.29 + @Override
94.30 + protected void tearDown() throws Exception {
94.31 + }
94.32 +
94.33 + /** Create convertor that understands two currencies, CZK and
94.34 + * USD. Make 1 USD == 17 CZK.
94.35 + *
94.36 + * Creation of the convertor shall not require subclassing of any class
94.37 + * or interface on the client side.
94.38 + *
94.39 + * @return prepared convertor ready for converting USD to CZK and CZK to USD
94.40 + */
94.41 + public static Convertor createCZKtoUSD() {
94.42 + ConvertorCurrency fromCurrency = ConvertorCurrency.getInstance("CZK");
94.43 + ConvertorCurrency toCurrency = ConvertorCurrency.getInstance("USD");
94.44 + ExchangeRateProvider exchangeRateProvider = new ExchangeRateProvider(new BigDecimal(17), fromCurrency, new BigDecimal(1), toCurrency);
94.45 +
94.46 + return Convertor.createConvertor(exchangeRateProvider);
94.47 + }
94.48 +
94.49 + /** Create convertor that understands two currencies, CZK and
94.50 + * SKK. Make 100 SKK == 80 CZK.
94.51 + *
94.52 + * Creation of the convertor shall not require subclassing of any class
94.53 + * or interface on the client side.
94.54 + *
94.55 + * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
94.56 + */
94.57 + public static Convertor createSKKtoCZK() {
94.58 + ConvertorCurrency fromCurrency = ConvertorCurrency.getInstance("SKK");
94.59 + ConvertorCurrency toCurrency = ConvertorCurrency.getInstance("CZK");
94.60 + ExchangeRateProvider exchangeRateProvider = new ExchangeRateProvider(new BigDecimal(100), fromCurrency, new BigDecimal(80), toCurrency);
94.61 +
94.62 + return Convertor.createConvertor(exchangeRateProvider);
94.63 + }
94.64 +
94.65 +
94.66 + public static Convertor createCZKtoYEN() {
94.67 + ConvertorCurrency fromCurrency = ConvertorCurrency.getInstance("CZK");
94.68 + ConvertorCurrency toCurrency = ConvertorCurrency.getInstance("JPY");
94.69 + ExchangeRateProvider exchangeRateProvider = new ExchangeRateProvider(new BigDecimal(1), fromCurrency, new BigDecimal(1), toCurrency);
94.70 +
94.71 + return Convertor.createConvertor(exchangeRateProvider);
94.72 + }
94.73 +
94.74 + /** Use the convertor from <code>createCZKtoUSD</code> method and do few conversions
94.75 + * with it.
94.76 + */
94.77 + public void testCurrencyCZKUSD() throws Exception {
94.78 + Convertor convertCzkUsd = createCZKtoUSD();
94.79 +
94.80 + {
94.81 + // convert $1 to CZK using c:
94.82 + ConversionResult result = convertCzkUsd.convertBack(new BigDecimal(1));
94.83 + assertEquals("Result is 17 CZK", new BigDecimal("17.00"), result.getConverted());
94.84 + assertEquals("No Remainer", BigDecimal.ZERO, result.getRemainder());
94.85 + }
94.86 +
94.87 + {
94.88 + // convert 17CKZ to $ using c:
94.89 + ConversionResult result = convertCzkUsd.convert(new BigDecimal(17));
94.90 + assertEquals("Result is 1 $", new BigDecimal("1.00"), result.getConverted());
94.91 + assertEquals("No Remainer", BigDecimal.ZERO, result.getRemainder());
94.92 + }
94.93 +
94.94 + {
94.95 + // convert $5 to CZK using c:
94.96 + ConversionResult result = convertCzkUsd.convertBack(new BigDecimal(5));
94.97 + assertEquals("Result is 85 CZK", new BigDecimal("85.00"), result.getConverted());
94.98 + assertEquals("No Remainer", BigDecimal.ZERO, result.getRemainder());
94.99 + }
94.100 +
94.101 + {
94.102 + // convert $8 to CZK
94.103 + ConversionResult result = convertCzkUsd.convertBack(new BigDecimal(8));
94.104 + assertEquals("Result is 136 CZK", new BigDecimal("136.00"), result.getConverted());
94.105 + assertEquals("No Remainer", BigDecimal.ZERO, result.getRemainder());
94.106 + }
94.107 +
94.108 + {
94.109 + // convert 1003CZK to USD
94.110 + ConversionResult result = convertCzkUsd.convert(new BigDecimal(1003));
94.111 + assertEquals("Result is 59 USD", new BigDecimal("59.00"), result.getConverted());
94.112 + assertEquals("No Remainer", BigDecimal.ZERO, result.getRemainder());
94.113 + }
94.114 + }
94.115 +
94.116 + /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
94.117 + * with it.
94.118 + */
94.119 + public void testCurrencySKKCZK() throws Exception {
94.120 + Convertor convertSkkCzk = createSKKtoCZK();
94.121 + {
94.122 + // convert 100SKK using c:
94.123 + ConversionResult result = convertSkkCzk.convert(new BigDecimal(100));
94.124 + assertEquals("Result is 80 CZK", new BigDecimal("80.00"), result.getConverted());
94.125 + }
94.126 + {
94.127 + // convert 80CZK using c:
94.128 + ConversionResult result = convertSkkCzk.convertBack(new BigDecimal(80));
94.129 + assertEquals("Result is 100 SKK", new BigDecimal("100.00"), result.getConverted());
94.130 + }
94.131 +
94.132 + {
94.133 + // convert 16CZK using c:
94.134 + ConversionResult result = convertSkkCzk.convertBack(new BigDecimal(16));
94.135 + assertEquals("Result is 20 SKK", new BigDecimal("20.00"), result.getConverted());
94.136 + }
94.137 +
94.138 + {
94.139 + // convert 500SKK to CZK
94.140 + ConversionResult result = convertSkkCzk.convert(new BigDecimal(500));
94.141 + assertEquals("Result is 400 CZK", new BigDecimal("400.00"), result.getConverted());
94.142 + assertEquals("No Remainer", BigDecimal.ZERO, result.getRemainder());
94.143 + }
94.144 +
94.145 + {
94.146 + // convert 501SKK to CZK
94.147 + ConversionResult result = convertSkkCzk.convert(new BigDecimal(501));
94.148 + assertEquals("Result is 400 CZK", new BigDecimal("400.80"), result.getConverted());
94.149 + assertEquals("No Remainer", BigDecimal.ZERO, result.getRemainder());
94.150 +
94.151 + }
94.152 + }
94.153 +
94.154 + /**
94.155 + * Convert SKK to CZK. Convertor can't convert whole amout (can't convert one SKK cent to CZK). Remaining
94.156 + * amount is stored in remainder result.
94.157 + *
94.158 + * Test is currently failing, because implementation can't handle this case.
94.159 + */
94.160 +// public void testConvertSmallUnits_failing() {
94.161 +// Convertor convertSkkCzk = createSKKtoCZK();
94.162 +// {
94.163 +// // convert 501SKK to CZK
94.164 +// ConversionResult result = convertSkkCzk.convert(new BigDecimal("501.01"));
94.165 +// assertEquals("Result is 400 CZK", new BigDecimal("400.80"), result.getConverted());
94.166 +// assertEquals("No Remainer", new BigDecimal("0.01"), result.getRemainder());
94.167 +//
94.168 +// }
94.169 +//
94.170 +// }
94.171 +
94.172 + /**
94.173 + * Test converting from CZK to JPY. Remained has scale of CZK.
94.174 + *
94.175 + * This test is currently failing, because converter implementation currently can't handle conversion from "cent" to "no-cent" currency.
94.176 + */
94.177 +// public void testConvertCzkToJpy_failing() {
94.178 +// Convertor convertSkkCzk = createCZKtoYEN();
94.179 +// {
94.180 +// // convert 501SKK to CZK
94.181 +// ConversionResult result = convertSkkCzk.convert(new BigDecimal("120.00"));
94.182 +// assertEquals("Result is 120 YEN", new BigDecimal("120"), result.getConverted());
94.183 +// assertEquals("No Remainer", new BigDecimal("0.00"), result.getRemainder());
94.184 +//
94.185 +// }
94.186 +// }
94.187 +
94.188 + /**
94.189 + * Test converting from JPY to CZK. Remained has scale of JPY.
94.190 + *
94.191 + * This test is currently failing, because converter implementation currently can't handle conversion from "cent" to "no-cent" currency.
94.192 + */
94.193 +// public void testConvertJpyToCzk_failing() {
94.194 +// Convertor convertSkkCzk = createCZKtoYEN();
94.195 +// {
94.196 +// // convert 501SKK to CZK
94.197 +// ConversionResult result = convertSkkCzk.convert(new BigDecimal("120.00"));
94.198 +// assertEquals("Result is 120 YEN", new BigDecimal("120"), result.getConverted());
94.199 +// assertEquals("No Remainer", new BigDecimal("0"), result.getRemainder());
94.200 +//
94.201 +// }
94.202 +// }
94.203 +
94.204 + public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
94.205 + Convertor c = createCZKtoUSD();
94.206 + // convert $5 to SKK, the API shall say this is not possible
94.207 + try {
94.208 + c.convert(ConvertorCurrency.getInstance("USD"), ConvertorCurrency.getInstance("SKK"), new BigDecimal(5));
94.209 + fail();
94.210 + } catch (ConversionNotSupportedException e) {
94.211 + //expected error;
94.212 + assertEquals("Exception From USD", "USD",e.getFromCurrecyCode());
94.213 + assertEquals("Exception To SKK", "SKK",e.getToCurrecyCode());
94.214 + }
94.215 + // convert 500 SKK to CZK, the API shall say this is not possible
94.216 + try {
94.217 + c.convert(ConvertorCurrency.getInstance("SKK"), ConvertorCurrency.getInstance("CZK"), new BigDecimal(500));
94.218 + fail();
94.219 + } catch (ConversionNotSupportedException e) {
94.220 + assertEquals("Exception From USD", "SKK",e.getFromCurrecyCode());
94.221 + assertEquals("Exception To SKK", "CZK",e.getToCurrecyCode()); }
94.222 + }
94.223 +
94.224 +
94.225 +}
94.226 +
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/task3/solution13/test/org/apidesign/apifest08/test/Task2Test.java Tue Oct 07 11:05:34 2008 +0200
95.3 @@ -0,0 +1,136 @@
95.4 +package org.apidesign.apifest08.test;
95.5 +
95.6 +import java.math.BigDecimal;
95.7 +import junit.framework.TestCase;
95.8 +import org.apidesign.apifest08.currency.Convertor;
95.9 +import org.apidesign.apifest08.currency.ConvertorCurrency;
95.10 +import org.apidesign.apifest08.currency.ExchangeRateProvider;
95.11 +
95.12 +/** There are many currencies around the world and many banks manipulate
95.13 + * with more than one or two at the same time. As banks are usually the
95.14 + * best paying clients, which is true even in case of your Convertor API,
95.15 + * it is reasonable to listen to their requests.
95.16 + * <p>
95.17 + * The quest for today is to enhance your existing convertor API to hold
95.18 + * information about many currencies and allow conversions between any of them.
95.19 + * Also, as conversion rates for diferent currencies usually arise from various
95.20 + * bank departments, there is another important need. There is a need to
95.21 + * compose two convertors into one by merging all the information about
95.22 + * currencies they know about.
95.23 + */
95.24 +public class Task2Test extends TestCase {
95.25 + private static ConvertorCurrency currencyCZK = ConvertorCurrency.getInstance("CZK");
95.26 + private static ConvertorCurrency currencySKK = ConvertorCurrency.getInstance("SKK");
95.27 + private static ConvertorCurrency currencyUSD = ConvertorCurrency.getInstance("USD");
95.28 +
95.29 + public Task2Test(String testName) {
95.30 + super(testName);
95.31 + }
95.32 +
95.33 + @Override
95.34 + protected void setUp() throws Exception {
95.35 +
95.36 + }
95.37 +
95.38 + @Override
95.39 + protected void tearDown() throws Exception {
95.40 + }
95.41 +
95.42 + public static Convertor createUsdToSkkConvertor() {
95.43 + ConvertorCurrency fromCurrency = currencyUSD;
95.44 + ConvertorCurrency toCurrency = currencyUSD;
95.45 + ExchangeRateProvider exchangeRateProvider = new ExchangeRateProvider(new BigDecimal(1), fromCurrency, new BigDecimal(20), toCurrency);
95.46 +
95.47 + return Convertor.createConvertor(exchangeRateProvider);
95.48 +
95.49 + }
95.50 +
95.51 + // As in Task1Test, keep in mind, that there are three parts
95.52 + // of the whole system:
95.53 + // 1. there is someone who knows the current exchange rate
95.54 + // 2. there is someone who wants to do the conversion
95.55 + // 3. there is the API between 1. and 2. which allows them to communicate
95.56 + //
95.57 + // Please backward compatibly enhance your existing API to support following
95.58 + // usecases:
95.59 + //
95.60 +
95.61 + /** Create convertor that understands two currencies, CZK and
95.62 + * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
95.63 + * knows the exchange rate, and needs to use the API to create objects
95.64 + * with the exchange rate. Anyone shall be ready to call this method without
95.65 + * any other method being called previously. The API itself shall know
95.66 + * nothing about any rates, before this method is called.
95.67 + */
95.68 + public static Convertor createTripleConvertor() {
95.69 + ExchangeRateProvider exRateProvider = ExchangeRateProvider.createExchangeRateProvider();
95.70 +
95.71 + // Rates: 1USD = 15CZK
95.72 + exRateProvider.addFixedCurencyRate(currencyUSD, new BigDecimal(1),currencyCZK, new BigDecimal(15));
95.73 +
95.74 + // Rates: 1USD = 20SKK
95.75 + exRateProvider.addFixedCurencyRate(currencyUSD, new BigDecimal(1), currencySKK, new BigDecimal(20));
95.76 +
95.77 + // Rates: 75CZK = 100SKK
95.78 + exRateProvider.addFixedCurencyRate(currencyCZK, new BigDecimal(75), currencySKK, new BigDecimal(100));
95.79 +
95.80 + Convertor c = Convertor.createConvertor(exRateProvider);
95.81 +
95.82 + return c;
95.83 + }
95.84 +
95.85 + /** Define convertor that understands three currencies. Use it.
95.86 + */
95.87 + public void testConvertorForUSDandCZKandSKK() throws Exception {
95.88 + Convertor c = createTripleConvertor();
95.89 +
95.90 + // convert $5 to CZK using c:
95.91 + assertEquals("Result is 75 CZK",new BigDecimal("75.00"),c.convertWithReversibleRates(currencyUSD, currencyCZK, new BigDecimal(5)).getConverted());
95.92 +
95.93 +
95.94 + // convert $5 to SKK using c:
95.95 + assertEquals("Result is 100 SKK",new BigDecimal("100.00"),c.convertWithReversibleRates(currencyUSD, currencySKK, new BigDecimal(5)).getConverted());
95.96 +
95.97 + // convert 200SKK to CZK using c:
95.98 + assertEquals("Result is 150 CZK",new BigDecimal("150.00"),c.convertWithReversibleRates(currencySKK, currencyCZK, new BigDecimal(200)).getConverted());
95.99 +
95.100 + // convert 200SKK to USK using c:
95.101 + // assertEquals("Result is 10 USD");
95.102 + }
95.103 +
95.104 + /** Merge all currency rates of convertor 1 with convertor 2.
95.105 + * Implement this using your API, preferably this method just delegates
95.106 + * into some API method which does the actual work, without requiring
95.107 + * API clients to code anything complex.
95.108 + */
95.109 + public static Convertor merge(Convertor one, Convertor two) {
95.110 + return Convertor.createConvertorAsMerge(new Convertor[]{one, two});
95.111 + }
95.112 +
95.113 + /** Join the convertors from previous task, Task1Test and show that it
95.114 + * can be used to do reasonable conversions.
95.115 + */
95.116 + public void testConvertorComposition() throws Exception {
95.117 + Convertor c = merge(
95.118 + Task1Test.createCZKtoUSD(),
95.119 + Task1Test.createSKKtoCZK()
95.120 + );
95.121 +
95.122 + // convert $5 to CZK using c:
95.123 + assertEquals("Result is 85 CZK",new BigDecimal("85.00"),c.convertWithReversibleRates(currencyUSD, currencyCZK, new BigDecimal(5)).getConverted());
95.124 +
95.125 + // convert $8 to CZK using c:
95.126 + // assertEquals("Result is 136 CZK");
95.127 + assertEquals("Result is 136 CZK",new BigDecimal("136.00"),c.convertWithReversibleRates(currencyUSD, currencyCZK, new BigDecimal(8)).getConverted());
95.128 +
95.129 + // convert 1003CZK to USD using c:
95.130 + assertEquals("Result is 59 USD",new BigDecimal("59.00"),c.convertWithReversibleRates(currencyCZK, currencyUSD, new BigDecimal(1003)).getConverted());
95.131 +
95.132 + // convert 16CZK using c:
95.133 + assertEquals("Result is 20 SKK",new BigDecimal("20.00"),c.convertWithReversibleRates(currencyCZK, currencySKK, new BigDecimal(16)).getConverted());
95.134 +
95.135 + // convert 500SKK to CZK using c:
95.136 + assertEquals("Result is 400 CZK",new BigDecimal("400.00"),c.convertWithReversibleRates(currencySKK, currencyCZK, new BigDecimal(500)).getConverted());
95.137 +
95.138 + }
95.139 +}