<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xml:id="sd1Deploy"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:svg="http://www.w3.org/2000/svg"
         xmlns:ns="http://docbook.org/ns/transclusion"
         xmlns:m="http://www.w3.org/1998/Math/MathML"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns:db="http://docbook.org/ns/docbook">
  <title>Application deployment I</title>

  <section xml:id="sd1DeployPrepare">
    <title>Preparations</title>

    <para>Read <link
    xlink:href="https://www.cs.swarthmore.edu/~newhall/unixhelp/debuggingtips_Java.html">http://www.cs.swarthmore.edu/~newhall/unixhelp/debuggingtips_Java.html</link>
    up to including the <quote>The <code>CLASSPATH</code> environment variable
    and JAR files</quote> section.</para>
  </section>

  <section xml:id="sda1DeployExercise">
    <title>Exercises</title>

    <qandaset defaultlabel="qanda" xml:id="sd1QandaArrayVarious">
      <title>Various integer array algorithms</title>

      <qandadiv>
        <qandaentry>
          <question>
            <para>The following Maven project contains a series of yet
            unimplemented methods and corresponding tests currently being
            excluded by an <interfacename
            xlink:href="https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/Disabled.html">@Disabled</interfacename>
            annotation:</para>

            <annotation role="make">
              <para role="eclipse">P/Sd1/Array/arraycalcExercise</para>
            </annotation>

            <programlisting language="java">...
<emphasis role="bold">@Disabled // Remove me to enable testing your application</emphasis>
@SuppressWarnings("javadoc")
public class ArrayMethodTest {

  @Test
  public void testFindIndex(){
    assertEquals(Arraymethods.findIndex(new int[]{1, 3, -3, 5}, -3), 2);...</programlisting>

            <para>Import this project for getting started. The following hints
            may help you completing the implementation</para>

            <glosslist>
              <glossentry>
                <glossterm><link
                xlink:href="P/Sd1/Array/arraycalcExercise/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/Arraymethods.html#swap-int:A-int:A-">swap</link></glossterm>

                <glossdef>
                  <para>This effectively requires extending the concept of
                  swapping just two integer values within a block</para>

                  <programlisting language="java">int a = 3, b = 5;

// Other code ...

{// Swap values of a and b
  final int tmp = a;
  a = b;
  b = tmp;
}</programlisting>
                </glossdef>
              </glossentry>

              <glossentry>
                <glossterm><link
                xlink:href="P/Sd1/Array/arraycalcExercise/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/Arraymethods.html#isPalindrome-java.lang.String-">isPalindrome</link></glossterm>

                <glossdef>
                  <para>Consider a two step implementation:</para>

                  <orderedlist>
                    <listitem>
                      <para>Normalize a given palindrome candidate by
                      transforming to lower case and erasing
                      non-letters:</para>

                      <para><code>Hey, Roy! Am I mayor? Yeh!</code> --&gt;
                      <code>heyroyamimayoryeh</code></para>

                      <para>You may search the <xref linkend="glo_API"/> of
                      class <classname
                      xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Character.html">Character</classname>
                      assisting you to distinguish letters from
                      non-letters.</para>
                    </listitem>

                    <listitem>
                      <para>Check the remaining string for being a
                      palindrome.</para>
                    </listitem>
                  </orderedlist>
                </glossdef>
              </glossentry>

              <glossentry>
                <glossterm><link
                xlink:href="P/Sd1/Array/arraycalcExercise/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/Arraymethods.html#containsSameElements-int:A-int:A-">containsSameElements</link></glossterm>

                <glossdef>
                  <para>You may copy <code language="java">int[] b</code>
                  array to a <quote>shadow</quote> array and then subsequently
                  erase all elements of <code language="java">int[] a</code>
                  from this copy. The method <link
                  xlink:href="P/Sd1/Array/arraycalcExercise/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/Arraymethods.html#findIndex-int:A-int-">findIndex</link>
                  is quite helpful.</para>

                  <para>Consider for example <code language="java">int[] bCopy
                  = {1, 3, 4, 3, 7}</code> containing 5 elements. Suppose our
                  array <code language="java">a</code> contains the value 3
                  which exists at index position 1 in <code
                  language="java">bCopy</code>. We may override the value
                  index position 1 by the last array value 7 and thereby
                  keeping track of reducing the number of array elements to 4
                  like {1, 7, 4, 3}.</para>

                  <para>Off course the array <code
                  language="java">bCopy</code> cannot shrink. But we may
                  introduce an integer variable to account for the effective
                  number of array elements still to be considered. If and only
                  if all elements from <code language="java">a</code> are
                  subsequently found within <code language="java">bCopy</code>
                  the two arrays <code language="java">a</code> and <code
                  language="java">b</code> are equal.</para>
                </glossdef>
              </glossentry>
            </glosslist>
          </question>

          <answer>
            <annotation role="make">
              <para role="eclipse">P/Sd1/Array/arraycalcSolution</para>
            </annotation>
          </answer>
        </qandaentry>
      </qandadiv>
    </qandaset>
  </section>

  <section xml:id="sd1AppDeploy2Exercise">
    <title>Part II, Exercises</title>

    <qandaset defaultlabel="qanda" xml:id="sd1QandaMedianCmdline">
      <title>A command line version computing a sample's average and
      median</title>

      <qandadiv>
        <qandaentry>
          <question>
            <para>This exercise extends <xref linkend="sd1StoreStatistics"/>
            by adding a command line interface. Consider the following console
            execution:</para>

            <screen>goik &gt;java -jar statistics-1.0.jar 2 6 7
Your sample's average is: 5.0
Your sample's median is: 6.0</screen>

            <para>The above example executes our Java program in a shell and
            supplies three command line parameters 2, 6 and 7. The program
            then executes and creates the desired statistical data.</para>

            <para>The subsequent remarks may assist you creating an
            implementation:</para>

            <orderedlist>
              <listitem xml:id="sd1OlMedianCmdLineStep1">
                <para>Using command line values means entering strings rather
                then e.g. integer values: In the current example the Java
                runtime will pass an array of strings <code
                language="java">{"2", "6", "7"}</code> on behalf of the user's
                input <quote><code language="java">2 6 7</code></quote> to
                your <code language="java">main(String [] args)</code> method.
                These strings must be converted to integer values. This may be
                achieved by means of <methodname
                xlink:href="https://docs.oracle.com/javase/10/docs/api/java/lang/Integer.html#parseInt-java.lang.String-">parseInt(String)</methodname>.</para>

                <para>Depending on inconsistent user input like <quote><code
                language="java">three</code></quote> instead of <quote><code
                language="java">3</code></quote> you may decide to terminate
                your application thereby providing a meaningful error
                message:</para>

                <screen>goik &gt;java -jar statistics-1.0.jar 1 2 three
Input string 'three' does not represent an integer value</screen>
              </listitem>

              <listitem>
                <para>If the user does not provide any input at all our
                program shall terminate as well:</para>

                <screen>goik &gt;java -jar statistics-1.0.jar
No values provided</screen>
              </listitem>

              <listitem>
                <para>Provide an <classname>public enum ErrorState</classname>
                definition representing all three possible error
                states:</para>

                <glosslist>
                  <glossentry>
                    <glossterm><code>OK</code>:</glossterm>

                    <glossdef>
                      <para>No error, all user input strings represent integer
                      values.</para>
                    </glossdef>
                  </glossentry>

                  <glossentry>
                    <glossterm><code>NO_VALUE</code>:</glossterm>

                    <glossdef>
                      <para>Error: No user input at all.</para>
                    </glossdef>
                  </glossentry>

                  <glossentry>
                    <glossterm><code>NO_INTEGER</code>:</glossterm>

                    <glossdef>
                      <para>Error: At least one input value does not represent
                      an integer value.</para>
                    </glossdef>
                  </glossentry>
                </glosslist>
              </listitem>

              <listitem>
                <para>Implement a class <classname>InputValidator</classname>
                to validate user input and thereby converting string values to
                an integer array of equal size:</para>

                <programlisting language="java">/**
 * Validate sample input strings and convert
 * them to integer values.
 */
public class InputValidator {

  /**
   * Integer values being calculated upon
   * constructor call.
   */
  public final int[] values;

  /**
   * Transform a series of strings into integer values. In case
   * of invalid input, a corresponding error messsage will be written
   * to System.err and the current application will terminate by calling
   * {@link System#exit(int)}. Example: The array ["-1", "20", "three"]
   * contains two valid elements and the invalid element "three" which
   * cannot be converted to an integer value by virtue of
   * {@link Integer#parseInt(String)}.
   *
   * @param userInput A set of strings possibly representing integer values.
   */
  public InputValidator(final String[] userInput) {...}
}</programlisting>

                <para>You may then create an instance by supplying your <code
                language="java">main(String[] args)</code> command line
                values:</para>

                <programlisting language="java">public static void main(String[] args) {

  final InputValidator userInput = new InputValidator(args);
...</programlisting>

                <para>Choose your implementation with testing in mind.</para>
              </listitem>

              <listitem>
                <para>Write at least one test case for all three possible
                error categories and check for correct behaviour of your
                <classname>InputValidator</classname> class.</para>
              </listitem>

              <listitem>
                <para>Use your class <classname
                xlink:href="P/Sd1/Array/integerStoreMedianAnswer/target/site/apidocs/de/hdm_stuttgart/mi/sd1/store/IntegerStore.html">IntegerStore</classname>
                from exercise <xref linkend="sd1StoreStatistics"/> to compute
                the desired output.</para>
              </listitem>

              <listitem>
                <para>Simulating command line arguments in <xref
                linkend="glo_Soft_Eclipse"/> requires a run time
                configuration. Click <guimenu>Run</guimenu> <guimenuitem>Run
                Configurations...</guimenuitem>. Choose <quote>Java
                Applications</quote> and "new launch configuration" from the
                panel's left side, choose your project and main class (if not
                already selected).</para>

                <screenshot>
                  <info>
                    <title>Defining an Eclipse runtime configuration</title>
                  </info>

                  <mediaobject>
                    <imageobject>
                      <imagedata fileref="Ref/Fig/runconfigSelectClass.png"/>
                    </imageobject>
                  </mediaobject>
                </screenshot>

                <para>Select the <guimenu>Arguments</guimenu> tab. Enter your
                desired command line values, hit <guibutton>Apply</guibutton>
                and subsequently <guibutton>Run</guibutton> to launch your
                application.</para>

                <screenshot>
                  <info>
                    <title>Defining an Eclipse runtime configuration</title>
                  </info>

                  <mediaobject>
                    <imageobject>
                      <imagedata fileref="Ref/Fig/runconfigDefineArgs.png"/>
                    </imageobject>
                  </mediaobject>
                </screenshot>
              </listitem>

              <listitem>
                <para>Maven projects allow for creation of executable jar
                archives. This leverages the process being described in <link
                xlink:href="http://www.skylit.com/javamethods/faqs/createjar.html">Creating
                an Executable jar File</link>. It avoids messing with manifest
                files and zipping up archives manually.</para>

                <para>Among several configuration possibilities you may use
                the <link
                xlink:href="https://maven.apache.org/plugins/maven-jar-plugin">Maven
                JAR Plugin</link> and its <option
                xlink:href="https://maven.apache.org/plugins/maven-jar-plugin/usage.html#How_to_build_a_JAR_file">package</option>
                goal. You have to add this plugin to the <tag
                class="starttag">plugins</tag> section of your
                <filename>pom.xml</filename> file. The plugin in turn requires
                defining the fully qualified name of your entry class <coref
                linkend="sd1CaPomFqnMainEntryClass"/> containing the desired
                <methodname>main(String[] args)</methodname> method:</para>

                <programlisting language="xml">...
&lt;properties&gt;
  &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
  &lt;javadocDestdir&gt;~/tmp&lt;/javadocDestdir&gt;
&lt;/properties&gt;

&lt;build&gt;
  &lt;plugins&gt;
    &lt;plugin&gt;
      &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
      &lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;
      &lt;version&gt;2.4&lt;/version&gt;
      &lt;configuration&gt;
        &lt;archive&gt;
          &lt;manifest&gt;
          &lt;addClasspath&gt;true&lt;/addClasspath&gt;
<emphasis role="bold">          &lt;mainClass&gt;de.hdm_stuttgart.mi.sd1.statistics.main.Statistics&lt;/mainClass&gt;
                                                             </emphasis> <co
                    xml:id="sd1CaPomFqnMainEntryClass"/>
          &lt;/manifest&gt;
        &lt;/archive&gt;
      &lt;/configuration&gt;
    &lt;/plugin&gt;
  &lt;/plugins&gt;
&lt;/build&gt;
...</programlisting>

                <para>Creating the actual jar archive may be triggered by
                either of:</para>

                <glosslist>
                  <glossentry>
                    <glossterm>From the command line:</glossterm>

                    <glossdef>
                      <para>Change to your project root containing your
                      <filename>pom.xml</filename> file and execute
                      <command>mvn</command> <option>package</option>.</para>
                    </glossdef>
                  </glossentry>

                  <glossentry>
                    <glossterm>From inside <xref
                    linkend="glo_Soft_Eclipse"/>:</glossterm>

                    <glossdef>
                      <para>Create a maven run time configuration (see above)
                      containing your <option>package</option> goal:</para>

                      <screenshot>
                        <info>
                          <title>Creating a Maven runtime configuration
                          corresponding to the <option>package</option>
                          goal</title>
                        </info>

                        <mediaobject>
                          <imageobject>
                            <imagedata fileref="Ref/Fig/runconfigMavenGoalPackage.png"/>
                          </imageobject>
                        </mediaobject>
                      </screenshot>
                    </glossdef>
                  </glossentry>
                </glosslist>

                <para>After creating the jar archive you may now run your
                program in a shell as being described in <xref
                linkend="sd1OlMedianCmdLineStep1"/> of this section.</para>
              </listitem>
            </orderedlist>
          </question>

          <answer>
            <annotation role="make">
              <para role="eclipse">P/Sd1/Array/medianCmdLine</para>
            </annotation>
          </answer>
        </qandaentry>
      </qandadiv>
    </qandaset>
  </section>
</chapter>