From 1eac542beb6e03e8390f07e9890c58e3f7e4023c Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 19:41:34 +0200 Subject: [PATCH 01/45] Uitwerking Koenen Kramers Workshop --- exercises/koenenkramers/pom.xml | 12 +++++++++ .../src/main/java/DictionaryAdapter.java | 6 +++++ .../main/java/DictionaryAdapterFactory.java | 24 +++++++++++++++++ .../main/java/KoenenDictionaryAdapter.java | 19 ++++++++++++++ .../main/java/KramersDictionaryAdapter.java | 16 ++++++++++++ .../src/main/java/TranslateToDutch.java | 26 +++++++++++++++++++ 6 files changed, 103 insertions(+) create mode 100644 exercises/koenenkramers/pom.xml create mode 100755 exercises/koenenkramers/src/main/java/DictionaryAdapter.java create mode 100644 exercises/koenenkramers/src/main/java/DictionaryAdapterFactory.java create mode 100644 exercises/koenenkramers/src/main/java/KoenenDictionaryAdapter.java create mode 100755 exercises/koenenkramers/src/main/java/KramersDictionaryAdapter.java create mode 100755 exercises/koenenkramers/src/main/java/TranslateToDutch.java diff --git a/exercises/koenenkramers/pom.xml b/exercises/koenenkramers/pom.xml new file mode 100644 index 0000000..78d3cf4 --- /dev/null +++ b/exercises/koenenkramers/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + nl.oose.dea.workshop + KoenenKramers + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/exercises/koenenkramers/src/main/java/DictionaryAdapter.java b/exercises/koenenkramers/src/main/java/DictionaryAdapter.java new file mode 100755 index 0000000..61d95ac --- /dev/null +++ b/exercises/koenenkramers/src/main/java/DictionaryAdapter.java @@ -0,0 +1,6 @@ +public interface DictionaryAdapter +{ + public String getName(); + + public String translate(String input); +} diff --git a/exercises/koenenkramers/src/main/java/DictionaryAdapterFactory.java b/exercises/koenenkramers/src/main/java/DictionaryAdapterFactory.java new file mode 100644 index 0000000..3e00329 --- /dev/null +++ b/exercises/koenenkramers/src/main/java/DictionaryAdapterFactory.java @@ -0,0 +1,24 @@ +public class DictionaryAdapterFactory +{ + private static DictionaryAdapterFactory instance; + + private DictionaryAdapterFactory() + { + } + + public static DictionaryAdapterFactory getInstance() + { + if(instance == null) + instance = new DictionaryAdapterFactory(); + return instance; + } + + public DictionaryAdapter create(String name) + { + if("Koenen".equals(name)) + return new KoenenDictionaryAdapter(); + else if("Kramers".equals(name)) + return new KramersDictionaryAdapter(); + return null; + } +} diff --git a/exercises/koenenkramers/src/main/java/KoenenDictionaryAdapter.java b/exercises/koenenkramers/src/main/java/KoenenDictionaryAdapter.java new file mode 100644 index 0000000..ab750ce --- /dev/null +++ b/exercises/koenenkramers/src/main/java/KoenenDictionaryAdapter.java @@ -0,0 +1,19 @@ +public class KoenenDictionaryAdapter implements DictionaryAdapter { + + private KoenenDictionary kd; + + public KoenenDictionaryAdapter(){ + kd = new KoenenDictionary(); + kd.openEnglishDutch(); + kd.openDutchEnglish(); + } + + public String getName() { + return "Koenen"; + } + + public String translate(String word) { + return kd.lookUp(word); + } + +} diff --git a/exercises/koenenkramers/src/main/java/KramersDictionaryAdapter.java b/exercises/koenenkramers/src/main/java/KramersDictionaryAdapter.java new file mode 100755 index 0000000..a303881 --- /dev/null +++ b/exercises/koenenkramers/src/main/java/KramersDictionaryAdapter.java @@ -0,0 +1,16 @@ +public class KramersDictionaryAdapter implements DictionaryAdapter +{ + private KramersDictionary kramersDictionary = new KramersDictionary(); + + @Override + public String getName() + { + return "Kramers"; + } + + @Override + public String translate(String input) + { + return kramersDictionary.find(input); + } +} diff --git a/exercises/koenenkramers/src/main/java/TranslateToDutch.java b/exercises/koenenkramers/src/main/java/TranslateToDutch.java new file mode 100755 index 0000000..0e177ab --- /dev/null +++ b/exercises/koenenkramers/src/main/java/TranslateToDutch.java @@ -0,0 +1,26 @@ +public class TranslateToDutch { + private DictionaryAdapterFactory daf = DictionaryAdapterFactory.getInstance(); + + + public static void main(String[] args) { + TranslateToDutch translateToDutch = new TranslateToDutch(); + translateToDutch.translate(); + } + + public void translate() { + String toTranslate = "goat"; + + DictionaryAdapter koenen = daf.create("Koenen"); + DictionaryAdapter kramer = daf.create("Kramers"); + + String translatedWord = koenen.translate(toTranslate); + if (translatedWord != null) { + System.out.println(translatedWord); + } + else if(kramer.translate(toTranslate) != null){ + System.out.println(kramer.translate(toTranslate)); + } else { + System.out.println("woord niet gevonden"); + } + } +} From 3481d6d5b1765804bfc3263e379cc17439117db9 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 19:58:27 +0200 Subject: [PATCH 02/45] Uitwerking BolAnimatie --- .../runversie/BolAnimatieApplet.jar | Bin 7324 -> 0 bytes .../bolanimatie/runversie/bolanimatie.html | 11 - .../java/bolanimatie/AnimatieRegelaar.java | 244 ++++++++------- .../main/java/bolanimatie/BolAnimatie.java | 280 ++++++++++-------- .../java/bolanimatie/BolAnimatieApplet.java | 78 ++--- 5 files changed, 334 insertions(+), 279 deletions(-) delete mode 100755 exercises/bolanimatie/runversie/BolAnimatieApplet.jar delete mode 100755 exercises/bolanimatie/runversie/bolanimatie.html mode change 100755 => 100644 exercises/bolanimatie/src/main/java/bolanimatie/AnimatieRegelaar.java mode change 100755 => 100644 exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatie.java mode change 100755 => 100644 exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatieApplet.java diff --git a/exercises/bolanimatie/runversie/BolAnimatieApplet.jar b/exercises/bolanimatie/runversie/BolAnimatieApplet.jar deleted file mode 100755 index 0cfc62f72d43d0f628bceddf3d30be01537a14bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7324 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 z - -Stuiterballetje - - -

Speel pong!

- -Your browser does not support Java, so nothing is displayed. - - - diff --git a/exercises/bolanimatie/src/main/java/bolanimatie/AnimatieRegelaar.java b/exercises/bolanimatie/src/main/java/bolanimatie/AnimatieRegelaar.java old mode 100755 new mode 100644 index 4084a49..bf16f87 --- a/exercises/bolanimatie/src/main/java/bolanimatie/AnimatieRegelaar.java +++ b/exercises/bolanimatie/src/main/java/bolanimatie/AnimatieRegelaar.java @@ -1,109 +1,135 @@ -package bolanimatie; - -/** - * - */ - -import java.awt.*; -import java.awt.event.*; -import java.applet.*; -import java.util.*; -import javax.swing.*; - -class AnimatieRegelaar extends JPanel - implements ActionListener -{ // Variables - private BolAnimatie ba; - - private JLabel richtingLabel; - private JTextField richtingInput; - private JButton richtingOk; - - private JButton stapbutton; - - private JLabel snelheidLabel; - private JTextField snelheidInput; - private JButton snelheidOk; - - public AnimatieRegelaar(BolAnimatie b, Color bg) - { ba = b; - Font display = new Font("SansSerif", Font.PLAIN, 12); - setBackground(bg); - - setSize(250, 400); - setLayout(null); - - richtingLabel = new JLabel("Richting (0-90)"); - richtingLabel.setFont(display); - richtingLabel.setVisible(true); - richtingLabel.setSize(100, 20); - richtingLabel.setLocation(5, 20); - add(richtingLabel); - richtingInput = new JTextField(Integer.toString(BolAnimatie.STARTRICHTING), 5); - richtingInput.setFont(display); - richtingInput.setVisible(true); - richtingInput.setSize(60, 24); - richtingInput.setLocation(110, 20); - add(richtingInput); - richtingOk = new JButton( "Ok"); - richtingOk.addActionListener(this); - richtingOk.setFont(display); - richtingOk.setVisible(true); - richtingOk.setEnabled(true); - richtingOk.setSize(60, 24); - richtingOk.setLocation(180, 20); - add(richtingOk); - - stapbutton = new JButton( "Stap" ); - stapbutton.addActionListener(this); - stapbutton.setFont(display); - stapbutton.setVisible(true); - stapbutton.setEnabled(true); - stapbutton.setSize(120, 25); - stapbutton.setLocation(5, 200); - add(stapbutton); - - snelheidLabel = new JLabel("Snelheid (1-50)"); - snelheidLabel.setFont(display); - snelheidLabel.setVisible(true); - snelheidLabel.setSize(100, 20); - snelheidLabel.setLocation(5, 300); - add(snelheidLabel); - snelheidInput = new JTextField(Integer.toString(BolAnimatie.STARTSNELHEID), 5); - snelheidInput.setFont(display); - snelheidInput.setVisible(true); - snelheidInput.setSize(60, 24); - snelheidInput.setLocation(110, 300); - add(snelheidInput); - snelheidOk = new JButton( "Ok"); - snelheidOk.addActionListener(this); - snelheidOk.setFont(display); - snelheidOk.setVisible(true); - snelheidOk.setEnabled(true); - snelheidOk.setSize(60, 24); - snelheidOk.setLocation(180, 300); - add(snelheidOk); - } - -// ----- Listeners, ActionListener ------- - - public void actionPerformed(ActionEvent e) - { if ( e.getSource() == stapbutton ) - { ba.paintStep(); - } else if ( e.getSource() == richtingOk ) - { try - { int ri = Integer.parseInt(richtingInput.getText()); - ba.setRichting(ri); - } catch ( NumberFormatException e1 ) - {} // niks doen als input niet ok is... - } else if ( e.getSource() == snelheidOk ) - { int v = 0; - try - { int s = Integer.parseInt(snelheidInput.getText()); - ba.setSnelheid(s); - } catch ( NumberFormatException e2 ) - {} - } - } - -} +package bolanimatie; + +/** + * + */ + +import java.awt.*; +import java.awt.event.*; +import java.applet.*; +import java.util.*; +import javax.swing.*; + +class AnimatieRegelaar extends JPanel implements ActionListener { // Variables + private BolAnimatie ba; + + private JLabel richtingLabel; + private JTextField richtingInput; + private JButton richtingOk; + + private JButton stapbutton; + private JButton startStopButton; + + private JLabel snelheidLabel; + private JTextField snelheidInput; + private JButton snelheidOk; + + public AnimatieRegelaar(BolAnimatie b, Color bg) { + ba = b; + Font display = new Font("SansSerif", Font.PLAIN, 12); + setBackground(bg); + + setSize(250, 400); + setLayout(null); + + richtingLabel = new JLabel("Richting (0-90)"); + richtingLabel.setFont(display); + richtingLabel.setVisible(true); + richtingLabel.setSize(100, 20); + richtingLabel.setLocation(5, 20); + add(richtingLabel); + richtingInput = new JTextField( + Integer.toString(BolAnimatie.STARTRICHTING), 5); + richtingInput.setFont(display); + richtingInput.setVisible(true); + richtingInput.setSize(60, 24); + richtingInput.setLocation(110, 20); + add(richtingInput); + richtingOk = new JButton("Ok"); + richtingOk.addActionListener(this); + richtingOk.setFont(display); + richtingOk.setVisible(true); + richtingOk.setEnabled(true); + richtingOk.setSize(60, 24); + richtingOk.setLocation(180, 20); + add(richtingOk); + + stapbutton = new JButton("Stap"); + stapbutton.addActionListener(this); + stapbutton.setFont(display); + stapbutton.setVisible(true); + stapbutton.setEnabled(true); + stapbutton.setSize(120, 25); + stapbutton.setLocation(5, 200); + add(stapbutton); + + startStopButton = new JButton("Start"); + startStopButton.addActionListener(this); + startStopButton.setVisible(true); + startStopButton.setEnabled(true); + startStopButton.setSize(120, 25); + stapbutton.setLocation(130, 200); + + add(startStopButton); + + snelheidLabel = new JLabel("Snelheid (1-50)"); + snelheidLabel.setFont(display); + snelheidLabel.setVisible(true); + snelheidLabel.setSize(100, 20); + snelheidLabel.setLocation(5, 300); + add(snelheidLabel); + snelheidInput = new JTextField( + Integer.toString(BolAnimatie.STARTSNELHEID), 5); + snelheidInput.setFont(display); + snelheidInput.setVisible(true); + snelheidInput.setSize(60, 24); + snelheidInput.setLocation(110, 300); + add(snelheidInput); + snelheidOk = new JButton("Ok"); + snelheidOk.addActionListener(this); + snelheidOk.setFont(display); + snelheidOk.setVisible(true); + snelheidOk.setEnabled(true); + snelheidOk.setSize(60, 24); + snelheidOk.setLocation(180, 300); + add(snelheidOk); + } + + // ----- Listeners, ActionListener ------- + public void threadHasStopped() + { + startStopButton.setEnabled(true); + } + + public void actionPerformed(ActionEvent e) { + if (e.getSource() == startStopButton) + { + startStopButton.setEnabled(false); + ba.toggle(this); + if(startStopButton.getText().equals("Start")) + { + startStopButton.setText("Stop"); + } + else { + startStopButton.setText("Start"); + } + } + else if (e.getSource() == stapbutton) { + ba.paintStep(); + } else if (e.getSource() == richtingOk) { + try { + int ri = Integer.parseInt(richtingInput.getText()); + ba.setRichting(ri); + } catch (NumberFormatException e1) { + } // niks doen als input niet ok is... + } else if (e.getSource() == snelheidOk) { + int v = 0; + try { + int s = Integer.parseInt(snelheidInput.getText()); + ba.setSnelheid(s); + } catch (NumberFormatException e2) { + } + } + } + +} diff --git a/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatie.java b/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatie.java old mode 100755 new mode 100644 index 5748308..a53cec5 --- a/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatie.java +++ b/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatie.java @@ -1,120 +1,160 @@ -package bolanimatie; - -/** - * - */ - -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import javax.swing.*; - -class BolAnimatie extends JPanel -{ // Constants - public static final int SIZE = 350; // omvang Canvas: 350x350 - public static final int BOLSIZE = 20; // omvang vierkant: 20x20 - public static final int COLORSTEP = 255/(BOLSIZE/2); - public static final int STARTSNELHEID = 10; // sleeptime is 1000/snelheid - public static final int STARTRICHTING = 45; // schuin - - private double xpos = (SIZE-BOLSIZE)/2; // zet balletje in het midden - private double ypos = (SIZE-BOLSIZE)/2; // linksbovenhoek van bounding vierkant! - private double xspeed = 7; - private double yspeed = 7; - private int xdir = 1; // -1 of +1 - private int ydir = 1; - - private int sleeptime = 1000/STARTSNELHEID; // sleeptime van de thread - -/** - * constructor - */ - public BolAnimatie() - { // ----- uiterlijk - setBackground(Color.white); - setSize(SIZE, SIZE); - } - -/** - * Balletje verplaatsen. - * NB: de x- en y-component in de stap zijn altijd positief. De variabelen xdir en - * ydir zijn -1 of 1 en bepalen de richting door vermenigvuldiging - * (bijvoorbeeld xdir*xspeed) - * Wanneer het balletje de rand van het speelveld dreigt te passeren, wordt de - * betreffende dir-variable omgeklapt, waardoor de richting van de bal omdraait. - */ - private void moveBol() - { xpos = xpos + xdir*xspeed; - if ( xpos <= 0 ) // kan als xdir = -1, bal loopt links weg - { xpos = 0; - xdir = 1; // change dir - } - if ( xpos >= SIZE-BOLSIZE ) // kan als xdir = 1, bal loopt rechts weg - { xpos = SIZE-BOLSIZE; - xdir = -1; // change dir - } - ypos = ypos + ydir*yspeed; - if ( ypos <= 0 ) // kan als ydir = -1, bal loopt boven weg - { ypos = 0; - ydir = 1; // change dir - } - if ( ypos >= SIZE-BOLSIZE ) // kan als xdir = 1, bal loopt onder weg - { ypos = SIZE-BOLSIZE; - ydir = -1; // change dir - } - } - -// ------- Gebruikersacties -------------------- - -/** - * Richting instellen: De hoek van de richting (in graden) wordt omgerekend - * in radialen. Daarna sin en cos gebruiken om de y- en x-component van een - * stap uit te rekenen - * - * @param ri De gekozen hoek uit de regelaar - */ - public void setRichting(int ri) - { if ( ri >= 0 && ri <= 90 ) - { double rad = (Math.PI/2)*( ((double)ri)/90); - xspeed = Math.cos(rad)*10; - yspeed = Math.sin(rad)*10; - } // else do nothing - } - -/** - * Snelheid instellen: hogere snelheid realiseren door de tijd bij sleep(int t) - * te verlagen. Dit wordt bereikt door 1000/snelheid als slaaptijd te nemen. - * - * @param s De gekozen snelheid uit de regelaar - */ - public void setSnelheid(int s) - { if ( s>=1 && s<=50 ) - { sleeptime = 1000/s; // hogere snelheid: kortere slaaptijd! - } // else do nothing - } - -/** - * Teken een stap: verplaats het balletje en teken opnieuw - */ - public void paintStep() // Regelpaneel: knop 'Stap' - { moveBol(); - repaint(); - } - -// ------- Painting and buffering -------------------- - -/** - * Teken het speelveld (wit vlak!) en het balletje - */ - public void paintComponent(Graphics g) - { // verplicht, zorgt voor witte achtergrond - super.paintComponent(g); - // Bol bestaat uit in kleur verlopende concentrische cirkels (blauw -> rood) - int ixpos = (int)Math.round(xpos); - int iypos = (int)Math.round(ypos); - for ( int k=0; k<=BOLSIZE/2; k++ ) - { g.setColor(new Color(COLORSTEP*k, 0, 255-COLORSTEP*k)); - g.fillOval(ixpos+k, iypos+k, BOLSIZE-2*k, BOLSIZE-2*k); - } - } -} +package bolanimatie; + +/** + * + */ + +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +import javax.swing.*; + +class BolAnimatie extends JPanel implements Runnable { // Constants + public static final int SIZE = 350; // omvang Canvas: 350x350 + public static final int BOLSIZE = 20; // omvang vierkant: 20x20 + public static final int COLORSTEP = 255 / (BOLSIZE / 2); + public static final int STARTSNELHEID = 10; // sleeptime is 1000/snelheid + public static final int STARTRICHTING = 45; // schuin + + private double xpos = (SIZE - BOLSIZE) / 2; // zet balletje in het midden + private double ypos = (SIZE - BOLSIZE) / 2; // linksbovenhoek van bounding + // vierkant! + private double xspeed = 7; + private double yspeed = 7; + private int xdir = 1; // -1 of +1 + private int ydir = 1; + + private int sleeptime = 1000 / STARTSNELHEID; // sleeptime van de thread + + private boolean running; + private Thread tekenThread; + + /** + * constructor + */ + public BolAnimatie() { // ----- uiterlijk + setBackground(Color.white); + setSize(SIZE, SIZE); + } + + /** + * Balletje verplaatsen. NB: de x- en y-component in de stap zijn altijd + * positief. De variabelen xdir en ydir zijn -1 of 1 en bepalen de richting + * door vermenigvuldiging (bijvoorbeeld xdir*xspeed) Wanneer het balletje de + * rand van het speelveld dreigt te passeren, wordt de betreffende + * dir-variable omgeklapt, waardoor de richting van de bal omdraait. + */ + private void moveBol() { + xpos = xpos + xdir * xspeed; + if (xpos <= 0) // kan als xdir = -1, bal loopt links weg + { + xpos = 0; + xdir = 1; // change dir + } + if (xpos >= SIZE - BOLSIZE) // kan als xdir = 1, bal loopt rechts weg + { + xpos = SIZE - BOLSIZE; + xdir = -1; // change dir + } + ypos = ypos + ydir * yspeed; + if (ypos <= 0) // kan als ydir = -1, bal loopt boven weg + { + ypos = 0; + ydir = 1; // change dir + } + if (ypos >= SIZE - BOLSIZE) // kan als xdir = 1, bal loopt onder weg + { + ypos = SIZE - BOLSIZE; + ydir = -1; // change dir + } + } + + // ------- Gebruikersacties -------------------- + + /** + * Richting instellen: De hoek van de richting (in graden) wordt omgerekend + * in radialen. Daarna sin en cos gebruiken om de y- en x-component van een + * stap uit te rekenen + * + * @param ri + * De gekozen hoek uit de regelaar + */ + public void setRichting(int ri) { + if (ri >= 0 && ri <= 90) { + double rad = (Math.PI / 2) * (((double) ri) / 90); + xspeed = Math.cos(rad) * 10; + yspeed = Math.sin(rad) * 10; + } // else do nothing + } + + /** + * Snelheid instellen: hogere snelheid realiseren door de tijd bij sleep(int + * t) te verlagen. Dit wordt bereikt door 1000/snelheid als slaaptijd te + * nemen. + * + * @param s + * De gekozen snelheid uit de regelaar + */ + public void setSnelheid(int s) { + if (s >= 1 && s <= 50) { + sleeptime = 1000 / s; // hogere snelheid: kortere slaaptijd! + } // else do nothing + } + + /** + * Teken een stap: verplaats het balletje en teken opnieuw + */ + public void paintStep() // Regelpaneel: knop 'Stap' + { + moveBol(); + repaint(); + } + + // ------- Painting and buffering -------------------- + + /** + * Teken het speelveld (wit vlak!) en het balletje + */ + public void paintComponent(Graphics g) { // verplicht, zorgt voor witte + // achtergrond + super.paintComponent(g); + // Bol bestaat uit in kleur verlopende concentrische cirkels (blauw -> + // rood) + int ixpos = (int) Math.round(xpos); + int iypos = (int) Math.round(ypos); + for (int k = 0; k <= BOLSIZE / 2; k++) { + g.setColor(new Color(COLORSTEP * k, 0, 255 - COLORSTEP * k)); + g.fillOval(ixpos + k, iypos + k, BOLSIZE - 2 * k, BOLSIZE - 2 * k); + } + } + + public void toggle(AnimatieRegelaar animatieRegelaar) + { + running = !running; + if (running) + { + tekenThread = new Thread( this ); + tekenThread.start(); + } + else { + tekenThread = null; + } + + if (animatieRegelaar != null) + animatieRegelaar.threadHasStopped(); + } + + @Override + public void run() { + while(running) + { + paintStep(); + try { + Thread.sleep(sleeptime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatieApplet.java b/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatieApplet.java old mode 100755 new mode 100644 index 6a81d1a..7849b08 --- a/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatieApplet.java +++ b/exercises/bolanimatie/src/main/java/bolanimatie/BolAnimatieApplet.java @@ -1,39 +1,39 @@ -package bolanimatie; - -/* - * Animatie met stuiterend balletje - * - * @author Paul Bergervoet - * - */ - -import java.awt.*; -import java.awt.event.*; -import java.applet.*; -import javax.swing.*; - -public class BolAnimatieApplet extends JApplet -{ // Componenten - BolAnimatie bolanim; - AnimatieRegelaar animreg; - - // initialize applet - public void init() - { - setSize(650, 400); - Container mypane = getContentPane(); - mypane.setLayout(null); - - bolanim = new BolAnimatie(); - bolanim.setLocation(25, 25); // grootte ster: 350x350 - mypane.add(bolanim); - - animreg = new AnimatieRegelaar(bolanim, new Color(255, 255, 204)); - animreg.setLocation(400, 0); // grootte regelaar: 250x400 - mypane.add(animreg); - - mypane.setBackground(new Color(255, 255, 51)); - setVisible(true); - } - -} +package bolanimatie; + +/* + * Animatie met stuiterend balletje + * + * @author Paul Bergervoet + * + */ + +import java.awt.*; +import java.awt.event.*; +import java.applet.*; +import javax.swing.*; + +public class BolAnimatieApplet extends JApplet +{ // Componenten + BolAnimatie bolanim; + AnimatieRegelaar animreg; + + // initialize applet + public void init() + { + setSize(650, 400); + Container mypane = getContentPane(); + mypane.setLayout(null); + + bolanim = new BolAnimatie(); + bolanim.setLocation(25, 25); // grootte ster: 350x350 + mypane.add(bolanim); + + animreg = new AnimatieRegelaar(bolanim, new Color(255, 255, 204)); + animreg.setLocation(400, 0); // grootte regelaar: 250x400 + mypane.add(animreg); + + mypane.setBackground(new Color(255, 255, 51)); + setVisible(true); + } + +} From 896d5a745f9ed78187496ea31abdad91921273d4 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 20:05:48 +0200 Subject: [PATCH 03/45] Uitwerking KleurenMenger --- .../java/kleurapplet/HSBInvoerPaneel.java | 64 ++++++++ .../src/main/java/kleurapplet/Kleur.java | 103 ++++++++++++ .../main/java/kleurapplet/KleurApplet.java | 39 +++++ .../main/java/kleurapplet/KleurCanvas.java | 151 ++++++++++++++++++ .../java/kleurapplet/RGBInvoerPaneel.java | 64 ++++++++ 5 files changed, 421 insertions(+) create mode 100644 exercises/kleurenmenger/src/main/java/kleurapplet/HSBInvoerPaneel.java create mode 100644 exercises/kleurenmenger/src/main/java/kleurapplet/Kleur.java create mode 100644 exercises/kleurenmenger/src/main/java/kleurapplet/KleurApplet.java create mode 100644 exercises/kleurenmenger/src/main/java/kleurapplet/KleurCanvas.java create mode 100644 exercises/kleurenmenger/src/main/java/kleurapplet/RGBInvoerPaneel.java diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/HSBInvoerPaneel.java b/exercises/kleurenmenger/src/main/java/kleurapplet/HSBInvoerPaneel.java new file mode 100644 index 0000000..000a519 --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/HSBInvoerPaneel.java @@ -0,0 +1,64 @@ +/* + * HSBInvoerPaneel.java 13 maart 2003, Paul Bergervoet + * + */ + +package kleurapplet; + +import kleurapplet.grnuminput.NumberListener; +import kleurapplet.grnuminput.NumberSlider; + +import java.awt.*; +import java.util.Observable; +import java.util.Observer; + +class HSBInvoerPaneel extends Panel implements Observer +{ // Variables + private NumberSlider hue; + private NumberSlider sat; + private NumberSlider bright; + + /** + * Was: KleurCanvas, maar alleen de interface is hier nodig. Bij de aanroep kan dus gerust Kleur meegegeven worden. + * @param numberListener + */ + public HSBInvoerPaneel(NumberListener numberListener) + { // NB: mwt klassieke awt, niet met behulp van Swing-componenten. + setBackground(new Color(204, 204, 204)); + GridLayout g = new GridLayout(3, 1); + g.setHgap(10); + setLayout(g); + + hue = new NumberSlider(0, 1, 0.5, 2, "Tint", ""); + hue.addNumberListener(numberListener); + add(hue); + + sat = new NumberSlider(0, 1, 0.5, 2, "Verzadiging", ""); + sat.addNumberListener(numberListener); + add(sat); + + bright = new NumberSlider(0, 1, 0.5, 2, "Helderheid", ""); + bright.addNumberListener(numberListener); + add(bright); + } + + /** + * Was eerst public + * @param h + * @param s + * @param b + */ + private void setSliders(float h, float s, float b) + { hue.setValue(h); + sat.setValue(s); + bright.setValue(b); + } + + @Override + public void update(Observable o, Object arg) { + if (arg instanceof Kleur.KleurUpdate) { + Kleur.KleurUpdate kleurUpdate = (Kleur.KleurUpdate) arg; + setSliders(kleurUpdate.hue, kleurUpdate.saturation, kleurUpdate.brightness); + } + } +} diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/Kleur.java b/exercises/kleurenmenger/src/main/java/kleurapplet/Kleur.java new file mode 100644 index 0000000..1b88488 --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/Kleur.java @@ -0,0 +1,103 @@ +package kleurapplet; + +import kleurapplet.grnuminput.NumberListener; + +import java.awt.*; +import java.util.Observable; + +public class Kleur extends Observable implements NumberListener { + private int roodval; + private int groenval; + private int blauwval; + private float[] hsbvalues; + + public Kleur() { + this.roodval = 127; + this.groenval = 127; + this.blauwval = 127; + } + + public void numberChanged(String naam, double v) { + if (naam.equals("Rood")) { + roodval = (int) v; // harde cast!! v loopt van 0 tot 255 met 0 decimalen! + adjustHSBValues(); + } else if (naam.equals("Groen")) { + groenval = (int) v; + adjustHSBValues(); + } else if (naam.equals("Blauw")) { + blauwval = (int) v; + adjustHSBValues(); + } else if (naam.equals("Tint")) { + hsbvalues[0] = (float) v; // harde cast!! v loopt van 0 tot 1 met 3 decimalen! + adjustRGBValues(); + } else if (naam.equals("Verzadiging")) { + hsbvalues[1] = (float) v; + adjustRGBValues(); + } else // must be "Helderheid" + { + hsbvalues[2] = (float) v; + adjustRGBValues(); + } + + setChanged(); + notifyObservers(dataObject()); + } + + public KleurUpdate dataObject() { + adjustHSBValues(); + return new KleurUpdate(roodval, groenval, blauwval, hsbvalues[0], hsbvalues[1], hsbvalues[2]); + } + + /** + * Met deze extra class geven we alleen de essentiele data weg aan de observers en + * houden we bij ons wat van ons is, zoals de numberChanged en de conversie RGB->HSB. + * + * Hiermee verlagen we de koppeling, maar ook helaas de cohesie. + * Alternatief is het Kleur object aan alle Observers mee te geven, dit is een een hogere koppeling maar ook hogere cohesie. + */ + class KleurUpdate { + public int rood; + public int groen; + public int blauw; + public float hue; + public float saturation; + public float brightness; + + /** + * Alleen Kleur en KleurUpdate mogen deze constructor aanroepen. + * @param rood + * @param groen + * @param blauw + * @param hue + * @param saturation + * @param brightness + */ + private KleurUpdate(int rood, int groen, int blauw, float hue, float saturation, float brightness) + { + this.rood = rood; + this.groen = groen; + this.blauw = blauw; + this.hue = hue; + this.saturation = saturation; + this.brightness = brightness; + } + } + + /** + * Bij verandering van RGB moet HSB worden aangepast + */ + private void adjustHSBValues() { + hsbvalues = Color.RGBtoHSB(roodval, groenval, blauwval, hsbvalues); + } + + /** + * Bij verandering van HSB moet RGB worden aangepast + */ + private void adjustRGBValues() { + Color c = Color.getHSBColor(hsbvalues[0], hsbvalues[1], hsbvalues[2]); + roodval = c.getRed(); + groenval = c.getGreen(); + blauwval = c.getBlue(); + } + +} diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/KleurApplet.java b/exercises/kleurenmenger/src/main/java/kleurapplet/KleurApplet.java new file mode 100644 index 0000000..0b14d7a --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/KleurApplet.java @@ -0,0 +1,39 @@ +/* + * KleurApplet.java 13 maart 2003, Paul Bergervoet + * + * Applet toont kleurenmenger + */ + +package kleurapplet; + +import java.awt.*; +import java.applet.*; + +public class KleurApplet extends Applet +{ KleurCanvas kc; + RGBInvoerPaneel rgbip; + HSBInvoerPaneel hsbip; + + public void init() + { + setLayout(new BorderLayout()); + Kleur kleur = new Kleur(); + kc = new KleurCanvas(kleur.dataObject()); + add(kc, "Center"); + rgbip = new RGBInvoerPaneel(kleur); + add(rgbip, "East"); + hsbip = new HSBInvoerPaneel(kleur); + add(hsbip, "West"); + setSize(600,340); + setVisible(true); + + kleur.addObserver(kc); + kleur.addObserver(rgbip); + kleur.addObserver(hsbip); + } +} + + + + + diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/KleurCanvas.java b/exercises/kleurenmenger/src/main/java/kleurapplet/KleurCanvas.java new file mode 100644 index 0000000..bce6cb1 --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/KleurCanvas.java @@ -0,0 +1,151 @@ +/* + * KleurCanvas.java 13 maart 2003, Paul Bergervoet + * + */ + +package kleurapplet; + +import java.awt.*; +import java.util.Observable; +import java.util.Observer; + +import kleurapplet.Kleur.KleurUpdate; + +class KleurCanvas extends Canvas implements Observer +{ // Variables for double buffering + Dimension dd; + private Image bufferTekening; // Image tbv offline painting + private Graphics bufferGraphics; // Graphics object van bufferTekening + private Dimension bufferGrootte = new Dimension(0, 0); + // Size of Image, check with Frame size + private KleurUpdate kleur; + + // Constants + private static Color echtRood = new Color(255, 0, 0); + private static Color echtGroen = new Color(0, 255, 0); + private static Color echtBlauw = new Color(0, 0, 255); + private static Font displayfont = new Font("SansSerif", Font.PLAIN, 12); + + // Panels + RGBInvoerPaneel rgbip; + HSBInvoerPaneel hsbip; + + /** + * Alleen voor initiele vulling van het canvas. + * De update-methode zorgt telkens voor een nieuwe instantie van kleurUpdate. + * + * @param kleurUpdate + */ + public KleurCanvas(KleurUpdate kleurUpdate) + { + this.kleur = kleurUpdate; + setBackground(Color.white); + setSize(360, 340); + } + +/** + * Vertaalt een RGB-component in een tweecijferige hexamdecimale waarde. + */ + public String hexValue(int c) + { String h = Integer.toHexString(c); + if ( h.length() == 1 ) // add zero voor eencijferige string + { h = "0".concat(h); + } + return h; + } + +/** + * Tekent naam van de kleurcomponent plus vlakje gekleurd in die component. + * bij RGB zetten we klein blokje in volle kleur voor de naam (argument fc) + * Bij HSB niet, dan is dat arg null. + * + * @param naam Naam van de Kleurcomponent (Tint, Verzadiging, .., Rood ...) + * @param c De te tekenen Kleurcomponent + * @param fc Kleur van het blokje met volle kleur R, G of B. ja/nee + * @param x De x-positie + * @param y De y-positie + * @param g De Graphics-context + */ + private void paintKleurComponent(String naam, Color c, Color fc, int x, int y, Graphics g) + { int schuifx = 0; + if ( fc != null ) // blokje echt rood/groen/blauw + { g.setColor(fc); + g.fillRect(x, y+5, 10, 10); + schuifx = 15; // naam zometeen 15 pixels naar rechts + } + g.setColor(c); + g.fillRoundRect(x, y+20, 60, 40, 5, 5); + g.setColor(Color.black); + g.drawString(naam, x+schuifx, y+15); + g.drawRoundRect(x, y+20, 60, 40, 5, 5); + } + + public void paint(Graphics g) + { g.setFont(displayfont); + Color c; + // --- tint ---- + c = Color.getHSBColor(kleur.hue, 1, 1); // helderheid, verzadiging vol + paintKleurComponent("Tint", c, null, 30, 20, g); + // --- verzadiging ---- + c = Color.getHSBColor(kleur.hue, kleur.saturation, 1); // helderheid vol + paintKleurComponent("Verzadiging", c, null, 30, 100, g); + // --- helderheid ---- + c = Color.getHSBColor(kleur.hue, 0, kleur.brightness); // verzadiging 0: grijs dus + paintKleurComponent("Helderheid", c, null, 30, 180, g); + + // --- rood ---- + c = new Color(kleur.rood, 0, 0); + paintKleurComponent("Rood", c, echtRood, 270, 20, g); + // --- groen ---- + c = new Color(0, kleur.groen, 0); + paintKleurComponent("Groen", c, echtGroen, 270, 100, g); + // --- blauw ---- + c = new Color(0, 0, kleur.blauw); + paintKleurComponent("Blauw", c, echtBlauw, 270, 180, g); + + // --- menging ---- + g.setColor(new Color(kleur.rood, kleur.groen, kleur.blauw)); + g.fillRoundRect(120, 40, 120, 280, 5, 5); + g.setColor(Color.black); + g.drawString("De kleur", 120, 35); + g.drawRoundRect(120, 40, 120, 280, 5, 5); + + // --- hexadecimaal RGB --- + g.setColor(Color.black); + g.drawString("Hex. RGB:", 270, 300); + String hrgb = "#"; + hrgb = hrgb.concat(hexValue(kleur.rood)); + hrgb = hrgb.concat(hexValue(kleur.groen)); + hrgb = hrgb.concat(hexValue(kleur.blauw)); + g.drawString(hrgb, 270, 315); + } + +// Event handler + + +// ----- tbv double buffering + public void update(Graphics g) + { dd = getSize(); // check eventuele resize... + if ( bufferTekening == null || // Image is er nog niet of .. + bufferGrootte.width != dd.width || // breedte/lengte van Canvas + bufferGrootte.height != dd.height // veranderd: dan nieuwe! + ) + { bufferTekening = createImage(dd.width, dd.height); + bufferGrootte = dd; + bufferGraphics = bufferTekening.getGraphics(); + } + // Teken het nieuwe plaatje... + bufferGraphics.setColor(Color.white); // background vullen + bufferGraphics.fillRect(0, 0, bufferGrootte.width, bufferGrootte.height); + paint(bufferGraphics); // laat paint in Image werken! + g.drawImage(bufferTekening, 0, 0, null); // zet Image op Canvas.... + } + + @Override + public void update(Observable o, Object arg) { + if (arg instanceof KleurUpdate) { + this.kleur = (KleurUpdate) arg; + repaint(); + } + } +} diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/RGBInvoerPaneel.java b/exercises/kleurenmenger/src/main/java/kleurapplet/RGBInvoerPaneel.java new file mode 100644 index 0000000..cc29f8f --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/RGBInvoerPaneel.java @@ -0,0 +1,64 @@ +/* + * RGBInvoerPaneel.java 13 maart 2003, Paul Bergervoet + * + */ + +package kleurapplet; + +import java.awt.*; +import java.awt.event.*; +import java.util.Observable; +import java.util.Observer; + +import kleurapplet.grnuminput.*; + +class RGBInvoerPaneel extends Panel implements Observer +{ // Variables + private NumberSlider rood; + private NumberSlider groen; + private NumberSlider blauw; + + /** + * Was: KleurCanvas, maar alleen de interface is hier nodig. Bij de aanroep kan dus gerust Kleur meegegeven worden. + * @param numberListener + */ + public RGBInvoerPaneel(NumberListener numberListener) + { // NB: mwt klassieke awt, niet met behulp van Swing-componenten. + setBackground(new Color(204, 204, 204)); + GridLayout g = new GridLayout(3, 1); + g.setHgap(10); + setLayout(g); + + rood = new NumberSlider(0, 255, 127, 0, "Rood", ""); + rood.addNumberListener(numberListener); + add(rood); + + groen = new NumberSlider(0, 255, 127, 0, "Groen", ""); + groen.addNumberListener(numberListener); + add(groen); + + blauw = new NumberSlider(0, 255, 127, 0, "Blauw", ""); + blauw.addNumberListener(numberListener); + add(blauw); + } + + /** + * Was eerst public + * @param r + * @param g + * @param b + */ + private void setSliders(int r, int g, int b) + { rood.setValue(r); + groen.setValue(g); + blauw.setValue(b); + } + + @Override + public void update(Observable o, Object arg) { + if (arg instanceof Kleur.KleurUpdate) { + Kleur.KleurUpdate kleurUpdate = (Kleur.KleurUpdate) arg; + setSliders(kleurUpdate.rood, kleurUpdate.groen, kleurUpdate.blauw); + } + } +} From 4f92ff89053441547e44d17e5f926de312d1f795 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 20:06:17 +0200 Subject: [PATCH 04/45] Uitwerking KleurenMenger --- .../src/main/java/HSBInvoerPaneel.java | 43 -- .../kleurapplet/src/main/java/KleurApplet.jar | Bin 41348 -> 0 bytes .../src/main/java/KleurApplet.java | 34 -- .../src/main/java/KleurCanvas.java | 181 ------ .../src/main/java/RGBInvoerPaneel.java | 43 -- .../kleurapplet/src/main/java/example1.html | 10 - .../main/java/grnuminput/NumOnlyField.java | 167 ------ .../src/main/java/grnuminput/NumberArrow.java | 566 ------------------ .../main/java/grnuminput/NumberListener.java | 23 - .../main/java/grnuminput/NumberSlider.java | 476 --------------- 10 files changed, 1543 deletions(-) delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/HSBInvoerPaneel.java delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/KleurApplet.jar delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/KleurApplet.java delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/KleurCanvas.java delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/RGBInvoerPaneel.java delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/example1.html delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumOnlyField.java delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberArrow.java delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberListener.java delete mode 100755 exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberSlider.java diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/HSBInvoerPaneel.java b/exercises/kleurenmenger/kleurapplet/src/main/java/HSBInvoerPaneel.java deleted file mode 100755 index cf338e4..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/HSBInvoerPaneel.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * HSBInvoerPaneel.java 13 maart 2003, Paul Bergervoet - * - */ - -package kleurapplet; - -import java.awt.*; -import java.awt.event.*; -import kleurapplet.grnuminput.*; - -class HSBInvoerPaneel extends Panel -{ // Variables - private NumberSlider hue; - private NumberSlider sat; - private NumberSlider bright; - - public HSBInvoerPaneel(KleurCanvas k) - { // NB: mwt klassieke awt, niet met behulp van Swing-componenten. - setBackground(new Color(204, 204, 204)); - GridLayout g = new GridLayout(3, 1); - g.setHgap(10); - setLayout(g); - - hue = new NumberSlider(0, 1, 0.5, 2, "Tint", ""); - hue.addNumberListener(k); - add(hue); - - sat = new NumberSlider(0, 1, 0.5, 2, "Verzadiging", ""); - sat.addNumberListener(k); - add(sat); - - bright = new NumberSlider(0, 1, 0.5, 2, "Helderheid", ""); - bright.addNumberListener(k); - add(bright); - } - - public void setSliders(float h, float s, float b) - { hue.setValue(h); - sat.setValue(s); - bright.setValue(b); - } -} diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/KleurApplet.jar b/exercises/kleurenmenger/kleurapplet/src/main/java/KleurApplet.jar deleted file mode 100755 index 76857e0d1485313ffc4b7870374c834269224396..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41348 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 diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/KleurApplet.java b/exercises/kleurenmenger/kleurapplet/src/main/java/KleurApplet.java deleted file mode 100755 index b1fa1a9..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/KleurApplet.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * KleurApplet.java 13 maart 2003, Paul Bergervoet - * - * Applet toont kleurenmenger - */ - -package kleurapplet; - -import java.awt.*; -import java.applet.*; - -public class KleurApplet extends Applet -{ KleurCanvas kc; - RGBInvoerPaneel rgbip; - HSBInvoerPaneel hsbip; - - public void init() - { // NB: mwt klassieke awt, niet met behulp van Swing-componenten. - setLayout(new BorderLayout()); - kc = new KleurCanvas(); - add(kc, "Center"); - rgbip = new RGBInvoerPaneel(kc); - add(rgbip, "East"); - hsbip = new HSBInvoerPaneel(kc); - add(hsbip, "West"); - setSize(600,340); - setVisible(true); - } -} - - - - - diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/KleurCanvas.java b/exercises/kleurenmenger/kleurapplet/src/main/java/KleurCanvas.java deleted file mode 100755 index 50a0045..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/KleurCanvas.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * KleurCanvas.java 13 maart 2003, Paul Bergervoet - * - */ - -package kleurapplet; - -import java.awt.*; -import kleurapplet.grnuminput.*; - -class KleurCanvas extends Canvas - implements NumberListener -{ // Variables for double buffering - Dimension dd; - private Image bufferTekening; // Image tbv offline painting - private Graphics bufferGraphics; // Graphics object van bufferTekening - private Dimension bufferGrootte = new Dimension(0, 0); - // Size of Image, check with Frame size - // Variables - private int roodval; - private int groenval; - private int blauwval; - private float[] hsbvalues; - - // Constants - private static Color echtRood = new Color(255, 0, 0); - private static Color echtGroen = new Color(0, 255, 0); - private static Color echtBlauw = new Color(0, 0, 255); - private static Font displayfont = new Font("SansSerif", Font.PLAIN, 12); - - // Panels - RGBInvoerPaneel rgbip; - HSBInvoerPaneel hsbip; - - public KleurCanvas() - { roodval = 127; - groenval = 127; - blauwval = 127; - hsbvalues = Color.RGBtoHSB(roodval, groenval, blauwval, hsbvalues); - setBackground(Color.white); - setSize(360, 340); - } - -/** - * Vertaalt een RGB-component in een tweecijferige hexamdecimale waarde. - */ - public String hexValue(int c) - { String h = Integer.toHexString(c); - if ( h.length() == 1 ) // add zero voor eencijferige string - { h = "0".concat(h); - } - return h; - } - -/** - * Tekent naam van de kleurcomponent plus vlakje gekleurd in die component. - * bij RGB zetten we klein blokje in volle kleur voor de naam (argument fc) - * Bij HSB niet, dan is dat arg null. - * - * @param naam Naam van de Kleurcomponent (Tint, Verzadiging, .., Rood ...) - * @param c De te tekenen Kleurcomponent - * @param fc Kleur van het blokje met volle kleur R, G of B. ja/nee - * @param x De x-positie - * @param y De y-positie - * @param g De Graphics-context - */ - private void paintKleurComponent(String naam, Color c, Color fc, int x, int y, Graphics g) - { int schuifx = 0; - if ( fc != null ) // blokje echt rood/groen/blauw - { g.setColor(fc); - g.fillRect(x, y+5, 10, 10); - schuifx = 15; // naam zometeen 15 pixels naar rechts - } - g.setColor(c); - g.fillRoundRect(x, y+20, 60, 40, 5, 5); - g.setColor(Color.black); - g.drawString(naam, x+schuifx, y+15); - g.drawRoundRect(x, y+20, 60, 40, 5, 5); - } - - public void paint(Graphics g) - { g.setFont(displayfont); - Color c; - // --- tint ---- - c = Color.getHSBColor(hsbvalues[0], 1, 1); // helderheid, verzadiging vol - paintKleurComponent("Tint", c, null, 30, 20, g); - // --- verzadiging ---- - c = Color.getHSBColor(hsbvalues[0], hsbvalues[1], 1); // helderheid vol - paintKleurComponent("Verzadiging", c, null, 30, 100, g); - // --- helderheid ---- - c = Color.getHSBColor(hsbvalues[0], 0, hsbvalues[2]); // verzadiging 0: grijs dus - paintKleurComponent("Helderheid", c, null, 30, 180, g); - - // --- rood ---- - c = new Color(roodval, 0, 0); - paintKleurComponent("Rood", c, echtRood, 270, 20, g); - // --- groen ---- - c = new Color(0, groenval, 0); - paintKleurComponent("Groen", c, echtGroen, 270, 100, g); - // --- blauw ---- - c = new Color(0, 0, blauwval); - paintKleurComponent("Blauw", c, echtBlauw, 270, 180, g); - - // --- menging ---- - g.setColor(new Color(roodval, groenval, blauwval)); - g.fillRoundRect(120, 40, 120, 280, 5, 5); - g.setColor(Color.black); - g.drawString("De kleur", 120, 35); - g.drawRoundRect(120, 40, 120, 280, 5, 5); - - // --- hexadecimaal RGB --- - g.setColor(Color.black); - g.drawString("Hex. RGB:", 270, 300); - String hrgb = "#"; - hrgb = hrgb.concat(hexValue(roodval)); - hrgb = hrgb.concat(hexValue(groenval)); - hrgb = hrgb.concat(hexValue(blauwval)); - g.drawString(hrgb, 270, 315); - } - -// Event handler - -/** - * Bij verandering van RGB moet HSB worden aangepast - */ - private void adjustHSBValues() - { hsbvalues = Color.RGBtoHSB(roodval, groenval, blauwval, hsbvalues); - } - -/** - * Bij verandering van HSB moet RGB worden aangepast - */ - private void adjustRGBValues() - { Color c = Color.getHSBColor(hsbvalues[0], hsbvalues[1], hsbvalues[2]); - roodval = c.getRed(); - groenval = c.getGreen(); - blauwval = c.getBlue(); - } - - public void numberChanged(String naam, double v) - { if ( naam.equals("Rood") ) - { roodval = (int)v; // harde cast!! v loopt van 0 tot 255 met 0 decimalen! - adjustHSBValues(); - } else if ( naam.equals("Groen") ) - { groenval = (int)v; - adjustHSBValues(); - } else if ( naam.equals("Blauw") ) - { blauwval = (int)v; - adjustHSBValues(); - } else if ( naam.equals("Tint") ) - { hsbvalues[0] = (float)v; // harde cast!! v loopt van 0 tot 1 met 3 decimalen! - adjustRGBValues(); - } else if ( naam.equals("Verzadiging") ) - { hsbvalues[1] = (float)v; - adjustRGBValues(); - } else // must be "Helderheid" - { hsbvalues[2] = (float)v; - adjustRGBValues(); - } - repaint(); - } - -// ----- tbv double buffering - public void update(Graphics g) - { dd = getSize(); // check eventuele resize... - if ( bufferTekening == null || // Image is er nog niet of .. - bufferGrootte.width != dd.width || // breedte/lengte van Canvas - bufferGrootte.height != dd.height // veranderd: dan nieuwe! - ) - { bufferTekening = createImage(dd.width, dd.height); - bufferGrootte = dd; - bufferGraphics = bufferTekening.getGraphics(); - } - // Teken het nieuwe plaatje... - bufferGraphics.setColor(Color.white); // background vullen - bufferGraphics.fillRect(0, 0, bufferGrootte.width, bufferGrootte.height); - paint(bufferGraphics); // laat paint in Image werken! - g.drawImage(bufferTekening, 0, 0, null); // zet Image op Canvas.... - } - -} diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/RGBInvoerPaneel.java b/exercises/kleurenmenger/kleurapplet/src/main/java/RGBInvoerPaneel.java deleted file mode 100755 index 4c4df52..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/RGBInvoerPaneel.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * RGBInvoerPaneel.java 13 maart 2003, Paul Bergervoet - * - */ - -package kleurapplet; - -import java.awt.*; -import java.awt.event.*; -import kleurapplet.grnuminput.*; - -class RGBInvoerPaneel extends Panel -{ // Variables - private NumberSlider rood; - private NumberSlider groen; - private NumberSlider blauw; - - public RGBInvoerPaneel(KleurCanvas k) - { // NB: mwt klassieke awt, niet met behulp van Swing-componenten. - setBackground(new Color(204, 204, 204)); - GridLayout g = new GridLayout(3, 1); - g.setHgap(10); - setLayout(g); - - rood = new NumberSlider(0, 255, 127, 0, "Rood", ""); - rood.addNumberListener(k); - add(rood); - - groen = new NumberSlider(0, 255, 127, 0, "Groen", ""); - groen.addNumberListener(k); - add(groen); - - blauw = new NumberSlider(0, 255, 127, 0, "Blauw", ""); - blauw.addNumberListener(k); - add(blauw); - } - - public void setSliders(int r, int g, int b) - { rood.setValue(r); - groen.setValue(g); - blauw.setValue(b); - } -} diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/example1.html b/exercises/kleurenmenger/kleurapplet/src/main/java/example1.html deleted file mode 100755 index c9b4d94..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/example1.html +++ /dev/null @@ -1,10 +0,0 @@ - - -Simple Applet Example - - - -Your browser does not support Java, so nothing is displayed. - - - diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumOnlyField.java b/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumOnlyField.java deleted file mode 100755 index 1ba47f3..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumOnlyField.java +++ /dev/null @@ -1,167 +0,0 @@ -package kleurapplet.grnuminput; - -import java.awt.*; -import java.awt.event.*; -import java.text.DecimalFormat; -import java.util.Vector; - -/** - * Class NumOnlyField assist the main components of the grnuminput package. - * It provides a TextField with number checking features. It tells its users of changes - * using the NumberListener interface. - */ - - -class NumOnlyField extends TextField - implements KeyListener, FocusListener -{ private double waarde; - private double initw; // initial value - private double minw; - private double maxw; - private int decimals; // number of decimals - private long truncator; // intermediate when fixing decimals - private double fact; // = Math.pow(10,decimals) - private DecimalFormat df; - - private boolean enabled = true; - private static Color enabledValueColor = Color.black; - private static Color disabledValueColor = Color.gray; - - private Vector listeners; // too much, there will be only one - - public NumOnlyField(double mn, double mx, double val, int dec) - { super(); - addKeyListener(this); - addFocusListener(this); - listeners = new Vector(); - - setBackground(Color.white); - setForeground(enabledValueColor); - - waarde = val; - initw = val; - minw = mn; - maxw = mx; - decimals = dec; - fact = Math.pow(10,decimals); - String dfstring; // create template-string for number formatting - if ( dec == 0 ) - { dfstring = "0"; - } else - { dfstring = "0."; - for ( int i=0; i maxw ) - { waarde = maxw; - } else if (newval < minw ) - { waarde = minw; - } else - { waarde = setDecimals(newval); // truncate - } - setText( df.format(waarde) ); - } - - public double getValue() - { return waarde; - } - - // private help methods: convert string to number, - // truncate number to required number of decimals - - private double setDecimals(double val) // returns val, truncated to - { truncator = Math.round( val*fact ); // required number of decimals - return ((double)truncator) / fact; - } - - private void processTextChange(String s) - { try // no need to test 'enabled', user can't type then - { Number f = df.parse( s.trim() ); - double w = f.doubleValue(); - if ( w < minw ) - { throw new NumberFormatException("getal te klein"); - } - if ( w > maxw ) - { throw new NumberFormatException("getal te groot"); - } - w = setDecimals(w); - if ( w != waarde ) // only when value changed! - { waarde = w; - setText( df.format(waarde) ); - tellListeners(); - } - } - catch (Exception exc) - { setText( df.format(waarde) ); - // just reset previous input - } - } - - public void checkValue() - { processTextChange( getText() ); - } - - // Listeners, KeyListener (check out adapters later, compiler freeze on first try!!! - - public void keyReleased(KeyEvent e) - { if ( e.getKeyCode() == KeyEvent.VK_ENTER ) // Is it 'virtual key' Enter? - { processTextChange( getText() ); - } - } - - public void keyTyped(KeyEvent e) - { // don't react - } - - public void keyPressed(KeyEvent e) - { // don't react - } - - // Listeners, FocusListener - public void focusLost(FocusEvent e) - { if ( !e.isTemporary() ) - { processTextChange( getText() ); - } - } - - public void focusGained(FocusEvent e) - { // don't react - } - - -} - - - - diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberArrow.java b/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberArrow.java deleted file mode 100755 index b1dfb73..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberArrow.java +++ /dev/null @@ -1,566 +0,0 @@ -package kleurapplet.grnuminput; - -import java.awt.*; -import java.awt.event.*; -import java.text.DecimalFormat; -import java.util.Vector; - -/** - * class ArrowCanvas - * Helper class for NumberArrow, displays picture of arrows and handles events. - */ - -class ArrowCanvas extends Canvas - { private Color disabledArrowColor = Color.gray; - private Color enabledArrowColor = Color.red; - private Color activeArrowColor = Color.green; - private Dimension dd; - - private Polygon up; - private boolean upActive = false; - private Polygon down; - private boolean downActive = false; - private boolean enabled = true; - - /** - * Constructor for ArrowCanvas - * Creates Canvas with arrows drawn on it. - */ - public ArrowCanvas() // initial position - { dd = new Dimension(19, 23); // fixed size.... ok? - setSize(dd); - // triangles for up and down arrows - up = new Polygon(); - up.addPoint(10, 2); - up.addPoint(3, 10); - up.addPoint(17, 10); - down = new Polygon(); - down.addPoint(3, 13); - down.addPoint(17, 13); - down.addPoint(10, 21); - } - -// painting the arrows - - private void paintPolygon(Graphics g, Polygon p, boolean active) - { if ( enabled ) - { if ( active ) - { g.setColor(activeArrowColor); - } else - { g.setColor(enabledArrowColor); - } - } else - { g.setColor(disabledArrowColor); - } - g.drawPolygon(p); // draw and fill, will they look the same - g.fillPolygon(p); // using fill only, the up-arrow will be smaller! - } - - public void paint(Graphics g) - { g.setColor(Color.black); - g.drawRect(0, 0, dd.width-1, dd.height-1); - g.setColor(Color.white); - g.fillRect(1, 1, dd.width-2, dd.height-2); // background - paintPolygon(g, up, upActive); - paintPolygon(g, down, downActive); - } - -// Set and get by NumberArrow - - protected int getArrow(int clicky) // threshold down arrow - { int dir = 0; // no direction (yet) - if ( clicky > 12 ) - { downActive = true; - dir = -1; - repaint(); - } else if ( clicky < 11 ) - { upActive = true; - dir = 1; - repaint(); - } - return dir; - } - - protected void setInactive() - { upActive = false; - downActive = false; - repaint(); - } - -/** - * Enable or disable the NumberArrow depending on the value of b. - * An enabled NumberArrow can respond to user input and generates events. - * NumberArrows are enabled initially by default. - * - * @param b If true this NumberArrow is enabled, otherwise the arrow is disabled. - * - */ - public void setEnabled(boolean b) - { enabled = b; - } - - protected void setDisabledArrowColor(Color c) - { disabledArrowColor = c; // call to repaint() in NumberArrow - } - - protected void setEnabledArrowColor(Color c) - { enabledArrowColor = c; - } - - protected void setActiveArrowColor(Color c) - { activeArrowColor = c; - } - - } // class ArrowCanvas - -/** - * class ArrowRunner - * Helper class for NumberArrow, it will time how long arrow is being 'mouseheld' - * and generates 'kicks' for NumberArrow - */ - class ArrowRunner extends Thread - { private NumberArrow owner; - private boolean running = true; - - public ArrowRunner(NumberArrow o) - { owner = o; - setDaemon(true); - } - - public void run() - { int teller = 0; // count how many times the thread 'kicks' - try - { sleep(500); - } catch ( InterruptedException e ) { } - while (running) // will be stopped by release of mouse! - { teller++; // increase count (first kick will be 1) - owner.kick(teller); // pass on count (so NumberArrow can increase steps - try // while 'mouse hold' lasts - { sleep(250); - } catch ( InterruptedException e ) { } - } - } - - public void neatstop() - { running = false; - } - } - -/** - * - * NumberArrow is a component for input of numbers. It consists of a - * TextField for keyboards entry of numbers plus up and down arrows - * to increase/decrease the number value in the TextField. - *
- * Values are doubles, precision can be indicated by specifying the number of decimals. - * The step size on arrowclick can be specified. - *
- * When an arrow is being held, the steps will increase to give an accelaration in the - * change of value. This accelaration can be limited by setting 'MaxFactor' of steps. - * The meaning of the number must be specified by 'parameter name' also on display. - * Also, a units label can be given. - *
- * Display: - *

- * | Parameter name | - * | × Value Units | - * - *

- * Value is Textfield holding value, × is picture with up- and down-arrow. - * - * Use is like standard AWT-components: - *
- * - Listener must implement interface NumberListener - *
- * - Listeners register with 'addNumberListener' - *
- * - void numberChanged(String, double) will be called by NumberArrow - * (String == parameter name, double holds new value - * - * @author Paul Bergervoet - * @version 3.1 5 maart 1999 - * @since JDK 1.1 - * - * @see NumberListener - */ - -public class NumberArrow extends Panel - implements NumberListener, MouseListener - { private double waarde; // current value - private double initw; // initial value - private double minw; // smallest value - private double maxw; // biggest value - private double stap; // size of step +/- at arrowclick - private String grootheid; // name of parameter - private String eenheid; // unit name - - private int decimals; // number of decimals - private long truncator; // intermediate when fixing decimals - private double fact; // = Math.pow(10,decimals) - - private NumOnlyField wtekst; - private ArrowCanvas warrow; - private ArrowRunner arwr; - private int dir; // 1 = up, -1 = down - private int maxStepFactor; - - private Label lgh; - private Label leh; - private boolean enabled = true; - private Vector listeners; - -/** - * Constructor for NumberArrow. - * Creates a NumberArrow with the two arrows left of the textfield. - * - * @param mn minimum value of the numberarrow - * @param mx maximum value of the numberarrow - * @param w initial value - * @param s step of the number arrow (change of value at arrow click) - * @param dec number of decimals (precision) of value - * @param gh parameter name - * @param eh parameter unit - */ - public NumberArrow( double mn, double mx, // min, max - double w, // value == initial value - double s, // step+/- - int dec, // number of decimals - String gh, String eh // parameter name and unit - ) - { minw = mn; - maxw = mx; - waarde = w; - initw = w; - stap = s; - maxStepFactor = 1; // default, see second constructor - decimals = dec; - grootheid = gh; - eenheid = eh; - fact = Math.pow(10,decimals); - listeners = new Vector(); - - // set up lay out - GridBagLayout gridbag = new GridBagLayout(); // set up data-area - GridBagConstraints c = new GridBagConstraints(); - setLayout(gridbag); - - // component, Label: parameter name - c.gridwidth = GridBagConstraints.REMAINDER; // line holding Name - c.anchor = GridBagConstraints.WEST; // left - lgh = new Label(grootheid); - gridbag.setConstraints(lgh, c); - add(lgh); - - // components: Arrows, NumOnlyField and Units - c.gridwidth = 1; - c.insets = new Insets(5, 0, 0, 0); // space above TextField - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.NONE; - warrow = new ArrowCanvas(); - warrow.addMouseListener(this); - gridbag.setConstraints(warrow, c); - add(warrow); - wtekst = new NumOnlyField( minw, maxw, waarde, dec); // no width! (columns) - wtekst.setEnabled(true); // also sets color.... - wtekst.addNumberListener(this); // NumberArrow listen to NumOnlyField! - gridbag.setConstraints(wtekst, c); - add(wtekst); - c.anchor = GridBagConstraints.WEST; // put left - c.fill = GridBagConstraints.HORIZONTAL; - leh = new Label(eenheid); - gridbag.setConstraints(leh, c); - add(leh); - } - - /** - * Add a listener to the numberarrow. - * - * @param l NumberListener to be added. - */ - public void addNumberListener(NumberListener l) - { listeners.addElement(l); - } - - private void tellListeners() - { for ( int i=0; i maxw ) - { waarde = maxw; - } else if (newval < minw ) - { waarde = minw; - } else - { waarde = setDecimals(newval); // truncate - } - wtekst.setValue( waarde ); - } - -/** - * SetValue with int value. - * - * @param newval The new int value to be displayed. - * - * @see NumberArrow#setValue(double newval) - */ - public void setValue(int newval) // int-waarde zetten - { setValue((double)newval); // - } - - /** - * Resets the value of the NumberArrow to the initial value. - * Note: Does not tell listeners!!!! - * - */ - public void setInitValue() - { setValue(initw); - } - - /** - * The value of the NumberArrow is returned as double. - * - * @return value of NumberArrow. - */ - public double getValue() - { return waarde; - } - - /** - * Force NumberArrow to check whether the value has changed. - * - * NumberArrow will check the number value of the textfield. If the value is different - * from the current value, the Listeners will be informed in the normal way, using numberChanged. - *
- * Note: useful when you don't want to force the user to press ENTER after typing a new value. - * When the user moves to another textfield after typing something, this is noticed through focusLost(). - * However, when the user moves the mouse and clicks a button, no loss of keyboard focus occurs. - * In this case you may want to check if the value has changed explicitly. - */ - public void checkValue() - { wtekst.checkValue(); - } - -// overriding default settings - -/** - * Sets the number of colums of the textfield of the NumberArrow. - *
- * Note: by default the width of the TextField will be calculated from the min and max values: - * number of digits needed + 1. - * - * @param n New number of colums of the textfield. - */ - public void setColumns(int n) - { wtekst.setColumns(n); - } - -/** - * Sets the maximum multiplication factor of the step size to a new value. - *
- * When the arrow button is pushed in for a longer period the step size - * is multiplied by an increasing factor: 2, 3, 4 etc.. - * Therefore the number change increases when you hold the number. - * MaxFactor limits the increase. - *
- * Default value is 1, meaning constant step size. - * - * @param m New factor value. - */ - public void setMaxFactor(int m) - { maxStepFactor = m; - } - -/** - * Set the color the arrows must have when the NumberArrow is disabled. - * - * @param c The preferred color. - * - */ - public void setDisabledArrowColor(Color c) - { warrow.setDisabledArrowColor( c); - repaint(); - } - -/** - * Set the color the arrows must have when the NumberArrow is enabled, but not touched by the mouse. - * - * @param c The preferred color. - */ - public void setEnabledArrowColor(Color c) - { warrow.setEnabledArrowColor( c); - repaint(); - } - -/** - * Set the color of an active arrow, that is: someone is pressing the mouse on the arrow. - * - * @param c The preferred color. - */ - public void setActiveArrowColor(Color c) - { warrow.setActiveArrowColor( c); - repaint(); - } - -/** - * Set the font of the labels: parameter name and units. - * - * @param f The preferred font. - */ - public void setLabelFont(Font f) - { lgh.setFont( f); - leh.setFont( f); - repaint(); - } - -/** - * Set the font of the value in the TextField. - * - * @param f The preferred font. - */ - public void setValueFont(Font f) - { wtekst.setFont( f); - repaint(); - } - -/** - * Set the foregroundcolor of the labels: parameter name and units. - * - * @param c The preferred color. - */ - public void setLabelForeground( Color c ) - { lgh.setForeground( c ) ; - leh.setForeground( c ) ; - repaint(); - } - -/** - * Set the color of the value in the TextField - * - * @param c The preferred color. - */ - public void setValueColor( Color c ) - { wtekst.setForeground( c ) ; - repaint(); - } - -// Event handling - // 1. MouseListener - - private void stopThread() - { if ( arwr !=null ) - { arwr.neatstop(); - warrow.setInactive(); - arwr = null; - } - } - -/** - * Invoked by timer when mouse is held on an arrow. - * - * @param count Counter of kicks, for accelaration. - */ - protected void kick(int count) // mouse held - { setValue(waarde + dir*Math.min(count, maxStepFactor)*stap); // 1 or -1 times count times stap - tellListeners(); // count at most 5 - } - -/** - * Invoked when mouse button is pressed on the NumberArrow. - * Does step and starts ArrowRunner. - */ - public void mousePressed(MouseEvent e) - { dir = warrow.getArrow( e.getY() ); // get height of click to decide up or down - if ( enabled && dir!=0 ) - { stopThread(); // make sure! - setValue(waarde + dir*stap); // 1 or -1 times stap - tellListeners(); - arwr = new ArrowRunner(this); // will kick as long as mouse is held - arwr.start(); - } - // System.out.println("pressed, new value is "+waarde ); - } - - /** - * Invoked when mouse button is released over the NumberArrow. - * stops ArrowRunner. - */ - public void mouseReleased(MouseEvent e) - { stopThread(); - } - - /** - * Invoked when mouse button is clicked on the NumberArrow. - * Does nothing. - */ - public void mouseClicked(MouseEvent e) - { // do nothing - } - - /** - * Invoked when mouse has entered the NumberArrow. - * Does nothing. - */ - public void mouseEntered(MouseEvent e) - { // do nothing - } - - /** - * Invoked when mouse has exited the NumberArrow. - * stops ArrowRunner. - */ - public void mouseExited(MouseEvent e) - { stopThread(); - } - - // 2. NumberListener: react to change in NumOnlyField - -/** - * Invoked when the number in the textfield has changed. - * - * @param s Dummy string: name of the NumOnlyTextField. - * @param w Double value of the textfield. - */ - public void numberChanged(String s, double w) // dummy String from NumOnlyField - { waarde = w; - // no need to do anything with arrows - tellListeners(); - } -} - diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberListener.java b/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberListener.java deleted file mode 100755 index 32baa00..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package kleurapplet.grnuminput; - -/** - * Listener interface for objects who listen to NumberSlider and/or NumberArrow components. - * - * @author Paul Bergervoet - * @version 3.1 22 februari 1999 - * @since JDK 1.1 - */ - -public interface NumberListener -{ -/** - * Invoked when a number value has been changed. - * The component passes on the new value and also the 'parameter name', so that Listeners - * who listen to several components using a single 'numberChanged' method can - * distinguish between them. - * - * @param name The name of the numinput component. - * @param val The new value. - */ - public void numberChanged(String name, double val); -} diff --git a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberSlider.java b/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberSlider.java deleted file mode 100755 index 96836ea..0000000 --- a/exercises/kleurenmenger/kleurapplet/src/main/java/grnuminput/NumberSlider.java +++ /dev/null @@ -1,476 +0,0 @@ -package kleurapplet.grnuminput; - -import java.awt.*; -import java.awt.event.*; -import java.util.Vector; - -/** - * class Slider: draws bar & slider - */ - -class Slider extends Canvas - { double huidigePos; // position, value from 0 to 1 - private Color enabledSliderColor = Color.red; - private Color disabledSliderColor = Color.gray; - Color sliderColor = enabledSliderColor; - Dimension dd; - - public Slider(double initp) // initial position - { setSize(100,20); // for now fixed size (not needed for functionality) - dd = getSize(); - huidigePos = initp; - } - - public void paint(Graphics g) - { dd = getSize(); - g.drawRect(1, 7, dd.width-2, 6); // bar - g.setColor(sliderColor); - g.fillOval((int)Math.round( huidigePos*(dd.width-7) ), 1, 7, 20); - // -7 because of width oval (=7) - } - - protected double getPos( int mousepos ) // working width of bar for scaling MouseEvents - { return ((double)(mousepos-3)) / (dd.width-7); - } - - protected void setSlide(double p) // set position to p, 0<=p<=1 - { huidigePos = p; - repaint(); - } - - public void setEnabled(boolean ena) - { if ( ena ) // Color only, NumberSlider handles events - { sliderColor = enabledSliderColor; - } else - { sliderColor = disabledSliderColor; - } - repaint(); // eigenlijk onnodig - } - - protected void setDisabledSliderColor(Color c) - { disabledSliderColor = c; // call to repaint() in NumberSlider - } - - protected void setEnabledSliderColor(Color c) - { enabledSliderColor = c; - } - - } - -/** - * NumberSlider is a component for input of numbers. It consists of a - * TextField for keyboards entry of numbers plus a 'slider' that can be dragged - * across a bar representing the possible range of values. - *
- * Values are doubles, precision can be indicated by specifying the number of decimals. - * The meaning of the number must be specified by 'parameter name' also on display. - * Also, a units label can be given. - *
- * Display: - *

- * | Parameter name | - * | min max | - * | --- Slider --------- | - * | Value Units | - * - *

- * Use is like standard AWT-components: - *
- * - Listener must implement interface NumberListener - *
- * - Listeners register with 'addNumberListener' - *
- * - void numberChanged(String, double) will be called by NumberSlider - * (String == parameter name, double holds new value - * - * @author Paul Bergervoet, additions bij Joost Rommes - * @version 3.2 18 februari 2000 - * @since JDK 1.1 - * - * @see NumberListener - */ - -public class NumberSlider extends Panel - implements NumberListener, MouseListener, MouseMotionListener - { private double waarde; // current value - private double initw; // initial value - private double minw; // smallest value - private double maxw; // biggest value - private String grootheid; // name of parameter - private String eenheid; // unit name - - private int decimals; // number of decimals - private long truncator; // intermediate when fixing decimals - private double fact; // = Math.pow(10,decimals) - - private NumOnlyField wtekst; - private Slider wschuif; - private Label lgh; - private Label leh; - private Label lmin; - private Label lmax; - - private boolean enabled = true; - private Vector listeners; - -/** - * Constructor for NumberSlider. - * - * @param mn minimum value of the NumberSlider - * @param mx maximum value of the NumberSlider - * @param w initial value - * @param dec number of decimals (precision) of value - * @param gh parameter name - * @param eh parameter unit - */ - public NumberSlider( double mn, double mx, // min, max - double w, // value == initial value - int dec, // number of decimals - String gh, String eh // parameter name and unit - ) - { minw = mn; - maxw = mx; - waarde = w; - initw = w; - decimals = dec; - grootheid = gh; - eenheid = eh; - fact = Math.pow(10,decimals); - listeners = new Vector(); - - // set up lay out - GridBagLayout gridbag = new GridBagLayout(); // set up data-area - GridBagConstraints c = new GridBagConstraints(); - setLayout(gridbag); - - // component, Label: parameter name - c.gridwidth = GridBagConstraints.REMAINDER; // line holding Name - c.anchor = GridBagConstraints.WEST; // left - lgh = new Label(grootheid); - gridbag.setConstraints(lgh, c); - add(lgh); - - // components, Labels: min and max value, show rounded values, min and max should be ints - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; // left - lmin = new Label( String.valueOf((int)Math.round(minw)) ); - gridbag.setConstraints(lmin, c); - add(lmin); - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.EAST; // right - lmax = new Label( String.valueOf((int)Math.round(maxw)) ); - gridbag.setConstraints(lmax, c); - add(lmax); - - // component slide bar - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.HORIZONTAL; - wschuif = new Slider( valToPos(waarde) ); - wschuif.addMouseListener(this); - wschuif.addMouseMotionListener(this); - gridbag.setConstraints(wschuif, c); - add(wschuif); - - // components: NumOnlyField and Units - c.gridwidth = 1 ; - c.insets = new Insets(5, 0, 0, 0); // space above TextField - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.NONE; - wtekst = new NumOnlyField( minw, maxw, waarde, dec); // no width! (columns) - wtekst.setEnabled(true); // also sets color.... - wtekst.addNumberListener(this); // NumberSlider listen to NumOnlyField! - gridbag.setConstraints(wtekst, c); - add(wtekst); - c.anchor = GridBagConstraints.WEST; // put left - leh = new Label(eenheid); - gridbag.setConstraints(leh, c); - add(leh); - } - - /** - * Add a listener to the NumberSlider. - * - * @param l NumberListener to be added. - */ - public void addNumberListener(NumberListener l) - { listeners.addElement(l); - } - - private void tellListeners() - { for ( int i=0; i 1 ) { relpos = 1; } - waarde = setDecimals( minw + relpos*(maxw-minw) ); - wschuif.setSlide( valToPos(waarde) ); - wtekst.setValue( waarde ); - tellListeners(); - } - -// Public methods: Enable/disable, setValue, getValue - -/** - * Enables or disables the NumberSlider. When disabled it becomes disabledSliderColor. - * - * @param b True to enable the textfield, False to disable it. - */ - public void setEnabled(boolean b) - { enabled = b; - wtekst.setEnabled(b); - wschuif.setEnabled(b); - repaint(); - } - -/** - * Find out if the NumberSlider is enabled. - * - * @return boolean indicating if the component is enabled. - */ - public boolean isEnabled() - { return enabled; - } - -/** - * Sets the value to be displayed in the number textfield & slider. - *
- * Note: Does not tell listeners!!!! - * - * @param newval The new double value to be displayed. - */ - public void setValue(double newval) - { if ( newval > maxw ) - { waarde = maxw; - } else if (newval < minw ) - { waarde = minw; - } else - { waarde = setDecimals(newval); // truncate - } - wtekst.setValue( waarde ); - wschuif.setSlide( valToPos(waarde) ); - } - -/** - * SetValue with int value. - * - * @param newval The new int value to be displayed. - * - * @see NumberSlider#setValue(double newval) - */ - public void setValue(int newval) - { setValue((double)newval); - } - -/** - * Resets the value of the NumberSlider to the initial value. - *
- * Note: Does not tell listeners!!!! - * - */ - public void setInitValue() - { setValue(initw); - } - - /** - * The value of the NumberSlider is returned as double. - * - * @return value of NumberSlider. - */ - public double getValue() - { return waarde; - } - - /** - * Force NumberSlider to check whether the value has changed. - * - * NumberSlider will check the number value of the textfield. If the value is different - * from the current value, the Listeners will be informed in the normal way, using numberChanged. - *
- * Note: useful when you don't want to force the user to press ENTER after typing a new value. - * When the user moves to another textfield after typing something, this is noticed through focusLost(). - * However, when the user moves the mouse and clicks a button, no loss of keyboard focus occurs. - * In this case you may want to check if the value has changed explicitly. - */ - public void checkValue() - { wtekst.checkValue(); - } - -// overriding default settings - -/** - * Sets the number of colums of the textfield of the NumberSlider. - *
- * Note: by default the width of the TextField will be calculated from the min and max values: - * number of digits needed + 1. - * - * @param n New number of colums of the textfield. - */ - public void setColumns(int n) - { wtekst.setColumns(n); - } - -/** - * Set the color the handle must have when the NumberSlider is disabled. - * - * @param c The preferred color. - */ - public void setDisabledSliderColor(Color c) - { wschuif.setDisabledSliderColor( c); - repaint(); - } - -/** - * Set the color the handle must have when the NumberSlider is enabled. - * - * @param c The preferred color. - */ - public void setEnabledSliderColor(Color c) - { wschuif.setEnabledSliderColor( c); - repaint(); - } - -/** - * Set the font of the labels: parameter name, min, max and units. - * - * @param f The preferred font. - */ - public void setLabelFont(Font f) - { lgh.setFont( f); - leh.setFont( f); - lmin.setFont( f); - lmax.setFont( f); - repaint(); - } - -/** - * Set the font of the value in the TextField - * - * @param f The preferred font. - */ - public void setValueFont(Font f) - { wtekst.setFont( f); - repaint(); - } - -/** - * Set the foregroundcolor of the labels: parameter name, min, max and units. - * - * @param c The preferred color. - */ - public void setLabelForeground( Color c ) - { - lgh.setForeground( c ) ; - leh.setForeground( c ) ; - lmin.setForeground( c ) ; - lmax.setForeground( c ) ; - repaint(); - } - -/** - * Set the color of the value in the TextField - * - * @param c The preferred color. - */ - public void setValueColor( Color c ) - { - wtekst.setForeground( c ) ; - repaint(); - } - -// Event handling - // 1. MouseListener - -/** - * Invoked when mouse button is pressed on the NumberSlider. - * Move slide to click location. - */ - public void mousePressed(MouseEvent e) - { processSliderChange( e.getX() ); - // System.out.println("pressed, new value is "+waarde ); - } - - /** - * Invoked when mouse button is released over the NumberSlider. - * Does nothing. - */ - public void mouseReleased(MouseEvent e) - { // do nothing - } - - /** - * Invoked when mouse button is clicked on the NumberSlider. - * Does nothing. - */ - public void mouseClicked(MouseEvent e) - { // do nothing - } - - /** - * Invoked when mouse has entered the NumberSlider. - * Does nothing. - */ - public void mouseEntered(MouseEvent e) - { // do nothing - } - - /** - * Invoked when mouse has exited the NumberSlider. - * Does nothing. - */ - public void mouseExited(MouseEvent e) - { // do nothing - } - - // 2. MouseMotionListener - - /** - * Invoked when mouse is dragged the NumberSlider. - * Move slide to drag location. - */ - public void mouseDragged(MouseEvent e) - { processSliderChange( e.getX() ); - // System.out.println("dragged, new value is "+waarde ); - } - - /** - * Invoked when mouse is moved the NumberSlider. - * Does nothing. - */ - public void mouseMoved(MouseEvent e) - { // do nothing - } - -// 3. NumberListener: react to change in NumOnlyField - -/** - * Invoked when the number in the textfield has changed. - * - * @param s Dummy string: name of the NumOnlyTextField. - * @param w Double value of the textfield. - */ - public void numberChanged(String s, double w) // String s doesn't matter, it's the NumOnlyField - { waarde = w; - wschuif.setSlide( valToPos(waarde) ); - tellListeners(); - } -} From b8e77ecd7cde4cf4500dce97a81cc274f14c7a1f Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 20:08:04 +0200 Subject: [PATCH 05/45] Uitwerking KleurenMenger --- .../kleurapplet/grnuminput/NumOnlyField.java | 167 ++++++ .../kleurapplet/grnuminput/NumberArrow.java | 566 ++++++++++++++++++ .../grnuminput/NumberListener.java | 23 + .../kleurapplet/grnuminput/NumberSlider.java | 476 +++++++++++++++ 4 files changed, 1232 insertions(+) create mode 100755 exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumOnlyField.java create mode 100755 exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberArrow.java create mode 100755 exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberListener.java create mode 100755 exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberSlider.java diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumOnlyField.java b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumOnlyField.java new file mode 100755 index 0000000..1ba47f3 --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumOnlyField.java @@ -0,0 +1,167 @@ +package kleurapplet.grnuminput; + +import java.awt.*; +import java.awt.event.*; +import java.text.DecimalFormat; +import java.util.Vector; + +/** + * Class NumOnlyField assist the main components of the grnuminput package. + * It provides a TextField with number checking features. It tells its users of changes + * using the NumberListener interface. + */ + + +class NumOnlyField extends TextField + implements KeyListener, FocusListener +{ private double waarde; + private double initw; // initial value + private double minw; + private double maxw; + private int decimals; // number of decimals + private long truncator; // intermediate when fixing decimals + private double fact; // = Math.pow(10,decimals) + private DecimalFormat df; + + private boolean enabled = true; + private static Color enabledValueColor = Color.black; + private static Color disabledValueColor = Color.gray; + + private Vector listeners; // too much, there will be only one + + public NumOnlyField(double mn, double mx, double val, int dec) + { super(); + addKeyListener(this); + addFocusListener(this); + listeners = new Vector(); + + setBackground(Color.white); + setForeground(enabledValueColor); + + waarde = val; + initw = val; + minw = mn; + maxw = mx; + decimals = dec; + fact = Math.pow(10,decimals); + String dfstring; // create template-string for number formatting + if ( dec == 0 ) + { dfstring = "0"; + } else + { dfstring = "0."; + for ( int i=0; i maxw ) + { waarde = maxw; + } else if (newval < minw ) + { waarde = minw; + } else + { waarde = setDecimals(newval); // truncate + } + setText( df.format(waarde) ); + } + + public double getValue() + { return waarde; + } + + // private help methods: convert string to number, + // truncate number to required number of decimals + + private double setDecimals(double val) // returns val, truncated to + { truncator = Math.round( val*fact ); // required number of decimals + return ((double)truncator) / fact; + } + + private void processTextChange(String s) + { try // no need to test 'enabled', user can't type then + { Number f = df.parse( s.trim() ); + double w = f.doubleValue(); + if ( w < minw ) + { throw new NumberFormatException("getal te klein"); + } + if ( w > maxw ) + { throw new NumberFormatException("getal te groot"); + } + w = setDecimals(w); + if ( w != waarde ) // only when value changed! + { waarde = w; + setText( df.format(waarde) ); + tellListeners(); + } + } + catch (Exception exc) + { setText( df.format(waarde) ); + // just reset previous input + } + } + + public void checkValue() + { processTextChange( getText() ); + } + + // Listeners, KeyListener (check out adapters later, compiler freeze on first try!!! + + public void keyReleased(KeyEvent e) + { if ( e.getKeyCode() == KeyEvent.VK_ENTER ) // Is it 'virtual key' Enter? + { processTextChange( getText() ); + } + } + + public void keyTyped(KeyEvent e) + { // don't react + } + + public void keyPressed(KeyEvent e) + { // don't react + } + + // Listeners, FocusListener + public void focusLost(FocusEvent e) + { if ( !e.isTemporary() ) + { processTextChange( getText() ); + } + } + + public void focusGained(FocusEvent e) + { // don't react + } + + +} + + + + diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberArrow.java b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberArrow.java new file mode 100755 index 0000000..b1dfb73 --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberArrow.java @@ -0,0 +1,566 @@ +package kleurapplet.grnuminput; + +import java.awt.*; +import java.awt.event.*; +import java.text.DecimalFormat; +import java.util.Vector; + +/** + * class ArrowCanvas + * Helper class for NumberArrow, displays picture of arrows and handles events. + */ + +class ArrowCanvas extends Canvas + { private Color disabledArrowColor = Color.gray; + private Color enabledArrowColor = Color.red; + private Color activeArrowColor = Color.green; + private Dimension dd; + + private Polygon up; + private boolean upActive = false; + private Polygon down; + private boolean downActive = false; + private boolean enabled = true; + + /** + * Constructor for ArrowCanvas + * Creates Canvas with arrows drawn on it. + */ + public ArrowCanvas() // initial position + { dd = new Dimension(19, 23); // fixed size.... ok? + setSize(dd); + // triangles for up and down arrows + up = new Polygon(); + up.addPoint(10, 2); + up.addPoint(3, 10); + up.addPoint(17, 10); + down = new Polygon(); + down.addPoint(3, 13); + down.addPoint(17, 13); + down.addPoint(10, 21); + } + +// painting the arrows + + private void paintPolygon(Graphics g, Polygon p, boolean active) + { if ( enabled ) + { if ( active ) + { g.setColor(activeArrowColor); + } else + { g.setColor(enabledArrowColor); + } + } else + { g.setColor(disabledArrowColor); + } + g.drawPolygon(p); // draw and fill, will they look the same + g.fillPolygon(p); // using fill only, the up-arrow will be smaller! + } + + public void paint(Graphics g) + { g.setColor(Color.black); + g.drawRect(0, 0, dd.width-1, dd.height-1); + g.setColor(Color.white); + g.fillRect(1, 1, dd.width-2, dd.height-2); // background + paintPolygon(g, up, upActive); + paintPolygon(g, down, downActive); + } + +// Set and get by NumberArrow + + protected int getArrow(int clicky) // threshold down arrow + { int dir = 0; // no direction (yet) + if ( clicky > 12 ) + { downActive = true; + dir = -1; + repaint(); + } else if ( clicky < 11 ) + { upActive = true; + dir = 1; + repaint(); + } + return dir; + } + + protected void setInactive() + { upActive = false; + downActive = false; + repaint(); + } + +/** + * Enable or disable the NumberArrow depending on the value of b. + * An enabled NumberArrow can respond to user input and generates events. + * NumberArrows are enabled initially by default. + * + * @param b If true this NumberArrow is enabled, otherwise the arrow is disabled. + * + */ + public void setEnabled(boolean b) + { enabled = b; + } + + protected void setDisabledArrowColor(Color c) + { disabledArrowColor = c; // call to repaint() in NumberArrow + } + + protected void setEnabledArrowColor(Color c) + { enabledArrowColor = c; + } + + protected void setActiveArrowColor(Color c) + { activeArrowColor = c; + } + + } // class ArrowCanvas + +/** + * class ArrowRunner + * Helper class for NumberArrow, it will time how long arrow is being 'mouseheld' + * and generates 'kicks' for NumberArrow + */ + class ArrowRunner extends Thread + { private NumberArrow owner; + private boolean running = true; + + public ArrowRunner(NumberArrow o) + { owner = o; + setDaemon(true); + } + + public void run() + { int teller = 0; // count how many times the thread 'kicks' + try + { sleep(500); + } catch ( InterruptedException e ) { } + while (running) // will be stopped by release of mouse! + { teller++; // increase count (first kick will be 1) + owner.kick(teller); // pass on count (so NumberArrow can increase steps + try // while 'mouse hold' lasts + { sleep(250); + } catch ( InterruptedException e ) { } + } + } + + public void neatstop() + { running = false; + } + } + +/** + * + * NumberArrow is a component for input of numbers. It consists of a + * TextField for keyboards entry of numbers plus up and down arrows + * to increase/decrease the number value in the TextField. + *
+ * Values are doubles, precision can be indicated by specifying the number of decimals. + * The step size on arrowclick can be specified. + *
+ * When an arrow is being held, the steps will increase to give an accelaration in the + * change of value. This accelaration can be limited by setting 'MaxFactor' of steps. + * The meaning of the number must be specified by 'parameter name' also on display. + * Also, a units label can be given. + *
+ * Display: + *

+ * | Parameter name | + * | × Value Units | + * + *

+ * Value is Textfield holding value, × is picture with up- and down-arrow. + * + * Use is like standard AWT-components: + *
+ * - Listener must implement interface NumberListener + *
+ * - Listeners register with 'addNumberListener' + *
+ * - void numberChanged(String, double) will be called by NumberArrow + * (String == parameter name, double holds new value + * + * @author Paul Bergervoet + * @version 3.1 5 maart 1999 + * @since JDK 1.1 + * + * @see NumberListener + */ + +public class NumberArrow extends Panel + implements NumberListener, MouseListener + { private double waarde; // current value + private double initw; // initial value + private double minw; // smallest value + private double maxw; // biggest value + private double stap; // size of step +/- at arrowclick + private String grootheid; // name of parameter + private String eenheid; // unit name + + private int decimals; // number of decimals + private long truncator; // intermediate when fixing decimals + private double fact; // = Math.pow(10,decimals) + + private NumOnlyField wtekst; + private ArrowCanvas warrow; + private ArrowRunner arwr; + private int dir; // 1 = up, -1 = down + private int maxStepFactor; + + private Label lgh; + private Label leh; + private boolean enabled = true; + private Vector listeners; + +/** + * Constructor for NumberArrow. + * Creates a NumberArrow with the two arrows left of the textfield. + * + * @param mn minimum value of the numberarrow + * @param mx maximum value of the numberarrow + * @param w initial value + * @param s step of the number arrow (change of value at arrow click) + * @param dec number of decimals (precision) of value + * @param gh parameter name + * @param eh parameter unit + */ + public NumberArrow( double mn, double mx, // min, max + double w, // value == initial value + double s, // step+/- + int dec, // number of decimals + String gh, String eh // parameter name and unit + ) + { minw = mn; + maxw = mx; + waarde = w; + initw = w; + stap = s; + maxStepFactor = 1; // default, see second constructor + decimals = dec; + grootheid = gh; + eenheid = eh; + fact = Math.pow(10,decimals); + listeners = new Vector(); + + // set up lay out + GridBagLayout gridbag = new GridBagLayout(); // set up data-area + GridBagConstraints c = new GridBagConstraints(); + setLayout(gridbag); + + // component, Label: parameter name + c.gridwidth = GridBagConstraints.REMAINDER; // line holding Name + c.anchor = GridBagConstraints.WEST; // left + lgh = new Label(grootheid); + gridbag.setConstraints(lgh, c); + add(lgh); + + // components: Arrows, NumOnlyField and Units + c.gridwidth = 1; + c.insets = new Insets(5, 0, 0, 0); // space above TextField + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.NONE; + warrow = new ArrowCanvas(); + warrow.addMouseListener(this); + gridbag.setConstraints(warrow, c); + add(warrow); + wtekst = new NumOnlyField( minw, maxw, waarde, dec); // no width! (columns) + wtekst.setEnabled(true); // also sets color.... + wtekst.addNumberListener(this); // NumberArrow listen to NumOnlyField! + gridbag.setConstraints(wtekst, c); + add(wtekst); + c.anchor = GridBagConstraints.WEST; // put left + c.fill = GridBagConstraints.HORIZONTAL; + leh = new Label(eenheid); + gridbag.setConstraints(leh, c); + add(leh); + } + + /** + * Add a listener to the numberarrow. + * + * @param l NumberListener to be added. + */ + public void addNumberListener(NumberListener l) + { listeners.addElement(l); + } + + private void tellListeners() + { for ( int i=0; i maxw ) + { waarde = maxw; + } else if (newval < minw ) + { waarde = minw; + } else + { waarde = setDecimals(newval); // truncate + } + wtekst.setValue( waarde ); + } + +/** + * SetValue with int value. + * + * @param newval The new int value to be displayed. + * + * @see NumberArrow#setValue(double newval) + */ + public void setValue(int newval) // int-waarde zetten + { setValue((double)newval); // + } + + /** + * Resets the value of the NumberArrow to the initial value. + * Note: Does not tell listeners!!!! + * + */ + public void setInitValue() + { setValue(initw); + } + + /** + * The value of the NumberArrow is returned as double. + * + * @return value of NumberArrow. + */ + public double getValue() + { return waarde; + } + + /** + * Force NumberArrow to check whether the value has changed. + * + * NumberArrow will check the number value of the textfield. If the value is different + * from the current value, the Listeners will be informed in the normal way, using numberChanged. + *
+ * Note: useful when you don't want to force the user to press ENTER after typing a new value. + * When the user moves to another textfield after typing something, this is noticed through focusLost(). + * However, when the user moves the mouse and clicks a button, no loss of keyboard focus occurs. + * In this case you may want to check if the value has changed explicitly. + */ + public void checkValue() + { wtekst.checkValue(); + } + +// overriding default settings + +/** + * Sets the number of colums of the textfield of the NumberArrow. + *
+ * Note: by default the width of the TextField will be calculated from the min and max values: + * number of digits needed + 1. + * + * @param n New number of colums of the textfield. + */ + public void setColumns(int n) + { wtekst.setColumns(n); + } + +/** + * Sets the maximum multiplication factor of the step size to a new value. + *
+ * When the arrow button is pushed in for a longer period the step size + * is multiplied by an increasing factor: 2, 3, 4 etc.. + * Therefore the number change increases when you hold the number. + * MaxFactor limits the increase. + *
+ * Default value is 1, meaning constant step size. + * + * @param m New factor value. + */ + public void setMaxFactor(int m) + { maxStepFactor = m; + } + +/** + * Set the color the arrows must have when the NumberArrow is disabled. + * + * @param c The preferred color. + * + */ + public void setDisabledArrowColor(Color c) + { warrow.setDisabledArrowColor( c); + repaint(); + } + +/** + * Set the color the arrows must have when the NumberArrow is enabled, but not touched by the mouse. + * + * @param c The preferred color. + */ + public void setEnabledArrowColor(Color c) + { warrow.setEnabledArrowColor( c); + repaint(); + } + +/** + * Set the color of an active arrow, that is: someone is pressing the mouse on the arrow. + * + * @param c The preferred color. + */ + public void setActiveArrowColor(Color c) + { warrow.setActiveArrowColor( c); + repaint(); + } + +/** + * Set the font of the labels: parameter name and units. + * + * @param f The preferred font. + */ + public void setLabelFont(Font f) + { lgh.setFont( f); + leh.setFont( f); + repaint(); + } + +/** + * Set the font of the value in the TextField. + * + * @param f The preferred font. + */ + public void setValueFont(Font f) + { wtekst.setFont( f); + repaint(); + } + +/** + * Set the foregroundcolor of the labels: parameter name and units. + * + * @param c The preferred color. + */ + public void setLabelForeground( Color c ) + { lgh.setForeground( c ) ; + leh.setForeground( c ) ; + repaint(); + } + +/** + * Set the color of the value in the TextField + * + * @param c The preferred color. + */ + public void setValueColor( Color c ) + { wtekst.setForeground( c ) ; + repaint(); + } + +// Event handling + // 1. MouseListener + + private void stopThread() + { if ( arwr !=null ) + { arwr.neatstop(); + warrow.setInactive(); + arwr = null; + } + } + +/** + * Invoked by timer when mouse is held on an arrow. + * + * @param count Counter of kicks, for accelaration. + */ + protected void kick(int count) // mouse held + { setValue(waarde + dir*Math.min(count, maxStepFactor)*stap); // 1 or -1 times count times stap + tellListeners(); // count at most 5 + } + +/** + * Invoked when mouse button is pressed on the NumberArrow. + * Does step and starts ArrowRunner. + */ + public void mousePressed(MouseEvent e) + { dir = warrow.getArrow( e.getY() ); // get height of click to decide up or down + if ( enabled && dir!=0 ) + { stopThread(); // make sure! + setValue(waarde + dir*stap); // 1 or -1 times stap + tellListeners(); + arwr = new ArrowRunner(this); // will kick as long as mouse is held + arwr.start(); + } + // System.out.println("pressed, new value is "+waarde ); + } + + /** + * Invoked when mouse button is released over the NumberArrow. + * stops ArrowRunner. + */ + public void mouseReleased(MouseEvent e) + { stopThread(); + } + + /** + * Invoked when mouse button is clicked on the NumberArrow. + * Does nothing. + */ + public void mouseClicked(MouseEvent e) + { // do nothing + } + + /** + * Invoked when mouse has entered the NumberArrow. + * Does nothing. + */ + public void mouseEntered(MouseEvent e) + { // do nothing + } + + /** + * Invoked when mouse has exited the NumberArrow. + * stops ArrowRunner. + */ + public void mouseExited(MouseEvent e) + { stopThread(); + } + + // 2. NumberListener: react to change in NumOnlyField + +/** + * Invoked when the number in the textfield has changed. + * + * @param s Dummy string: name of the NumOnlyTextField. + * @param w Double value of the textfield. + */ + public void numberChanged(String s, double w) // dummy String from NumOnlyField + { waarde = w; + // no need to do anything with arrows + tellListeners(); + } +} + diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberListener.java b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberListener.java new file mode 100755 index 0000000..32baa00 --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberListener.java @@ -0,0 +1,23 @@ +package kleurapplet.grnuminput; + +/** + * Listener interface for objects who listen to NumberSlider and/or NumberArrow components. + * + * @author Paul Bergervoet + * @version 3.1 22 februari 1999 + * @since JDK 1.1 + */ + +public interface NumberListener +{ +/** + * Invoked when a number value has been changed. + * The component passes on the new value and also the 'parameter name', so that Listeners + * who listen to several components using a single 'numberChanged' method can + * distinguish between them. + * + * @param name The name of the numinput component. + * @param val The new value. + */ + public void numberChanged(String name, double val); +} diff --git a/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberSlider.java b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberSlider.java new file mode 100755 index 0000000..96836ea --- /dev/null +++ b/exercises/kleurenmenger/src/main/java/kleurapplet/grnuminput/NumberSlider.java @@ -0,0 +1,476 @@ +package kleurapplet.grnuminput; + +import java.awt.*; +import java.awt.event.*; +import java.util.Vector; + +/** + * class Slider: draws bar & slider + */ + +class Slider extends Canvas + { double huidigePos; // position, value from 0 to 1 + private Color enabledSliderColor = Color.red; + private Color disabledSliderColor = Color.gray; + Color sliderColor = enabledSliderColor; + Dimension dd; + + public Slider(double initp) // initial position + { setSize(100,20); // for now fixed size (not needed for functionality) + dd = getSize(); + huidigePos = initp; + } + + public void paint(Graphics g) + { dd = getSize(); + g.drawRect(1, 7, dd.width-2, 6); // bar + g.setColor(sliderColor); + g.fillOval((int)Math.round( huidigePos*(dd.width-7) ), 1, 7, 20); + // -7 because of width oval (=7) + } + + protected double getPos( int mousepos ) // working width of bar for scaling MouseEvents + { return ((double)(mousepos-3)) / (dd.width-7); + } + + protected void setSlide(double p) // set position to p, 0<=p<=1 + { huidigePos = p; + repaint(); + } + + public void setEnabled(boolean ena) + { if ( ena ) // Color only, NumberSlider handles events + { sliderColor = enabledSliderColor; + } else + { sliderColor = disabledSliderColor; + } + repaint(); // eigenlijk onnodig + } + + protected void setDisabledSliderColor(Color c) + { disabledSliderColor = c; // call to repaint() in NumberSlider + } + + protected void setEnabledSliderColor(Color c) + { enabledSliderColor = c; + } + + } + +/** + * NumberSlider is a component for input of numbers. It consists of a + * TextField for keyboards entry of numbers plus a 'slider' that can be dragged + * across a bar representing the possible range of values. + *
+ * Values are doubles, precision can be indicated by specifying the number of decimals. + * The meaning of the number must be specified by 'parameter name' also on display. + * Also, a units label can be given. + *
+ * Display: + *

+ * | Parameter name | + * | min max | + * | --- Slider --------- | + * | Value Units | + * + *

+ * Use is like standard AWT-components: + *
+ * - Listener must implement interface NumberListener + *
+ * - Listeners register with 'addNumberListener' + *
+ * - void numberChanged(String, double) will be called by NumberSlider + * (String == parameter name, double holds new value + * + * @author Paul Bergervoet, additions bij Joost Rommes + * @version 3.2 18 februari 2000 + * @since JDK 1.1 + * + * @see NumberListener + */ + +public class NumberSlider extends Panel + implements NumberListener, MouseListener, MouseMotionListener + { private double waarde; // current value + private double initw; // initial value + private double minw; // smallest value + private double maxw; // biggest value + private String grootheid; // name of parameter + private String eenheid; // unit name + + private int decimals; // number of decimals + private long truncator; // intermediate when fixing decimals + private double fact; // = Math.pow(10,decimals) + + private NumOnlyField wtekst; + private Slider wschuif; + private Label lgh; + private Label leh; + private Label lmin; + private Label lmax; + + private boolean enabled = true; + private Vector listeners; + +/** + * Constructor for NumberSlider. + * + * @param mn minimum value of the NumberSlider + * @param mx maximum value of the NumberSlider + * @param w initial value + * @param dec number of decimals (precision) of value + * @param gh parameter name + * @param eh parameter unit + */ + public NumberSlider( double mn, double mx, // min, max + double w, // value == initial value + int dec, // number of decimals + String gh, String eh // parameter name and unit + ) + { minw = mn; + maxw = mx; + waarde = w; + initw = w; + decimals = dec; + grootheid = gh; + eenheid = eh; + fact = Math.pow(10,decimals); + listeners = new Vector(); + + // set up lay out + GridBagLayout gridbag = new GridBagLayout(); // set up data-area + GridBagConstraints c = new GridBagConstraints(); + setLayout(gridbag); + + // component, Label: parameter name + c.gridwidth = GridBagConstraints.REMAINDER; // line holding Name + c.anchor = GridBagConstraints.WEST; // left + lgh = new Label(grootheid); + gridbag.setConstraints(lgh, c); + add(lgh); + + // components, Labels: min and max value, show rounded values, min and max should be ints + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; // left + lmin = new Label( String.valueOf((int)Math.round(minw)) ); + gridbag.setConstraints(lmin, c); + add(lmin); + c.gridwidth = GridBagConstraints.REMAINDER; + c.anchor = GridBagConstraints.EAST; // right + lmax = new Label( String.valueOf((int)Math.round(maxw)) ); + gridbag.setConstraints(lmax, c); + add(lmax); + + // component slide bar + c.gridwidth = GridBagConstraints.REMAINDER; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.HORIZONTAL; + wschuif = new Slider( valToPos(waarde) ); + wschuif.addMouseListener(this); + wschuif.addMouseMotionListener(this); + gridbag.setConstraints(wschuif, c); + add(wschuif); + + // components: NumOnlyField and Units + c.gridwidth = 1 ; + c.insets = new Insets(5, 0, 0, 0); // space above TextField + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.NONE; + wtekst = new NumOnlyField( minw, maxw, waarde, dec); // no width! (columns) + wtekst.setEnabled(true); // also sets color.... + wtekst.addNumberListener(this); // NumberSlider listen to NumOnlyField! + gridbag.setConstraints(wtekst, c); + add(wtekst); + c.anchor = GridBagConstraints.WEST; // put left + leh = new Label(eenheid); + gridbag.setConstraints(leh, c); + add(leh); + } + + /** + * Add a listener to the NumberSlider. + * + * @param l NumberListener to be added. + */ + public void addNumberListener(NumberListener l) + { listeners.addElement(l); + } + + private void tellListeners() + { for ( int i=0; i 1 ) { relpos = 1; } + waarde = setDecimals( minw + relpos*(maxw-minw) ); + wschuif.setSlide( valToPos(waarde) ); + wtekst.setValue( waarde ); + tellListeners(); + } + +// Public methods: Enable/disable, setValue, getValue + +/** + * Enables or disables the NumberSlider. When disabled it becomes disabledSliderColor. + * + * @param b True to enable the textfield, False to disable it. + */ + public void setEnabled(boolean b) + { enabled = b; + wtekst.setEnabled(b); + wschuif.setEnabled(b); + repaint(); + } + +/** + * Find out if the NumberSlider is enabled. + * + * @return boolean indicating if the component is enabled. + */ + public boolean isEnabled() + { return enabled; + } + +/** + * Sets the value to be displayed in the number textfield & slider. + *
+ * Note: Does not tell listeners!!!! + * + * @param newval The new double value to be displayed. + */ + public void setValue(double newval) + { if ( newval > maxw ) + { waarde = maxw; + } else if (newval < minw ) + { waarde = minw; + } else + { waarde = setDecimals(newval); // truncate + } + wtekst.setValue( waarde ); + wschuif.setSlide( valToPos(waarde) ); + } + +/** + * SetValue with int value. + * + * @param newval The new int value to be displayed. + * + * @see NumberSlider#setValue(double newval) + */ + public void setValue(int newval) + { setValue((double)newval); + } + +/** + * Resets the value of the NumberSlider to the initial value. + *
+ * Note: Does not tell listeners!!!! + * + */ + public void setInitValue() + { setValue(initw); + } + + /** + * The value of the NumberSlider is returned as double. + * + * @return value of NumberSlider. + */ + public double getValue() + { return waarde; + } + + /** + * Force NumberSlider to check whether the value has changed. + * + * NumberSlider will check the number value of the textfield. If the value is different + * from the current value, the Listeners will be informed in the normal way, using numberChanged. + *
+ * Note: useful when you don't want to force the user to press ENTER after typing a new value. + * When the user moves to another textfield after typing something, this is noticed through focusLost(). + * However, when the user moves the mouse and clicks a button, no loss of keyboard focus occurs. + * In this case you may want to check if the value has changed explicitly. + */ + public void checkValue() + { wtekst.checkValue(); + } + +// overriding default settings + +/** + * Sets the number of colums of the textfield of the NumberSlider. + *
+ * Note: by default the width of the TextField will be calculated from the min and max values: + * number of digits needed + 1. + * + * @param n New number of colums of the textfield. + */ + public void setColumns(int n) + { wtekst.setColumns(n); + } + +/** + * Set the color the handle must have when the NumberSlider is disabled. + * + * @param c The preferred color. + */ + public void setDisabledSliderColor(Color c) + { wschuif.setDisabledSliderColor( c); + repaint(); + } + +/** + * Set the color the handle must have when the NumberSlider is enabled. + * + * @param c The preferred color. + */ + public void setEnabledSliderColor(Color c) + { wschuif.setEnabledSliderColor( c); + repaint(); + } + +/** + * Set the font of the labels: parameter name, min, max and units. + * + * @param f The preferred font. + */ + public void setLabelFont(Font f) + { lgh.setFont( f); + leh.setFont( f); + lmin.setFont( f); + lmax.setFont( f); + repaint(); + } + +/** + * Set the font of the value in the TextField + * + * @param f The preferred font. + */ + public void setValueFont(Font f) + { wtekst.setFont( f); + repaint(); + } + +/** + * Set the foregroundcolor of the labels: parameter name, min, max and units. + * + * @param c The preferred color. + */ + public void setLabelForeground( Color c ) + { + lgh.setForeground( c ) ; + leh.setForeground( c ) ; + lmin.setForeground( c ) ; + lmax.setForeground( c ) ; + repaint(); + } + +/** + * Set the color of the value in the TextField + * + * @param c The preferred color. + */ + public void setValueColor( Color c ) + { + wtekst.setForeground( c ) ; + repaint(); + } + +// Event handling + // 1. MouseListener + +/** + * Invoked when mouse button is pressed on the NumberSlider. + * Move slide to click location. + */ + public void mousePressed(MouseEvent e) + { processSliderChange( e.getX() ); + // System.out.println("pressed, new value is "+waarde ); + } + + /** + * Invoked when mouse button is released over the NumberSlider. + * Does nothing. + */ + public void mouseReleased(MouseEvent e) + { // do nothing + } + + /** + * Invoked when mouse button is clicked on the NumberSlider. + * Does nothing. + */ + public void mouseClicked(MouseEvent e) + { // do nothing + } + + /** + * Invoked when mouse has entered the NumberSlider. + * Does nothing. + */ + public void mouseEntered(MouseEvent e) + { // do nothing + } + + /** + * Invoked when mouse has exited the NumberSlider. + * Does nothing. + */ + public void mouseExited(MouseEvent e) + { // do nothing + } + + // 2. MouseMotionListener + + /** + * Invoked when mouse is dragged the NumberSlider. + * Move slide to drag location. + */ + public void mouseDragged(MouseEvent e) + { processSliderChange( e.getX() ); + // System.out.println("dragged, new value is "+waarde ); + } + + /** + * Invoked when mouse is moved the NumberSlider. + * Does nothing. + */ + public void mouseMoved(MouseEvent e) + { // do nothing + } + +// 3. NumberListener: react to change in NumOnlyField + +/** + * Invoked when the number in the textfield has changed. + * + * @param s Dummy string: name of the NumOnlyTextField. + * @param w Double value of the textfield. + */ + public void numberChanged(String s, double w) // String s doesn't matter, it's the NumOnlyField + { waarde = w; + wschuif.setSlide( valToPos(waarde) ); + tellListeners(); + } +} From f0df8b19eb5591a5890de20b67782c3ff1fc0192 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 20:09:27 +0200 Subject: [PATCH 06/45] Update README.md --- exercises/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exercises/README.md b/exercises/README.md index 06bc258..68e1883 100644 --- a/exercises/README.md +++ b/exercises/README.md @@ -4,3 +4,5 @@ This subdirectory contains the quickstart projects to do the exercises/workshops * Kleurenmenger (Observer) * Koenen/Kramers (Adapter, Factory, Singleton) * Reporting (SOLID) + +Checkout the branch "exercice-results" for the results of the first three workshops/exercises From 9ef680f6d2cb8e79e9825f28a14788da2881f5ef Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 20:09:43 +0200 Subject: [PATCH 07/45] Update README.md --- exercises/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/README.md b/exercises/README.md index 68e1883..7d6d90a 100644 --- a/exercises/README.md +++ b/exercises/README.md @@ -5,4 +5,4 @@ This subdirectory contains the quickstart projects to do the exercises/workshops * Koenen/Kramers (Adapter, Factory, Singleton) * Reporting (SOLID) -Checkout the branch "exercice-results" for the results of the first three workshops/exercises +Checkout the branch "exercise-results" for the results of the first three workshops/exercises From bf2ec844fcbdc065aab30e8ebc93a6085465c6c6 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Wed, 24 Sep 2014 20:10:32 +0200 Subject: [PATCH 08/45] Update README.md --- exercises/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/exercises/README.md b/exercises/README.md index 7d6d90a..6e85fc9 100644 --- a/exercises/README.md +++ b/exercises/README.md @@ -1,8 +1,6 @@ -This subdirectory contains the quickstart projects to do the exercises/workshops from the DEA course: +This subdirectory contains some results of the quickstart projects to do the exercises/workshops from the DEA course: * Bolanimatie (Threads) * VideoStore (Refactoring) * Kleurenmenger (Observer) * Koenen/Kramers (Adapter, Factory, Singleton) * Reporting (SOLID) - -Checkout the branch "exercise-results" for the results of the first three workshops/exercises From 3c0c9d04195a716a285b0152500ef1c76fa6a356 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Fri, 7 Nov 2014 13:43:59 +0100 Subject: [PATCH 09/45] Example Maven build file for .NET projects --- maven/dotnet-example/pom.xml | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 maven/dotnet-example/pom.xml diff --git a/maven/dotnet-example/pom.xml b/maven/dotnet-example/pom.xml new file mode 100644 index 0000000..45ec15e --- /dev/null +++ b/maven/dotnet-example/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + nl.yourcompanyname + yourappname + 1.0-SNAPSHOT + OOSE CompanyName AppName + netpack + + + nameofyoursolutionfile.sln + *.Tests + 4.0 + cs + C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319 + skip + C:/Program Files/Gallio + + + + + + org.codehaus.sonar-plugins.dotnet + maven-dotnet-plugin + 1.0 + true + + c:\Program Files\Gallio + + + + org.codehaus.mojo + sonar-maven-plugin + + cs + + + + + From 2cf6b72a1ed01d663249f16cfa948f2c04716ee5 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Thu, 12 Feb 2015 20:22:19 +0100 Subject: [PATCH 10/45] Uitwerking RMI terugteller workshop --- exercises/terugteller/pom.xml | 18 +++++++++ .../src/main/java/nl/ica/oose/ICallback.java | 8 ++++ .../main/java/nl/ica/oose/ITerugTeller.java | 14 +++++++ .../main/java/nl/ica/oose/TerugTeller.java | 38 +++++++++++++++++++ .../java/nl/ica/oose/TerugTellerClient.java | 33 ++++++++++++++++ .../java/nl/ica/oose/TerugTellerServer.java | 23 +++++++++++ .../java/nl/ica/oose/TerugTellerTest.java | 26 +++++++++++++ 7 files changed, 160 insertions(+) create mode 100644 exercises/terugteller/pom.xml create mode 100644 exercises/terugteller/src/main/java/nl/ica/oose/ICallback.java create mode 100644 exercises/terugteller/src/main/java/nl/ica/oose/ITerugTeller.java create mode 100644 exercises/terugteller/src/main/java/nl/ica/oose/TerugTeller.java create mode 100644 exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerClient.java create mode 100644 exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerServer.java create mode 100644 exercises/terugteller/src/test/java/nl/ica/oose/TerugTellerTest.java diff --git a/exercises/terugteller/pom.xml b/exercises/terugteller/pom.xml new file mode 100644 index 0000000..a9d06c3 --- /dev/null +++ b/exercises/terugteller/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + nl.oose.dea + TerugTeller + 1.0-SNAPSHOT + + + + junit + junit + 4.11 + + + \ No newline at end of file diff --git a/exercises/terugteller/src/main/java/nl/ica/oose/ICallback.java b/exercises/terugteller/src/main/java/nl/ica/oose/ICallback.java new file mode 100644 index 0000000..e8dda78 --- /dev/null +++ b/exercises/terugteller/src/main/java/nl/ica/oose/ICallback.java @@ -0,0 +1,8 @@ +package nl.ica.oose; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface ICallback extends Remote { + public void notifyChange(int value) throws RemoteException; +} diff --git a/exercises/terugteller/src/main/java/nl/ica/oose/ITerugTeller.java b/exercises/terugteller/src/main/java/nl/ica/oose/ITerugTeller.java new file mode 100644 index 0000000..4f92721 --- /dev/null +++ b/exercises/terugteller/src/main/java/nl/ica/oose/ITerugTeller.java @@ -0,0 +1,14 @@ +package nl.ica.oose; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface ITerugTeller extends Remote { + public void decrement() throws RemoteException; + + public int getValue() throws RemoteException; + + public void setValue(int value) throws RemoteException; + + public void addCallbackListener(ICallback iCallback) throws RemoteException; +} diff --git a/exercises/terugteller/src/main/java/nl/ica/oose/TerugTeller.java b/exercises/terugteller/src/main/java/nl/ica/oose/TerugTeller.java new file mode 100644 index 0000000..11d6f30 --- /dev/null +++ b/exercises/terugteller/src/main/java/nl/ica/oose/TerugTeller.java @@ -0,0 +1,38 @@ +package nl.ica.oose; + +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.ArrayList; +import java.util.List; + +public class TerugTeller extends UnicastRemoteObject implements ITerugTeller { + private int value; + private List callbacks = new ArrayList(); + + protected TerugTeller() throws RemoteException { + } + + public void decrement() throws RemoteException { + value -= 1; + if(value %25 ==0) + { + for(ICallback iCallback:callbacks) + { + iCallback.notifyChange(value); + } + } + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + @Override + public void addCallbackListener(ICallback iCallback) throws RemoteException { + callbacks.add(iCallback); + } +} diff --git a/exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerClient.java b/exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerClient.java new file mode 100644 index 0000000..1a88e5c --- /dev/null +++ b/exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerClient.java @@ -0,0 +1,33 @@ +package nl.ica.oose; + +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.server.UnicastRemoteObject; + +public class TerugTellerClient extends UnicastRemoteObject implements ICallback{ + protected TerugTellerClient() throws RemoteException { + } + + public static void main(String[] args) throws RemoteException, NotBoundException { + TerugTellerClient terugTellerClient = new TerugTellerClient(); + terugTellerClient.start(); + } + + private void start() throws RemoteException, NotBoundException { + ITerugTeller teller = + (ITerugTeller) LocateRegistry.getRegistry().lookup("terugteller"); + teller.addCallbackListener(this); + teller.setValue(200); + for (int i = 0; i < 100; i++) { + teller.decrement(); + } + System.out.println(teller.getValue()); + + } + + @Override + public void notifyChange(int value) throws RemoteException { + System.out.println("De volgende waarde is een veelvoud van 25: " + value); + } +} diff --git a/exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerServer.java b/exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerServer.java new file mode 100644 index 0000000..53a1eac --- /dev/null +++ b/exercises/terugteller/src/main/java/nl/ica/oose/TerugTellerServer.java @@ -0,0 +1,23 @@ +package nl.ica.oose; + +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; + +public class TerugTellerServer { + public static void main(String[] args) { + TerugTellerServer terugTellerServer = new TerugTellerServer(); + terugTellerServer.start(); + } + + private void start() { + ITerugTeller teller; + try { + teller = new TerugTeller(); + Registry r = LocateRegistry.createRegistry(1099); + r.bind("terugteller", teller); + } catch (Exception e) { + e.printStackTrace(); + } + + } +} diff --git a/exercises/terugteller/src/test/java/nl/ica/oose/TerugTellerTest.java b/exercises/terugteller/src/test/java/nl/ica/oose/TerugTellerTest.java new file mode 100644 index 0000000..b1588f5 --- /dev/null +++ b/exercises/terugteller/src/test/java/nl/ica/oose/TerugTellerTest.java @@ -0,0 +1,26 @@ +package nl.ica.oose; + +import org.junit.Test; + +import java.rmi.RemoteException; + +import static org.junit.Assert.*; + +public class TerugTellerTest implements ICallback { + + @Test + public void testDecrement() throws Exception { + TerugTeller terugTeller = new TerugTeller(); + terugTeller.addCallbackListener(this); + terugTeller.setValue(200); + for (int i = 0; i < 100; i++) { + terugTeller.decrement(); + } + assertEquals(100, terugTeller.getValue()); + } + + @Override + public void notifyChange(int value) throws RemoteException { + assertTrue(value % 25 == 0); + } +} \ No newline at end of file From a2e3248c00415ffa3d250c2de82a1ecd1f43ab5d Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Tue, 24 Feb 2015 23:05:49 +0100 Subject: [PATCH 11/45] Changed SOLID Examples --- exercises/solid/1-SOLID-SRP/.idea/.name | 1 - .../solid/1-SOLID-SRP/.idea/compiler.xml | 30 - .../.idea/copyright/profiles_settings.xml | 3 - .../solid/1-SOLID-SRP/.idea/encodings.xml | 8 - .../libraries/Maven__junit_junit_4_11.xml | 13 - .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 - exercises/solid/1-SOLID-SRP/.idea/misc.xml | 18 - exercises/solid/1-SOLID-SRP/.idea/modules.xml | 9 - .../.idea/scopes/scope_settings.xml | 5 - .../solid/1-SOLID-SRP/.idea/uiDesigner.xml | 125 -- exercises/solid/1-SOLID-SRP/.idea/vcs.xml | 7 - .../solid/1-SOLID-SRP/.idea/workspace.xml | 665 ---------- exercises/solid/1-SOLID-SRP/pom.xml | 24 - .../src/main/java/oose/dea/solid/Program.java | 16 - .../src/main/java/oose/dea/solid/Report.java | 26 - .../oose/dea/solid/ReportDataElement.java | 13 - exercises/solid/2-SOLID-OCP/.idea/.name | 1 - .../solid/2-SOLID-OCP/.idea/compiler.xml | 31 - .../.idea/copyright/profiles_settings.xml | 3 - .../solid/2-SOLID-OCP/.idea/encodings.xml | 8 - .../libraries/Maven__junit_junit_4_11.xml | 13 - .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 - exercises/solid/2-SOLID-OCP/.idea/misc.xml | 18 - exercises/solid/2-SOLID-OCP/.idea/modules.xml | 9 - .../.idea/scopes/scope_settings.xml | 5 - .../solid/2-SOLID-OCP/.idea/uiDesigner.xml | 125 -- exercises/solid/2-SOLID-OCP/.idea/vcs.xml | 7 - .../solid/2-SOLID-OCP/.idea/workspace.xml | 688 ----------- exercises/solid/2-SOLID-OCP/pom.xml | 24 - .../main/java/oose/dea/solid/DataAccess.java | 12 - .../src/main/java/oose/dea/solid/Program.java | 16 - .../src/main/java/oose/dea/solid/Report.java | 13 - .../oose/dea/solid/ReportDataElement.java | 13 - .../java/oose/dea/solid/ReportFormatter.java | 10 - .../java/oose/dea/solid/ReportPrinter.java | 15 - exercises/solid/3-SOLID-LSP/.idea/.name | 1 - .../solid/3-SOLID-LSP/.idea/compiler.xml | 31 - .../.idea/copyright/profiles_settings.xml | 3 - .../solid/3-SOLID-LSP/.idea/encodings.xml | 8 - .../libraries/Maven__junit_junit_4_11.xml | 13 - .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 - exercises/solid/3-SOLID-LSP/.idea/misc.xml | 18 - exercises/solid/3-SOLID-LSP/.idea/modules.xml | 9 - .../.idea/scopes/scope_settings.xml | 5 - .../solid/3-SOLID-LSP/.idea/uiDesigner.xml | 125 -- exercises/solid/3-SOLID-LSP/.idea/vcs.xml | 7 - .../solid/3-SOLID-LSP/.idea/workspace.xml | 722 ----------- exercises/solid/3-SOLID-LSP/pom.xml | 24 - .../main/java/oose/dea/solid/DataAccess.java | 12 - .../src/main/java/oose/dea/solid/Program.java | 16 - .../src/main/java/oose/dea/solid/Report.java | 13 - .../oose/dea/solid/ReportDataElement.java | 13 - .../java/oose/dea/solid/ReportFormatter.java | 10 - .../java/oose/dea/solid/ReportPrinter.java | 15 - .../java/oose/dea/solid/TabloidReport.java | 13 - .../dea/solid/TabloidReportFormatter.java | 11 - .../oose/dea/solid/TabloidReportPrinter.java | 19 - exercises/solid/4-SOLID-ISP/.idea/.name | 1 - .../solid/4-SOLID-ISP/.idea/compiler.xml | 33 - .../.idea/copyright/profiles_settings.xml | 3 - .../solid/4-SOLID-ISP/.idea/encodings.xml | 8 - .../libraries/Maven__junit_junit_4_11.xml | 13 - .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 - exercises/solid/4-SOLID-ISP/.idea/misc.xml | 18 - exercises/solid/4-SOLID-ISP/.idea/modules.xml | 9 - .../.idea/scopes/scope_settings.xml | 5 - .../solid/4-SOLID-ISP/.idea/uiDesigner.xml | 125 -- exercises/solid/4-SOLID-ISP/.idea/vcs.xml | 7 - .../solid/4-SOLID-ISP/.idea/workspace.xml | 1067 ----------------- exercises/solid/4-SOLID-ISP/pom.xml | 24 - .../main/java/oose/dea/solid/IDataAccess.java | 15 - .../java/oose/dea/solid/IDataElement.java | 8 - .../java/oose/dea/solid/LetterReport.java | 13 - .../oose/dea/solid/LetterReportFormatter.java | 11 - .../oose/dea/solid/LetterReportPrinter.java | 16 - .../src/main/java/oose/dea/solid/Program.java | 16 - .../src/main/java/oose/dea/solid/Report.java | 9 - .../java/oose/dea/solid/ReportDataAccess.java | 24 - .../oose/dea/solid/ReportDataElement.java | 13 - .../java/oose/dea/solid/ReportFormatter.java | 5 - .../java/oose/dea/solid/ReportPrinter.java | 5 - .../java/oose/dea/solid/TabloidReport.java | 13 - .../dea/solid/TabloidReportFormatter.java | 11 - .../oose/dea/solid/TabloidReportPrinter.java | 19 - exercises/solid/5-SOLID-DIP/.idea/.name | 1 - .../solid/5-SOLID-DIP/.idea/compiler.xml | 34 - .../.idea/copyright/profiles_settings.xml | 3 - .../solid/5-SOLID-DIP/.idea/encodings.xml | 8 - .../Maven__aopalliance_aopalliance_1_0.xml | 13 - ..._commons_logging_commons_logging_1_1_1.xml | 13 - .../libraries/Maven__junit_junit_4_11.xml | 13 - .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 - ...ringframework_spring_aop_3_2_4_RELEASE.xml | 13 - ...ngframework_spring_beans_3_2_4_RELEASE.xml | 13 - ...framework_spring_context_3_2_4_RELEASE.xml | 13 - ...ingframework_spring_core_3_2_4_RELEASE.xml | 13 - ...mework_spring_expression_3_2_4_RELEASE.xml | 13 - exercises/solid/5-SOLID-DIP/.idea/misc.xml | 18 - exercises/solid/5-SOLID-DIP/.idea/modules.xml | 9 - .../.idea/scopes/scope_settings.xml | 5 - .../solid/5-SOLID-DIP/.idea/uiDesigner.xml | 125 -- exercises/solid/5-SOLID-DIP/.idea/vcs.xml | 7 - .../solid/5-SOLID-DIP/.idea/workspace.xml | 983 --------------- exercises/solid/5-SOLID-DIP/pom.xml | 39 - .../main/java/oose/dea/solid/IDataAccess.java | 14 - .../java/oose/dea/solid/IDataElement.java | 8 - .../oose/dea/solid/IReportDataAccess.java | 11 - .../java/oose/dea/solid/LetterReport.java | 13 - .../oose/dea/solid/LetterReportFormatter.java | 11 - .../oose/dea/solid/LetterReportPrinter.java | 16 - .../src/main/java/oose/dea/solid/Program.java | 16 - .../src/main/java/oose/dea/solid/Report.java | 9 - .../java/oose/dea/solid/ReportDataAccess.java | 24 - .../oose/dea/solid/ReportDataElement.java | 13 - .../java/oose/dea/solid/ReportFormatter.java | 5 - .../java/oose/dea/solid/ReportPrinter.java | 5 - .../java/oose/dea/solid/TabloidReport.java | 13 - .../dea/solid/TabloidReportFormatter.java | 11 - .../oose/dea/solid/TabloidReportPrinter.java | 19 - .../src/main/resources/applicationContext.xml | 6 - 120 files changed, 6148 deletions(-) delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/.name delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/compiler.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/copyright/profiles_settings.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/encodings.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__junit_junit_4_11.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/misc.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/modules.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/scopes/scope_settings.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/uiDesigner.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/vcs.xml delete mode 100644 exercises/solid/1-SOLID-SRP/.idea/workspace.xml delete mode 100644 exercises/solid/1-SOLID-SRP/pom.xml delete mode 100644 exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Program.java delete mode 100644 exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Report.java delete mode 100644 exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/ReportDataElement.java delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/.name delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/compiler.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/copyright/profiles_settings.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/encodings.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__junit_junit_4_11.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/misc.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/modules.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/scopes/scope_settings.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/uiDesigner.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/vcs.xml delete mode 100644 exercises/solid/2-SOLID-OCP/.idea/workspace.xml delete mode 100644 exercises/solid/2-SOLID-OCP/pom.xml delete mode 100644 exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/DataAccess.java delete mode 100644 exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Program.java delete mode 100644 exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Report.java delete mode 100644 exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportDataElement.java delete mode 100644 exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportFormatter.java delete mode 100644 exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportPrinter.java delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/.name delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/compiler.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/copyright/profiles_settings.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/encodings.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__junit_junit_4_11.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/misc.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/modules.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/scopes/scope_settings.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/uiDesigner.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/vcs.xml delete mode 100644 exercises/solid/3-SOLID-LSP/.idea/workspace.xml delete mode 100644 exercises/solid/3-SOLID-LSP/pom.xml delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/DataAccess.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Program.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Report.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportDataElement.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportFormatter.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportPrinter.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReport.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportFormatter.java delete mode 100644 exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportPrinter.java delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/.name delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/compiler.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/copyright/profiles_settings.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/encodings.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__junit_junit_4_11.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/misc.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/modules.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/scopes/scope_settings.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/uiDesigner.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/vcs.xml delete mode 100644 exercises/solid/4-SOLID-ISP/.idea/workspace.xml delete mode 100644 exercises/solid/4-SOLID-ISP/pom.xml delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataAccess.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataElement.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReport.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportFormatter.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportPrinter.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Program.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Report.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataAccess.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataElement.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportFormatter.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportPrinter.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReport.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportFormatter.java delete mode 100644 exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportPrinter.java delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/.name delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/compiler.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/copyright/profiles_settings.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/encodings.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__commons_logging_commons_logging_1_1_1.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__junit_junit_4_11.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_aop_3_2_4_RELEASE.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_beans_3_2_4_RELEASE.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_context_3_2_4_RELEASE.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_core_3_2_4_RELEASE.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_expression_3_2_4_RELEASE.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/misc.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/modules.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/scopes/scope_settings.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/uiDesigner.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/vcs.xml delete mode 100644 exercises/solid/5-SOLID-DIP/.idea/workspace.xml delete mode 100644 exercises/solid/5-SOLID-DIP/pom.xml delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataAccess.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataElement.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IReportDataAccess.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReport.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportFormatter.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportPrinter.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Program.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Report.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataAccess.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataElement.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportFormatter.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportPrinter.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReport.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportFormatter.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportPrinter.java delete mode 100644 exercises/solid/5-SOLID-DIP/src/main/resources/applicationContext.xml diff --git a/exercises/solid/1-SOLID-SRP/.idea/.name b/exercises/solid/1-SOLID-SRP/.idea/.name deleted file mode 100644 index 57375f5..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -SOLID-SRP \ No newline at end of file diff --git a/exercises/solid/1-SOLID-SRP/.idea/compiler.xml b/exercises/solid/1-SOLID-SRP/.idea/compiler.xml deleted file mode 100644 index 6d73d6c..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/compiler.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - diff --git a/exercises/solid/1-SOLID-SRP/.idea/copyright/profiles_settings.xml b/exercises/solid/1-SOLID-SRP/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/exercises/solid/1-SOLID-SRP/.idea/encodings.xml b/exercises/solid/1-SOLID-SRP/.idea/encodings.xml deleted file mode 100644 index 2f1a13c..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/encodings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__junit_junit_4_11.xml b/exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__junit_junit_4_11.xml deleted file mode 100644 index f33320d..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__junit_junit_4_11.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml deleted file mode 100644 index f58bbc1..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/1-SOLID-SRP/.idea/misc.xml b/exercises/solid/1-SOLID-SRP/.idea/misc.xml deleted file mode 100644 index da56fbd..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/misc.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/exercises/solid/1-SOLID-SRP/.idea/modules.xml b/exercises/solid/1-SOLID-SRP/.idea/modules.xml deleted file mode 100644 index 1db324d..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/exercises/solid/1-SOLID-SRP/.idea/scopes/scope_settings.xml b/exercises/solid/1-SOLID-SRP/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/exercises/solid/1-SOLID-SRP/.idea/uiDesigner.xml b/exercises/solid/1-SOLID-SRP/.idea/uiDesigner.xml deleted file mode 100644 index 3b00020..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/uiDesigner.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/exercises/solid/1-SOLID-SRP/.idea/vcs.xml b/exercises/solid/1-SOLID-SRP/.idea/vcs.xml deleted file mode 100644 index def6a6a..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/exercises/solid/1-SOLID-SRP/.idea/workspace.xml b/exercises/solid/1-SOLID-SRP/.idea/workspace.xml deleted file mode 100644 index a7aa8e0..0000000 --- a/exercises/solid/1-SOLID-SRP/.idea/workspace.xml +++ /dev/null @@ -1,665 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - localhost - 5050 - - - - - - - 1402220195132 - 1402220195132 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No facets are configured - - - - - - - - abstract (v1.0.0, ruby-1.8.7-p249) [gem] - - - - - - - - 1.6 - - - - - - - - SOLID-SRP - - - - - - - - Maven: junit:junit:4.11 - - - - - - - - - diff --git a/exercises/solid/1-SOLID-SRP/pom.xml b/exercises/solid/1-SOLID-SRP/pom.xml deleted file mode 100644 index dacf9f9..0000000 --- a/exercises/solid/1-SOLID-SRP/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - 4.0.0 - - oose.dea.solid - SOLID-SRP - 1.0-SNAPSHOT - jar - - SOLID-SRP - - - UTF-8 - - - - - junit - junit - 4.11 - test - - - diff --git a/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Program.java b/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Program.java deleted file mode 100644 index 1368ac4..0000000 --- a/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Program.java +++ /dev/null @@ -1,16 +0,0 @@ -package oose.dea.solid; - -import java.io.IOException; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Program { - public static void main(String[] args) throws IOException { - Report report = new Report(); - report.print(); - System.out.println("Program ended, press a key to continue"); - System.in.read(); - } -} diff --git a/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Report.java b/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Report.java deleted file mode 100644 index 4331278..0000000 --- a/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/Report.java +++ /dev/null @@ -1,26 +0,0 @@ -package oose.dea.solid; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Report { - public void print() { - getData(); - formatReport(); - System.out.println("Printing report"); - } - - private void formatReport() { - System.out.println("Formatting report..."); - } - - private List getData() { - List dataElements = new ArrayList(); - dataElements.add(new ReportDataElement("Rody")); - return dataElements; - } -} diff --git a/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/ReportDataElement.java b/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/ReportDataElement.java deleted file mode 100644 index 7e3a917..0000000 --- a/exercises/solid/1-SOLID-SRP/src/main/java/oose/dea/solid/ReportDataElement.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class ReportDataElement { - private String customerName; - - public ReportDataElement(String customerName) { - this.customerName = customerName; - } -} diff --git a/exercises/solid/2-SOLID-OCP/.idea/.name b/exercises/solid/2-SOLID-OCP/.idea/.name deleted file mode 100644 index 934d594..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -SOLID-OCP \ No newline at end of file diff --git a/exercises/solid/2-SOLID-OCP/.idea/compiler.xml b/exercises/solid/2-SOLID-OCP/.idea/compiler.xml deleted file mode 100644 index 90bf204..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/compiler.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - diff --git a/exercises/solid/2-SOLID-OCP/.idea/copyright/profiles_settings.xml b/exercises/solid/2-SOLID-OCP/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/exercises/solid/2-SOLID-OCP/.idea/encodings.xml b/exercises/solid/2-SOLID-OCP/.idea/encodings.xml deleted file mode 100644 index 2f1a13c..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/encodings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__junit_junit_4_11.xml b/exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__junit_junit_4_11.xml deleted file mode 100644 index f33320d..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__junit_junit_4_11.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml deleted file mode 100644 index f58bbc1..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/2-SOLID-OCP/.idea/misc.xml b/exercises/solid/2-SOLID-OCP/.idea/misc.xml deleted file mode 100644 index da56fbd..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/misc.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/exercises/solid/2-SOLID-OCP/.idea/modules.xml b/exercises/solid/2-SOLID-OCP/.idea/modules.xml deleted file mode 100644 index 437e952..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/exercises/solid/2-SOLID-OCP/.idea/scopes/scope_settings.xml b/exercises/solid/2-SOLID-OCP/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/exercises/solid/2-SOLID-OCP/.idea/uiDesigner.xml b/exercises/solid/2-SOLID-OCP/.idea/uiDesigner.xml deleted file mode 100644 index 3b00020..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/uiDesigner.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/exercises/solid/2-SOLID-OCP/.idea/vcs.xml b/exercises/solid/2-SOLID-OCP/.idea/vcs.xml deleted file mode 100644 index def6a6a..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/exercises/solid/2-SOLID-OCP/.idea/workspace.xml b/exercises/solid/2-SOLID-OCP/.idea/workspace.xml deleted file mode 100644 index ccac5a4..0000000 --- a/exercises/solid/2-SOLID-OCP/.idea/workspace.xml +++ /dev/null @@ -1,688 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - localhost - 5050 - - - - - - - 1402220195132 - 1402220195132 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No facets are configured - - - - - - - - abstract (v1.0.0, ruby-1.8.7-p249) [gem] - - - - - - - - 1.6 - - - - - - - - SOLID-OCP - - - - - - - - Maven: junit:junit:4.11 - - - - - - - - - diff --git a/exercises/solid/2-SOLID-OCP/pom.xml b/exercises/solid/2-SOLID-OCP/pom.xml deleted file mode 100644 index f2bb4ff..0000000 --- a/exercises/solid/2-SOLID-OCP/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - 4.0.0 - - oose.dea.solid - SOLID-OCP - 1.0-SNAPSHOT - jar - - SOLID-OCP - - - UTF-8 - - - - - junit - junit - 4.11 - test - - - diff --git a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/DataAccess.java b/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/DataAccess.java deleted file mode 100644 index 92d0080..0000000 --- a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/DataAccess.java +++ /dev/null @@ -1,12 +0,0 @@ -package oose.dea.solid; - -import java.util.ArrayList; -import java.util.List; - -public class DataAccess { - public List getData() { - List dataElements = new ArrayList(); - dataElements.add(new ReportDataElement("Rody")); - return dataElements; - } -} \ No newline at end of file diff --git a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Program.java b/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Program.java deleted file mode 100644 index 755c6e0..0000000 --- a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Program.java +++ /dev/null @@ -1,16 +0,0 @@ -package oose.dea.solid; - -import java.io.IOException; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Program { - public static void main(String[] args) throws IOException { - Report report = new Report(); - report.print(); - System.out.println("Program ended, press a key to continue"); - System.in.read(); - } -} diff --git a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Report.java b/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Report.java deleted file mode 100644 index 6672ba3..0000000 --- a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/Report.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Report { - private final ReportPrinter reportPrinter = new ReportPrinter(); - - public void print() { - reportPrinter.print(); - } -} diff --git a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportDataElement.java b/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportDataElement.java deleted file mode 100644 index 7e3a917..0000000 --- a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportDataElement.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class ReportDataElement { - private String customerName; - - public ReportDataElement(String customerName) { - this.customerName = customerName; - } -} diff --git a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportFormatter.java b/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportFormatter.java deleted file mode 100644 index ed6dbcb..0000000 --- a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportFormatter.java +++ /dev/null @@ -1,10 +0,0 @@ -package oose.dea.solid; - -public class ReportFormatter { - public ReportFormatter() { - } - - public void formatReport() { - System.out.println("Formatting report for 8-1/2x11 ..."); - } -} \ No newline at end of file diff --git a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportPrinter.java b/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportPrinter.java deleted file mode 100644 index 069a1f7..0000000 --- a/exercises/solid/2-SOLID-OCP/src/main/java/oose/dea/solid/ReportPrinter.java +++ /dev/null @@ -1,15 +0,0 @@ -package oose.dea.solid; - -public class ReportPrinter { - private final DataAccess dataAccess = new DataAccess(); - private final ReportFormatter reportFormatter = new ReportFormatter(); - - public ReportPrinter() { - } - - public void print() { - dataAccess.getData(); - reportFormatter.formatReport(); - System.out.println("Printing report to laser printer"); - } -} \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/.idea/.name b/exercises/solid/3-SOLID-LSP/.idea/.name deleted file mode 100644 index 83dd0b9..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -SOLID-LSP \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/.idea/compiler.xml b/exercises/solid/3-SOLID-LSP/.idea/compiler.xml deleted file mode 100644 index 90bf204..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/compiler.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - diff --git a/exercises/solid/3-SOLID-LSP/.idea/copyright/profiles_settings.xml b/exercises/solid/3-SOLID-LSP/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/.idea/encodings.xml b/exercises/solid/3-SOLID-LSP/.idea/encodings.xml deleted file mode 100644 index 2f1a13c..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/encodings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__junit_junit_4_11.xml b/exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__junit_junit_4_11.xml deleted file mode 100644 index f33320d..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__junit_junit_4_11.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml deleted file mode 100644 index f58bbc1..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/.idea/misc.xml b/exercises/solid/3-SOLID-LSP/.idea/misc.xml deleted file mode 100644 index da56fbd..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/misc.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/exercises/solid/3-SOLID-LSP/.idea/modules.xml b/exercises/solid/3-SOLID-LSP/.idea/modules.xml deleted file mode 100644 index 47f25f5..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/exercises/solid/3-SOLID-LSP/.idea/scopes/scope_settings.xml b/exercises/solid/3-SOLID-LSP/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/.idea/uiDesigner.xml b/exercises/solid/3-SOLID-LSP/.idea/uiDesigner.xml deleted file mode 100644 index 3b00020..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/uiDesigner.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/exercises/solid/3-SOLID-LSP/.idea/vcs.xml b/exercises/solid/3-SOLID-LSP/.idea/vcs.xml deleted file mode 100644 index def6a6a..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/exercises/solid/3-SOLID-LSP/.idea/workspace.xml b/exercises/solid/3-SOLID-LSP/.idea/workspace.xml deleted file mode 100644 index 06b3916..0000000 --- a/exercises/solid/3-SOLID-LSP/.idea/workspace.xml +++ /dev/null @@ -1,722 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - localhost - 5050 - - - - - - - 1402220195132 - 1402220195132 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No facets are configured - - - - - - - - abstract (v1.0.0, ruby-1.8.7-p249) [gem] - - - - - - - - 1.6 - - - - - - - - SOLID-LSP - - - - - - - - Maven: junit:junit:4.11 - - - - - - - - - diff --git a/exercises/solid/3-SOLID-LSP/pom.xml b/exercises/solid/3-SOLID-LSP/pom.xml deleted file mode 100644 index 5e841b6..0000000 --- a/exercises/solid/3-SOLID-LSP/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - 4.0.0 - - oose.dea.solid - SOLID-LSP - 1.0-SNAPSHOT - jar - - SOLID-LSP - - - UTF-8 - - - - - junit - junit - 4.11 - test - - - diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/DataAccess.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/DataAccess.java deleted file mode 100644 index 92d0080..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/DataAccess.java +++ /dev/null @@ -1,12 +0,0 @@ -package oose.dea.solid; - -import java.util.ArrayList; -import java.util.List; - -public class DataAccess { - public List getData() { - List dataElements = new ArrayList(); - dataElements.add(new ReportDataElement("Rody")); - return dataElements; - } -} \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Program.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Program.java deleted file mode 100644 index ac2d88d..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Program.java +++ /dev/null @@ -1,16 +0,0 @@ -package oose.dea.solid; - -import java.io.IOException; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Program { - public static void main(String[] args) throws IOException { - Report report = new TabloidReport(); - report.print(); - System.out.println("Program ended, press a key to continue"); - System.in.read(); - } -} diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Report.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Report.java deleted file mode 100644 index 6672ba3..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/Report.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Report { - private final ReportPrinter reportPrinter = new ReportPrinter(); - - public void print() { - reportPrinter.print(); - } -} diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportDataElement.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportDataElement.java deleted file mode 100644 index 7e3a917..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportDataElement.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class ReportDataElement { - private String customerName; - - public ReportDataElement(String customerName) { - this.customerName = customerName; - } -} diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportFormatter.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportFormatter.java deleted file mode 100644 index ed6dbcb..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportFormatter.java +++ /dev/null @@ -1,10 +0,0 @@ -package oose.dea.solid; - -public class ReportFormatter { - public ReportFormatter() { - } - - public void formatReport() { - System.out.println("Formatting report for 8-1/2x11 ..."); - } -} \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportPrinter.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportPrinter.java deleted file mode 100644 index 069a1f7..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/ReportPrinter.java +++ /dev/null @@ -1,15 +0,0 @@ -package oose.dea.solid; - -public class ReportPrinter { - private final DataAccess dataAccess = new DataAccess(); - private final ReportFormatter reportFormatter = new ReportFormatter(); - - public ReportPrinter() { - } - - public void print() { - dataAccess.getData(); - reportFormatter.formatReport(); - System.out.println("Printing report to laser printer"); - } -} \ No newline at end of file diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReport.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReport.java deleted file mode 100644 index 85d300f..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReport.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReport extends Report { - private final ReportPrinter reportPrinter = new TabloidReportPrinter(); - - public void print() { - reportPrinter.print(); - } -} diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportFormatter.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportFormatter.java deleted file mode 100644 index adb649f..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportFormatter.java +++ /dev/null @@ -1,11 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReportFormatter extends ReportFormatter { - public void formatReport() { - System.out.println("Formatting report for 11x17 ..."); - } -} diff --git a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportPrinter.java b/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportPrinter.java deleted file mode 100644 index 9a5f4c3..0000000 --- a/exercises/solid/3-SOLID-LSP/src/main/java/oose/dea/solid/TabloidReportPrinter.java +++ /dev/null @@ -1,19 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReportPrinter extends ReportPrinter { - - private final DataAccess dataAccess = new DataAccess(); - private final ReportFormatter reportFormatter = new TabloidReportFormatter(); - - - public void print() { - dataAccess.getData(); - reportFormatter.formatReport(); - System.out.println("Printing report to matrix printer"); - } - -} diff --git a/exercises/solid/4-SOLID-ISP/.idea/.name b/exercises/solid/4-SOLID-ISP/.idea/.name deleted file mode 100644 index 680bb3b..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -SOLID-ISP \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/.idea/compiler.xml b/exercises/solid/4-SOLID-ISP/.idea/compiler.xml deleted file mode 100644 index 1ad1fed..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/compiler.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - diff --git a/exercises/solid/4-SOLID-ISP/.idea/copyright/profiles_settings.xml b/exercises/solid/4-SOLID-ISP/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/.idea/encodings.xml b/exercises/solid/4-SOLID-ISP/.idea/encodings.xml deleted file mode 100644 index 2f1a13c..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/encodings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__junit_junit_4_11.xml b/exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__junit_junit_4_11.xml deleted file mode 100644 index f33320d..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__junit_junit_4_11.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml deleted file mode 100644 index f58bbc1..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/.idea/misc.xml b/exercises/solid/4-SOLID-ISP/.idea/misc.xml deleted file mode 100644 index da56fbd..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/misc.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/exercises/solid/4-SOLID-ISP/.idea/modules.xml b/exercises/solid/4-SOLID-ISP/.idea/modules.xml deleted file mode 100644 index db58894..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/exercises/solid/4-SOLID-ISP/.idea/scopes/scope_settings.xml b/exercises/solid/4-SOLID-ISP/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/.idea/uiDesigner.xml b/exercises/solid/4-SOLID-ISP/.idea/uiDesigner.xml deleted file mode 100644 index 3b00020..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/uiDesigner.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/exercises/solid/4-SOLID-ISP/.idea/vcs.xml b/exercises/solid/4-SOLID-ISP/.idea/vcs.xml deleted file mode 100644 index def6a6a..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/exercises/solid/4-SOLID-ISP/.idea/workspace.xml b/exercises/solid/4-SOLID-ISP/.idea/workspace.xml deleted file mode 100644 index bce8272..0000000 --- a/exercises/solid/4-SOLID-ISP/.idea/workspace.xml +++ /dev/null @@ -1,1067 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - localhost - 5050 - - - - - - - 1402220195132 - 1402220195132 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No facets are configured - - - - - - - - abstract (v1.0.0, ruby-1.8.7-p249) [gem] - - - - - - - - 1.6 - - - - - - - - SOLID-ISP - - - - - - - - Maven: junit:junit:4.11 - - - - - - - - - diff --git a/exercises/solid/4-SOLID-ISP/pom.xml b/exercises/solid/4-SOLID-ISP/pom.xml deleted file mode 100644 index 733af03..0000000 --- a/exercises/solid/4-SOLID-ISP/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - 4.0.0 - - oose.dea.solid - SOLID-ISP - 1.0-SNAPSHOT - jar - - SOLID-ISP - - - UTF-8 - - - - - junit - junit - 4.11 - test - - - diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataAccess.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataAccess.java deleted file mode 100644 index 45d71d9..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataAccess.java +++ /dev/null @@ -1,15 +0,0 @@ -package oose.dea.solid; - -import java.util.List; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public interface IDataAccess { - List getReportData(); - - List queryData(String queryString); - - void saveData(IDataElement elementToSave); -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataElement.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataElement.java deleted file mode 100644 index 18968ce..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/IDataElement.java +++ /dev/null @@ -1,8 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public interface IDataElement { -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReport.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReport.java deleted file mode 100644 index 8a45786..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReport.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class LetterReport extends Report { - private final ReportPrinter reportPrinter = new LetterReportPrinter(); - - public void print() { - reportPrinter.print(); - } -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportFormatter.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportFormatter.java deleted file mode 100644 index 2c5e80e..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportFormatter.java +++ /dev/null @@ -1,11 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class LetterReportFormatter extends ReportFormatter { - public void formatReport() { - System.out.println("Formatting report for 8-1/2x11 ..."); - } -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportPrinter.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportPrinter.java deleted file mode 100644 index a8ac674..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/LetterReportPrinter.java +++ /dev/null @@ -1,16 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class LetterReportPrinter extends ReportPrinter { - private final IDataAccess reportDataAcccess = new ReportDataAccess(); - private final ReportFormatter reportFormatter = new LetterReportFormatter(); - - public void print() { - reportDataAcccess.getReportData(); - reportFormatter.formatReport(); - System.out.println("Printing report to laser printer"); - } -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Program.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Program.java deleted file mode 100644 index bc2b282..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Program.java +++ /dev/null @@ -1,16 +0,0 @@ -package oose.dea.solid; - -import java.io.IOException; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Program { - public static void main(String[] args) throws IOException { - Report report = new LetterReport(); - report.print(); - System.out.println("Program ended, press a key to continue"); - System.in.read(); - } -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Report.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Report.java deleted file mode 100644 index 4f0bafd..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/Report.java +++ /dev/null @@ -1,9 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public abstract class Report { - public abstract void print(); -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataAccess.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataAccess.java deleted file mode 100644 index 4396621..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataAccess.java +++ /dev/null @@ -1,24 +0,0 @@ -package oose.dea.solid; - -import sun.reflect.generics.reflectiveObjects.NotImplementedException; - -import java.util.ArrayList; -import java.util.List; - -public class ReportDataAccess implements IDataAccess { - public List getReportData() { - List dataElements = new ArrayList(); - dataElements.add(new ReportDataElement("Rody")); - return dataElements; - } - - @Override - public List queryData(String queryString) { - throw new NotImplementedException(); - } - - @Override - public void saveData(IDataElement elementToSave) { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataElement.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataElement.java deleted file mode 100644 index b698512..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportDataElement.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class ReportDataElement implements IDataElement { - private String customerName; - - public ReportDataElement(String customerName) { - this.customerName = customerName; - } -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportFormatter.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportFormatter.java deleted file mode 100644 index b3ef930..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportFormatter.java +++ /dev/null @@ -1,5 +0,0 @@ -package oose.dea.solid; - -public abstract class ReportFormatter { - public abstract void formatReport(); -} \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportPrinter.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportPrinter.java deleted file mode 100644 index 3de1af3..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/ReportPrinter.java +++ /dev/null @@ -1,5 +0,0 @@ -package oose.dea.solid; - -public abstract class ReportPrinter { - public abstract void print(); -} \ No newline at end of file diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReport.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReport.java deleted file mode 100644 index 85d300f..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReport.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReport extends Report { - private final ReportPrinter reportPrinter = new TabloidReportPrinter(); - - public void print() { - reportPrinter.print(); - } -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportFormatter.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportFormatter.java deleted file mode 100644 index adb649f..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportFormatter.java +++ /dev/null @@ -1,11 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReportFormatter extends ReportFormatter { - public void formatReport() { - System.out.println("Formatting report for 11x17 ..."); - } -} diff --git a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportPrinter.java b/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportPrinter.java deleted file mode 100644 index da281ce..0000000 --- a/exercises/solid/4-SOLID-ISP/src/main/java/oose/dea/solid/TabloidReportPrinter.java +++ /dev/null @@ -1,19 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReportPrinter extends ReportPrinter { - - private final IDataAccess reportDataAcccess = new ReportDataAccess(); - private final ReportFormatter reportFormatter = new TabloidReportFormatter(); - - - public void print() { - reportDataAcccess.getReportData(); - reportFormatter.formatReport(); - System.out.println("Printing report to matrix printer"); - } - -} diff --git a/exercises/solid/5-SOLID-DIP/.idea/.name b/exercises/solid/5-SOLID-DIP/.idea/.name deleted file mode 100644 index 4fbf8a0..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -SOLID-DIP \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/compiler.xml b/exercises/solid/5-SOLID-DIP/.idea/compiler.xml deleted file mode 100644 index bbfa77a..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/compiler.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - diff --git a/exercises/solid/5-SOLID-DIP/.idea/copyright/profiles_settings.xml b/exercises/solid/5-SOLID-DIP/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/encodings.xml b/exercises/solid/5-SOLID-DIP/.idea/encodings.xml deleted file mode 100644 index 2f1a13c..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/encodings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml deleted file mode 100644 index 30ff5cb..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__commons_logging_commons_logging_1_1_1.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__commons_logging_commons_logging_1_1_1.xml deleted file mode 100644 index b770f56..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__commons_logging_commons_logging_1_1_1.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__junit_junit_4_11.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__junit_junit_4_11.xml deleted file mode 100644 index f33320d..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__junit_junit_4_11.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml deleted file mode 100644 index f58bbc1..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_aop_3_2_4_RELEASE.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_aop_3_2_4_RELEASE.xml deleted file mode 100644 index 9f3472f..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_aop_3_2_4_RELEASE.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_beans_3_2_4_RELEASE.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_beans_3_2_4_RELEASE.xml deleted file mode 100644 index a59054d..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_beans_3_2_4_RELEASE.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_context_3_2_4_RELEASE.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_context_3_2_4_RELEASE.xml deleted file mode 100644 index 11bd5f0..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_context_3_2_4_RELEASE.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_core_3_2_4_RELEASE.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_core_3_2_4_RELEASE.xml deleted file mode 100644 index 3718263..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_core_3_2_4_RELEASE.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_expression_3_2_4_RELEASE.xml b/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_expression_3_2_4_RELEASE.xml deleted file mode 100644 index 3214c89..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/libraries/Maven__org_springframework_spring_expression_3_2_4_RELEASE.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/misc.xml b/exercises/solid/5-SOLID-DIP/.idea/misc.xml deleted file mode 100644 index da56fbd..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/misc.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/exercises/solid/5-SOLID-DIP/.idea/modules.xml b/exercises/solid/5-SOLID-DIP/.idea/modules.xml deleted file mode 100644 index 9764d36..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/exercises/solid/5-SOLID-DIP/.idea/scopes/scope_settings.xml b/exercises/solid/5-SOLID-DIP/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/.idea/uiDesigner.xml b/exercises/solid/5-SOLID-DIP/.idea/uiDesigner.xml deleted file mode 100644 index 3b00020..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/uiDesigner.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/exercises/solid/5-SOLID-DIP/.idea/vcs.xml b/exercises/solid/5-SOLID-DIP/.idea/vcs.xml deleted file mode 100644 index def6a6a..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/exercises/solid/5-SOLID-DIP/.idea/workspace.xml b/exercises/solid/5-SOLID-DIP/.idea/workspace.xml deleted file mode 100644 index 78f7eb4..0000000 --- a/exercises/solid/5-SOLID-DIP/.idea/workspace.xml +++ /dev/null @@ -1,983 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - localhost - 5050 - - - - - - - 1402220195132 - 1402220195132 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No facets are configured - - - - - - - - abstract (v1.0.0, ruby-1.8.7-p249) [gem] - - - - - - - - 1.6 - - - - - - - - SOLID-DIP - - - - - - - - Maven: junit:junit:4.11 - - - - - - - - - diff --git a/exercises/solid/5-SOLID-DIP/pom.xml b/exercises/solid/5-SOLID-DIP/pom.xml deleted file mode 100644 index c4ae44d..0000000 --- a/exercises/solid/5-SOLID-DIP/pom.xml +++ /dev/null @@ -1,39 +0,0 @@ - - 4.0.0 - - oose.dea.solid - SOLID-DIP - 1.0-SNAPSHOT - jar - - SOLID-DIP - - - UTF-8 - - - - - junit - junit - 4.11 - test - - - org.springframework - spring-beans - 3.2.4.RELEASE - - - org.springframework - spring-core - 3.2.4.RELEASE - - - org.springframework - spring-context - 3.2.4.RELEASE - - - diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataAccess.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataAccess.java deleted file mode 100644 index 4d77e9c..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataAccess.java +++ /dev/null @@ -1,14 +0,0 @@ -package oose.dea.solid; - -import java.util.List; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public interface IDataAccess extends IReportDataAccess { - - List queryData(String queryString); - - void saveData(IDataElement elementToSave); -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataElement.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataElement.java deleted file mode 100644 index 18968ce..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IDataElement.java +++ /dev/null @@ -1,8 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public interface IDataElement { -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IReportDataAccess.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IReportDataAccess.java deleted file mode 100644 index 133b00f..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/IReportDataAccess.java +++ /dev/null @@ -1,11 +0,0 @@ -package oose.dea.solid; - -import java.util.List; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public interface IReportDataAccess { - List getReportData(); -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReport.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReport.java deleted file mode 100644 index 8a45786..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReport.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class LetterReport extends Report { - private final ReportPrinter reportPrinter = new LetterReportPrinter(); - - public void print() { - reportPrinter.print(); - } -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportFormatter.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportFormatter.java deleted file mode 100644 index 2c5e80e..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportFormatter.java +++ /dev/null @@ -1,11 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class LetterReportFormatter extends ReportFormatter { - public void formatReport() { - System.out.println("Formatting report for 8-1/2x11 ..."); - } -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportPrinter.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportPrinter.java deleted file mode 100644 index 40e8761..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/LetterReportPrinter.java +++ /dev/null @@ -1,16 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class LetterReportPrinter extends ReportPrinter { - private final IReportDataAccess reportDataAcccess = new ReportDataAccess(); - private final ReportFormatter reportFormatter = new LetterReportFormatter(); - - public void print() { - reportDataAcccess.getReportData(); - reportFormatter.formatReport(); - System.out.println("Printing report to laser printer"); - } -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Program.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Program.java deleted file mode 100644 index bc2b282..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Program.java +++ /dev/null @@ -1,16 +0,0 @@ -package oose.dea.solid; - -import java.io.IOException; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class Program { - public static void main(String[] args) throws IOException { - Report report = new LetterReport(); - report.print(); - System.out.println("Program ended, press a key to continue"); - System.in.read(); - } -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Report.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Report.java deleted file mode 100644 index 4f0bafd..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/Report.java +++ /dev/null @@ -1,9 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public abstract class Report { - public abstract void print(); -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataAccess.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataAccess.java deleted file mode 100644 index 4396621..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataAccess.java +++ /dev/null @@ -1,24 +0,0 @@ -package oose.dea.solid; - -import sun.reflect.generics.reflectiveObjects.NotImplementedException; - -import java.util.ArrayList; -import java.util.List; - -public class ReportDataAccess implements IDataAccess { - public List getReportData() { - List dataElements = new ArrayList(); - dataElements.add(new ReportDataElement("Rody")); - return dataElements; - } - - @Override - public List queryData(String queryString) { - throw new NotImplementedException(); - } - - @Override - public void saveData(IDataElement elementToSave) { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataElement.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataElement.java deleted file mode 100644 index b698512..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportDataElement.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class ReportDataElement implements IDataElement { - private String customerName; - - public ReportDataElement(String customerName) { - this.customerName = customerName; - } -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportFormatter.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportFormatter.java deleted file mode 100644 index b3ef930..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportFormatter.java +++ /dev/null @@ -1,5 +0,0 @@ -package oose.dea.solid; - -public abstract class ReportFormatter { - public abstract void formatReport(); -} \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportPrinter.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportPrinter.java deleted file mode 100644 index 3de1af3..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/ReportPrinter.java +++ /dev/null @@ -1,5 +0,0 @@ -package oose.dea.solid; - -public abstract class ReportPrinter { - public abstract void print(); -} \ No newline at end of file diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReport.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReport.java deleted file mode 100644 index 85d300f..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReport.java +++ /dev/null @@ -1,13 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReport extends Report { - private final ReportPrinter reportPrinter = new TabloidReportPrinter(); - - public void print() { - reportPrinter.print(); - } -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportFormatter.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportFormatter.java deleted file mode 100644 index adb649f..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportFormatter.java +++ /dev/null @@ -1,11 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReportFormatter extends ReportFormatter { - public void formatReport() { - System.out.println("Formatting report for 11x17 ..."); - } -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportPrinter.java b/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportPrinter.java deleted file mode 100644 index b15db9e..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/java/oose/dea/solid/TabloidReportPrinter.java +++ /dev/null @@ -1,19 +0,0 @@ -package oose.dea.solid; - -/** - * @author mdkr - * @version Copyright (c) 2014 HAN University, All rights reserved. - */ -public class TabloidReportPrinter extends ReportPrinter { - - private final IReportDataAccess reportDataAcccess = new ReportDataAccess(); - private final ReportFormatter reportFormatter = new TabloidReportFormatter(); - - - public void print() { - reportDataAcccess.getReportData(); - reportFormatter.formatReport(); - System.out.println("Printing report to matrix printer"); - } - -} diff --git a/exercises/solid/5-SOLID-DIP/src/main/resources/applicationContext.xml b/exercises/solid/5-SOLID-DIP/src/main/resources/applicationContext.xml deleted file mode 100644 index 7300b34..0000000 --- a/exercises/solid/5-SOLID-DIP/src/main/resources/applicationContext.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - From 17990e098cb08f8ffc0c3b5be0aa9a9b79c3e72c Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Tue, 24 Feb 2015 23:09:08 +0100 Subject: [PATCH 12/45] New SOLID examples based on PluralSight video's --- exercises/solid/1.SRP/README.md | 14 +++++ exercises/solid/1.SRP/SRP-Example.iml | 19 ++++++ exercises/solid/1.SRP/SRP.iml | 19 ++++++ exercises/solid/1.SRP/pom.xml | 23 ++++++++ .../dea/orderservice/withoutsrp/Cart.java | 31 ++++++++++ .../InsufficientInventoryException.java | 4 ++ .../withoutsrp/InventorySystem.java | 26 +++++++++ .../dea/orderservice/withoutsrp/Item.java | 12 ++++ .../dea/orderservice/withoutsrp/Order.java | 44 ++++++++++++++ .../withoutsrp/OrderException.java | 7 +++ .../withoutsrp/PaymentDetails.java | 6 ++ .../withoutsrp/PaymentMethod.java | 5 ++ .../withsrp/CafetariaReservationService.java | 23 ++++++++ .../oose/dea/orderservice/withsrp/Cart.java | 31 ++++++++++ .../InsufficientInventoryException.java | 4 ++ .../orderservice/withsrp/InventorySystem.java | 26 +++++++++ .../oose/dea/orderservice/withsrp/Item.java | 12 ++++ .../withsrp/LoggingPaymentProcessor.java | 12 ++++ .../withsrp/MailNotificationService.java | 21 +++++++ .../withsrp/NotificationService.java | 5 ++ .../dea/orderservice/withsrp/OnlineOrder.java | 22 +++++++ .../oose/dea/orderservice/withsrp/Order.java | 12 ++++ .../orderservice/withsrp/OrderException.java | 7 +++ .../orderservice/withsrp/POSCashOrder.java | 7 +++ .../orderservice/withsrp/POSCreditOrder.java | 17 ++++++ .../orderservice/withsrp/PaymentDetails.java | 6 ++ .../orderservice/withsrp/PaymentMethod.java | 5 ++ .../withsrp/PaymentProcessor.java | 5 ++ .../withsrp/ReservationService.java | 7 +++ .../withoutsrp/InventorySystemTest.java | 27 +++++++++ .../withoutsrp/MailClientTest.java | 16 +++++ .../orderservice/withoutsrp/OrderTest.java | 58 +++++++++++++++++++ .../withoutsrp/PaymentGatewayTest.java | 14 +++++ .../withsrp/NotificationServiceTest.java | 23 ++++++++ .../orderservice/withsrp/OnlineOrderTest.java | 34 +++++++++++ .../withsrp/POSCashOrderTest.java | 25 ++++++++ .../withsrp/POSCreditOrderTest.java | 35 +++++++++++ .../withsrp/PaymentProcessorTest.java | 30 ++++++++++ .../withsrp/ReservationServiceTest.java | 40 +++++++++++++ exercises/solid/2.OCP/OCP.iml | 17 ++++++ exercises/solid/2.OCP/README.md | 13 +++++ exercises/solid/2.OCP/pom.xml | 17 ++++++ .../oose/dea/orderservice/withocp/Cart.java | 27 +++++++++ .../orderservice/withocp/EachPriceRule.java | 13 +++++ .../withocp/IPricingCalculator.java | 5 ++ .../oose/dea/orderservice/withocp/Item.java | 14 +++++ .../withocp/PerGramPriceRule.java | 13 +++++ .../dea/orderservice/withocp/PriceRule.java | 7 +++ .../withocp/PricingCalculator.java | 25 ++++++++ .../withocp/SpecialPriceRule.java | 16 +++++ .../dea/orderservice/withoutocp/Cart.java | 40 +++++++++++++ .../dea/orderservice/withoutocp/Item.java | 14 +++++ .../dea/orderservice/withocp/CartTest.java | 47 +++++++++++++++ .../withocp/EachPriceRuleTest.java | 38 ++++++++++++ .../withocp/PerGramPriceRuleTest.java | 38 ++++++++++++ .../withocp/PricingCalculatorTest.java | 46 +++++++++++++++ .../withocp/SpecialPriceRuleTest.java | 38 ++++++++++++ .../dea/orderservice/withoutocp/CartTest.java | 47 +++++++++++++++ exercises/solid/3.LSP/LSP.iml | 17 ++++++ exercises/solid/3.LSP/README.md | 11 ++++ exercises/solid/3.LSP/pom.xml | 17 ++++++ .../oose/dea/drawing/withlsp/Rectangle.java | 26 +++++++++ .../nl/oose/dea/drawing/withlsp/Shape.java | 5 ++ .../nl/oose/dea/drawing/withlsp/Square.java | 17 ++++++ .../nl/oose/dea/drawing/withlsp/Triangle.java | 27 +++++++++ .../drawing/withoutlsp/AreaCalculator.java | 18 ++++++ .../dea/drawing/withoutlsp/Rectangle.java | 22 +++++++ .../oose/dea/drawing/withoutlsp/Square.java | 15 +++++ .../drawing/withlsp/AreaCalculationTest.java | 58 +++++++++++++++++++ .../withoutlsp/AreaCalculatorTest.java | 39 +++++++++++++ exercises/solid/4.ISP/ISP.iml | 17 ++++++ exercises/solid/4.ISP/README.md | 6 ++ exercises/solid/4.ISP/pom.xml | 18 ++++++ .../oose/dea/orderservice/withisp/Cart.java | 28 +++++++++ .../orderservice/withisp/CartRepository.java | 4 ++ .../withisp/FullAccessClient.java | 17 ++++++ .../withisp/InMemoryCartRepository.java | 40 +++++++++++++ .../oose/dea/orderservice/withisp/Item.java | 12 ++++ .../withisp/ReadOnlyAccessClient.java | 26 +++++++++ .../dea/orderservice/withisp/Repository.java | 15 +++++ .../dea/orderservice/withoutisp/Cart.java | 28 +++++++++ .../withoutisp/CartRepository.java | 8 +++ .../withoutisp/FullAccessClient.java | 17 ++++++ .../withoutisp/InMemoryCartRepository.java | 40 +++++++++++++ .../dea/orderservice/withoutisp/Item.java | 12 ++++ .../withoutisp/ReadOnlyAccessClient.java | 17 ++++++ .../withoutisp/ReadOnlyCartRepository.java | 4 ++ .../withoutisp/ReadOnlyRepository.java | 9 +++ .../orderservice/withoutisp/Repository.java | 9 +++ .../withisp/CartRepositoryTest.java | 46 +++++++++++++++ .../dea/orderservice/withisp/ClientsTest.java | 33 +++++++++++ .../orderservice/withoutisp/ClientsTest.java | 36 ++++++++++++ exercises/solid/5.DIP/DIP-Example.iml | 27 +++++++++ exercises/solid/5.DIP/README.md | 6 ++ exercises/solid/5.DIP/pom.xml | 43 ++++++++++++++ .../withdip/CafetariaReservationService.java | 23 ++++++++ .../oose/dea/orderservice/withdip/Cart.java | 31 ++++++++++ .../dea/orderservice/withdip/CartFactory.java | 7 +++ .../InsufficientInventoryException.java | 4 ++ .../orderservice/withdip/InventorySystem.java | 26 +++++++++ .../oose/dea/orderservice/withdip/Item.java | 12 ++++ .../withdip/LoggingPaymentProcessor.java | 10 ++++ .../dea/orderservice/withdip/MailClient.java | 43 ++++++++++++++ .../withdip/MailNotificationService.java | 19 ++++++ .../withdip/NotificationService.java | 5 ++ .../dea/orderservice/withdip/OnlineOrder.java | 26 +++++++++ .../oose/dea/orderservice/withdip/Order.java | 12 ++++ .../orderservice/withdip/OrderException.java | 7 +++ .../withdip/OrderServiceSpringBootstrap.java | 19 ++++++ .../orderservice/withdip/POSCashOrder.java | 7 +++ .../orderservice/withdip/POSCreditOrder.java | 19 ++++++ .../orderservice/withdip/PaymentDetails.java | 6 ++ .../withdip/PaymentDetailsFactory.java | 10 ++++ .../orderservice/withdip/PaymentGateway.java | 13 +++++ .../orderservice/withdip/PaymentMethod.java | 5 ++ .../withdip/PaymentProcessor.java | 5 ++ .../withdip/ReservationService.java | 7 +++ .../CafetariaReservationService.java | 23 ++++++++ .../dea/orderservice/withoutdip/Cart.java | 31 ++++++++++ .../InsufficientInventoryException.java | 4 ++ .../withoutdip/InventorySystem.java | 26 +++++++++ .../dea/orderservice/withoutdip/Item.java | 12 ++++ .../withoutdip/LoggingPaymentProcessor.java | 10 ++++ .../orderservice/withoutdip/MailClient.java | 43 ++++++++++++++ .../withoutdip/MailNotificationService.java | 19 ++++++ .../withoutdip/NotificationService.java | 5 ++ .../orderservice/withoutdip/OnlineOrder.java | 22 +++++++ .../dea/orderservice/withoutdip/Order.java | 12 ++++ .../withoutdip/OrderException.java | 7 +++ .../orderservice/withoutdip/POSCashOrder.java | 7 +++ .../withoutdip/POSCreditOrder.java | 17 ++++++ .../withoutdip/PaymentDetails.java | 6 ++ .../withoutdip/PaymentGateway.java | 13 +++++ .../withoutdip/PaymentMethod.java | 5 ++ .../withoutdip/PaymentProcessor.java | 5 ++ .../withoutdip/ReservationService.java | 7 +++ .../src/main/resources/applicationContext.xml | 23 ++++++++ .../withdip/NotificationServiceTest.java | 21 +++++++ .../orderservice/withdip/OnlineOrderTest.java | 56 ++++++++++++++++++ .../withdip/POSCashOrderTest.java | 17 ++++++ .../withdip/POSCreditOrderTest.java | 39 +++++++++++++ .../withdip/PaymentProcessorTest.java | 31 ++++++++++ .../withdip/ReservationServiceTest.java | 40 +++++++++++++ .../withoutdip/NotificationServiceTest.java | 16 +++++ .../withoutdip/OnlineOrderTest.java | 24 ++++++++ .../withoutdip/POSCashOrderTest.java | 16 +++++ .../withoutdip/POSCreditOrderTest.java | 24 ++++++++ .../withoutdip/PaymentProcessorTest.java | 25 ++++++++ .../withoutdip/ReservationServiceTest.java | 35 +++++++++++ 149 files changed, 2956 insertions(+) create mode 100644 exercises/solid/1.SRP/README.md create mode 100644 exercises/solid/1.SRP/SRP-Example.iml create mode 100644 exercises/solid/1.SRP/SRP.iml create mode 100644 exercises/solid/1.SRP/pom.xml create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Cart.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InsufficientInventoryException.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InventorySystem.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Item.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Order.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/OrderException.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentDetails.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentMethod.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/CafetariaReservationService.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Cart.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InsufficientInventoryException.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InventorySystem.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Item.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/LoggingPaymentProcessor.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/MailNotificationService.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/NotificationService.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OnlineOrder.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Order.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OrderException.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCashOrder.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCreditOrder.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentDetails.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentMethod.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentProcessor.java create mode 100644 exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/ReservationService.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/InventorySystemTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/MailClientTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/OrderTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/PaymentGatewayTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/NotificationServiceTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/OnlineOrderTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCashOrderTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCreditOrderTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/PaymentProcessorTest.java create mode 100644 exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/ReservationServiceTest.java create mode 100644 exercises/solid/2.OCP/OCP.iml create mode 100644 exercises/solid/2.OCP/README.md create mode 100644 exercises/solid/2.OCP/pom.xml create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Cart.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/EachPriceRule.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/IPricingCalculator.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Item.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PerGramPriceRule.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PriceRule.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PricingCalculator.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/SpecialPriceRule.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Cart.java create mode 100644 exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Item.java create mode 100644 exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/CartTest.java create mode 100644 exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/EachPriceRuleTest.java create mode 100644 exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PerGramPriceRuleTest.java create mode 100644 exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PricingCalculatorTest.java create mode 100644 exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/SpecialPriceRuleTest.java create mode 100644 exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withoutocp/CartTest.java create mode 100644 exercises/solid/3.LSP/LSP.iml create mode 100644 exercises/solid/3.LSP/README.md create mode 100644 exercises/solid/3.LSP/pom.xml create mode 100644 exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Rectangle.java create mode 100644 exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Shape.java create mode 100644 exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Square.java create mode 100644 exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Triangle.java create mode 100644 exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/AreaCalculator.java create mode 100644 exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Rectangle.java create mode 100644 exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Square.java create mode 100644 exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withlsp/AreaCalculationTest.java create mode 100644 exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withoutlsp/AreaCalculatorTest.java create mode 100644 exercises/solid/4.ISP/ISP.iml create mode 100644 exercises/solid/4.ISP/README.md create mode 100644 exercises/solid/4.ISP/pom.xml create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Cart.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/CartRepository.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/FullAccessClient.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/InMemoryCartRepository.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Item.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/ReadOnlyAccessClient.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Repository.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Cart.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/CartRepository.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/FullAccessClient.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/InMemoryCartRepository.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Item.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyAccessClient.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyCartRepository.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyRepository.java create mode 100644 exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Repository.java create mode 100644 exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/CartRepositoryTest.java create mode 100644 exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/ClientsTest.java create mode 100644 exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withoutisp/ClientsTest.java create mode 100644 exercises/solid/5.DIP/DIP-Example.iml create mode 100644 exercises/solid/5.DIP/README.md create mode 100644 exercises/solid/5.DIP/pom.xml create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CafetariaReservationService.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Cart.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CartFactory.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InsufficientInventoryException.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InventorySystem.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Item.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/LoggingPaymentProcessor.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailClient.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailNotificationService.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/NotificationService.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OnlineOrder.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Order.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderException.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderServiceSpringBootstrap.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCashOrder.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCreditOrder.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetails.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetailsFactory.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentGateway.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentMethod.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentProcessor.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/ReservationService.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/CafetariaReservationService.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Cart.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InsufficientInventoryException.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InventorySystem.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Item.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/LoggingPaymentProcessor.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailClient.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailNotificationService.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/NotificationService.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OnlineOrder.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Order.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OrderException.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCashOrder.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrder.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentDetails.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentGateway.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentMethod.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessor.java create mode 100644 exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/ReservationService.java create mode 100644 exercises/solid/5.DIP/src/main/resources/applicationContext.xml create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/NotificationServiceTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/OnlineOrderTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCashOrderTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCreditOrderTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/PaymentProcessorTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/ReservationServiceTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/NotificationServiceTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/OnlineOrderTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCashOrderTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrderTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessorTest.java create mode 100644 exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/ReservationServiceTest.java diff --git a/exercises/solid/1.SRP/README.md b/exercises/solid/1.SRP/README.md new file mode 100644 index 0000000..8f6c02a --- /dev/null +++ b/exercises/solid/1.SRP/README.md @@ -0,0 +1,14 @@ +This project contains an implementation of an OrderService with two packages: +* nl.oose.dea.orderservice.withoutsrp contains classes and test cases without the SRP principle applied +* nl.oose.dea.orderservice.withsrp contains some classes and test cases that guide you to apply the SRP + +First read the sourcecode without SRP and run the test cases (comment the testcases with SRP applied to compile and run these testcases). +Second, read the test cases with SRP and (re)create the correct classes and interfaces so the unit tests all pass. + +Refactor the code in the following order: +* PaymentProcessor +* ReservationService +* NotificationService +* POSCashOrder +* POSCreditOrder +* OnlineOrder \ No newline at end of file diff --git a/exercises/solid/1.SRP/SRP-Example.iml b/exercises/solid/1.SRP/SRP-Example.iml new file mode 100644 index 0000000..c3fe000 --- /dev/null +++ b/exercises/solid/1.SRP/SRP-Example.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exercises/solid/1.SRP/SRP.iml b/exercises/solid/1.SRP/SRP.iml new file mode 100644 index 0000000..c3fe000 --- /dev/null +++ b/exercises/solid/1.SRP/SRP.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exercises/solid/1.SRP/pom.xml b/exercises/solid/1.SRP/pom.xml new file mode 100644 index 0000000..10097e9 --- /dev/null +++ b/exercises/solid/1.SRP/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + nl.oose.dea + SRP-Example + 1.0-SNAPSHOT + + + + junit + junit + 4.11 + + + javax.mail + mail + 1.4 + + + \ No newline at end of file diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Cart.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Cart.java new file mode 100644 index 0000000..d5b7c1b --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Cart.java @@ -0,0 +1,31 @@ +package nl.oose.dea.orderservice.withoutsrp; + +public class Cart { + private Item[] items; + private String customerName; + private int amount; + private String customerEmail; + + public Cart(String customerName, String customerEmail, Item[] items, int amount){ + this.customerName = customerName; + this.customerEmail = customerEmail; + this.items = items; + this.amount = amount; + } + + public Item[] getItems() { + return items; + } + + public String getCustomerName() { + return customerName; + } + + public int getBillingTotal() { + return amount; + } + + public String getCustomerEmail() { + return customerEmail; + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InsufficientInventoryException.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InsufficientInventoryException.java new file mode 100644 index 0000000..aa7b59b --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InsufficientInventoryException.java @@ -0,0 +1,4 @@ +package nl.oose.dea.orderservice.withoutsrp; + +public class InsufficientInventoryException extends Exception{ +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InventorySystem.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InventorySystem.java new file mode 100644 index 0000000..6fa7fb9 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/InventorySystem.java @@ -0,0 +1,26 @@ +package nl.oose.dea.orderservice.withoutsrp; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +public class InventorySystem { + private Logger logger = Logger.getLogger(getClass().getName()); + + private Map inventory = new HashMap() {{ + put("Frikandel", 20); + put("Bamihap", 25); + put("Mexicano", 50); + }}; + + public void reserve(String sku, int quantity) throws InsufficientInventoryException { + if (isOnStock(sku, quantity)) + inventory.put(sku, inventory.get(sku) - quantity); + else throw new InsufficientInventoryException(); + logger.info("There is still " + inventory.get(sku) + " of " + sku + " left in inventory"); + } + + public boolean isOnStock(String sku, int quantity) { + return inventory.get(sku) >= quantity; + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Item.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Item.java new file mode 100644 index 0000000..732e0b6 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Item.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withoutsrp; + +public class Item { + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Order.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Order.java new file mode 100644 index 0000000..8790450 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/Order.java @@ -0,0 +1,44 @@ +package nl.oose.dea.orderservice.withoutsrp; + +import javax.mail.MessagingException; +import java.util.logging.Logger; + +public class Order { + private Logger logger = Logger.getLogger(getClass().getName()); + + public void checkout(Cart cart, PaymentDetails paymentDetails, boolean notifyCustomer) + { + if (paymentDetails.paymentMethod == PaymentMethod.CreditCard) chargeCard(paymentDetails, cart); + reserveInventory(cart); + if (notifyCustomer) notifyCustomer(cart); + } + + private void notifyCustomer(Cart cart) { + MailClient mailClient = new MailClient(); + try { + mailClient.send("Your order is processed.", cart.getCustomerEmail()); + } catch (MessagingException e) { + logger.severe(e.getMessage()); + throw new OrderException("Cannot send mail to " + cart.getCustomerEmail(), e); + } + + } + + private void reserveInventory(Cart cart) { + for(Item item : cart.getItems()) + { + try { + InventorySystem inventorySystem = new InventorySystem(); + inventorySystem.reserve(item.sku, item.quantity); + } catch(InsufficientInventoryException insufficientInventoryException) + { + throw new OrderException("Insufficient inventory for item " + item.sku, insufficientInventoryException); + } + } + } + + private void chargeCard(PaymentDetails paymentDetails, Cart cart) { + PaymentGateway paymentGateway = new PaymentGateway(); + paymentGateway.charge(cart.getBillingTotal(), cart.getCustomerName(), paymentDetails.cardNumber); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/OrderException.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/OrderException.java new file mode 100644 index 0000000..fdbfc3b --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/OrderException.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withoutsrp; + +public class OrderException extends RuntimeException { + public OrderException(String message, Exception originalException) { + super(message, originalException); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentDetails.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentDetails.java new file mode 100644 index 0000000..c0ddb2c --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentDetails.java @@ -0,0 +1,6 @@ +package nl.oose.dea.orderservice.withoutsrp; + +public class PaymentDetails { + public PaymentMethod paymentMethod; + public int cardNumber; +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentMethod.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentMethod.java new file mode 100644 index 0000000..7eb6282 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withoutsrp/PaymentMethod.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withoutsrp; + +public enum PaymentMethod { + CreditCard +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/CafetariaReservationService.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/CafetariaReservationService.java new file mode 100644 index 0000000..8f630b6 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/CafetariaReservationService.java @@ -0,0 +1,23 @@ +package nl.oose.dea.orderservice.withsrp; + +public class CafetariaReservationService implements ReservationService { + private InventorySystem inventorySystem = new InventorySystem(); + + @Override + public void reserveInventory(Cart cart) { + for(Item item : cart.getItems()) + { + try { + inventorySystem.reserve(item.sku, item.quantity); + } catch(InsufficientInventoryException insufficientInventoryException) + { + throw new OrderException("Insufficient inventory for item " + item.sku, insufficientInventoryException); + } + } + } + + @Override + public boolean isOnStock(String product, int amount) { + return inventorySystem.isOnStock(product, amount); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Cart.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Cart.java new file mode 100644 index 0000000..ba82ef0 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Cart.java @@ -0,0 +1,31 @@ +package nl.oose.dea.orderservice.withsrp; + +public class Cart { + private Item[] items; + private String customerName; + private int amount; + private String customerEmail; + + public Cart(String customerName, String customerEmail, Item[] items, int amount){ + this.customerName = customerName; + this.customerEmail = customerEmail; + this.items = items; + this.amount = amount; + } + + public Item[] getItems() { + return items; + } + + public String getCustomerName() { + return customerName; + } + + public int getBillingTotal() { + return amount; + } + + public String getCustomerEmail() { + return customerEmail; + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InsufficientInventoryException.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InsufficientInventoryException.java new file mode 100644 index 0000000..bb882f2 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InsufficientInventoryException.java @@ -0,0 +1,4 @@ +package nl.oose.dea.orderservice.withsrp; + +public class InsufficientInventoryException extends Exception{ +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InventorySystem.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InventorySystem.java new file mode 100644 index 0000000..5d8ce87 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/InventorySystem.java @@ -0,0 +1,26 @@ +package nl.oose.dea.orderservice.withsrp; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +public class InventorySystem { + private Logger logger = Logger.getLogger(getClass().getName()); + + private Map inventory = new HashMap() {{ + put("Frikandel", 20); + put("Bamihap", 25); + put("Mexicano", 50); + }}; + + public void reserve(String sku, int quantity) throws InsufficientInventoryException { + if (isOnStock(sku, quantity)) + inventory.put(sku, inventory.get(sku) - quantity); + else throw new InsufficientInventoryException(); + logger.info("There is still " + inventory.get(sku) + " of " + sku + " left in inventory"); + } + + public boolean isOnStock(String sku, int quantity) { + return inventory.get(sku) >= quantity; + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Item.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Item.java new file mode 100644 index 0000000..eeb6081 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Item.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withsrp; + +public class Item { + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/LoggingPaymentProcessor.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/LoggingPaymentProcessor.java new file mode 100644 index 0000000..990efbc --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/LoggingPaymentProcessor.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withsrp; + +import nl.oose.dea.orderservice.withoutsrp.PaymentGateway; + +public class LoggingPaymentProcessor implements PaymentProcessor { + private PaymentGateway paymentGateway = new PaymentGateway(); + + @Override + public boolean chargeCard(PaymentDetails paymentDetails, Cart cart) { + return paymentGateway.charge(cart.getBillingTotal(), cart.getCustomerName(), paymentDetails.cardNumber); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/MailNotificationService.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/MailNotificationService.java new file mode 100644 index 0000000..c8c3866 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/MailNotificationService.java @@ -0,0 +1,21 @@ +package nl.oose.dea.orderservice.withsrp; + +import nl.oose.dea.orderservice.withoutsrp.*; + +import javax.mail.MessagingException; +import java.util.logging.Logger; + +public class MailNotificationService implements NotificationService { + private Logger logger = Logger.getLogger(getClass().getName()); + + @Override + public void notifyCustomer(Cart cart) { + MailClient mailClient = new MailClient(); + try { + mailClient.send("Your order is processed.", cart.getCustomerEmail()); + } catch (MessagingException e) { + logger.severe(e.getMessage()); + throw new OrderException("Cannot send mail to " + cart.getCustomerEmail(), e); + } + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/NotificationService.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/NotificationService.java new file mode 100644 index 0000000..51f7c8b --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/NotificationService.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withsrp; + +public interface NotificationService { + void notifyCustomer(Cart cart); +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OnlineOrder.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OnlineOrder.java new file mode 100644 index 0000000..8f1b941 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OnlineOrder.java @@ -0,0 +1,22 @@ +package nl.oose.dea.orderservice.withsrp; + +public class OnlineOrder extends Order { + private final PaymentDetails paymentDetails; + + private PaymentProcessor paymentProcessor = new LoggingPaymentProcessor(); + private NotificationService notificationService = new MailNotificationService(); + private ReservationService reservationService = new CafetariaReservationService(); + + public OnlineOrder(Cart cart, PaymentDetails paymentDetails) { + super(cart); + this.paymentDetails = paymentDetails; + } + + @Override + public void checkout() { + paymentProcessor.chargeCard(paymentDetails, cart); + reservationService.reserveInventory(cart); + notificationService.notifyCustomer(cart); + super.checkout(); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Order.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Order.java new file mode 100644 index 0000000..121079f --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/Order.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withsrp; + +public abstract class Order { + protected Cart cart; + + public Order(Cart cart) + { + this.cart = cart; + } + + public void checkout() {} +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OrderException.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OrderException.java new file mode 100644 index 0000000..3aeaf70 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/OrderException.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withsrp; + +public class OrderException extends RuntimeException { + public OrderException(String message, Exception originalException) { + super(message, originalException); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCashOrder.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCashOrder.java new file mode 100644 index 0000000..b8c6669 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCashOrder.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withsrp; + +public class POSCashOrder extends Order { + public POSCashOrder(Cart cart) { + super(cart); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCreditOrder.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCreditOrder.java new file mode 100644 index 0000000..94c9124 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/POSCreditOrder.java @@ -0,0 +1,17 @@ +package nl.oose.dea.orderservice.withsrp; + +public class POSCreditOrder extends Order { + private final PaymentDetails paymentDetails; + private PaymentProcessor paymentProcessor = new LoggingPaymentProcessor(); + + public POSCreditOrder(Cart cart, PaymentDetails paymentDetails) { + super(cart); + this.paymentDetails = paymentDetails; + } + + @Override + public void checkout() { + paymentProcessor.chargeCard(paymentDetails, cart); + super.checkout(); + } +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentDetails.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentDetails.java new file mode 100644 index 0000000..eda805a --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentDetails.java @@ -0,0 +1,6 @@ +package nl.oose.dea.orderservice.withsrp; + +public class PaymentDetails { + public PaymentMethod paymentMethod; + public int cardNumber; +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentMethod.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentMethod.java new file mode 100644 index 0000000..d1d82a1 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentMethod.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withsrp; + +public enum PaymentMethod { + CreditCard +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentProcessor.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentProcessor.java new file mode 100644 index 0000000..80cd392 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/PaymentProcessor.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withsrp; + +public interface PaymentProcessor { + boolean chargeCard(PaymentDetails paymentDetails, Cart cart); +} diff --git a/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/ReservationService.java b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/ReservationService.java new file mode 100644 index 0000000..befd634 --- /dev/null +++ b/exercises/solid/1.SRP/src/main/java/nl/oose/dea/orderservice/withsrp/ReservationService.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withsrp; + +public interface ReservationService { + void reserveInventory(Cart cart); + + boolean isOnStock(String product, int amount); +} diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/InventorySystemTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/InventorySystemTest.java new file mode 100644 index 0000000..9a30dd0 --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/InventorySystemTest.java @@ -0,0 +1,27 @@ +package nl.oose.dea.orderservice.withoutsrp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class InventorySystemTest { + private InventorySystem inventorySystem; + + @Before + public void setUp() + { + inventorySystem = new InventorySystem(); + } + + @Test + public void buyAllFrikandellen() throws Exception { + inventorySystem.reserve("Frikandel", 20); + assertTrue(inventorySystem.isOnStock("Frikandel", 0)); + } + + @Test(expected = InsufficientInventoryException.class) + public void youCannotBuyMoreThanAvailableInTheInventory() throws Exception { + inventorySystem.reserve("Frikandel", 21); + } +} \ No newline at end of file diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/MailClientTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/MailClientTest.java new file mode 100644 index 0000000..62e7a5a --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/MailClientTest.java @@ -0,0 +1,16 @@ +package nl.oose.dea.orderservice.withoutsrp; + +import org.junit.Test; + +import javax.mail.MessagingException; + +import static org.junit.Assert.*; + +public class MailClientTest { + + @Test(expected = MessagingException.class) + public void youCannotSendAMailUsingGmailWithAnEmptyUsernameAndPass() throws Exception { + MailClient mailClient = new MailClient(); + mailClient.send("Test", "oose@gmail.com"); + } +} \ No newline at end of file diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/OrderTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/OrderTest.java new file mode 100644 index 0000000..20c87c3 --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/OrderTest.java @@ -0,0 +1,58 @@ +package nl.oose.dea.orderservice.withoutsrp; + +import org.junit.Before; +import org.junit.Test; + +/** + * You might have been missing an assertEquals-statement in this unit test, this is due to the fact that + * we don't apply the Dependency Inversion Principle (DIP from SOLID) yet. + */ +public class OrderTest { + private Order order; + + @Before + public void setUp() throws Exception { + order = new Order(); + } + + @Test + public void checkoutProductsWithoutNotification() throws Exception { + // notification is always false when order created by a retail PoS + order.checkout(createCartWithSufficientInventory(), createPaymentDetails(), false); + } + + @Test(expected = OrderException.class) + public void checkoutProductsWhenInsufficientInventoryWithoutNotification() throws Exception { + // notification is always false when order created by a retail PoS + order.checkout(createCartWithInsufficientInventory(), createPaymentDetails(), false); + } + + @Test(expected = OrderException.class) // an exception is thrown because of the missing username/password + public void checkoutProductsWithNotification() throws Exception { + // notification is always true when order created by the web site + order.checkout(createCartWithSufficientInventory(), createPaymentDetails(), true); + } + + private PaymentDetails createPaymentDetails() { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.cardNumber = 1234; + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + return paymentDetails; + } + + private Cart createCartWithSufficientInventory() { + Cart cart = new Cart("OOSE", "oose@gmail.com", + new Item[]{ + new Item("Frikandel", 10), + new Item("Bamihap", 5) }, 20); + return cart; + } + + private Cart createCartWithInsufficientInventory() { + Cart cart = new Cart("OOSE", "oose@gmail.com", + new Item[]{ + new Item("Frikandel", 100), + new Item("Bamihap", 5) }, 200); + return cart; + } +} \ No newline at end of file diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/PaymentGatewayTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/PaymentGatewayTest.java new file mode 100644 index 0000000..c9dd3dc --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withoutsrp/PaymentGatewayTest.java @@ -0,0 +1,14 @@ +package nl.oose.dea.orderservice.withoutsrp; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PaymentGatewayTest { + + @Test + public void testCharge() throws Exception { + PaymentGateway paymentGateway = new PaymentGateway(); + assertTrue(paymentGateway.charge(20,"OOSE", 1234)); + } +} \ No newline at end of file diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/NotificationServiceTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/NotificationServiceTest.java new file mode 100644 index 0000000..b763ad4 --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/NotificationServiceTest.java @@ -0,0 +1,23 @@ +package nl.oose.dea.orderservice.withsrp; + +import org.junit.Test; + +import javax.mail.MessagingException; + +public class NotificationServiceTest { + + @Test(expected = OrderException.class) + public void youCannotSendAMailUsingGmailWithAnEmptyUsernameAndPass() throws Exception { + /** + * TIP: + * - create a new class MailNotificationService that implements a new interface NotificationService + * - implement a notifyCustomer method using the code from the 'old' Order class. + */ + NotificationService notificationService = new MailNotificationService(); + notificationService.notifyCustomer(createCart()); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{}, 0); + } +} \ No newline at end of file diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/OnlineOrderTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/OnlineOrderTest.java new file mode 100644 index 0000000..ec7c980 --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/OnlineOrderTest.java @@ -0,0 +1,34 @@ +package nl.oose.dea.orderservice.withsrp; + +import org.junit.Test; + +public class OnlineOrderTest { + @Test(expected = OrderException.class) + public void checkoutOnlineOrder() + { + /** + * TIP: Re-create Order as an abstract base class which can hold the cart and defines an parameterless + * method called checkout with an empty body. Instead of passing parameters to the method, pass required + * parameters to the constructor. + * + * An OnlineOrder depends on three interfaces: + * - NotificationService + * - ReservationService + * - PaymentProcessor + */ + Order order = new OnlineOrder(createCart(), createPaymentDetails()); + order.checkout(); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } + + private PaymentDetails createPaymentDetails() + { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + paymentDetails.cardNumber = 1234; + return paymentDetails; + } +} diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCashOrderTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCashOrderTest.java new file mode 100644 index 0000000..5931f4c --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCashOrderTest.java @@ -0,0 +1,25 @@ +package nl.oose.dea.orderservice.withsrp; + +import org.junit.Test; + +public class POSCashOrderTest { + @Test + public void checkoutOnlineOrder() + { + /** + * TIP: Re-create Order as an abstract base class which can hold the cart and defines an parameterless + * method called checkout with an empty body. Instead of passing parameters to the method, pass required + * parameters to the constructor. + * + * An POSCashOrder depends on none of the given interfaces. It does not depend on the ReservationService because we can get the items right out of the shop, we don't + * have to access our inventory, and we get paid cash. + + */ + Order order = new POSCashOrder(createCart()); + order.checkout(); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } +} diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCreditOrderTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCreditOrderTest.java new file mode 100644 index 0000000..76254e9 --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/POSCreditOrderTest.java @@ -0,0 +1,35 @@ +package nl.oose.dea.orderservice.withsrp; + +import org.junit.Test; + +public class POSCreditOrderTest { + @Test + public void checkoutOnlineOrder() + { + /** + * TIP: Re-create Order as an abstract base class which can hold the cart and defines an parameterless + * method called checkout with an empty body. Instead of passing parameters to the method, pass required + * parameters to the constructor. + * + * An POSCreditOrder depends on one interface: + * - PaymentProcessor + * + * It does not depend on the InventorySystem because we can get the items right out of the shop, we don't + * have to access our inventory + */ + Order order = new POSCreditOrder(createCart(), createPaymentDetails()); + order.checkout(); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } + + private PaymentDetails createPaymentDetails() + { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + paymentDetails.cardNumber = 1234; + return paymentDetails; + } +} diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/PaymentProcessorTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/PaymentProcessorTest.java new file mode 100644 index 0000000..cef8108 --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/PaymentProcessorTest.java @@ -0,0 +1,30 @@ +package nl.oose.dea.orderservice.withsrp; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class PaymentProcessorTest { + + @Test + public void testCharge() throws Exception { + /** + * TIP: + * - create a new class LoggingPaymentProcessor that implements a new interface PaymentProcessor + * - implement a chargeCard method using the code from the 'old' Order class. + */ + PaymentProcessor paymentProcessor = new LoggingPaymentProcessor(); + assertTrue(paymentProcessor.chargeCard(createPaymentDetails(),createCart())); + } + + private Cart createCart() { + return new Cart("OOSE", "oose@gmail.com", new Item[]{}, 0); + } + + private PaymentDetails createPaymentDetails() { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.cardNumber = 1234; + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + return paymentDetails; + } +} \ No newline at end of file diff --git a/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/ReservationServiceTest.java b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/ReservationServiceTest.java new file mode 100644 index 0000000..b97f24d --- /dev/null +++ b/exercises/solid/1.SRP/src/test/java/nl/oose/dea/orderservice/withsrp/ReservationServiceTest.java @@ -0,0 +1,40 @@ +package nl.oose.dea.orderservice.withsrp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class ReservationServiceTest { + private ReservationService reservationService; + + @Before + public void setUp() + { + /** + * TIP: + * - create a new class CafetariaReservationService that implements a new interface ReservationService + * - implement a reserveInventory method using the code from the 'old' Order class. + */ + reservationService = new CafetariaReservationService(); + } + + @Test + public void buyAllFrikandellen() throws Exception { + reservationService.reserveInventory(createCartWithSufficientInventory()); + assertTrue(reservationService.isOnStock("Frikandel", 0)); + } + + private Cart createCartWithSufficientInventory() { + return new Cart("OOSE","oose@gmail.com", new Item[] { new Item("Frikandel", 20) }, 50); + } + + private Cart createCartWithInsufficientInventory() { + return new Cart("OOSE","oose@gmail.com", new Item[] { new Item("Frikandel", 21) }, 50); + } + + @Test(expected = OrderException.class) + public void youCannotBuyMoreThanAvailableInTheInventory() throws Exception { + reservationService.reserveInventory(createCartWithInsufficientInventory()); + } +} \ No newline at end of file diff --git a/exercises/solid/2.OCP/OCP.iml b/exercises/solid/2.OCP/OCP.iml new file mode 100644 index 0000000..e04193a --- /dev/null +++ b/exercises/solid/2.OCP/OCP.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exercises/solid/2.OCP/README.md b/exercises/solid/2.OCP/README.md new file mode 100644 index 0000000..9a32a9f --- /dev/null +++ b/exercises/solid/2.OCP/README.md @@ -0,0 +1,13 @@ +This project contains an implementation of an OrderService with two packages: +* nl.oose.dea.orderservice.withoutocp contains classes and test cases without the OCP principle applied +* nl.oose.dea.orderservice.withocp contains some classes and test cases that guide you to apply the OCP + +First read the sourcecode without OCP and run the test cases (comment the testcases with OCP applied to compile and run these testcases). +Second, read the test cases with OCP and (re)create the correct classes and interfaces so the unit tests all pass. + +Refactor the code in the following order: +* EachPriceRule +* PerGramPriceRule +* SpecialPriceRule +* PricingCalculator and IPricingCalculator +* Cart \ No newline at end of file diff --git a/exercises/solid/2.OCP/pom.xml b/exercises/solid/2.OCP/pom.xml new file mode 100644 index 0000000..5e0245f --- /dev/null +++ b/exercises/solid/2.OCP/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + nl.oose.dea + OCP-Example + 1.0-SNAPSHOT + + + junit + junit + 4.11 + + + \ No newline at end of file diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Cart.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Cart.java new file mode 100644 index 0000000..d9a1946 --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Cart.java @@ -0,0 +1,27 @@ +package nl.oose.dea.orderservice.withocp; + +import java.util.ArrayList; +import java.util.List; + +public class Cart { + private IPricingCalculator pricingCalculator; + private List items; + + public Cart(IPricingCalculator pricingCalculator) { + this.pricingCalculator = pricingCalculator; + this.items = new ArrayList(); + } + + public void addItem(Item item) + { + items.add(item); + } + + public double totalAmount() { + double total = 0; + for(Item item: items) { + total += pricingCalculator.calculatePrice(item); + } + return total; + } +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/EachPriceRule.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/EachPriceRule.java new file mode 100644 index 0000000..b6feb13 --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/EachPriceRule.java @@ -0,0 +1,13 @@ +package nl.oose.dea.orderservice.withocp; + +public class EachPriceRule implements PriceRule { + @Override + public boolean isMatch(Item eachItem) { + return eachItem.sku.startsWith("EACH"); + } + + @Override + public double calculatePrice(Item eachItem) { + return 5.0 * eachItem.quantity; + } +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/IPricingCalculator.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/IPricingCalculator.java new file mode 100644 index 0000000..c3bc86c --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/IPricingCalculator.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withocp; + +public interface IPricingCalculator { + double calculatePrice(Item item); +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Item.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Item.java new file mode 100644 index 0000000..64ac299 --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/Item.java @@ -0,0 +1,14 @@ +package nl.oose.dea.orderservice.withocp; + +public class Item { + // SKU' A store's or catalog's product and service identification code, often portrayed as a + // machine-readable bar code that helps the item to be tracked for inventory. + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PerGramPriceRule.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PerGramPriceRule.java new file mode 100644 index 0000000..b6ef4c9 --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PerGramPriceRule.java @@ -0,0 +1,13 @@ +package nl.oose.dea.orderservice.withocp; + +public class PerGramPriceRule implements PriceRule { + @Override + public boolean isMatch(Item item) { + return item.sku.startsWith("WEIGHT"); + } + + @Override + public double calculatePrice(Item item) { + return (item.quantity * 4.0) / 1000; + } +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PriceRule.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PriceRule.java new file mode 100644 index 0000000..e2a07b1 --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PriceRule.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withocp; + +public interface PriceRule { + boolean isMatch(Item eachItem); + + double calculatePrice(Item eachItem); +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PricingCalculator.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PricingCalculator.java new file mode 100644 index 0000000..86e34ea --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/PricingCalculator.java @@ -0,0 +1,25 @@ +package nl.oose.dea.orderservice.withocp; + +import java.util.ArrayList; +import java.util.List; + +public class PricingCalculator implements IPricingCalculator { + private List rules; + + public PricingCalculator() { + rules = new ArrayList() {{ + add(new EachPriceRule()); + add(new PerGramPriceRule()); + add(new SpecialPriceRule()); + }}; + } + + public double calculatePrice(Item item) { + for(PriceRule rule : rules) + { + if (rule.isMatch(item)) + return rule.calculatePrice(item); + } + return 0; + } +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/SpecialPriceRule.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/SpecialPriceRule.java new file mode 100644 index 0000000..6d437de --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withocp/SpecialPriceRule.java @@ -0,0 +1,16 @@ +package nl.oose.dea.orderservice.withocp; + +public class SpecialPriceRule implements PriceRule { + @Override + public boolean isMatch(Item item) { + return item.sku.startsWith("SPECIAL"); + } + + @Override + public double calculatePrice(Item item) { + double price = item.quantity * 0.4; + int setsOfThree = item.quantity / 3; + price -= setsOfThree * 0.2; + return price; + } +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Cart.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Cart.java new file mode 100644 index 0000000..33d01bc --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Cart.java @@ -0,0 +1,40 @@ +package nl.oose.dea.orderservice.withoutocp; + +import java.util.ArrayList; +import java.util.List; + +public class Cart { + private List items = new ArrayList(); + + public void addItem(Item item) { + items.add(item); + } + + /** + * We need to modify this code when adding new rules. This method does not + * comply to the OCP! + * @return + */ + public double totalAmount() + { + double total = 0; + for(Item item: items) + { + if (item.sku.startsWith("EACH")) + { + total += item.quantity * 5.0; + } + else if(item.sku.startsWith("WEIGHT")) + { + total += (item.quantity * 4.0) / 1000; + } + else if(item.sku.startsWith("SPECIAL")) + { + total += item.quantity * 0.4; + int setsOfThree = item.quantity / 3; + total -= setsOfThree * 0.2; + } + } + return total; + } +} diff --git a/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Item.java b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Item.java new file mode 100644 index 0000000..90a6112 --- /dev/null +++ b/exercises/solid/2.OCP/src/main/java/nl/oose/dea/orderservice/withoutocp/Item.java @@ -0,0 +1,14 @@ +package nl.oose.dea.orderservice.withoutocp; + +public class Item { + // SKU' A store's or catalog's product and service identification code, often portrayed as a + // machine-readable bar code that helps the item to be tracked for inventory. + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/CartTest.java b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/CartTest.java new file mode 100644 index 0000000..8a2b8f9 --- /dev/null +++ b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/CartTest.java @@ -0,0 +1,47 @@ +package nl.oose.dea.orderservice.withocp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CartTest { + private Cart cart; + + @Before + public void setUp() throws Exception { + cart = new Cart(new PricingCalculator()); + } + + @Test + public void totalIsZeroWhenCartIsEmpty() { + assertEquals(0, cart.totalAmount(), 0); + } + + @Test + public void totalIsFiveWhenCartHasOneEachItem() { + cart.addItem(new Item("EACH_Frikandel", 1)); + assertEquals(5.0, cart.totalAmount(), 0); + } + + @Test + public void totalIsTwoWhenCartHasOnePoundOfFrenchFries() { + cart.addItem(new Item("WEIGHT_Frietjes", 200)); // small size bag + cart.addItem(new Item("WEIGHT_Frietjes", 300)); // medium size bag + + assertEquals(2.0, cart.totalAmount(), 0.1); + } + + @Test + public void totalIsEightyCentsWhenCartHasTwoSpecialItems() { + cart.addItem(new Item("SPECIAL_Fritessaus", 2)); + assertEquals(0.8, cart.totalAmount(), 0.01); + } + + @Test + public void totalIsTwoWhenCartHasSixSpecialItems() { + cart.addItem(new Item("SPECIAL_Fritessaus", 3)); + cart.addItem(new Item("SPECIAL_Fritessaus", 3)); + assertEquals(2, cart.totalAmount(), 0.01); + } +} \ No newline at end of file diff --git a/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/EachPriceRuleTest.java b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/EachPriceRuleTest.java new file mode 100644 index 0000000..eb794b2 --- /dev/null +++ b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/EachPriceRuleTest.java @@ -0,0 +1,38 @@ +package nl.oose.dea.orderservice.withocp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class EachPriceRuleTest { + private PriceRule eachPriceRule; + + @Before + public void setUp() + { + eachPriceRule = new EachPriceRule(); + } + + @Test + public void ruleOnlyAppliesToSKUStartingWithTheWordEach() + { + assertTrue(eachPriceRule.isMatch(createEachItem())); + assertFalse(eachPriceRule.isMatch(createItem("WEIGHT"))); + } + + @Test + public void ruleCalculatesPriceAmountTimesFive() + { + assertEquals(5.0, eachPriceRule.calculatePrice(createEachItem()),0); + } + + private Item createEachItem() + { + return createItem("EACH"); + } + + private Item createItem(String prefix) { + return new Item(prefix + "_Frikandel", 1); + } +} diff --git a/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PerGramPriceRuleTest.java b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PerGramPriceRuleTest.java new file mode 100644 index 0000000..c468a2c --- /dev/null +++ b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PerGramPriceRuleTest.java @@ -0,0 +1,38 @@ +package nl.oose.dea.orderservice.withocp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PerGramPriceRuleTest { + private PriceRule eachPriceRule; + + @Before + public void setUp() + { + eachPriceRule = new PerGramPriceRule(); + } + + @Test + public void ruleOnlyAppliesToSKUStartingWithTheWordEach() + { + assertTrue(eachPriceRule.isMatch(createPerGramItem())); + assertFalse(eachPriceRule.isMatch(createItem("EACH"))); + } + + @Test + public void ruleCalculatesPriceAmountTimesFive() + { + assertEquals(2.0, eachPriceRule.calculatePrice(createPerGramItem()),0); + } + + private Item createPerGramItem() + { + return createItem("WEIGHT"); + } + + private Item createItem(String prefix) { + return new Item(prefix + "_Frietjes", 500); + } +} diff --git a/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PricingCalculatorTest.java b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PricingCalculatorTest.java new file mode 100644 index 0000000..45d6e0d --- /dev/null +++ b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/PricingCalculatorTest.java @@ -0,0 +1,46 @@ +package nl.oose.dea.orderservice.withocp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PricingCalculatorTest { + private IPricingCalculator pricingCalculator; + + @Before + public void setUp() throws Exception { + pricingCalculator = new PricingCalculator(); + } + + @Test + public void totalIsZeroWhenCartIsEmpty() { + assertEquals(0, pricingCalculator.calculatePrice(new Item("EACH_Frikandel", 0)), 0); + } + + @Test + public void totalIsFiveWhenCartHasOneEachItem() { + assertEquals(5.0, pricingCalculator.calculatePrice(new Item("EACH_Frikandel", 1)), 0); + } + + @Test + public void totalIsTwoWhenCartHasOnePoundOfFrenchFries() { + assertEquals(2.0, pricingCalculator.calculatePrice(new Item("WEIGHT_Frietjes", 500)), 0); + } + + @Test + public void totalIsEightyCentsWhenCartHasTwoSpecialItems() { + assertEquals(0.8, pricingCalculator.calculatePrice(new Item("SPECIAL_Fritessaus", 2)), 0.01); + } + + @Test + public void totalIsTwoWhenCartHasSixSpecialItems() { + assertEquals(2, pricingCalculator.calculatePrice(new Item("SPECIAL_Fritessaus", 6)), 0.01); + } + + @Test + public void totalIsZeroWhenNoRuleApplies() + { + assertEquals(0, pricingCalculator.calculatePrice(new Item("SOME_Frikandel", 100)), 0); + } +} \ No newline at end of file diff --git a/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/SpecialPriceRuleTest.java b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/SpecialPriceRuleTest.java new file mode 100644 index 0000000..616096c --- /dev/null +++ b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withocp/SpecialPriceRuleTest.java @@ -0,0 +1,38 @@ +package nl.oose.dea.orderservice.withocp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SpecialPriceRuleTest { + private PriceRule eachPriceRule; + + @Before + public void setUp() + { + eachPriceRule = new SpecialPriceRule(); + } + + @Test + public void ruleOnlyAppliesToSKUStartingWithTheWordEach() + { + assertTrue(eachPriceRule.isMatch(createSpecialItem())); + assertFalse(eachPriceRule.isMatch(createItem("EACH"))); + } + + @Test + public void ruleCalculatesPriceAmountTimesFive() + { + assertEquals(2.0, eachPriceRule.calculatePrice(createSpecialItem()),0.1); + } + + private Item createSpecialItem() + { + return createItem("SPECIAL"); + } + + private Item createItem(String prefix) { + return new Item(prefix + "_Fritessaus", 6); + } +} diff --git a/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withoutocp/CartTest.java b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withoutocp/CartTest.java new file mode 100644 index 0000000..506ab11 --- /dev/null +++ b/exercises/solid/2.OCP/src/test/java/nl/oose/dea/orderservice/withoutocp/CartTest.java @@ -0,0 +1,47 @@ +package nl.oose.dea.orderservice.withoutocp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CartTest { + private Cart cart; + + @Before + public void setUp() throws Exception { + cart = new Cart(); + } + + @Test + public void totalIsZeroWhenCartIsEmpty() { + assertEquals(0, cart.totalAmount(), 0); + } + + @Test + public void totalIsFiveWhenCartHasOneEachItem() { + cart.addItem(new Item("EACH_Frikandel", 1)); + assertEquals(5.0, cart.totalAmount(), 0); + } + + @Test + public void totalIsTwoWhenCartHasOnePoundOfFrenchFries() { + cart.addItem(new Item("WEIGHT_Frietjes", 200)); // small size bag + cart.addItem(new Item("WEIGHT_Frietjes", 300)); // medium size bag + + assertEquals(2.0, cart.totalAmount(), 0); + } + + @Test + public void totalIsEightyCentsWhenCartHasTwoSpecialItems() { + cart.addItem(new Item("SPECIAL_Fritessaus", 2)); + assertEquals(0.8, cart.totalAmount(), 0.01); + } + + @Test + public void totalIsTwoWhenCartHasSixSpecialItems() { + cart.addItem(new Item("SPECIAL_Fritessaus", 3)); + cart.addItem(new Item("SPECIAL_Fritessaus", 3)); + assertEquals(2, cart.totalAmount(), 0.01); + } +} \ No newline at end of file diff --git a/exercises/solid/3.LSP/LSP.iml b/exercises/solid/3.LSP/LSP.iml new file mode 100644 index 0000000..e04193a --- /dev/null +++ b/exercises/solid/3.LSP/LSP.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exercises/solid/3.LSP/README.md b/exercises/solid/3.LSP/README.md new file mode 100644 index 0000000..2b7a637 --- /dev/null +++ b/exercises/solid/3.LSP/README.md @@ -0,0 +1,11 @@ +This project contains an implementation of a small drawing application with two packages: +* nl.oose.dea.drawing.withoutlsp contains classes and test cases without the LSP principle applied +* nl.oose.dea.drawing.withlsp contains some classes and test cases that guide you to apply the LSP + +First read the sourcecode without LSP and run the test cases (comment the testcases with LSP applied to compile and run these testcases). +Second, read the test cases with LSP and (re)create the correct classes and interfaces so the unit tests all pass. + +* Break the is-a relationship between Rectangle and Square +* Introduce a superclass for both shapes, called .... Shape :) +* Move the area-calculation to the right spot +* When all the unit tests pass, add a new Shape called Triangle and adjust the third test case so it also calculates the area for a Triangle \ No newline at end of file diff --git a/exercises/solid/3.LSP/pom.xml b/exercises/solid/3.LSP/pom.xml new file mode 100644 index 0000000..1402257 --- /dev/null +++ b/exercises/solid/3.LSP/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + nl.oose.dea + LSP-Example + 1.0-SNAPSHOT + + + junit + junit + 4.11 + + + \ No newline at end of file diff --git a/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Rectangle.java b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Rectangle.java new file mode 100644 index 0000000..716027a --- /dev/null +++ b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Rectangle.java @@ -0,0 +1,26 @@ +package nl.oose.dea.drawing.withlsp; + +public class Rectangle implements Shape { + private int height; + private int width; + + public void setHeight(int height) { + this.height = height; + } + + public int getHeight() { + return height; + } + + public void setWidth(int width) { + this.width = width; + } + + public int getWidth() { + return width; + } + + public int area() { + return width * height; + } +} diff --git a/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Shape.java b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Shape.java new file mode 100644 index 0000000..b66211a --- /dev/null +++ b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Shape.java @@ -0,0 +1,5 @@ +package nl.oose.dea.drawing.withlsp; + +public interface Shape { + int area(); +} diff --git a/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Square.java b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Square.java new file mode 100644 index 0000000..2b2edaa --- /dev/null +++ b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Square.java @@ -0,0 +1,17 @@ +package nl.oose.dea.drawing.withlsp; + +public class Square implements Shape { + private int sideLength; + + public void setSideLength(int sideLength) { + this.sideLength = sideLength; + } + + public int getSideLength() { + return sideLength; + } + + public int area() { + return sideLength * sideLength; + } +} diff --git a/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Triangle.java b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Triangle.java new file mode 100644 index 0000000..9ea2354 --- /dev/null +++ b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withlsp/Triangle.java @@ -0,0 +1,27 @@ +package nl.oose.dea.drawing.withlsp; + +public class Triangle implements Shape { + private int base; + private int height; + + public void setBase(int base) { + this.base = base; + } + + public int getBase() { + return base; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getHeight() { + return height; + } + + @Override + public int area() { + return (base * height) / 2; + } +} diff --git a/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/AreaCalculator.java b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/AreaCalculator.java new file mode 100644 index 0000000..5b61fc2 --- /dev/null +++ b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/AreaCalculator.java @@ -0,0 +1,18 @@ +package nl.oose.dea.drawing.withoutlsp; + +/** + * We use overloading here to create area-implementations for different types. + * + * It violates a principle called "Tell, don't ask". Rectangle and Square both + * need to expose their properties to calculate the area. We're going to refactor that, because we + * decoupled behaviour from state which is not a good example of information hiding. + */ +public class AreaCalculator { + public static int calulateArea(Rectangle rectangle) { + return rectangle.getHeight() * rectangle.getWidth(); + } + + public static int calulateArea(Square square) { + return square.getHeight() * square.getHeight(); + } +} diff --git a/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Rectangle.java b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Rectangle.java new file mode 100644 index 0000000..2612d48 --- /dev/null +++ b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Rectangle.java @@ -0,0 +1,22 @@ +package nl.oose.dea.drawing.withoutlsp; + +public class Rectangle { + private int height; + private int width; + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } +} diff --git a/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Square.java b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Square.java new file mode 100644 index 0000000..0e35a3f --- /dev/null +++ b/exercises/solid/3.LSP/src/main/java/nl/oose/dea/drawing/withoutlsp/Square.java @@ -0,0 +1,15 @@ +package nl.oose.dea.drawing.withoutlsp; + +public class Square extends Rectangle { + @Override + public void setWidth(int width) { + super.setWidth(width); + super.setHeight(width); + } + + @Override + public void setHeight(int height) { + super.setHeight(height); + super.setWidth(height); + } +} diff --git a/exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withlsp/AreaCalculationTest.java b/exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withlsp/AreaCalculationTest.java new file mode 100644 index 0000000..6307966 --- /dev/null +++ b/exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withlsp/AreaCalculationTest.java @@ -0,0 +1,58 @@ +package nl.oose.dea.drawing.withlsp; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class AreaCalculationTest { + + @Test + public void sixFor2x3Rectangle() throws Exception { + Rectangle rectangle = new Rectangle(); + rectangle.setHeight(2); + rectangle.setWidth(3); + + assertEquals(6, rectangle.area()); + } + + @Test + public void nineFor3x3Square() throws Exception { + Square square = new Square(); + square.setSideLength(3); + + assertEquals(9, square.area()); + } + + @Test + public void twentyFor4x5RectangleFromSquare() throws Exception { + final Rectangle rectangle = new Rectangle(); + rectangle.setWidth(5); + rectangle.setHeight(4); + + final Square square = new Square(); + square.setSideLength(3); + + final Triangle triangle = new Triangle(); + triangle.setBase(10); + triangle.setHeight(5); + + List shapes = new ArrayList() {{ + add(rectangle); + add(square); + add(triangle); + }}; + + List areas = new ArrayList(); + for(Shape shape:shapes) + { + areas.add(shape.area()); + } + + assertEquals(20, areas.get(0).intValue()); + assertEquals(9, areas.get(1).intValue()); + assertEquals(25, areas.get(2).intValue()); + } +} \ No newline at end of file diff --git a/exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withoutlsp/AreaCalculatorTest.java b/exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withoutlsp/AreaCalculatorTest.java new file mode 100644 index 0000000..f5d583d --- /dev/null +++ b/exercises/solid/3.LSP/src/test/java/nl/oose/dea/drawing/withoutlsp/AreaCalculatorTest.java @@ -0,0 +1,39 @@ +package nl.oose.dea.drawing.withoutlsp; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class AreaCalculatorTest { + + @Test + public void sixFor2x3Rectangle() throws Exception { + Rectangle rectangle = new Rectangle(); + rectangle.setHeight(2); + rectangle.setWidth(3); + + assertEquals(6, AreaCalculator.calulateArea(rectangle)); + } + + @Test + public void nineFor3x3Square() throws Exception { + Square square = new Square(); + square.setHeight(3); + + assertEquals(9, AreaCalculator.calulateArea(square)); + } + + @Test + /** + * Isn't supposed to fail, but it does because we did not apply the LSP-principle + */ + public void twentyFor4x5RectangleFromSquare() throws Exception { + Rectangle square = new Square(); + square.setHeight(5); + square.setWidth(4); + + // It _is_ a Rectangle so we may expect the behaviour of the Rectangle class! + assertEquals(20, AreaCalculator.calulateArea(square)); + // Apparently Square does not have the same behaviour as Rectangle, so it is _not_ a Rectangle + } +} \ No newline at end of file diff --git a/exercises/solid/4.ISP/ISP.iml b/exercises/solid/4.ISP/ISP.iml new file mode 100644 index 0000000..e04193a --- /dev/null +++ b/exercises/solid/4.ISP/ISP.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exercises/solid/4.ISP/README.md b/exercises/solid/4.ISP/README.md new file mode 100644 index 0000000..98a4c1f --- /dev/null +++ b/exercises/solid/4.ISP/README.md @@ -0,0 +1,6 @@ +This project contains an implementation of a CartRepository with two packages: +* nl.oose.dea.orderservice.withoutisp contains classes and test cases without the ISP principle applied +* nl.oose.dea.orderservice.withisp contains some classes and test cases that guide you to apply the ISP + +First read the sourcecode without ISP and run the test cases (comment the testcases with ISP applied to compile and run these testcases). +Second, read the test cases with ISP and (re)create the correct classes and interfaces so the unit tests all pass. diff --git a/exercises/solid/4.ISP/pom.xml b/exercises/solid/4.ISP/pom.xml new file mode 100644 index 0000000..b4edc3f --- /dev/null +++ b/exercises/solid/4.ISP/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + nl.oose.dea + ISP-Example + 1.0-SNAPSHOT + + + junit + junit + 4.11 + + + + \ No newline at end of file diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Cart.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Cart.java new file mode 100644 index 0000000..94a9779 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Cart.java @@ -0,0 +1,28 @@ +package nl.oose.dea.orderservice.withisp; + +public class Cart { + private int id; + private Item[] items; + private String customerName; + private int billingTotal; + private String customerEmail; + + public Cart(String customerName, String customerEmail, Item[] items, int billingTotal){ + this.customerName = customerName; + this.customerEmail = customerEmail; + this.items = items; + this.billingTotal = billingTotal; + } + + public Item[] getItems() { + return items; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/CartRepository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/CartRepository.java new file mode 100644 index 0000000..45ab1e8 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/CartRepository.java @@ -0,0 +1,4 @@ +package nl.oose.dea.orderservice.withisp; + +public interface CartRepository extends Repository{ +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/FullAccessClient.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/FullAccessClient.java new file mode 100644 index 0000000..6528fc6 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/FullAccessClient.java @@ -0,0 +1,17 @@ +package nl.oose.dea.orderservice.withisp; + +public class FullAccessClient { + private CartRepository cartRepository; + + public FullAccessClient(CartRepository cartRepository) + { + + this.cartRepository = cartRepository; + } + + public int saveCurrentCart(Cart c) + { + cartRepository.add(c); + return c.getId(); + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/InMemoryCartRepository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/InMemoryCartRepository.java new file mode 100644 index 0000000..97019ec --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/InMemoryCartRepository.java @@ -0,0 +1,40 @@ +package nl.oose.dea.orderservice.withisp; + +import java.util.ArrayList; +import java.util.List; + +public class InMemoryCartRepository implements CartRepository { + private List carts = new ArrayList(); + private int lastId = 0; + + @Override + public void add(Cart cart) { + cart.setId(lastId); + carts.add(cart); + lastId++; + } + + @Override + public void update(Cart updatedCart) { + carts.set(carts.indexOf(find(updatedCart.getId())), updatedCart); + } + + @Override + public void remove(Cart cart) { + carts.remove(cart); + } + + @Override + public List list() { + return carts; + } + + @Override + public Cart find(int cartId) { + for(Cart cart:carts) + { + if (cart.getId() == cartId) return cart; + } + return null; + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Item.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Item.java new file mode 100644 index 0000000..908b50b --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Item.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withisp; + +public class Item { + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/ReadOnlyAccessClient.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/ReadOnlyAccessClient.java new file mode 100644 index 0000000..36e8396 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/ReadOnlyAccessClient.java @@ -0,0 +1,26 @@ +package nl.oose.dea.orderservice.withisp; + +import java.util.List; + +public class ReadOnlyAccessClient { + + private CartRepository cartRepository; + + public ReadOnlyAccessClient(CartRepository cartRepository) + { + this.cartRepository = cartRepository; + } + + public int getNumberOfCarts() + { + return cartRepository.list().size(); + } + + public void deleteAll() + { + List carts = cartRepository.list(); + for (int i = carts.size() - 1; i >= 0; i--) { + cartRepository.remove(carts.get(i)); + } + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Repository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Repository.java new file mode 100644 index 0000000..6eb398a --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withisp/Repository.java @@ -0,0 +1,15 @@ +package nl.oose.dea.orderservice.withisp; + +import java.util.List; + +public interface Repository { + void add(T entity); + + void update(T updatedEntity); + + void remove(T entity); + + List list(); + + T find(int id); +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Cart.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Cart.java new file mode 100644 index 0000000..e4db132 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Cart.java @@ -0,0 +1,28 @@ +package nl.oose.dea.orderservice.withoutisp; + +public class Cart { + private int id; + private nl.oose.dea.orderservice.withoutisp.Item[] items; + private String customerName; + private int billingTotal; + private String customerEmail; + + public Cart(String customerName, String customerEmail, Item[] items, int billingTotal){ + this.customerName = customerName; + this.customerEmail = customerEmail; + this.items = items; + this.billingTotal = billingTotal; + } + + public Item[] getItems() { + return items; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/CartRepository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/CartRepository.java new file mode 100644 index 0000000..8c0c950 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/CartRepository.java @@ -0,0 +1,8 @@ +package nl.oose.dea.orderservice.withoutisp; + +/** + * Also possible to implement also ReadOnlyCartRepository and remove the extends relationship + * between Repository and ReadOnlyRepository + */ +public interface CartRepository extends Repository { +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/FullAccessClient.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/FullAccessClient.java new file mode 100644 index 0000000..8a329b1 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/FullAccessClient.java @@ -0,0 +1,17 @@ +package nl.oose.dea.orderservice.withoutisp; + +public class FullAccessClient { + private CartRepository cartRepository; + + public FullAccessClient(nl.oose.dea.orderservice.withoutisp.CartRepository cartRepository) + { + + this.cartRepository = cartRepository; + } + + public int saveCurrentCart(Cart c) + { + cartRepository.add(c); + return c.getId(); + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/InMemoryCartRepository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/InMemoryCartRepository.java new file mode 100644 index 0000000..88f83ce --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/InMemoryCartRepository.java @@ -0,0 +1,40 @@ +package nl.oose.dea.orderservice.withoutisp; + +import java.util.ArrayList; +import java.util.List; + +public class InMemoryCartRepository implements CartRepository, ReadOnlyCartRepository { + private List carts = new ArrayList(); + private int lastId = 0; + + @Override + public void add(Cart cart) { + cart.setId(lastId); + carts.add(cart); + lastId++; + } + + @Override + public void update(Cart updatedCart) { + carts.set(carts.indexOf(find(updatedCart.getId())), updatedCart); + } + + @Override + public void remove(nl.oose.dea.orderservice.withoutisp.Cart cart) { + carts.remove(cart); + } + + @Override + public List list() { + return carts; + } + + @Override + public nl.oose.dea.orderservice.withoutisp.Cart find(int cartId) { + for(Cart cart:carts) + { + if (cart.getId() == cartId) return cart; + } + return null; + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Item.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Item.java new file mode 100644 index 0000000..b8bb0d2 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Item.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withoutisp; + +public class Item { + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyAccessClient.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyAccessClient.java new file mode 100644 index 0000000..78a8cd7 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyAccessClient.java @@ -0,0 +1,17 @@ +package nl.oose.dea.orderservice.withoutisp; + +public class ReadOnlyAccessClient { + + private ReadOnlyCartRepository cartRepository; + + public ReadOnlyAccessClient(ReadOnlyCartRepository cartRepository) + { + this.cartRepository = cartRepository; + } + + public int getNumberOfCarts() + { + return cartRepository.list().size(); + } + +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyCartRepository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyCartRepository.java new file mode 100644 index 0000000..e458628 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyCartRepository.java @@ -0,0 +1,4 @@ +package nl.oose.dea.orderservice.withoutisp; + +public interface ReadOnlyCartRepository extends ReadOnlyRepository{ +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyRepository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyRepository.java new file mode 100644 index 0000000..adee4d5 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/ReadOnlyRepository.java @@ -0,0 +1,9 @@ +package nl.oose.dea.orderservice.withoutisp; + +import java.util.List; + +public interface ReadOnlyRepository { + List list(); + + T find(int id); +} diff --git a/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Repository.java b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Repository.java new file mode 100644 index 0000000..36dfc28 --- /dev/null +++ b/exercises/solid/4.ISP/src/main/java/nl/oose/dea/orderservice/withoutisp/Repository.java @@ -0,0 +1,9 @@ +package nl.oose.dea.orderservice.withoutisp; + +public interface Repository extends ReadOnlyRepository{ + void add(T entity); + + void update(T updatedEntity); + + void remove(T entity); +} diff --git a/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/CartRepositoryTest.java b/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/CartRepositoryTest.java new file mode 100644 index 0000000..2a1b4ac --- /dev/null +++ b/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/CartRepositoryTest.java @@ -0,0 +1,46 @@ +package nl.oose.dea.orderservice.withisp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CartRepositoryTest { + private CartRepository cartRepository; + private Cart c1; + + @Before + public void setUp() throws Exception { + cartRepository = new InMemoryCartRepository(); + c1 = new Cart("OOSE1", "oose1@gmail.com", new Item[]{ new Item("Frikandel", 10)}, 100); + } + + @Test + public void basicFlowOfAllRepositoryActions() + { + cartRepository.add(c1); + assertNotNull(cartRepository.find(0)); + assertEquals(1, cartRepository.list().size()); + c1.getItems()[0].quantity = 2; + cartRepository.update(c1); + assertEquals(2, cartRepository.find(0).getItems()[0].quantity); + cartRepository.remove(c1); + assertEquals(0, cartRepository.list().size()); + } + + @Test + public void cannotFindAnythingInAnEmptyRepository() + { + assertNull(cartRepository.find(0)); + assertEquals(0, cartRepository.list().size()); + } + + @Test + public void cannotFindWhenUsingAWrongIdInAFilledRepository() + { + cartRepository.add(c1); + assertNull(cartRepository.find(1)); + assertEquals(1, cartRepository.list().size()); + } + +} \ No newline at end of file diff --git a/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/ClientsTest.java b/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/ClientsTest.java new file mode 100644 index 0000000..5fabdc6 --- /dev/null +++ b/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withisp/ClientsTest.java @@ -0,0 +1,33 @@ +package nl.oose.dea.orderservice.withisp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ClientsTest { + private ReadOnlyAccessClient readOnlyAccessClient; + private FullAccessClient fullAccessClient; + + @Before + public void setUp() throws Exception { + CartRepository cartRepository = new InMemoryCartRepository(); + readOnlyAccessClient = new ReadOnlyAccessClient(cartRepository); + fullAccessClient = new FullAccessClient(cartRepository); + } + + @Test + public void whenBothClientsShareTheSameDataSourceBothHaveTheSameAccess() + { + Cart c1 = new Cart("OOSE1", "oose1@gmail.com", new Item[]{ new Item("Frikandel", 10)}, 100); + Cart c2 = new Cart("OOSE2", "oose2@gmail.com", new Item[]{ new Item("Bamihap", 10)}, 150); + + assertEquals(0, fullAccessClient.saveCurrentCart(c1)); + assertEquals(1, fullAccessClient.saveCurrentCart(c2)); + + assertEquals(2, readOnlyAccessClient.getNumberOfCarts()); + + readOnlyAccessClient.deleteAll(); + assertEquals(0, readOnlyAccessClient.getNumberOfCarts()); + } +} \ No newline at end of file diff --git a/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withoutisp/ClientsTest.java b/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withoutisp/ClientsTest.java new file mode 100644 index 0000000..e8c23a3 --- /dev/null +++ b/exercises/solid/4.ISP/src/test/java/nl/oose/dea/orderservice/withoutisp/ClientsTest.java @@ -0,0 +1,36 @@ +package nl.oose.dea.orderservice.withoutisp; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ClientsTest { + private ReadOnlyAccessClient readOnlyAccessClient; + private FullAccessClient fullAccessClient; + + @Before + public void setUp() throws Exception { + CartRepository cartRepository = new InMemoryCartRepository(); + ReadOnlyCartRepository readOnlyCartRepository = (ReadOnlyCartRepository)cartRepository; + + readOnlyAccessClient = new ReadOnlyAccessClient(readOnlyCartRepository); + fullAccessClient = new FullAccessClient(cartRepository); + } + + @Test + public void whenBothClientsShareTheSameDataSourceBothHaveTheSameAccess() + { + Cart c1 = new Cart("OOSE1", "oose1@gmail.com", new Item[]{ new Item("Frikandel", 10)}, 100); + Cart c2 = new Cart("OOSE2", "oose2@gmail.com", new Item[]{ new Item("Bamihap", 10)}, 150); + + assertEquals(0, fullAccessClient.saveCurrentCart(c1)); + assertEquals(1, fullAccessClient.saveCurrentCart(c2)); + + + // Try to uncomment and try call the delete method just like in the old version + // readOnlyAccessClient.deleteAll(); + + assertEquals(2, readOnlyAccessClient.getNumberOfCarts()); + } +} \ No newline at end of file diff --git a/exercises/solid/5.DIP/DIP-Example.iml b/exercises/solid/5.DIP/DIP-Example.iml new file mode 100644 index 0000000..9d24d22 --- /dev/null +++ b/exercises/solid/5.DIP/DIP-Example.iml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exercises/solid/5.DIP/README.md b/exercises/solid/5.DIP/README.md new file mode 100644 index 0000000..a0367c1 --- /dev/null +++ b/exercises/solid/5.DIP/README.md @@ -0,0 +1,6 @@ +This project contains an implementation of an OrderService with two packages: +* nl.oose.dea.orderservice.withoutdip contains classes and test cases without the DIP principle applied +* nl.oose.dea.orderservice.withdip contains some classes and test cases that guide you to apply the DIP + +First read the sourcecode without DIP and run the test cases (comment the testcases with DIP applied to compile and run these testcases). +Second, read the test cases with DIP and (re)create the correct classes and interfaces so the unit tests all pass. \ No newline at end of file diff --git a/exercises/solid/5.DIP/pom.xml b/exercises/solid/5.DIP/pom.xml new file mode 100644 index 0000000..9a2d26a --- /dev/null +++ b/exercises/solid/5.DIP/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + nl.oose.dea + DIP-Example + 1.0-SNAPSHOT + + + + junit + junit + 4.11 + + + javax.mail + mail + 1.4 + + + org.mockito + mockito-all + 1.9.5 + + + org.springframework + spring-beans + 3.2.4.RELEASE + + + org.springframework + spring-core + 3.2.4.RELEASE + + + org.springframework + spring-context + 3.2.4.RELEASE + + + \ No newline at end of file diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CafetariaReservationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CafetariaReservationService.java new file mode 100644 index 0000000..600703b --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CafetariaReservationService.java @@ -0,0 +1,23 @@ +package nl.oose.dea.orderservice.withdip; + +public class CafetariaReservationService implements ReservationService { + private InventorySystem inventorySystem = new InventorySystem(); + + @Override + public void reserveInventory(Cart cart) { + for(Item item : cart.getItems()) + { + try { + inventorySystem.reserve(item.sku, item.quantity); + } catch(InsufficientInventoryException insufficientInventoryException) + { + throw new OrderException("Insufficient inventory for item " + item.sku, insufficientInventoryException); + } + } + } + + @Override + public boolean isOnStock(String product, int amount) { + return inventorySystem.isOnStock(product, amount); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Cart.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Cart.java new file mode 100644 index 0000000..25d03a3 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Cart.java @@ -0,0 +1,31 @@ +package nl.oose.dea.orderservice.withdip; + +public class Cart { + private Item[] items; + private String customerName; + private int amount; + private String customerEmail; + + public Cart(String customerName, String customerEmail, Item[] items, int amount){ + this.customerName = customerName; + this.customerEmail = customerEmail; + this.items = items; + this.amount = amount; + } + + public Item[] getItems() { + return items; + } + + public String getCustomerName() { + return customerName; + } + + public int getBillingTotal() { + return amount; + } + + public String getCustomerEmail() { + return customerEmail; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CartFactory.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CartFactory.java new file mode 100644 index 0000000..bfce114 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/CartFactory.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withdip; + +public class CartFactory { + public Cart create() { + return new Cart("OOSE", "oose@gmail.com", new Item[] { new Item("Frikandel", 10)}, 100); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InsufficientInventoryException.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InsufficientInventoryException.java new file mode 100644 index 0000000..37e8970 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InsufficientInventoryException.java @@ -0,0 +1,4 @@ +package nl.oose.dea.orderservice.withdip; + +public class InsufficientInventoryException extends Exception{ +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InventorySystem.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InventorySystem.java new file mode 100644 index 0000000..204cb72 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/InventorySystem.java @@ -0,0 +1,26 @@ +package nl.oose.dea.orderservice.withdip; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +public class InventorySystem { + private Logger logger = Logger.getLogger(getClass().getName()); + + private Map inventory = new HashMap() {{ + put("Frikandel", 20); + put("Bamihap", 25); + put("Mexicano", 50); + }}; + + public void reserve(String sku, int quantity) throws InsufficientInventoryException { + if (isOnStock(sku, quantity)) + inventory.put(sku, inventory.get(sku) - quantity); + else throw new InsufficientInventoryException(); + logger.info("There is still " + inventory.get(sku) + " of " + sku + " left in inventory"); + } + + public boolean isOnStock(String sku, int quantity) { + return inventory.get(sku) >= quantity; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Item.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Item.java new file mode 100644 index 0000000..87343d8 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Item.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withdip; + +public class Item { + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/LoggingPaymentProcessor.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/LoggingPaymentProcessor.java new file mode 100644 index 0000000..6edb9c1 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/LoggingPaymentProcessor.java @@ -0,0 +1,10 @@ +package nl.oose.dea.orderservice.withdip; + +public class LoggingPaymentProcessor implements PaymentProcessor { + private PaymentGateway paymentGateway = new PaymentGateway(); + + @Override + public boolean chargeCard(PaymentDetails paymentDetails, Cart cart) { + return paymentGateway.charge(cart.getBillingTotal(), cart.getCustomerName(), paymentDetails.cardNumber); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailClient.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailClient.java new file mode 100644 index 0000000..deea186 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailClient.java @@ -0,0 +1,43 @@ +package nl.oose.dea.orderservice.withdip; + +import javax.mail.*; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.Properties; + +public class MailClient { + // This MailClient actually works when you have a valid GMail user + private final static String USERNAME = ""; + private final static String PASSWORD = ""; + + public void send(String message, String customerEmail) throws MessagingException { + Transport.send(prepareMessage(message, customerEmail)); + } + + private Message prepareMessage(String messageBody, String customerEmail) throws MessagingException { + Message message = new MimeMessage(setGoogleSession(prepareSMTPProperties())); + message.setFrom(new InternetAddress(USERNAME)); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(customerEmail)); + message.setSubject(messageBody); + message.setText(messageBody); + return message; + } + + private Properties prepareSMTPProperties() { + Properties props = new Properties(); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.smtp.host", "smtp.gmail.com"); + props.put("mail.smtp.port", "587"); + return props; + } + + private Session setGoogleSession(Properties props) { + return Session.getInstance(props, + new Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(USERNAME, PASSWORD); + } + }); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailNotificationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailNotificationService.java new file mode 100644 index 0000000..00c0f44 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/MailNotificationService.java @@ -0,0 +1,19 @@ +package nl.oose.dea.orderservice.withdip; + +import javax.mail.MessagingException; +import java.util.logging.Logger; + +public class MailNotificationService implements NotificationService { + private Logger logger = Logger.getLogger(getClass().getName()); + + @Override + public void notifyCustomer(Cart cart) { + MailClient mailClient = new MailClient(); + try { + mailClient.send("Your order is processed.", cart.getCustomerEmail()); + } catch (MessagingException e) { + logger.severe(e.getMessage()); + throw new OrderException("Cannot send mail to " + cart.getCustomerEmail(), e); + } + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/NotificationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/NotificationService.java new file mode 100644 index 0000000..643e1cd --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/NotificationService.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withdip; + +public interface NotificationService { + void notifyCustomer(Cart cart); +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OnlineOrder.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OnlineOrder.java new file mode 100644 index 0000000..e522fcf --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OnlineOrder.java @@ -0,0 +1,26 @@ +package nl.oose.dea.orderservice.withdip; + +public class OnlineOrder extends Order { + private final PaymentDetails paymentDetails; + private final PaymentProcessor paymentProcessor; + private final NotificationService notificationService; + private final ReservationService reservationService; + + public OnlineOrder(Cart cart, PaymentDetails paymentDetails, PaymentProcessor paymentProcessor, NotificationService notificationService, ReservationService reservationService) { + super(cart); + this.paymentDetails = paymentDetails; + this.paymentProcessor = paymentProcessor; + this.notificationService = notificationService; + this.reservationService = reservationService; + } + + @Override + public void checkout() { + if (paymentProcessor.chargeCard(paymentDetails, cart)) { + reservationService.reserveInventory(cart); + notificationService.notifyCustomer(cart); + } + super.checkout(); + } + +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Order.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Order.java new file mode 100644 index 0000000..fb17d99 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/Order.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withdip; + +public abstract class Order { + protected Cart cart; + + public Order(Cart cart) + { + this.cart = cart; + } + + public void checkout() {} +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderException.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderException.java new file mode 100644 index 0000000..e076758 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderException.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withdip; + +public class OrderException extends RuntimeException { + public OrderException(String message, Exception originalException) { + super(message, originalException); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderServiceSpringBootstrap.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderServiceSpringBootstrap.java new file mode 100644 index 0000000..d6e6fb7 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/OrderServiceSpringBootstrap.java @@ -0,0 +1,19 @@ +package nl.oose.dea.orderservice.withdip; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class OrderServiceSpringBootstrap { + /** + * First define all "beans" in the applicationContext.xml and its dependencies. After that + * call getBean on the factory and call the checkout method + * + * @param args + */ + public static void main(String[] args) { + // We use the XML based version of Spring so our code will not be polluted with framework-dependent annotations + ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml"); + OnlineOrder onlineOrder = (OnlineOrder) factory.getBean("onlineOrder"); + onlineOrder.checkout(); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCashOrder.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCashOrder.java new file mode 100644 index 0000000..b1f08a6 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCashOrder.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withdip; + +public class POSCashOrder extends Order { + public POSCashOrder(Cart cart) { + super(cart); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCreditOrder.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCreditOrder.java new file mode 100644 index 0000000..b24567a --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/POSCreditOrder.java @@ -0,0 +1,19 @@ +package nl.oose.dea.orderservice.withdip; + +public class POSCreditOrder extends Order { + private final PaymentDetails paymentDetails; + private final PaymentProcessor paymentProcessor; + + public POSCreditOrder(Cart cart, PaymentDetails paymentDetails, PaymentProcessor paymentProcessor) { + super(cart); + this.paymentDetails = paymentDetails; + this.paymentProcessor = paymentProcessor; + } + + @Override + public void checkout() { + paymentProcessor.chargeCard(paymentDetails, cart); + super.checkout(); + } + +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetails.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetails.java new file mode 100644 index 0000000..abf4471 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetails.java @@ -0,0 +1,6 @@ +package nl.oose.dea.orderservice.withdip; + +public class PaymentDetails { + public PaymentMethod paymentMethod; + public int cardNumber; +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetailsFactory.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetailsFactory.java new file mode 100644 index 0000000..c36e0d2 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentDetailsFactory.java @@ -0,0 +1,10 @@ +package nl.oose.dea.orderservice.withdip; + +public class PaymentDetailsFactory { + public PaymentDetails create() { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + paymentDetails.cardNumber = 1234; + return paymentDetails; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentGateway.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentGateway.java new file mode 100644 index 0000000..41f8fb9 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentGateway.java @@ -0,0 +1,13 @@ +package nl.oose.dea.orderservice.withdip; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class PaymentGateway { + private Logger logger = Logger.getLogger(getClass().getName()); + + public boolean charge(int amount, String customerName, int cardNumber) { + logger.log(Level.INFO, "Charged " + customerName + " EUR " + amount + " on card: " + cardNumber); + return true; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentMethod.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentMethod.java new file mode 100644 index 0000000..404d6a2 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentMethod.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withdip; + +public enum PaymentMethod { + CreditCard +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentProcessor.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentProcessor.java new file mode 100644 index 0000000..e725f0d --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/PaymentProcessor.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withdip; + +public interface PaymentProcessor { + boolean chargeCard(PaymentDetails paymentDetails, Cart cart); +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/ReservationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/ReservationService.java new file mode 100644 index 0000000..cd0c1aa --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withdip/ReservationService.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withdip; + +public interface ReservationService { + void reserveInventory(Cart cart); + + boolean isOnStock(String product, int amount); +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/CafetariaReservationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/CafetariaReservationService.java new file mode 100644 index 0000000..854f2d2 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/CafetariaReservationService.java @@ -0,0 +1,23 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class CafetariaReservationService implements ReservationService { + private InventorySystem inventorySystem = new InventorySystem(); + + @Override + public void reserveInventory(Cart cart) { + for(Item item : cart.getItems()) + { + try { + inventorySystem.reserve(item.sku, item.quantity); + } catch(InsufficientInventoryException insufficientInventoryException) + { + throw new OrderException("Insufficient inventory for item " + item.sku, insufficientInventoryException); + } + } + } + + @Override + public boolean isOnStock(String product, int amount) { + return inventorySystem.isOnStock(product, amount); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Cart.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Cart.java new file mode 100644 index 0000000..0f122df --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Cart.java @@ -0,0 +1,31 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class Cart { + private Item[] items; + private String customerName; + private int amount; + private String customerEmail; + + public Cart(String customerName, String customerEmail, Item[] items, int amount){ + this.customerName = customerName; + this.customerEmail = customerEmail; + this.items = items; + this.amount = amount; + } + + public Item[] getItems() { + return items; + } + + public String getCustomerName() { + return customerName; + } + + public int getBillingTotal() { + return amount; + } + + public String getCustomerEmail() { + return customerEmail; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InsufficientInventoryException.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InsufficientInventoryException.java new file mode 100644 index 0000000..4b7de96 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InsufficientInventoryException.java @@ -0,0 +1,4 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class InsufficientInventoryException extends Exception{ +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InventorySystem.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InventorySystem.java new file mode 100644 index 0000000..e8a74cb --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/InventorySystem.java @@ -0,0 +1,26 @@ +package nl.oose.dea.orderservice.withoutdip; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +public class InventorySystem { + private Logger logger = Logger.getLogger(getClass().getName()); + + private Map inventory = new HashMap() {{ + put("Frikandel", 20); + put("Bamihap", 25); + put("Mexicano", 50); + }}; + + public void reserve(String sku, int quantity) throws InsufficientInventoryException { + if (isOnStock(sku, quantity)) + inventory.put(sku, inventory.get(sku) - quantity); + else throw new InsufficientInventoryException(); + logger.info("There is still " + inventory.get(sku) + " of " + sku + " left in inventory"); + } + + public boolean isOnStock(String sku, int quantity) { + return inventory.get(sku) >= quantity; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Item.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Item.java new file mode 100644 index 0000000..f20da8f --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Item.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class Item { + public String sku; + public int quantity; + + public Item(String sku, int quantity) + { + this.sku = sku; + this.quantity = quantity; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/LoggingPaymentProcessor.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/LoggingPaymentProcessor.java new file mode 100644 index 0000000..39aa87c --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/LoggingPaymentProcessor.java @@ -0,0 +1,10 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class LoggingPaymentProcessor implements PaymentProcessor { + private PaymentGateway paymentGateway = new PaymentGateway(); + + @Override + public boolean chargeCard(PaymentDetails paymentDetails, Cart cart) { + return paymentGateway.charge(cart.getBillingTotal(), cart.getCustomerName(), paymentDetails.cardNumber); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailClient.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailClient.java new file mode 100644 index 0000000..085d70c --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailClient.java @@ -0,0 +1,43 @@ +package nl.oose.dea.orderservice.withoutdip; + +import javax.mail.*; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.Properties; + +public class MailClient { + // This MailClient actually works when you have a valid GMail user + private final static String USERNAME = ""; + private final static String PASSWORD = ""; + + public void send(String message, String customerEmail) throws MessagingException { + Transport.send(prepareMessage(message, customerEmail)); + } + + private Message prepareMessage(String messageBody, String customerEmail) throws MessagingException { + Message message = new MimeMessage(setGoogleSession(prepareSMTPProperties())); + message.setFrom(new InternetAddress(USERNAME)); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(customerEmail)); + message.setSubject(messageBody); + message.setText(messageBody); + return message; + } + + private Properties prepareSMTPProperties() { + Properties props = new Properties(); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.smtp.host", "smtp.gmail.com"); + props.put("mail.smtp.port", "587"); + return props; + } + + private Session setGoogleSession(Properties props) { + return Session.getInstance(props, + new Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(USERNAME, PASSWORD); + } + }); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailNotificationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailNotificationService.java new file mode 100644 index 0000000..c4067a5 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/MailNotificationService.java @@ -0,0 +1,19 @@ +package nl.oose.dea.orderservice.withoutdip; + +import javax.mail.MessagingException; +import java.util.logging.Logger; + +public class MailNotificationService implements NotificationService { + private Logger logger = Logger.getLogger(getClass().getName()); + + @Override + public void notifyCustomer(Cart cart) { + MailClient mailClient = new MailClient(); + try { + mailClient.send("Your order is processed.", cart.getCustomerEmail()); + } catch (MessagingException e) { + logger.severe(e.getMessage()); + throw new OrderException("Cannot send mail to " + cart.getCustomerEmail(), e); + } + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/NotificationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/NotificationService.java new file mode 100644 index 0000000..b829041 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/NotificationService.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withoutdip; + +public interface NotificationService { + void notifyCustomer(Cart cart); +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OnlineOrder.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OnlineOrder.java new file mode 100644 index 0000000..1c5f527 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OnlineOrder.java @@ -0,0 +1,22 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class OnlineOrder extends Order { + private final PaymentDetails paymentDetails; + + private PaymentProcessor paymentProcessor = new LoggingPaymentProcessor(); + private NotificationService notificationService = new MailNotificationService(); + private ReservationService reservationService = new CafetariaReservationService(); + + public OnlineOrder(Cart cart, PaymentDetails paymentDetails) { + super(cart); + this.paymentDetails = paymentDetails; + } + + @Override + public void checkout() { + paymentProcessor.chargeCard(paymentDetails, cart); + reservationService.reserveInventory(cart); + notificationService.notifyCustomer(cart); + super.checkout(); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Order.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Order.java new file mode 100644 index 0000000..1d7bb9d --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/Order.java @@ -0,0 +1,12 @@ +package nl.oose.dea.orderservice.withoutdip; + +public abstract class Order { + protected Cart cart; + + public Order(Cart cart) + { + this.cart = cart; + } + + public void checkout() {} +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OrderException.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OrderException.java new file mode 100644 index 0000000..34f505f --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/OrderException.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class OrderException extends RuntimeException { + public OrderException(String message, Exception originalException) { + super(message, originalException); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCashOrder.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCashOrder.java new file mode 100644 index 0000000..0b780db --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCashOrder.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class POSCashOrder extends Order { + public POSCashOrder(Cart cart) { + super(cart); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrder.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrder.java new file mode 100644 index 0000000..05dd452 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrder.java @@ -0,0 +1,17 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class POSCreditOrder extends Order { + private final PaymentDetails paymentDetails; + private PaymentProcessor paymentProcessor = new LoggingPaymentProcessor(); + + public POSCreditOrder(Cart cart, PaymentDetails paymentDetails) { + super(cart); + this.paymentDetails = paymentDetails; + } + + @Override + public void checkout() { + paymentProcessor.chargeCard(paymentDetails, cart); + super.checkout(); + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentDetails.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentDetails.java new file mode 100644 index 0000000..57f63d3 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentDetails.java @@ -0,0 +1,6 @@ +package nl.oose.dea.orderservice.withoutdip; + +public class PaymentDetails { + public PaymentMethod paymentMethod; + public int cardNumber; +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentGateway.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentGateway.java new file mode 100644 index 0000000..fbece51 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentGateway.java @@ -0,0 +1,13 @@ +package nl.oose.dea.orderservice.withoutdip; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class PaymentGateway { + private Logger logger = Logger.getLogger(getClass().getName()); + + public boolean charge(int amount, String customerName, int cardNumber) { + logger.log(Level.INFO, "Charged " + customerName + " EUR " + amount + " on card: " + cardNumber); + return true; + } +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentMethod.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentMethod.java new file mode 100644 index 0000000..a47b6f7 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentMethod.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withoutdip; + +public enum PaymentMethod { + CreditCard +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessor.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessor.java new file mode 100644 index 0000000..ff18cbb --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessor.java @@ -0,0 +1,5 @@ +package nl.oose.dea.orderservice.withoutdip; + +public interface PaymentProcessor { + boolean chargeCard(PaymentDetails paymentDetails, Cart cart); +} diff --git a/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/ReservationService.java b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/ReservationService.java new file mode 100644 index 0000000..7122906 --- /dev/null +++ b/exercises/solid/5.DIP/src/main/java/nl/oose/dea/orderservice/withoutdip/ReservationService.java @@ -0,0 +1,7 @@ +package nl.oose.dea.orderservice.withoutdip; + +public interface ReservationService { + void reserveInventory(Cart cart); + + boolean isOnStock(String product, int amount); +} diff --git a/exercises/solid/5.DIP/src/main/resources/applicationContext.xml b/exercises/solid/5.DIP/src/main/resources/applicationContext.xml new file mode 100644 index 0000000..f779daf --- /dev/null +++ b/exercises/solid/5.DIP/src/main/resources/applicationContext.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/NotificationServiceTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/NotificationServiceTest.java new file mode 100644 index 0000000..2659823 --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/NotificationServiceTest.java @@ -0,0 +1,21 @@ +package nl.oose.dea.orderservice.withdip; + +import nl.oose.dea.orderservice.withoutdip.Cart; +import nl.oose.dea.orderservice.withoutdip.Item; +import nl.oose.dea.orderservice.withoutdip.MailNotificationService; +import nl.oose.dea.orderservice.withoutdip.NotificationService; +import nl.oose.dea.orderservice.withoutdip.OrderException; +import org.junit.Test; + +public class NotificationServiceTest { + + @Test(expected = OrderException.class) + public void youCannotSendAMailUsingGmailWithAnEmptyUsernameAndPass() throws Exception { + NotificationService notificationService = new MailNotificationService(); + notificationService.notifyCustomer(createCart()); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{}, 0); + } +} \ No newline at end of file diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/OnlineOrderTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/OnlineOrderTest.java new file mode 100644 index 0000000..0c5446b --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/OnlineOrderTest.java @@ -0,0 +1,56 @@ +package nl.oose.dea.orderservice.withdip; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +public class OnlineOrderTest { + private PaymentProcessor paymentProcessor = mock(PaymentProcessor.class); + private NotificationService notificationService = mock(NotificationService.class); + private ReservationService reservationService = mock(ReservationService.class); + + @Test + public void checkoutOnlineOrder() + { + // Create an order and pass all its dependencies. For unit tesing purposes we inject mock objects for the dependencies + Cart cart = createCart(); + PaymentDetails paymentDetails = createPaymentDetails(); + Order order = new OnlineOrder(cart, paymentDetails, setupPaymentProcessor(), setupNotificationService(), setupReservationService()); + order.checkout(); + + InOrder inOrder = inOrder(paymentProcessor, reservationService, notificationService); + inOrder.verify(paymentProcessor, times(1)).chargeCard(paymentDetails, cart); + inOrder.verify(reservationService, times(1)).reserveInventory(cart); + inOrder.verify(reservationService, never()).isOnStock(anyString(), anyInt()); + inOrder.verify(notificationService, times(1)).notifyCustomer(cart); + } + + private ReservationService setupReservationService() { + return reservationService; + } + + private NotificationService setupNotificationService() { + return notificationService; + } + + private PaymentProcessor setupPaymentProcessor() { + // always return true, enough for now + when(paymentProcessor.chargeCard(any(PaymentDetails.class), any(Cart.class))).thenReturn(true); + return paymentProcessor; + } + + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } + + private PaymentDetails createPaymentDetails() + { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + paymentDetails.cardNumber = 1234; + return paymentDetails; + } +} diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCashOrderTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCashOrderTest.java new file mode 100644 index 0000000..daf3b19 --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCashOrderTest.java @@ -0,0 +1,17 @@ +package nl.oose.dea.orderservice.withdip; + +import org.junit.Test; + +public class POSCashOrderTest { + @Test + public void checkoutOnlineOrder() + { + // Hah, still works, POSCashOrder has no other dependencies + Order order = new POSCashOrder(createCart()); + order.checkout(); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } +} diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCreditOrderTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCreditOrderTest.java new file mode 100644 index 0000000..28cd68c --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/POSCreditOrderTest.java @@ -0,0 +1,39 @@ +package nl.oose.dea.orderservice.withdip; + +import org.junit.Test; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +public class POSCreditOrderTest { + + private PaymentProcessor paymentProcessor = mock(PaymentProcessor.class); + + @Test + public void checkoutOnlineOrder() + { + // Create an order and pass all its dependencies. For unit tesing purposes we inject mock objects for the dependencies + Order order = new POSCreditOrder(createCart(), createPaymentDetails(), setupPaymentProcessor()); + order.checkout(); + + verify(paymentProcessor, times(1)).chargeCard(any(PaymentDetails.class), any(Cart.class)); + } + + private PaymentProcessor setupPaymentProcessor() { + // always return true, enough for now + when(paymentProcessor.chargeCard(any(PaymentDetails.class), any(Cart.class))).thenReturn(true); + return paymentProcessor; + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } + + private PaymentDetails createPaymentDetails() + { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + paymentDetails.cardNumber = 1234; + return paymentDetails; + } +} diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/PaymentProcessorTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/PaymentProcessorTest.java new file mode 100644 index 0000000..2df62db --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/PaymentProcessorTest.java @@ -0,0 +1,31 @@ +package nl.oose.dea.orderservice.withdip; + +import nl.oose.dea.orderservice.withoutdip.Cart; +import nl.oose.dea.orderservice.withoutdip.Item; +import nl.oose.dea.orderservice.withoutdip.LoggingPaymentProcessor; +import nl.oose.dea.orderservice.withoutdip.PaymentDetails; +import nl.oose.dea.orderservice.withoutdip.PaymentMethod; +import nl.oose.dea.orderservice.withoutdip.PaymentProcessor; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class PaymentProcessorTest { + + @Test + public void testCharge() throws Exception { + PaymentProcessor paymentProcessor = new LoggingPaymentProcessor(); + assertTrue(paymentProcessor.chargeCard(createPaymentDetails(),createCart())); + } + + private Cart createCart() { + return new Cart("OOSE", "oose@gmail.com", new Item[]{}, 0); + } + + private PaymentDetails createPaymentDetails() { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.cardNumber = 1234; + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + return paymentDetails; + } +} \ No newline at end of file diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/ReservationServiceTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/ReservationServiceTest.java new file mode 100644 index 0000000..d4c3619 --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withdip/ReservationServiceTest.java @@ -0,0 +1,40 @@ +package nl.oose.dea.orderservice.withdip; + +import nl.oose.dea.orderservice.withoutdip.CafetariaReservationService; +import nl.oose.dea.orderservice.withoutdip.Cart; +import nl.oose.dea.orderservice.withoutdip.Item; +import nl.oose.dea.orderservice.withoutdip.OrderException; +import nl.oose.dea.orderservice.withoutdip.ReservationService; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class ReservationServiceTest { + private ReservationService reservationService; + + @Before + public void setUp() + { + reservationService = new CafetariaReservationService(); + } + + @Test + public void buyAllFrikandellen() throws Exception { + reservationService.reserveInventory(createCartWithSufficientInventory()); + assertTrue(reservationService.isOnStock("Frikandel", 0)); + } + + private Cart createCartWithSufficientInventory() { + return new Cart("OOSE","oose@gmail.com", new Item[] { new Item("Frikandel", 20) }, 50); + } + + private Cart createCartWithInsufficientInventory() { + return new Cart("OOSE","oose@gmail.com", new Item[] { new Item("Frikandel", 21) }, 50); + } + + @Test(expected = OrderException.class) + public void youCannotBuyMoreThanAvailableInTheInventory() throws Exception { + reservationService.reserveInventory(createCartWithInsufficientInventory()); + } +} \ No newline at end of file diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/NotificationServiceTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/NotificationServiceTest.java new file mode 100644 index 0000000..f0feff0 --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/NotificationServiceTest.java @@ -0,0 +1,16 @@ +package nl.oose.dea.orderservice.withoutdip; + +import org.junit.Test; + +public class NotificationServiceTest { + + @Test(expected = OrderException.class) + public void youCannotSendAMailUsingGmailWithAnEmptyUsernameAndPass() throws Exception { + NotificationService notificationService = new MailNotificationService(); + notificationService.notifyCustomer(createCart()); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{}, 0); + } +} \ No newline at end of file diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/OnlineOrderTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/OnlineOrderTest.java new file mode 100644 index 0000000..2172321 --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/OnlineOrderTest.java @@ -0,0 +1,24 @@ +package nl.oose.dea.orderservice.withoutdip; + +import org.junit.Test; + +public class OnlineOrderTest { + @Test(expected = OrderException.class) + public void checkoutOnlineOrder() + { + Order order = new OnlineOrder(createCart(), createPaymentDetails()); + order.checkout(); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } + + private PaymentDetails createPaymentDetails() + { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + paymentDetails.cardNumber = 1234; + return paymentDetails; + } +} diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCashOrderTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCashOrderTest.java new file mode 100644 index 0000000..7d930e9 --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCashOrderTest.java @@ -0,0 +1,16 @@ +package nl.oose.dea.orderservice.withoutdip; + +import org.junit.Test; + +public class POSCashOrderTest { + @Test + public void checkoutOnlineOrder() + { + Order order = new POSCashOrder(createCart()); + order.checkout(); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } +} diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrderTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrderTest.java new file mode 100644 index 0000000..cd487dd --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/POSCreditOrderTest.java @@ -0,0 +1,24 @@ +package nl.oose.dea.orderservice.withoutdip; + +import org.junit.Test; + +public class POSCreditOrderTest { + @Test + public void checkoutOnlineOrder() + { + Order order = new POSCreditOrder(createCart(), createPaymentDetails()); + order.checkout(); + } + + private Cart createCart() { + return new Cart("Test", "oose@gmail.com", new Item[]{ new Item("Frikandel", 20)}, 100); + } + + private PaymentDetails createPaymentDetails() + { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + paymentDetails.cardNumber = 1234; + return paymentDetails; + } +} diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessorTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessorTest.java new file mode 100644 index 0000000..e105eec --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/PaymentProcessorTest.java @@ -0,0 +1,25 @@ +package nl.oose.dea.orderservice.withoutdip; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class PaymentProcessorTest { + + @Test + public void testCharge() throws Exception { + PaymentProcessor paymentProcessor = new LoggingPaymentProcessor(); + assertTrue(paymentProcessor.chargeCard(createPaymentDetails(),createCart())); + } + + private Cart createCart() { + return new Cart("OOSE", "oose@gmail.com", new Item[]{}, 0); + } + + private PaymentDetails createPaymentDetails() { + PaymentDetails paymentDetails = new PaymentDetails(); + paymentDetails.cardNumber = 1234; + paymentDetails.paymentMethod = PaymentMethod.CreditCard; + return paymentDetails; + } +} \ No newline at end of file diff --git a/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/ReservationServiceTest.java b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/ReservationServiceTest.java new file mode 100644 index 0000000..eb39d2b --- /dev/null +++ b/exercises/solid/5.DIP/src/test/java/nl/oose/dea/orderservice/withoutdip/ReservationServiceTest.java @@ -0,0 +1,35 @@ +package nl.oose.dea.orderservice.withoutdip; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class ReservationServiceTest { + private ReservationService reservationService; + + @Before + public void setUp() + { + reservationService = new CafetariaReservationService(); + } + + @Test + public void buyAllFrikandellen() throws Exception { + reservationService.reserveInventory(createCartWithSufficientInventory()); + assertTrue(reservationService.isOnStock("Frikandel", 0)); + } + + private Cart createCartWithSufficientInventory() { + return new Cart("OOSE","oose@gmail.com", new Item[] { new Item("Frikandel", 20) }, 50); + } + + private Cart createCartWithInsufficientInventory() { + return new Cart("OOSE","oose@gmail.com", new Item[] { new Item("Frikandel", 21) }, 50); + } + + @Test(expected = OrderException.class) + public void youCannotBuyMoreThanAvailableInTheInventory() throws Exception { + reservationService.reserveInventory(createCartWithInsufficientInventory()); + } +} \ No newline at end of file From 3604054a21fccfc38efe1e2994598137ea42477d Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Thu, 5 Mar 2015 16:06:45 +0100 Subject: [PATCH 13/45] Added class diagram --- exercises/koenenkramers/KoenenKramers.png | Bin 0 -> 110024 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 exercises/koenenkramers/KoenenKramers.png diff --git a/exercises/koenenkramers/KoenenKramers.png b/exercises/koenenkramers/KoenenKramers.png new file mode 100644 index 0000000000000000000000000000000000000000..9910a515e6bc2ee5ba60313ee168f3f038c79e92 GIT binary patch literal 110024 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 EA2HjM761SM literal 0 HcmV?d00001 From de0215ae874c8dba5afda60d6a1db950cd675555 Mon Sep 17 00:00:00 2001 From: Rody Middelkoop Date: Tue, 21 Apr 2015 00:09:04 +0200 Subject: [PATCH 14/45] Moved files to separate directory --- .../maven/AndroidManifest.xml | 20 ++++ android-deckard-unittest/maven/LICENSE.txt | 21 ++++ android-deckard-unittest/maven/README.md | 54 +++++++++ android-deckard-unittest/maven/pom.xml | 103 ++++++++++++++++++ .../maven/res/layout/deckard.xml | 19 ++++ .../example/activity/ButtonClickHandler.java | 37 +++++++ .../com/example/activity/DeckardActivity.java | 28 +++++ .../example/activity/DeckardApplication.java | 26 +++++ .../com/example/activity/DeckardModule.java | 25 +++++ .../example/activity/IButtonClickHandler.java | 19 ++++ .../com/example/activity/IDataController.java | 17 +++ .../example/activity/RestDataController.java | 22 ++++ .../activity/ButtonClickHandlerTest.java | 38 +++++++ .../example/activity/DeckardActivityTest.java | 47 ++++++++ .../com/example/activity/TestGuiceModule.java | 65 +++++++++++ 15 files changed, 541 insertions(+) create mode 100644 android-deckard-unittest/maven/AndroidManifest.xml create mode 100644 android-deckard-unittest/maven/LICENSE.txt create mode 100644 android-deckard-unittest/maven/README.md create mode 100644 android-deckard-unittest/maven/pom.xml create mode 100644 android-deckard-unittest/maven/res/layout/deckard.xml create mode 100644 android-deckard-unittest/maven/src/main/java/com/example/activity/ButtonClickHandler.java create mode 100644 android-deckard-unittest/maven/src/main/java/com/example/activity/DeckardActivity.java create mode 100644 android-deckard-unittest/maven/src/main/java/com/example/activity/DeckardApplication.java create mode 100644 android-deckard-unittest/maven/src/main/java/com/example/activity/DeckardModule.java create mode 100644 android-deckard-unittest/maven/src/main/java/com/example/activity/IButtonClickHandler.java create mode 100644 android-deckard-unittest/maven/src/main/java/com/example/activity/IDataController.java create mode 100644 android-deckard-unittest/maven/src/main/java/com/example/activity/RestDataController.java create mode 100644 android-deckard-unittest/maven/src/test/java/com/example/activity/ButtonClickHandlerTest.java create mode 100644 android-deckard-unittest/maven/src/test/java/com/example/activity/DeckardActivityTest.java create mode 100644 android-deckard-unittest/maven/src/test/java/com/example/activity/TestGuiceModule.java diff --git a/android-deckard-unittest/maven/AndroidManifest.xml b/android-deckard-unittest/maven/AndroidManifest.xml new file mode 100644 index 0000000..0ef4888 --- /dev/null +++ b/android-deckard-unittest/maven/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android-deckard-unittest/maven/LICENSE.txt b/android-deckard-unittest/maven/LICENSE.txt new file mode 100644 index 0000000..c1f1ac8 --- /dev/null +++ b/android-deckard-unittest/maven/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2013 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/android-deckard-unittest/maven/README.md b/android-deckard-unittest/maven/README.md new file mode 100644 index 0000000..a1eb23c --- /dev/null +++ b/android-deckard-unittest/maven/README.md @@ -0,0 +1,54 @@ +# Deckard + +Deckard is the simplest possible Android project that uses Robolectric for testing and Maven to build. It has one Activity (with an empty layout), and a Robolectric test that creates that Activity. Deckard also imports seamlessly into IntelliJ, due to IntelliJ's support for Maven. Just import the pom.xml. + +This project has been created using Deckard and shows how Robolectric can be used to perform unittesting. Support for Roboguice and Mockito was added in the pom.xml and the example to show the advantage of DI. + +The TestGuiceModule was originally written by Moritz Post: http://eclipsesource.com/blogs/2012/09/25/advanced-android-testing-with-roboguice-and-robolectric/. + +## Setup + +*Note: These instructions assume you have a Java 1.6 [JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html) installed.* + +To start a new Android project: + +1. Install the [Android SDK](http://developer.android.com/sdk/index.html). On Mac OS X with [Homebrew](http://brew.sh/) just run: + ```bash + brew install android-sdk + ``` + +2. Set your `ANDROID_HOME` environment variable to `/usr/local/Cellar/android-sdk/`. + +3. Run the Android SDK GUI and install API 18 and any other APIs you might need. You can start the GUI like so: + ```bash + android + ``` +4. Install Maven if you haven't already (run `mvn` to check). On OS X (as before) this is easiest with [Homebrew](http://brew.sh/) (unfortunately we have to install Maven 3.0.x as Maven 3.1.x is currently buggy on OS X): + ```bash + brew install homebrew/versions/maven30 + ``` + +5. Use [Maven Android SDK Deployer](https://github.com/mosabua/maven-android-sdk-deployer) to maven-ize the Android SDK: + ```bash + git clone https://github.com/mosabua/maven-android-sdk-deployer.git + (cd maven-android-sdk-deployer && mvn install -P 4.3) + ``` + +6. Download the DDA-examples project from GitHub: + ```bash + wget https://github.com/ddoa/dda-code-examples/archive/master.zip + unzip master.zip + cp android-deckard-unittest my-new-project + ``` + +7. In the project directory you should be able to run the tests: + ```bash + cd my-new-project + mvn clean test + ``` + +8. Optionally, import the project into IntelliJ (or Eclipse) by selecting 'Import Project' in IntelliJ and selecting the project's `pom.xml`. When prompted to pick an SDK you just need to select the Android SDK home and your JDK. + +9. Change the names of things from 'Deckard' to whatever is appropriate for your project. Package name, classes, and the AndroidManifest are good places to start. + +10. Build an app. Win. diff --git a/android-deckard-unittest/maven/pom.xml b/android-deckard-unittest/maven/pom.xml new file mode 100644 index 0000000..1b5ac90 --- /dev/null +++ b/android-deckard-unittest/maven/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + + com.example + deckard + 1.0.0-SNAPSHOT + apk + Deckard + Who is the replicant here? + + + + robojuice + http://repo1.maven.org/maven2/org/roboguice/roboguice/ + + + + + + + junit + junit + 4.8.2 + test + + + + org.mockito + mockito-core + 1.9.5 + test + + + + + org.robolectric + robolectric + 2.2 + test + + + + android + android + 4.3_r2 + provided + + + + + org.roboguice + roboguice + 2.0 + + + com.google.inject + guice + 3.0 + no_aop + + + + + + ${project.artifactId} + + + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + 3.6.1 + + + + 18 + + true + + true + + + org.apache.maven.plugins + maven-surefire-plugin + 2.6 + + + **/Test*.java + + -Xmx1024m + + + + + diff --git a/android-deckard-unittest/maven/res/layout/deckard.xml b/android-deckard-unittest/maven/res/layout/deckard.xml new file mode 100644 index 0000000..2495ca0 --- /dev/null +++ b/android-deckard-unittest/maven/res/layout/deckard.xml @@ -0,0 +1,19 @@ + + + +