from psm to code - mcmaster universitymohammh/projects/insuline pump doc4.pdf · 1 from psm to code...

40
1 From PSM to Code And summery of Development Process For Insulin Pump Written by: Morteza Yousef-Sanati Hamid Mohammad-Gholizadeh Assignment 4 Course: 703 Software Design Professor: Dr. Tom Maibaum April 2011

Upload: vuongdang

Post on 17-Feb-2019

223 views

Category:

Documents


1 download

TRANSCRIPT

1

From PSM to Code

And summery of Development Process

For Insulin Pump

Written by:

Morteza Yousef-Sanati

Hamid Mohammad-Gholizadeh

Assignment 4

Course: 703 Software Design

Professor: Dr. Tom Maibaum

April 2011

2

Table of Contents

TABLE OF CONTENTS.............................................................................................................................................. 2

DEVELOPMENT PROCESS ...................................................................................................................................... 3

PSM TO CODE MOVEMENT .................................................................................................................................... 8

MAINSCREEN TO CODE ............................................................................................................................................ 9

MAINFRAME STATECHART TO CODE .......................................................................................................................... 12

MENU STAECHART TO CODE: ................................................................................................................................... 15

PUMP CLASS TO CODE ........................................................................................................................................... 18

BATTERY CLASS TOCODE: ........................................................................................................................................ 20

PUMPTIMER TO CODE ........................................................................................................................................... 25

USING JAVA PROPERTIES CLASS ................................................................................................................................ 25

IMPLEMENTING COLLECTIONS .................................................................................................................................. 26

USING JAVA SERIALIZABLE CLASS ............................................................................................................................... 26

SINGLETON PATTERN ............................................................................................................................................. 26

EXCEPTION ERROR HANDLING ................................................................................................................................... 26

TEST PLAN ............................................................................................................................................................ 27

BLACK BOX TEST ................................................................................................................................................... 27

UNIT TEST........................................................................................................................................................... 27

INTEGRATION TEST ................................................................................................................................................ 28

TEST DRIVER PROGRAM ......................................................................................................................................... 28

A TYPICAL FEATURE OF SYSTEM FOR TESTING ............................................................................................................... 36

SAMPLE TEST CASES............................................................................................................................................. 37

UNIT TEST, TEST CASES LEVEL ................................................................................................................................... 37

Test Case 1: Store and retrieve of Battery information ................................................................................ 37

Test Case 2: Store and retrieve of bolus history information ........................................................................ 38

ACCEPTANCE TEST, TEST CASES LEVEL ......................................................................................................................... 39

Test Case 1: Change Battery Level ............................................................................................................... 39

Test Case 2: Test battery usage ratio ........................................................................................................... 39

Test Case 3: Display Bolus History................................................................................................................ 39

3

Development Process

Our system development started defining some elementary usescase for

simulating an insullin pump. You can see the overall use case diagram

below.

Figure 1: Use case diagram for the insulin pump simulator

Navigating Menus to access

Bolus Menu (This is a common

Practice for other Usecases

but I avoid to repeat it for

simplicity)

Note: An insulin pump has five

main buttons, including “UP”,

“Down”, “B”, “ACT” and

“ESC/Back” button and one

indicator l ight

<<include>>

<<include>>

<<include>>

<<extend>>

pump Initialize

ShowPump Status

set Alerts

Set Bolus

lock and unlock pump

set Date TimeAccess Bolus

Menu

Display Bolus

History

Suspend & resume

<<abstract>>

Set Basal

Review Basal

Set Single Basal Rate

Set Multiple Basal Rate

Patient

changeBatteryLevel

changeReservoirLevel

4

After defining these use case we started to design the class diagrams

based on these use cases. First design PIM and then tried to get the PSM

from that and finally reach the code. For example you can see a part a PIM

class diagram in the figure bellow

Figure 2: PIM Class diagram of the controller package

Our design is based on 3-tier architecture which is reflected by three

packages: GUI, Controller and Data. This decision is made because of

separating the functionality of the system between different packages. For

tankCapacity>=0 and

tankCapacity<=1000

Battery

-

-

charge

status

: int

: CapacityStatus Derived

+

+

+

getStatus ()

startConsumption ()

stopConsumption ()

: CapacityStatus

: void

: void

self<=100 and self>=0

charge>=0 and charge <=20 => status=low

1..1

1..*

rates

Ordered

1..1

1..1

1..1

1..1

1..1

1..1

reservoirStatus

1..1

1..1

BatteryStatus

1..1

1..1

1..1

0..1

0..1

0..*

boluses

Ordered

1..1

0..1

currentBolus

Pump

+

-

state

datetime

: int

: Date

+

+

+

+

+

+

+

+

+

-

initialize ()

getStatus ()

alarm ()

suspend ()

resume ()

changeBattery ()

changeResorvoir ()

finalize ()

lock ()

displayLocked ()...

: void

: void

: void

: void

: void

: void

: void

: void

Reservoir

-

-

tankCapacity

status

: int

: CapacityStatus

+ consume (int amount) : void

Bolus

-

-

amount

amountDelivered

: int

: int

+

+

start ()

stop ()

<<enumeration>>

PumpState

+

+

+

NORMAL

SPECIAL

ATTENTION

: int

: int

: int

Basal

- basalRateCounts : int Derived

+

+

+

addBasalRate (BasalRate brate)

deleteBasalRate (BasalRate brate)

clearBasalAll ()

BasalRate

-

-

Time

Rate

: Date

: double

<<enumeration>>

CapacityStatus

-

-

-

-

-

VERY_LOW

LOW

MID

HIGH

FULL

: int

: int

: int

: int

: int

BolusHistory

+

+

+

addBolus (Bolus bolus)

ClearHistory ()

exportToList ()

DataProvider

(Data)

- fi lePath : String

+

+

+

+

+

+

storeBasal (Basal basal)

retriveBasal ()

storeBatteryState (Battery Parameter_1)

retriveBatteryState ()

storeReservoirState ()

retriveReservoirState ()...

: Basal

: Battery

: Reservoir

5

doing this we mostly considered less coupling between packages and more

cohesion inside each package principle.

GUI includes classes related to GUI Design like, Frames, Buttons, Panels

and etc. which is constructing our user interface. Controller includes core

classes like classes which control the pump functionality and Data package

contains a class which is responsible for storing and retrieving system

data.

Figure3 :System Design Architecture

After doing PIM design we refine the models in PIM models to get the PSM

models. You can find detailed explanation for this refinement in our

GUI

Controller

Data

6

previous document. As an example you see below the PSM class diagram

for the previous PIM class diagram already demonstrated.

Figure 4: PSM class diagram for the controller package

uniqueInstance

status

uniqueInstance

uniqueInstance

uniqueInstance

workingStatus

battery

pumpStatereservoir

basal

bolus

bolusHistory

dataProvider guiStub

uniqueInstance

status

uniqueInstance

Basal

-

-

rates

uniqueInstance

: Vector<BasalRate>

: Basal = null

+

-

+

+

+

+

+

+

<<Constructor>>

getBasal ()

Basal ()

addBasalRate (BasalRate brate)

clearBasalAll ()

getBasalRate (int ith)

setBasalRate (int ith, BasalRate brate)

getCurrentBasalRate ()

getBasalVector ()

: Basal

: void

: void

: BasalRate

: void

: BasalRate

: Vector<String>

<<Unresolved Class>>

Thread

<<Unresolved Interface>>

Serializable

(io)

<<Enum>>

BasalDeliveryStatus

+

+

DELIVERY

SUSPENDED

: EnumConstant

: EnumConstant

BasalRate

-

-

time

rate

: Date

: double

+

+

+

+

+

+

+

+

<<Constructor>>

<<Constructor>>

<<Constructor>>

BasalRate ()

toString ()

BasalRate (BasalRate brate)

BasalRate (Date time, double rate)

setTime (Date time)

getTime ()

setRate (double rate)

getRate ()

: String

: void

: Date

: void

: double

Battery

-

-

-

-

-

-

turnOff

charge

rate

status

MaxBatteryAmount

uniqueInstance

: boolean

: int

: int

: CapacityStatus

: int

: Battery

= 1000

= null

+

-

+

+

+

+

+

+

+

+

+

-

<<Constructor>>

getBattery ()

Battery ()

getMaxBatteryamount ()

run ()

toString ()

setCharge (int charge)

getCharge ()

getStatus ()

setRate (int rate)

getRate ()

setTurnOff ()

adjustStatus ()

: Battery

: int

: void

: String

: void

: int

: CapacityStatus

: void

: int

: void

: void

Bolus

-

-

-

amount

amountDelivered

dateTime

: double

: double

: Date

+

+

+

+

+

+

+

+

+

<<Constructor>>

<<Constructor>>

Bolus ()

Bolus (Bolus bolus)

setAmount (double amount)

getAmount ()

getAmountDelivered ()

setAmountDelivered (double amount)

setDateTime (Date dateTime)

toString ()

getDateTime ()

: void

: double

: double

: void

: void

: String

: Date

BolusHistory

-

-

boluses

uniqueInstance

: java.util.Vector<Bolus>

: BolusHistory = null

-

+

+

+

+

+

<<Constructor>> BolusHistory ()

getBolusHistory ()

addBolus (Bolus bolus)

clearHistory ()

getLastBolus ()

getBolusHistoryVector ()

: BolusHistory

: void

: void

: Bolus

: Vector<String>

<<Enum>>

CapacityStatus

+

+

+

+

+

VERY_LOW

LOW

MID

HIGH

FULL

: EnumConstant

: EnumConstant

: EnumConstant

: EnumConstant

: EnumConstant

Config

- RATE : int = 60

+ getRate () : int

Pump

-

-

-

-

-

-

-

-

-

-

-

-

-

DeliveryRateForBolus

uniqueInstance

workingStatus

battery

pumpState

reservoir

basal

bolus

bolusHistory

tempCounter

finaled

dataProvider

guiStub

: int

: Pump

: WorkingStatus

: Battery

: PumpState

: Reservoir

: Basal

: Bolus

: BolusHistory

: int

: Boolean

: DataProvider

: PumpGUI

= 10

= null

-

+

+

+

+

+

+

+

+

+

+

+

-

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

<<Constructor>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

<<Implement>>

Pump ()

getPump ()

initialize ()

getStatus ()

alarm ()

suspendPump ()

resumePump ()

changeBattery (int charge)

changeResorvoir (double capacity)

pumpFinalize ()

run ()

setDateTime (Date dt)

checkPumpState ()

getBatteryAmount ()

getMaxBatteryAmount ()

getMaxReservoirAmount ()

getReservoirAmount ()

getPumpState ()

getBasalRate (int ith)

getPumpStatusInfo ()

getBolusHistory ()

setBolus (double b)

clearBolusHistory ()

clearBasalRates ()

getBasalReview ()

getDateTime ()

isSuspended ()

setBasalRate (int ith, int hour,

int minute, int rate)

startController ()

setBatteryVal (int val)

setReservoirVal (int val)

: Pump

: void

: PumpState

: void

: void

: void

: void

: void

: boolean

: void

: void

: void

: int

: int

: int

: int

: PumpState

: BasalRate

: Vector<String>

: Vector<String>

: void

: void

: void

: Vector<String>

: Date

: boolean

: void

: void

: void

: void

PumpInterface

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

getMaxBatteryAmount ()

getBatteryAmount ()

getMaxReservoirAmount ()

getReservoirAmount ()

isSuspended ()

getPumpState ()

getBasalRate (int ith)

getPumpStatusInfo ()

getBolusHistory ()

getBasalReview ()

getDateTime ()

setBasalRate (int ith, int hour,

int minute, int rate)

setBolus (double b)

setDateTime (Date b)

setBatteryVal (int val)

setReservoirVal (int val)

clearBolusHistory ()

clearBasalRates ()

suspendPump ()

resumePump ()

initialize ()

startController ()

pumpFinalize ()

: int

: int

: int

: int

: boolean

: PumpState

: BasalRate

: Vector<String>

: Vector<String>

: Vector<String>

: Date

: void

: void

: void

: void

: void

: void

: void

: void

: void

: void

: void

: boolean

<<Enum>>

PumpState

+

+

+

NORMAL

SPECIAL

ATTENTION

: EnumConstant

: EnumConstant

: EnumConstant

PumpTimer

-

-

-

-

uniqueInstance

dateTime

turnOff

tempStop

: PumpTimer

: Date

: boolean

: boolean

= null

= null

+

-

+

+

+

+

+

+

<<Constructor>>

setTempStop (boolean tempStop)

PumpTimer ()

toString ()

getPumpTimer ()

run ()

setTurnOff ()

setDateTime (Date dateTime1)

getDateTime ()

: void

: String

: PumpTimer

: void

: void

: void

: Date

Reservoir

-

-

-

-

tankCapacity

MaxReservoirAmount

status

uniqueInstance

: double

: double

: CapacityStatus

: Reservoir

= 1000

= null

-

+

+

+

+

+

+

+

-

<<Constructor>>

<<Getter>>

Reservoir ()

getReservoir ()

toString ()

consume (double amount)

setTankCapacity (double tankCapacity)

getTankCapacity ()

getMaxReservoirAmount ()

getStatus ()

adjustStatus ()

: Reservoir

: String

: double

: void

: double

: double

: CapacityStatus

: void

<<Enum>>

WorkingStatus

+

+

+

WORKING

SUSPENDED

NOBATTERY

: EnumConstant

: EnumConstant

: EnumConstant

DataProvider

(Data)

-

-

-

-

-

-

-

-

-

-

basalFilePath

batteryConfigFilePath

reservoirConfigFilePath

bolusHistoryFilePath

dateFilePath

uniqueInstance

output

input

outputtext

inputtext

: String

: String

: String

: String

: String

: DataProvider

: ObjectOutputStream

: ObjectInputStream

: Formatter

: Scanner

= null

-

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

<<Constructor>> DataProvider (String basalFilePath,

String batteryConfigFilePath,

String reservoirConfigFilePath,

String bolusHistoryFilePath,

String dateFilePath)

getDataProvider (String basalFilePath,

String batteryConfigFilePath,

String reservoirConfigFilePath,

String bolusHistoryFilePath,

String dateFilePath)

storeBasal (Basal basal)

retriveBasal ()

storeBatteryState (Battery battery)

retriveBatteryState ()

storeReservoirState (Reservoir reservoir

)

retriveReservoirState ()

storeBolusHistory (BolusHistory bolusHis

tory)

storeDateTime (Date date)

retriveBolusHistory ()

retriveDateTime ()

setBasalFilePath (String basalFilePath)

getBasalFilePath ()

setConfigFilePath (String configFilePath

)

getConfigFilePath ()

setBolusHistoryFilePath (String bolusHis

toryFilePath)

getBolusHistoryFilePath ()

getDateFilePath ()

setDateFilePath (String dateFilePath)

removeBolusHistory ()

removeBatteryConfig ()

removeReservoirConfig ()

removeDateFile ()

removeBasal ()

: DataProvider

: void

: Basal

: void

: Battery

: void

: Reservoir

: void

: void

: BolusHistory

: Date

: void

: String

: void

: String

: void

: String

: String

: void

: void

: void

: void

: void

: void

PumpGUI

(gui)

+

+

+

+

+

+

+

reservoirChanged ()

batteryChanged ()

pumpStateChanged ()

dateTimeChanged ()

bolusDeliveryCompleted ()

bolusDeliveryStarted ()

batteryCharged ()

: void

: void

: void

: void

: void

: void

: void

7

For modual(package) communication we put an Interface between these

modules to ensure the loose coupling between them. Two interfaces

named PumpGUI and PumpInterface provide Modula interfaces for the gui

and ccontroller packags respectively. Two classes that implement these

two interfaces are MainFram and Pump respectively as you see in figure

below:

Figure 5 - PumpInterface in controller package. Pump implements this interface

Pump

(Controller)

-

-

-

-

-

-

-

-

-

-

-

-

-

DeliveryRateForBolus

uniqueInstance

workingStatus

battery

pumpState

reservoir

basal

bolus

bolusHistory

tempCounter

finaled

dataProvider

guiStub

: int

: Pump

: WorkingStatus

: Battery

: PumpState

: Reservoir

: Basal

: Bolus

: BolusHistory

: int

: Boolean

: DataProvider

: PumpGUI

= 10

= null

-

+

+

<<Constructor>>

<<Implement>>

Pump ()

getPump ()

initialize ()...

: Pump

: void

PumpInterface

(Controller)

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

getMaxBatteryAmount ()

getBatteryAmount ()

getMaxReservoirAmount ()

getReservoirAmount ()

isSuspended ()

getPumpState ()

getBasalRate (int ith)

getPumpStatusInfo ()

getBolusHistory ()

getBasalReview ()

getDateTime ()

setBasalRate (int ith, int hour,

int minute, int rate)

setBolus (double b)

setDateTime (Date b)

setBatteryVal (int val)

setReservoirVal (int val)

clearBolusHistory ()

clearBasalRates ()

suspendPump ()

resumePump ()

initialize ()

startController ()

pumpFinalize ()

: int

: int

: int

: int

: boolean

: PumpState

: BasalRate

: Vector<String>

: Vector<String>

: Vector<String>

: Date

: void

: void

: void

: void

: void

: void

: void

: void

: void

: void

: void

: boolean

8

Figure 6- PumpGui Interface is an interface for gui modual. MainFrame implements this interface. Most

attributes and operations of Mainframe is omitted in this diagram.

PSM to Code Movement

Almost all of our class diagram conforms to the code, i.e. they are

reflected in the code without any modification. We used a code generator of

PowerDesigner to do that and reverse Engineering of the tool helped us to

keep the consistency between the code and the diagrams. Then we don't

have that much modification while moving to the code.

You can see an screenshot of the simulator in Figure below:

MainFrame

(gui)

-

-

-

-

-

-

-

-

-

reservoir

battery

time

pumpController

UPBtn

DownBtn

BolusBtn

jButton7

jButton6...

: JProgressBar

: JProgressBar

: JTextField

: PumpInterface

: JButton

: JButton

: JButton

: JButton

: JButton

PumpGUI

(gui)

+

+

+

+

+

+

+

reservoirChanged ()

batteryChanged ()

pumpStateChanged ()

dateTimeChanged ()

bolusDeliveryCompleted ()

bolusDeliveryStarted ()

batteryCharged ()

: void

: void

: void

: void

: void

: void

: void

9

Figure 7: an Screenshot of the running insulin pump simulator

In the following we discuss some of the techniques we used for

implementing statechart diagrams and some algorithm implementations.

MainScreen To Code

What we mean by the main screen is the screen section of the simulator.

For closing our simulation to a real insulin pump, we limited the number of

lines in our main screen. We implemented our screen using a JPanel

component of the JAVA. This panel contains three Panels which represents

the three line of the screen. In each line we used a JLabel to reprent the

text which can be displayed in each line. So we defined a template for the

main screen named TemplateScreen. This template screen implements all

the commonality necessary for the screens to show something

inside.Below is the code for implementation of this class.

10

public abstract class TemplateScreen extends javax.swing.JPanel {

private JPanel jPanel1;

private JLabel jLabel1;

private JPanel line3;

private JPanel line2;

private JPanel line1;

public JPanel getLine3() {

return line3;

}

public JPanel getLine2() {

return line2;

}

public JPanel getLine1() {

return line1;

}

public void setTitle(String title) {

this.title = title;

this.jLabel1.setText(title);

}

private String title;

public TemplateScreen() {

super();

initGUI();

}

private void initGUI() {

try {

GridLayout thisLayout = new GridLayout(4, 1);

thisLayout.setHgap(5);

thisLayout.setVgap(5);

thisLayout.setColumns(1);

thisLayout.setRows(4);

this.setLayout(thisLayout);

this.setPreferredSize(new java.awt.Dimension(301, 240));

{

jPanel1 = new JPanel();

this.add(jPanel1);

jPanel1.setPreferredSize(new java.awt.Dimension(301, 40));

{

jLabel1 = new JLabel();

FlowLayout jLabel1Layout = new FlowLayout();

jLabel1.setLayout(jLabel1Layout);

jPanel1.add(jLabel1);

jLabel1.setText("");

jLabel1.setFont(new Font("Times", Font.BOLD, 20));

jLabel1.setPreferredSize(new java.awt.Dimension(217, 27));

}

}

11

{

line1 = new JPanel();

this.add(line1);

}

{

line2 = new JPanel();

this.add(line2);

}

{

line3 = new JPanel();

this.add(line3);

}

} catch (Exception e) {

e.printStackTrace();

}

}

protected abstract void makeScreen();

public void showMsg(String msg) {

this.getLine1().removeAll();

this.getLine2().removeAll();

this.getLine3().removeAll();

JLabel m=new JLabel(msg);

m.setFont(new Font("Times", Font.ITALIC, 15));

this.getLine2().add(m);

this.repaint();

this.validate();

}

}

Figure 8: Implementation of Template screen

As you see in the code above there are three Lines, named Line1, Line2

and Line 3 representing the three lines of the screen. These lines are used

to show the information to the user.

In the picture bellow you can see an snapshot of setting basal rates in the

system. This screen is a class that implements the Templatescreen above.

12

Figure 9: setBasal Screen uses the TemplateScreen for showing its component to the user.

MainFrame StateChart To code

We defined an enumeration named GUIStatus to represent the different

states in the statechart diagram below.

According to the states of the MainFram, functionalities of the Buttons

changes. As we stated in our previous documentations, We exploited

Command Pattern to deal with this problem. The state change of the

MainFrame class is encapsulated in a method named

"changeStatusTo(guiStatus)" as you see in figure 2.

Every command in the system which like to change the status of the

system, call this method and pass the status as a parameter to that. As it is

clear in this method, for each status of the system a collection of command

class is assigned. For example for the setDateTime status, the

corresponding command Classes will be: DateTimeACTCommand,

VoidCommand, DateTimeESCCommand, DateTimeUPCommand and

13

DateTimeDownCommand. "VoidCommand" represents no actions! While

this command is assigned to a button nothing will happen when user clicks

that button. As another example, in "Default" status, the ACTCommand will

show the menu to the user and this command is assigned to the

ACTButton in the system.

public void changeStatusTo(GUIStatus guiStatus) {

switch (guiStatus) {

UP

Esc/ showHowToUnlock

Down

Bolus/ ShowLocked

ACT/ ShowLocked

UP/ ShowLocked

Esc/ showHowToUnlock

Down/ ShowLocked

Bolus/ ShowLocked

ACT/ ShowLocked

UP/ ShowLocked

Bolus

ACT

Esc

ACT

ACT

ACT/ SaveRate/ShowNextPanel

ACT

ACT/ SaveDateTime

ACT

Esc

ACT

Esc

UP/ ShowPreviousRecordDown/ ShowNextRecord

ACT

Esc

UP/ ShowPreviousRate

Down/ ShowNextRate

Esc

Esc

Down/ IncrementRate

Down/ DecrementRate

ACT/ StartDelivery

Esc

UP/ ShowPreviousLine

Down

ACT

Pump

EscInLock--

SetBolusPanel

Menu

Down

Down

Down

Down

Down

Down

Down

Down/ Beep

UP

UP

UP

UP

UP

UP

UP

UP/ Beep

ACTACT

ACTACT

ACTACT

ACTACT

ACTACT

ACTACT

ACTACT

DateTime

Suspend-Resume

ShowStatus

BolusHistory

BasalReview

Lock

setBasal

setBolus

Locked--

Default

Esc

Down Esc

Down

UP

UPUP

Normal--

EscPressed--

setBasalPanel

ACT ACT

UP/ IncrementHourDown/ DecrementHour

UP/ IncrementMinute

Down/ DecrementMinute

UP/ IncrementRateDown/ DecrementRate

ACT/ SaveRate/ShowNextPanelACT/ SaveRate/ShowNextPanel

AdjustHour

AdjustMinute

AdjustRate

DateTimePanel

ACT

ACT

ACT ACT

Down/ DecrementYearUP/ IncrementYearDown/ DecrementMonthUP/ IncrementMonth

Down/ DecrementDayUP/ IncrementDay

Down/ DecrementHour

UP/ IncrementHour

UP/ IncrementMinuteDown/ DecrementMinute

ACT/ SaveDateTimeACT/ SaveDateTime

AdjustYear

AdjustMonth AdjustDay AdjustHours AdjustMinutes

StatusDisplay

BolusHistoryDisplay

ReviewDisplay

14

case Menu:

this.setACTCommand(new gui.menu.ACTCommand());

this.setBolusCommand(new gui.menu.BolusCommand());

this.setESCCommand(new gui.menu.ESCCommand());

this.setUPCommand(new gui.menu.UPCommand());

this.setDownCommand(new gui.menu.DownCommand());

break;

case Default:

this.setACTCommand(new DefaultACTCommand());

this.setBolusCommand(new DefaultBolusCommand());

this.setESCCommand(new VoidCommand());

this.setUPCommand(new VoidCommand());

this.setDownCommand(new VoidCommand());

break;

case SetBalsal:

this.setACTCommand(new BasalACTCommand());

this.setBolusCommand(new VoidCommand());

this.setESCCommand(new BasalESCCommand());

this.setUPCommand(new BasalUPCommand());

this.setDownCommand(new BasalDownCommand());

break;

case SetBolus:

this.setACTCommand(new BolusACTCommand());

this.setBolusCommand(new VoidCommand());

this.setESCCommand(new BolusESCCommand());

this.setUPCommand(new BolusUPCommand());

this.setDownCommand(new BolusDownCommand());

break;

case SetDateTime:

this.setACTCommand(new DateTimeACTCommand());

this.setBolusCommand(new VoidCommand());

this.setESCCommand(new DateTimeESCCommand());

this.setUPCommand(new DateTimeUPCommand());

this.setDownCommand(new DateTimeDownCommand());

break;

case SuspendResum:

this.setACTCommand(new DefaultACTCommand());

this.setBolusCommand(new DefaultBolusCommand());

this.setESCCommand(new DefaultESCCommand());

this.setUPCommand(new VoidCommand());

this.setDownCommand(new VoidCommand());

break;

case StatusDisplay:

this.setACTCommand(new VoidCommand());

this.setBolusCommand(new VoidCommand());

this.setESCCommand(new ListDisplayESCCommand());

this.setUPCommand(new ListDisplayUPCommand());

this.setDownCommand(new ListDisplayDownCommand());

break;

case BolusHistoryDisplay:

this.setACTCommand(new VoidCommand());

this.setBolusCommand(new VoidCommand());

this.setESCCommand(new ListDisplayESCCommand());

this.setUPCommand(new ListDisplayUPCommand());

15

this.setDownCommand(new ListDisplayDownCommand());

break;

case BasalReviewDisplay:

this.setACTCommand(new VoidCommand());

this.setBolusCommand(new VoidCommand());

this.setESCCommand(new ListDisplayESCCommand());

this.setUPCommand(new ListDisplayUPCommand());

this.setDownCommand(new ListDisplayDownCommand());

break;

case Lock:

this.setACTCommand(new LockACTCommand());

this.setBolusCommand(new LockBolusCommand());

this.setESCCommand(new LockEscCommand());

this.setUPCommand(new LockUPCommand());

this.setDownCommand(new LockDownCommand());

break;

}

this.validate();

}

Figure 10: method "changeStateTo()" controlles the state change in the "MainFrame" Class

Menu Staechart to Code:

We should also implement the menu according to the statechart in figure 3.

For implementing that the state of the menu is represented by a "status"

property of the MenuScreen, which is of type "MenuStatus". MenuStatus is

an enumeration type of: "ViewUP", "ViewMID" and "ViewDown". "D" and

"U" in the statechart diagram represent Down and UP commands

respectively. You can see the implementation of the Down Command in

Figure 4.

16

Figure 11: An state chart for "MenuScreen" Class

public void execute(Object obj) {

// TODO Auto-generated method stub

MenuScreen s=(MenuScreen)MainFrame.getFrame().getScreenContent();

switch (s.getStatus()){

case ViewUP:

switch (s.getSelected()){

case 1:

s.setSelected(s.getSelected()+1);

break;

case 2:

s.setSelected(s.getSelected()+1);

break;

case 3:

s.setStartView(s.getStartView()+1);

s.setStatus(MenuStatus.ViewMID);

break;

}

break;

Menu

U [window+1=itemCount]/ vu

D [window+1=itemCount]/ vd

U [window+1<itemCount]/ vu

D [sv+3=7]/ vd

D [window+1<itemCount]/ vd

U [sv=2]/ vu

ViewMiddle

D [sv+3<7]/ vd

U [sv>2]/ vu

U/ u

U/ u D/ d

D/ d

U [window+1<itemCount]/ vuU [window+1<itemCount]/ vu

U [sv=2]/ vuU [sv=2]/ vu

D [sv+3=7]/ vdD [sv+3=7]/ vd

D [window+1<itemCount]/ vdD [window+1<itemCount]/ vd

m1

m3

m2

ViewUP

D [window=itemCount]/ beep

U/ u

U/ beep

U/ u

D/ d

D/ d

U [window+1=itemCount]/ vuU [window+1=itemCount]/ vu

U [sv=2]/ vuU [sv=2]/ vu

D [window+1=itemCount]/ vdD [window+1=itemCount]/ vd

D [window+1<itemCount]/ vdD [window+1<itemCount]/ vd

u1

u3

u2

ViewDown

D/ beep

U/ u

U/ u D/ d

D/ d

U [window+1=itemCount]/ vuU [window+1=itemCount]/ vu

U [window+1<itemCount]/ vuU [window+1<itemCount]/ vu

D [window+1=itemCount]/ vdD [window+1=itemCount]/ vd

D [sv+3=7]/ vdD [sv+3=7]/ vd

d1

d2

d3

d = selected --

u= selected ++

vd = startView --

vu= startView ++

sv= startView

17

case ViewMID:

switch (s.getSelected()){

case 1:

s.setSelected(s.getSelected()+1);

break;

case 2:

s.setSelected(s.getSelected()+1);

break;

case 3:

if (s.getStartView()==s.ITEM_COUNT-4){

s.setStartView(s.getStartView()+1);

s.setStatus(MenuStatus.ViewDown);

}

else{ //(s.getEndView()<7)

s.setStartView(s.getStartView()+1);

}

break;

}

break;

case ViewDown:

switch (s.getSelected()){

case 1:

s.setSelected(s.getSelected()+1);

break;

case 2:

s.setSelected(s.getSelected()+1);

break;

case 3:

//beep

java.awt.Toolkit.getDefaultToolkit().beep();

break;

}

break;

}

s.updateScreen();

}

Figure 12: implementation of menu statechart Diagram.

Inner cases in this implementation map to the inner states in the

statechart diagram. In the case that the menu reaches the last element of

the menu it beeps to indicates no further movement is possible.

18

Like the other commands in the system, Command of the Down button is an

implementation of the "Command" interface. That is why we don't have a

method like Down or something like that, and we have a method named

execute instead. You can see the implementation of the menu in figure

bellow.

Figure 13:Implementation of the menu in the insulin pump

Pump Class to Code

We need to use thread to implement concurrency in the program

executions. Since we have some tasks that execute concurrently like

consuming battery and injecting reservoir and also counting down times.

The classes that are uses threads are pump, battery and pumptimer.

Pump class is the most important class in the system, which controls the

whole behavior of the system. This class has to be a thread to control the

delivery of insulin and also to control the some other parts such as

reservoir, basal and bolus. This class has many functions and implements

19

the pump interface to provide some facility for GUI packages. In the other

word, the pump class plays as a virtual machine for the GUI level (Figure

1).

package Controller;

import java.util.Date;

import java.util.Vector;

public interface PumpInterface {

public int getMaxBatteryAmount();

public void setMaxBatteryAmount(int amount);

public void setBatteryUsageRate(int rate);

public void setDeliveryRateForBolus(int rate);

public void AlarmRateSeconds(int rate);

public int getBatteryAmount();

public int getMaxReservoirAmount();

public void setMaxReservoirAmount(int amount);

public int getReservoirAmount();

public boolean isSuspended();

public PumpState getPumpState();

public BasalRate getBasalRate(int ith);

public Vector<String> getPumpStatusInfo();

public Vector<String> getBolusHistory();

public Vector<String> getBasalReview();

public Date getDateTime();

public void setBasalRate(int ith, int hour, int minute, int

rate);

20

public boolean setBolus(double b);

public void setDateTime(Date b);

public void setBatteryVal(int val);

public void setReservoirVal(int val);

public void clearBolusHistory() throws Exception;

public void clearBasalRates() throws Exception;

public void suspendPump();

public void resumePump();

public void initialize()throws Exception ;

public void startController();

public boolean pumpFinalize();

public int getBolusAmount();

public int getMaxBolusAmount();

}

Figure 14- Pump Interface

Battery Class toCode: Battery is a major part in a real pump and also battery is used continuously

by pump to do its activities. Therefore in this simulation battery has been

developed by a java thread. Importantly, battery has different usage rates

to simulate real situation correctly. We change the battery status to the

NOBATTERY which means the battery has finished and the pump doesn’t

work any more but If the tester recharge the battery by the provided slider

then pump ill work properly again. Figure shows the implementation of

the battery class.

package Controller;

public class Battery extends Thread {

21

private boolean turnOff;

private int charge;

private static int Rate = 1;

private CapacityStatus status;

private static int MaxBatteryAmount = 1000;

private static Battery uniqueInstance = null;

public static Battery getBattery(){

if (uniqueInstance == null) {

uniqueInstance = new Battery();

}

return uniqueInstance ;

}

public static void setBatteryUsageRate(int rate){

Rate = 1;

if (rate >= 1)

Rate = rate;

System.out.println("RATE ---->"+rate);

}

private Battery() {

charge = MaxBatteryAmount;

status = CapacityStatus.FULL;

turnOff = false;

}

public int getMaxBatteryamount(){

return MaxBatteryAmount;

22

}

public static void setMaxBatteryamount(int amount){

if (amount > 0)

{

MaxBatteryAmount = amount;

}else{

MaxBatteryAmount = 1000;

}

}

public void run(){

try {

charge = charge - (1*Rate);

Thread.sleep(1000);

adjustStatus();

if (charge <0){

charge = 0;

}

if (!turnOff){

run();

}

else{

System.out.println("Battery Terminated");

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

23

@Override

public String toString() {

return "Battery [turnOff=" + turnOff + ", charge=" +

charge + ", rate="

+ Rate + ", status=" + status + "]";

}

public void setCharge(int charge) {

if (charge < 0)

charge = 0;

if (charge >= MaxBatteryAmount)

{

this.charge = MaxBatteryAmount;

}

else{

this.charge = charge;

}

adjustStatus();

}

public int getCharge() {

return charge;

}

public CapacityStatus getStatus() {

return status;

}

24

public int getRate() {

return Rate;

}

public void setTurnOff(){

turnOff = true;

}

private void adjustStatus(){

if (charge >= 0 && charge < 0.2*MaxBatteryAmount){

status = CapacityStatus.VERY_LOW;

}

if (charge >= 0.2*MaxBatteryAmount && charge <

0.4*MaxBatteryAmount){

status = CapacityStatus.LOW;

}

if (charge >= 0.4*MaxBatteryAmount && charge <

0.6*MaxBatteryAmount){

status = CapacityStatus.MID;

}

if (charge >= 0.6*MaxBatteryAmount && charge <

0.8*MaxBatteryAmount){

status = CapacityStatus.HIGH;

}

if (charge >= 0.8*MaxBatteryAmount){

status = CapacityStatus.FULL;

}

}

}

Figure 15- Battery Class

25

PumpTimer to Code

This class simulates the time and plays the clock role in the pump. Hence

this class has to be a thread and run simultaneously with other parts of the

pump.

Using Java Properties Class

To save and manages the configuration parameter of the pump, we used

the properties class of Java. Desired properties, which we manage them,

these properties are:

MaxBatteryAmount

This value shows the maximum amount, which the battery can have.

MaxResevoirAmount

This value shows the maximum tank capacity, which the reservoir can have.

BatteryUsageRate

This property indicates what is the battery usage ratio when the pump tries to deliver insulin to

the patient.

DeliveryRateForBolus

In this property we can set how many seconds do we like to deliver whole bolus amount to the

patient.

AlarmRateSeconds

This property has the period (in seconds) that the pump generates an alarm for the patient.

26

Implementing Collections

We have used Vector class to implement the compositions and the

aggregations in the UML model. For example this can be seen in the

Using Java Serializable class

In order to save and to restore some classes from and to file we inherit our

classes from this class. Therefore we could store and retrieve some

classes in the dataprovider class easily.

Singleton Pattern

To ensure that some classes have just one object in runtime we implement

this pattern for the below classes.

1) DataProvider 2) Basal 3) PumpTimer 4) Pump 5) Battery 6) BolusHistory 7) Reservoir

Exception error handling

We have used try and catch mechanism to handle the errors, which occur

in runtime.

27

Test Plan

Black Box test

“Black-box testing is a method of software testing that tests the functionality

of an application as opposed to its internal structures or workings. Specific

knowledge of the application's code/internal structure and programming

knowledge in general is not required. Test cases are built around

specifications and requirements, i.e., what the application is supposed to

do. It uses external descriptions of the software, including specifications,

requirements, and design to derive test cases. These tests can be

functional or non-functional, though usually functional. The test designer

selects valid and invalid inputs and determines the correct output. There is

no knowledge of the test object's internal structure. (Ref: wikipedia)”

We have used this kind of testing in the level of unit, integration and

acceptance.

Unit Test

“Unit testing is a method by which individual units of source code are tested

to determine if they are fit for use. A unit is the smallest testable part of an

application. In procedural programming a unit may be an individual function

or procedure. In object-oriented programming a unit is usually a method.“

28

In our project almost we tested each packages separately. For this reason

we defined some test driver program and we feed the driver with some data

to check correctness of the package activity.

Integration Test

“Integration is the phase in software testing in which individual software

modules are combined and tested as a group.”

After unit test, we integrated the packages then we tested the application

again by test driver program. You can see the program in the Figure 16.

This program was used for unit test and integration test.

Test Driver Program

import java.io.IOException;

import java.io.ObjectInputStream.GetField;

import java.sql.Time;

import java.util.*;

import Controller.*;

import Data.*;

public class main {

private static void PrintMenu()

{

System.out.println("1: Set Time");

29

System.out.println("2: Add Bolus");

System.out.println("3: Add basel");

System.out.println("4: Change Reservoir");

System.out.println("5: Change Battery");

System.out.println("6: Show Basal Rates");

System.out.println("7: Show Pump Status");

System.out.println("8: Show Bolus History");

System.out.println("9: Suspend");

System.out.println("10: Resume");

System.out.println("11: Remove Bolus History");

System.out.println("12: Clear Basal Rates");

System.out.println("13: Terminate");

}

public static void main(String[] args) {

Pump pump = Pump.getPump();

BasalRate br = new BasalRate();

try{

/* DataProvider dataProvider =

DataProvider.getDataProvider("basal.txt",

"battery.txt","reservoir.txt","bolushist.txt", "date.txt");

Reservoir reservoir = Reservoir.getReservoir();

reservoir.setTankCapacity(34.98);

dataProvider.storeReservoirState(reservoir);

reservoir.setTankCapacity(120);

reservoir=dataProvider.retriveReservoirState();

30

System.out.println(reservoir.getTankCapacity());

*/

int test;

pump.initialize();

pump.start();

Scanner in = new Scanner(System.in);

while(true){

PrintMenu();

test=in.nextInt();

if (test == 1){

long tt;

tt = in.nextLong();

Date dt = new Date(tt);

pump.setDateTime(dt);

}

if (test==2){

double db = in.nextDouble();

pump.setBolus(db);

}

if (test == 3){

System.out.print("Enter ith ---> ");

int ith = in.nextInt();

System.out.print("Enter Rate ---> ");

br.setRate(in.nextDouble());

System.out.print("Enter Date ---> ");

Date t = new Date(in.nextLong());

br.setTime(t);

pump.setBasalRate(ith, br);

31

}

if(test == 4){

double b = in.nextDouble();

pump.changeResorvoir(b);

}

if (test == 5){

int i = in.nextInt();

pump.changeBattery(i);

}

if(test == 6){

int j = 1;

if (pump.getBasalRate(1)==null){

System.out.println("No Basal

Rate");

}

else{

while(pump.getBasalRate(j)!=null){

System.out.println(pump.getBasalRate(j).toString());

j++;

}

}

}

if (test == 7)

{

Vector<String> vc =new

Vector<String>();

if (pump.getPumpStatusInfo()!=null){

vc = pump.getPumpStatusInfo();

}

if (vc != null){

32

System.out.println(vc.size());

for(int i =0; i < vc.size();

i++){

System.out.println(vc.elementAt(i).toString());

}

}

else{

System.out.println("No

History");

}

}

if (test==8){

Vector<String> vc =new

Vector<String>();

// if (pump.getBolusHistory()!=null){

vc = pump.getBolusHistory();

// }

if (vc != null){

//System.out.println(vc.size());

for(int i =0; i < vc.size();

i++){

System.out.println(vc.elementAt(i).toString());

}

}

else{

System.out.println("No

History");

}

}

33

if (test == 9)

{

pump.suspendPump();

}

if(test==10){

pump.resumePump();

}

if (test == 11){

pump.clearBolusHistory();

;}

if (test == 12){

pump.clearBasalRates();

}

if (test == 13){

if (pump.pumpFinalize())

break;}

}

in.close();

/* DataProvider dataProvider =

DataProvider.getDataProvider("basal.txt",

"battery.txt","reservoir.txt","bolushist.txt");

BasalRate br1 = new BasalRate();

BasalRate br2 = new BasalRate();

BasalRate br3 = new BasalRate();

br1.setTime(new Time(120000000));

br1.setRate(12.1);

br2.setTime(new Time(220000000));

34

br2.setRate(14.3);

br3.setTime(new Time(320000000));

br3.setRate(16.2);

Battery bat = new Battery();

bat.setCharge(100);

bat.start();

Basal bs = Basal.getBasal();

bs.addBasalRate(br3);

bs.addBasalRate(br2);

bs.addBasalRate(br1);

bs.exportToList();

dataProvider.storeBasal(bs);

bs.clearBasalAll();

bs.exportToList();

bs = dataProvider.retriveBasal();

bs.exportToList();

for (long i=0; i < 100; i++)

{

for(long j =0; j < 100; j++)

{

System.out.println("test");

if (i*j ==8000)

bat.setCharge(10);

35

}

}

Bolus b1 = new Bolus();

b1.setAmount(20);

b1.setAmountDelivered(21);

Bolus b2 = new Bolus();

b2.setAmount(40);

b2.setAmountDelivered(41);

BolusHistory bh= new BolusHistory();

bh.addBolus(b1);

bh.addBoluses(b2);

bh.addBolus(b1);

bh.addBolus(b1);

dataProvider.storeBolusHistory(bh);

BolusHistory bh2= new BolusHistory();

bh2 = dataProvider.retriveBolusHistory();

bh2.exportToList();

/* Battery battery = new Battery();

battery.setCharge(110);

dataProvider.storeBatteryState(battery);

battery = dataProvider.retriveBatteryState();

System.out.println(battery.getCharge());

36

*/

}

catch(Exception exception){

System.err.println(exception.toString());

pump.pumpFinalize();

}

}

}

Figure 16- Test Driver Program

A Typical Feature of system for testing

We tried to use some slider in the interface to facilitate testing the pump

while intentionally decreasing to increasing the battery and the reservoir

content. Using these slide bar, user can increase or decrease the battery

level or he/she can increase or decrease the reservoir content and get the

reaction of the systems to these events.

When user, for example push up the battery slidebar, the Pump class in the

controller package is informed by the user interface. Then the appropriate

reaction to this change is calculated and generated by the pump. This

reaction will be reflected by the userinterface to the user. As an example if

37

the battery levels comes down from an special amount, say 20 percent,

Pump goes to an especial status and this is reflected on the pump interface

by showing an special indicator on the screen. Figure bellow:

Figure 17: Slidebars to change the values of reservoir and battery

Sample Test cases

We ignored the whole scenario of the test cases since the steps are trivial

therefore just we’ve mentioned the conditions and the results.

Unit test, test cases level

Test Case 1: Store and retrieve of Battery information

SCENARIO: In the test driver program we constructed an object of Battery

then we set the battery level to 110 then we stored them and after that we

retrieved the object of the battery from the file and we printed the

information (see below).

38

Battery battery = new Battery();

battery.setCharge(110);

dataProvider.storeBatteryState(battery);

battery = dataProvider.retriveBatteryState();

System.out.println(battery.getCharge());

Test Case 2: Store and retrieve of bolus history information

SCENARIO: In the test driver program we constructed an object of Bolus

history and also we constructed two bolus object and delivered insulin to

the patient by them then add them to the bolus history. Afterward we stored

the bolus history by dataprovider object and after that we retrieved the

object of the bolus history from the file and we printed the information.

Bolus b1 = new Bolus();

b1.setAmount(20);

b1.setAmountDelivered(21);

Bolus b2 = new Bolus();

b2.setAmount(40);

b2.setAmountDelivered(41);

BolusHistory bh= new BolusHistory();

bh.addBolus(b1);

bh.addBoluses(b2);

bh.addBolus(b1);

bh.addBolus(b1);

39

dataProvider.storeBolusHistory(bh);

BolusHistory bh2= new BolusHistory();

bh2 = dataProvider.retriveBolusHistory();

bh2.exportToList();

Acceptance test, test cases level

Test Case 1: Change Battery Level

SCENARIO: Tester change battery level to ZERO level to test the behavior

of software and check the stability of system.

RESULT: Software produced some EXCEPTION.

Test Case 2: Test battery usage ratio

SCENARIO: Tester use bolus key and set the bolus rate to 10 units and

compare the battery usage per minute to the past.

RESULT: There isn’t any change in the usage ratio.

Test Case 3: Display Bolus History

40

SCENARIO: Tester push the ACT button then selects the bolus history

menu.

RESULT: The bolus history was displayed successfully without any

problem.