1. Maven

Maven is a project management and comprehension tool. From now on we will be using Mave to

  1. Declare and donwload code dependencies (libraries)

  2. Build our code

  3. Build our tests

  4. Run our tests

  5. Generate reports about

    1. out code

    2. our tests

Most IDEs (including Eclipse and IntelliJ) have support for Maven. During this lab we will demonstrate how to use Maven from within Eclipse. We will also explain the basic concepts and files used to configure and control Maven. There is plenty of docuementation online about Maven that you should read.

Project that use Maven can be uploaded to Mave Central. This is a repository of project that you can search, download and use in your project.

1.1. Eclipse

Show and tell of how to start a Maven project.

  1. Create new Maven Project

    1. groupId - maps to the the root package edu.neu.ccs.cs5004.seattle

    2. artifactId - the package under root package that holds your application, e.g., assignment1

  2. Explain structure of Maven Project

  3. Explain how to run a

    1. build (compile)

    2. tests (test)

    3. reports (site)

2. POM.xml

Maven, like most build tools, uses targets to designate what actions to perform, for example

  • To build your source code

    1. Find the program’s source

    2. Use Java’s compiler to build the source

  • To test your source code

    1. Find the program’s source and build it

    2. Find the program’s test source and build it

    3. Run the tests using your testing framework

Maven reads pom.xml in order to figure out what actions to perform for each target.

2.1. POM intro

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> (1)
  <modelVersion>4.0.0</modelVersion> (2)

  <groupId>edu.neu.ccs.cs5004.seattle</groupId> (3)
  <artifactId>assignment1</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>assignment1</name>      (4)
  <url>http://maven.apache.org</url> (5)

  <properties> (6)
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
1 Points to the schema and default Maven pom configuration
2 The maven model version that we are going to use
3 The groupId is a unique identifier for the organization or project
4 The artifactId is an identifier for the project
5 The version is the project version
6 The packaging is what kind of package we would like to generate from our compiled code

2.2. POM dependencies

 <dependencies> (1)
    <dependency> (2)
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
1 This starts a group of 1 or more dependencies for your project. Dependencies are other libraries/code that you need in order to build/test your code.
2 If you search Maven Central you can find your dependencies, their names and versions and Maven Central even provides the XML that you need to add to your POM in order to download and use this dependency.

2.3. POM plugins: build

Maven plugins can be used to customize or add actions during the execution of a target. Here is the relevant XML that customizes our build target.

  <!-- build -->
    <build>    (1)
        <plugins> (2)
            <plugin> (3)
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
1 Designate which target we would like to alter/add/customize
2 Starts a group of plugins that we would like to use for this target
3 Starts a plugin with its customizatio. Here we are using the compiler plugin and configuring it so that the source file and output (target) files must be java 1.8.

2.4. POM plugins: reports

 <reporting> (1)
        <plugins> (2)
            <plugin> (3)
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>cobertura-maven-plugin</artifactId>
                <version>2.7</version>
            </plugin>
            <plugin> (4)
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>findbugs-maven-plugin</artifactId>
                <version>3.0.1</version>
                <configuration>
                    <xmlOutput>true</xmlOutput>
                    <!-- Optional directory to put findbugs xdoc xml report -->
                    <xmlOutputDirectory>target/site</xmlOutputDirectory>
                </configuration>
            </plugin>
        </plugins>
    </reporting>
1 Designate which target we would like to alter/add/customize
2 Starts a group of plugins that we would like to use for this target
3 Starts a plugin with its customization. Here we are adding the plugin for Cobertura
4 We are adding and configuring a plugin for FindBugs
Practise Exercises
  1. Create a new Maven project in your IDE.

  2. Update the file pom.xml to configure your

    1. dependencies; make sure you are using JUnit 4.12

    2. build; make sure you are building for Java 1.8

    3. reports; make sure you generate

      1. Cobertura reports (test coverage)

      2. FindBugs reports

  3. Build your code.

  4. Run your tests.

  5. Run your reports and see their output.

3. Refactoring in Eclipse

Show and tell of Eclipse’s Refactoring operations.

  1. Rename

  2. Extract constant

  3. Extract method

  4. Extract interface

  5. Extract class

  6. Pull up

  7. Push down

4. ADTs, again.

We would like to design a program that implements a Double Ended Queue (DEQ). A DEQ is much like a queue but we can operate on both ends of the queue. We will use {< >} to represent an empty DEQ

We are asked to create a DEQ that holds Strings.

Operation Specification Comments

Empty() : DEQ

Empty() = {< >}

  • Creates an empty DEQ

isEmpty: Boolean

{<>}.isEmpty()          = true

{<s,x, ... >}.isEmpty() = false
  • returns true if the DEQ is empty

  • returns false if the DEQ is non-empty

size() : Integer

{<>}.size()          = 0

{<s, x, ...>}.size() =
    1 + {<x, ...>}.size()
  • returns 0 if the DEQ is empty

  • returns the number of elements in the DEQ

prepend(x): DEQ

{<>}.prepend(x)         = {< x >}

{<s, y, ..>}.prepend(x) =
    {<x, s, y, ...>}
  • if the DEQ is empty returns a new DEQ with one element x

  • if the DEQ is non-empty returns a new DEQ that has the same elements in the same order as the original non-empty DEQ but with the element x prepended

append(x): DEQ

{<>}.append(x)         = {< x >}

{<s, y, ..>}.append(x) =
    {<s, y, ...,x>}
  • if the DEQ is empty returns a new DEQ with one element x

  • if the DEQ is non-empty returns a new DEQ that has the same elements in the same order as the original non-empty DEQ but with the element x appended at the end

eject() : DEQ

{<>}.eject()             = {<>}

{<s, x, ..., y>}.eject() =
      {<s, x, ...>}
  • if the DEQ is empty eject returns the empty DEQ

  • if the DEQ is not empty then we return a new DEQ with all the elements as before except the last element

pop() : DEQ

{<>}.pop()           = {<>}

{<s, x, ...,>}.pop() =
      {<x, ...>}
  • if the DEQ is empty pop returns the empty DEQ

  • if the DEQ is not empty then we return a new DEQ with all the elements as before except the first element

last() : String

{<>}.last()            = ERROR

{<s, x, ...,y>}.last() = y
  • if the DEQ is empty last throws an error

  • if the DEQ is not empty then return the last element. The DEQ remains unchanged.

first() : String

{<>}.first()          = ERROR

{<s, x, ...>}.first() = x
  • if the DEQ is empty first throws an error

  • if the DEQ is not empty then return the first element. The DEQ remains unchanged.

has(s): Boolean

{<>}.has(s)          = false

{<s, x, ...>}.has(s) = true

{<y,x, ...>}.has(s)  = {<x, ...>}.has(x)
  • if the DEQ is empty return false

  • return true only if you find s in the DEQ, return false otherwise

Practise Exercises
  1. Design a Java program that implements the DEQ ADT.

  2. Write Blackbox tests in a separate package.

  3. Write Glassbox tests in the same package are your DEQ implementation.

Can we use your implementation to also provide a Queue implementation. Here is the ADT for a simple Queue.

Operation Specification Comments

Empty() : Queue

Empty() = {< >}

  • Creates an empty Queue

isEmpty: Boolean

{<>}.isEmpty()          = true

{<s,x, ... >}.isEmpty() = false
  • returns true if the Queue is empty

  • returns false if the Queue is non-empty

size() : Integer

{<>}.size()          = 0

{<s, x, ...>}.size() =
    1 + {<x, ...>}.size()
  • returns 0 if the Queue is empty

  • returns the number of elements in the Queue

push(x): Queue

{<>}.push(x)         = {< x >}

{<s, y, ..>}.push(x) =
    {<x, s, y, ...>}
  • if the Queue is empty returns a new Queue with one element x

  • if the Queue is non-empty returns a new Queue that has the same elements in the same order as the original non-empty Queue but with the element x pushed

pop() : Queue

{<>}.pop()           = {<>}

{<s, x, ...,>}.pop() =
      {<x, ...>}
  • if the Queue is empty pop returns the empty Queue

  • if the Queue is not empty then we return a new Queue with all the elements as before except the first element

peek() : String

{<>}.peek()          = ERROR

{<s, x, ...>}.peek() = x
  • if the Queue is empty peek throws an error

  • if the Queue is not empty then return the peek element. The Queue remains unchanged.

has(s): Boolean

{<>}.has(s)          = false

{<s, x, ...>}.has(s) = true

{<y,x, ...>}.has(s)  = {<x, ...>}.has(x)
  • if the Queue is empty return false

  • return true only if you find s in the Queue, return false otherwise

Practise Exercises
  1. Implement Queue. Try to reuse as much code as possible from your DEQ implementation.

4.1. Priority Queue

A Priority Queue PQ is similar to a simple Queue but the elements of a PQ are pairs that contain

  1. a priority, for our case this is a number

  2. a value, for our case this is a string.

The operations on a PQ are similar to the ones in Queue

  • Empty() is the same as in Queue.

  • isEmpty() is the same as in Queue.

  • size() is the same as in Queue.

  • push(p,v) adds a new element to the Queue with priority p and value v. There is no restriction as to where in the PQ the new element is added.

  • pop() returns a new PQ by removing the element that has the highest priority.

  • peek() returns the value v of the element in PQ that has the highest priority.

  • has(s) is the same as in Queue, it checks that the value s is in the PQ.

Practise Exercises
  1. Write the ADT table for PQ. See the examples for DEQ and Queue.

  2. Design a Java program that implements your PQ ADT.

  3. Write Blackbox tests.

  4. Write Whitebox tests.

  5. Generate code coverage reports and ensure that you are testing all of your code with the following exceptions

    1. Auto-generated getters

    2. toString