diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..fb19b513 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.svn/ +bin/ +target/ \ No newline at end of file diff --git a/jdom2.format/.classpath b/HF_DP/.classpath similarity index 84% rename from jdom2.format/.classpath rename to HF_DP/.classpath index b86a1c21..fb565a58 100644 --- a/jdom2.format/.classpath +++ b/HF_DP/.classpath @@ -2,6 +2,5 @@ - diff --git a/jdom2.format/.project b/HF_DP/.project similarity index 92% rename from jdom2.format/.project rename to HF_DP/.project index 25379c48..6985aeb6 100644 --- a/jdom2.format/.project +++ b/HF_DP/.project @@ -1,6 +1,6 @@ - jdom2.format + HF_DP diff --git a/HF_DP/.settings/org.eclipse.jdt.core.prefs b/HF_DP/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..f42de363 --- /dev/null +++ b/HF_DP/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/HF_DP/src/headfirst/adapter/ducks/Duck.java b/HF_DP/src/headfirst/adapter/ducks/Duck.java new file mode 100644 index 00000000..2333e6c2 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/Duck.java @@ -0,0 +1,6 @@ +package headfirst.adapter.ducks; + +public interface Duck { + public void quack(); + public void fly(); +} diff --git a/HF_DP/src/headfirst/adapter/ducks/DuckAdapter.java b/HF_DP/src/headfirst/adapter/ducks/DuckAdapter.java new file mode 100644 index 00000000..508d0eaf --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/DuckAdapter.java @@ -0,0 +1,22 @@ +package headfirst.adapter.ducks; +import java.util.Random; + +public class DuckAdapter implements Turkey { + Duck duck; + Random rand; + + public DuckAdapter(Duck duck) { + this.duck = duck; + rand = new Random(); + } + + public void gobble() { + duck.quack(); + } + + public void fly() { + if (rand.nextInt(5) == 0) { + duck.fly(); + } + } +} diff --git a/HF_DP/src/headfirst/adapter/ducks/DuckTestDrive.java b/HF_DP/src/headfirst/adapter/ducks/DuckTestDrive.java new file mode 100644 index 00000000..24914691 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/DuckTestDrive.java @@ -0,0 +1,25 @@ +package headfirst.adapter.ducks; + +public class DuckTestDrive { + public static void main(String[] args) { + MallardDuck duck = new MallardDuck(); + + WildTurkey turkey = new WildTurkey(); + Duck turkeyAdapter = new TurkeyAdapter(turkey); + + System.out.println("The Turkey says..."); + turkey.gobble(); + turkey.fly(); + + System.out.println("\nThe Duck says..."); + testDuck(duck); + + System.out.println("\nThe TurkeyAdapter says..."); + testDuck(turkeyAdapter); + } + + static void testDuck(Duck duck) { + duck.quack(); + duck.fly(); + } +} diff --git a/HF_DP/src/headfirst/adapter/ducks/MallardDuck.java b/HF_DP/src/headfirst/adapter/ducks/MallardDuck.java new file mode 100644 index 00000000..2c3d4546 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/MallardDuck.java @@ -0,0 +1,11 @@ +package headfirst.adapter.ducks; + +public class MallardDuck implements Duck { + public void quack() { + System.out.println("Quack"); + } + + public void fly() { + System.out.println("I'm flying"); + } +} diff --git a/HF_DP/src/headfirst/adapter/ducks/Turkey.java b/HF_DP/src/headfirst/adapter/ducks/Turkey.java new file mode 100644 index 00000000..3deb96b0 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/Turkey.java @@ -0,0 +1,6 @@ +package headfirst.adapter.ducks; + +public interface Turkey { + public void gobble(); + public void fly(); +} diff --git a/HF_DP/src/headfirst/adapter/ducks/TurkeyAdapter.java b/HF_DP/src/headfirst/adapter/ducks/TurkeyAdapter.java new file mode 100644 index 00000000..51bd81d8 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/TurkeyAdapter.java @@ -0,0 +1,19 @@ +package headfirst.adapter.ducks; + +public class TurkeyAdapter implements Duck { + Turkey turkey; + + public TurkeyAdapter(Turkey turkey) { + this.turkey = turkey; + } + + public void quack() { + turkey.gobble(); + } + + public void fly() { + for(int i=0; i < 5; i++) { + turkey.fly(); + } + } +} diff --git a/HF_DP/src/headfirst/adapter/ducks/TurkeyTestDrive.java b/HF_DP/src/headfirst/adapter/ducks/TurkeyTestDrive.java new file mode 100644 index 00000000..8bb2038c --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/TurkeyTestDrive.java @@ -0,0 +1,14 @@ +package headfirst.adapter.ducks; + +public class TurkeyTestDrive { + public static void main(String[] args) { + MallardDuck duck = new MallardDuck(); + Turkey duckAdapter = new DuckAdapter(duck); + + for(int i=0;i<10;i++) { + System.out.println("The DuckAdapter says..."); + duckAdapter.gobble(); + duckAdapter.fly(); + } + } +} diff --git a/HF_DP/src/headfirst/adapter/ducks/WildTurkey.java b/HF_DP/src/headfirst/adapter/ducks/WildTurkey.java new file mode 100644 index 00000000..6dddec67 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/ducks/WildTurkey.java @@ -0,0 +1,11 @@ +package headfirst.adapter.ducks; + +public class WildTurkey implements Turkey { + public void gobble() { + System.out.println("Gobble gobble"); + } + + public void fly() { + System.out.println("I'm flying a short distance"); + } +} diff --git a/HF_DP/src/headfirst/adapter/iterenum/EI.java b/HF_DP/src/headfirst/adapter/iterenum/EI.java new file mode 100644 index 00000000..2c70c3cc --- /dev/null +++ b/HF_DP/src/headfirst/adapter/iterenum/EI.java @@ -0,0 +1,17 @@ +package headfirst.adapter.iterenum; + +import java.util.*; + +public class EI { + public static void main (String args[]) { + Vector v = new Vector(Arrays.asList(args)); + Enumeration enumeration = v.elements(); + while (enumeration.hasMoreElements()) { + System.out.println(enumeration.nextElement()); + } + Iterator iterator = v.iterator(); + while (iterator.hasNext()) { + System.out.println(iterator.next()); + } + } +} diff --git a/HF_DP/src/headfirst/adapter/iterenum/EnumerationIterator.java b/HF_DP/src/headfirst/adapter/iterenum/EnumerationIterator.java new file mode 100644 index 00000000..09e7d4f3 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/iterenum/EnumerationIterator.java @@ -0,0 +1,23 @@ +package headfirst.adapter.iterenum; + +import java.util.*; + +public class EnumerationIterator implements Iterator { + Enumeration enumeration; + + public EnumerationIterator(Enumeration enumeration) { + this.enumeration = enumeration; + } + + public boolean hasNext() { + return enumeration.hasMoreElements(); + } + + public Object next() { + return enumeration.nextElement(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/HF_DP/src/headfirst/adapter/iterenum/EnumerationIteratorTestDrive.java b/HF_DP/src/headfirst/adapter/iterenum/EnumerationIteratorTestDrive.java new file mode 100644 index 00000000..6d39c713 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/iterenum/EnumerationIteratorTestDrive.java @@ -0,0 +1,13 @@ +package headfirst.adapter.iterenum; + +import java.util.*; + +public class EnumerationIteratorTestDrive { + public static void main (String args[]) { + Vector v = new Vector(Arrays.asList(args)); + Iterator iterator = new EnumerationIterator(v.elements()); + while (iterator.hasNext()) { + System.out.println(iterator.next()); + } + } +} diff --git a/HF_DP/src/headfirst/adapter/iterenum/IteratorEnumeration.java b/HF_DP/src/headfirst/adapter/iterenum/IteratorEnumeration.java new file mode 100644 index 00000000..a9a4e692 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/iterenum/IteratorEnumeration.java @@ -0,0 +1,19 @@ +package headfirst.adapter.iterenum; + +import java.util.*; + +public class IteratorEnumeration implements Enumeration { + Iterator iterator; + + public IteratorEnumeration(Iterator iterator) { + this.iterator = iterator; + } + + public boolean hasMoreElements() { + return iterator.hasNext(); + } + + public Object nextElement() { + return iterator.next(); + } +} diff --git a/HF_DP/src/headfirst/adapter/iterenum/IteratorEnumerationTestDrive.java b/HF_DP/src/headfirst/adapter/iterenum/IteratorEnumerationTestDrive.java new file mode 100644 index 00000000..9c886f75 --- /dev/null +++ b/HF_DP/src/headfirst/adapter/iterenum/IteratorEnumerationTestDrive.java @@ -0,0 +1,13 @@ +package headfirst.adapter.iterenum; + +import java.util.*; + +public class IteratorEnumerationTestDrive { + public static void main (String args[]) { + ArrayList l = new ArrayList(Arrays.asList(args)); + Enumeration enumeration = new IteratorEnumeration(l.iterator()); + while (enumeration.hasMoreElements()) { + System.out.println(enumeration.nextElement()); + } + } +} diff --git a/HF_DP/src/headfirst/combined/djview/BPMObserver.java b/HF_DP/src/headfirst/combined/djview/BPMObserver.java new file mode 100644 index 00000000..0099177c --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/BPMObserver.java @@ -0,0 +1,5 @@ +package headfirst.combined.djview; + +public interface BPMObserver { + void updateBPM(); +} diff --git a/HF_DP/src/headfirst/combined/djview/BeatBar.java b/HF_DP/src/headfirst/combined/djview/BeatBar.java new file mode 100644 index 00000000..47f2b1d4 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/BeatBar.java @@ -0,0 +1,28 @@ +package headfirst.combined.djview; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +public class BeatBar extends JProgressBar implements Runnable { + JProgressBar progressBar; + Thread thread; + + public BeatBar() { + thread = new Thread(this); + setMaximum(100); + thread.start(); + } + + public void run() { + for(;;) { + int value = getValue(); + value = (int)(value * .75); + setValue(value); + repaint(); + try { + Thread.sleep(50); + } catch (Exception e) {}; + } + } +} diff --git a/HF_DP/src/headfirst/combined/djview/BeatController.java b/HF_DP/src/headfirst/combined/djview/BeatController.java new file mode 100644 index 00000000..ec78fb55 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/BeatController.java @@ -0,0 +1,42 @@ +package headfirst.combined.djview; + +public class BeatController implements ControllerInterface { + BeatModelInterface model; + DJView view; + + public BeatController(BeatModelInterface model) { + this.model = model; + view = new DJView(this, model); + view.createView(); + view.createControls(); + view.disableStopMenuItem(); + view.enableStartMenuItem(); + model.initialize(); + } + + public void start() { + model.on(); + view.disableStartMenuItem(); + view.enableStopMenuItem(); + } + + public void stop() { + model.off(); + view.disableStopMenuItem(); + view.enableStartMenuItem(); + } + + public void increaseBPM() { + int bpm = model.getBPM(); + model.setBPM(bpm + 1); + } + + public void decreaseBPM() { + int bpm = model.getBPM(); + model.setBPM(bpm - 1); + } + + public void setBPM(int bpm) { + model.setBPM(bpm); + } +} diff --git a/HF_DP/src/headfirst/combined/djview/BeatModel.java b/HF_DP/src/headfirst/combined/djview/BeatModel.java new file mode 100644 index 00000000..fb29e0b5 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/BeatModel.java @@ -0,0 +1,144 @@ +package headfirst.combined.djview; + +import javax.sound.midi.*; +import java.util.*; + +public class BeatModel implements BeatModelInterface, MetaEventListener { + Sequencer sequencer; + ArrayList beatObservers = new ArrayList(); + ArrayList bpmObservers = new ArrayList(); + int bpm = 90; + Sequence sequence; + Track track; + + public void initialize() { + setUpMidi(); + buildTrackAndStart(); + } + + public void on() { + sequencer.start(); + setBPM(90); + } + + public void off() { + setBPM(0); + sequencer.stop(); + } + + public void setBPM(int bpm) { + this.bpm = bpm; + sequencer.setTempoInBPM(getBPM()); + notifyBPMObservers(); + } + + public int getBPM() { + return bpm; + } + + void beatEvent() { + notifyBeatObservers(); + } + + + public void registerObserver(BeatObserver o) { + beatObservers.add(o); + } + + public void notifyBeatObservers() { + for(int i = 0; i < beatObservers.size(); i++) { + BeatObserver observer = (BeatObserver)beatObservers.get(i); + observer.updateBeat(); + } + } + + public void registerObserver(BPMObserver o) { + bpmObservers.add(o); + } + + public void notifyBPMObservers() { + for(int i = 0; i < bpmObservers.size(); i++) { + BPMObserver observer = (BPMObserver)bpmObservers.get(i); + observer.updateBPM(); + } + } + + + public void removeObserver(BeatObserver o) { + int i = beatObservers.indexOf(o); + if (i >= 0) { + beatObservers.remove(i); + } + } + + + + public void removeObserver(BPMObserver o) { + int i = bpmObservers.indexOf(o); + if (i >= 0) { + bpmObservers.remove(i); + } + } + + + public void meta(MetaMessage message) { + if (message.getType() == 47) { + beatEvent(); + sequencer.start(); + setBPM(getBPM()); + } + } + + public void setUpMidi() { + try { + sequencer = MidiSystem.getSequencer(); + sequencer.open(); + sequencer.addMetaEventListener(this); + sequence = new Sequence(Sequence.PPQ,4); + track = sequence.createTrack(); + sequencer.setTempoInBPM(getBPM()); + } catch(Exception e) { + e.printStackTrace(); + } + } + + public void buildTrackAndStart() { + int[] trackList = {35, 0, 46, 0}; + + sequence.deleteTrack(null); + track = sequence.createTrack(); + + makeTracks(trackList); + track.add(makeEvent(192,9,1,0,4)); + try { + sequencer.setSequence(sequence); + } catch(Exception e) { + e.printStackTrace(); + } + } + + public void makeTracks(int[] list) { + + for (int i = 0; i < list.length; i++) { + int key = list[i]; + + if (key != 0) { + track.add(makeEvent(144,9,key, 100, i)); + track.add(makeEvent(128,9,key, 100, i+1)); + } + } + } + + public MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) { + MidiEvent event = null; + try { + ShortMessage a = new ShortMessage(); + a.setMessage(comd, chan, one, two); + event = new MidiEvent(a, tick); + + } catch(Exception e) { + e.printStackTrace(); + } + return event; + } +} diff --git a/HF_DP/src/headfirst/combined/djview/BeatModelInterface.java b/HF_DP/src/headfirst/combined/djview/BeatModelInterface.java new file mode 100644 index 00000000..5daab8a6 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/BeatModelInterface.java @@ -0,0 +1,21 @@ +package headfirst.combined.djview; + +public interface BeatModelInterface { + void initialize(); + + void on(); + + void off(); + + void setBPM(int bpm); + + int getBPM(); + + void registerObserver(BeatObserver o); + + void removeObserver(BeatObserver o); + + void registerObserver(BPMObserver o); + + void removeObserver(BPMObserver o); +} diff --git a/HF_DP/src/headfirst/combined/djview/BeatObserver.java b/HF_DP/src/headfirst/combined/djview/BeatObserver.java new file mode 100644 index 00000000..da1de895 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/BeatObserver.java @@ -0,0 +1,5 @@ +package headfirst.combined.djview; + +public interface BeatObserver { + void updateBeat(); +} diff --git a/HF_DP/src/headfirst/combined/djview/ControllerInterface.java b/HF_DP/src/headfirst/combined/djview/ControllerInterface.java new file mode 100644 index 00000000..20d554b1 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/ControllerInterface.java @@ -0,0 +1,9 @@ +package headfirst.combined.djview; + +public interface ControllerInterface { + void start(); + void stop(); + void increaseBPM(); + void decreaseBPM(); + void setBPM(int bpm); +} diff --git a/HF_DP/src/headfirst/combined/djview/DJTestDrive.java b/HF_DP/src/headfirst/combined/djview/DJTestDrive.java new file mode 100644 index 00000000..bcc45797 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/DJTestDrive.java @@ -0,0 +1,9 @@ +package headfirst.combined.djview; + +public class DJTestDrive { + + public static void main (String[] args) { + BeatModelInterface model = new BeatModel(); + ControllerInterface controller = new BeatController(model); + } +} diff --git a/HF_DP/src/headfirst/combined/djview/DJView.java b/HF_DP/src/headfirst/combined/djview/DJView.java new file mode 100644 index 00000000..051e33a0 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/DJView.java @@ -0,0 +1,169 @@ +package headfirst.combined.djview; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +public class DJView implements ActionListener, BeatObserver, BPMObserver { + BeatModelInterface model; + ControllerInterface controller; + JFrame viewFrame; + JPanel viewPanel; + BeatBar beatBar; + JLabel bpmOutputLabel; + JFrame controlFrame; + JPanel controlPanel; + JLabel bpmLabel; + JTextField bpmTextField; + JButton setBPMButton; + JButton increaseBPMButton; + JButton decreaseBPMButton; + JMenuBar menuBar; + JMenu menu; + JMenuItem startMenuItem; + JMenuItem stopMenuItem; + + public DJView(ControllerInterface controller, BeatModelInterface model) { + this.controller = controller; + this.model = model; + model.registerObserver((BeatObserver)this); + model.registerObserver((BPMObserver)this); + } + + public void createView() { + // Create all Swing components here + viewPanel = new JPanel(new GridLayout(1, 2)); + viewFrame = new JFrame("View"); + viewFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + viewFrame.setSize(new Dimension(100, 80)); + bpmOutputLabel = new JLabel("offline", SwingConstants.CENTER); + beatBar = new BeatBar(); + beatBar.setValue(0); + JPanel bpmPanel = new JPanel(new GridLayout(2, 1)); + bpmPanel.add(beatBar); + bpmPanel.add(bpmOutputLabel); + viewPanel.add(bpmPanel); + viewFrame.getContentPane().add(viewPanel, BorderLayout.CENTER); + viewFrame.pack(); + viewFrame.setVisible(true); + } + + + public void createControls() { + // Create all Swing components here + JFrame.setDefaultLookAndFeelDecorated(true); + controlFrame = new JFrame("Control"); + controlFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + controlFrame.setSize(new Dimension(100, 80)); + + controlPanel = new JPanel(new GridLayout(1, 2)); + + menuBar = new JMenuBar(); + menu = new JMenu("DJ Control"); + startMenuItem = new JMenuItem("Start"); + menu.add(startMenuItem); + startMenuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + controller.start(); + } + }); + stopMenuItem = new JMenuItem("Stop"); + menu.add(stopMenuItem); + stopMenuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + controller.stop(); + } + }); + JMenuItem exit = new JMenuItem("Quit"); + exit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + System.exit(0); + } + }); + + menu.add(exit); + menuBar.add(menu); + controlFrame.setJMenuBar(menuBar); + + bpmTextField = new JTextField(2); + bpmLabel = new JLabel("Enter BPM:", SwingConstants.RIGHT); + setBPMButton = new JButton("Set"); + setBPMButton.setSize(new Dimension(10,40)); + increaseBPMButton = new JButton(">>"); + decreaseBPMButton = new JButton("<<"); + setBPMButton.addActionListener(this); + increaseBPMButton.addActionListener(this); + decreaseBPMButton.addActionListener(this); + + JPanel buttonPanel = new JPanel(new GridLayout(1, 2)); + + buttonPanel.add(decreaseBPMButton); + buttonPanel.add(increaseBPMButton); + + JPanel enterPanel = new JPanel(new GridLayout(1, 2)); + enterPanel.add(bpmLabel); + enterPanel.add(bpmTextField); + JPanel insideControlPanel = new JPanel(new GridLayout(3, 1)); + insideControlPanel.add(enterPanel); + insideControlPanel.add(setBPMButton); + insideControlPanel.add(buttonPanel); + controlPanel.add(insideControlPanel); + + bpmLabel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); + bpmOutputLabel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); + + controlFrame.getRootPane().setDefaultButton(setBPMButton); + controlFrame.getContentPane().add(controlPanel, BorderLayout.CENTER); + + controlFrame.pack(); + controlFrame.setVisible(true); + } + + public void enableStopMenuItem() { + stopMenuItem.setEnabled(true); + } + + public void disableStopMenuItem() { + stopMenuItem.setEnabled(false); + } + + public void enableStartMenuItem() { + startMenuItem.setEnabled(true); + } + + public void disableStartMenuItem() { + startMenuItem.setEnabled(false); + } + + public void actionPerformed(ActionEvent event) { + if (event.getSource() == setBPMButton) { + int bpm = Integer.parseInt(bpmTextField.getText()); + controller.setBPM(bpm); + } else if (event.getSource() == increaseBPMButton) { + controller.increaseBPM(); + } else if (event.getSource() == decreaseBPMButton) { + controller.decreaseBPM(); + } + } + + public void updateBPM() { + if (model != null) { + int bpm = model.getBPM(); + if (bpm == 0) { + if (bpmOutputLabel != null) { + bpmOutputLabel.setText("offline"); + } + } else { + if (bpmOutputLabel != null) { + bpmOutputLabel.setText("Current BPM: " + model.getBPM()); + } + } + } + } + + public void updateBeat() { + if (beatBar != null) { + beatBar.setValue(100); + } + } +} diff --git a/HF_DP/src/headfirst/combined/djview/HeartAdapter.java b/HF_DP/src/headfirst/combined/djview/HeartAdapter.java new file mode 100644 index 00000000..4fb17132 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/HeartAdapter.java @@ -0,0 +1,37 @@ +package headfirst.combined.djview; + +public class HeartAdapter implements BeatModelInterface { + HeartModelInterface heart; + + public HeartAdapter(HeartModelInterface heart) { + this.heart = heart; + } + + public void initialize() {} + + public void on() {} + + public void off() {} + + public int getBPM() { + return heart.getHeartRate(); + } + + public void setBPM(int bpm) {} + + public void registerObserver(BeatObserver o) { + heart.registerObserver(o); + } + + public void removeObserver(BeatObserver o) { + heart.removeObserver(o); + } + + public void registerObserver(BPMObserver o) { + heart.registerObserver(o); + } + + public void removeObserver(BPMObserver o) { + heart.removeObserver(o); + } +} diff --git a/HF_DP/src/headfirst/combined/djview/HeartController.java b/HF_DP/src/headfirst/combined/djview/HeartController.java new file mode 100644 index 00000000..9df79d90 --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/HeartController.java @@ -0,0 +1,28 @@ +package headfirst.combined.djview; + +public class HeartController implements ControllerInterface { + HeartModelInterface model; + DJView view; + + public HeartController(HeartModelInterface model) { + this.model = model; + view = new DJView(this, new HeartAdapter(model)); + view.createView(); + view.createControls(); + view.disableStopMenuItem(); + view.disableStartMenuItem(); + } + + public void start() {} + + public void stop() {} + + public void increaseBPM() {} + + public void decreaseBPM() {} + + public void setBPM(int bpm) {} +} + + + diff --git a/HF_DP/src/headfirst/combined/djview/HeartModel.java b/HF_DP/src/headfirst/combined/djview/HeartModel.java new file mode 100644 index 00000000..9c14d73c --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/HeartModel.java @@ -0,0 +1,79 @@ +package headfirst.combined.djview; + +import java.util.*; + +public class HeartModel implements HeartModelInterface, Runnable { + ArrayList beatObservers = new ArrayList(); + ArrayList bpmObservers = new ArrayList(); + int time = 1000; + int bpm = 90; + Random random = new Random(System.currentTimeMillis()); + Thread thread; + + public HeartModel() { + thread = new Thread(this); + thread.start(); + } + + public void run() { + int lastrate = -1; + + for(;;) { + int change = random.nextInt(10); + if (random.nextInt(2) == 0) { + change = 0 - change; + } + int rate = 60000/(time + change); + if (rate < 120 && rate > 50) { + time += change; + notifyBeatObservers(); + if (rate != lastrate) { + lastrate = rate; + notifyBPMObservers(); + } + } + try { + Thread.sleep(time); + } catch (Exception e) {} + } + } + public int getHeartRate() { + return 60000/time; + } + + public void registerObserver(BeatObserver o) { + beatObservers.add(o); + } + + public void removeObserver(BeatObserver o) { + int i = beatObservers.indexOf(o); + if (i >= 0) { + beatObservers.remove(i); + } + } + + public void notifyBeatObservers() { + for(int i = 0; i < beatObservers.size(); i++) { + BeatObserver observer = (BeatObserver)beatObservers.get(i); + observer.updateBeat(); + } + } + + public void registerObserver(BPMObserver o) { + bpmObservers.add(o); + } + + public void removeObserver(BPMObserver o) { + int i = bpmObservers.indexOf(o); + if (i >= 0) { + bpmObservers.remove(i); + } + } + + public void notifyBPMObservers() { + for(int i = 0; i < bpmObservers.size(); i++) { + BPMObserver observer = (BPMObserver)bpmObservers.get(i); + observer.updateBPM(); + } + } +} diff --git a/HF_DP/src/headfirst/combined/djview/HeartModelInterface.java b/HF_DP/src/headfirst/combined/djview/HeartModelInterface.java new file mode 100644 index 00000000..7fbe5b8b --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/HeartModelInterface.java @@ -0,0 +1,9 @@ +package headfirst.combined.djview; + +public interface HeartModelInterface { + int getHeartRate(); + void registerObserver(BeatObserver o); + void removeObserver(BeatObserver o); + void registerObserver(BPMObserver o); + void removeObserver(BPMObserver o); +} diff --git a/HF_DP/src/headfirst/combined/djview/HeartTestDrive.java b/HF_DP/src/headfirst/combined/djview/HeartTestDrive.java new file mode 100644 index 00000000..5bc7e58f --- /dev/null +++ b/HF_DP/src/headfirst/combined/djview/HeartTestDrive.java @@ -0,0 +1,9 @@ +package headfirst.combined.djview; + +public class HeartTestDrive { + + public static void main (String[] args) { + HeartModel heartModel = new HeartModel(); + ControllerInterface model = new HeartController(heartModel); + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/DecoyDuck.java b/HF_DP/src/headfirst/combining/adapter/DecoyDuck.java new file mode 100644 index 00000000..d0f2a43d --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/DecoyDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.adapter; + +public class DecoyDuck implements Quackable { + public void quack() { + System.out.println("<< Silence >>"); + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/DuckCall.java b/HF_DP/src/headfirst/combining/adapter/DuckCall.java new file mode 100644 index 00000000..150221b0 --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/DuckCall.java @@ -0,0 +1,7 @@ +package headfirst.combining.adapter; + +public class DuckCall implements Quackable { + public void quack() { + System.out.println("Kwak"); + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/DuckSimulator.java b/HF_DP/src/headfirst/combining/adapter/DuckSimulator.java new file mode 100644 index 00000000..f70ab940 --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/DuckSimulator.java @@ -0,0 +1,28 @@ +package headfirst.combining.adapter; + +public class DuckSimulator { + public static void main(String[] args) { + DuckSimulator simulator = new DuckSimulator(); + simulator.simulate(); + } + + void simulate() { + Quackable mallardDuck = new MallardDuck(); + Quackable redheadDuck = new RedheadDuck(); + Quackable duckCall = new DuckCall(); + Quackable rubberDuck = new RubberDuck(); + Quackable gooseDuck = new GooseAdapter(new Goose()); + + System.out.println("\nDuck Simulator: With Goose Adapter"); + + simulate(mallardDuck); + simulate(redheadDuck); + simulate(duckCall); + simulate(rubberDuck); + simulate(gooseDuck); + } + + void simulate(Quackable duck) { + duck.quack(); + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/Goose.java b/HF_DP/src/headfirst/combining/adapter/Goose.java new file mode 100644 index 00000000..c89f6c0b --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/Goose.java @@ -0,0 +1,7 @@ +package headfirst.combining.adapter; + +public class Goose { + public void honk() { + System.out.println("Honk"); + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/GooseAdapter.java b/HF_DP/src/headfirst/combining/adapter/GooseAdapter.java new file mode 100644 index 00000000..ccd544b0 --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/GooseAdapter.java @@ -0,0 +1,17 @@ +package headfirst.combining.adapter; + +public class GooseAdapter implements Quackable { + Goose goose; + + public GooseAdapter(Goose goose) { + this.goose = goose; + } + + public void quack() { + goose.honk(); + } + + public String toString() { + return "Goose pretending to be a Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/MallardDuck.java b/HF_DP/src/headfirst/combining/adapter/MallardDuck.java new file mode 100644 index 00000000..f033648e --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/MallardDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.adapter; + +public class MallardDuck implements Quackable { + public void quack() { + System.out.println("Quack"); + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/Quackable.java b/HF_DP/src/headfirst/combining/adapter/Quackable.java new file mode 100644 index 00000000..68f91141 --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/Quackable.java @@ -0,0 +1,5 @@ +package headfirst.combining.adapter; + +public interface Quackable { + public void quack(); +} diff --git a/HF_DP/src/headfirst/combining/adapter/RedheadDuck.java b/HF_DP/src/headfirst/combining/adapter/RedheadDuck.java new file mode 100644 index 00000000..37f161bd --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/RedheadDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.adapter; + +public class RedheadDuck implements Quackable { + public void quack() { + System.out.println("Quack"); + } +} diff --git a/HF_DP/src/headfirst/combining/adapter/RubberDuck.java b/HF_DP/src/headfirst/combining/adapter/RubberDuck.java new file mode 100644 index 00000000..9f007d24 --- /dev/null +++ b/HF_DP/src/headfirst/combining/adapter/RubberDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.adapter; + +public class RubberDuck implements Quackable { + public void quack() { + System.out.println("Squeak"); + } +} diff --git a/HF_DP/src/headfirst/combining/composite/AbstractDuckFactory.java b/HF_DP/src/headfirst/combining/composite/AbstractDuckFactory.java new file mode 100644 index 00000000..74fe3897 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/AbstractDuckFactory.java @@ -0,0 +1,9 @@ +package headfirst.combining.composite; + +public abstract class AbstractDuckFactory { + + public abstract Quackable createMallardDuck(); + public abstract Quackable createRedheadDuck(); + public abstract Quackable createDuckCall(); + public abstract Quackable createRubberDuck(); +} diff --git a/HF_DP/src/headfirst/combining/composite/CountingDuckFactory.java b/HF_DP/src/headfirst/combining/composite/CountingDuckFactory.java new file mode 100644 index 00000000..e384e323 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/CountingDuckFactory.java @@ -0,0 +1,20 @@ +package headfirst.combining.composite; + +public class CountingDuckFactory extends AbstractDuckFactory { + + public Quackable createMallardDuck() { + return new QuackCounter(new MallardDuck()); + } + + public Quackable createRedheadDuck() { + return new QuackCounter(new RedheadDuck()); + } + + public Quackable createDuckCall() { + return new QuackCounter(new DuckCall()); + } + + public Quackable createRubberDuck() { + return new QuackCounter(new RubberDuck()); + } +} diff --git a/HF_DP/src/headfirst/combining/composite/DecoyDuck.java b/HF_DP/src/headfirst/combining/composite/DecoyDuck.java new file mode 100644 index 00000000..deb14b64 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/DecoyDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.composite; + +public class DecoyDuck implements Quackable { + + public void quack() { + System.out.println("<< Silence >>"); + } + + public String toString() { + return "Decoy Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/composite/DuckCall.java b/HF_DP/src/headfirst/combining/composite/DuckCall.java new file mode 100644 index 00000000..bc6a9898 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/DuckCall.java @@ -0,0 +1,12 @@ +package headfirst.combining.composite; + +public class DuckCall implements Quackable { + + public void quack() { + System.out.println("Kwak"); + } + + public String toString() { + return "Duck Call"; + } +} diff --git a/HF_DP/src/headfirst/combining/composite/DuckFactory.java b/HF_DP/src/headfirst/combining/composite/DuckFactory.java new file mode 100644 index 00000000..c9cffaab --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/DuckFactory.java @@ -0,0 +1,20 @@ +package headfirst.combining.composite; + +public class DuckFactory extends AbstractDuckFactory { + + public Quackable createMallardDuck() { + return new MallardDuck(); + } + + public Quackable createRedheadDuck() { + return new RedheadDuck(); + } + + public Quackable createDuckCall() { + return new DuckCall(); + } + + public Quackable createRubberDuck() { + return new RubberDuck(); + } +} diff --git a/HF_DP/src/headfirst/combining/composite/DuckSimulator.java b/HF_DP/src/headfirst/combining/composite/DuckSimulator.java new file mode 100644 index 00000000..f64b4225 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/DuckSimulator.java @@ -0,0 +1,55 @@ +package headfirst.combining.composite; + +public class DuckSimulator { + + public static void main(String[] args) { + DuckSimulator simulator = new DuckSimulator(); + AbstractDuckFactory duckFactory = new CountingDuckFactory(); + + simulator.simulate(duckFactory); + } + + void simulate(AbstractDuckFactory duckFactory) { + Quackable redheadDuck = duckFactory.createRedheadDuck(); + Quackable duckCall = duckFactory.createDuckCall(); + Quackable rubberDuck = duckFactory.createRubberDuck(); + Quackable gooseDuck = new GooseAdapter(new Goose()); + + System.out.println("\nDuck Simulator: With Composite - Flocks"); + + Flock flockOfDucks = new Flock(); + + flockOfDucks.add(redheadDuck); + flockOfDucks.add(duckCall); + flockOfDucks.add(rubberDuck); + flockOfDucks.add(gooseDuck); + + Flock flockOfMallards = new Flock(); + + Quackable mallardOne = duckFactory.createMallardDuck(); + Quackable mallardTwo = duckFactory.createMallardDuck(); + Quackable mallardThree = duckFactory.createMallardDuck(); + Quackable mallardFour = duckFactory.createMallardDuck(); + + flockOfMallards.add(mallardOne); + flockOfMallards.add(mallardTwo); + flockOfMallards.add(mallardThree); + flockOfMallards.add(mallardFour); + + flockOfDucks.add(flockOfMallards); + + System.out.println("\nDuck Simulator: Whole Flock Simulation"); + simulate(flockOfDucks); + + System.out.println("\nDuck Simulator: Mallard Flock Simulation"); + simulate(flockOfMallards); + + System.out.println("\nThe ducks quacked " + + QuackCounter.getQuacks() + + " times"); + } + + void simulate(Quackable duck) { + duck.quack(); + } +} diff --git a/HF_DP/src/headfirst/combining/composite/Flock.java b/HF_DP/src/headfirst/combining/composite/Flock.java new file mode 100644 index 00000000..bd16ee1e --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/Flock.java @@ -0,0 +1,24 @@ +package headfirst.combining.composite; + +import java.util.Iterator; +import java.util.ArrayList; + +public class Flock implements Quackable { + ArrayList quackers = new ArrayList(); + + public void add(Quackable quacker) { + quackers.add(quacker); + } + + public void quack() { + Iterator iterator = quackers.iterator(); + while (iterator.hasNext()) { + Quackable quacker = (Quackable)iterator.next(); + quacker.quack(); + } + } + + public String toString() { + return "Flock of Quackers"; + } +} diff --git a/HF_DP/src/headfirst/combining/composite/Goose.java b/HF_DP/src/headfirst/combining/composite/Goose.java new file mode 100644 index 00000000..3b226fda --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/Goose.java @@ -0,0 +1,11 @@ +package headfirst.combining.composite; + +public class Goose { + public void honk() { + System.out.println("Honk"); + } + + public String toString() { + return "Goose"; + } +} diff --git a/HF_DP/src/headfirst/combining/composite/GooseAdapter.java b/HF_DP/src/headfirst/combining/composite/GooseAdapter.java new file mode 100644 index 00000000..5a1accf3 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/GooseAdapter.java @@ -0,0 +1,17 @@ +package headfirst.combining.composite; + +public class GooseAdapter implements Quackable { + Goose goose; + + public GooseAdapter(Goose goose) { + this.goose = goose; + } + + public void quack() { + goose.honk(); + } + + public String toString() { + return "Goose pretending to be a Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/composite/MallardDuck.java b/HF_DP/src/headfirst/combining/composite/MallardDuck.java new file mode 100644 index 00000000..e4dbc54c --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/MallardDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.composite; + +public class MallardDuck implements Quackable { + + public void quack() { + System.out.println("Quack"); + } + + public String toString() { + return "Mallard Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/composite/QuackCounter.java b/HF_DP/src/headfirst/combining/composite/QuackCounter.java new file mode 100644 index 00000000..8199a06c --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/QuackCounter.java @@ -0,0 +1,23 @@ +package headfirst.combining.composite; + +public class QuackCounter implements Quackable { + Quackable duck; + static int numberOfQuacks; + + public QuackCounter(Quackable duck) { + this.duck = duck; + } + + public void quack() { + duck.quack(); + numberOfQuacks++; + } + + public static int getQuacks() { + return numberOfQuacks; + } + + public String toString() { + return duck.toString(); + } +} diff --git a/HF_DP/src/headfirst/combining/composite/Quackable.java b/HF_DP/src/headfirst/combining/composite/Quackable.java new file mode 100644 index 00000000..d5bb01f5 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/Quackable.java @@ -0,0 +1,5 @@ +package headfirst.combining.composite; + +public interface Quackable { + public void quack(); +} diff --git a/HF_DP/src/headfirst/combining/composite/RedheadDuck.java b/HF_DP/src/headfirst/combining/composite/RedheadDuck.java new file mode 100644 index 00000000..55ea0163 --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/RedheadDuck.java @@ -0,0 +1,11 @@ +package headfirst.combining.composite; + +public class RedheadDuck implements Quackable { + public void quack() { + System.out.println("Quack"); + } + + public String toString() { + return "Redhead Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/composite/RubberDuck.java b/HF_DP/src/headfirst/combining/composite/RubberDuck.java new file mode 100644 index 00000000..89de47fa --- /dev/null +++ b/HF_DP/src/headfirst/combining/composite/RubberDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.composite; + +public class RubberDuck implements Quackable { + + public void quack() { + System.out.println("Squeak"); + } + + public String toString() { + return "Rubber Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/DecoyDuck.java b/HF_DP/src/headfirst/combining/decorator/DecoyDuck.java new file mode 100644 index 00000000..11baa478 --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/DecoyDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.decorator; + +public class DecoyDuck implements Quackable { + + public void quack() { + System.out.println("<< Silence >>"); + } + + public String toString() { + return "Decoy Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/DuckCall.java b/HF_DP/src/headfirst/combining/decorator/DuckCall.java new file mode 100644 index 00000000..1b6e53d7 --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/DuckCall.java @@ -0,0 +1,12 @@ +package headfirst.combining.decorator; + +public class DuckCall implements Quackable { + + public void quack() { + System.out.println("Kwak"); + } + + public String toString() { + return "Duck Call"; + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/DuckSimulator.java b/HF_DP/src/headfirst/combining/decorator/DuckSimulator.java new file mode 100644 index 00000000..b895c235 --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/DuckSimulator.java @@ -0,0 +1,31 @@ +package headfirst.combining.decorator; + +public class DuckSimulator { + public static void main(String[] args) { + DuckSimulator simulator = new DuckSimulator(); + simulator.simulate(); + } + + void simulate() { + Quackable mallardDuck = new QuackCounter(new MallardDuck()); + Quackable redheadDuck = new QuackCounter(new RedheadDuck()); + Quackable duckCall = new QuackCounter(new DuckCall()); + Quackable rubberDuck = new QuackCounter(new RubberDuck()); + Quackable gooseDuck = new GooseAdapter(new Goose()); + + System.out.println("\nDuck Simulator: With Decorator"); + + simulate(mallardDuck); + simulate(redheadDuck); + simulate(duckCall); + simulate(rubberDuck); + simulate(gooseDuck); + + System.out.println("The ducks quacked " + + QuackCounter.getQuacks() + " times"); + } + + void simulate(Quackable duck) { + duck.quack(); + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/Goose.java b/HF_DP/src/headfirst/combining/decorator/Goose.java new file mode 100644 index 00000000..2f977adb --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/Goose.java @@ -0,0 +1,11 @@ +package headfirst.combining.decorator; + +public class Goose { + public void honk() { + System.out.println("Honk"); + } + + public String toString() { + return "Goose"; + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/GooseAdapter.java b/HF_DP/src/headfirst/combining/decorator/GooseAdapter.java new file mode 100644 index 00000000..5d22849d --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/GooseAdapter.java @@ -0,0 +1,17 @@ +package headfirst.combining.decorator; + +public class GooseAdapter implements Quackable { + Goose goose; + + public GooseAdapter(Goose goose) { + this.goose = goose; + } + + public void quack() { + goose.honk(); + } + + public String toString() { + return "Goose pretending to be a Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/MallardDuck.java b/HF_DP/src/headfirst/combining/decorator/MallardDuck.java new file mode 100644 index 00000000..e764d4b5 --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/MallardDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.decorator; + +public class MallardDuck implements Quackable { + + public void quack() { + System.out.println("Quack"); + } + + public String toString() { + return "Mallard Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/QuackCounter.java b/HF_DP/src/headfirst/combining/decorator/QuackCounter.java new file mode 100644 index 00000000..3206861d --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/QuackCounter.java @@ -0,0 +1,22 @@ +package headfirst.combining.decorator; + +public class QuackCounter implements Quackable { + Quackable duck; + static int numberOfQuacks; + + public QuackCounter (Quackable duck) { + this.duck = duck; + } + + public void quack() { + duck.quack(); + numberOfQuacks++; + } + + public static int getQuacks() { + return numberOfQuacks; + } + public String toString() { + return duck.toString(); + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/Quackable.java b/HF_DP/src/headfirst/combining/decorator/Quackable.java new file mode 100644 index 00000000..41689a96 --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/Quackable.java @@ -0,0 +1,5 @@ +package headfirst.combining.decorator; + +public interface Quackable { + public void quack(); +} diff --git a/HF_DP/src/headfirst/combining/decorator/RedheadDuck.java b/HF_DP/src/headfirst/combining/decorator/RedheadDuck.java new file mode 100644 index 00000000..95dad6ae --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/RedheadDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.decorator; + +public class RedheadDuck implements Quackable { + public void quack() { + System.out.println("Quack"); + } +} diff --git a/HF_DP/src/headfirst/combining/decorator/RubberDuck.java b/HF_DP/src/headfirst/combining/decorator/RubberDuck.java new file mode 100644 index 00000000..171f6937 --- /dev/null +++ b/HF_DP/src/headfirst/combining/decorator/RubberDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.decorator; + +public class RubberDuck implements Quackable { + + public void quack() { + System.out.println("Squeak"); + } + + public String toString() { + return "Rubber Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/ducks/DecoyDuck.java b/HF_DP/src/headfirst/combining/ducks/DecoyDuck.java new file mode 100644 index 00000000..085cff35 --- /dev/null +++ b/HF_DP/src/headfirst/combining/ducks/DecoyDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.ducks; + +public class DecoyDuck implements Quackable { + public void quack() { + System.out.println("<< Silence >>"); + } +} diff --git a/HF_DP/src/headfirst/combining/ducks/DuckCall.java b/HF_DP/src/headfirst/combining/ducks/DuckCall.java new file mode 100644 index 00000000..dcdc02ce --- /dev/null +++ b/HF_DP/src/headfirst/combining/ducks/DuckCall.java @@ -0,0 +1,7 @@ +package headfirst.combining.ducks; + +public class DuckCall implements Quackable { + public void quack() { + System.out.println("Kwak"); + } +} diff --git a/HF_DP/src/headfirst/combining/ducks/DuckSimulator.java b/HF_DP/src/headfirst/combining/ducks/DuckSimulator.java new file mode 100644 index 00000000..46e56094 --- /dev/null +++ b/HF_DP/src/headfirst/combining/ducks/DuckSimulator.java @@ -0,0 +1,26 @@ +package headfirst.combining.ducks; + +public class DuckSimulator { + public static void main(String[] args) { + DuckSimulator simulator = new DuckSimulator(); + simulator.simulate(); + } + + void simulate() { + Quackable mallardDuck = new MallardDuck(); + Quackable redheadDuck = new RedheadDuck(); + Quackable duckCall = new DuckCall(); + Quackable rubberDuck = new RubberDuck(); + + System.out.println("\nDuck Simulator"); + + simulate(mallardDuck); + simulate(redheadDuck); + simulate(duckCall); + simulate(rubberDuck); + } + + void simulate(Quackable duck) { + duck.quack(); + } +} diff --git a/HF_DP/src/headfirst/combining/ducks/MallardDuck.java b/HF_DP/src/headfirst/combining/ducks/MallardDuck.java new file mode 100644 index 00000000..404d6099 --- /dev/null +++ b/HF_DP/src/headfirst/combining/ducks/MallardDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.ducks; + +public class MallardDuck implements Quackable { + public void quack() { + System.out.println("Quack"); + } +} diff --git a/HF_DP/src/headfirst/combining/ducks/Quackable.java b/HF_DP/src/headfirst/combining/ducks/Quackable.java new file mode 100644 index 00000000..e4bfe19d --- /dev/null +++ b/HF_DP/src/headfirst/combining/ducks/Quackable.java @@ -0,0 +1,5 @@ +package headfirst.combining.ducks; + +public interface Quackable { + public void quack(); +} diff --git a/HF_DP/src/headfirst/combining/ducks/RedheadDuck.java b/HF_DP/src/headfirst/combining/ducks/RedheadDuck.java new file mode 100644 index 00000000..4f1f9f06 --- /dev/null +++ b/HF_DP/src/headfirst/combining/ducks/RedheadDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.ducks; + +public class RedheadDuck implements Quackable { + public void quack() { + System.out.println("Quack"); + } +} diff --git a/HF_DP/src/headfirst/combining/ducks/RubberDuck.java b/HF_DP/src/headfirst/combining/ducks/RubberDuck.java new file mode 100644 index 00000000..54f1d846 --- /dev/null +++ b/HF_DP/src/headfirst/combining/ducks/RubberDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.ducks; + +public class RubberDuck implements Quackable { + public void quack() { + System.out.println("Squeak"); + } +} diff --git a/HF_DP/src/headfirst/combining/factory/AbstractDuckFactory.java b/HF_DP/src/headfirst/combining/factory/AbstractDuckFactory.java new file mode 100644 index 00000000..7287a7d1 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/AbstractDuckFactory.java @@ -0,0 +1,9 @@ +package headfirst.combining.factory; + +public abstract class AbstractDuckFactory { + + public abstract Quackable createMallardDuck(); + public abstract Quackable createRedheadDuck(); + public abstract Quackable createDuckCall(); + public abstract Quackable createRubberDuck(); +} diff --git a/HF_DP/src/headfirst/combining/factory/CountingDuckFactory.java b/HF_DP/src/headfirst/combining/factory/CountingDuckFactory.java new file mode 100644 index 00000000..501e6e76 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/CountingDuckFactory.java @@ -0,0 +1,20 @@ +package headfirst.combining.factory; + +public class CountingDuckFactory extends AbstractDuckFactory { + + public Quackable createMallardDuck() { + return new QuackCounter(new MallardDuck()); + } + + public Quackable createRedheadDuck() { + return new QuackCounter(new RedheadDuck()); + } + + public Quackable createDuckCall() { + return new QuackCounter(new DuckCall()); + } + + public Quackable createRubberDuck() { + return new QuackCounter(new RubberDuck()); + } +} diff --git a/HF_DP/src/headfirst/combining/factory/DecoyDuck.java b/HF_DP/src/headfirst/combining/factory/DecoyDuck.java new file mode 100644 index 00000000..322c91af --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/DecoyDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.factory; + +public class DecoyDuck implements Quackable { + + public void quack() { + System.out.println("<< Silence >>"); + } + + public String toString() { + return "Decoy Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/factory/DuckCall.java b/HF_DP/src/headfirst/combining/factory/DuckCall.java new file mode 100644 index 00000000..1a216358 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/DuckCall.java @@ -0,0 +1,12 @@ +package headfirst.combining.factory; + +public class DuckCall implements Quackable { + + public void quack() { + System.out.println("Kwak"); + } + + public String toString() { + return "Duck Call"; + } +} diff --git a/HF_DP/src/headfirst/combining/factory/DuckFactory.java b/HF_DP/src/headfirst/combining/factory/DuckFactory.java new file mode 100644 index 00000000..f9cf89a4 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/DuckFactory.java @@ -0,0 +1,20 @@ +package headfirst.combining.factory; + +public class DuckFactory extends AbstractDuckFactory { + + public Quackable createMallardDuck() { + return new MallardDuck(); + } + + public Quackable createRedheadDuck() { + return new RedheadDuck(); + } + + public Quackable createDuckCall() { + return new DuckCall(); + } + + public Quackable createRubberDuck() { + return new RubberDuck(); + } +} diff --git a/HF_DP/src/headfirst/combining/factory/DuckSimulator.java b/HF_DP/src/headfirst/combining/factory/DuckSimulator.java new file mode 100644 index 00000000..4a56ab32 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/DuckSimulator.java @@ -0,0 +1,34 @@ +package headfirst.combining.factory; + +public class DuckSimulator { + public static void main(String[] args) { + DuckSimulator simulator = new DuckSimulator(); + AbstractDuckFactory duckFactory = new CountingDuckFactory(); + + simulator.simulate(duckFactory); + } + + void simulate(AbstractDuckFactory duckFactory) { + Quackable mallardDuck = duckFactory.createMallardDuck(); + Quackable redheadDuck = duckFactory.createRedheadDuck(); + Quackable duckCall = duckFactory.createDuckCall(); + Quackable rubberDuck = duckFactory.createRubberDuck(); + Quackable gooseDuck = new GooseAdapter(new Goose()); + + System.out.println("\nDuck Simulator: With Abstract Factory"); + + simulate(mallardDuck); + simulate(redheadDuck); + simulate(duckCall); + simulate(rubberDuck); + simulate(gooseDuck); + + System.out.println("The ducks quacked " + + QuackCounter.getQuacks() + + " times"); + } + + void simulate(Quackable duck) { + duck.quack(); + } +} diff --git a/HF_DP/src/headfirst/combining/factory/Goose.java b/HF_DP/src/headfirst/combining/factory/Goose.java new file mode 100644 index 00000000..36b8cee4 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/Goose.java @@ -0,0 +1,11 @@ +package headfirst.combining.factory; + +public class Goose { + public void honk() { + System.out.println("Honk"); + } + + public String toString() { + return "Goose"; + } +} diff --git a/HF_DP/src/headfirst/combining/factory/GooseAdapter.java b/HF_DP/src/headfirst/combining/factory/GooseAdapter.java new file mode 100644 index 00000000..ce742a5a --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/GooseAdapter.java @@ -0,0 +1,17 @@ +package headfirst.combining.factory; + +public class GooseAdapter implements Quackable { + Goose goose; + + public GooseAdapter(Goose goose) { + this.goose = goose; + } + + public void quack() { + goose.honk(); + } + + public String toString() { + return "Goose pretending to be a Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/factory/MallardDuck.java b/HF_DP/src/headfirst/combining/factory/MallardDuck.java new file mode 100644 index 00000000..e10680dc --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/MallardDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.factory; + +public class MallardDuck implements Quackable { + + public void quack() { + System.out.println("Quack"); + } + + public String toString() { + return "Mallard Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/factory/QuackCounter.java b/HF_DP/src/headfirst/combining/factory/QuackCounter.java new file mode 100644 index 00000000..4db317b0 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/QuackCounter.java @@ -0,0 +1,23 @@ +package headfirst.combining.factory; + +public class QuackCounter implements Quackable { + Quackable duck; + static int numberOfQuacks; + + public QuackCounter(Quackable duck) { + this.duck = duck; + } + + public void quack() { + duck.quack(); + numberOfQuacks++; + } + + public static int getQuacks() { + return numberOfQuacks; + } + + public String toString() { + return duck.toString(); + } +} diff --git a/HF_DP/src/headfirst/combining/factory/Quackable.java b/HF_DP/src/headfirst/combining/factory/Quackable.java new file mode 100644 index 00000000..88ec2e42 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/Quackable.java @@ -0,0 +1,5 @@ +package headfirst.combining.factory; + +public interface Quackable { + public void quack(); +} diff --git a/HF_DP/src/headfirst/combining/factory/RedheadDuck.java b/HF_DP/src/headfirst/combining/factory/RedheadDuck.java new file mode 100644 index 00000000..77cb8668 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/RedheadDuck.java @@ -0,0 +1,7 @@ +package headfirst.combining.factory; + +public class RedheadDuck implements Quackable { + public void quack() { + System.out.println("Quack"); + } +} diff --git a/HF_DP/src/headfirst/combining/factory/RubberDuck.java b/HF_DP/src/headfirst/combining/factory/RubberDuck.java new file mode 100644 index 00000000..f0849cc7 --- /dev/null +++ b/HF_DP/src/headfirst/combining/factory/RubberDuck.java @@ -0,0 +1,12 @@ +package headfirst.combining.factory; + +public class RubberDuck implements Quackable { + + public void quack() { + System.out.println("Squeak"); + } + + public String toString() { + return "Rubber Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/AbstractDuckFactory.java b/HF_DP/src/headfirst/combining/observer/AbstractDuckFactory.java new file mode 100644 index 00000000..9fdf9e50 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/AbstractDuckFactory.java @@ -0,0 +1,9 @@ +package headfirst.combining.observer; + +public abstract class AbstractDuckFactory { + + public abstract Quackable createMallardDuck(); + public abstract Quackable createRedheadDuck(); + public abstract Quackable createDuckCall(); + public abstract Quackable createRubberDuck(); +} diff --git a/HF_DP/src/headfirst/combining/observer/CountingDuckFactory.java b/HF_DP/src/headfirst/combining/observer/CountingDuckFactory.java new file mode 100644 index 00000000..5a528b16 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/CountingDuckFactory.java @@ -0,0 +1,20 @@ +package headfirst.combining.observer; + +public class CountingDuckFactory extends AbstractDuckFactory { + + public Quackable createMallardDuck() { + return new QuackCounter(new MallardDuck()); + } + + public Quackable createRedheadDuck() { + return new QuackCounter(new RedheadDuck()); + } + + public Quackable createDuckCall() { + return new QuackCounter(new DuckCall()); + } + + public Quackable createRubberDuck() { + return new QuackCounter(new RubberDuck()); + } +} diff --git a/HF_DP/src/headfirst/combining/observer/DecoyDuck.java b/HF_DP/src/headfirst/combining/observer/DecoyDuck.java new file mode 100644 index 00000000..c9cbcda0 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/DecoyDuck.java @@ -0,0 +1,26 @@ +package headfirst.combining.observer; + +public class DecoyDuck implements Quackable { + Observable observable; + + public DecoyDuck() { + observable = new Observable(this); + } + + public void quack() { + System.out.println("<< Silence >>"); + notifyObservers(); + } + + public void registerObserver(Observer observer) { + observable.registerObserver(observer); + } + + public void notifyObservers() { + observable.notifyObservers(); + } + + public String toString() { + return "Decoy Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/DuckCall.java b/HF_DP/src/headfirst/combining/observer/DuckCall.java new file mode 100644 index 00000000..1c7dfd80 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/DuckCall.java @@ -0,0 +1,26 @@ +package headfirst.combining.observer; + +public class DuckCall implements Quackable { + Observable observable; + + public DuckCall() { + observable = new Observable(this); + } + + public void quack() { + System.out.println("Kwak"); + notifyObservers(); + } + + public void registerObserver(Observer observer) { + observable.registerObserver(observer); + } + + public void notifyObservers() { + observable.notifyObservers(); + } + + public String toString() { + return "Duck Call"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/DuckFactory.java b/HF_DP/src/headfirst/combining/observer/DuckFactory.java new file mode 100644 index 00000000..029b944f --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/DuckFactory.java @@ -0,0 +1,20 @@ +package headfirst.combining.observer; + +public class DuckFactory extends AbstractDuckFactory { + + public Quackable createMallardDuck() { + return new MallardDuck(); + } + + public Quackable createRedheadDuck() { + return new RedheadDuck(); + } + + public Quackable createDuckCall() { + return new DuckCall(); + } + + public Quackable createRubberDuck() { + return new RubberDuck(); + } +} diff --git a/HF_DP/src/headfirst/combining/observer/DuckSimulator.java b/HF_DP/src/headfirst/combining/observer/DuckSimulator.java new file mode 100644 index 00000000..54f2279d --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/DuckSimulator.java @@ -0,0 +1,54 @@ +package headfirst.combining.observer; + +public class DuckSimulator { + public static void main(String[] args) { + DuckSimulator simulator = new DuckSimulator(); + AbstractDuckFactory duckFactory = new CountingDuckFactory(); + + simulator.simulate(duckFactory); + } + + void simulate(AbstractDuckFactory duckFactory) { + + Quackable redheadDuck = duckFactory.createRedheadDuck(); + Quackable duckCall = duckFactory.createDuckCall(); + Quackable rubberDuck = duckFactory.createRubberDuck(); + Quackable gooseDuck = new GooseAdapter(new Goose()); + + Flock flockOfDucks = new Flock(); + + flockOfDucks.add(redheadDuck); + flockOfDucks.add(duckCall); + flockOfDucks.add(rubberDuck); + flockOfDucks.add(gooseDuck); + + Flock flockOfMallards = new Flock(); + + Quackable mallardOne = duckFactory.createMallardDuck(); + Quackable mallardTwo = duckFactory.createMallardDuck(); + Quackable mallardThree = duckFactory.createMallardDuck(); + Quackable mallardFour = duckFactory.createMallardDuck(); + + flockOfMallards.add(mallardOne); + flockOfMallards.add(mallardTwo); + flockOfMallards.add(mallardThree); + flockOfMallards.add(mallardFour); + + flockOfDucks.add(flockOfMallards); + + System.out.println("\nDuck Simulator: With Observer"); + + Quackologist quackologist = new Quackologist(); + flockOfDucks.registerObserver(quackologist); + + simulate(flockOfDucks); + + System.out.println("\nThe ducks quacked " + + QuackCounter.getQuacks() + + " times"); + } + + void simulate(Quackable duck) { + duck.quack(); + } +} diff --git a/HF_DP/src/headfirst/combining/observer/Flock.java b/HF_DP/src/headfirst/combining/observer/Flock.java new file mode 100644 index 00000000..7b57be6b --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/Flock.java @@ -0,0 +1,34 @@ +package headfirst.combining.observer; + +import java.util.Iterator; +import java.util.ArrayList; + +public class Flock implements Quackable { + ArrayList ducks = new ArrayList(); + + public void add(Quackable duck) { + ducks.add(duck); + } + + public void quack() { + Iterator iterator = ducks.iterator(); + while (iterator.hasNext()) { + Quackable duck = (Quackable)iterator.next(); + duck.quack(); + } + } + + public void registerObserver(Observer observer) { + Iterator iterator = ducks.iterator(); + while (iterator.hasNext()) { + Quackable duck = (Quackable)iterator.next(); + duck.registerObserver(observer); + } + } + + public void notifyObservers() { } + + public String toString() { + return "Flock of Ducks"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/Goose.java b/HF_DP/src/headfirst/combining/observer/Goose.java new file mode 100644 index 00000000..eca1ed56 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/Goose.java @@ -0,0 +1,12 @@ +package headfirst.combining.observer; + +public class Goose { + + public void honk() { + System.out.println("Honk"); + } + + public String toString() { + return "Goose"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/GooseAdapter.java b/HF_DP/src/headfirst/combining/observer/GooseAdapter.java new file mode 100644 index 00000000..72c0954e --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/GooseAdapter.java @@ -0,0 +1,28 @@ +package headfirst.combining.observer; + +public class GooseAdapter implements Quackable { + Goose goose; + Observable observable; + + public GooseAdapter(Goose goose) { + this.goose = goose; + observable = new Observable(this); + } + + public void quack() { + goose.honk(); + notifyObservers(); + } + + public void registerObserver(Observer observer) { + observable.registerObserver(observer); + } + + public void notifyObservers() { + observable.notifyObservers(); + } + + public String toString() { + return "Goose pretending to be a Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/MallardDuck.java b/HF_DP/src/headfirst/combining/observer/MallardDuck.java new file mode 100644 index 00000000..51a4df1f --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/MallardDuck.java @@ -0,0 +1,26 @@ +package headfirst.combining.observer; + +public class MallardDuck implements Quackable { + Observable observable; + + public MallardDuck() { + observable = new Observable(this); + } + + public void quack() { + System.out.println("Quack"); + notifyObservers(); + } + + public void registerObserver(Observer observer) { + observable.registerObserver(observer); + } + + public void notifyObservers() { + observable.notifyObservers(); + } + + public String toString() { + return "Mallard Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/Observable.java b/HF_DP/src/headfirst/combining/observer/Observable.java new file mode 100644 index 00000000..92ca35b5 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/Observable.java @@ -0,0 +1,29 @@ +package headfirst.combining.observer; + +import java.util.Iterator; +import java.util.ArrayList; + +public class Observable implements QuackObservable { + ArrayList observers = new ArrayList(); + QuackObservable duck; + + public Observable(QuackObservable duck) { + this.duck = duck; + } + + public void registerObserver(Observer observer) { + observers.add(observer); + } + + public void notifyObservers() { + Iterator iterator = observers.iterator(); + while (iterator.hasNext()) { + Observer observer = (Observer)iterator.next(); + observer.update(duck); + } + } + + public Iterator getObservers() { + return observers.iterator(); + } +} diff --git a/HF_DP/src/headfirst/combining/observer/Observer.java b/HF_DP/src/headfirst/combining/observer/Observer.java new file mode 100644 index 00000000..d35999ef --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/Observer.java @@ -0,0 +1,5 @@ +package headfirst.combining.observer; + +public interface Observer { + public void update(QuackObservable duck); +} diff --git a/HF_DP/src/headfirst/combining/observer/QuackCounter.java b/HF_DP/src/headfirst/combining/observer/QuackCounter.java new file mode 100644 index 00000000..40581b13 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/QuackCounter.java @@ -0,0 +1,31 @@ +package headfirst.combining.observer; + +public class QuackCounter implements Quackable { + Quackable duck; + static int numberOfQuacks; + + public QuackCounter(Quackable duck) { + this.duck = duck; + } + + public void quack() { + duck.quack(); + numberOfQuacks++; + } + + public static int getQuacks() { + return numberOfQuacks; + } + + public void registerObserver(Observer observer) { + duck.registerObserver(observer); + } + + public void notifyObservers() { + duck.notifyObservers(); + } + + public String toString() { + return duck.toString(); + } +} diff --git a/HF_DP/src/headfirst/combining/observer/QuackObservable.java b/HF_DP/src/headfirst/combining/observer/QuackObservable.java new file mode 100644 index 00000000..f2525475 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/QuackObservable.java @@ -0,0 +1,6 @@ +package headfirst.combining.observer; + +public interface QuackObservable { + public void registerObserver(Observer observer); + public void notifyObservers(); +} diff --git a/HF_DP/src/headfirst/combining/observer/Quackable.java b/HF_DP/src/headfirst/combining/observer/Quackable.java new file mode 100644 index 00000000..e9b8711c --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/Quackable.java @@ -0,0 +1,5 @@ +package headfirst.combining.observer; + +public interface Quackable extends QuackObservable { + public void quack(); +} diff --git a/HF_DP/src/headfirst/combining/observer/Quackologist.java b/HF_DP/src/headfirst/combining/observer/Quackologist.java new file mode 100644 index 00000000..ce2f54f3 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/Quackologist.java @@ -0,0 +1,12 @@ +package headfirst.combining.observer; + +public class Quackologist implements Observer { + + public void update(QuackObservable duck) { + System.out.println("Quackologist: " + duck + " just quacked."); + } + + public String toString() { + return "Quackologist"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/RedheadDuck.java b/HF_DP/src/headfirst/combining/observer/RedheadDuck.java new file mode 100644 index 00000000..0d311cd6 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/RedheadDuck.java @@ -0,0 +1,26 @@ +package headfirst.combining.observer; + +public class RedheadDuck implements Quackable { + Observable observable; + + public RedheadDuck() { + observable = new Observable(this); + } + + public void quack() { + System.out.println("Quack"); + notifyObservers(); + } + + public void registerObserver(Observer observer) { + observable.registerObserver(observer); + } + + public void notifyObservers() { + observable.notifyObservers(); + } + + public String toString() { + return "Redhead Duck"; + } +} diff --git a/HF_DP/src/headfirst/combining/observer/RubberDuck.java b/HF_DP/src/headfirst/combining/observer/RubberDuck.java new file mode 100644 index 00000000..db712833 --- /dev/null +++ b/HF_DP/src/headfirst/combining/observer/RubberDuck.java @@ -0,0 +1,26 @@ +package headfirst.combining.observer; + +public class RubberDuck implements Quackable { + Observable observable; + + public RubberDuck() { + observable = new Observable(this); + } + + public void quack() { + System.out.println("Squeak"); + notifyObservers(); + } + + public void registerObserver(Observer observer) { + observable.registerObserver(observer); + } + + public void notifyObservers() { + observable.notifyObservers(); + } + + public String toString() { + return "Rubber Duck"; + } +} diff --git a/HF_DP/src/headfirst/command/party/CeilingFan.java b/HF_DP/src/headfirst/command/party/CeilingFan.java new file mode 100644 index 00000000..af7c94c8 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/CeilingFan.java @@ -0,0 +1,42 @@ +package headfirst.command.party; + +public class CeilingFan { + public static final int HIGH = 3; + public static final int MEDIUM = 2; + public static final int LOW = 1; + public static final int OFF = 0; + String location; + int speed; + + public CeilingFan(String location) { + this.location = location; + } + + public void high() { + // turns the ceiling fan on to high + speed = HIGH; + System.out.println(location + " ceiling fan is on high"); + } + + public void medium() { + // turns the ceiling fan on to medium + speed = MEDIUM; + System.out.println(location + " ceiling fan is on medium"); + } + + public void low() { + // turns the ceiling fan on to low + speed = LOW; + System.out.println(location + " ceiling fan is on low"); + } + + public void off() { + // turns the ceiling fan off + speed = OFF; + System.out.println(location + " ceiling fan is off"); + } + + public int getSpeed() { + return speed; + } +} diff --git a/HF_DP/src/headfirst/command/party/CeilingFanHighCommand.java b/HF_DP/src/headfirst/command/party/CeilingFanHighCommand.java new file mode 100644 index 00000000..81a25f80 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/CeilingFanHighCommand.java @@ -0,0 +1,22 @@ +package headfirst.command.party; + +public class CeilingFanHighCommand implements Command { + CeilingFan ceilingFan; + int prevSpeed; + + public CeilingFanHighCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + public void execute() { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.high(); + } + public void undo() { + switch (prevSpeed) { + case CeilingFan.HIGH: ceilingFan.high(); break; + case CeilingFan.MEDIUM: ceilingFan.medium(); break; + case CeilingFan.LOW: ceilingFan.low(); break; + default: ceilingFan.off(); break; + } + } +} diff --git a/HF_DP/src/headfirst/command/party/CeilingFanMediumCommand.java b/HF_DP/src/headfirst/command/party/CeilingFanMediumCommand.java new file mode 100644 index 00000000..c7c7c360 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/CeilingFanMediumCommand.java @@ -0,0 +1,22 @@ +package headfirst.command.party; + +public class CeilingFanMediumCommand implements Command { + CeilingFan ceilingFan; + int prevSpeed; + + public CeilingFanMediumCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + public void execute() { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.medium(); + } + public void undo() { + switch (prevSpeed) { + case CeilingFan.HIGH: ceilingFan.high(); break; + case CeilingFan.MEDIUM: ceilingFan.medium(); break; + case CeilingFan.LOW: ceilingFan.low(); break; + default: ceilingFan.off(); break; + } + } +} diff --git a/HF_DP/src/headfirst/command/party/CeilingFanOffCommand.java b/HF_DP/src/headfirst/command/party/CeilingFanOffCommand.java new file mode 100644 index 00000000..ce75c97a --- /dev/null +++ b/HF_DP/src/headfirst/command/party/CeilingFanOffCommand.java @@ -0,0 +1,22 @@ +package headfirst.command.party; + +public class CeilingFanOffCommand implements Command { + CeilingFan ceilingFan; + int prevSpeed; + + public CeilingFanOffCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + public void execute() { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.off(); + } + public void undo() { + switch (prevSpeed) { + case CeilingFan.HIGH: ceilingFan.high(); break; + case CeilingFan.MEDIUM: ceilingFan.medium(); break; + case CeilingFan.LOW: ceilingFan.low(); break; + default: ceilingFan.off(); break; + } + } +} diff --git a/HF_DP/src/headfirst/command/party/Command.java b/HF_DP/src/headfirst/command/party/Command.java new file mode 100644 index 00000000..1dfca6fb --- /dev/null +++ b/HF_DP/src/headfirst/command/party/Command.java @@ -0,0 +1,6 @@ +package headfirst.command.party; + +public interface Command { + public void execute(); + public void undo(); +} diff --git a/HF_DP/src/headfirst/command/party/Hottub.java b/HF_DP/src/headfirst/command/party/Hottub.java new file mode 100644 index 00000000..1b300db6 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/Hottub.java @@ -0,0 +1,45 @@ +package headfirst.command.party; + +public class Hottub { + boolean on; + int temperature; + + public Hottub() { + } + + public void on() { + on = true; + } + + public void off() { + on = false; + } + + public void circulate() { + if (on) { + System.out.println("Hottub is bubbling!"); + } + } + + public void jetsOn() { + if (on) { + System.out.println("Hottub jets are on"); + } + } + + public void jetsOff() { + if (on) { + System.out.println("Hottub jets are off"); + } + } + + public void setTemperature(int temperature) { + if (temperature > this.temperature) { + System.out.println("Hottub is heating to a steaming " + temperature + " degrees"); + } + else { + System.out.println("Hottub is cooling to " + temperature + " degrees"); + } + this.temperature = temperature; + } +} diff --git a/HF_DP/src/headfirst/command/party/HottubOffCommand.java b/HF_DP/src/headfirst/command/party/HottubOffCommand.java new file mode 100644 index 00000000..f8f36b86 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/HottubOffCommand.java @@ -0,0 +1,17 @@ +package headfirst.command.party; + +public class HottubOffCommand implements Command { + Hottub hottub; + + public HottubOffCommand(Hottub hottub) { + this.hottub = hottub; + } + + public void execute() { + hottub.setTemperature(98); + hottub.off(); + } + public void undo() { + hottub.on(); + } +} diff --git a/HF_DP/src/headfirst/command/party/HottubOnCommand.java b/HF_DP/src/headfirst/command/party/HottubOnCommand.java new file mode 100644 index 00000000..493acd20 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/HottubOnCommand.java @@ -0,0 +1,17 @@ +package headfirst.command.party; + +public class HottubOnCommand implements Command { + Hottub hottub; + + public HottubOnCommand(Hottub hottub) { + this.hottub = hottub; + } + public void execute() { + hottub.on(); + hottub.setTemperature(104); + hottub.circulate(); + } + public void undo() { + hottub.off(); + } +} diff --git a/HF_DP/src/headfirst/command/party/Light.java b/HF_DP/src/headfirst/command/party/Light.java new file mode 100644 index 00000000..3a74c632 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/Light.java @@ -0,0 +1,34 @@ +package headfirst.command.party; + +public class Light { + String location; + int level; + + public Light(String location) { + this.location = location; + } + + public void on() { + level = 100; + System.out.println("Light is on"); + } + + public void off() { + level = 0; + System.out.println("Light is off"); + } + + public void dim(int level) { + this.level = level; + if (level == 0) { + off(); + } + else { + System.out.println("Light is dimmed to " + level + "%"); + } + } + + public int getLevel() { + return level; + } +} diff --git a/HF_DP/src/headfirst/command/party/LightOffCommand.java b/HF_DP/src/headfirst/command/party/LightOffCommand.java new file mode 100644 index 00000000..24bb480b --- /dev/null +++ b/HF_DP/src/headfirst/command/party/LightOffCommand.java @@ -0,0 +1,17 @@ +package headfirst.command.party; + +public class LightOffCommand implements Command { + Light light; + + public LightOffCommand(Light light) { + this.light = light; + } + + public void execute() { + light.off(); + } + + public void undo() { + light.on(); + } +} diff --git a/HF_DP/src/headfirst/command/party/LightOnCommand.java b/HF_DP/src/headfirst/command/party/LightOnCommand.java new file mode 100644 index 00000000..d767bce4 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/LightOnCommand.java @@ -0,0 +1,17 @@ +package headfirst.command.party; + +public class LightOnCommand implements Command { + Light light; + + public LightOnCommand(Light light) { + this.light = light; + } + + public void execute() { + light.on(); + } + + public void undo() { + light.off(); + } +} diff --git a/HF_DP/src/headfirst/command/party/LivingroomLightOffCommand.java b/HF_DP/src/headfirst/command/party/LivingroomLightOffCommand.java new file mode 100644 index 00000000..aa532a51 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/LivingroomLightOffCommand.java @@ -0,0 +1,15 @@ +package headfirst.command.party; + +public class LivingroomLightOffCommand implements Command { + Light light; + + public LivingroomLightOffCommand(Light light) { + this.light = light; + } + public void execute() { + light.off(); + } + public void undo() { + light.on(); + } +} diff --git a/HF_DP/src/headfirst/command/party/LivingroomLightOnCommand.java b/HF_DP/src/headfirst/command/party/LivingroomLightOnCommand.java new file mode 100644 index 00000000..57e4844e --- /dev/null +++ b/HF_DP/src/headfirst/command/party/LivingroomLightOnCommand.java @@ -0,0 +1,15 @@ +package headfirst.command.party; + +public class LivingroomLightOnCommand implements Command { + Light light; + + public LivingroomLightOnCommand(Light light) { + this.light = light; + } + public void execute() { + light.on(); + } + public void undo() { + light.off(); + } +} diff --git a/HF_DP/src/headfirst/command/party/MacroCommand.java b/HF_DP/src/headfirst/command/party/MacroCommand.java new file mode 100644 index 00000000..a821fe7d --- /dev/null +++ b/HF_DP/src/headfirst/command/party/MacroCommand.java @@ -0,0 +1,25 @@ +package headfirst.command.party; + +public class MacroCommand implements Command { + Command[] commands; + + public MacroCommand(Command[] commands) { + this.commands = commands; + } + + public void execute() { + for (int i = 0; i < commands.length; i++) { + commands[i].execute(); + } + } + + /** + * NOTE: these commands have to be done backwards to ensure proper undo functionality + */ + public void undo() { + for (int i = commands.length -1; i >= 0; i--) { + commands[i].undo(); + } + } +} + diff --git a/HF_DP/src/headfirst/command/party/NoCommand.java b/HF_DP/src/headfirst/command/party/NoCommand.java new file mode 100644 index 00000000..1d094356 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/NoCommand.java @@ -0,0 +1,6 @@ +package headfirst.command.party; + +public class NoCommand implements Command { + public void execute() { } + public void undo() { } +} diff --git a/HF_DP/src/headfirst/command/party/RemoteControl.java b/HF_DP/src/headfirst/command/party/RemoteControl.java new file mode 100644 index 00000000..7fc7f737 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/RemoteControl.java @@ -0,0 +1,54 @@ +package headfirst.command.party; + +import java.util.*; + +// +// This is the invoker +// +public class RemoteControl { + Command[] onCommands; + Command[] offCommands; + Command undoCommand; + + public RemoteControl() { + onCommands = new Command[7]; + offCommands = new Command[7]; + + Command noCommand = new NoCommand(); + for(int i=0;i<7;i++) { + onCommands[i] = noCommand; + offCommands[i] = noCommand; + } + undoCommand = noCommand; + } + + public void setCommand(int slot, Command onCommand, Command offCommand) { + onCommands[slot] = onCommand; + offCommands[slot] = offCommand; + } + + public void onButtonWasPushed(int slot) { + onCommands[slot].execute(); + undoCommand = onCommands[slot]; + } + + public void offButtonWasPushed(int slot) { + offCommands[slot].execute(); + undoCommand = offCommands[slot]; + } + + public void undoButtonWasPushed() { + undoCommand.undo(); + } + + public String toString() { + StringBuffer stringBuff = new StringBuffer(); + stringBuff.append("\n------ Remote Control -------\n"); + for (int i = 0; i < onCommands.length; i++) { + stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName() + + " " + offCommands[i].getClass().getName() + "\n"); + } + stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n"); + return stringBuff.toString(); + } +} diff --git a/HF_DP/src/headfirst/command/party/RemoteLoader.java b/HF_DP/src/headfirst/command/party/RemoteLoader.java new file mode 100644 index 00000000..478f1f41 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/RemoteLoader.java @@ -0,0 +1,37 @@ +package headfirst.command.party; + +public class RemoteLoader { + + public static void main(String[] args) { + + RemoteControl remoteControl = new RemoteControl(); + + Light light = new Light("Living Room"); + TV tv = new TV("Living Room"); + Stereo stereo = new Stereo("Living Room"); + Hottub hottub = new Hottub(); + + LightOnCommand lightOn = new LightOnCommand(light); + StereoOnCommand stereoOn = new StereoOnCommand(stereo); + TVOnCommand tvOn = new TVOnCommand(tv); + HottubOnCommand hottubOn = new HottubOnCommand(hottub); + LightOffCommand lightOff = new LightOffCommand(light); + StereoOffCommand stereoOff = new StereoOffCommand(stereo); + TVOffCommand tvOff = new TVOffCommand(tv); + HottubOffCommand hottubOff = new HottubOffCommand(hottub); + + Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn}; + Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff}; + + MacroCommand partyOnMacro = new MacroCommand(partyOn); + MacroCommand partyOffMacro = new MacroCommand(partyOff); + + remoteControl.setCommand(0, partyOnMacro, partyOffMacro); + + System.out.println(remoteControl); + System.out.println("--- Pushing Macro On---"); + remoteControl.onButtonWasPushed(0); + System.out.println("--- Pushing Macro Off---"); + remoteControl.offButtonWasPushed(0); + } +} diff --git a/HF_DP/src/headfirst/command/party/Stereo.java b/HF_DP/src/headfirst/command/party/Stereo.java new file mode 100644 index 00000000..361d09e0 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/Stereo.java @@ -0,0 +1,35 @@ +package headfirst.command.party; + +public class Stereo { + String location; + + public Stereo(String location) { + this.location = location; + } + + public void on() { + System.out.println(location + " stereo is on"); + } + + public void off() { + System.out.println(location + " stereo is off"); + } + + public void setCD() { + System.out.println(location + " stereo is set for CD input"); + } + + public void setDVD() { + System.out.println(location + " stereo is set for DVD input"); + } + + public void setRadio() { + System.out.println(location + " stereo is set for Radio"); + } + + public void setVolume(int volume) { + // code to set the volume + // valid range: 1-11 (after all 11 is better than 10, right?) + System.out.println(location + " Stereo volume set to " + volume); + } +} diff --git a/HF_DP/src/headfirst/command/party/StereoOffCommand.java b/HF_DP/src/headfirst/command/party/StereoOffCommand.java new file mode 100644 index 00000000..c8e515db --- /dev/null +++ b/HF_DP/src/headfirst/command/party/StereoOffCommand.java @@ -0,0 +1,17 @@ +package headfirst.command.party; + +public class StereoOffCommand implements Command { + Stereo stereo; + + public StereoOffCommand(Stereo stereo) { + this.stereo = stereo; + } + + public void execute() { + stereo.off(); + } + + public void undo() { + stereo.on(); + } +} diff --git a/HF_DP/src/headfirst/command/party/StereoOnCommand.java b/HF_DP/src/headfirst/command/party/StereoOnCommand.java new file mode 100644 index 00000000..965c94da --- /dev/null +++ b/HF_DP/src/headfirst/command/party/StereoOnCommand.java @@ -0,0 +1,17 @@ +package headfirst.command.party; + +public class StereoOnCommand implements Command { + Stereo stereo; + + public StereoOnCommand(Stereo stereo) { + this.stereo = stereo; + } + + public void execute() { + stereo.on(); + } + + public void undo() { + stereo.off(); + } +} diff --git a/HF_DP/src/headfirst/command/party/StereoOnWithCDCommand.java b/HF_DP/src/headfirst/command/party/StereoOnWithCDCommand.java new file mode 100644 index 00000000..6b6d8d99 --- /dev/null +++ b/HF_DP/src/headfirst/command/party/StereoOnWithCDCommand.java @@ -0,0 +1,19 @@ +package headfirst.command.party; + +public class StereoOnWithCDCommand implements Command { + Stereo stereo; + + public StereoOnWithCDCommand(Stereo stereo) { + this.stereo = stereo; + } + + public void execute() { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } + + public void undo() { + stereo.off(); + } +} diff --git a/HF_DP/src/headfirst/command/party/TV.java b/HF_DP/src/headfirst/command/party/TV.java new file mode 100644 index 00000000..21c2e59e --- /dev/null +++ b/HF_DP/src/headfirst/command/party/TV.java @@ -0,0 +1,23 @@ +package headfirst.command.party; + +public class TV { + String location; + int channel; + + public TV(String location) { + this.location = location; + } + + public void on() { + System.out.println(location + " TV is on"); + } + + public void off() { + System.out.println(location + " TV is off"); + } + + public void setInputChannel() { + this.channel = 3; + System.out.println(location + " TV channel is set for DVD"); + } +} diff --git a/HF_DP/src/headfirst/command/party/TVOffCommand.java b/HF_DP/src/headfirst/command/party/TVOffCommand.java new file mode 100644 index 00000000..446b5d4b --- /dev/null +++ b/HF_DP/src/headfirst/command/party/TVOffCommand.java @@ -0,0 +1,17 @@ +package headfirst.command.party; + +public class TVOffCommand implements Command { + TV tv; + + public TVOffCommand(TV tv) { + this.tv= tv; + } + + public void execute() { + tv.off(); + } + + public void undo() { + tv.on(); + } +} diff --git a/HF_DP/src/headfirst/command/party/TVOnCommand.java b/HF_DP/src/headfirst/command/party/TVOnCommand.java new file mode 100644 index 00000000..40bfed2d --- /dev/null +++ b/HF_DP/src/headfirst/command/party/TVOnCommand.java @@ -0,0 +1,18 @@ +package headfirst.command.party; + +public class TVOnCommand implements Command { + TV tv; + + public TVOnCommand(TV tv) { + this.tv= tv; + } + + public void execute() { + tv.on(); + tv.setInputChannel(); + } + + public void undo() { + tv.off(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/CeilingFan.java b/HF_DP/src/headfirst/command/remote/CeilingFan.java new file mode 100644 index 00000000..c505c2a1 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/CeilingFan.java @@ -0,0 +1,42 @@ +package headfirst.command.remote; + +public class CeilingFan { + String location = ""; + int level; + public static final int HIGH = 2; + public static final int MEDIUM = 1; + public static final int LOW = 0; + + public CeilingFan(String location) { + this.location = location; + } + + public void high() { + // turns the ceiling fan on to high + level = HIGH; + System.out.println(location + " ceiling fan is on high"); + + } + + public void medium() { + // turns the ceiling fan on to medium + level = MEDIUM; + System.out.println(location + " ceiling fan is on medium"); + } + + public void low() { + // turns the ceiling fan on to low + level = LOW; + System.out.println(location + " ceiling fan is on low"); + } + + public void off() { + // turns the ceiling fan off + level = 0; + System.out.println(location + " ceiling fan is off"); + } + + public int getSpeed() { + return level; + } +} diff --git a/HF_DP/src/headfirst/command/remote/CeilingFanOffCommand.java b/HF_DP/src/headfirst/command/remote/CeilingFanOffCommand.java new file mode 100644 index 00000000..e42c2705 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/CeilingFanOffCommand.java @@ -0,0 +1,12 @@ +package headfirst.command.remote; + +public class CeilingFanOffCommand implements Command { + CeilingFan ceilingFan; + + public CeilingFanOffCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + public void execute() { + ceilingFan.off(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/CeilingFanOnCommand.java b/HF_DP/src/headfirst/command/remote/CeilingFanOnCommand.java new file mode 100644 index 00000000..28cbb01b --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/CeilingFanOnCommand.java @@ -0,0 +1,12 @@ +package headfirst.command.remote; + +public class CeilingFanOnCommand implements Command { + CeilingFan ceilingFan; + + public CeilingFanOnCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + public void execute() { + ceilingFan.high(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/Command.java b/HF_DP/src/headfirst/command/remote/Command.java new file mode 100644 index 00000000..c164d3a5 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/Command.java @@ -0,0 +1,5 @@ +package headfirst.command.remote; + +public interface Command { + public void execute(); +} diff --git a/HF_DP/src/headfirst/command/remote/GarageDoor.java b/HF_DP/src/headfirst/command/remote/GarageDoor.java new file mode 100644 index 00000000..9a34fac9 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/GarageDoor.java @@ -0,0 +1,29 @@ +package headfirst.command.remote; + +public class GarageDoor { + String location; + + public GarageDoor(String location) { + this.location = location; + } + + public void up() { + System.out.println(location + " garage Door is Up"); + } + + public void down() { + System.out.println(location + " garage Door is Down"); + } + + public void stop() { + System.out.println(location + " garage Door is Stopped"); + } + + public void lightOn() { + System.out.println(location + " garage light is on"); + } + + public void lightOff() { + System.out.println(location + " garage light is off"); + } +} diff --git a/HF_DP/src/headfirst/command/remote/GarageDoorDownCommand.java b/HF_DP/src/headfirst/command/remote/GarageDoorDownCommand.java new file mode 100644 index 00000000..9c722ef8 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/GarageDoorDownCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.remote; + +public class GarageDoorDownCommand implements Command { + GarageDoor garageDoor; + + public GarageDoorDownCommand(GarageDoor garageDoor) { + this.garageDoor = garageDoor; + } + + public void execute() { + garageDoor.up(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/GarageDoorUpCommand.java b/HF_DP/src/headfirst/command/remote/GarageDoorUpCommand.java new file mode 100644 index 00000000..15d04777 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/GarageDoorUpCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.remote; + +public class GarageDoorUpCommand implements Command { + GarageDoor garageDoor; + + public GarageDoorUpCommand(GarageDoor garageDoor) { + this.garageDoor = garageDoor; + } + + public void execute() { + garageDoor.up(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/Hottub.java b/HF_DP/src/headfirst/command/remote/Hottub.java new file mode 100644 index 00000000..d2a967e3 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/Hottub.java @@ -0,0 +1,56 @@ +package headfirst.command.remote; + +public class Hottub { + boolean on; + int temperature; + + public Hottub() { + } + + public void on() { + on = true; + } + + public void off() { + on = false; + } + + public void bubblesOn() { + if (on) { + System.out.println("Hottub is bubbling!"); + } + } + + public void bubblesOff() { + if (on) { + System.out.println("Hottub is not bubbling"); + } + } + + public void jetsOn() { + if (on) { + System.out.println("Hottub jets are on"); + } + } + + public void jetsOff() { + if (on) { + System.out.println("Hottub jets are off"); + } + } + + public void setTemperature(int temperature) { + this.temperature = temperature; + } + + public void heat() { + temperature = 105; + System.out.println("Hottub is heating to a steaming 105 degrees"); + } + + public void cool() { + temperature = 98; + System.out.println("Hottub is cooling to 98 degrees"); + } + +} diff --git a/HF_DP/src/headfirst/command/remote/HottubOffCommand.java b/HF_DP/src/headfirst/command/remote/HottubOffCommand.java new file mode 100644 index 00000000..4a22741e --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/HottubOffCommand.java @@ -0,0 +1,14 @@ +package headfirst.command.remote; + +public class HottubOffCommand implements Command { + Hottub hottub; + + public HottubOffCommand(Hottub hottub) { + this.hottub = hottub; + } + + public void execute() { + hottub.cool(); + hottub.off(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/HottubOnCommand.java b/HF_DP/src/headfirst/command/remote/HottubOnCommand.java new file mode 100644 index 00000000..fc587702 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/HottubOnCommand.java @@ -0,0 +1,15 @@ +package headfirst.command.remote; + +public class HottubOnCommand implements Command { + Hottub hottub; + + public HottubOnCommand(Hottub hottub) { + this.hottub = hottub; + } + + public void execute() { + hottub.on(); + hottub.heat(); + hottub.bubblesOn(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/Light.java b/HF_DP/src/headfirst/command/remote/Light.java new file mode 100644 index 00000000..0ef421de --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/Light.java @@ -0,0 +1,17 @@ +package headfirst.command.remote; + +public class Light { + String location = ""; + + public Light(String location) { + this.location = location; + } + + public void on() { + System.out.println(location + " light is on"); + } + + public void off() { + System.out.println(location + " light is off"); + } +} diff --git a/HF_DP/src/headfirst/command/remote/LightOffCommand.java b/HF_DP/src/headfirst/command/remote/LightOffCommand.java new file mode 100644 index 00000000..6f0ce86f --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/LightOffCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.remote; + +public class LightOffCommand implements Command { + Light light; + + public LightOffCommand(Light light) { + this.light = light; + } + + public void execute() { + light.off(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/LightOnCommand.java b/HF_DP/src/headfirst/command/remote/LightOnCommand.java new file mode 100644 index 00000000..e7c680d2 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/LightOnCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.remote; + +public class LightOnCommand implements Command { + Light light; + + public LightOnCommand(Light light) { + this.light = light; + } + + public void execute() { + light.on(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/LivingroomLightOffCommand.java b/HF_DP/src/headfirst/command/remote/LivingroomLightOffCommand.java new file mode 100644 index 00000000..f90e5444 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/LivingroomLightOffCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.remote; + +public class LivingroomLightOffCommand implements Command { + Light light; + + public LivingroomLightOffCommand(Light light) { + this.light = light; + } + + public void execute() { + light.off(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/LivingroomLightOnCommand.java b/HF_DP/src/headfirst/command/remote/LivingroomLightOnCommand.java new file mode 100644 index 00000000..8ca938b6 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/LivingroomLightOnCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.remote; + +public class LivingroomLightOnCommand implements Command { + Light light; + + public LivingroomLightOnCommand(Light light) { + this.light = light; + } + + public void execute() { + light.on(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/NoCommand.java b/HF_DP/src/headfirst/command/remote/NoCommand.java new file mode 100644 index 00000000..a10ca1cb --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/NoCommand.java @@ -0,0 +1,5 @@ +package headfirst.command.remote; + +public class NoCommand implements Command { + public void execute() { } +} diff --git a/HF_DP/src/headfirst/command/remote/RemoteControl.java b/HF_DP/src/headfirst/command/remote/RemoteControl.java new file mode 100644 index 00000000..319d3b7a --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/RemoteControl.java @@ -0,0 +1,45 @@ +package headfirst.command.remote; + +import java.util.*; + +// +// This is the invoker +// +public class RemoteControl { + Command[] onCommands; + Command[] offCommands; + + public RemoteControl() { + onCommands = new Command[7]; + offCommands = new Command[7]; + + Command noCommand = new NoCommand(); + for (int i = 0; i < 7; i++) { + onCommands[i] = noCommand; + offCommands[i] = noCommand; + } + } + + public void setCommand(int slot, Command onCommand, Command offCommand) { + onCommands[slot] = onCommand; + offCommands[slot] = offCommand; + } + + public void onButtonWasPushed(int slot) { + onCommands[slot].execute(); + } + + public void offButtonWasPushed(int slot) { + offCommands[slot].execute(); + } + + public String toString() { + StringBuffer stringBuff = new StringBuffer(); + stringBuff.append("\n------ Remote Control -------\n"); + for (int i = 0; i < onCommands.length; i++) { + stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName() + + " " + offCommands[i].getClass().getName() + "\n"); + } + return stringBuff.toString(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/RemoteLoader.java b/HF_DP/src/headfirst/command/remote/RemoteLoader.java new file mode 100644 index 00000000..f9a7a7b6 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/RemoteLoader.java @@ -0,0 +1,54 @@ +package headfirst.command.remote; + +public class RemoteLoader { + + public static void main(String[] args) { + RemoteControl remoteControl = new RemoteControl(); + + Light livingRoomLight = new Light("Living Room"); + Light kitchenLight = new Light("Kitchen"); + CeilingFan ceilingFan= new CeilingFan("Living Room"); + GarageDoor garageDoor = new GarageDoor(""); + Stereo stereo = new Stereo("Living Room"); + + LightOnCommand livingRoomLightOn = + new LightOnCommand(livingRoomLight); + LightOffCommand livingRoomLightOff = + new LightOffCommand(livingRoomLight); + LightOnCommand kitchenLightOn = + new LightOnCommand(kitchenLight); + LightOffCommand kitchenLightOff = + new LightOffCommand(kitchenLight); + + CeilingFanOnCommand ceilingFanOn = + new CeilingFanOnCommand(ceilingFan); + CeilingFanOffCommand ceilingFanOff = + new CeilingFanOffCommand(ceilingFan); + + GarageDoorUpCommand garageDoorUp = + new GarageDoorUpCommand(garageDoor); + GarageDoorDownCommand garageDoorDown = + new GarageDoorDownCommand(garageDoor); + + StereoOnWithCDCommand stereoOnWithCD = + new StereoOnWithCDCommand(stereo); + StereoOffCommand stereoOff = + new StereoOffCommand(stereo); + + remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff); + remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff); + remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff); + remoteControl.setCommand(3, stereoOnWithCD, stereoOff); + + System.out.println(remoteControl); + + remoteControl.onButtonWasPushed(0); + remoteControl.offButtonWasPushed(0); + remoteControl.onButtonWasPushed(1); + remoteControl.offButtonWasPushed(1); + remoteControl.onButtonWasPushed(2); + remoteControl.offButtonWasPushed(2); + remoteControl.onButtonWasPushed(3); + remoteControl.offButtonWasPushed(3); + } +} diff --git a/HF_DP/src/headfirst/command/remote/Stereo.java b/HF_DP/src/headfirst/command/remote/Stereo.java new file mode 100644 index 00000000..c1cabc04 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/Stereo.java @@ -0,0 +1,35 @@ +package headfirst.command.remote; + +public class Stereo { + String location; + + public Stereo(String location) { + this.location = location; + } + + public void on() { + System.out.println(location + " stereo is on"); + } + + public void off() { + System.out.println(location + " stereo is off"); + } + + public void setCD() { + System.out.println(location + " stereo is set for CD input"); + } + + public void setDVD() { + System.out.println(location + " stereo is set for DVD input"); + } + + public void setRadio() { + System.out.println(location + " stereo is set for Radio"); + } + + public void setVolume(int volume) { + // code to set the volume + // valid range: 1-11 (after all 11 is better than 10, right?) + System.out.println(location + " Stereo volume set to " + volume); + } +} diff --git a/HF_DP/src/headfirst/command/remote/StereoOffCommand.java b/HF_DP/src/headfirst/command/remote/StereoOffCommand.java new file mode 100644 index 00000000..99b43a03 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/StereoOffCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.remote; + +public class StereoOffCommand implements Command { + Stereo stereo; + + public StereoOffCommand(Stereo stereo) { + this.stereo = stereo; + } + + public void execute() { + stereo.off(); + } +} diff --git a/HF_DP/src/headfirst/command/remote/StereoOnWithCDCommand.java b/HF_DP/src/headfirst/command/remote/StereoOnWithCDCommand.java new file mode 100644 index 00000000..89e19d25 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/StereoOnWithCDCommand.java @@ -0,0 +1,15 @@ +package headfirst.command.remote; + +public class StereoOnWithCDCommand implements Command { + Stereo stereo; + + public StereoOnWithCDCommand(Stereo stereo) { + this.stereo = stereo; + } + + public void execute() { + stereo.on(); + stereo.setCD(); + stereo.setVolume(11); + } +} diff --git a/HF_DP/src/headfirst/command/remote/TV.java b/HF_DP/src/headfirst/command/remote/TV.java new file mode 100644 index 00000000..41ca0028 --- /dev/null +++ b/HF_DP/src/headfirst/command/remote/TV.java @@ -0,0 +1,23 @@ +package headfirst.command.remote; + +public class TV { + String location; + int channel; + + public TV(String location) { + this.location = location; + } + + public void on() { + System.out.println("TV is on"); + } + + public void off() { + System.out.println("TV is off"); + } + + public void setInputChannel() { + this.channel = 3; + System.out.println("Channel is set for VCR"); + } +} diff --git a/HF_DP/src/headfirst/command/simpleremote/Command.java b/HF_DP/src/headfirst/command/simpleremote/Command.java new file mode 100644 index 00000000..78180500 --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/Command.java @@ -0,0 +1,5 @@ +package headfirst.command.simpleremote; + +public interface Command { + public void execute(); +} diff --git a/HF_DP/src/headfirst/command/simpleremote/GarageDoor.java b/HF_DP/src/headfirst/command/simpleremote/GarageDoor.java new file mode 100644 index 00000000..a96a1687 --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/GarageDoor.java @@ -0,0 +1,27 @@ +package headfirst.command.simpleremote; + +public class GarageDoor { + + public GarageDoor() { + } + + public void up() { + System.out.println("Garage Door is Open"); + } + + public void down() { + System.out.println("Garage Door is Closed"); + } + + public void stop() { + System.out.println("Garage Door is Stopped"); + } + + public void lightOn() { + System.out.println("Garage light is on"); + } + + public void lightOff() { + System.out.println("Garage light is off"); + } +} diff --git a/HF_DP/src/headfirst/command/simpleremote/GarageDoorOpenCommand.java b/HF_DP/src/headfirst/command/simpleremote/GarageDoorOpenCommand.java new file mode 100644 index 00000000..dc2c5bed --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/GarageDoorOpenCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.simpleremote; + +public class GarageDoorOpenCommand implements Command { + GarageDoor garageDoor; + + public GarageDoorOpenCommand(GarageDoor garageDoor) { + this.garageDoor = garageDoor; + } + + public void execute() { + garageDoor.up(); + } +} diff --git a/HF_DP/src/headfirst/command/simpleremote/Light.java b/HF_DP/src/headfirst/command/simpleremote/Light.java new file mode 100644 index 00000000..68c32163 --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/Light.java @@ -0,0 +1,15 @@ +package headfirst.command.simpleremote; + +public class Light { + + public Light() { + } + + public void on() { + System.out.println("Light is on"); + } + + public void off() { + System.out.println("Light is off"); + } +} diff --git a/HF_DP/src/headfirst/command/simpleremote/LightOffCommand.java b/HF_DP/src/headfirst/command/simpleremote/LightOffCommand.java new file mode 100644 index 00000000..d89ecf99 --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/LightOffCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.simpleremote; + +public class LightOffCommand implements Command { + Light light; + + public LightOffCommand(Light light) { + this.light = light; + } + + public void execute() { + light.off(); + } +} diff --git a/HF_DP/src/headfirst/command/simpleremote/LightOnCommand.java b/HF_DP/src/headfirst/command/simpleremote/LightOnCommand.java new file mode 100644 index 00000000..900d5672 --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/LightOnCommand.java @@ -0,0 +1,13 @@ +package headfirst.command.simpleremote; + +public class LightOnCommand implements Command { + Light light; + + public LightOnCommand(Light light) { + this.light = light; + } + + public void execute() { + light.on(); + } +} diff --git a/HF_DP/src/headfirst/command/simpleremote/RemoteControlTest.java b/HF_DP/src/headfirst/command/simpleremote/RemoteControlTest.java new file mode 100644 index 00000000..b70cdf76 --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/RemoteControlTest.java @@ -0,0 +1,17 @@ +package headfirst.command.simpleremote; + +public class RemoteControlTest { + public static void main(String[] args) { + SimpleRemoteControl remote = new SimpleRemoteControl(); + Light light = new Light(); + GarageDoor garageDoor = new GarageDoor(); + LightOnCommand lightOn = new LightOnCommand(light); + GarageDoorOpenCommand garageOpen = + new GarageDoorOpenCommand(garageDoor); + + remote.setCommand(lightOn); + remote.buttonWasPressed(); + remote.setCommand(garageOpen); + remote.buttonWasPressed(); + } +} diff --git a/HF_DP/src/headfirst/command/simpleremote/SimpleRemoteControl.java b/HF_DP/src/headfirst/command/simpleremote/SimpleRemoteControl.java new file mode 100644 index 00000000..7b0bb4fd --- /dev/null +++ b/HF_DP/src/headfirst/command/simpleremote/SimpleRemoteControl.java @@ -0,0 +1,20 @@ +package headfirst.command.simpleremote; + +import java.util.*; + +// +// This is the invoker +// +public class SimpleRemoteControl { + Command slot; + + public SimpleRemoteControl() {} + + public void setCommand(Command command) { + slot = command; + } + + public void buttonWasPressed() { + slot.execute(); + } +} diff --git a/HF_DP/src/headfirst/command/undo/CeilingFan.java b/HF_DP/src/headfirst/command/undo/CeilingFan.java new file mode 100644 index 00000000..59e461cd --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/CeilingFan.java @@ -0,0 +1,39 @@ +package headfirst.command.undo; + +public class CeilingFan { + public static final int HIGH = 3; + public static final int MEDIUM = 2; + public static final int LOW = 1; + public static final int OFF = 0; + String location; + int speed; + + public CeilingFan(String location) { + this.location = location; + speed = OFF; + } + + public void high() { + speed = HIGH; + System.out.println(location + " ceiling fan is on high"); + } + + public void medium() { + speed = MEDIUM; + System.out.println(location + " ceiling fan is on medium"); + } + + public void low() { + speed = LOW; + System.out.println(location + " ceiling fan is on low"); + } + + public void off() { + speed = OFF; + System.out.println(location + " ceiling fan is off"); + } + + public int getSpeed() { + return speed; + } +} diff --git a/HF_DP/src/headfirst/command/undo/CeilingFanHighCommand.java b/HF_DP/src/headfirst/command/undo/CeilingFanHighCommand.java new file mode 100644 index 00000000..33bb558b --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/CeilingFanHighCommand.java @@ -0,0 +1,27 @@ +package headfirst.command.undo; + +public class CeilingFanHighCommand implements Command { + CeilingFan ceilingFan; + int prevSpeed; + + public CeilingFanHighCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + + public void execute() { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.high(); + } + + public void undo() { + if (prevSpeed == CeilingFan.HIGH) { + ceilingFan.high(); + } else if (prevSpeed == CeilingFan.MEDIUM) { + ceilingFan.medium(); + } else if (prevSpeed == CeilingFan.LOW) { + ceilingFan.low(); + } else if (prevSpeed == CeilingFan.OFF) { + ceilingFan.off(); + } + } +} diff --git a/HF_DP/src/headfirst/command/undo/CeilingFanLowCommand.java b/HF_DP/src/headfirst/command/undo/CeilingFanLowCommand.java new file mode 100644 index 00000000..6b9037c0 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/CeilingFanLowCommand.java @@ -0,0 +1,27 @@ +package headfirst.command.undo; + +public class CeilingFanLowCommand implements Command { + CeilingFan ceilingFan; + int prevSpeed; + + public CeilingFanLowCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + + public void execute() { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.low(); + } + + public void undo() { + if (prevSpeed == CeilingFan.HIGH) { + ceilingFan.high(); + } else if (prevSpeed == CeilingFan.MEDIUM) { + ceilingFan.medium(); + } else if (prevSpeed == CeilingFan.LOW) { + ceilingFan.low(); + } else if (prevSpeed == CeilingFan.OFF) { + ceilingFan.off(); + } + } +} diff --git a/HF_DP/src/headfirst/command/undo/CeilingFanMediumCommand.java b/HF_DP/src/headfirst/command/undo/CeilingFanMediumCommand.java new file mode 100644 index 00000000..d3fa43b4 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/CeilingFanMediumCommand.java @@ -0,0 +1,27 @@ +package headfirst.command.undo; + +public class CeilingFanMediumCommand implements Command { + CeilingFan ceilingFan; + int prevSpeed; + + public CeilingFanMediumCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + + public void execute() { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.medium(); + } + + public void undo() { + if (prevSpeed == CeilingFan.HIGH) { + ceilingFan.high(); + } else if (prevSpeed == CeilingFan.MEDIUM) { + ceilingFan.medium(); + } else if (prevSpeed == CeilingFan.LOW) { + ceilingFan.low(); + } else if (prevSpeed == CeilingFan.OFF) { + ceilingFan.off(); + } + } +} diff --git a/HF_DP/src/headfirst/command/undo/CeilingFanOffCommand.java b/HF_DP/src/headfirst/command/undo/CeilingFanOffCommand.java new file mode 100644 index 00000000..8b354c20 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/CeilingFanOffCommand.java @@ -0,0 +1,27 @@ +package headfirst.command.undo; + +public class CeilingFanOffCommand implements Command { + CeilingFan ceilingFan; + int prevSpeed; + + public CeilingFanOffCommand(CeilingFan ceilingFan) { + this.ceilingFan = ceilingFan; + } + + public void execute() { + prevSpeed = ceilingFan.getSpeed(); + ceilingFan.off(); + } + + public void undo() { + if (prevSpeed == CeilingFan.HIGH) { + ceilingFan.high(); + } else if (prevSpeed == CeilingFan.MEDIUM) { + ceilingFan.medium(); + } else if (prevSpeed == CeilingFan.LOW) { + ceilingFan.low(); + } else if (prevSpeed == CeilingFan.OFF) { + ceilingFan.off(); + } + } +} diff --git a/HF_DP/src/headfirst/command/undo/Command.java b/HF_DP/src/headfirst/command/undo/Command.java new file mode 100644 index 00000000..4868b852 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/Command.java @@ -0,0 +1,6 @@ +package headfirst.command.undo; + +public interface Command { + public void execute(); + public void undo(); +} diff --git a/HF_DP/src/headfirst/command/undo/DimmerLightOffCommand.java b/HF_DP/src/headfirst/command/undo/DimmerLightOffCommand.java new file mode 100644 index 00000000..74d0c211 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/DimmerLightOffCommand.java @@ -0,0 +1,20 @@ +package headfirst.command.undo; + +public class DimmerLightOffCommand implements Command { + Light light; + int prevLevel; + + public DimmerLightOffCommand(Light light) { + this.light = light; + prevLevel = 100; + } + + public void execute() { + prevLevel = light.getLevel(); + light.off(); + } + + public void undo() { + light.dim(prevLevel); + } +} diff --git a/HF_DP/src/headfirst/command/undo/DimmerLightOnCommand.java b/HF_DP/src/headfirst/command/undo/DimmerLightOnCommand.java new file mode 100644 index 00000000..2d8e13e2 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/DimmerLightOnCommand.java @@ -0,0 +1,19 @@ +package headfirst.command.undo; + +public class DimmerLightOnCommand implements Command { + Light light; + int prevLevel; + + public DimmerLightOnCommand(Light light) { + this.light = light; + } + + public void execute() { + prevLevel = light.getLevel(); + light.dim(75); + } + + public void undo() { + light.dim(prevLevel); + } +} diff --git a/HF_DP/src/headfirst/command/undo/Light.java b/HF_DP/src/headfirst/command/undo/Light.java new file mode 100644 index 00000000..df38902e --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/Light.java @@ -0,0 +1,34 @@ +package headfirst.command.undo; + +public class Light { + String location; + int level; + + public Light(String location) { + this.location = location; + } + + public void on() { + level = 100; + System.out.println("Light is on"); + } + + public void off() { + level = 0; + System.out.println("Light is off"); + } + + public void dim(int level) { + this.level = level; + if (level == 0) { + off(); + } + else { + System.out.println("Light is dimmed to " + level + "%"); + } + } + + public int getLevel() { + return level; + } +} diff --git a/HF_DP/src/headfirst/command/undo/LightOffCommand.java b/HF_DP/src/headfirst/command/undo/LightOffCommand.java new file mode 100644 index 00000000..fd3452bc --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/LightOffCommand.java @@ -0,0 +1,18 @@ +package headfirst.command.undo; + +public class LightOffCommand implements Command { + Light light; + int level; + public LightOffCommand(Light light) { + this.light = light; + } + + public void execute() { + level = light.getLevel(); + light.off(); + } + + public void undo() { + light.dim(level); + } +} diff --git a/HF_DP/src/headfirst/command/undo/LightOnCommand.java b/HF_DP/src/headfirst/command/undo/LightOnCommand.java new file mode 100644 index 00000000..32018553 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/LightOnCommand.java @@ -0,0 +1,18 @@ +package headfirst.command.undo; + +public class LightOnCommand implements Command { + Light light; + int level; + public LightOnCommand(Light light) { + this.light = light; + } + + public void execute() { + level = light.getLevel(); + light.on(); + } + + public void undo() { + light.dim(level); + } +} diff --git a/HF_DP/src/headfirst/command/undo/NoCommand.java b/HF_DP/src/headfirst/command/undo/NoCommand.java new file mode 100644 index 00000000..b836a716 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/NoCommand.java @@ -0,0 +1,6 @@ +package headfirst.command.undo; + +public class NoCommand implements Command { + public void execute() { } + public void undo() { } +} diff --git a/HF_DP/src/headfirst/command/undo/RemoteControlWithUndo.java b/HF_DP/src/headfirst/command/undo/RemoteControlWithUndo.java new file mode 100644 index 00000000..ad7912df --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/RemoteControlWithUndo.java @@ -0,0 +1,54 @@ +package headfirst.command.undo; + +import java.util.*; + +// +// This is the invoker +// +public class RemoteControlWithUndo { + Command[] onCommands; + Command[] offCommands; + Command undoCommand; + + public RemoteControlWithUndo() { + onCommands = new Command[7]; + offCommands = new Command[7]; + + Command noCommand = new NoCommand(); + for(int i=0;i<7;i++) { + onCommands[i] = noCommand; + offCommands[i] = noCommand; + } + undoCommand = noCommand; + } + + public void setCommand(int slot, Command onCommand, Command offCommand) { + onCommands[slot] = onCommand; + offCommands[slot] = offCommand; + } + + public void onButtonWasPushed(int slot) { + onCommands[slot].execute(); + undoCommand = onCommands[slot]; + } + + public void offButtonWasPushed(int slot) { + offCommands[slot].execute(); + undoCommand = offCommands[slot]; + } + + public void undoButtonWasPushed() { + undoCommand.undo(); + } + + public String toString() { + StringBuffer stringBuff = new StringBuffer(); + stringBuff.append("\n------ Remote Control -------\n"); + for (int i = 0; i < onCommands.length; i++) { + stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName() + + " " + offCommands[i].getClass().getName() + "\n"); + } + stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n"); + return stringBuff.toString(); + } +} diff --git a/HF_DP/src/headfirst/command/undo/RemoteLoader.java b/HF_DP/src/headfirst/command/undo/RemoteLoader.java new file mode 100644 index 00000000..bca49683 --- /dev/null +++ b/HF_DP/src/headfirst/command/undo/RemoteLoader.java @@ -0,0 +1,47 @@ +package headfirst.command.undo; + +public class RemoteLoader { + + public static void main(String[] args) { + RemoteControlWithUndo remoteControl = new RemoteControlWithUndo(); + + Light livingRoomLight = new Light("Living Room"); + + LightOnCommand livingRoomLightOn = + new LightOnCommand(livingRoomLight); + LightOffCommand livingRoomLightOff = + new LightOffCommand(livingRoomLight); + + remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff); + + remoteControl.onButtonWasPushed(0); + remoteControl.offButtonWasPushed(0); + System.out.println(remoteControl); + remoteControl.undoButtonWasPushed(); + remoteControl.offButtonWasPushed(0); + remoteControl.onButtonWasPushed(0); + System.out.println(remoteControl); + remoteControl.undoButtonWasPushed(); + + CeilingFan ceilingFan = new CeilingFan("Living Room"); + + CeilingFanMediumCommand ceilingFanMedium = + new CeilingFanMediumCommand(ceilingFan); + CeilingFanHighCommand ceilingFanHigh = + new CeilingFanHighCommand(ceilingFan); + CeilingFanOffCommand ceilingFanOff = + new CeilingFanOffCommand(ceilingFan); + + remoteControl.setCommand(0, ceilingFanMedium, ceilingFanOff); + remoteControl.setCommand(1, ceilingFanHigh, ceilingFanOff); + + remoteControl.onButtonWasPushed(0); + remoteControl.offButtonWasPushed(0); + System.out.println(remoteControl); + remoteControl.undoButtonWasPushed(); + + remoteControl.onButtonWasPushed(1); + System.out.println(remoteControl); + remoteControl.undoButtonWasPushed(); + } +} diff --git a/HF_DP/src/headfirst/composite/menu/Menu.java b/HF_DP/src/headfirst/composite/menu/Menu.java new file mode 100644 index 00000000..d20283c0 --- /dev/null +++ b/HF_DP/src/headfirst/composite/menu/Menu.java @@ -0,0 +1,48 @@ +package headfirst.composite.menu; + +import java.util.Iterator; +import java.util.ArrayList; + +public class Menu extends MenuComponent { + ArrayList menuComponents = new ArrayList(); + String name; + String description; + + public Menu(String name, String description) { + this.name = name; + this.description = description; + } + + public void add(MenuComponent menuComponent) { + menuComponents.add(menuComponent); + } + + public void remove(MenuComponent menuComponent) { + menuComponents.remove(menuComponent); + } + + public MenuComponent getChild(int i) { + return (MenuComponent)menuComponents.get(i); + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public void print() { + System.out.print("\n" + getName()); + System.out.println(", " + getDescription()); + System.out.println("---------------------"); + + Iterator iterator = menuComponents.iterator(); + while (iterator.hasNext()) { + MenuComponent menuComponent = + (MenuComponent)iterator.next(); + menuComponent.print(); + } + } +} diff --git a/HF_DP/src/headfirst/composite/menu/MenuComponent.java b/HF_DP/src/headfirst/composite/menu/MenuComponent.java new file mode 100644 index 00000000..03477f16 --- /dev/null +++ b/HF_DP/src/headfirst/composite/menu/MenuComponent.java @@ -0,0 +1,33 @@ +package headfirst.composite.menu; + +import java.util.*; + +public abstract class MenuComponent { + + public void add(MenuComponent menuComponent) { + throw new UnsupportedOperationException(); + } + public void remove(MenuComponent menuComponent) { + throw new UnsupportedOperationException(); + } + public MenuComponent getChild(int i) { + throw new UnsupportedOperationException(); + } + + public String getName() { + throw new UnsupportedOperationException(); + } + public String getDescription() { + throw new UnsupportedOperationException(); + } + public double getPrice() { + throw new UnsupportedOperationException(); + } + public boolean isVegetarian() { + throw new UnsupportedOperationException(); + } + + public void print() { + throw new UnsupportedOperationException(); + } +} diff --git a/HF_DP/src/headfirst/composite/menu/MenuItem.java b/HF_DP/src/headfirst/composite/menu/MenuItem.java new file mode 100644 index 00000000..cbb0cfde --- /dev/null +++ b/HF_DP/src/headfirst/composite/menu/MenuItem.java @@ -0,0 +1,47 @@ +package headfirst.composite.menu; + +import java.util.Iterator; +import java.util.ArrayList; + +public class MenuItem extends MenuComponent { + String name; + String description; + boolean vegetarian; + double price; + + public MenuItem(String name, + String description, + boolean vegetarian, + double price) + { + this.name = name; + this.description = description; + this.vegetarian = vegetarian; + this.price = price; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public double getPrice() { + return price; + } + + public boolean isVegetarian() { + return vegetarian; + } + + public void print() { + System.out.print(" " + getName()); + if (isVegetarian()) { + System.out.print("(v)"); + } + System.out.println(", " + getPrice()); + System.out.println(" -- " + getDescription()); + } +} diff --git a/HF_DP/src/headfirst/composite/menu/MenuTestDrive.java b/HF_DP/src/headfirst/composite/menu/MenuTestDrive.java new file mode 100644 index 00000000..21876d8d --- /dev/null +++ b/HF_DP/src/headfirst/composite/menu/MenuTestDrive.java @@ -0,0 +1,133 @@ +package headfirst.composite.menu; + +import java.util.*; + +public class MenuTestDrive { + public static void main(String args[]) { + MenuComponent pancakeHouseMenu = + new Menu("PANCAKE HOUSE MENU", "Breakfast"); + MenuComponent dinerMenu = + new Menu("DINER MENU", "Lunch"); + MenuComponent cafeMenu = + new Menu("CAFE MENU", "Dinner"); + MenuComponent dessertMenu = + new Menu("DESSERT MENU", "Dessert of course!"); + MenuComponent coffeeMenu = new Menu("COFFEE MENU", "Stuff to go with your afternoon coffee"); + + MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined"); + + allMenus.add(pancakeHouseMenu); + allMenus.add(dinerMenu); + allMenus.add(cafeMenu); + + pancakeHouseMenu.add(new MenuItem( + "K&B's Pancake Breakfast", + "Pancakes with scrambled eggs, and toast", + true, + 2.99)); + pancakeHouseMenu.add(new MenuItem( + "Regular Pancake Breakfast", + "Pancakes with fried eggs, sausage", + false, + 2.99)); + pancakeHouseMenu.add(new MenuItem( + "Blueberry Pancakes", + "Pancakes made with fresh blueberries, and blueberry syrup", + true, + 3.49)); + pancakeHouseMenu.add(new MenuItem( + "Waffles", + "Waffles, with your choice of blueberries or strawberries", + true, + 3.59)); + + dinerMenu.add(new MenuItem( + "Vegetarian BLT", + "(Fakin') Bacon with lettuce & tomato on whole wheat", + true, + 2.99)); + dinerMenu.add(new MenuItem( + "BLT", + "Bacon with lettuce & tomato on whole wheat", + false, + 2.99)); + dinerMenu.add(new MenuItem( + "Soup of the day", + "A bowl of the soup of the day, with a side of potato salad", + false, + 3.29)); + dinerMenu.add(new MenuItem( + "Hotdog", + "A hot dog, with saurkraut, relish, onions, topped with cheese", + false, + 3.05)); + dinerMenu.add(new MenuItem( + "Steamed Veggies and Brown Rice", + "Steamed vegetables over brown rice", + true, + 3.99)); + + dinerMenu.add(new MenuItem( + "Pasta", + "Spaghetti with Marinara Sauce, and a slice of sourdough bread", + true, + 3.89)); + + dinerMenu.add(dessertMenu); + + dessertMenu.add(new MenuItem( + "Apple Pie", + "Apple pie with a flakey crust, topped with vanilla icecream", + true, + 1.59)); + + dessertMenu.add(new MenuItem( + "Cheesecake", + "Creamy New York cheesecake, with a chocolate graham crust", + true, + 1.99)); + dessertMenu.add(new MenuItem( + "Sorbet", + "A scoop of raspberry and a scoop of lime", + true, + 1.89)); + + cafeMenu.add(new MenuItem( + "Veggie Burger and Air Fries", + "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", + true, + 3.99)); + cafeMenu.add(new MenuItem( + "Soup of the day", + "A cup of the soup of the day, with a side salad", + false, + 3.69)); + cafeMenu.add(new MenuItem( + "Burrito", + "A large burrito, with whole pinto beans, salsa, guacamole", + true, + 4.29)); + + cafeMenu.add(coffeeMenu); + + coffeeMenu.add(new MenuItem( + "Coffee Cake", + "Crumbly cake topped with cinnamon and walnuts", + true, + 1.59)); + coffeeMenu.add(new MenuItem( + "Bagel", + "Flavors include sesame, poppyseed, cinnamon raisin, pumpkin", + false, + 0.69)); + coffeeMenu.add(new MenuItem( + "Biscotti", + "Three almond or hazelnut biscotti cookies", + true, + 0.89)); + + Waitress waitress = new Waitress(allMenus); + + waitress.printMenu(); + } +} diff --git a/HF_DP/src/headfirst/composite/menu/Waitress.java b/HF_DP/src/headfirst/composite/menu/Waitress.java new file mode 100644 index 00000000..ba2df135 --- /dev/null +++ b/HF_DP/src/headfirst/composite/menu/Waitress.java @@ -0,0 +1,15 @@ +package headfirst.composite.menu; + +import java.util.Iterator; + +public class Waitress { + MenuComponent allMenus; + + public Waitress(MenuComponent allMenus) { + this.allMenus = allMenus; + } + + public void printMenu() { + allMenus.print(); + } +} diff --git a/HF_DP/src/headfirst/composite/menuiterator/CompositeIterator.java b/HF_DP/src/headfirst/composite/menuiterator/CompositeIterator.java new file mode 100644 index 00000000..36f14cba --- /dev/null +++ b/HF_DP/src/headfirst/composite/menuiterator/CompositeIterator.java @@ -0,0 +1,45 @@ +package headfirst.composite.menuiterator; + + +import java.util.*; + +public class CompositeIterator implements Iterator { + Stack stack = new Stack(); + + public CompositeIterator(Iterator iterator) { + stack.push(iterator); + } + + public Object next() { + if (hasNext()) { + Iterator iterator = (Iterator) stack.peek(); + MenuComponent component = (MenuComponent) iterator.next(); + if (component instanceof Menu) { + stack.push(component.createIterator()); + } + return component; + } else { + return null; + } + } + + public boolean hasNext() { + if (stack.empty()) { + return false; + } else { + Iterator iterator = (Iterator) stack.peek(); + if (!iterator.hasNext()) { + stack.pop(); + return hasNext(); + } else { + return true; + } + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } +} + + diff --git a/HF_DP/src/headfirst/composite/menuiterator/Menu.java b/HF_DP/src/headfirst/composite/menuiterator/Menu.java new file mode 100644 index 00000000..8256287b --- /dev/null +++ b/HF_DP/src/headfirst/composite/menuiterator/Menu.java @@ -0,0 +1,55 @@ +package headfirst.composite.menuiterator; + +import java.util.Iterator; +import java.util.ArrayList; + +public class Menu extends MenuComponent { + + ArrayList menuComponents = new ArrayList(); + String name; + String description; + + public Menu(String name, String description) { + this.name = name; + this.description = description; + } + + public void add(MenuComponent menuComponent) { + menuComponents.add(menuComponent); + } + + public void remove(MenuComponent menuComponent) { + menuComponents.remove(menuComponent); + } + + public MenuComponent getChild(int i) { + return (MenuComponent)menuComponents.get(i); + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + + public Iterator createIterator() { + return new CompositeIterator(menuComponents.iterator()); + } + + + public void print() { + System.out.print("\n" + getName()); + System.out.println(", " + getDescription()); + System.out.println("---------------------"); + + Iterator iterator = menuComponents.iterator(); + while (iterator.hasNext()) { + MenuComponent menuComponent = + (MenuComponent)iterator.next(); + menuComponent.print(); + } + } +} diff --git a/HF_DP/src/headfirst/composite/menuiterator/MenuComponent.java b/HF_DP/src/headfirst/composite/menuiterator/MenuComponent.java new file mode 100644 index 00000000..5b5c278d --- /dev/null +++ b/HF_DP/src/headfirst/composite/menuiterator/MenuComponent.java @@ -0,0 +1,35 @@ +package headfirst.composite.menuiterator; + +import java.util.*; + +public abstract class MenuComponent { + + public void add(MenuComponent menuComponent) { + throw new UnsupportedOperationException(); + } + public void remove(MenuComponent menuComponent) { + throw new UnsupportedOperationException(); + } + public MenuComponent getChild(int i) { + throw new UnsupportedOperationException(); + } + + public String getName() { + throw new UnsupportedOperationException(); + } + public String getDescription() { + throw new UnsupportedOperationException(); + } + public double getPrice() { + throw new UnsupportedOperationException(); + } + public boolean isVegetarian() { + throw new UnsupportedOperationException(); + } + + public abstract Iterator createIterator(); + + public void print() { + throw new UnsupportedOperationException(); + } +} diff --git a/HF_DP/src/headfirst/composite/menuiterator/MenuItem.java b/HF_DP/src/headfirst/composite/menuiterator/MenuItem.java new file mode 100644 index 00000000..0cfd39bc --- /dev/null +++ b/HF_DP/src/headfirst/composite/menuiterator/MenuItem.java @@ -0,0 +1,55 @@ +package headfirst.composite.menuiterator; + +import java.util.Iterator; +import java.util.ArrayList; + +public class MenuItem extends MenuComponent { + + String name; + String description; + boolean vegetarian; + double price; + + public MenuItem(String name, + String description, + boolean vegetarian, + double price) + { + this.name = name; + this.description = description; + this.vegetarian = vegetarian; + this.price = price; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public double getPrice() { + return price; + } + + public boolean isVegetarian() { + return vegetarian; + } + + public Iterator createIterator() { + return new NullIterator(); + } + + public void print() { + System.out.print(" " + getName()); + if (isVegetarian()) { + System.out.print("(v)"); + } + System.out.println(", " + getPrice()); + System.out.println(" -- " + getDescription()); + } +//vv MenuItemCompositeV2Main +} +//^^ MenuItemCompositeV2Main +//^^ MenuItemCompositeV2 diff --git a/HF_DP/src/headfirst/composite/menuiterator/MenuTestDrive.java b/HF_DP/src/headfirst/composite/menuiterator/MenuTestDrive.java new file mode 100644 index 00000000..0dbeae28 --- /dev/null +++ b/HF_DP/src/headfirst/composite/menuiterator/MenuTestDrive.java @@ -0,0 +1,115 @@ +package headfirst.composite.menuiterator; + +import java.util.*; + +public class MenuTestDrive { + public static void main(String args[]) { + + MenuComponent pancakeHouseMenu = + new Menu("PANCAKE HOUSE MENU", "Breakfast"); + MenuComponent dinerMenu = + new Menu("DINER MENU", "Lunch"); + MenuComponent cafeMenu = + new Menu("CAFE MENU", "Dinner"); + MenuComponent dessertMenu = + new Menu("DESSERT MENU", "Dessert of course!"); + + MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined"); + + allMenus.add(pancakeHouseMenu); + allMenus.add(dinerMenu); + allMenus.add(cafeMenu); + + pancakeHouseMenu.add(new MenuItem( + "K&B's Pancake Breakfast", + "Pancakes with scrambled eggs, and toast", + true, + 2.99)); + pancakeHouseMenu.add(new MenuItem( + "Regular Pancake Breakfast", + "Pancakes with fried eggs, sausage", + false, + 2.99)); + pancakeHouseMenu.add(new MenuItem( + "Blueberry Pancakes", + "Pancakes made with fresh blueberries, and blueberry syrup", + true, + 3.49)); + pancakeHouseMenu.add(new MenuItem( + "Waffles", + "Waffles, with your choice of blueberries or strawberries", + true, + 3.59)); + + dinerMenu.add(new MenuItem( + "Vegetarian BLT", + "(Fakin') Bacon with lettuce & tomato on whole wheat", + true, + 2.99)); + dinerMenu.add(new MenuItem( + "BLT", + "Bacon with lettuce & tomato on whole wheat", + false, + 2.99)); + dinerMenu.add(new MenuItem( + "Soup of the day", + "A bowl of the soup of the day, with a side of potato salad", + false, + 3.29)); + dinerMenu.add(new MenuItem( + "Hotdog", + "A hot dog, with saurkraut, relish, onions, topped with cheese", + false, + 3.05)); + dinerMenu.add(new MenuItem( + "Steamed Veggies and Brown Rice", + "A medly of steamed vegetables over brown rice", + true, + 3.99)); + + dinerMenu.add(new MenuItem( + "Pasta", + "Spaghetti with Marinara Sauce, and a slice of sourdough bread", + true, + 3.89)); + + dinerMenu.add(dessertMenu); + + dessertMenu.add(new MenuItem( + "Apple Pie", + "Apple pie with a flakey crust, topped with vanilla icecream", + true, + 1.59)); + dessertMenu.add(new MenuItem( + "Cheesecake", + "Creamy New York cheesecake, with a chocolate graham crust", + true, + 1.99)); + dessertMenu.add(new MenuItem( + "Sorbet", + "A scoop of raspberry and a scoop of lime", + true, + 1.89)); + + cafeMenu.add(new MenuItem( + "Veggie Burger and Air Fries", + "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", + true, + 3.99)); + cafeMenu.add(new MenuItem( + "Soup of the day", + "A cup of the soup of the day, with a side salad", + false, + 3.69)); + cafeMenu.add(new MenuItem( + "Burrito", + "A large burrito, with whole pinto beans, salsa, guacamole", + true, + 4.29)); + + Waitress waitress = new Waitress(allMenus); + + waitress.printVegetarianMenu(); + + } +} diff --git a/HF_DP/src/headfirst/composite/menuiterator/NullIterator.java b/HF_DP/src/headfirst/composite/menuiterator/NullIterator.java new file mode 100644 index 00000000..d4f15c5b --- /dev/null +++ b/HF_DP/src/headfirst/composite/menuiterator/NullIterator.java @@ -0,0 +1,18 @@ +package headfirst.composite.menuiterator; + +import java.util.Iterator; + +public class NullIterator implements Iterator { + + public Object next() { + return null; + } + + public boolean hasNext() { + return false; + } + + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/HF_DP/src/headfirst/composite/menuiterator/Waitress.java b/HF_DP/src/headfirst/composite/menuiterator/Waitress.java new file mode 100644 index 00000000..4a66210d --- /dev/null +++ b/HF_DP/src/headfirst/composite/menuiterator/Waitress.java @@ -0,0 +1,30 @@ +package headfirst.composite.menuiterator; + +import java.util.Iterator; + +public class Waitress { + MenuComponent allMenus; + + public Waitress(MenuComponent allMenus) { + this.allMenus = allMenus; + } + + public void printMenu() { + allMenus.print(); + } + + public void printVegetarianMenu() { + Iterator iterator = allMenus.createIterator(); + + System.out.println("\nVEGETARIAN MENU\n----"); + while (iterator.hasNext()) { + MenuComponent menuComponent = + (MenuComponent)iterator.next(); + try { + if (menuComponent.isVegetarian()) { + menuComponent.print(); + } + } catch (UnsupportedOperationException e) {} + } + } +} diff --git a/HF_DP/src/headfirst/decorator/io/InputTest.java b/HF_DP/src/headfirst/decorator/io/InputTest.java new file mode 100644 index 00000000..cee51eae --- /dev/null +++ b/HF_DP/src/headfirst/decorator/io/InputTest.java @@ -0,0 +1,24 @@ +package headfirst.decorator.io; + +import java.io.*; + +public class InputTest { + public static void main(String[] args) throws IOException { + int c; + + try { + InputStream in = + new LowerCaseInputStream( + new BufferedInputStream( + new FileInputStream("test.txt"))); + + while((c = in.read()) >= 0) { + System.out.print((char)c); + } + + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/HF_DP/src/headfirst/decorator/io/LowerCaseInputStream.java b/HF_DP/src/headfirst/decorator/io/LowerCaseInputStream.java new file mode 100644 index 00000000..e5b051da --- /dev/null +++ b/HF_DP/src/headfirst/decorator/io/LowerCaseInputStream.java @@ -0,0 +1,23 @@ +package headfirst.decorator.io; + +import java.io.*; + +public class LowerCaseInputStream extends FilterInputStream { + + public LowerCaseInputStream(InputStream in) { + super(in); + } + + public int read() throws IOException { + int c = super.read(); + return (c == -1 ? c : Character.toLowerCase((char)c)); + } + + public int read(byte[] b, int offset, int len) throws IOException { + int result = super.read(b, offset, len); + for (int i = offset; i < offset+result; i++) { + b[i] = (byte)Character.toLowerCase((char)b[i]); + } + return result; + } +} diff --git a/HF_DP/src/headfirst/decorator/starbuzz/Beverage.java b/HF_DP/src/headfirst/decorator/starbuzz/Beverage.java new file mode 100644 index 00000000..258c8fd2 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/Beverage.java @@ -0,0 +1,11 @@ +package headfirst.decorator.starbuzz; + +public abstract class Beverage { + String description = "Unknown Beverage"; + + public String getDescription() { + return description; + } + + public abstract double cost(); +} diff --git a/HF_DP/src/headfirst/decorator/starbuzz/CondimentDecorator.java b/HF_DP/src/headfirst/decorator/starbuzz/CondimentDecorator.java new file mode 100644 index 00000000..b4da75a5 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/CondimentDecorator.java @@ -0,0 +1,5 @@ +package headfirst.decorator.starbuzz; + +public abstract class CondimentDecorator extends Beverage { + public abstract String getDescription(); +} diff --git a/HF_DP/src/headfirst/decorator/starbuzz/DarkRoast.java b/HF_DP/src/headfirst/decorator/starbuzz/DarkRoast.java new file mode 100644 index 00000000..52a71833 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/DarkRoast.java @@ -0,0 +1,12 @@ +package headfirst.decorator.starbuzz; + +public class DarkRoast extends Beverage { + public DarkRoast() { + description = "Dark Roast Coffee"; + } + + public double cost() { + return .99; + } +} + diff --git a/HF_DP/src/headfirst/decorator/starbuzz/Decaf.java b/HF_DP/src/headfirst/decorator/starbuzz/Decaf.java new file mode 100644 index 00000000..093ea971 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/Decaf.java @@ -0,0 +1,12 @@ +package headfirst.decorator.starbuzz; + +public class Decaf extends Beverage { + public Decaf() { + description = "Decaf Coffee"; + } + + public double cost() { + return 1.05; + } +} + diff --git a/HF_DP/src/headfirst/decorator/starbuzz/Espresso.java b/HF_DP/src/headfirst/decorator/starbuzz/Espresso.java new file mode 100644 index 00000000..2bcd3a93 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/Espresso.java @@ -0,0 +1,13 @@ +package headfirst.decorator.starbuzz; + +public class Espresso extends Beverage { + + public Espresso() { + description = "Espresso"; + } + + public double cost() { + return 1.99; + } +} + diff --git a/HF_DP/src/headfirst/decorator/starbuzz/HouseBlend.java b/HF_DP/src/headfirst/decorator/starbuzz/HouseBlend.java new file mode 100644 index 00000000..37a041b7 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/HouseBlend.java @@ -0,0 +1,12 @@ +package headfirst.decorator.starbuzz; + +public class HouseBlend extends Beverage { + public HouseBlend() { + description = "House Blend Coffee"; + } + + public double cost() { + return .89; + } +} + diff --git a/HF_DP/src/headfirst/decorator/starbuzz/Milk.java b/HF_DP/src/headfirst/decorator/starbuzz/Milk.java new file mode 100644 index 00000000..174a9612 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/Milk.java @@ -0,0 +1,17 @@ +package headfirst.decorator.starbuzz; + +public class Milk extends CondimentDecorator { + Beverage beverage; + + public Milk(Beverage beverage) { + this.beverage = beverage; + } + + public String getDescription() { + return beverage.getDescription() + ", Milk"; + } + + public double cost() { + return .10 + beverage.cost(); + } +} diff --git a/HF_DP/src/headfirst/decorator/starbuzz/Mocha.java b/HF_DP/src/headfirst/decorator/starbuzz/Mocha.java new file mode 100644 index 00000000..2f20d4d8 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/Mocha.java @@ -0,0 +1,17 @@ +package headfirst.decorator.starbuzz; + +public class Mocha extends CondimentDecorator { + Beverage beverage; + + public Mocha(Beverage beverage) { + this.beverage = beverage; + } + + public String getDescription() { + return beverage.getDescription() + ", Mocha"; + } + + public double cost() { + return .20 + beverage.cost(); + } +} diff --git a/HF_DP/src/headfirst/decorator/starbuzz/Soy.java b/HF_DP/src/headfirst/decorator/starbuzz/Soy.java new file mode 100644 index 00000000..d557e8e4 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/Soy.java @@ -0,0 +1,17 @@ +package headfirst.decorator.starbuzz; + +public class Soy extends CondimentDecorator { + Beverage beverage; + + public Soy(Beverage beverage) { + this.beverage = beverage; + } + + public String getDescription() { + return beverage.getDescription() + ", Soy"; + } + + public double cost() { + return .15 + beverage.cost(); + } +} diff --git a/HF_DP/src/headfirst/decorator/starbuzz/StarbuzzCoffee.java b/HF_DP/src/headfirst/decorator/starbuzz/StarbuzzCoffee.java new file mode 100644 index 00000000..88a2417c --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/StarbuzzCoffee.java @@ -0,0 +1,24 @@ +package headfirst.decorator.starbuzz; + +public class StarbuzzCoffee { + + public static void main(String args[]) { + Beverage beverage = new Espresso(); + System.out.println(beverage.getDescription() + + " $" + beverage.cost()); + + Beverage beverage2 = new DarkRoast(); + beverage2 = new Mocha(beverage2); + beverage2 = new Mocha(beverage2); + beverage2 = new Whip(beverage2); + System.out.println(beverage2.getDescription() + + " $" + beverage2.cost()); + + Beverage beverage3 = new HouseBlend(); + beverage3 = new Soy(beverage3); + beverage3 = new Mocha(beverage3); + beverage3 = new Whip(beverage3); + System.out.println(beverage3.getDescription() + + " $" + beverage3.cost()); + } +} diff --git a/HF_DP/src/headfirst/decorator/starbuzz/Whip.java b/HF_DP/src/headfirst/decorator/starbuzz/Whip.java new file mode 100644 index 00000000..606654a5 --- /dev/null +++ b/HF_DP/src/headfirst/decorator/starbuzz/Whip.java @@ -0,0 +1,17 @@ +package headfirst.decorator.starbuzz; + +public class Whip extends CondimentDecorator { + Beverage beverage; + + public Whip(Beverage beverage) { + this.beverage = beverage; + } + + public String getDescription() { + return beverage.getDescription() + ", Whip"; + } + + public double cost() { + return .10 + beverage.cost(); + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/Amplifier.java b/HF_DP/src/headfirst/facade/hometheater/Amplifier.java new file mode 100644 index 00000000..5e4fcbb3 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/Amplifier.java @@ -0,0 +1,51 @@ +package headfirst.facade.hometheater; + +public class Amplifier { + String description; + Tuner tuner; + DvdPlayer dvd; + CdPlayer cd; + + public Amplifier(String description) { + this.description = description; + } + + public void on() { + System.out.println(description + " on"); + } + + public void off() { + System.out.println(description + " off"); + } + + public void setStereoSound() { + System.out.println(description + " stereo mode on"); + } + + public void setSurroundSound() { + System.out.println(description + " surround sound on (5 speakers, 1 subwoofer)"); + } + + public void setVolume(int level) { + System.out.println(description + " setting volume to " + level); + } + + public void setTuner(Tuner tuner) { + System.out.println(description + " setting tuner to " + dvd); + this.tuner = tuner; + } + + public void setDvd(DvdPlayer dvd) { + System.out.println(description + " setting DVD player to " + dvd); + this.dvd = dvd; + } + + public void setCd(CdPlayer cd) { + System.out.println(description + " setting CD player to " + cd); + this.cd = cd; + } + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/CdPlayer.java b/HF_DP/src/headfirst/facade/hometheater/CdPlayer.java new file mode 100644 index 00000000..0a164060 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/CdPlayer.java @@ -0,0 +1,55 @@ +package headfirst.facade.hometheater; + +public class CdPlayer { + String description; + int currentTrack; + Amplifier amplifier; + String title; + + public CdPlayer(String description, Amplifier amplifier) { + this.description = description; + this.amplifier = amplifier; + } + + public void on() { + System.out.println(description + " on"); + } + + public void off() { + System.out.println(description + " off"); + } + + public void eject() { + title = null; + System.out.println(description + " eject"); + } + + public void play(String title) { + this.title = title; + currentTrack = 0; + System.out.println(description + " playing \"" + title + "\""); + } + + public void play(int track) { + if (title == null) { + System.out.println(description + " can't play track " + currentTrack + + ", no cd inserted"); + } else { + currentTrack = track; + System.out.println(description + " playing track " + currentTrack); + } + } + + public void stop() { + currentTrack = 0; + System.out.println(description + " stopped"); + } + + public void pause() { + System.out.println(description + " paused \"" + title + "\""); + } + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/DvdPlayer.java b/HF_DP/src/headfirst/facade/hometheater/DvdPlayer.java new file mode 100644 index 00000000..996912e7 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/DvdPlayer.java @@ -0,0 +1,62 @@ +package headfirst.facade.hometheater; + +public class DvdPlayer { + String description; + int currentTrack; + Amplifier amplifier; + String movie; + + public DvdPlayer(String description, Amplifier amplifier) { + this.description = description; + this.amplifier = amplifier; + } + + public void on() { + System.out.println(description + " on"); + } + + public void off() { + System.out.println(description + " off"); + } + + public void eject() { + movie = null; + System.out.println(description + " eject"); + } + + public void play(String movie) { + this.movie = movie; + currentTrack = 0; + System.out.println(description + " playing \"" + movie + "\""); + } + + public void play(int track) { + if (movie == null) { + System.out.println(description + " can't play track " + track + " no dvd inserted"); + } else { + currentTrack = track; + System.out.println(description + " playing track " + currentTrack + " of \"" + movie + "\""); + } + } + + public void stop() { + currentTrack = 0; + System.out.println(description + " stopped \"" + movie + "\""); + } + + public void pause() { + System.out.println(description + " paused \"" + movie + "\""); + } + + public void setTwoChannelAudio() { + System.out.println(description + " set two channel audio"); + } + + public void setSurroundAudio() { + System.out.println(description + " set surround audio"); + } + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/HomeTheaterFacade.java b/HF_DP/src/headfirst/facade/hometheater/HomeTheaterFacade.java new file mode 100644 index 00000000..6aad9c89 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/HomeTheaterFacade.java @@ -0,0 +1,94 @@ +package headfirst.facade.hometheater; + +public class HomeTheaterFacade { + Amplifier amp; + Tuner tuner; + DvdPlayer dvd; + CdPlayer cd; + Projector projector; + TheaterLights lights; + Screen screen; + PopcornPopper popper; + + public HomeTheaterFacade(Amplifier amp, + Tuner tuner, + DvdPlayer dvd, + CdPlayer cd, + Projector projector, + Screen screen, + TheaterLights lights, + PopcornPopper popper) { + + this.amp = amp; + this.tuner = tuner; + this.dvd = dvd; + this.cd = cd; + this.projector = projector; + this.screen = screen; + this.lights = lights; + this.popper = popper; + } + + public void watchMovie(String movie) { + System.out.println("Get ready to watch a movie..."); + popper.on(); + popper.pop(); + lights.dim(10); + screen.down(); + projector.on(); + projector.wideScreenMode(); + amp.on(); + amp.setDvd(dvd); + amp.setSurroundSound(); + amp.setVolume(5); + dvd.on(); + dvd.play(movie); + } + + + public void endMovie() { + System.out.println("Shutting movie theater down..."); + popper.off(); + lights.on(); + screen.up(); + projector.off(); + amp.off(); + dvd.stop(); + dvd.eject(); + dvd.off(); + } + + public void listenToCd(String cdTitle) { + System.out.println("Get ready for an audiopile experence..."); + lights.on(); + amp.on(); + amp.setVolume(5); + amp.setCd(cd); + amp.setStereoSound(); + cd.on(); + cd.play(cdTitle); + } + + public void endCd() { + System.out.println("Shutting down CD..."); + amp.off(); + amp.setCd(cd); + cd.eject(); + cd.off(); + } + + public void listenToRadio(double frequency) { + System.out.println("Tuning in the airwaves..."); + tuner.on(); + tuner.setFrequency(frequency); + amp.on(); + amp.setVolume(5); + amp.setTuner(tuner); + } + + public void endRadio() { + System.out.println("Shutting down the tuner..."); + tuner.off(); + amp.off(); + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/HomeTheaterTestDrive.java b/HF_DP/src/headfirst/facade/hometheater/HomeTheaterTestDrive.java new file mode 100644 index 00000000..013740f1 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/HomeTheaterTestDrive.java @@ -0,0 +1,21 @@ +package headfirst.facade.hometheater; + +public class HomeTheaterTestDrive { + public static void main(String[] args) { + Amplifier amp = new Amplifier("Top-O-Line Amplifier"); + Tuner tuner = new Tuner("Top-O-Line AM/FM Tuner", amp); + DvdPlayer dvd = new DvdPlayer("Top-O-Line DVD Player", amp); + CdPlayer cd = new CdPlayer("Top-O-Line CD Player", amp); + Projector projector = new Projector("Top-O-Line Projector", dvd); + TheaterLights lights = new TheaterLights("Theater Ceiling Lights"); + Screen screen = new Screen("Theater Screen"); + PopcornPopper popper = new PopcornPopper("Popcorn Popper"); + + HomeTheaterFacade homeTheater = + new HomeTheaterFacade(amp, tuner, dvd, cd, + projector, screen, lights, popper); + + homeTheater.watchMovie("Raiders of the Lost Ark"); + homeTheater.endMovie(); + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/PopcornPopper.java b/HF_DP/src/headfirst/facade/hometheater/PopcornPopper.java new file mode 100644 index 00000000..bc831c62 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/PopcornPopper.java @@ -0,0 +1,26 @@ +package headfirst.facade.hometheater; + +public class PopcornPopper { + String description; + + public PopcornPopper(String description) { + this.description = description; + } + + public void on() { + System.out.println(description + " on"); + } + + public void off() { + System.out.println(description + " off"); + } + + public void pop() { + System.out.println(description + " popping popcorn!"); + } + + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/Projector.java b/HF_DP/src/headfirst/facade/hometheater/Projector.java new file mode 100644 index 00000000..dbe9e669 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/Projector.java @@ -0,0 +1,31 @@ +package headfirst.facade.hometheater; + +public class Projector { + String description; + DvdPlayer dvdPlayer; + + public Projector(String description, DvdPlayer dvdPlayer) { + this.description = description; + this.dvdPlayer = dvdPlayer; + } + + public void on() { + System.out.println(description + " on"); + } + + public void off() { + System.out.println(description + " off"); + } + + public void wideScreenMode() { + System.out.println(description + " in widescreen mode (16x9 aspect ratio)"); + } + + public void tvMode() { + System.out.println(description + " in tv mode (4x3 aspect ratio)"); + } + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/Screen.java b/HF_DP/src/headfirst/facade/hometheater/Screen.java new file mode 100644 index 00000000..0646d896 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/Screen.java @@ -0,0 +1,22 @@ +package headfirst.facade.hometheater; + +public class Screen { + String description; + + public Screen(String description) { + this.description = description; + } + + public void up() { + System.out.println(description + " going up"); + } + + public void down() { + System.out.println(description + " going down"); + } + + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/TheaterLights.java b/HF_DP/src/headfirst/facade/hometheater/TheaterLights.java new file mode 100644 index 00000000..cc90f374 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/TheaterLights.java @@ -0,0 +1,25 @@ +package headfirst.facade.hometheater; + +public class TheaterLights { + String description; + + public TheaterLights(String description) { + this.description = description; + } + + public void on() { + System.out.println(description + " on"); + } + + public void off() { + System.out.println(description + " off"); + } + + public void dim(int level) { + System.out.println(description + " dimming to " + level + "%"); + } + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/facade/hometheater/Tuner.java b/HF_DP/src/headfirst/facade/hometheater/Tuner.java new file mode 100644 index 00000000..ed83b467 --- /dev/null +++ b/HF_DP/src/headfirst/facade/hometheater/Tuner.java @@ -0,0 +1,36 @@ +package headfirst.facade.hometheater; + +public class Tuner { + String description; + Amplifier amplifier; + double frequency; + + public Tuner(String description, Amplifier amplifier) { + this.description = description; + } + + public void on() { + System.out.println(description + " on"); + } + + public void off() { + System.out.println(description + " off"); + } + + public void setFrequency(double frequency) { + System.out.println(description + " setting frequency to " + frequency); + this.frequency = frequency; + } + + public void setAm() { + System.out.println(description + " setting AM mode"); + } + + public void setFm() { + System.out.println(description + " setting FM mode"); + } + + public String toString() { + return description; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/BlackOlives.java b/HF_DP/src/headfirst/factory/pizzaaf/BlackOlives.java new file mode 100644 index 00000000..2f13416a --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/BlackOlives.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class BlackOlives implements Veggies { + + public String toString() { + return "Black Olives"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Cheese.java b/HF_DP/src/headfirst/factory/pizzaaf/Cheese.java new file mode 100644 index 00000000..0602ee2e --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Cheese.java @@ -0,0 +1,5 @@ +package headfirst.factory.pizzaaf; + +public interface Cheese { + public String toString(); +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/CheesePizza.java b/HF_DP/src/headfirst/factory/pizzaaf/CheesePizza.java new file mode 100644 index 00000000..8242b504 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/CheesePizza.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzaaf; + +public class CheesePizza extends Pizza { + PizzaIngredientFactory ingredientFactory; + + public CheesePizza(PizzaIngredientFactory ingredientFactory) { + this.ingredientFactory = ingredientFactory; + } + + void prepare() { + System.out.println("Preparing " + name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/ChicagoPizzaIngredientFactory.java b/HF_DP/src/headfirst/factory/pizzaaf/ChicagoPizzaIngredientFactory.java new file mode 100644 index 00000000..6929175a --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/ChicagoPizzaIngredientFactory.java @@ -0,0 +1,33 @@ +package headfirst.factory.pizzaaf; + +public class ChicagoPizzaIngredientFactory + implements PizzaIngredientFactory +{ + + public Dough createDough() { + return new ThickCrustDough(); + } + + public Sauce createSauce() { + return new PlumTomatoSauce(); + } + + public Cheese createCheese() { + return new MozzarellaCheese(); + } + + public Veggies[] createVeggies() { + Veggies veggies[] = { new BlackOlives(), + new Spinach(), + new Eggplant() }; + return veggies; + } + + public Pepperoni createPepperoni() { + return new SlicedPepperoni(); + } + + public Clams createClam() { + return new FrozenClams(); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/ChicagoPizzaStore.java b/HF_DP/src/headfirst/factory/pizzaaf/ChicagoPizzaStore.java new file mode 100644 index 00000000..92be5522 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/ChicagoPizzaStore.java @@ -0,0 +1,33 @@ +package headfirst.factory.pizzaaf; + +public class ChicagoPizzaStore extends PizzaStore { + + protected Pizza createPizza(String item) { + Pizza pizza = null; + PizzaIngredientFactory ingredientFactory = + new ChicagoPizzaIngredientFactory(); + + if (item.equals("cheese")) { + + pizza = new CheesePizza(ingredientFactory); + pizza.setName("Chicago Style Cheese Pizza"); + + } else if (item.equals("veggie")) { + + pizza = new VeggiePizza(ingredientFactory); + pizza.setName("Chicago Style Veggie Pizza"); + + } else if (item.equals("clam")) { + + pizza = new ClamPizza(ingredientFactory); + pizza.setName("Chicago Style Clam Pizza"); + + } else if (item.equals("pepperoni")) { + + pizza = new PepperoniPizza(ingredientFactory); + pizza.setName("Chicago Style Pepperoni Pizza"); + + } + return pizza; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/ClamPizza.java b/HF_DP/src/headfirst/factory/pizzaaf/ClamPizza.java new file mode 100644 index 00000000..9e2c594b --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/ClamPizza.java @@ -0,0 +1,17 @@ +package headfirst.factory.pizzaaf; + +public class ClamPizza extends Pizza { + PizzaIngredientFactory ingredientFactory; + + public ClamPizza(PizzaIngredientFactory ingredientFactory) { + this.ingredientFactory = ingredientFactory; + } + + void prepare() { + System.out.println("Preparing " + name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + clam = ingredientFactory.createClam(); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Clams.java b/HF_DP/src/headfirst/factory/pizzaaf/Clams.java new file mode 100644 index 00000000..947ced88 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Clams.java @@ -0,0 +1,5 @@ +package headfirst.factory.pizzaaf; + +public interface Clams { + public String toString(); +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Dough.java b/HF_DP/src/headfirst/factory/pizzaaf/Dough.java new file mode 100644 index 00000000..d298f45c --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Dough.java @@ -0,0 +1,5 @@ +package headfirst.factory.pizzaaf; + +public interface Dough { + public String toString(); +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Eggplant.java b/HF_DP/src/headfirst/factory/pizzaaf/Eggplant.java new file mode 100644 index 00000000..f0288fac --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Eggplant.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class Eggplant implements Veggies { + + public String toString() { + return "Eggplant"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/FreshClams.java b/HF_DP/src/headfirst/factory/pizzaaf/FreshClams.java new file mode 100644 index 00000000..56a72bf5 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/FreshClams.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class FreshClams implements Clams { + + public String toString() { + return "Fresh Clams from Long Island Sound"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/FrozenClams.java b/HF_DP/src/headfirst/factory/pizzaaf/FrozenClams.java new file mode 100644 index 00000000..7a735269 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/FrozenClams.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class FrozenClams implements Clams { + + public String toString() { + return "Frozen Clams from Chesapeake Bay"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Garlic.java b/HF_DP/src/headfirst/factory/pizzaaf/Garlic.java new file mode 100644 index 00000000..426edff8 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Garlic.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class Garlic implements Veggies { + + public String toString() { + return "Garlic"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/MarinaraSauce.java b/HF_DP/src/headfirst/factory/pizzaaf/MarinaraSauce.java new file mode 100644 index 00000000..9d033507 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/MarinaraSauce.java @@ -0,0 +1,7 @@ +package headfirst.factory.pizzaaf; + +public class MarinaraSauce implements Sauce { + public String toString() { + return "Marinara Sauce"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/MozzarellaCheese.java b/HF_DP/src/headfirst/factory/pizzaaf/MozzarellaCheese.java new file mode 100644 index 00000000..195507d4 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/MozzarellaCheese.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class MozzarellaCheese implements Cheese { + + public String toString() { + return "Shredded Mozzarella"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Mushroom.java b/HF_DP/src/headfirst/factory/pizzaaf/Mushroom.java new file mode 100644 index 00000000..9856b339 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Mushroom.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class Mushroom implements Veggies { + + public String toString() { + return "Mushrooms"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/NYPizzaIngredientFactory.java b/HF_DP/src/headfirst/factory/pizzaaf/NYPizzaIngredientFactory.java new file mode 100644 index 00000000..11a4f7f2 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/NYPizzaIngredientFactory.java @@ -0,0 +1,29 @@ +package headfirst.factory.pizzaaf; + +public class NYPizzaIngredientFactory implements PizzaIngredientFactory { + + public Dough createDough() { + return new ThinCrustDough(); + } + + public Sauce createSauce() { + return new MarinaraSauce(); + } + + public Cheese createCheese() { + return new ReggianoCheese(); + } + + public Veggies[] createVeggies() { + Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() }; + return veggies; + } + + public Pepperoni createPepperoni() { + return new SlicedPepperoni(); + } + + public Clams createClam() { + return new FreshClams(); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/NYPizzaStore.java b/HF_DP/src/headfirst/factory/pizzaaf/NYPizzaStore.java new file mode 100644 index 00000000..29d2c477 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/NYPizzaStore.java @@ -0,0 +1,33 @@ +package headfirst.factory.pizzaaf; + +public class NYPizzaStore extends PizzaStore { + + protected Pizza createPizza(String item) { + Pizza pizza = null; + PizzaIngredientFactory ingredientFactory = + new NYPizzaIngredientFactory(); + + if (item.equals("cheese")) { + + pizza = new CheesePizza(ingredientFactory); + pizza.setName("New York Style Cheese Pizza"); + + } else if (item.equals("veggie")) { + + pizza = new VeggiePizza(ingredientFactory); + pizza.setName("New York Style Veggie Pizza"); + + } else if (item.equals("clam")) { + + pizza = new ClamPizza(ingredientFactory); + pizza.setName("New York Style Clam Pizza"); + + } else if (item.equals("pepperoni")) { + + pizza = new PepperoniPizza(ingredientFactory); + pizza.setName("New York Style Pepperoni Pizza"); + + } + return pizza; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Onion.java b/HF_DP/src/headfirst/factory/pizzaaf/Onion.java new file mode 100644 index 00000000..77f2d686 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Onion.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class Onion implements Veggies { + + public String toString() { + return "Onion"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/ParmesanCheese.java b/HF_DP/src/headfirst/factory/pizzaaf/ParmesanCheese.java new file mode 100644 index 00000000..55866024 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/ParmesanCheese.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class ParmesanCheese implements Cheese { + + public String toString() { + return "Shredded Parmesan"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Pepperoni.java b/HF_DP/src/headfirst/factory/pizzaaf/Pepperoni.java new file mode 100644 index 00000000..d6059b8f --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Pepperoni.java @@ -0,0 +1,5 @@ +package headfirst.factory.pizzaaf; + +public interface Pepperoni { + public String toString(); +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/PepperoniPizza.java b/HF_DP/src/headfirst/factory/pizzaaf/PepperoniPizza.java new file mode 100644 index 00000000..5a1ab0a5 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/PepperoniPizza.java @@ -0,0 +1,18 @@ +package headfirst.factory.pizzaaf; + +public class PepperoniPizza extends Pizza { + PizzaIngredientFactory ingredientFactory; + + public PepperoniPizza(PizzaIngredientFactory ingredientFactory) { + this.ingredientFactory = ingredientFactory; + } + + void prepare() { + System.out.println("Preparing " + name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + veggies = ingredientFactory.createVeggies(); + pepperoni = ingredientFactory.createPepperoni(); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Pizza.java b/HF_DP/src/headfirst/factory/pizzaaf/Pizza.java new file mode 100644 index 00000000..a65fd8d7 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Pizza.java @@ -0,0 +1,69 @@ +package headfirst.factory.pizzaaf; + +public abstract class Pizza { + String name; + + Dough dough; + Sauce sauce; + Veggies veggies[]; + Cheese cheese; + Pepperoni pepperoni; + Clams clam; + + abstract void prepare(); + + void bake() { + System.out.println("Bake for 25 minutes at 350"); + } + + void cut() { + System.out.println("Cutting the pizza into diagonal slices"); + } + + void box() { + System.out.println("Place pizza in official PizzaStore box"); + } + + void setName(String name) { + this.name = name; + } + + String getName() { + return name; + } + + public String toString() { + StringBuffer result = new StringBuffer(); + result.append("---- " + name + " ----\n"); + if (dough != null) { + result.append(dough); + result.append("\n"); + } + if (sauce != null) { + result.append(sauce); + result.append("\n"); + } + if (cheese != null) { + result.append(cheese); + result.append("\n"); + } + if (veggies != null) { + for (int i = 0; i < veggies.length; i++) { + result.append(veggies[i]); + if (i < veggies.length-1) { + result.append(", "); + } + } + result.append("\n"); + } + if (clam != null) { + result.append(clam); + result.append("\n"); + } + if (pepperoni != null) { + result.append(pepperoni); + result.append("\n"); + } + return result.toString(); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/PizzaIngredientFactory.java b/HF_DP/src/headfirst/factory/pizzaaf/PizzaIngredientFactory.java new file mode 100644 index 00000000..396b4cc4 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/PizzaIngredientFactory.java @@ -0,0 +1,12 @@ +package headfirst.factory.pizzaaf; + +public interface PizzaIngredientFactory { + + public Dough createDough(); + public Sauce createSauce(); + public Cheese createCheese(); + public Veggies[] createVeggies(); + public Pepperoni createPepperoni(); + public Clams createClam(); + +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/PizzaStore.java b/HF_DP/src/headfirst/factory/pizzaaf/PizzaStore.java new file mode 100644 index 00000000..1d8fd26e --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/PizzaStore.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzaaf; + +public abstract class PizzaStore { + + protected abstract Pizza createPizza(String item); + + public Pizza orderPizza(String type) { + Pizza pizza = createPizza(type); + System.out.println("--- Making a " + pizza.getName() + " ---"); + pizza.prepare(); + pizza.bake(); + pizza.cut(); + pizza.box(); + return pizza; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/PizzaTestDrive.java b/HF_DP/src/headfirst/factory/pizzaaf/PizzaTestDrive.java new file mode 100644 index 00000000..dd2c9fb5 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/PizzaTestDrive.java @@ -0,0 +1,33 @@ +package headfirst.factory.pizzaaf; + +public class PizzaTestDrive { + + public static void main(String[] args) { + PizzaStore nyStore = new NYPizzaStore(); + PizzaStore chicagoStore = new ChicagoPizzaStore(); + + Pizza pizza = nyStore.orderPizza("cheese"); + System.out.println("Ethan ordered a " + pizza + "\n"); + + pizza = chicagoStore.orderPizza("cheese"); + System.out.println("Joel ordered a " + pizza + "\n"); + + pizza = nyStore.orderPizza("clam"); + System.out.println("Ethan ordered a " + pizza + "\n"); + + pizza = chicagoStore.orderPizza("clam"); + System.out.println("Joel ordered a " + pizza + "\n"); + + pizza = nyStore.orderPizza("pepperoni"); + System.out.println("Ethan ordered a " + pizza + "\n"); + + pizza = chicagoStore.orderPizza("pepperoni"); + System.out.println("Joel ordered a " + pizza + "\n"); + + pizza = nyStore.orderPizza("veggie"); + System.out.println("Ethan ordered a " + pizza + "\n"); + + pizza = chicagoStore.orderPizza("veggie"); + System.out.println("Joel ordered a " + pizza + "\n"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/PlumTomatoSauce.java b/HF_DP/src/headfirst/factory/pizzaaf/PlumTomatoSauce.java new file mode 100644 index 00000000..f0f90b64 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/PlumTomatoSauce.java @@ -0,0 +1,7 @@ +package headfirst.factory.pizzaaf; + +public class PlumTomatoSauce implements Sauce { + public String toString() { + return "Tomato sauce with plum tomatoes"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/RedPepper.java b/HF_DP/src/headfirst/factory/pizzaaf/RedPepper.java new file mode 100644 index 00000000..bb073bab --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/RedPepper.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class RedPepper implements Veggies { + + public String toString() { + return "Red Pepper"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/ReggianoCheese.java b/HF_DP/src/headfirst/factory/pizzaaf/ReggianoCheese.java new file mode 100644 index 00000000..3a8a33a9 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/ReggianoCheese.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class ReggianoCheese implements Cheese { + + public String toString() { + return "Reggiano Cheese"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Sauce.java b/HF_DP/src/headfirst/factory/pizzaaf/Sauce.java new file mode 100644 index 00000000..daa5568d --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Sauce.java @@ -0,0 +1,5 @@ +package headfirst.factory.pizzaaf; + +public interface Sauce { + public String toString(); +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/SlicedPepperoni.java b/HF_DP/src/headfirst/factory/pizzaaf/SlicedPepperoni.java new file mode 100644 index 00000000..d608c450 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/SlicedPepperoni.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class SlicedPepperoni implements Pepperoni { + + public String toString() { + return "Sliced Pepperoni"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Spinach.java b/HF_DP/src/headfirst/factory/pizzaaf/Spinach.java new file mode 100644 index 00000000..b48b74b5 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Spinach.java @@ -0,0 +1,8 @@ +package headfirst.factory.pizzaaf; + +public class Spinach implements Veggies { + + public String toString() { + return "Spinach"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/ThickCrustDough.java b/HF_DP/src/headfirst/factory/pizzaaf/ThickCrustDough.java new file mode 100644 index 00000000..bd50809d --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/ThickCrustDough.java @@ -0,0 +1,7 @@ +package headfirst.factory.pizzaaf; + +public class ThickCrustDough implements Dough { + public String toString() { + return "ThickCrust style extra thick crust dough"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/ThinCrustDough.java b/HF_DP/src/headfirst/factory/pizzaaf/ThinCrustDough.java new file mode 100644 index 00000000..87f666d3 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/ThinCrustDough.java @@ -0,0 +1,7 @@ +package headfirst.factory.pizzaaf; + +public class ThinCrustDough implements Dough { + public String toString() { + return "Thin Crust Dough"; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/VeggiePizza.java b/HF_DP/src/headfirst/factory/pizzaaf/VeggiePizza.java new file mode 100644 index 00000000..2d05532e --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/VeggiePizza.java @@ -0,0 +1,17 @@ +package headfirst.factory.pizzaaf; + +public class VeggiePizza extends Pizza { + PizzaIngredientFactory ingredientFactory; + + public VeggiePizza(PizzaIngredientFactory ingredientFactory) { + this.ingredientFactory = ingredientFactory; + } + + void prepare() { + System.out.println("Preparing " + name); + dough = ingredientFactory.createDough(); + sauce = ingredientFactory.createSauce(); + cheese = ingredientFactory.createCheese(); + veggies = ingredientFactory.createVeggies(); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzaaf/Veggies.java b/HF_DP/src/headfirst/factory/pizzaaf/Veggies.java new file mode 100644 index 00000000..938c81df --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzaaf/Veggies.java @@ -0,0 +1,5 @@ +package headfirst.factory.pizzaaf; + +public interface Veggies { + public String toString(); +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/ChicagoPizzaStore.java b/HF_DP/src/headfirst/factory/pizzafm/ChicagoPizzaStore.java new file mode 100644 index 00000000..e3dcf666 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/ChicagoPizzaStore.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzafm; + +public class ChicagoPizzaStore extends PizzaStore { + + Pizza createPizza(String item) { + if (item.equals("cheese")) { + return new ChicagoStyleCheesePizza(); + } else if (item.equals("veggie")) { + return new ChicagoStyleVeggiePizza(); + } else if (item.equals("clam")) { + return new ChicagoStyleClamPizza(); + } else if (item.equals("pepperoni")) { + return new ChicagoStylePepperoniPizza(); + } else return null; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleCheesePizza.java b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleCheesePizza.java new file mode 100644 index 00000000..f1f85754 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleCheesePizza.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzafm; + +public class ChicagoStyleCheesePizza extends Pizza { + + public ChicagoStyleCheesePizza() { + name = "Chicago Style Deep Dish Cheese Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings.add("Shredded Mozzarella Cheese"); + } + + void cut() { + System.out.println("Cutting the pizza into square slices"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleClamPizza.java b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleClamPizza.java new file mode 100644 index 00000000..7b64a2a7 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleClamPizza.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzafm; + +public class ChicagoStyleClamPizza extends Pizza { + public ChicagoStyleClamPizza() { + name = "Chicago Style Clam Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings.add("Shredded Mozzarella Cheese"); + toppings.add("Frozen Clams from Chesapeake Bay"); + } + + void cut() { + System.out.println("Cutting the pizza into square slices"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/ChicagoStylePepperoniPizza.java b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStylePepperoniPizza.java new file mode 100644 index 00000000..cafb6b67 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStylePepperoniPizza.java @@ -0,0 +1,19 @@ +package headfirst.factory.pizzafm; + +public class ChicagoStylePepperoniPizza extends Pizza { + public ChicagoStylePepperoniPizza() { + name = "Chicago Style Pepperoni Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings.add("Shredded Mozzarella Cheese"); + toppings.add("Black Olives"); + toppings.add("Spinach"); + toppings.add("Eggplant"); + toppings.add("Sliced Pepperoni"); + } + + void cut() { + System.out.println("Cutting the pizza into square slices"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleVeggiePizza.java b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleVeggiePizza.java new file mode 100644 index 00000000..8ae0c5a5 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/ChicagoStyleVeggiePizza.java @@ -0,0 +1,18 @@ +package headfirst.factory.pizzafm; + +public class ChicagoStyleVeggiePizza extends Pizza { + public ChicagoStyleVeggiePizza() { + name = "Chicago Deep Dish Veggie Pizza"; + dough = "Extra Thick Crust Dough"; + sauce = "Plum Tomato Sauce"; + + toppings.add("Shredded Mozzarella Cheese"); + toppings.add("Black Olives"); + toppings.add("Spinach"); + toppings.add("Eggplant"); + } + + void cut() { + System.out.println("Cutting the pizza into square slices"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/DependentPizzaStore.java b/HF_DP/src/headfirst/factory/pizzafm/DependentPizzaStore.java new file mode 100644 index 00000000..89080a1f --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/DependentPizzaStore.java @@ -0,0 +1,37 @@ +package headfirst.factory.pizzafm; + +public class DependentPizzaStore { + + public Pizza createPizza(String style, String type) { + Pizza pizza = null; + if (style.equals("NY")) { + if (type.equals("cheese")) { + pizza = new NYStyleCheesePizza(); + } else if (type.equals("veggie")) { + pizza = new NYStyleVeggiePizza(); + } else if (type.equals("clam")) { + pizza = new NYStyleClamPizza(); + } else if (type.equals("pepperoni")) { + pizza = new NYStylePepperoniPizza(); + } + } else if (style.equals("Chicago")) { + if (type.equals("cheese")) { + pizza = new ChicagoStyleCheesePizza(); + } else if (type.equals("veggie")) { + pizza = new ChicagoStyleVeggiePizza(); + } else if (type.equals("clam")) { + pizza = new ChicagoStyleClamPizza(); + } else if (type.equals("pepperoni")) { + pizza = new ChicagoStylePepperoniPizza(); + } + } else { + System.out.println("Error: invalid type of pizza"); + return null; + } + pizza.prepare(); + pizza.bake(); + pizza.cut(); + pizza.box(); + return pizza; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/NYPizzaStore.java b/HF_DP/src/headfirst/factory/pizzafm/NYPizzaStore.java new file mode 100644 index 00000000..1a56f05b --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/NYPizzaStore.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzafm; + +public class NYPizzaStore extends PizzaStore { + + Pizza createPizza(String item) { + if (item.equals("cheese")) { + return new NYStyleCheesePizza(); + } else if (item.equals("veggie")) { + return new NYStyleVeggiePizza(); + } else if (item.equals("clam")) { + return new NYStyleClamPizza(); + } else if (item.equals("pepperoni")) { + return new NYStylePepperoniPizza(); + } else return null; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/NYStyleCheesePizza.java b/HF_DP/src/headfirst/factory/pizzafm/NYStyleCheesePizza.java new file mode 100644 index 00000000..bf49730c --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/NYStyleCheesePizza.java @@ -0,0 +1,12 @@ +package headfirst.factory.pizzafm; + +public class NYStyleCheesePizza extends Pizza { + + public NYStyleCheesePizza() { + name = "NY Style Sauce and Cheese Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings.add("Grated Reggiano Cheese"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/NYStyleClamPizza.java b/HF_DP/src/headfirst/factory/pizzafm/NYStyleClamPizza.java new file mode 100644 index 00000000..6ff53671 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/NYStyleClamPizza.java @@ -0,0 +1,13 @@ +package headfirst.factory.pizzafm; + +public class NYStyleClamPizza extends Pizza { + + public NYStyleClamPizza() { + name = "NY Style Clam Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings.add("Grated Reggiano Cheese"); + toppings.add("Fresh Clams from Long Island Sound"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/NYStylePepperoniPizza.java b/HF_DP/src/headfirst/factory/pizzafm/NYStylePepperoniPizza.java new file mode 100644 index 00000000..cc20e840 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/NYStylePepperoniPizza.java @@ -0,0 +1,17 @@ +package headfirst.factory.pizzafm; + +public class NYStylePepperoniPizza extends Pizza { + + public NYStylePepperoniPizza() { + name = "NY Style Pepperoni Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings.add("Grated Reggiano Cheese"); + toppings.add("Sliced Pepperoni"); + toppings.add("Garlic"); + toppings.add("Onion"); + toppings.add("Mushrooms"); + toppings.add("Red Pepper"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/NYStyleVeggiePizza.java b/HF_DP/src/headfirst/factory/pizzafm/NYStyleVeggiePizza.java new file mode 100644 index 00000000..cfdd2c19 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/NYStyleVeggiePizza.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzafm; + +public class NYStyleVeggiePizza extends Pizza { + + public NYStyleVeggiePizza() { + name = "NY Style Veggie Pizza"; + dough = "Thin Crust Dough"; + sauce = "Marinara Sauce"; + + toppings.add("Grated Reggiano Cheese"); + toppings.add("Garlic"); + toppings.add("Onion"); + toppings.add("Mushrooms"); + toppings.add("Red Pepper"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/Pizza.java b/HF_DP/src/headfirst/factory/pizzafm/Pizza.java new file mode 100644 index 00000000..0e81eb28 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/Pizza.java @@ -0,0 +1,50 @@ +package headfirst.factory.pizzafm; + +import java.util.ArrayList; + +public abstract class Pizza { + String name; + String dough; + String sauce; + ArrayList toppings = new ArrayList(); + + void prepare() { + System.out.println("Preparing " + name); + System.out.println("Tossing dough..."); + System.out.println("Adding sauce..."); + System.out.println("Adding toppings: "); + for (int i = 0; i < toppings.size(); i++) { + System.out.println(" " + toppings.get(i)); + } + } + + void bake() { + System.out.println("Bake for 25 minutes at 350"); + } + + void cut() { + System.out.println("Cutting the pizza into diagonal slices"); + } + + void box() { + System.out.println("Place pizza in official PizzaStore box"); + } + + public String getName() { + return name; + } + + public String toString() { + StringBuffer display = new StringBuffer(); + display.append("---- " + name + " ----\n"); + display.append(dough + "\n"); + display.append(sauce + "\n"); + for (int i = 0; i < toppings.size(); i++) { + display.append((String )toppings.get(i) + "\n"); + } + return display.toString(); + } +} + + + diff --git a/HF_DP/src/headfirst/factory/pizzafm/PizzaStore.java b/HF_DP/src/headfirst/factory/pizzafm/PizzaStore.java new file mode 100644 index 00000000..5c800382 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/PizzaStore.java @@ -0,0 +1,16 @@ +package headfirst.factory.pizzafm; + +public abstract class PizzaStore { + + abstract Pizza createPizza(String item); + + public Pizza orderPizza(String type) { + Pizza pizza = createPizza(type); + System.out.println("--- Making a " + pizza.getName() + " ---"); + pizza.prepare(); + pizza.bake(); + pizza.cut(); + pizza.box(); + return pizza; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzafm/PizzaTestDrive.java b/HF_DP/src/headfirst/factory/pizzafm/PizzaTestDrive.java new file mode 100644 index 00000000..8ae85071 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzafm/PizzaTestDrive.java @@ -0,0 +1,33 @@ +package headfirst.factory.pizzafm; + +public class PizzaTestDrive { + + public static void main(String[] args) { + PizzaStore nyStore = new NYPizzaStore(); + PizzaStore chicagoStore = new ChicagoPizzaStore(); + + Pizza pizza = nyStore.orderPizza("cheese"); + System.out.println("Ethan ordered a " + pizza.getName() + "\n"); + + pizza = chicagoStore.orderPizza("cheese"); + System.out.println("Joel ordered a " + pizza.getName() + "\n"); + + pizza = nyStore.orderPizza("clam"); + System.out.println("Ethan ordered a " + pizza.getName() + "\n"); + + pizza = chicagoStore.orderPizza("clam"); + System.out.println("Joel ordered a " + pizza.getName() + "\n"); + + pizza = nyStore.orderPizza("pepperoni"); + System.out.println("Ethan ordered a " + pizza.getName() + "\n"); + + pizza = chicagoStore.orderPizza("pepperoni"); + System.out.println("Joel ordered a " + pizza.getName() + "\n"); + + pizza = nyStore.orderPizza("veggie"); + System.out.println("Ethan ordered a " + pizza.getName() + "\n"); + + pizza = chicagoStore.orderPizza("veggie"); + System.out.println("Joel ordered a " + pizza.getName() + "\n"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzas/CheesePizza.java b/HF_DP/src/headfirst/factory/pizzas/CheesePizza.java new file mode 100644 index 00000000..1d19132e --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/CheesePizza.java @@ -0,0 +1,11 @@ +package headfirst.factory.pizzas; + +public class CheesePizza extends Pizza { + public CheesePizza() { + name = "Cheese Pizza"; + dough = "Regular Crust"; + sauce = "Marinara Pizza Sauce"; + toppings.add("Fresh Mozzarella"); + toppings.add("Parmesan"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzas/ClamPizza.java b/HF_DP/src/headfirst/factory/pizzas/ClamPizza.java new file mode 100644 index 00000000..51ad3313 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/ClamPizza.java @@ -0,0 +1,11 @@ +package headfirst.factory.pizzas; + +public class ClamPizza extends Pizza { + public ClamPizza() { + name = "Clam Pizza"; + dough = "Thin crust"; + sauce = "White garlic sauce"; + toppings.add("Clams"); + toppings.add("Grated parmesan cheese"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzas/PepperoniPizza.java b/HF_DP/src/headfirst/factory/pizzas/PepperoniPizza.java new file mode 100644 index 00000000..9180954a --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/PepperoniPizza.java @@ -0,0 +1,12 @@ +package headfirst.factory.pizzas; + +public class PepperoniPizza extends Pizza { + public PepperoniPizza() { + name = "Pepperoni Pizza"; + dough = "Crust"; + sauce = "Marinara sauce"; + toppings.add("Sliced Pepperoni"); + toppings.add("Sliced Onion"); + toppings.add("Grated parmesan cheese"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzas/Pizza.java b/HF_DP/src/headfirst/factory/pizzas/Pizza.java new file mode 100644 index 00000000..fbd85003 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/Pizza.java @@ -0,0 +1,43 @@ +package headfirst.factory.pizzas; + +import java.util.ArrayList; + +abstract public class Pizza { + String name; + String dough; + String sauce; + ArrayList toppings = new ArrayList(); + + public String getName() { + return name; + } + + public void prepare() { + System.out.println("Preparing " + name); + } + + public void bake() { + System.out.println("Baking " + name); + } + + public void cut() { + System.out.println("Cutting " + name); + } + + public void box() { + System.out.println("Boxing " + name); + } + + public String toString() { + // code to display pizza name and ingredients + StringBuffer display = new StringBuffer(); + display.append("---- " + name + " ----\n"); + display.append(dough + "\n"); + display.append(sauce + "\n"); + for (int i = 0; i < toppings.size(); i++) { + display.append((String )toppings.get(i) + "\n"); + } + return display.toString(); + } +} + diff --git a/HF_DP/src/headfirst/factory/pizzas/PizzaStore.java b/HF_DP/src/headfirst/factory/pizzas/PizzaStore.java new file mode 100644 index 00000000..aa8e0936 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/PizzaStore.java @@ -0,0 +1,23 @@ +package headfirst.factory.pizzas; + +public class PizzaStore { + SimplePizzaFactory factory; + + public PizzaStore(SimplePizzaFactory factory) { + this.factory = factory; + } + + public Pizza orderPizza(String type) { + Pizza pizza; + + pizza = factory.createPizza(type); + + pizza.prepare(); + pizza.bake(); + pizza.cut(); + pizza.box(); + + return pizza; + } + +} diff --git a/HF_DP/src/headfirst/factory/pizzas/PizzaTestDrive.java b/HF_DP/src/headfirst/factory/pizzas/PizzaTestDrive.java new file mode 100644 index 00000000..1a568a1c --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/PizzaTestDrive.java @@ -0,0 +1,15 @@ +package headfirst.factory.pizzas; + +public class PizzaTestDrive { + + public static void main(String[] args) { + SimplePizzaFactory factory = new SimplePizzaFactory(); + PizzaStore store = new PizzaStore(factory); + + Pizza pizza = store.orderPizza("cheese"); + System.out.println("We ordered a " + pizza.getName() + "\n"); + + pizza = store.orderPizza("veggie"); + System.out.println("We ordered a " + pizza.getName() + "\n"); + } +} diff --git a/HF_DP/src/headfirst/factory/pizzas/SimplePizzaFactory.java b/HF_DP/src/headfirst/factory/pizzas/SimplePizzaFactory.java new file mode 100644 index 00000000..17a0edd4 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/SimplePizzaFactory.java @@ -0,0 +1,19 @@ +package headfirst.factory.pizzas; + +public class SimplePizzaFactory { + + public Pizza createPizza(String type) { + Pizza pizza = null; + + if (type.equals("cheese")) { + pizza = new CheesePizza(); + } else if (type.equals("pepperoni")) { + pizza = new PepperoniPizza(); + } else if (type.equals("clam")) { + pizza = new ClamPizza(); + } else if (type.equals("veggie")) { + pizza = new VeggiePizza(); + } + return pizza; + } +} diff --git a/HF_DP/src/headfirst/factory/pizzas/VeggiePizza.java b/HF_DP/src/headfirst/factory/pizzas/VeggiePizza.java new file mode 100644 index 00000000..534cc3b9 --- /dev/null +++ b/HF_DP/src/headfirst/factory/pizzas/VeggiePizza.java @@ -0,0 +1,15 @@ +package headfirst.factory.pizzas; + +public class VeggiePizza extends Pizza { + public VeggiePizza() { + name = "Veggie Pizza"; + dough = "Crust"; + sauce = "Marinara sauce"; + toppings.add("Shredded mozzarella"); + toppings.add("Grated parmesan"); + toppings.add("Diced onion"); + toppings.add("Sliced mushrooms"); + toppings.add("Sliced red pepper"); + toppings.add("Sliced black olives"); + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/AlternatingDinerMenuIterator.java b/HF_DP/src/headfirst/iterator/dinermerger/AlternatingDinerMenuIterator.java new file mode 100644 index 00000000..50bf0cae --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/AlternatingDinerMenuIterator.java @@ -0,0 +1,29 @@ +package headfirst.iterator.dinermerger; + +import java.util.Calendar; + +public class AlternatingDinerMenuIterator implements Iterator { + MenuItem[] list; + int position; + + public AlternatingDinerMenuIterator(MenuItem[] list) { + this.list = list; + Calendar rightNow = Calendar.getInstance(); + position = rightNow.DAY_OF_WEEK % 2; + } + public Object next() { + MenuItem menuItem = list[position]; + position = position + 2; + return menuItem; + } + public boolean hasNext() { + if (position >= list.length || list[position] == null) { + return false; + } else { + return true; + } + } + public String toString() { + return "Alternating Diner Menu Iterator"; + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/ArrayIterator.java b/HF_DP/src/headfirst/iterator/dinermerger/ArrayIterator.java new file mode 100644 index 00000000..c4d4b9dd --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/ArrayIterator.java @@ -0,0 +1,24 @@ +package headfirst.iterator.dinermerger; + +public class ArrayIterator implements Iterator { + MenuItem[] items; + int position = 0; + + public ArrayIterator(MenuItem[] items) { + this.items = items; + } + + public Object next() { + MenuItem menuItem = items[position]; + position = position + 1; + return menuItem; + } + + public boolean hasNext() { + if (position >= items.length || items[position] == null) { + return false; + } else { + return true; + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/ArrayListIterator.java b/HF_DP/src/headfirst/iterator/dinermerger/ArrayListIterator.java new file mode 100644 index 00000000..45b950a7 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/ArrayListIterator.java @@ -0,0 +1,26 @@ +package headfirst.iterator.dinermerger; + +import java.util.ArrayList; + +public class ArrayListIterator implements Iterator { + ArrayList items; + int position = 0; + + public ArrayListIterator(ArrayList items) { + this.items = items; + } + + public Object next() { + Object object = items.get(position); + position = position + 1; + return object; + } + + public boolean hasNext() { + if (position >= items.size()) { + return false; + } else { + return true; + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/DinerMenu.java b/HF_DP/src/headfirst/iterator/dinermerger/DinerMenu.java new file mode 100644 index 00000000..c1bfce24 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/DinerMenu.java @@ -0,0 +1,48 @@ +package headfirst.iterator.dinermerger; + +public class DinerMenu implements Menu { + static final int MAX_ITEMS = 6; + int numberOfItems = 0; + MenuItem[] menuItems; + + public DinerMenu() { + menuItems = new MenuItem[MAX_ITEMS]; + + addItem("Vegetarian BLT", + "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99); + addItem("BLT", + "Bacon with lettuce & tomato on whole wheat", false, 2.99); + addItem("Soup of the day", + "Soup of the day, with a side of potato salad", false, 3.29); + addItem("Hotdog", + "A hot dog, with saurkraut, relish, onions, topped with cheese", + false, 3.05); + addItem("Steamed Veggies and Brown Rice", + "Steamed vegetables over brown rice", true, 3.99); + addItem("Pasta", + "Spaghetti with Marinara Sauce, and a slice of sourdough bread", + true, 3.89); + } + + public void addItem(String name, String description, + boolean vegetarian, double price) + { + MenuItem menuItem = new MenuItem(name, description, vegetarian, price); + if (numberOfItems >= MAX_ITEMS) { + System.err.println("Sorry, menu is full! Can't add item to menu"); + } else { + menuItems[numberOfItems] = menuItem; + numberOfItems = numberOfItems + 1; + } + } + + public MenuItem[] getMenuItems() { + return menuItems; + } + + public Iterator createIterator() { + return new DinerMenuIterator(menuItems); + } + + // other menu methods here +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/DinerMenuIterator.java b/HF_DP/src/headfirst/iterator/dinermerger/DinerMenuIterator.java new file mode 100644 index 00000000..8f5e2a46 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/DinerMenuIterator.java @@ -0,0 +1,24 @@ +package headfirst.iterator.dinermerger; + +public class DinerMenuIterator implements Iterator { + MenuItem[] items; + int position = 0; + + public DinerMenuIterator(MenuItem[] items) { + this.items = items; + } + + public Object next() { + MenuItem menuItem = items[position]; + position = position + 1; + return menuItem; + } + + public boolean hasNext() { + if (position >= items.length || items[position] == null) { + return false; + } else { + return true; + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/Iterator.java b/HF_DP/src/headfirst/iterator/dinermerger/Iterator.java new file mode 100644 index 00000000..a4e64ce9 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/Iterator.java @@ -0,0 +1,6 @@ +package headfirst.iterator.dinermerger; + +public interface Iterator { + boolean hasNext(); + Object next(); +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/Menu.java b/HF_DP/src/headfirst/iterator/dinermerger/Menu.java new file mode 100644 index 00000000..1f10d16a --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/Menu.java @@ -0,0 +1,5 @@ +package headfirst.iterator.dinermerger; + +public interface Menu { + public Iterator createIterator(); +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/MenuItem.java b/HF_DP/src/headfirst/iterator/dinermerger/MenuItem.java new file mode 100644 index 00000000..80009c9a --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/MenuItem.java @@ -0,0 +1,38 @@ +package headfirst.iterator.dinermerger; + +public class MenuItem { + String name; + String description; + boolean vegetarian; + double price; + + public MenuItem(String name, + String description, + boolean vegetarian, + double price) + { + this.name = name; + this.description = description; + this.vegetarian = vegetarian; + this.price = price; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public double getPrice() { + return price; + } + + public boolean isVegetarian() { + return vegetarian; + } + public String toString() { + return (name + ", $" + price + "\n " + description); + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/MenuTestDrive.java b/HF_DP/src/headfirst/iterator/dinermerger/MenuTestDrive.java new file mode 100644 index 00000000..75950625 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/MenuTestDrive.java @@ -0,0 +1,37 @@ +package headfirst.iterator.dinermerger; + +import java.util.*; + +public class MenuTestDrive { + public static void main(String args[]) { + PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); + DinerMenu dinerMenu = new DinerMenu(); + + Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu); + + waitress.printMenu(); + } + + public static void printMenu() { + PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); + DinerMenu dinerMenu = new DinerMenu(); + + ArrayList breakfastItems = pancakeHouseMenu.getMenuItems(); + + for (int i = 0; i < breakfastItems.size(); i++) { + MenuItem menuItem = (MenuItem)breakfastItems.get(i); + System.out.print(menuItem.getName()); + System.out.println("\t\t" + menuItem.getPrice()); + System.out.println("\t" + menuItem.getDescription()); + } + + MenuItem[] lunchItems = dinerMenu.getMenuItems(); + + for (int i = 0; i < lunchItems.length; i++) { + MenuItem menuItem = lunchItems[i]; + System.out.print(menuItem.getName()); + System.out.println("\t\t" + menuItem.getPrice()); + System.out.println("\t" + menuItem.getDescription()); + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/PancakeHouseMenu.java b/HF_DP/src/headfirst/iterator/dinermerger/PancakeHouseMenu.java new file mode 100644 index 00000000..9160b073 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/PancakeHouseMenu.java @@ -0,0 +1,52 @@ +package headfirst.iterator.dinermerger; + +import java.util.ArrayList; + +public class PancakeHouseMenu implements Menu { + ArrayList menuItems; + + public PancakeHouseMenu() { + menuItems = new ArrayList(); + + addItem("K&B's Pancake Breakfast", + "Pancakes with scrambled eggs, and toast", + true, + 2.99); + + addItem("Regular Pancake Breakfast", + "Pancakes with fried eggs, sausage", + false, + 2.99); + + addItem("Blueberry Pancakes", + "Pancakes made with fresh blueberries", + true, + 3.49); + + addItem("Waffles", + "Waffles, with your choice of blueberries or strawberries", + true, + 3.59); + } + + public void addItem(String name, String description, + boolean vegetarian, double price) + { + MenuItem menuItem = new MenuItem(name, description, vegetarian, price); + menuItems.add(menuItem); + } + + public ArrayList getMenuItems() { + return menuItems; + } + + public Iterator createIterator() { + return new PancakeHouseMenuIterator(menuItems); + } + + public String toString() { + return "Objectville Pancake House Menu"; + } + + // other menu methods here +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/PancakeHouseMenuIterator.java b/HF_DP/src/headfirst/iterator/dinermerger/PancakeHouseMenuIterator.java new file mode 100644 index 00000000..e9fd5265 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/PancakeHouseMenuIterator.java @@ -0,0 +1,26 @@ +package headfirst.iterator.dinermerger; + +import java.util.ArrayList; + +public class PancakeHouseMenuIterator implements Iterator { + ArrayList items; + int position = 0; + + public PancakeHouseMenuIterator(ArrayList items) { + this.items = items; + } + + public Object next() { + Object object = items.get(position); + position = position + 1; + return object; + } + + public boolean hasNext() { + if (position >= items.size()) { + return false; + } else { + return true; + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermerger/Waitress.java b/HF_DP/src/headfirst/iterator/dinermerger/Waitress.java new file mode 100644 index 00000000..9079d067 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermerger/Waitress.java @@ -0,0 +1,71 @@ +package headfirst.iterator.dinermerger; + +public class Waitress { + PancakeHouseMenu pancakeHouseMenu; + DinerMenu dinerMenu; + + public Waitress(PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) { + this.pancakeHouseMenu = pancakeHouseMenu; + this.dinerMenu = dinerMenu; + } + + public void printMenu() { + Iterator pancakeIterator = pancakeHouseMenu.createIterator(); + Iterator dinerIterator = dinerMenu.createIterator(); + + System.out.println("MENU\n----\nBREAKFAST"); + printMenu(pancakeIterator); + System.out.println("\nLUNCH"); + printMenu(dinerIterator); + } + + private void printMenu(Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + System.out.print(menuItem.getName() + ", "); + System.out.print(menuItem.getPrice() + " -- "); + System.out.println(menuItem.getDescription()); + } + } + + public void printVegetarianMenu() { + printVegetarianMenu(pancakeHouseMenu.createIterator()); + printVegetarianMenu(dinerMenu.createIterator()); + } + + public boolean isItemVegetarian(String name) { + Iterator breakfastIterator = pancakeHouseMenu.createIterator(); + if (isVegetarian(name, breakfastIterator)) { + return true; + } + Iterator dinnerIterator = dinerMenu.createIterator(); + if (isVegetarian(name, dinnerIterator)) { + return true; + } + return false; + } + + + private void printVegetarianMenu(Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + if (menuItem.isVegetarian()) { + System.out.print(menuItem.getName()); + System.out.println("\t\t" + menuItem.getPrice()); + System.out.println("\t" + menuItem.getDescription()); + } + } + } + + private boolean isVegetarian(String name, Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + if (menuItem.getName().equals(name)) { + if (menuItem.isVegetarian()) { + return true; + } + } + } + return false; + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/AlternatingDinerMenuIterator.java b/HF_DP/src/headfirst/iterator/dinermergercafe/AlternatingDinerMenuIterator.java new file mode 100644 index 00000000..b6e25a5d --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/AlternatingDinerMenuIterator.java @@ -0,0 +1,31 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.Iterator; +import java.util.Calendar; + +public class AlternatingDinerMenuIterator implements Iterator { + MenuItem[] items; + int position; + + public AlternatingDinerMenuIterator(MenuItem[] items) { + this.items = items; + Calendar rightNow = Calendar.getInstance(); + position = rightNow.DAY_OF_WEEK % 2; + } + public Object next() { + MenuItem menuItem = items[position]; + position = position + 2; + return menuItem; + } + public boolean hasNext() { + if (position >= items.length || items[position] == null) { + return false; + } else { + return true; + } + } + public void remove() { + throw new UnsupportedOperationException( + "Alternating Diner Menu Iterator does not support remove()"); + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/CafeMenu.java b/HF_DP/src/headfirst/iterator/dinermergercafe/CafeMenu.java new file mode 100644 index 00000000..d2737614 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/CafeMenu.java @@ -0,0 +1,34 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.*; + +public class CafeMenu implements Menu { + Hashtable menuItems = new Hashtable(); + + public CafeMenu() { + addItem("Veggie Burger and Air Fries", + "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", + true, 3.99); + addItem("Soup of the day", + "A cup of the soup of the day, with a side salad", + false, 3.69); + addItem("Burrito", + "A large burrito, with whole pinto beans, salsa, guacamole", + true, 4.29); + } + + public void addItem(String name, String description, + boolean vegetarian, double price) + { + MenuItem menuItem = new MenuItem(name, description, vegetarian, price); + menuItems.put(menuItem.getName(), menuItem); + } + + public Hashtable getItems() { + return menuItems; + } + + public Iterator createIterator() { + return menuItems.values().iterator(); + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/DinerMenu.java b/HF_DP/src/headfirst/iterator/dinermergercafe/DinerMenu.java new file mode 100644 index 00000000..3473046d --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/DinerMenu.java @@ -0,0 +1,51 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.Iterator; + +public class DinerMenu implements Menu { + static final int MAX_ITEMS = 6; + int numberOfItems = 0; + MenuItem[] menuItems; + + public DinerMenu() { + menuItems = new MenuItem[MAX_ITEMS]; + + addItem("Vegetarian BLT", + "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99); + addItem("BLT", + "Bacon with lettuce & tomato on whole wheat", false, 2.99); + addItem("Soup of the day", + "Soup of the day, with a side of potato salad", false, 3.29); + addItem("Hotdog", + "A hot dog, with saurkraut, relish, onions, topped with cheese", + false, 3.05); + addItem("Steamed Veggies and Brown Rice", + "A medly of steamed vegetables over brown rice", true, 3.99); + addItem("Pasta", + "Spaghetti with Marinara Sauce, and a slice of sourdough bread", + true, 3.89); + } + + public void addItem(String name, String description, + boolean vegetarian, double price) + { + MenuItem menuItem = new MenuItem(name, description, vegetarian, price); + if (numberOfItems >= MAX_ITEMS) { + System.err.println("Sorry, menu is full! Can't add item to menu"); + } else { + menuItems[numberOfItems] = menuItem; + numberOfItems = numberOfItems + 1; + } + } + + public MenuItem[] getMenuItems() { + return menuItems; + } + + public Iterator createIterator() { + return new DinerMenuIterator(menuItems); + //return new AlternatingDinerMenuIterator(menuItems); + } + + // other menu methods here +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/DinerMenuIterator.java b/HF_DP/src/headfirst/iterator/dinermergercafe/DinerMenuIterator.java new file mode 100644 index 00000000..f6d648e3 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/DinerMenuIterator.java @@ -0,0 +1,39 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.Iterator; + +public class DinerMenuIterator implements Iterator { + MenuItem[] list; + int position = 0; + + public DinerMenuIterator(MenuItem[] list) { + this.list = list; + } + + public Object next() { + MenuItem menuItem = list[position]; + position = position + 1; + return menuItem; + } + + public boolean hasNext() { + if (position >= list.length || list[position] == null) { + return false; + } else { + return true; + } + } + + public void remove() { + if (position <= 0) { + throw new IllegalStateException + ("You can't remove an item until you've done at least one next()"); + } + if (list[position-1] != null) { + for (int i = position-1; i < (list.length-1); i++) { + list[i] = list[i+1]; + } + list[list.length-1] = null; + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/Menu.java b/HF_DP/src/headfirst/iterator/dinermergercafe/Menu.java new file mode 100644 index 00000000..d06c4028 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/Menu.java @@ -0,0 +1,7 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.Iterator; + +public interface Menu { + public Iterator createIterator(); +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/MenuItem.java b/HF_DP/src/headfirst/iterator/dinermergercafe/MenuItem.java new file mode 100644 index 00000000..45fda957 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/MenuItem.java @@ -0,0 +1,35 @@ +package headfirst.iterator.dinermergercafe; + +public class MenuItem { + String name; + String description; + boolean vegetarian; + double price; + + public MenuItem(String name, + String description, + boolean vegetarian, + double price) + { + this.name = name; + this.description = description; + this.vegetarian = vegetarian; + this.price = price; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public double getPrice() { + return price; + } + + public boolean isVegetarian() { + return vegetarian; + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/MenuTestDrive.java b/HF_DP/src/headfirst/iterator/dinermergercafe/MenuTestDrive.java new file mode 100644 index 00000000..ff2be030 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/MenuTestDrive.java @@ -0,0 +1,31 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.*; + +public class MenuTestDrive { + public static void main(String args[]) { + PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); + DinerMenu dinerMenu = new DinerMenu(); + CafeMenu cafeMenu = new CafeMenu(); + + Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu, cafeMenu); + + waitress.printMenu(); + waitress.printVegetarianMenu(); + + System.out.println("\nCustomer asks, is the Hotdog vegetarian?"); + System.out.print("Waitress says: "); + if (waitress.isItemVegetarian("Hotdog")) { + System.out.println("Yes"); + } else { + System.out.println("No"); + } + System.out.println("\nCustomer asks, are the Waffles vegetarian?"); + System.out.print("Waitress says: "); + if (waitress.isItemVegetarian("Waffles")) { + System.out.println("Yes"); + } else { + System.out.println("No"); + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/PancakeHouseMenu.java b/HF_DP/src/headfirst/iterator/dinermergercafe/PancakeHouseMenu.java new file mode 100644 index 00000000..aa255370 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/PancakeHouseMenu.java @@ -0,0 +1,49 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.ArrayList; +import java.util.Iterator; + +public class PancakeHouseMenu implements Menu { + ArrayList menuItems; + + public PancakeHouseMenu() { + menuItems = new ArrayList(); + + addItem("K&B's Pancake Breakfast", + "Pancakes with scrambled eggs, and toast", + true, + 2.99); + + addItem("Regular Pancake Breakfast", + "Pancakes with fried eggs, sausage", + false, + 2.99); + + addItem("Blueberry Pancakes", + "Pancakes made with fresh blueberries, and blueberry syrup", + true, + 3.49); + + addItem("Waffles", + "Waffles, with your choice of blueberries or strawberries", + true, + 3.59); + } + + public void addItem(String name, String description, + boolean vegetarian, double price) + { + MenuItem menuItem = new MenuItem(name, description, vegetarian, price); + menuItems.add(menuItem); + } + + public ArrayList getMenuItems() { + return menuItems; + } + + public Iterator createIterator() { + return menuItems.iterator(); + } + + // other menu methods here +} diff --git a/HF_DP/src/headfirst/iterator/dinermergercafe/Waitress.java b/HF_DP/src/headfirst/iterator/dinermergercafe/Waitress.java new file mode 100644 index 00000000..86cd1810 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergercafe/Waitress.java @@ -0,0 +1,86 @@ +package headfirst.iterator.dinermergercafe; + +import java.util.Iterator; + +public class Waitress { + Menu pancakeHouseMenu; + Menu dinerMenu; + Menu cafeMenu; + + public Waitress(Menu pancakeHouseMenu, Menu dinerMenu, Menu cafeMenu) { + this.pancakeHouseMenu = pancakeHouseMenu; + this.dinerMenu = dinerMenu; + this.cafeMenu = cafeMenu; + } + + public void printMenu() { + Iterator pancakeIterator = pancakeHouseMenu.createIterator(); + Iterator dinerIterator = dinerMenu.createIterator(); + Iterator cafeIterator = cafeMenu.createIterator(); + + System.out.println("MENU\n----\nBREAKFAST"); + printMenu(pancakeIterator); + System.out.println("\nLUNCH"); + printMenu(dinerIterator); + System.out.println("\nDINNER"); + printMenu(cafeIterator); + } + + private void printMenu(Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + System.out.print(menuItem.getName() + ", "); + System.out.print(menuItem.getPrice() + " -- "); + System.out.println(menuItem.getDescription()); + } + } + + public void printVegetarianMenu() { + System.out.println("\nVEGETARIAN MENU\n---------------"); + printVegetarianMenu(pancakeHouseMenu.createIterator()); + printVegetarianMenu(dinerMenu.createIterator()); + printVegetarianMenu(cafeMenu.createIterator()); + } + + public boolean isItemVegetarian(String name) { + Iterator pancakeIterator = pancakeHouseMenu.createIterator(); + if (isVegetarian(name, pancakeIterator)) { + return true; + } + Iterator dinerIterator = dinerMenu.createIterator(); + if (isVegetarian(name, dinerIterator)) { + return true; + } + Iterator cafeIterator = cafeMenu.createIterator(); + if (isVegetarian(name, cafeIterator)) { + return true; + } + return false; + } + + + private void printVegetarianMenu(Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + if (menuItem.isVegetarian()) { + System.out.print(menuItem.getName() + ", "); + System.out.print(menuItem.getPrice() + " -- "); + System.out.println(menuItem.getDescription()); + } + } + } + + private boolean isVegetarian(String name, Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + if (menuItem.getName().equals(name)) { + if (menuItem.isVegetarian()) { + return true; + } + } + } + return false; + } +} +//^^ WaitressCafeMain +//^^ WaitressCafe diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/AlternatingDinerMenuIterator.java b/HF_DP/src/headfirst/iterator/dinermergeri/AlternatingDinerMenuIterator.java new file mode 100644 index 00000000..feaf5684 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/AlternatingDinerMenuIterator.java @@ -0,0 +1,31 @@ +package headfirst.iterator.dinermergeri; + +import java.util.Iterator; +import java.util.Calendar; + +public class AlternatingDinerMenuIterator implements Iterator { + MenuItem[] items; + int position; + + public AlternatingDinerMenuIterator(MenuItem[] items) { + this.items = items; + Calendar rightNow = Calendar.getInstance(); + position = rightNow.DAY_OF_WEEK % 2; + } + public Object next() { + MenuItem menuItem = items[position]; + position = position + 2; + return menuItem; + } + public boolean hasNext() { + if (position >= items.length || items[position] == null) { + return false; + } else { + return true; + } + } + public void remove() { + throw new UnsupportedOperationException( + "Alternating Diner Menu Iterator does not support remove()"); + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/DinerMenu.java b/HF_DP/src/headfirst/iterator/dinermergeri/DinerMenu.java new file mode 100644 index 00000000..daec3eb8 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/DinerMenu.java @@ -0,0 +1,51 @@ +package headfirst.iterator.dinermergeri; + +import java.util.Iterator; + +public class DinerMenu implements Menu { + static final int MAX_ITEMS = 6; + int numberOfItems = 0; + MenuItem[] menuItems; + + public DinerMenu() { + menuItems = new MenuItem[MAX_ITEMS]; + + addItem("Vegetarian BLT", + "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99); + addItem("BLT", + "Bacon with lettuce & tomato on whole wheat", false, 2.99); + addItem("Soup of the day", + "Soup of the day, with a side of potato salad", false, 3.29); + addItem("Hotdog", + "A hot dog, with saurkraut, relish, onions, topped with cheese", + false, 3.05); + addItem("Steamed Veggies and Brown Rice", + "Steamed vegetables over brown rice", true, 3.99); + addItem("Pasta", + "Spaghetti with Marinara Sauce, and a slice of sourdough bread", + true, 3.89); + } + + public void addItem(String name, String description, + boolean vegetarian, double price) + { + MenuItem menuItem = new MenuItem(name, description, vegetarian, price); + if (numberOfItems >= MAX_ITEMS) { + System.err.println("Sorry, menu is full! Can't add item to menu"); + } else { + menuItems[numberOfItems] = menuItem; + numberOfItems = numberOfItems + 1; + } + } + + public MenuItem[] getMenuItems() { + return menuItems; + } + + public Iterator createIterator() { + return new DinerMenuIterator(menuItems); + //return new AlternatingDinerMenuIterator(menuItems); + } + + // other menu methods here +} diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/DinerMenuIterator.java b/HF_DP/src/headfirst/iterator/dinermergeri/DinerMenuIterator.java new file mode 100644 index 00000000..c8a1a7eb --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/DinerMenuIterator.java @@ -0,0 +1,39 @@ +package headfirst.iterator.dinermergeri; + +import java.util.Iterator; + +public class DinerMenuIterator implements Iterator { + MenuItem[] list; + int position = 0; + + public DinerMenuIterator(MenuItem[] list) { + this.list = list; + } + + public Object next() { + MenuItem menuItem = list[position]; + position = position + 1; + return menuItem; + } + + public boolean hasNext() { + if (position >= list.length || list[position] == null) { + return false; + } else { + return true; + } + } + + public void remove() { + if (position <= 0) { + throw new IllegalStateException + ("You can't remove an item until you've done at least one next()"); + } + if (list[position-1] != null) { + for (int i = position-1; i < (list.length-1); i++) { + list[i] = list[i+1]; + } + list[list.length-1] = null; + } + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/Menu.java b/HF_DP/src/headfirst/iterator/dinermergeri/Menu.java new file mode 100644 index 00000000..153819bf --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/Menu.java @@ -0,0 +1,7 @@ +package headfirst.iterator.dinermergeri; + +import java.util.Iterator; + +public interface Menu { + public Iterator createIterator(); +} diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/MenuItem.java b/HF_DP/src/headfirst/iterator/dinermergeri/MenuItem.java new file mode 100644 index 00000000..4f96823b --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/MenuItem.java @@ -0,0 +1,35 @@ +package headfirst.iterator.dinermergeri; + +public class MenuItem { + String name; + String description; + boolean vegetarian; + double price; + + public MenuItem(String name, + String description, + boolean vegetarian, + double price) + { + this.name = name; + this.description = description; + this.vegetarian = vegetarian; + this.price = price; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public double getPrice() { + return price; + } + + public boolean isVegetarian() { + return vegetarian; + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/MenuTestDrive.java b/HF_DP/src/headfirst/iterator/dinermergeri/MenuTestDrive.java new file mode 100644 index 00000000..b8e6712c --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/MenuTestDrive.java @@ -0,0 +1,29 @@ +package headfirst.iterator.dinermergeri; + +import java.util.*; + +public class MenuTestDrive { + public static void main(String args[]) { + PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); + DinerMenu dinerMenu = new DinerMenu(); + Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu); + waitress.printMenu(); + waitress.printVegetarianMenu(); + + System.out.println("\nCustomer asks, is the Hotdog vegetarian?"); + System.out.print("Waitress says: "); + if (waitress.isItemVegetarian("Hotdog")) { + System.out.println("Yes"); + } else { + System.out.println("No"); + } + System.out.println("\nCustomer asks, are the Waffles vegetarian?"); + System.out.print("Waitress says: "); + if (waitress.isItemVegetarian("Waffles")) { + System.out.println("Yes"); + } else { + System.out.println("No"); + } + + } +} diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/PancakeHouseMenu.java b/HF_DP/src/headfirst/iterator/dinermergeri/PancakeHouseMenu.java new file mode 100644 index 00000000..fdf2db3f --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/PancakeHouseMenu.java @@ -0,0 +1,49 @@ +package headfirst.iterator.dinermergeri; + +import java.util.ArrayList; +import java.util.Iterator; + +public class PancakeHouseMenu implements Menu { + ArrayList menuItems; + + public PancakeHouseMenu() { + menuItems = new ArrayList(); + + addItem("K&B's Pancake Breakfast", + "Pancakes with scrambled eggs, and toast", + true, + 2.99); + + addItem("Regular Pancake Breakfast", + "Pancakes with fried eggs, sausage", + false, + 2.99); + + addItem("Blueberry Pancakes", + "Pancakes made with fresh blueberries, and blueberry syrup", + true, + 3.49); + + addItem("Waffles", + "Waffles, with your choice of blueberries or strawberries", + true, + 3.59); + } + + public void addItem(String name, String description, + boolean vegetarian, double price) + { + MenuItem menuItem = new MenuItem(name, description, vegetarian, price); + menuItems.add(menuItem); + } + + public ArrayList getMenuItems() { + return menuItems; + } + + public Iterator createIterator() { + return menuItems.iterator(); + } + + // other menu methods here +} diff --git a/HF_DP/src/headfirst/iterator/dinermergeri/Waitress.java b/HF_DP/src/headfirst/iterator/dinermergeri/Waitress.java new file mode 100644 index 00000000..3059eb60 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/dinermergeri/Waitress.java @@ -0,0 +1,76 @@ +package headfirst.iterator.dinermergeri; + +import java.util.Iterator; + + +public class Waitress { + Menu pancakeHouseMenu; + Menu dinerMenu; + + public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) { + this.pancakeHouseMenu = pancakeHouseMenu; + this.dinerMenu = dinerMenu; + } + + public void printMenu() { + Iterator pancakeIterator = pancakeHouseMenu.createIterator(); + Iterator dinerIterator = dinerMenu.createIterator(); + + System.out.println("MENU\n----\nBREAKFAST"); + printMenu(pancakeIterator); + System.out.println("\nLUNCH"); + printMenu(dinerIterator); + } + + private void printMenu(Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + System.out.print(menuItem.getName() + ", "); + System.out.print(menuItem.getPrice() + " -- "); + System.out.println(menuItem.getDescription()); + } + } + + public void printVegetarianMenu() { + System.out.println("\nVEGETARIAN MENU\n----\nBREAKFAST"); + printVegetarianMenu(pancakeHouseMenu.createIterator()); + System.out.println("\nLUNCH"); + printVegetarianMenu(dinerMenu.createIterator()); + } + + public boolean isItemVegetarian(String name) { + Iterator pancakeIterator = pancakeHouseMenu.createIterator(); + if (isVegetarian(name, pancakeIterator)) { + return true; + } + Iterator dinerIterator = dinerMenu.createIterator(); + if (isVegetarian(name, dinerIterator)) { + return true; + } + return false; + } + + + private void printVegetarianMenu(Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + if (menuItem.isVegetarian()) { + System.out.print(menuItem.getName()); + System.out.println("\t\t" + menuItem.getPrice()); + System.out.println("\t" + menuItem.getDescription()); + } + } + } + + private boolean isVegetarian(String name, Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + if (menuItem.getName().equals(name)) { + if (menuItem.isVegetarian()) { + return true; + } + } + } + return false; + } +} diff --git a/HF_DP/src/headfirst/iterator/transition/Menu.java b/HF_DP/src/headfirst/iterator/transition/Menu.java new file mode 100644 index 00000000..87ea7b24 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/transition/Menu.java @@ -0,0 +1,7 @@ +package headfirst.iterator.transition; + +import java.util.Iterator; + +public interface Menu { + public Iterator createIterator(); +} diff --git a/HF_DP/src/headfirst/iterator/transition/MenuItem.java b/HF_DP/src/headfirst/iterator/transition/MenuItem.java new file mode 100644 index 00000000..7367edf5 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/transition/MenuItem.java @@ -0,0 +1,35 @@ +package headfirst.iterator.transition; + +public class MenuItem { + String name; + String description; + boolean vegetarian; + double price; + + public MenuItem(String name, + String description, + boolean vegetarian, + double price) + { + this.name = name; + this.description = description; + this.vegetarian = vegetarian; + this.price = price; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public double getPrice() { + return price; + } + + public boolean isVegetarian() { + return vegetarian; + } +} diff --git a/HF_DP/src/headfirst/iterator/transition/Waitress.java b/HF_DP/src/headfirst/iterator/transition/Waitress.java new file mode 100644 index 00000000..06214bb2 --- /dev/null +++ b/HF_DP/src/headfirst/iterator/transition/Waitress.java @@ -0,0 +1,29 @@ +package headfirst.iterator.transition; +import java.util.*; + + +public class Waitress { + ArrayList menus; + + + public Waitress(ArrayList menus) { + this.menus = menus; + } + + public void printMenu() { + Iterator menuIterator = menus.iterator(); + while(menuIterator.hasNext()) { + Menu menu = (Menu)menuIterator.next(); + printMenu(menu.createIterator()); + } + } + + void printMenu(Iterator iterator) { + while (iterator.hasNext()) { + MenuItem menuItem = (MenuItem)iterator.next(); + System.out.print(menuItem.getName() + ", "); + System.out.print(menuItem.getPrice() + " -- "); + System.out.println(menuItem.getDescription()); + } + } +} diff --git a/HF_DP/src/headfirst/observer/swing/SwingObserverExample.java b/HF_DP/src/headfirst/observer/swing/SwingObserverExample.java new file mode 100644 index 00000000..367d24db --- /dev/null +++ b/HF_DP/src/headfirst/observer/swing/SwingObserverExample.java @@ -0,0 +1,42 @@ +package headfirst.observer.swing; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; + +public class SwingObserverExample { + JFrame frame; + + public static void main(String[] args) { + SwingObserverExample example = new SwingObserverExample(); + example.go(); + } + + public void go() { + frame = new JFrame(); + + JButton button = new JButton("Should I do it?"); + button.addActionListener(new AngelListener()); + button.addActionListener(new DevilListener()); + frame.getContentPane().add(BorderLayout.CENTER, button); + + // Set frame properties + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().add(BorderLayout.CENTER, button); + frame.setSize(300,300); + frame.setVisible(true); + } + + class AngelListener implements ActionListener { + public void actionPerformed(ActionEvent event) { + System.out.println("Don't do it, you might regret it!"); + } + } + + class DevilListener implements ActionListener { + public void actionPerformed(ActionEvent event) { + System.out.println("Come on, do it!"); + } + } +} diff --git a/HF_DP/src/headfirst/observer/weather/CurrentConditionsDisplay.java b/HF_DP/src/headfirst/observer/weather/CurrentConditionsDisplay.java new file mode 100644 index 00000000..78680844 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/CurrentConditionsDisplay.java @@ -0,0 +1,23 @@ +package headfirst.observer.weather; + +public class CurrentConditionsDisplay implements Observer, DisplayElement { + private float temperature; + private float humidity; + private Subject weatherData; + + public CurrentConditionsDisplay(Subject weatherData) { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + public void update(float temperature, float humidity, float pressure) { + this.temperature = temperature; + this.humidity = humidity; + display(); + } + + public void display() { + System.out.println("Current conditions: " + temperature + + "F degrees and " + humidity + "% humidity"); + } +} diff --git a/HF_DP/src/headfirst/observer/weather/DisplayElement.java b/HF_DP/src/headfirst/observer/weather/DisplayElement.java new file mode 100644 index 00000000..c482707b --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/DisplayElement.java @@ -0,0 +1,5 @@ +package headfirst.observer.weather; + +public interface DisplayElement { + public void display(); +} diff --git a/HF_DP/src/headfirst/observer/weather/ForecastDisplay.java b/HF_DP/src/headfirst/observer/weather/ForecastDisplay.java new file mode 100644 index 00000000..7fb89491 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/ForecastDisplay.java @@ -0,0 +1,32 @@ +package headfirst.observer.weather; + +import java.util.*; + +public class ForecastDisplay implements Observer, DisplayElement { + private float currentPressure = 29.92f; + private float lastPressure; + private WeatherData weatherData; + + public ForecastDisplay(WeatherData weatherData) { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + public void update(float temp, float humidity, float pressure) { + lastPressure = currentPressure; + currentPressure = pressure; + + display(); + } + + public void display() { + System.out.print("Forecast: "); + if (currentPressure > lastPressure) { + System.out.println("Improving weather on the way!"); + } else if (currentPressure == lastPressure) { + System.out.println("More of the same"); + } else if (currentPressure < lastPressure) { + System.out.println("Watch out for cooler, rainy weather"); + } + } +} diff --git a/HF_DP/src/headfirst/observer/weather/HeatIndexDisplay.java b/HF_DP/src/headfirst/observer/weather/HeatIndexDisplay.java new file mode 100644 index 00000000..d3809b51 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/HeatIndexDisplay.java @@ -0,0 +1,32 @@ +package headfirst.observer.weather; + +public class HeatIndexDisplay implements Observer, DisplayElement { + float heatIndex = 0.0f; + private WeatherData weatherData; + + public HeatIndexDisplay(WeatherData weatherData) { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + public void update(float t, float rh, float pressure) { + heatIndex = computeHeatIndex(t, rh); + display(); + } + + private float computeHeatIndex(float t, float rh) { + float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) + + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) + + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) + + (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * + (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) + + (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) + + 0.000000000843296 * (t * t * rh * rh * rh)) - + (0.0000000000481975 * (t * t * t * rh * rh * rh))); + return index; + } + + public void display() { + System.out.println("Heat index is " + heatIndex); + } +} diff --git a/HF_DP/src/headfirst/observer/weather/Observer.java b/HF_DP/src/headfirst/observer/weather/Observer.java new file mode 100644 index 00000000..92d04c2e --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/Observer.java @@ -0,0 +1,5 @@ +package headfirst.observer.weather; + +public interface Observer { + public void update(float temp, float humidity, float pressure); +} diff --git a/HF_DP/src/headfirst/observer/weather/StatisticsDisplay.java b/HF_DP/src/headfirst/observer/weather/StatisticsDisplay.java new file mode 100644 index 00000000..1f60757e --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/StatisticsDisplay.java @@ -0,0 +1,36 @@ +package headfirst.observer.weather; + +import java.util.*; + +public class StatisticsDisplay implements Observer, DisplayElement { + private float maxTemp = 0.0f; + private float minTemp = 200; + private float tempSum= 0.0f; + private int numReadings; + private WeatherData weatherData; + + public StatisticsDisplay(WeatherData weatherData) { + this.weatherData = weatherData; + weatherData.registerObserver(this); + } + + public void update(float temp, float humidity, float pressure) { + tempSum += temp; + numReadings++; + + if (temp > maxTemp) { + maxTemp = temp; + } + + if (temp < minTemp) { + minTemp = temp; + } + + display(); + } + + public void display() { + System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings) + + "/" + maxTemp + "/" + minTemp); + } +} diff --git a/HF_DP/src/headfirst/observer/weather/Subject.java b/HF_DP/src/headfirst/observer/weather/Subject.java new file mode 100644 index 00000000..5cf0468f --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/Subject.java @@ -0,0 +1,7 @@ +package headfirst.observer.weather; + +public interface Subject { + public void registerObserver(Observer o); + public void removeObserver(Observer o); + public void notifyObservers(); +} diff --git a/HF_DP/src/headfirst/observer/weather/WeatherData.java b/HF_DP/src/headfirst/observer/weather/WeatherData.java new file mode 100644 index 00000000..47f7f682 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/WeatherData.java @@ -0,0 +1,55 @@ +package headfirst.observer.weather; + +import java.util.*; + +public class WeatherData implements Subject { + private ArrayList observers; + private float temperature; + private float humidity; + private float pressure; + + public WeatherData() { + observers = new ArrayList(); + } + + public void registerObserver(Observer o) { + observers.add(o); + } + + public void removeObserver(Observer o) { + int i = observers.indexOf(o); + if (i >= 0) { + observers.remove(i); + } + } + + public void notifyObservers() { + for (int i = 0; i < observers.size(); i++) { + Observer observer = (Observer)observers.get(i); + observer.update(temperature, humidity, pressure); + } + } + + public void measurementsChanged() { + notifyObservers(); + } + + public void setMeasurements(float temperature, float humidity, float pressure) { + this.temperature = temperature; + this.humidity = humidity; + this.pressure = pressure; + measurementsChanged(); + } + + public float getTemperature() { + return temperature; + } + + public float getHumidity() { + return humidity; + } + + public float getPressure() { + return pressure; + } +} diff --git a/HF_DP/src/headfirst/observer/weather/WeatherStation.java b/HF_DP/src/headfirst/observer/weather/WeatherStation.java new file mode 100644 index 00000000..29a2a69b --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/WeatherStation.java @@ -0,0 +1,19 @@ +package headfirst.observer.weather; + +import java.util.*; + +public class WeatherStation { + + public static void main(String[] args) { + WeatherData weatherData = new WeatherData(); + + CurrentConditionsDisplay currentDisplay = + new CurrentConditionsDisplay(weatherData); + StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); + ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); + + weatherData.setMeasurements(80, 65, 30.4f); + weatherData.setMeasurements(82, 70, 29.2f); + weatherData.setMeasurements(78, 90, 29.2f); + } +} diff --git a/HF_DP/src/headfirst/observer/weather/WeatherStationHeatIndex.java b/HF_DP/src/headfirst/observer/weather/WeatherStationHeatIndex.java new file mode 100644 index 00000000..4250be6e --- /dev/null +++ b/HF_DP/src/headfirst/observer/weather/WeatherStationHeatIndex.java @@ -0,0 +1,18 @@ +package headfirst.observer.weather; + +import java.util.*; + +public class WeatherStationHeatIndex { + + public static void main(String[] args) { + WeatherData weatherData = new WeatherData(); + CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); + StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); + ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); + HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData); + + weatherData.setMeasurements(80, 65, 30.4f); + weatherData.setMeasurements(82, 70, 29.2f); + weatherData.setMeasurements(78, 90, 29.2f); + } +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/CurrentConditionsDisplay.java b/HF_DP/src/headfirst/observer/weatherobservable/CurrentConditionsDisplay.java new file mode 100644 index 00000000..74a32577 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/CurrentConditionsDisplay.java @@ -0,0 +1,29 @@ +package headfirst.observer.weatherobservable; + +import java.util.Observable; +import java.util.Observer; + +public class CurrentConditionsDisplay implements Observer, DisplayElement { + Observable observable; + private float temperature; + private float humidity; + + public CurrentConditionsDisplay(Observable observable) { + this.observable = observable; + observable.addObserver(this); + } + + public void update(Observable obs, Object arg) { + if (obs instanceof WeatherData) { + WeatherData weatherData = (WeatherData)obs; + this.temperature = weatherData.getTemperature(); + this.humidity = weatherData.getHumidity(); + display(); + } + } + + public void display() { + System.out.println("Current conditions: " + temperature + + "F degrees and " + humidity + "% humidity"); + } +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/DisplayElement.java b/HF_DP/src/headfirst/observer/weatherobservable/DisplayElement.java new file mode 100644 index 00000000..74ad8c7d --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/DisplayElement.java @@ -0,0 +1,5 @@ +package headfirst.observer.weatherobservable; + +public interface DisplayElement { + public void display(); +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/ForecastDisplay.java b/HF_DP/src/headfirst/observer/weatherobservable/ForecastDisplay.java new file mode 100644 index 00000000..7484e312 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/ForecastDisplay.java @@ -0,0 +1,33 @@ +package headfirst.observer.weatherobservable; + +import java.util.Observable; +import java.util.Observer; + +public class ForecastDisplay implements Observer, DisplayElement { + private float currentPressure = 29.92f; + private float lastPressure; + + public ForecastDisplay(Observable observable) { + observable.addObserver(this); + } + + public void update(Observable observable, Object arg) { + if (observable instanceof WeatherData) { + WeatherData weatherData = (WeatherData)observable; + lastPressure = currentPressure; + currentPressure = weatherData.getPressure(); + display(); + } + } + + public void display() { + System.out.print("Forecast: "); + if (currentPressure > lastPressure) { + System.out.println("Improving weather on the way!"); + } else if (currentPressure == lastPressure) { + System.out.println("More of the same"); + } else if (currentPressure < lastPressure) { + System.out.println("Watch out for cooler, rainy weather"); + } + } +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/HeatIndexDisplay.java b/HF_DP/src/headfirst/observer/weatherobservable/HeatIndexDisplay.java new file mode 100644 index 00000000..049eb73c --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/HeatIndexDisplay.java @@ -0,0 +1,42 @@ +package headfirst.observer.weatherobservable; + +import java.util.Observable; +import java.util.Observer; + +public class HeatIndexDisplay implements Observer, DisplayElement { + float heatIndex = 0.0f; + + public HeatIndexDisplay(Observable observable) { + observable.addObserver(this); + } + + public void update(Observable observable, Object arg) { + if (observable instanceof WeatherData) { + WeatherData weatherData = (WeatherData)observable; + float t = weatherData.getTemperature(); + float rh = weatherData.getHumidity(); + heatIndex = (float) + ( + (16.923 + (0.185212 * t)) + + (5.37941 * rh) - + (0.100254 * t * rh) + + (0.00941695 * (t * t)) + + (0.00728898 * (rh * rh)) + + (0.000345372 * (t * t * rh)) - + (0.000814971 * (t * rh * rh)) + + (0.0000102102 * (t * t * rh * rh)) - + (0.000038646 * (t * t * t)) + + (0.0000291583 * (rh * rh * rh)) + + (0.00000142721 * (t * t * t * rh)) + + (0.000000197483 * (t * rh * rh * rh)) - + (0.0000000218429 * (t * t * t * rh * rh)) + + (0.000000000843296 * (t * t * rh * rh * rh)) - + (0.0000000000481975 * (t * t * t * rh * rh * rh))); + display(); + } + } + + public void display() { + System.out.println("Heat index is " + heatIndex); + } +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/StatisticsDisplay.java b/HF_DP/src/headfirst/observer/weatherobservable/StatisticsDisplay.java new file mode 100644 index 00000000..948c2526 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/StatisticsDisplay.java @@ -0,0 +1,39 @@ +package headfirst.observer.weatherobservable; + +import java.util.Observable; +import java.util.Observer; + +public class StatisticsDisplay implements Observer, DisplayElement { + private float maxTemp = 0.0f; + private float minTemp = 200; + private float tempSum= 0.0f; + private int numReadings; + + public StatisticsDisplay(Observable observable) { + observable.addObserver(this); + } + + public void update(Observable observable, Object arg) { + if (observable instanceof WeatherData) { + WeatherData weatherData = (WeatherData)observable; + float temp = weatherData.getTemperature(); + tempSum += temp; + numReadings++; + + if (temp > maxTemp) { + maxTemp = temp; + } + + if (temp < minTemp) { + minTemp = temp; + } + + display(); + } + } + + public void display() { + System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings) + + "/" + maxTemp + "/" + minTemp); + } +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/WeatherData.java b/HF_DP/src/headfirst/observer/weatherobservable/WeatherData.java new file mode 100644 index 00000000..aae07b41 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/WeatherData.java @@ -0,0 +1,36 @@ +package headfirst.observer.weatherobservable; + +import java.util.Observable; +import java.util.Observer; + +public class WeatherData extends Observable { + private float temperature; + private float humidity; + private float pressure; + + public WeatherData() { } + + public void measurementsChanged() { + setChanged(); + notifyObservers(); + } + + public void setMeasurements(float temperature, float humidity, float pressure) { + this.temperature = temperature; + this.humidity = humidity; + this.pressure = pressure; + measurementsChanged(); + } + + public float getTemperature() { + return temperature; + } + + public float getHumidity() { + return humidity; + } + + public float getPressure() { + return pressure; + } +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/WeatherStation.java b/HF_DP/src/headfirst/observer/weatherobservable/WeatherStation.java new file mode 100644 index 00000000..0df1aea8 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/WeatherStation.java @@ -0,0 +1,15 @@ +package headfirst.observer.weatherobservable; + +public class WeatherStation { + + public static void main(String[] args) { + WeatherData weatherData = new WeatherData(); + CurrentConditionsDisplay currentConditions = new CurrentConditionsDisplay(weatherData); + StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); + ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); + + weatherData.setMeasurements(80, 65, 30.4f); + weatherData.setMeasurements(82, 70, 29.2f); + weatherData.setMeasurements(78, 90, 29.2f); + } +} diff --git a/HF_DP/src/headfirst/observer/weatherobservable/WeatherStationHeatIndex.java b/HF_DP/src/headfirst/observer/weatherobservable/WeatherStationHeatIndex.java new file mode 100644 index 00000000..34dee678 --- /dev/null +++ b/HF_DP/src/headfirst/observer/weatherobservable/WeatherStationHeatIndex.java @@ -0,0 +1,16 @@ +package headfirst.observer.weatherobservable; + +public class WeatherStationHeatIndex { + + public static void main(String[] args) { + WeatherData weatherData = new WeatherData(); + CurrentConditionsDisplay currentConditions = new CurrentConditionsDisplay(weatherData); + StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); + ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); + HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData); + + weatherData.setMeasurements(80, 65, 30.4f); + weatherData.setMeasurements(82, 70, 29.2f); + weatherData.setMeasurements(78, 90, 29.2f); + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/GumballMachine.java b/HF_DP/src/headfirst/proxy/gumball/GumballMachine.java new file mode 100644 index 00000000..0afe1bcd --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/GumballMachine.java @@ -0,0 +1,107 @@ +package headfirst.proxy.gumball; + +import java.rmi.*; +import java.rmi.server.*; + +public class GumballMachine + extends UnicastRemoteObject implements GumballMachineRemote +{ + State soldOutState; + State noQuarterState; + State hasQuarterState; + State soldState; + State winnerState; + + State state = soldOutState; + int count = 0; + String location; + + public GumballMachine(String location, int numberGumballs) throws RemoteException { + soldOutState = new SoldOutState(this); + noQuarterState = new NoQuarterState(this); + hasQuarterState = new HasQuarterState(this); + soldState = new SoldState(this); + winnerState = new WinnerState(this); + + this.count = numberGumballs; + if (numberGumballs > 0) { + state = noQuarterState; + } + this.location = location; + } + + + public void insertQuarter() { + state.insertQuarter(); + } + + public void ejectQuarter() { + state.ejectQuarter(); + } + + public void turnCrank() { + state.turnCrank(); + state.dispense(); + } + + void setState(State state) { + this.state = state; + } + + void releaseBall() { + System.out.println("A gumball comes rolling out the slot..."); + if (count != 0) { + count = count - 1; + } + } + + public void refill(int count) { + this.count = count; + state = noQuarterState; + } + + public int getCount() { + return count; + } + + public State getState() { + return state; + } + + public String getLocation() { + return location; + } + + public State getSoldOutState() { + return soldOutState; + } + + public State getNoQuarterState() { + return noQuarterState; + } + + public State getHasQuarterState() { + return hasQuarterState; + } + + public State getSoldState() { + return soldState; + } + + public State getWinnerState() { + return winnerState; + } + + public String toString() { + StringBuffer result = new StringBuffer(); + result.append("\nMighty Gumball, Inc."); + result.append("\nJava-enabled Standing Gumball Model #2004"); + result.append("\nInventory: " + count + " gumball"); + if (count != 1) { + result.append("s"); + } + result.append("\n"); + result.append("Machine is " + state + "\n"); + return result.toString(); + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/GumballMachineRemote.java b/HF_DP/src/headfirst/proxy/gumball/GumballMachineRemote.java new file mode 100644 index 00000000..da5dd5ae --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/GumballMachineRemote.java @@ -0,0 +1,9 @@ +package headfirst.proxy.gumball; + +import java.rmi.*; + +public interface GumballMachineRemote extends Remote { + public int getCount() throws RemoteException; + public String getLocation() throws RemoteException; + public State getState() throws RemoteException; +} diff --git a/HF_DP/src/headfirst/proxy/gumball/GumballMachineTestDrive.java b/HF_DP/src/headfirst/proxy/gumball/GumballMachineTestDrive.java new file mode 100644 index 00000000..4e566433 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/GumballMachineTestDrive.java @@ -0,0 +1,25 @@ +package headfirst.proxy.gumball; +import java.rmi.*; + +public class GumballMachineTestDrive { + + public static void main(String[] args) { + GumballMachineRemote gumballMachine = null; + int count; + + if (args.length < 2) { + System.out.println("GumballMachine "); + System.exit(1); + } + + try { + count = Integer.parseInt(args[1]); + + gumballMachine = + new GumballMachine(args[0], count); + Naming.rebind("//" + args[0] + "/gumballmachine", gumballMachine); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/GumballMonitor.java b/HF_DP/src/headfirst/proxy/gumball/GumballMonitor.java new file mode 100644 index 00000000..0f7b1fe9 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/GumballMonitor.java @@ -0,0 +1,21 @@ +package headfirst.proxy.gumball; + +import java.rmi.*; + +public class GumballMonitor { + GumballMachineRemote machine; + + public GumballMonitor(GumballMachineRemote machine) { + this.machine = machine; + } + + public void report() { + try { + System.out.println("Gumball Machine: " + machine.getLocation()); + System.out.println("Current inventory: " + machine.getCount() + " gumballs"); + System.out.println("Current state: " + machine.getState()); + } catch (RemoteException e) { + e.printStackTrace(); + } + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/GumballMonitorTestDrive.java b/HF_DP/src/headfirst/proxy/gumball/GumballMonitorTestDrive.java new file mode 100644 index 00000000..e097d19d --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/GumballMonitorTestDrive.java @@ -0,0 +1,37 @@ +package headfirst.proxy.gumball; + +import java.rmi.*; + +public class GumballMonitorTestDrive { + + public static void main(String[] args) { + String[] location = {"rmi://santafe.mightygumball.com/gumballmachine", + "rmi://boulder.mightygumball.com/gumballmachine", + "rmi://seattle.mightygumball.com/gumballmachine"}; + + if (args.length >= 0) + { + location = new String[1]; + location[0] = "rmi://" + args[0] + "/gumballmachine"; + } + + GumballMonitor[] monitor = new GumballMonitor[location.length]; + + + + for (int i=0;i < location.length; i++) { + try { + GumballMachineRemote machine = + (GumballMachineRemote) Naming.lookup(location[i]); + monitor[i] = new GumballMonitor(machine); + System.out.println(monitor[i]); + } catch (Exception e) { + e.printStackTrace(); + } + } + + for(int i=0; i < monitor.length; i++) { + monitor[i].report(); + } + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/HasQuarterState.java b/HF_DP/src/headfirst/proxy/gumball/HasQuarterState.java new file mode 100644 index 00000000..e86ae4fe --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/HasQuarterState.java @@ -0,0 +1,39 @@ +package headfirst.proxy.gumball; + +import java.util.Random; + +public class HasQuarterState implements State { + Random randomWinner = new Random(System.currentTimeMillis()); + transient GumballMachine gumballMachine; + + public HasQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert another quarter"); + } + + public void ejectQuarter() { + System.out.println("Quarter returned"); + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + public void turnCrank() { + System.out.println("You turned..."); + int winner = randomWinner.nextInt(10); + if (winner == 0) { + gumballMachine.setState(gumballMachine.getWinnerState()); + } else { + gumballMachine.setState(gumballMachine.getSoldState()); + } + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "waiting for turn of crank"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/NoQuarterState.java b/HF_DP/src/headfirst/proxy/gumball/NoQuarterState.java new file mode 100644 index 00000000..f4efa737 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/NoQuarterState.java @@ -0,0 +1,30 @@ +package headfirst.proxy.gumball; + +public class NoQuarterState implements State { + transient GumballMachine gumballMachine; + + public NoQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You inserted a quarter"); + gumballMachine.setState(gumballMachine.getHasQuarterState()); + } + + public void ejectQuarter() { + System.out.println("You haven't inserted a quarter"); + } + + public void turnCrank() { + System.out.println("You turned, but there's no quarter"); + } + + public void dispense() { + System.out.println("You need to pay first"); + } + + public String toString() { + return "waiting for quarter"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/SoldOutState.java b/HF_DP/src/headfirst/proxy/gumball/SoldOutState.java new file mode 100644 index 00000000..ce823078 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/SoldOutState.java @@ -0,0 +1,29 @@ +package headfirst.proxy.gumball; + +public class SoldOutState implements State { + transient GumballMachine gumballMachine; + + public SoldOutState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert a quarter, the machine is sold out"); + } + + public void ejectQuarter() { + System.out.println("You can't eject, you haven't inserted a quarter yet"); + } + + public void turnCrank() { + System.out.println("You turned, but there are no gumballs"); + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "sold out"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/SoldState.java b/HF_DP/src/headfirst/proxy/gumball/SoldState.java new file mode 100644 index 00000000..07bb0512 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/SoldState.java @@ -0,0 +1,35 @@ +package headfirst.proxy.gumball; + +public class SoldState implements State { + transient GumballMachine gumballMachine; + + public SoldState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("Please wait, we're already giving you a gumball"); + } + + public void ejectQuarter() { + System.out.println("Sorry, you already turned the crank"); + } + + public void turnCrank() { + System.out.println("Turning twice doesn't get you another gumball!"); + } + + public void dispense() { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } else { + System.out.println("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + + public String toString() { + return "dispensing a gumball"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumball/State.java b/HF_DP/src/headfirst/proxy/gumball/State.java new file mode 100644 index 00000000..9fa1181d --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/State.java @@ -0,0 +1,10 @@ +package headfirst.proxy.gumball; + +import java.io.*; + +public interface State extends Serializable { + public void insertQuarter(); + public void ejectQuarter(); + public void turnCrank(); + public void dispense(); +} diff --git a/HF_DP/src/headfirst/proxy/gumball/WinnerState.java b/HF_DP/src/headfirst/proxy/gumball/WinnerState.java new file mode 100644 index 00000000..8fbd7e46 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumball/WinnerState.java @@ -0,0 +1,41 @@ +package headfirst.proxy.gumball; + +public class WinnerState implements State { + transient GumballMachine gumballMachine; + + public WinnerState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("Please wait, we're already giving you a Gumball"); + } + + public void ejectQuarter() { + System.out.println("Please wait, we're already giving you a Gumball"); + } + + public void turnCrank() { + System.out.println("Turning again doesn't get you another gumball!"); + } + + public void dispense() { + System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter"); + gumballMachine.releaseBall(); + if (gumballMachine.getCount() == 0) { + gumballMachine.setState(gumballMachine.getSoldOutState()); + } else { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } else { + System.out.println("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + } + + public String toString() { + return "despensing two gumballs for your quarter, because YOU'RE A WINNER!"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMachine.java b/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMachine.java new file mode 100644 index 00000000..88971bd6 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMachine.java @@ -0,0 +1,101 @@ +package headfirst.proxy.gumballmonitor; + +public class GumballMachine { + State soldOutState; + State noQuarterState; + State hasQuarterState; + State soldState; + State winnerState; + + State state = soldOutState; + int count = 0; + String location; + + public GumballMachine(String location, int count) { + soldOutState = new SoldOutState(this); + noQuarterState = new NoQuarterState(this); + hasQuarterState = new HasQuarterState(this); + soldState = new SoldState(this); + winnerState = new WinnerState(this); + + this.count = count; + if (count > 0) { + state = noQuarterState; + } + this.location = location; + } + + public void insertQuarter() { + state.insertQuarter(); + } + + public void ejectQuarter() { + state.ejectQuarter(); + } + + public void turnCrank() { + state.turnCrank(); + state.dispense(); + } + + void setState(State state) { + this.state = state; + } + + void releaseBall() { + System.out.println("A gumball comes rolling out the slot..."); + if (count != 0) { + count = count - 1; + } + } + + public int getCount() { + return count; + } + + public void refill(int count) { + this.count = count; + state = noQuarterState; + } + + public State getState() { + return state; + } + + public String getLocation() { + return location; + } + + public State getSoldOutState() { + return soldOutState; + } + + public State getNoQuarterState() { + return noQuarterState; + } + + public State getHasQuarterState() { + return hasQuarterState; + } + + public State getSoldState() { + return soldState; + } + + public State getWinnerState() { + return winnerState; + } + + public String toString() { + StringBuffer result = new StringBuffer(); + result.append("\nMighty Gumball, Inc."); + result.append("\nJava-enabled Standing Gumball Model #2004"); + result.append("\nInventory: " + count + " gumball"); + if (count != 1) { + result.append("s"); + } + result.append("\n"); + result.append("Machine is " + state + "\n"); + return result.toString(); + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMachineTestDrive.java b/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMachineTestDrive.java new file mode 100644 index 00000000..1d2d14fb --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMachineTestDrive.java @@ -0,0 +1,63 @@ +package headfirst.proxy.gumballmonitor; + +public class GumballMachineTestDrive { + + public static void main(String[] args) { + int count = 0; + + if (args.length < 2) { + System.out.println("GumballMachine "); + System.exit(1); + } + + try { + count = Integer.parseInt(args[1]); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + GumballMachine gumballMachine = new GumballMachine(args[0], count); + + GumballMonitor monitor = new GumballMonitor(gumballMachine); + + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + monitor.report(); + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMonitor.java b/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMonitor.java new file mode 100644 index 00000000..11ce6331 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/GumballMonitor.java @@ -0,0 +1,15 @@ +package headfirst.proxy.gumballmonitor; + +public class GumballMonitor { + GumballMachine machine; + + public GumballMonitor(GumballMachine machine) { + this.machine = machine; + } + + public void report() { + System.out.println("Gumball Machine: " + machine.getLocation()); + System.out.println("Current inventory: " + machine.getCount() + " gumballs"); + System.out.println("Current state: " + machine.getState()); + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/HasQuarterState.java b/HF_DP/src/headfirst/proxy/gumballmonitor/HasQuarterState.java new file mode 100644 index 00000000..9b73214a --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/HasQuarterState.java @@ -0,0 +1,40 @@ +package headfirst.proxy.gumballmonitor; + + +import java.util.Random; + +public class HasQuarterState implements State { + Random randomWinner = new Random(System.currentTimeMillis()); + GumballMachine gumballMachine; + + public HasQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert another quarter"); + } + + public void ejectQuarter() { + System.out.println("Quarter returned"); + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + public void turnCrank() { + System.out.println("You turned..."); + int winner = randomWinner.nextInt(10); + if (winner == 0) { + gumballMachine.setState(gumballMachine.getWinnerState()); + } else { + gumballMachine.setState(gumballMachine.getSoldState()); + } + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "waiting for turn of crank"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/NoQuarterState.java b/HF_DP/src/headfirst/proxy/gumballmonitor/NoQuarterState.java new file mode 100644 index 00000000..8b6777f8 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/NoQuarterState.java @@ -0,0 +1,30 @@ +package headfirst.proxy.gumballmonitor; + +public class NoQuarterState implements State { + GumballMachine gumballMachine; + + public NoQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You inserted a quarter"); + gumballMachine.setState(gumballMachine.getHasQuarterState()); + } + + public void ejectQuarter() { + System.out.println("You haven't inserted a quarter"); + } + + public void turnCrank() { + System.out.println("You turned, but there's no quarter"); + } + + public void dispense() { + System.out.println("You need to pay first"); + } + + public String toString() { + return "waiting for quarter"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/SoldOutState.java b/HF_DP/src/headfirst/proxy/gumballmonitor/SoldOutState.java new file mode 100644 index 00000000..0d2b954c --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/SoldOutState.java @@ -0,0 +1,29 @@ +package headfirst.proxy.gumballmonitor; + +public class SoldOutState implements State { + GumballMachine gumballMachine; + + public SoldOutState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert a quarter, the machine is sold out"); + } + + public void ejectQuarter() { + System.out.println("You can't eject, you haven't inserted a quarter yet"); + } + + public void turnCrank() { + System.out.println("You turned, but there are no gumballs"); + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "sold out"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/SoldState.java b/HF_DP/src/headfirst/proxy/gumballmonitor/SoldState.java new file mode 100644 index 00000000..8bae7a6a --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/SoldState.java @@ -0,0 +1,39 @@ +package headfirst.proxy.gumballmonitor; + +public class SoldState implements State { + GumballMachine gumballMachine; + + public SoldState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("Please wait, we're already giving you a gumball"); + } + + public void ejectQuarter() { + System.out.println("Sorry, you already turned the crank"); + } + + public void turnCrank() { + System.out.println("Turning twice doesn't get you another gumball!"); + } + + public void dispense() { + gumballMachine.releaseBall(); + try { + if (gumballMachine.getCount() > 0) { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } else { + System.out.println("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String toString() { + return "dispensing a gumball"; + } +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/State.java b/HF_DP/src/headfirst/proxy/gumballmonitor/State.java new file mode 100644 index 00000000..6e9c805c --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/State.java @@ -0,0 +1,11 @@ +package headfirst.proxy.gumballmonitor; + +import java.io.*; + +public interface State extends Serializable { + + public void insertQuarter(); + public void ejectQuarter(); + public void turnCrank(); + public void dispense(); +} diff --git a/HF_DP/src/headfirst/proxy/gumballmonitor/WinnerState.java b/HF_DP/src/headfirst/proxy/gumballmonitor/WinnerState.java new file mode 100644 index 00000000..142863ad --- /dev/null +++ b/HF_DP/src/headfirst/proxy/gumballmonitor/WinnerState.java @@ -0,0 +1,45 @@ +package headfirst.proxy.gumballmonitor; + +public class WinnerState implements State { + GumballMachine gumballMachine; + + public WinnerState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("Please wait, we're already giving you a Gumball"); + } + + public void ejectQuarter() { + System.out.println("Please wait, we're already giving you a Gumball"); + } + + public void turnCrank() { + System.out.println("Turning again doesn't get you another gumball!"); + } + + public void dispense() { + System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter"); + try { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() == 0) { + gumballMachine.setState(gumballMachine.getSoldOutState()); + } else { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } else { + System.out.println("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String toString() { + return "despensing two gumballs for your quarter, because YOU'RE A WINNER!"; + } +} diff --git a/HF_DP/src/headfirst/proxy/javaproxy/MatchMakingTestDrive.java b/HF_DP/src/headfirst/proxy/javaproxy/MatchMakingTestDrive.java new file mode 100644 index 00000000..ec970a80 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/javaproxy/MatchMakingTestDrive.java @@ -0,0 +1,76 @@ +package headfirst.proxy.javaproxy; + +import java.lang.reflect.*; +import java.util.*; + +public class MatchMakingTestDrive { + Hashtable datingDB = new Hashtable(); + + public static void main(String[] args) { + MatchMakingTestDrive test = new MatchMakingTestDrive(); + test.drive(); + } + + public MatchMakingTestDrive() { + initializeDatabase(); + } + + public void drive() { + PersonBean joe = getPersonFromDatabase("Joe Javabean"); + PersonBean ownerProxy = getOwnerProxy(joe); + System.out.println("Name is " + ownerProxy.getName()); + ownerProxy.setInterests("bowling, Go"); + System.out.println("Interests set from owner proxy"); + try { + ownerProxy.setHotOrNotRating(10); + } catch (Exception e) { + System.out.println("Can't set rating from owner proxy"); + } + System.out.println("Rating is " + ownerProxy.getHotOrNotRating()); + + PersonBean nonOwnerProxy = getNonOwnerProxy(joe); + System.out.println("Name is " + nonOwnerProxy.getName()); + try { + nonOwnerProxy.setInterests("bowling, Go"); + } catch (Exception e) { + System.out.println("Can't set interests from non owner proxy"); + } + nonOwnerProxy.setHotOrNotRating(3); + System.out.println("Rating set from non owner proxy"); + System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating()); + } + + PersonBean getOwnerProxy(PersonBean person) { + + return (PersonBean) Proxy.newProxyInstance( + person.getClass().getClassLoader(), + person.getClass().getInterfaces(), + new OwnerInvocationHandler(person)); + } + + PersonBean getNonOwnerProxy(PersonBean person) { + + return (PersonBean) Proxy.newProxyInstance( + person.getClass().getClassLoader(), + person.getClass().getInterfaces(), + new NonOwnerInvocationHandler(person)); + } + + PersonBean getPersonFromDatabase(String name) { + return (PersonBean)datingDB.get(name); + } + + void initializeDatabase() { + PersonBean joe = new PersonBeanImpl(); + joe.setName("Joe Javabean"); + joe.setInterests("cars, computers, music"); + joe.setHotOrNotRating(7); + datingDB.put(joe.getName(), joe); + + PersonBean kelly = new PersonBeanImpl(); + kelly.setName("Kelly Klosure"); + kelly.setInterests("ebay, movies, music"); + kelly.setHotOrNotRating(6); + datingDB.put(kelly.getName(), kelly); + } +} diff --git a/HF_DP/src/headfirst/proxy/javaproxy/NonOwnerInvocationHandler.java b/HF_DP/src/headfirst/proxy/javaproxy/NonOwnerInvocationHandler.java new file mode 100644 index 00000000..9d8bf3c0 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/javaproxy/NonOwnerInvocationHandler.java @@ -0,0 +1,28 @@ +package headfirst.proxy.javaproxy; + +import java.lang.reflect.*; + +public class NonOwnerInvocationHandler implements InvocationHandler { + PersonBean person; + + public NonOwnerInvocationHandler(PersonBean person) { + this.person = person; + } + + public Object invoke(Object proxy, Method method, Object[] args) + throws IllegalAccessException { + + try { + if (method.getName().startsWith("get")) { + return method.invoke(person, args); + } else if (method.getName().equals("setHotOrNotRating")) { + return method.invoke(person, args); + } else if (method.getName().startsWith("set")) { + throw new IllegalAccessException(); + } + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/HF_DP/src/headfirst/proxy/javaproxy/OwnerInvocationHandler.java b/HF_DP/src/headfirst/proxy/javaproxy/OwnerInvocationHandler.java new file mode 100644 index 00000000..37c8960c --- /dev/null +++ b/HF_DP/src/headfirst/proxy/javaproxy/OwnerInvocationHandler.java @@ -0,0 +1,28 @@ +package headfirst.proxy.javaproxy; + +import java.lang.reflect.*; + +public class OwnerInvocationHandler implements InvocationHandler { + PersonBean person; + + public OwnerInvocationHandler(PersonBean person) { + this.person = person; + } + + public Object invoke(Object proxy, Method method, Object[] args) + throws IllegalAccessException { + + try { + if (method.getName().startsWith("get")) { + return method.invoke(person, args); + } else if (method.getName().equals("setHotOrNotRating")) { + throw new IllegalAccessException(); + } else if (method.getName().startsWith("set")) { + return method.invoke(person, args); + } + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/HF_DP/src/headfirst/proxy/javaproxy/PersonBean.java b/HF_DP/src/headfirst/proxy/javaproxy/PersonBean.java new file mode 100644 index 00000000..44e3e210 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/javaproxy/PersonBean.java @@ -0,0 +1,15 @@ +package headfirst.proxy.javaproxy; + +public interface PersonBean { + + String getName(); + String getGender(); + String getInterests(); + int getHotOrNotRating(); + + void setName(String name); + void setGender(String gender); + void setInterests(String interests); + void setHotOrNotRating(int rating); + +} diff --git a/HF_DP/src/headfirst/proxy/javaproxy/PersonBeanImpl.java b/HF_DP/src/headfirst/proxy/javaproxy/PersonBeanImpl.java new file mode 100644 index 00000000..ad26a438 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/javaproxy/PersonBeanImpl.java @@ -0,0 +1,44 @@ +package headfirst.proxy.javaproxy; + +public class PersonBeanImpl implements PersonBean { + String name; + String gender; + String interests; + int rating; + int ratingCount = 0; + + public String getName() { + return name; + } + + public String getGender() { + return gender; + } + + public String getInterests() { + return interests; + } + + public int getHotOrNotRating() { + if (ratingCount == 0) return 0; + return (rating/ratingCount); + } + + + public void setName(String name) { + this.name = name; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public void setInterests(String interests) { + this.interests = interests; + } + + public void setHotOrNotRating(int rating) { + this.rating += rating; + ratingCount++; + } +} diff --git a/HF_DP/src/headfirst/proxy/virtualproxy/ImageComponent.java b/HF_DP/src/headfirst/proxy/virtualproxy/ImageComponent.java new file mode 100644 index 00000000..e4580e66 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/virtualproxy/ImageComponent.java @@ -0,0 +1,25 @@ +package headfirst.proxy.virtualproxy; + +import java.awt.*; +import javax.swing.*; + +class ImageComponent extends JComponent { + private Icon icon; + + public ImageComponent(Icon icon) { + this.icon = icon; + } + + public void setIcon(Icon icon) { + this.icon = icon; + } + + public void paintComponent(Graphics g) { + super.paintComponent(g); + int w = icon.getIconWidth(); + int h = icon.getIconHeight(); + int x = (800 - w)/2; + int y = (600 - h)/2; + icon.paintIcon(this, g, x, y); + } +} diff --git a/HF_DP/src/headfirst/proxy/virtualproxy/ImageProxy.java b/HF_DP/src/headfirst/proxy/virtualproxy/ImageProxy.java new file mode 100644 index 00000000..4ffd6cc1 --- /dev/null +++ b/HF_DP/src/headfirst/proxy/virtualproxy/ImageProxy.java @@ -0,0 +1,54 @@ +package headfirst.proxy.virtualproxy; + +import java.net.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +class ImageProxy implements Icon { + ImageIcon imageIcon; + URL imageURL; + Thread retrievalThread; + boolean retrieving = false; + + public ImageProxy(URL url) { imageURL = url; } + + public int getIconWidth() { + if (imageIcon != null) { + return imageIcon.getIconWidth(); + } else { + return 800; + } + } + + public int getIconHeight() { + if (imageIcon != null) { + return imageIcon.getIconHeight(); + } else { + return 600; + } + } + + public void paintIcon(final Component c, Graphics g, int x, int y) { + if (imageIcon != null) { + imageIcon.paintIcon(c, g, x, y); + } else { + g.drawString("Loading CD cover, please wait...", x+300, y+190); + if (!retrieving) { + retrieving = true; + + retrievalThread = new Thread(new Runnable() { + public void run() { + try { + imageIcon = new ImageIcon(imageURL, "CD Cover"); + c.repaint(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + retrievalThread.start(); + } + } + } +} diff --git a/HF_DP/src/headfirst/proxy/virtualproxy/ImageProxyTestDrive.java b/HF_DP/src/headfirst/proxy/virtualproxy/ImageProxyTestDrive.java new file mode 100644 index 00000000..63df45af --- /dev/null +++ b/HF_DP/src/headfirst/proxy/virtualproxy/ImageProxyTestDrive.java @@ -0,0 +1,66 @@ +package headfirst.proxy.virtualproxy; + +import java.net.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.*; + +public class ImageProxyTestDrive { + ImageComponent imageComponent; + JFrame frame = new JFrame("CD Cover Viewer"); + JMenuBar menuBar; + JMenu menu; + Hashtable cds = new Hashtable(); + + public static void main (String[] args) throws Exception { + ImageProxyTestDrive testDrive = new ImageProxyTestDrive(); + } + + public ImageProxyTestDrive() throws Exception{ + cds.put("Ambient: Music for Airports","http://images.amazon.com/images/P/B000003S2K.01.LZZZZZZZ.jpg"); + cds.put("Buddha Bar","http://images.amazon.com/images/P/B00009XBYK.01.LZZZZZZZ.jpg"); + cds.put("Ima","http://images.amazon.com/images/P/B000005IRM.01.LZZZZZZZ.jpg"); + cds.put("Karma","http://images.amazon.com/images/P/B000005DCB.01.LZZZZZZZ.gif"); + cds.put("MCMXC A.D.","http://images.amazon.com/images/P/B000002URV.01.LZZZZZZZ.jpg"); + cds.put("Northern Exposure","http://images.amazon.com/images/P/B000003SFN.01.LZZZZZZZ.jpg"); + cds.put("Selected Ambient Works, Vol. 2","http://images.amazon.com/images/P/B000002MNZ.01.LZZZZZZZ.jpg"); + + URL initialURL = new URL((String)cds.get("Selected Ambient Works, Vol. 2")); + menuBar = new JMenuBar(); + menu = new JMenu("Favorite CDs"); + menuBar.add(menu); + frame.setJMenuBar(menuBar); + + for(Enumeration e = cds.keys(); e.hasMoreElements();) { + String name = (String)e.nextElement(); + JMenuItem menuItem = new JMenuItem(name); + menu.add(menuItem); + menuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + imageComponent.setIcon(new ImageProxy(getCDUrl(event.getActionCommand()))); + frame.repaint(); + } + }); + } + + // set up frame and menus + + Icon icon = new ImageProxy(initialURL); + imageComponent = new ImageComponent(icon); + frame.getContentPane().add(imageComponent); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(800,600); + frame.setVisible(true); + + } + + URL getCDUrl(String name) { + try { + return new URL((String)cds.get(name)); + } catch (MalformedURLException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/HF_DP/src/headfirst/singleton/chocolate/ChocolateBoiler.java b/HF_DP/src/headfirst/singleton/chocolate/ChocolateBoiler.java new file mode 100644 index 00000000..7f910a70 --- /dev/null +++ b/HF_DP/src/headfirst/singleton/chocolate/ChocolateBoiler.java @@ -0,0 +1,51 @@ +package headfirst.singleton.chocolate; + +public class ChocolateBoiler { + private boolean empty; + private boolean boiled; + private static ChocolateBoiler uniqueInstance; + + private ChocolateBoiler() { + empty = true; + boiled = false; + } + + public static ChocolateBoiler getInstance() { + if (uniqueInstance == null) { + System.out.println("Creating unique instance of Chocolate Boiler"); + uniqueInstance = new ChocolateBoiler(); + } + System.out.println("Returning instance of Chocolate Boiler"); + return uniqueInstance; + } + + public void fill() { + if (isEmpty()) { + empty = false; + boiled = false; + // fill the boiler with a milk/chocolate mixture + } + } + + public void drain() { + if (!isEmpty() && isBoiled()) { + // drain the boiled milk and chocolate + empty = true; + } + } + + public void boil() { + if (!isEmpty() && !isBoiled()) { + // bring the contents to a boil + boiled = true; + } + } + + public boolean isEmpty() { + return empty; + } + + public boolean isBoiled() { + return boiled; + } +} diff --git a/HF_DP/src/headfirst/singleton/chocolate/ChocolateController.java b/HF_DP/src/headfirst/singleton/chocolate/ChocolateController.java new file mode 100644 index 00000000..ca747497 --- /dev/null +++ b/HF_DP/src/headfirst/singleton/chocolate/ChocolateController.java @@ -0,0 +1,13 @@ +package headfirst.singleton.chocolate; + +public class ChocolateController { + public static void main(String args[]) { + ChocolateBoiler boiler = ChocolateBoiler.getInstance(); + boiler.fill(); + boiler.boil(); + boiler.drain(); + + // will return the existing instance + ChocolateBoiler boiler2 = ChocolateBoiler.getInstance(); + } +} diff --git a/HF_DP/src/headfirst/singleton/classic/Singleton.java b/HF_DP/src/headfirst/singleton/classic/Singleton.java new file mode 100644 index 00000000..5af3ec43 --- /dev/null +++ b/HF_DP/src/headfirst/singleton/classic/Singleton.java @@ -0,0 +1,20 @@ +package headfirst.singleton.classic; + +// NOTE: This is not thread safe! + +public class Singleton { + private static Singleton uniqueInstance; + + // other useful instance variables here + + private Singleton() {} + + public static Singleton getInstance() { + if (uniqueInstance == null) { + uniqueInstance = new Singleton(); + } + return uniqueInstance; + } + + // other useful methods here +} diff --git a/HF_DP/src/headfirst/singleton/dcl/Singleton.java b/HF_DP/src/headfirst/singleton/dcl/Singleton.java new file mode 100644 index 00000000..2a0aba1d --- /dev/null +++ b/HF_DP/src/headfirst/singleton/dcl/Singleton.java @@ -0,0 +1,23 @@ +package headfirst.singleton.dcl; + +// +// Danger! This implementation of Singleton not +// guaranteed to work prior to Java 5 +// + +public class Singleton { + private volatile static Singleton uniqueInstance; + + private Singleton() {} + + public static Singleton getInstance() { + if (uniqueInstance == null) { + synchronized (Singleton.class) { + if (uniqueInstance == null) { + uniqueInstance = new Singleton(); + } + } + } + return uniqueInstance; + } +} diff --git a/HF_DP/src/headfirst/singleton/dcl/SingletonClient.java b/HF_DP/src/headfirst/singleton/dcl/SingletonClient.java new file mode 100644 index 00000000..0bba206e --- /dev/null +++ b/HF_DP/src/headfirst/singleton/dcl/SingletonClient.java @@ -0,0 +1,7 @@ +package headfirst.singleton.dcl; + +public class SingletonClient { + public static void main(String[] args) { + Singleton singleton = Singleton.getInstance(); + } +} diff --git a/HF_DP/src/headfirst/singleton/stat/Singleton.java b/HF_DP/src/headfirst/singleton/stat/Singleton.java new file mode 100644 index 00000000..c4861faa --- /dev/null +++ b/HF_DP/src/headfirst/singleton/stat/Singleton.java @@ -0,0 +1,11 @@ +package headfirst.singleton.stat; + +public class Singleton { + private static Singleton uniqueInstance = new Singleton(); + + private Singleton() {} + + public static Singleton getInstance() { + return uniqueInstance; + } +} diff --git a/HF_DP/src/headfirst/singleton/stat/SingletonClient.java b/HF_DP/src/headfirst/singleton/stat/SingletonClient.java new file mode 100644 index 00000000..cb2c76da --- /dev/null +++ b/HF_DP/src/headfirst/singleton/stat/SingletonClient.java @@ -0,0 +1,7 @@ +package headfirst.singleton.stat; + +public class SingletonClient { + public static void main(String[] args) { + Singleton singleton = Singleton.getInstance(); + } +} diff --git a/HF_DP/src/headfirst/singleton/subclass/CoolerSingleton.java b/HF_DP/src/headfirst/singleton/subclass/CoolerSingleton.java new file mode 100644 index 00000000..a8ac5f55 --- /dev/null +++ b/HF_DP/src/headfirst/singleton/subclass/CoolerSingleton.java @@ -0,0 +1,12 @@ +package headfirst.singleton.subclass; + +public class CoolerSingleton extends Singleton { + // useful instance variables here + protected static Singleton uniqueInstance; + + private CoolerSingleton() { + super(); + } + + // useful methods here +} diff --git a/HF_DP/src/headfirst/singleton/subclass/HotterSingleton.java b/HF_DP/src/headfirst/singleton/subclass/HotterSingleton.java new file mode 100644 index 00000000..c25efb99 --- /dev/null +++ b/HF_DP/src/headfirst/singleton/subclass/HotterSingleton.java @@ -0,0 +1,11 @@ +package headfirst.singleton.subclass; + +public class HotterSingleton extends Singleton { + // useful instance variables here + + private HotterSingleton() { + super(); + } + + // useful methods here +} diff --git a/HF_DP/src/headfirst/singleton/subclass/Singleton.java b/HF_DP/src/headfirst/singleton/subclass/Singleton.java new file mode 100644 index 00000000..7adce89b --- /dev/null +++ b/HF_DP/src/headfirst/singleton/subclass/Singleton.java @@ -0,0 +1,18 @@ +package headfirst.singleton.subclass; + +public class Singleton { + protected static Singleton uniqueInstance; + + // other useful instance variables here + + protected Singleton() {} + + public static synchronized Singleton getInstance() { + if (uniqueInstance == null) { + uniqueInstance = new Singleton(); + } + return uniqueInstance; + } + + // other useful methods here +} diff --git a/HF_DP/src/headfirst/singleton/subclass/SingletonTestDrive.java b/HF_DP/src/headfirst/singleton/subclass/SingletonTestDrive.java new file mode 100644 index 00000000..551cd035 --- /dev/null +++ b/HF_DP/src/headfirst/singleton/subclass/SingletonTestDrive.java @@ -0,0 +1,10 @@ +package headfirst.singleton.subclass; + +public class SingletonTestDrive { + public static void main(String[] args) { + Singleton foo = CoolerSingleton.getInstance(); + Singleton bar = HotterSingleton.getInstance(); + System.out.println(foo); + System.out.println(bar); + } +} diff --git a/HF_DP/src/headfirst/singleton/threadsafe/Singleton.java b/HF_DP/src/headfirst/singleton/threadsafe/Singleton.java new file mode 100644 index 00000000..687b65be --- /dev/null +++ b/HF_DP/src/headfirst/singleton/threadsafe/Singleton.java @@ -0,0 +1,18 @@ +package headfirst.singleton.threadsafe; + +public class Singleton { + private static Singleton uniqueInstance; + + // other useful instance variables here + + private Singleton() {} + + public static synchronized Singleton getInstance() { + if (uniqueInstance == null) { + uniqueInstance = new Singleton(); + } + return uniqueInstance; + } + + // other useful methods here +} diff --git a/HF_DP/src/headfirst/state/gumball/GumballMachine.java b/HF_DP/src/headfirst/state/gumball/GumballMachine.java new file mode 100644 index 00000000..6c28ef74 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumball/GumballMachine.java @@ -0,0 +1,110 @@ +package headfirst.state.gumball; + +public class GumballMachine { + + final static int SOLD_OUT = 0; + final static int NO_QUARTER = 1; + final static int HAS_QUARTER = 2; + final static int SOLD = 3; + + int state = SOLD_OUT; + int count = 0; + + public GumballMachine(int count) { + this.count = count; + if (count > 0) { + state = NO_QUARTER; + } + } + + public void insertQuarter() { + if (state == HAS_QUARTER) { + System.out.println("You can't insert another quarter"); + } else if (state == NO_QUARTER) { + state = HAS_QUARTER; + System.out.println("You inserted a quarter"); + } else if (state == SOLD_OUT) { + System.out.println("You can't insert a quarter, the machine is sold out"); + } else if (state == SOLD) { + System.out.println("Please wait, we're already giving you a gumball"); + } + } + + public void ejectQuarter() { + if (state == HAS_QUARTER) { + System.out.println("Quarter returned"); + state = NO_QUARTER; + } else if (state == NO_QUARTER) { + System.out.println("You haven't inserted a quarter"); + } else if (state == SOLD) { + System.out.println("Sorry, you already turned the crank"); + } else if (state == SOLD_OUT) { + System.out.println("You can't eject, you haven't inserted a quarter yet"); + } + } + + + + + public void turnCrank() { + if (state == SOLD) { + System.out.println("Turning twice doesn't get you another gumball!"); + } else if (state == NO_QUARTER) { + System.out.println("You turned but there's no quarter"); + } else if (state == SOLD_OUT) { + System.out.println("You turned, but there are no gumballs"); + } else if (state == HAS_QUARTER) { + System.out.println("You turned..."); + state = SOLD; + dispense(); + } + } + + public void dispense() { + if (state == SOLD) { + System.out.println("A gumball comes rolling out the slot"); + count = count - 1; + if (count == 0) { + System.out.println("Oops, out of gumballs!"); + state = SOLD_OUT; + } else { + state = NO_QUARTER; + } + } else if (state == NO_QUARTER) { + System.out.println("You need to pay first"); + } else if (state == SOLD_OUT) { + System.out.println("No gumball dispensed"); + } else if (state == HAS_QUARTER) { + System.out.println("No gumball dispensed"); + } + } + + public void refill(int numGumBalls) { + this.count = numGumBalls; + state = NO_QUARTER; + } + + public String toString() { + StringBuffer result = new StringBuffer(); + result.append("\nMighty Gumball, Inc."); + result.append("\nJava-enabled Standing Gumball Model #2004\n"); + result.append("Inventory: " + count + " gumball"); + if (count != 1) { + result.append("s"); + } + result.append("\nMachine is "); + if (state == SOLD_OUT) { + result.append("sold out"); + } else if (state == NO_QUARTER) { + result.append("waiting for quarter"); + } else if (state == HAS_QUARTER) { + result.append("waiting for turn of crank"); + } else if (state == SOLD) { + result.append("delivering a gumball"); + } + result.append("\n"); + return result.toString(); + } +} + + diff --git a/HF_DP/src/headfirst/state/gumball/GumballMachineTestDrive.java b/HF_DP/src/headfirst/state/gumball/GumballMachineTestDrive.java new file mode 100644 index 00000000..a852d2e3 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumball/GumballMachineTestDrive.java @@ -0,0 +1,39 @@ +package headfirst.state.gumball; + +public class GumballMachineTestDrive { + + public static void main(String[] args) { + GumballMachine gumballMachine = new GumballMachine(5); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.ejectQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.ejectQuarter(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + } +} diff --git a/HF_DP/src/headfirst/state/gumballstate/GumballMachine.java b/HF_DP/src/headfirst/state/gumballstate/GumballMachine.java new file mode 100644 index 00000000..e734daae --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstate/GumballMachine.java @@ -0,0 +1,90 @@ +package headfirst.state.gumballstate; + +public class GumballMachine { + + State soldOutState; + State noQuarterState; + State hasQuarterState; + State soldState; + + State state = soldOutState; + int count = 0; + + public GumballMachine(int numberGumballs) { + soldOutState = new SoldOutState(this); + noQuarterState = new NoQuarterState(this); + hasQuarterState = new HasQuarterState(this); + soldState = new SoldState(this); + + this.count = numberGumballs; + if (numberGumballs > 0) { + state = noQuarterState; + } + } + + public void insertQuarter() { + state.insertQuarter(); + } + + public void ejectQuarter() { + state.ejectQuarter(); + } + + public void turnCrank() { + state.turnCrank(); + state.dispense(); + } + + void setState(State state) { + this.state = state; + } + + void releaseBall() { + System.out.println("A gumball comes rolling out the slot..."); + if (count != 0) { + count = count - 1; + } + } + + int getCount() { + return count; + } + + void refill(int count) { + this.count = count; + state = noQuarterState; + } + + public State getState() { + return state; + } + + public State getSoldOutState() { + return soldOutState; + } + + public State getNoQuarterState() { + return noQuarterState; + } + + public State getHasQuarterState() { + return hasQuarterState; + } + + public State getSoldState() { + return soldState; + } + + public String toString() { + StringBuffer result = new StringBuffer(); + result.append("\nMighty Gumball, Inc."); + result.append("\nJava-enabled Standing Gumball Model #2004"); + result.append("\nInventory: " + count + " gumball"); + if (count != 1) { + result.append("s"); + } + result.append("\n"); + result.append("Machine is " + state + "\n"); + return result.toString(); + } +} diff --git a/HF_DP/src/headfirst/state/gumballstate/GumballMachineTestDrive.java b/HF_DP/src/headfirst/state/gumballstate/GumballMachineTestDrive.java new file mode 100644 index 00000000..bc6d950d --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstate/GumballMachineTestDrive.java @@ -0,0 +1,22 @@ +package headfirst.state.gumballstate; + +public class GumballMachineTestDrive { + + public static void main(String[] args) { + GumballMachine gumballMachine = new GumballMachine(5); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + } +} diff --git a/HF_DP/src/headfirst/state/gumballstate/HasQuarterState.java b/HF_DP/src/headfirst/state/gumballstate/HasQuarterState.java new file mode 100644 index 00000000..71383182 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstate/HasQuarterState.java @@ -0,0 +1,33 @@ +package headfirst.state.gumballstate; + +import java.util.Random; + +public class HasQuarterState implements State { + GumballMachine gumballMachine; + + public HasQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert another quarter"); + } + + public void ejectQuarter() { + System.out.println("Quarter returned"); + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + public void turnCrank() { + System.out.println("You turned..."); + gumballMachine.setState(gumballMachine.getSoldState()); + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "waiting for turn of crank"; + } +} diff --git a/HF_DP/src/headfirst/state/gumballstate/NoQuarterState.java b/HF_DP/src/headfirst/state/gumballstate/NoQuarterState.java new file mode 100644 index 00000000..8ac9a368 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstate/NoQuarterState.java @@ -0,0 +1,30 @@ +package headfirst.state.gumballstate; + +public class NoQuarterState implements State { + GumballMachine gumballMachine; + + public NoQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You inserted a quarter"); + gumballMachine.setState(gumballMachine.getHasQuarterState()); + } + + public void ejectQuarter() { + System.out.println("You haven't inserted a quarter"); + } + + public void turnCrank() { + System.out.println("You turned, but there's no quarter"); + } + + public void dispense() { + System.out.println("You need to pay first"); + } + + public String toString() { + return "waiting for quarter"; + } +} diff --git a/HF_DP/src/headfirst/state/gumballstate/SoldOutState.java b/HF_DP/src/headfirst/state/gumballstate/SoldOutState.java new file mode 100644 index 00000000..48ec5318 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstate/SoldOutState.java @@ -0,0 +1,29 @@ +package headfirst.state.gumballstate; + +public class SoldOutState implements State { + GumballMachine gumballMachine; + + public SoldOutState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert a quarter, the machine is sold out"); + } + + public void ejectQuarter() { + System.out.println("You can't eject, you haven't inserted a quarter yet"); + } + + public void turnCrank() { + System.out.println("You turned, but there are no gumballs"); + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "sold out"; + } +} diff --git a/HF_DP/src/headfirst/state/gumballstate/SoldState.java b/HF_DP/src/headfirst/state/gumballstate/SoldState.java new file mode 100644 index 00000000..df0b3168 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstate/SoldState.java @@ -0,0 +1,38 @@ +package headfirst.state.gumballstate; + +public class SoldState implements State { + + GumballMachine gumballMachine; + + public SoldState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("Please wait, we're already giving you a gumball"); + } + + public void ejectQuarter() { + System.out.println("Sorry, you already turned the crank"); + } + + public void turnCrank() { + System.out.println("Turning twice doesn't get you another gumball!"); + } + + public void dispense() { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } else { + System.out.println("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + + public String toString() { + return "dispensing a gumball"; + } +} + + diff --git a/HF_DP/src/headfirst/state/gumballstate/State.java b/HF_DP/src/headfirst/state/gumballstate/State.java new file mode 100644 index 00000000..bce5ad21 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstate/State.java @@ -0,0 +1,9 @@ +package headfirst.state.gumballstate; + +public interface State { + + public void insertQuarter(); + public void ejectQuarter(); + public void turnCrank(); + public void dispense(); +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/GumballMachine.java b/HF_DP/src/headfirst/state/gumballstatewinner/GumballMachine.java new file mode 100644 index 00000000..e7e2c62c --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/GumballMachine.java @@ -0,0 +1,96 @@ +package headfirst.state.gumballstatewinner; + +public class GumballMachine { + + State soldOutState; + State noQuarterState; + State hasQuarterState; + State soldState; + State winnerState; + + State state = soldOutState; + int count = 0; + + public GumballMachine(int numberGumballs) { + soldOutState = new SoldOutState(this); + noQuarterState = new NoQuarterState(this); + hasQuarterState = new HasQuarterState(this); + soldState = new SoldState(this); + winnerState = new WinnerState(this); + + this.count = numberGumballs; + if (numberGumballs > 0) { + state = noQuarterState; + } + } + + public void insertQuarter() { + state.insertQuarter(); + } + + public void ejectQuarter() { + state.ejectQuarter(); + } + + public void turnCrank() { + state.turnCrank(); + state.dispense(); + } + + void setState(State state) { + this.state = state; + } + + void releaseBall() { + System.out.println("A gumball comes rolling out the slot..."); + if (count != 0) { + count = count - 1; + } + } + + int getCount() { + return count; + } + + void refill(int count) { + this.count = count; + state = noQuarterState; + } + + public State getState() { + return state; + } + + public State getSoldOutState() { + return soldOutState; + } + + public State getNoQuarterState() { + return noQuarterState; + } + + public State getHasQuarterState() { + return hasQuarterState; + } + + public State getSoldState() { + return soldState; + } + + public State getWinnerState() { + return winnerState; + } + + public String toString() { + StringBuffer result = new StringBuffer(); + result.append("\nMighty Gumball, Inc."); + result.append("\nJava-enabled Standing Gumball Model #2004"); + result.append("\nInventory: " + count + " gumball"); + if (count != 1) { + result.append("s"); + } + result.append("\n"); + result.append("Machine is " + state + "\n"); + return result.toString(); + } +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/GumballMachineTestDrive.java b/HF_DP/src/headfirst/state/gumballstatewinner/GumballMachineTestDrive.java new file mode 100644 index 00000000..e51f3f93 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/GumballMachineTestDrive.java @@ -0,0 +1,46 @@ +package headfirst.state.gumballstatewinner; + +public class GumballMachineTestDrive { + + public static void main(String[] args) { + GumballMachine gumballMachine = + new GumballMachine(10); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + System.out.println(gumballMachine); + } +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/HasQuarterState.java b/HF_DP/src/headfirst/state/gumballstatewinner/HasQuarterState.java new file mode 100644 index 00000000..6c3dacdd --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/HasQuarterState.java @@ -0,0 +1,39 @@ +package headfirst.state.gumballstatewinner; + +import java.util.Random; + +public class HasQuarterState implements State { + Random randomWinner = new Random(System.currentTimeMillis()); + GumballMachine gumballMachine; + + public HasQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert another quarter"); + } + + public void ejectQuarter() { + System.out.println("Quarter returned"); + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + public void turnCrank() { + System.out.println("You turned..."); + int winner = randomWinner.nextInt(10); + if ((winner == 0) && (gumballMachine.getCount() > 1)) { + gumballMachine.setState(gumballMachine.getWinnerState()); + } else { + gumballMachine.setState(gumballMachine.getSoldState()); + } + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "waiting for turn of crank"; + } +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/NoQuarterState.java b/HF_DP/src/headfirst/state/gumballstatewinner/NoQuarterState.java new file mode 100644 index 00000000..3e3c9c72 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/NoQuarterState.java @@ -0,0 +1,30 @@ +package headfirst.state.gumballstatewinner; + +public class NoQuarterState implements State { + GumballMachine gumballMachine; + + public NoQuarterState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You inserted a quarter"); + gumballMachine.setState(gumballMachine.getHasQuarterState()); + } + + public void ejectQuarter() { + System.out.println("You haven't inserted a quarter"); + } + + public void turnCrank() { + System.out.println("You turned, but there's no quarter"); + } + + public void dispense() { + System.out.println("You need to pay first"); + } + + public String toString() { + return "waiting for quarter"; + } +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/SoldOutState.java b/HF_DP/src/headfirst/state/gumballstatewinner/SoldOutState.java new file mode 100644 index 00000000..dcb043bc --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/SoldOutState.java @@ -0,0 +1,29 @@ +package headfirst.state.gumballstatewinner; + +public class SoldOutState implements State { + GumballMachine gumballMachine; + + public SoldOutState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("You can't insert a quarter, the machine is sold out"); + } + + public void ejectQuarter() { + System.out.println("You can't eject, you haven't inserted a quarter yet"); + } + + public void turnCrank() { + System.out.println("You turned, but there are no gumballs"); + } + + public void dispense() { + System.out.println("No gumball dispensed"); + } + + public String toString() { + return "sold out"; + } +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/SoldState.java b/HF_DP/src/headfirst/state/gumballstatewinner/SoldState.java new file mode 100644 index 00000000..d1bb3680 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/SoldState.java @@ -0,0 +1,35 @@ +package headfirst.state.gumballstatewinner; + +public class SoldState implements State { + GumballMachine gumballMachine; + + public SoldState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("Please wait, we're already giving you a gumball"); + } + + public void ejectQuarter() { + System.out.println("Sorry, you already turned the crank"); + } + + public void turnCrank() { + System.out.println("Turning twice doesn't get you another gumball!"); + } + + public void dispense() { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } else { + System.out.println("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + + public String toString() { + return "dispensing a gumball"; + } +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/State.java b/HF_DP/src/headfirst/state/gumballstatewinner/State.java new file mode 100644 index 00000000..ea9ff55b --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/State.java @@ -0,0 +1,9 @@ +package headfirst.state.gumballstatewinner; + +public interface State { + + public void insertQuarter(); + public void ejectQuarter(); + public void turnCrank(); + public void dispense(); +} diff --git a/HF_DP/src/headfirst/state/gumballstatewinner/WinnerState.java b/HF_DP/src/headfirst/state/gumballstatewinner/WinnerState.java new file mode 100644 index 00000000..27d07196 --- /dev/null +++ b/HF_DP/src/headfirst/state/gumballstatewinner/WinnerState.java @@ -0,0 +1,41 @@ +package headfirst.state.gumballstatewinner; + +public class WinnerState implements State { + GumballMachine gumballMachine; + + public WinnerState(GumballMachine gumballMachine) { + this.gumballMachine = gumballMachine; + } + + public void insertQuarter() { + System.out.println("Please wait, we're already giving you a Gumball"); + } + + public void ejectQuarter() { + System.out.println("Please wait, we're already giving you a Gumball"); + } + + public void turnCrank() { + System.out.println("Turning again doesn't get you another gumball!"); + } + + public void dispense() { + System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter"); + gumballMachine.releaseBall(); + if (gumballMachine.getCount() == 0) { + gumballMachine.setState(gumballMachine.getSoldOutState()); + } else { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } else { + System.out.println("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + } + + public String toString() { + return "despensing two gumballs for your quarter, because YOU'RE A WINNER!"; + } +} diff --git a/HF_DP/src/headfirst/strategy/DecoyDuck.java b/HF_DP/src/headfirst/strategy/DecoyDuck.java new file mode 100644 index 00000000..8d7d629d --- /dev/null +++ b/HF_DP/src/headfirst/strategy/DecoyDuck.java @@ -0,0 +1,11 @@ +package headfirst.strategy; + +public class DecoyDuck extends Duck { + public DecoyDuck() { + setFlyBehavior(new FlyNoWay()); + setQuackBehavior(new MuteQuack()); + } + public void display() { + System.out.println("I'm a duck Decoy"); + } +} diff --git a/HF_DP/src/headfirst/strategy/Duck.java b/HF_DP/src/headfirst/strategy/Duck.java new file mode 100644 index 00000000..837a369b --- /dev/null +++ b/HF_DP/src/headfirst/strategy/Duck.java @@ -0,0 +1,31 @@ +package headfirst.strategy; + +public abstract class Duck { + FlyBehavior flyBehavior; + QuackBehavior quackBehavior; + + public Duck() { + } + + public void setFlyBehavior (FlyBehavior fb) { + flyBehavior = fb; + } + + public void setQuackBehavior(QuackBehavior qb) { + quackBehavior = qb; + } + + abstract void display(); + + public void performFly() { + flyBehavior.fly(); + } + + public void performQuack() { + quackBehavior.quack(); + } + + public void swim() { + System.out.println("All ducks float, even decoys!"); + } +} diff --git a/HF_DP/src/headfirst/strategy/FakeQuack.java b/HF_DP/src/headfirst/strategy/FakeQuack.java new file mode 100644 index 00000000..9106b73d --- /dev/null +++ b/HF_DP/src/headfirst/strategy/FakeQuack.java @@ -0,0 +1,7 @@ +package headfirst.strategy; + +public class FakeQuack implements QuackBehavior { + public void quack() { + System.out.println("Qwak"); + } +} diff --git a/HF_DP/src/headfirst/strategy/FlyBehavior.java b/HF_DP/src/headfirst/strategy/FlyBehavior.java new file mode 100644 index 00000000..cc7c6eed --- /dev/null +++ b/HF_DP/src/headfirst/strategy/FlyBehavior.java @@ -0,0 +1,5 @@ +package headfirst.strategy; + +public interface FlyBehavior { + public void fly(); +} diff --git a/HF_DP/src/headfirst/strategy/FlyNoWay.java b/HF_DP/src/headfirst/strategy/FlyNoWay.java new file mode 100644 index 00000000..f149f5e5 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/FlyNoWay.java @@ -0,0 +1,7 @@ +package headfirst.strategy; + +public class FlyNoWay implements FlyBehavior { + public void fly() { + System.out.println("I can't fly"); + } +} diff --git a/HF_DP/src/headfirst/strategy/FlyRocketPowered.java b/HF_DP/src/headfirst/strategy/FlyRocketPowered.java new file mode 100644 index 00000000..602b5fc0 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/FlyRocketPowered.java @@ -0,0 +1,7 @@ +package headfirst.strategy; + +public class FlyRocketPowered implements FlyBehavior { + public void fly() { + System.out.println("I'm flying with a rocket"); + } +} diff --git a/HF_DP/src/headfirst/strategy/FlyWithWings.java b/HF_DP/src/headfirst/strategy/FlyWithWings.java new file mode 100644 index 00000000..40fc5b06 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/FlyWithWings.java @@ -0,0 +1,7 @@ +package headfirst.strategy; + +public class FlyWithWings implements FlyBehavior { + public void fly() { + System.out.println("I'm flying!!"); + } +} diff --git a/HF_DP/src/headfirst/strategy/MallardDuck.java b/HF_DP/src/headfirst/strategy/MallardDuck.java new file mode 100644 index 00000000..8fbda865 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/MallardDuck.java @@ -0,0 +1,16 @@ +package headfirst.strategy; + +public class MallardDuck extends Duck { + + public MallardDuck() { + + quackBehavior = new Quack(); + flyBehavior = new FlyWithWings(); + + + } + + public void display() { + System.out.println("I'm a real Mallard duck"); + } +} diff --git a/HF_DP/src/headfirst/strategy/MiniDuckSimulator.java b/HF_DP/src/headfirst/strategy/MiniDuckSimulator.java new file mode 100644 index 00000000..7707ef93 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/MiniDuckSimulator.java @@ -0,0 +1,21 @@ +package headfirst.strategy; + +public class MiniDuckSimulator { + + public static void main(String[] args) { + + MallardDuck mallard = new MallardDuck(); + RubberDuck rubberDuckie = new RubberDuck(); + DecoyDuck decoy = new DecoyDuck(); + + ModelDuck model = new ModelDuck(); + + mallard.performQuack(); + rubberDuckie.performQuack(); + decoy.performQuack(); + + model.performFly(); + model.setFlyBehavior(new FlyRocketPowered()); + model.performFly(); + } +} diff --git a/HF_DP/src/headfirst/strategy/MiniDuckSimulator1.java b/HF_DP/src/headfirst/strategy/MiniDuckSimulator1.java new file mode 100644 index 00000000..15ee8b17 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/MiniDuckSimulator1.java @@ -0,0 +1,17 @@ +package headfirst.strategy; + +public class MiniDuckSimulator1 { + + public static void main(String[] args) { + + Duck mallard = new MallardDuck(); + mallard.performQuack(); + mallard.performFly(); + + Duck model = new ModelDuck(); + model.performFly(); + model.setFlyBehavior(new FlyRocketPowered()); + model.performFly(); + + } +} diff --git a/HF_DP/src/headfirst/strategy/ModelDuck.java b/HF_DP/src/headfirst/strategy/ModelDuck.java new file mode 100644 index 00000000..39cb9928 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/ModelDuck.java @@ -0,0 +1,12 @@ +package headfirst.strategy; + +public class ModelDuck extends Duck { + public ModelDuck() { + flyBehavior = new FlyNoWay(); + quackBehavior = new Quack(); + } + + public void display() { + System.out.println("I'm a model duck"); + } +} diff --git a/HF_DP/src/headfirst/strategy/MuteQuack.java b/HF_DP/src/headfirst/strategy/MuteQuack.java new file mode 100644 index 00000000..1479c0f3 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/MuteQuack.java @@ -0,0 +1,7 @@ +package headfirst.strategy; + +public class MuteQuack implements QuackBehavior { + public void quack() { + System.out.println("<< Silence >>"); + } +} diff --git a/HF_DP/src/headfirst/strategy/Quack.java b/HF_DP/src/headfirst/strategy/Quack.java new file mode 100644 index 00000000..90390587 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/Quack.java @@ -0,0 +1,7 @@ +package headfirst.strategy; + +public class Quack implements QuackBehavior { + public void quack() { + System.out.println("Quack"); + } +} diff --git a/HF_DP/src/headfirst/strategy/QuackBehavior.java b/HF_DP/src/headfirst/strategy/QuackBehavior.java new file mode 100644 index 00000000..fae00c20 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/QuackBehavior.java @@ -0,0 +1,5 @@ +package headfirst.strategy; + +public interface QuackBehavior { + public void quack(); +} diff --git a/HF_DP/src/headfirst/strategy/RedHeadDuck.java b/HF_DP/src/headfirst/strategy/RedHeadDuck.java new file mode 100644 index 00000000..d81fac5d --- /dev/null +++ b/HF_DP/src/headfirst/strategy/RedHeadDuck.java @@ -0,0 +1,13 @@ +package headfirst.strategy; + +public class RedHeadDuck extends Duck { + + public RedHeadDuck() { + flyBehavior = new FlyWithWings(); + quackBehavior = new Quack(); + } + + public void display() { + System.out.println("I'm a real Red Headed duck"); + } +} diff --git a/HF_DP/src/headfirst/strategy/RubberDuck.java b/HF_DP/src/headfirst/strategy/RubberDuck.java new file mode 100644 index 00000000..513ca80a --- /dev/null +++ b/HF_DP/src/headfirst/strategy/RubberDuck.java @@ -0,0 +1,13 @@ +package headfirst.strategy; + +public class RubberDuck extends Duck { + + public RubberDuck() { + flyBehavior = new FlyNoWay(); + quackBehavior = new Squeak(); + } + + public void display() { + System.out.println("I'm a rubber duckie"); + } +} diff --git a/HF_DP/src/headfirst/strategy/Squeak.java b/HF_DP/src/headfirst/strategy/Squeak.java new file mode 100644 index 00000000..15a854b8 --- /dev/null +++ b/HF_DP/src/headfirst/strategy/Squeak.java @@ -0,0 +1,7 @@ +package headfirst.strategy; + +public class Squeak implements QuackBehavior { + public void quack() { + System.out.println("Squeak"); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/barista/BeverageTestDrive.java b/HF_DP/src/headfirst/templatemethod/barista/BeverageTestDrive.java new file mode 100644 index 00000000..7303a540 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/barista/BeverageTestDrive.java @@ -0,0 +1,25 @@ +package headfirst.templatemethod.barista; + +public class BeverageTestDrive { + public static void main(String[] args) { + + Tea tea = new Tea(); + Coffee coffee = new Coffee(); + + System.out.println("\nMaking tea..."); + tea.prepareRecipe(); + + System.out.println("\nMaking coffee..."); + coffee.prepareRecipe(); + + + TeaWithHook teaHook = new TeaWithHook(); + CoffeeWithHook coffeeHook = new CoffeeWithHook(); + + System.out.println("\nMaking tea..."); + teaHook.prepareRecipe(); + + System.out.println("\nMaking coffee..."); + coffeeHook.prepareRecipe(); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/barista/CaffeineBeverage.java b/HF_DP/src/headfirst/templatemethod/barista/CaffeineBeverage.java new file mode 100644 index 00000000..d0933623 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/barista/CaffeineBeverage.java @@ -0,0 +1,23 @@ +package headfirst.templatemethod.barista; + +public abstract class CaffeineBeverage { + + final void prepareRecipe() { + boilWater(); + brew(); + pourInCup(); + addCondiments(); + } + + abstract void brew(); + + abstract void addCondiments(); + + void boilWater() { + System.out.println("Boiling water"); + } + + void pourInCup() { + System.out.println("Pouring into cup"); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/barista/CaffeineBeverageWithHook.java b/HF_DP/src/headfirst/templatemethod/barista/CaffeineBeverageWithHook.java new file mode 100644 index 00000000..78eefd36 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/barista/CaffeineBeverageWithHook.java @@ -0,0 +1,29 @@ +package headfirst.templatemethod.barista; + +public abstract class CaffeineBeverageWithHook { + + void prepareRecipe() { + boilWater(); + brew(); + pourInCup(); + if (customerWantsCondiments()) { + addCondiments(); + } + } + + abstract void brew(); + + abstract void addCondiments(); + + void boilWater() { + System.out.println("Boiling water"); + } + + void pourInCup() { + System.out.println("Pouring into cup"); + } + + boolean customerWantsCondiments() { + return true; + } +} diff --git a/HF_DP/src/headfirst/templatemethod/barista/Coffee.java b/HF_DP/src/headfirst/templatemethod/barista/Coffee.java new file mode 100644 index 00000000..7a19f5e3 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/barista/Coffee.java @@ -0,0 +1,10 @@ +package headfirst.templatemethod.barista; + +public class Coffee extends CaffeineBeverage { + public void brew() { + System.out.println("Dripping Coffee through filter"); + } + public void addCondiments() { + System.out.println("Adding Sugar and Milk"); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/barista/CoffeeWithHook.java b/HF_DP/src/headfirst/templatemethod/barista/CoffeeWithHook.java new file mode 100644 index 00000000..8ba8da38 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/barista/CoffeeWithHook.java @@ -0,0 +1,42 @@ +package headfirst.templatemethod.barista; + +import java.io.*; + +public class CoffeeWithHook extends CaffeineBeverageWithHook { + + public void brew() { + System.out.println("Dripping Coffee through filter"); + } + + public void addCondiments() { + System.out.println("Adding Sugar and Milk"); + } + + public boolean customerWantsCondiments() { + + String answer = getUserInput(); + + if (answer.toLowerCase().startsWith("y")) { + return true; + } else { + return false; + } + } + + private String getUserInput() { + String answer = null; + + System.out.print("Would you like milk and sugar with your coffee (y/n)? "); + + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + try { + answer = in.readLine(); + } catch (IOException ioe) { + System.err.println("IO error trying to read your answer"); + } + if (answer == null) { + return "no"; + } + return answer; + } +} diff --git a/HF_DP/src/headfirst/templatemethod/barista/Tea.java b/HF_DP/src/headfirst/templatemethod/barista/Tea.java new file mode 100644 index 00000000..803bcd61 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/barista/Tea.java @@ -0,0 +1,10 @@ +package headfirst.templatemethod.barista; + +public class Tea extends CaffeineBeverage { + public void brew() { + System.out.println("Steeping the tea"); + } + public void addCondiments() { + System.out.println("Adding Lemon"); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/barista/TeaWithHook.java b/HF_DP/src/headfirst/templatemethod/barista/TeaWithHook.java new file mode 100644 index 00000000..6d0864d3 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/barista/TeaWithHook.java @@ -0,0 +1,43 @@ +package headfirst.templatemethod.barista; + +import java.io.*; + +public class TeaWithHook extends CaffeineBeverageWithHook { + + public void brew() { + System.out.println("Steeping the tea"); + } + + public void addCondiments() { + System.out.println("Adding Lemon"); + } + + public boolean customerWantsCondiments() { + + String answer = getUserInput(); + + if (answer.toLowerCase().startsWith("y")) { + return true; + } else { + return false; + } + } + + private String getUserInput() { + // get the user's response + String answer = null; + + System.out.print("Would you like lemon with your tea (y/n)? "); + + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + try { + answer = in.readLine(); + } catch (IOException ioe) { + System.err.println("IO error trying to read your answer"); + } + if (answer == null) { + return "no"; + } + return answer; + } +} diff --git a/HF_DP/src/headfirst/templatemethod/simplebarista/Barista.java b/HF_DP/src/headfirst/templatemethod/simplebarista/Barista.java new file mode 100644 index 00000000..46d2e7d0 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/simplebarista/Barista.java @@ -0,0 +1,13 @@ +package headfirst.templatemethod.simplebarista; + +public class Barista { + + public static void main(String[] args) { + Tea tea = new Tea(); + Coffee coffee = new Coffee(); + System.out.println("Making tea..."); + tea.prepareRecipe(); + System.out.println("Making coffee..."); + coffee.prepareRecipe(); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/simplebarista/Coffee.java b/HF_DP/src/headfirst/templatemethod/simplebarista/Coffee.java new file mode 100644 index 00000000..90773e69 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/simplebarista/Coffee.java @@ -0,0 +1,27 @@ +package headfirst.templatemethod.simplebarista; + +public class Coffee { + + void prepareRecipe() { + boilWater(); + brewCoffeeGrinds(); + pourInCup(); + addSugarAndMilk(); + } + + public void boilWater() { + System.out.println("Boiling water"); + } + + public void brewCoffeeGrinds() { + System.out.println("Dripping Coffee through filter"); + } + + public void pourInCup() { + System.out.println("Pouring into cup"); + } + + public void addSugarAndMilk() { + System.out.println("Adding Sugar and Milk"); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/simplebarista/Tea.java b/HF_DP/src/headfirst/templatemethod/simplebarista/Tea.java new file mode 100644 index 00000000..095134e7 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/simplebarista/Tea.java @@ -0,0 +1,27 @@ +package headfirst.templatemethod.simplebarista; + +public class Tea { + + void prepareRecipe() { + boilWater(); + steepTeaBag(); + pourInCup(); + addLemon(); + } + + public void boilWater() { + System.out.println("Boiling water"); + } + + public void steepTeaBag() { + System.out.println("Steeping the tea"); + } + + public void addLemon() { + System.out.println("Adding Lemon"); + } + + public void pourInCup() { + System.out.println("Pouring into cup"); + } +} diff --git a/HF_DP/src/headfirst/templatemethod/sort/Duck.java b/HF_DP/src/headfirst/templatemethod/sort/Duck.java new file mode 100644 index 00000000..5d44b17b --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/sort/Duck.java @@ -0,0 +1,30 @@ +package headfirst.templatemethod.sort; + +public class Duck implements Comparable { + String name; + int weight; + + public Duck(String name, int weight) { + this.name = name; + this.weight = weight; + } + + public String toString() { + return name + " weighs " + weight; + } + + + + public int compareTo(Object object) { + + Duck otherDuck = (Duck)object; + + if (this.weight < otherDuck.weight) { + return -1; + } else if (this.weight == otherDuck.weight) { + return 0; + } else { // this.weight > otherDuck.weight + return 1; + } + } +} diff --git a/HF_DP/src/headfirst/templatemethod/sort/DuckSortTestDrive.java b/HF_DP/src/headfirst/templatemethod/sort/DuckSortTestDrive.java new file mode 100644 index 00000000..400ab4e0 --- /dev/null +++ b/HF_DP/src/headfirst/templatemethod/sort/DuckSortTestDrive.java @@ -0,0 +1,32 @@ +package headfirst.templatemethod.sort; + +import java.util.ArrayList; +import java.util.Arrays; + +public class DuckSortTestDrive { + + public static void main(String[] args) { + Duck[] ducks = { + new Duck("Daffy", 8), + new Duck("Dewey", 2), + new Duck("Howard", 7), + new Duck("Louie", 2), + new Duck("Donald", 10), + new Duck("Huey", 2) + }; + + System.out.println("Before sorting:"); + display(ducks); + + Arrays.sort(ducks); + + System.out.println("\nAfter sorting:"); + display(ducks); + } + + public static void display(Duck[] ducks) { + for (int i = 0; i < ducks.length; i++) { + System.out.println(ducks[i]); + } + } +} diff --git a/basicKnowledge/.classpath b/basicKnowledge/.classpath index 91ee9a52..1f21617a 100644 --- a/basicKnowledge/.classpath +++ b/basicKnowledge/.classpath @@ -2,5 +2,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/basicKnowledge/.settings/org.eclipse.core.resources.prefs b/basicKnowledge/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000..233a5129 --- /dev/null +++ b/basicKnowledge/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//src/common-logging.properties=UTF-8 diff --git a/basicKnowledge/bin/com/xdc/basic/BasicKnowledge.class b/basicKnowledge/bin/com/xdc/basic/BasicKnowledge.class deleted file mode 100644 index 75516f3e..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/BasicKnowledge.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/collection/ArrayListTest.class b/basicKnowledge/bin/com/xdc/basic/java4android/collection/ArrayListTest.class deleted file mode 100644 index b2e10deb..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/collection/ArrayListTest.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/collection/HashMapTest.class b/basicKnowledge/bin/com/xdc/basic/java4android/collection/HashMapTest.class deleted file mode 100644 index 1c280d49..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/collection/HashMapTest.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/collection/HashSetTest.class b/basicKnowledge/bin/com/xdc/basic/java4android/collection/HashSetTest.class deleted file mode 100644 index 1291c807..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/collection/HashSetTest.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/equals/EqualsTest.class b/basicKnowledge/bin/com/xdc/basic/java4android/equals/EqualsTest.class deleted file mode 100644 index 4d2f739d..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/equals/EqualsTest.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/equals/User.class b/basicKnowledge/bin/com/xdc/basic/java4android/equals/User.class deleted file mode 100644 index 97b5c874..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/equals/User.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/io/BufferedReaderTest.class b/basicKnowledge/bin/com/xdc/basic/java4android/io/BufferedReaderTest.class deleted file mode 100644 index 085ddc74..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/io/BufferedReaderTest.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/io/IOByteStreamTest.class b/basicKnowledge/bin/com/xdc/basic/java4android/io/IOByteStreamTest.class deleted file mode 100644 index d5e5f667..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/io/IOByteStreamTest.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/io/IOCharStreamTest.class b/basicKnowledge/bin/com/xdc/basic/java4android/io/IOCharStreamTest.class deleted file mode 100644 index a447332a..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/io/IOCharStreamTest.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/thread/extendsthead/Test.class b/basicKnowledge/bin/com/xdc/basic/java4android/thread/extendsthead/Test.class deleted file mode 100644 index dbfc9dcd..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/thread/extendsthead/Test.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/thread/implrunable/RunnableImpl.class b/basicKnowledge/bin/com/xdc/basic/java4android/thread/implrunable/RunnableImpl.class deleted file mode 100644 index 37e9d4f1..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/thread/implrunable/RunnableImpl.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/thread/implrunable/Test.class b/basicKnowledge/bin/com/xdc/basic/java4android/thread/implrunable/Test.class deleted file mode 100644 index b9800d91..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/thread/implrunable/Test.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/thread/synclock/RunnableImpl.class b/basicKnowledge/bin/com/xdc/basic/java4android/thread/synclock/RunnableImpl.class deleted file mode 100644 index a8e34082..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/thread/synclock/RunnableImpl.class and /dev/null differ diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/thread/synclock/Test.class b/basicKnowledge/bin/com/xdc/basic/java4android/thread/synclock/Test.class deleted file mode 100644 index b489591b..00000000 Binary files a/basicKnowledge/bin/com/xdc/basic/java4android/thread/synclock/Test.class and /dev/null differ diff --git a/basicKnowledge/lib/apache/commons/commons-beanutils-1.8.3.jar b/basicKnowledge/lib/apache/commons/commons-beanutils-1.8.3.jar new file mode 100644 index 00000000..218510bc Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-beanutils-1.8.3.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-beanutils-bean-collections-1.8.3.jar b/basicKnowledge/lib/apache/commons/commons-beanutils-bean-collections-1.8.3.jar new file mode 100644 index 00000000..fdffaa1d Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-beanutils-bean-collections-1.8.3.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-beanutils-core-1.8.3.jar b/basicKnowledge/lib/apache/commons/commons-beanutils-core-1.8.3.jar new file mode 100644 index 00000000..7647dc52 Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-beanutils-core-1.8.3.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-codec-1.7.jar b/basicKnowledge/lib/apache/commons/commons-codec-1.7.jar new file mode 100644 index 00000000..efa7f729 Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-codec-1.7.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-collections-3.2.1.jar b/basicKnowledge/lib/apache/commons/commons-collections-3.2.1.jar new file mode 100644 index 00000000..c35fa1fe Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-collections-3.2.1.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-configuration-1.9.jar b/basicKnowledge/lib/apache/commons/commons-configuration-1.9.jar new file mode 100644 index 00000000..fa8fac19 Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-configuration-1.9.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-digester3-3.2.jar b/basicKnowledge/lib/apache/commons/commons-digester3-3.2.jar new file mode 100644 index 00000000..62e5140a Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-digester3-3.2.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-exec-1.1.jar b/basicKnowledge/lib/apache/commons/commons-exec-1.1.jar new file mode 100644 index 00000000..baee06ff Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-exec-1.1.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-io-2.4.jar b/basicKnowledge/lib/apache/commons/commons-io-2.4.jar new file mode 100644 index 00000000..90035a4f Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-io-2.4.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-jxpath-1.3.jar b/basicKnowledge/lib/apache/commons/commons-jxpath-1.3.jar new file mode 100644 index 00000000..e344a1e6 Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-jxpath-1.3.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-lang-2.6.jar b/basicKnowledge/lib/apache/commons/commons-lang-2.6.jar new file mode 100644 index 00000000..98467d3a Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-lang-2.6.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-lang3-3.1.jar b/basicKnowledge/lib/apache/commons/commons-lang3-3.1.jar new file mode 100644 index 00000000..a85e539b Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-lang3-3.1.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-logging-1.1.3.jar b/basicKnowledge/lib/apache/commons/commons-logging-1.1.3.jar new file mode 100644 index 00000000..ab512540 Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-logging-1.1.3.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-logging-adapters-1.1.3.jar b/basicKnowledge/lib/apache/commons/commons-logging-adapters-1.1.3.jar new file mode 100644 index 00000000..8250587b Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-logging-adapters-1.1.3.jar differ diff --git a/basicKnowledge/lib/apache/commons/commons-logging-api-1.1.3.jar b/basicKnowledge/lib/apache/commons/commons-logging-api-1.1.3.jar new file mode 100644 index 00000000..3786868d Binary files /dev/null and b/basicKnowledge/lib/apache/commons/commons-logging-api-1.1.3.jar differ diff --git a/basicKnowledge/lib/apache/http/fluent-hc-4.3.jar b/basicKnowledge/lib/apache/http/fluent-hc-4.3.jar new file mode 100644 index 00000000..73c49d94 Binary files /dev/null and b/basicKnowledge/lib/apache/http/fluent-hc-4.3.jar differ diff --git a/basicKnowledge/lib/apache/http/httpclient-4.3.jar b/basicKnowledge/lib/apache/http/httpclient-4.3.jar new file mode 100644 index 00000000..5c446f04 Binary files /dev/null and b/basicKnowledge/lib/apache/http/httpclient-4.3.jar differ diff --git a/basicKnowledge/lib/apache/http/httpclient-cache-4.3.jar b/basicKnowledge/lib/apache/http/httpclient-cache-4.3.jar new file mode 100644 index 00000000..ba489a4c Binary files /dev/null and b/basicKnowledge/lib/apache/http/httpclient-cache-4.3.jar differ diff --git a/basicKnowledge/lib/apache/http/httpcore-4.3.jar b/basicKnowledge/lib/apache/http/httpcore-4.3.jar new file mode 100644 index 00000000..e5da4578 Binary files /dev/null and b/basicKnowledge/lib/apache/http/httpcore-4.3.jar differ diff --git a/basicKnowledge/lib/apache/http/httpmime-4.3.jar b/basicKnowledge/lib/apache/http/httpmime-4.3.jar new file mode 100644 index 00000000..55dd8aec Binary files /dev/null and b/basicKnowledge/lib/apache/http/httpmime-4.3.jar differ diff --git a/basicKnowledge/lib/apache/log4j/log4j-1.2.17.jar b/basicKnowledge/lib/apache/log4j/log4j-1.2.17.jar new file mode 100644 index 00000000..068867eb Binary files /dev/null and b/basicKnowledge/lib/apache/log4j/log4j-1.2.17.jar differ diff --git a/basicKnowledge/lib/easymock-3.1.jar b/basicKnowledge/lib/easymock-3.1.jar new file mode 100644 index 00000000..f56f07ac Binary files /dev/null and b/basicKnowledge/lib/easymock-3.1.jar differ diff --git a/basicKnowledge/lib/guava-14.0.1.jar b/basicKnowledge/lib/guava-14.0.1.jar new file mode 100644 index 00000000..3a3d9258 Binary files /dev/null and b/basicKnowledge/lib/guava-14.0.1.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/hibernate-validator-5.0.1.Final.jar b/basicKnowledge/lib/hibernate-validator/hibernate-validator-5.0.1.Final.jar new file mode 100644 index 00000000..dc8f331f Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/hibernate-validator-5.0.1.Final.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/hibernate-validator-annotation-processor-5.0.1.Final.jar b/basicKnowledge/lib/hibernate-validator/hibernate-validator-annotation-processor-5.0.1.Final.jar new file mode 100644 index 00000000..0776b293 Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/hibernate-validator-annotation-processor-5.0.1.Final.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/hibernate-validator-cdi-5.0.1.Final.jar b/basicKnowledge/lib/hibernate-validator/hibernate-validator-cdi-5.0.1.Final.jar new file mode 100644 index 00000000..2982828f Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/hibernate-validator-cdi-5.0.1.Final.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/lib/required/classmate-0.8.0.jar b/basicKnowledge/lib/hibernate-validator/lib/required/classmate-0.8.0.jar new file mode 100644 index 00000000..38277cbc Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/lib/required/classmate-0.8.0.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/lib/required/javax.el-2.2.4.jar b/basicKnowledge/lib/hibernate-validator/lib/required/javax.el-2.2.4.jar new file mode 100644 index 00000000..76df3a0e Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/lib/required/javax.el-2.2.4.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/lib/required/javax.el-api-2.2.4.jar b/basicKnowledge/lib/hibernate-validator/lib/required/javax.el-api-2.2.4.jar new file mode 100644 index 00000000..20115bc5 Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/lib/required/javax.el-api-2.2.4.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/lib/required/jboss-logging-3.1.1.GA.jar b/basicKnowledge/lib/hibernate-validator/lib/required/jboss-logging-3.1.1.GA.jar new file mode 100644 index 00000000..891989aa Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/lib/required/jboss-logging-3.1.1.GA.jar differ diff --git a/basicKnowledge/lib/hibernate-validator/lib/required/validation-api-1.1.0.Final.jar b/basicKnowledge/lib/hibernate-validator/lib/required/validation-api-1.1.0.Final.jar new file mode 100644 index 00000000..de854038 Binary files /dev/null and b/basicKnowledge/lib/hibernate-validator/lib/required/validation-api-1.1.0.Final.jar differ diff --git a/basicKnowledge/lib/json/jackson/jackson-annotations-2.2.3.jar b/basicKnowledge/lib/json/jackson/jackson-annotations-2.2.3.jar new file mode 100644 index 00000000..b62c87d7 Binary files /dev/null and b/basicKnowledge/lib/json/jackson/jackson-annotations-2.2.3.jar differ diff --git a/basicKnowledge/lib/json/jackson/jackson-core-2.2.3.jar b/basicKnowledge/lib/json/jackson/jackson-core-2.2.3.jar new file mode 100644 index 00000000..24318a46 Binary files /dev/null and b/basicKnowledge/lib/json/jackson/jackson-core-2.2.3.jar differ diff --git a/basicKnowledge/lib/json/jackson/jackson-databind-2.2.3.jar b/basicKnowledge/lib/json/jackson/jackson-databind-2.2.3.jar new file mode 100644 index 00000000..85450847 Binary files /dev/null and b/basicKnowledge/lib/json/jackson/jackson-databind-2.2.3.jar differ diff --git a/basicKnowledge/lib/json/jsonsmart/json-smart-2.0-RC3.jar b/basicKnowledge/lib/json/jsonsmart/json-smart-2.0-RC3.jar new file mode 100644 index 00000000..5b6304fb Binary files /dev/null and b/basicKnowledge/lib/json/jsonsmart/json-smart-2.0-RC3.jar differ diff --git a/basicKnowledge/lib/json/jsonsmart/lib/asm-1.0-RC3.jar b/basicKnowledge/lib/json/jsonsmart/lib/asm-1.0-RC3.jar new file mode 100644 index 00000000..d6924f7b Binary files /dev/null and b/basicKnowledge/lib/json/jsonsmart/lib/asm-1.0-RC3.jar differ diff --git a/basicKnowledge/lib/json/jsonsmart/lib/asm-3.3.1.jar b/basicKnowledge/lib/json/jsonsmart/lib/asm-3.3.1.jar new file mode 100644 index 00000000..f50f03f3 Binary files /dev/null and b/basicKnowledge/lib/json/jsonsmart/lib/asm-3.3.1.jar differ diff --git a/basicKnowledge/lib/mq/rabbitmq-client-tests.jar b/basicKnowledge/lib/mq/rabbitmq-client-tests.jar new file mode 100644 index 00000000..1afdb264 Binary files /dev/null and b/basicKnowledge/lib/mq/rabbitmq-client-tests.jar differ diff --git a/basicKnowledge/lib/mq/rabbitmq-client.jar b/basicKnowledge/lib/mq/rabbitmq-client.jar new file mode 100644 index 00000000..671dcbca Binary files /dev/null and b/basicKnowledge/lib/mq/rabbitmq-client.jar differ diff --git a/basicKnowledge/lib/mybatis/mybatis-3.1.1.jar b/basicKnowledge/lib/mybatis/mybatis-3.1.1.jar new file mode 100644 index 00000000..2801833e Binary files /dev/null and b/basicKnowledge/lib/mybatis/mybatis-3.1.1.jar differ diff --git a/basicKnowledge/lib/mybatis/mysql-connector-java-5.1.24-bin.jar b/basicKnowledge/lib/mybatis/mysql-connector-java-5.1.24-bin.jar new file mode 100644 index 00000000..c640a8d1 Binary files /dev/null and b/basicKnowledge/lib/mybatis/mysql-connector-java-5.1.24-bin.jar differ diff --git a/basicKnowledge/lib/mybatis/ojdbc6.jar b/basicKnowledge/lib/mybatis/ojdbc6.jar new file mode 100644 index 00000000..01da074d Binary files /dev/null and b/basicKnowledge/lib/mybatis/ojdbc6.jar differ diff --git a/basicKnowledge/lib/spring/spring-aop-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-aop-3.2.2.RELEASE.jar new file mode 100644 index 00000000..386fe329 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-aop-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-aspects-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-aspects-3.2.2.RELEASE.jar new file mode 100644 index 00000000..d5246a87 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-aspects-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-beans-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-beans-3.2.2.RELEASE.jar new file mode 100644 index 00000000..52d0ae60 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-beans-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-build-src-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-build-src-3.2.2.RELEASE.jar new file mode 100644 index 00000000..10bd9743 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-build-src-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-context-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-context-3.2.2.RELEASE.jar new file mode 100644 index 00000000..b027ab85 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-context-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-context-support-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-context-support-3.2.2.RELEASE.jar new file mode 100644 index 00000000..f1df10b9 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-context-support-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-core-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-core-3.2.2.RELEASE.jar new file mode 100644 index 00000000..906326de Binary files /dev/null and b/basicKnowledge/lib/spring/spring-core-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-expression-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-expression-3.2.2.RELEASE.jar new file mode 100644 index 00000000..b5c6f1a6 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-expression-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-instrument-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-instrument-3.2.2.RELEASE.jar new file mode 100644 index 00000000..76e6d48c Binary files /dev/null and b/basicKnowledge/lib/spring/spring-instrument-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-instrument-tomcat-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-instrument-tomcat-3.2.2.RELEASE.jar new file mode 100644 index 00000000..04efc1de Binary files /dev/null and b/basicKnowledge/lib/spring/spring-instrument-tomcat-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-jdbc-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-jdbc-3.2.2.RELEASE.jar new file mode 100644 index 00000000..51a5f9df Binary files /dev/null and b/basicKnowledge/lib/spring/spring-jdbc-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-jms-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-jms-3.2.2.RELEASE.jar new file mode 100644 index 00000000..bfbe9f37 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-jms-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-orm-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-orm-3.2.2.RELEASE.jar new file mode 100644 index 00000000..e00f7793 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-orm-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-oxm-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-oxm-3.2.2.RELEASE.jar new file mode 100644 index 00000000..8e8e6ca1 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-oxm-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-struts-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-struts-3.2.2.RELEASE.jar new file mode 100644 index 00000000..5bb0943b Binary files /dev/null and b/basicKnowledge/lib/spring/spring-struts-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-test-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-test-3.2.2.RELEASE.jar new file mode 100644 index 00000000..a806bba7 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-test-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-tx-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-tx-3.2.2.RELEASE.jar new file mode 100644 index 00000000..413bec2b Binary files /dev/null and b/basicKnowledge/lib/spring/spring-tx-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-web-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-web-3.2.2.RELEASE.jar new file mode 100644 index 00000000..f11f3b23 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-web-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-webmvc-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-webmvc-3.2.2.RELEASE.jar new file mode 100644 index 00000000..991f4d30 Binary files /dev/null and b/basicKnowledge/lib/spring/spring-webmvc-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/spring/spring-webmvc-portlet-3.2.2.RELEASE.jar b/basicKnowledge/lib/spring/spring-webmvc-portlet-3.2.2.RELEASE.jar new file mode 100644 index 00000000..94defdff Binary files /dev/null and b/basicKnowledge/lib/spring/spring-webmvc-portlet-3.2.2.RELEASE.jar differ diff --git a/basicKnowledge/lib/xml/dom4j-1.6.1.jar b/basicKnowledge/lib/xml/dom4j-1.6.1.jar new file mode 100644 index 00000000..c8c4dbb9 Binary files /dev/null and b/basicKnowledge/lib/xml/dom4j-1.6.1.jar differ diff --git a/jdom2.format/lib/jdom-2.0.4.jar b/basicKnowledge/lib/xml/jdom-2.0.4.jar similarity index 100% rename from jdom2.format/lib/jdom-2.0.4.jar rename to basicKnowledge/lib/xml/jdom-2.0.4.jar diff --git a/basicKnowledge/lib/xml/xmlpull/kxml2-2.3.0.jar b/basicKnowledge/lib/xml/xmlpull/kxml2-2.3.0.jar new file mode 100644 index 00000000..64709522 Binary files /dev/null and b/basicKnowledge/lib/xml/xmlpull/kxml2-2.3.0.jar differ diff --git a/basicKnowledge/lib/xml/xmlpull/xmlpull_1_1_3_4c.jar b/basicKnowledge/lib/xml/xmlpull/xmlpull_1_1_3_4c.jar new file mode 100644 index 00000000..7240eff2 Binary files /dev/null and b/basicKnowledge/lib/xml/xmlpull/xmlpull_1_1_3_4c.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-beanutils-1.8.3-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-beanutils-1.8.3-sources.jar new file mode 100644 index 00000000..422d23dd Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-beanutils-1.8.3-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-codec-1.7-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-codec-1.7-sources.jar new file mode 100644 index 00000000..e5bd2498 Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-codec-1.7-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-collections-3.2.1-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-collections-3.2.1-sources.jar new file mode 100644 index 00000000..1c546a1e Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-collections-3.2.1-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-configuration-1.9-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-configuration-1.9-sources.jar new file mode 100644 index 00000000..14a346ae Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-configuration-1.9-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-digester3-3.2-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-digester3-3.2-sources.jar new file mode 100644 index 00000000..c0dcdf6c Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-digester3-3.2-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-exec-1.1-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-exec-1.1-sources.jar new file mode 100644 index 00000000..0fc4dd72 Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-exec-1.1-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-io-2.4-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-io-2.4-sources.jar new file mode 100644 index 00000000..f4ebc7b4 Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-io-2.4-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-jxpath-1.3-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-jxpath-1.3-sources.jar new file mode 100644 index 00000000..9959e9ac Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-jxpath-1.3-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-lang-2.6-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-lang-2.6-sources.jar new file mode 100644 index 00000000..b4230533 Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-lang-2.6-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-lang3-3.1-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-lang3-3.1-sources.jar new file mode 100644 index 00000000..02cd2f25 Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-lang3-3.1-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/commons/commons-logging-1.1.3-sources.jar b/basicKnowledge/libsrc/apache/commons/commons-logging-1.1.3-sources.jar new file mode 100644 index 00000000..7d7a9872 Binary files /dev/null and b/basicKnowledge/libsrc/apache/commons/commons-logging-1.1.3-sources.jar differ diff --git a/basicKnowledge/libsrc/apache/http/httpcomponents-client-4.3-src.zip b/basicKnowledge/libsrc/apache/http/httpcomponents-client-4.3-src.zip new file mode 100644 index 00000000..9f650a26 Binary files /dev/null and b/basicKnowledge/libsrc/apache/http/httpcomponents-client-4.3-src.zip differ diff --git a/basicKnowledge/libsrc/apache/http/httpcomponents-core-4.3-src.zip b/basicKnowledge/libsrc/apache/http/httpcomponents-core-4.3-src.zip new file mode 100644 index 00000000..6e1fb249 Binary files /dev/null and b/basicKnowledge/libsrc/apache/http/httpcomponents-core-4.3-src.zip differ diff --git a/basicKnowledge/libsrc/easymock-3.1-sources.jar b/basicKnowledge/libsrc/easymock-3.1-sources.jar new file mode 100644 index 00000000..002b20c7 Binary files /dev/null and b/basicKnowledge/libsrc/easymock-3.1-sources.jar differ diff --git a/basicKnowledge/libsrc/guava-14.0.1-sources.jar b/basicKnowledge/libsrc/guava-14.0.1-sources.jar new file mode 100644 index 00000000..55c848e5 Binary files /dev/null and b/basicKnowledge/libsrc/guava-14.0.1-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-aop-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-aop-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..d75d7436 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-aop-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-aspects-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-aspects-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..f365b801 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-aspects-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-beans-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-beans-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..6c501f91 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-beans-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-context-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-context-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..e188e47e Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-context-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-context-support-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-context-support-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..a4af4090 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-context-support-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-core-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-core-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..fff619f9 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-core-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-expression-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-expression-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..44fdc9ad Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-expression-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-instrument-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-instrument-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..78120b16 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-instrument-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-instrument-tomcat-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-instrument-tomcat-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..43ef7572 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-instrument-tomcat-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-jdbc-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-jdbc-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..1a19cbe1 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-jdbc-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-jms-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-jms-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..c6d26f38 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-jms-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-orm-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-orm-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..e0bc6a69 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-orm-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-oxm-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-oxm-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..38cd87b7 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-oxm-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-struts-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-struts-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..cdc569a7 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-struts-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-test-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-test-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..9c187eec Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-test-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-tx-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-tx-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..f41d53c8 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-tx-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-web-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-web-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..51f4f749 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-web-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-webmvc-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-webmvc-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..29e91279 Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-webmvc-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/libsrc/spring/spring-webmvc-portlet-3.2.2.RELEASE-sources.jar b/basicKnowledge/libsrc/spring/spring-webmvc-portlet-3.2.2.RELEASE-sources.jar new file mode 100644 index 00000000..3db045bd Binary files /dev/null and b/basicKnowledge/libsrc/spring/spring-webmvc-portlet-3.2.2.RELEASE-sources.jar differ diff --git a/basicKnowledge/src/com/xdc/basic/BasicKnowledge.java b/basicKnowledge/src/com/xdc/basic/BasicKnowledge.java index 3d4cb721..9ae31a70 100644 --- a/basicKnowledge/src/com/xdc/basic/BasicKnowledge.java +++ b/basicKnowledge/src/com/xdc/basic/BasicKnowledge.java @@ -1,61 +1,90 @@ package com.xdc.basic; +import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; import java.util.Random; +import org.apache.commons.lang3.SystemUtils; + public class BasicKnowledge { - public static void main(String[] args) - { - // 1. 获取环境变量 - System.getenv("PATH"); - System.getenv("JAVA_HOME"); - - // 2. 获取系统属性 - Properties p = System.getProperties(); // 得到所有属性值 - // p.list(System.out); - System.getProperty("file.separator"); // 文件分隔符(在 UNIX 系统中是“/”) - System.getProperty("path.separator"); // 路径分隔符(在 UNIX 系统中是“:”) - System.getProperty("line.separator"); // 行分隔符(在 UNIX 系统中是“/n”) - System.getProperty("user.name"); // 用户的账户名称 - System.getProperty("user.home"); // 用户的主目录 - System.getProperty("user.dir"); // 用户的当前工作目录 - - // 4. StringBuffer(同步)和StringBuilder(非同步) - StringBuilder sb = new StringBuilder(); - sb.append("Hello"); - sb.append("World"); - sb.reverse();// 反转字符串 - sb.toString(); - - // 5. 数字 - Integer integer = 1; - integer.intValue(); // 数字与对象之间互相转换 - Integer转int - - Integer.toBinaryString(15); // 整数 -> 二进制字符串 - Integer.toOctalString(15); // 整数 -> 八进制字符串 - Integer.toHexString(15); // 整数 -> 十六进制字符串 - - Math.round(3.4); // // 浮点数的舍入,结果为3 - - // 随机数 - Random r = new Random(); - r.nextDouble(); - r.nextInt(); - - // 6. 日期和时间 - Date today = new Date(); // 查看当前日期 - // System.out.println(today); - - // 按要求格式打印日期 - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); - sdf.format(today); - - // 记录耗时 - long start = System.currentTimeMillis(); - long end = System.currentTimeMillis(); - long elapsed = end - start; - } + @SuppressWarnings("unused") + public static void main(String[] args) + { + // 1. 获取环境变量 + System.getenv("PATH"); + System.getenv("JAVA_HOME"); + + // 2. 获取系统属性 + Properties p = System.getProperties(); // 得到所有属性值 + p.list(System.out); + System.getProperty("file.separator"); // 文件分隔符(在 UNIX 系统中是“/”) + System.getProperty("path.separator"); // 路径分隔符(在 UNIX 系统中是“:”) + System.getProperty("line.separator"); // 行分隔符(在 UNIX 系统中是“/n”) + System.getProperty("user.name"); // 用户的账户名称 + System.getProperty("user.home"); // 用户的主目录 + System.getProperty("user.dir"); // 用户的当前工作目录 + // apache 类库 + String LINE_SEPARATOR = SystemUtils.LINE_SEPARATOR; + System.out.println(LINE_SEPARATOR); + + // sun.jnu.encoding 影响文件名的创建、 cmd命令行的当前编码 + // file.encoding 影响到文件内容 + System.getProperty("sun.jnu.encoding"); + System.getProperty("file.encoding"); + + // 3. 字节数据-->字符串 + byte[] bytes = new byte[100]; + String str = new String(bytes); + + // 4. StringBuffer(同步)和StringBuilder(非同步) + // 如果是JDK1.5最好用StringBuilder取代StringBuffer, 除非有线程安全的要求. + StringBuilder sb = new StringBuilder(); + sb.append("Hello"); + sb.append("World"); + sb.reverse();// 反转字符串 + sb.toString(); + + // 5. 数字 + Integer integer = 1; + integer.intValue(); // 数字与对象之间互相转换 - Integer转int + + Integer.toBinaryString(15); // 整数 -> 二进制字符串 + Integer.toOctalString(15); // 整数 -> 八进制字符串 + Integer.toHexString(15); // 整数 -> 十六进制字符串 + + Math.round(3.4); // // 浮点数的舍入,结果为3 + + // 随机数 + Random r = new Random(); + r.nextDouble(); + r.nextInt(); + + // 47(参数类型为long) 为随机数种子,如果种子不变,产生的随机数序列不变。无参数时,取系统时间做种子 + Random rand = new Random(47); + // 产生0~25的随机值 + System.out.println(rand.nextInt(26)); + + // 产生0和1之间的(包括0,但不包括1)的一个double值 + System.out.println(Math.random()); + + // 6. 日期和时间 + Date today = new Date(); // 查看当前日期 + // System.out.println(today); + + // 按要求格式打印日期 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + sdf.format(today); + + // 记录耗时 + long start = System.currentTimeMillis(); + long end = System.currentTimeMillis(); + long elapsed = end - start; + System.out.println("用时:" + elapsed); + + // 获取Timestamp对象 + new Timestamp(System.currentTimeMillis()); + } } diff --git a/basicKnowledge/src/com/xdc/basic/JDBCDemo.java b/basicKnowledge/src/com/xdc/basic/JDBCDemo.java deleted file mode 100644 index 3fdd55cf..00000000 --- a/basicKnowledge/src/com/xdc/basic/JDBCDemo.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.xdc.basic; - -import java.sql.*; - -public class JDBCDemo { - public static void main(String[] args) { - try { - Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); - String url = "jdbc:odbc:myClass"; - String user = ""; - String password = ""; - Connection con = DriverManager.getConnection(url, user, password); - Statement stmt = con.createStatement( - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.TYPE_FORWARD_ONLY); - ResultSet res = stmt.executeQuery("select * from Exam"); - while (res.next()) { - System.out.println(res.getString(1)); - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (SQLException e) { - e.printStackTrace(); - } - } -} diff --git a/basicKnowledge/src/com/xdc/basic/ScannerDemo.java b/basicKnowledge/src/com/xdc/basic/ScannerDemo.java deleted file mode 100644 index cee76a7c..00000000 --- a/basicKnowledge/src/com/xdc/basic/ScannerDemo.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.xdc.basic; - -import java.util.Scanner; - -public class ScannerDemo -{ - public static void main(String[] args) - { - String s = "abcd, w2jfew, 1jkfew, 3reere"; - Scanner sc = new Scanner(s); - String answer = ""; - while ((answer = sc.findInLine("\\b\\d[a-z]*\\s")) != null) - { - // 试图在忽略分隔符的情况下查找下一个从指定字符串构造的模式。 - // System.out.println(answer); - } - sc = new Scanner(s); - String ss = sc.findWithinHorizon("[a-z]*", 10); - // 试图在忽略分隔符的情况下查找下一个从指定字符串构造的模式。 - System.out.println(ss); - - sc = new Scanner(s); - sc.useDelimiter("[,]\\s*"); - // 将此扫描器的分隔模式设置为从指定 String 构造的模式。 - while (sc.hasNext()) - { - System.out.println(sc.next()); - } - } - -} diff --git a/basicKnowledge/src/com/xdc/basic/WaitAndNotifyDemo.java b/basicKnowledge/src/com/xdc/basic/WaitAndNotifyDemo.java deleted file mode 100644 index 23b850d6..00000000 --- a/basicKnowledge/src/com/xdc/basic/WaitAndNotifyDemo.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.xdc.basic; - -import java.util.Vector; - -public class WaitAndNotifyDemo -{ - Vector data = new Vector(); - - void addData() - { - synchronized (data) - { - String name = Thread.currentThread().getName(); - System.out.println(name + " enter addData()"); - data.add("value" + ((int) (Math.random() * 100))); - data.notifyAll(); - System.out.println(name + " data added"); - } - } - - void removeData() - { - synchronized (data) - { - String name = Thread.currentThread().getName(); - System.out.println(name + " enter removeData()"); - - while (data.size() == 0) - { - System.out.println(name + " no data to remove, try to wait"); - try - { - data.wait(); - System.out.println(name + " wake up"); - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - } - Object o = data.remove(0); - System.out.println(name + " data removed " + o); - } - } - - private void start() - { - new Thread2(this).start(); - new Thread2(this).start(); - new Thread2(this).start(); - new Thread1(this).start(); - } - - /** - * @param args - */ - public static void main(String[] args) - { - // TODO Auto-generated method stub - WaitAndNotifyDemo object = new WaitAndNotifyDemo(); - object.start(); - } - - class Thread1 extends Thread - { - WaitAndNotifyDemo synObject; - - Thread1(WaitAndNotifyDemo synObject) - { - this.synObject = synObject; - } - - public void run() - { - String name = getName(); - while (true) - { - System.out.println(name + " try to addData..."); - synObject.addData(); - try - { - Thread.sleep(2000); - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - } - } - } - - class Thread2 extends Thread - { - WaitAndNotifyDemo synObject; - - Thread2(WaitAndNotifyDemo synObject) - { - this.synObject = synObject; - } - - public void run() - { - String name = getName(); - while (true) - { - System.out.println(name + " try to removeData..."); - synObject.removeData(); - try - { - Thread.sleep(100); - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - } - } - } -} diff --git a/basicKnowledge/src/com/xdc/basic/api/EnumTest.java b/basicKnowledge/src/com/xdc/basic/api/EnumTest.java new file mode 100644 index 00000000..817e5664 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/EnumTest.java @@ -0,0 +1,19 @@ +package com.xdc.basic.api; + +public class EnumTest +{ + public enum Color + { + RED, GREEN, BLANK, YELLOW + } + + public static void main(String[] args) + { + // 枚举可以用==比较 + Color color = Color.GREEN; + if (color == Color.GREEN) + { + System.out.println("颜色为GREEN"); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/FileTest.java b/basicKnowledge/src/com/xdc/basic/api/FileTest.java new file mode 100644 index 00000000..85f9a27f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/FileTest.java @@ -0,0 +1,36 @@ +package com.xdc.basic.api; + +import java.io.File; +import java.io.IOException; + +public class FileTest +{ + public static void main(String[] args) throws IOException + { + File f = new File("xdc.txt"); + // 获取文件信息 + f.exists(); // 如果文件存在,返回true + f.getCanonicalPath(); // 获取全名 + f.getName(); // 文件名 + f.getParent(); // 父目录 + f.canRead(); // 如果文件可读,返回true + f.canWrite(); // 如果文件可写,返回true + f.lastModified(); // 文件更新时间 + f.length(); // 文件大小 + f.isFile(); // 如果是文件,返回true + f.isDirectory(); // 如果是目录,返回true + + f.createNewFile(); // 创建 + f.delete(); // 文件 + + // 创建新目录 + new File("/home/ian/bin").mkdir(); // 如果"/home/ian"存在,则可以创建bin目录 + new File("/home/ian/bin").mkdirs(); // 如果"/home/ian"不存在,会创建所有的目录 + + // 临时文件 + File dir = new File("C:\\test"); // 指定一个文件夹 + // 在test文件夹中创建foo前缀,tmp后缀的临时文件 + File tmp = File.createTempFile("foo", "tmp", dir); + tmp.deleteOnExit(); // 在程序结束时删除该临时文件 + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/MessageFormatTest.java b/basicKnowledge/src/com/xdc/basic/api/MessageFormatTest.java new file mode 100644 index 00000000..05d0e659 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/MessageFormatTest.java @@ -0,0 +1,48 @@ +package com.xdc.basic.api; + +import java.text.MessageFormat; +import java.util.Date; + +/** + * http://www.oschina.net/code/snippet_109139_5062 + * + * @author xdc + * + */ +public class MessageFormatTest +{ + public static void main(String[] args) + { + // 1 + String model = "Hello {0}: Your name:{0} Age:{1} Address:{2}"; + String[] params = { "Asa", "23", "QiLiHe lz.China" }; + String msg1 = MessageFormat.format(model, (Object[]) params); + System.out.println(msg1); + // Hello Asa: Your name:Asa Age:23 Address:QiLiHe lz.China + + // 2 + Object[] params2 = new Object[] { new Date(), new Date(0), new Date() }; + String msg2 = MessageFormat.format("{0,date,short} --- {1,time,medium} --- {2,date,yyyy-MM-dd HH:mm:ss}", + params2); + System.out.println(msg2); + // 11-7-6 --- 8:00:00 --- 2011-07-06 15:40:59 + + // 3 + Object[] params3 = new Object[] { new Double(0.45), new Double(1234.56) }; + String msg3 = MessageFormat.format("{0,number,percent} --- {1,number,percent}", params3); + System.out.println(msg3); + // 45% --- 123,456% + + // 4 + Object[] params4 = new Object[] { new Double(123.45), new Double(1234.56) }; + String msg4 = MessageFormat.format("{0,number,currency} --- {1,number,currency}", params4); + System.out.println(msg4); + // ¥123.45 --- ¥1,234.56 + + // 5 + Object[] params5 = new Object[] { new Integer(123), new Integer(1234) }; + String msg5 = MessageFormat.format("{0,number,#} a''s and {1,number,#} b''s", params5); + System.out.println(msg5); + // 123 a's and 1234 b's + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/RandomTest.java b/basicKnowledge/src/com/xdc/basic/api/RandomTest.java new file mode 100644 index 00000000..3333d31c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/RandomTest.java @@ -0,0 +1,42 @@ +package com.xdc.basic.api; + +import java.security.SecureRandom; +import java.util.Random; + +public class RandomTest +{ + + public static void main(String[] args) + { + // Math.random()方法 + for (int i = 0; i < 10; i++) + { + System.out.print((int) (Math.random() * 100) + " "); + } + System.out.println(); + + // 不带种子,每次的随机数不同 + Random rand = new Random(); + for (int i = 0; i < 10; i++) + { + System.out.print(rand.nextInt(100) + " "); + } + System.out.println(); + + // 带种子,每次的随机数相同 + Random rand2 = new Random(10); + for (int i = 0; i < 10; i++) + { + System.out.print(rand2.nextInt(100) + " "); + } + System.out.println(); + + // 生成完全不重复的随机数 + SecureRandom random = new SecureRandom(); + for (int i = 0; i < 10; i++) + { + System.out.print(random.nextInt(100) + " "); + } + System.out.println(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/StackTraceElementTest.java b/basicKnowledge/src/com/xdc/basic/api/StackTraceElementTest.java new file mode 100644 index 00000000..0eeab909 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/StackTraceElementTest.java @@ -0,0 +1,69 @@ +package com.xdc.basic.api; + +/** + * java栈跟踪元素(StackTraceElement)用法示例 + * + * @author xdc + * + */ + +/* + * 1.获取当前运行代码的类名,方法名,行号,主要是通过java.lang.StackTraceElement类 + * + * 2. [1]获得调用者的方法名, 同new Throwable String _methodName = new + * Exception().getStackTrace()[1].getMethodName(); [0]获得当前的方法名, 同new Throwable + * String _thisMethodName = new Exception().getStackTrace()[0].getMethodName(); + */ + +/* + * 原理:使用getStackTrace()查明异常, 它位于Throwable类中。 + * getStackTrace()返回Throwable对象被创建时所创建的StackTraceElement对象的一个数组。 + * 查询这些StackTraceElements可以准确地找出错误发生在什么地方。 对于调用getStackTrace() + * 时被调用的每个方法,返回的数组包含与它们相应的一个元素,另外返回的数组还包含一个元素来表明发出调用的代码。 数组的第一个元素指出抛出最初异常的方法。 + */ +public class StackTraceElementTest +{ + public static void main(String[] args) + { + System.out.println("line1: " + new Throwable().getStackTrace()[0].getLineNumber()); + System.out.println("line2: " + getLineInfo()); + System.out.println("line3: " + getTraceInfo()); + + // output all related info of the existing stack traces + StackTraceElement[] steArray = Thread.currentThread().getStackTrace(); + int steArrayLength = steArray.length; + if (steArrayLength == 0) + { + System.err.println("No Stack Trace."); + } + else + { + for (int i = 0; i < steArrayLength; i++) + { + System.out.println("Stack Trace-" + i); + StackTraceElement ste = steArray[i]; + String s = ste.getFileName() + ": Line " + ste.getLineNumber(); + System.out.println(s); + } + } + } + + public static String getTraceInfo() + { + StringBuffer sb = new StringBuffer(); + + // 返回的数据组大小为2: [0] getTraceInfo(), [1] main() + StackTraceElement[] stacks = new Throwable().getStackTrace(); + + sb.append("class: ").append(stacks[1].getClassName()).append("; method: ").append(stacks[1].getMethodName()) + .append("; number: ").append(stacks[1].getLineNumber()); + + return sb.toString(); + } + + public static String getLineInfo() + { + StackTraceElement ste = new Throwable().getStackTrace()[1]; + return ste.getFileName() + ": Line " + ste.getLineNumber(); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/URLTest.java b/basicKnowledge/src/com/xdc/basic/api/URLTest.java new file mode 100644 index 00000000..ea7ac94f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/URLTest.java @@ -0,0 +1,44 @@ +package com.xdc.basic.api; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; + +public class URLTest +{ + public static void main(String[] args) + { + String url = "name = xdc"; + System.out.println(url); + + String en = encodeUrl(url); + System.out.println(en); + + String de = decode(en); + System.out.println(de); + } + + public static String encodeUrl(String url) + { + try + { + return URLEncoder.encode(url, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + return url; + } + } + + public static String decode(String url) + { + try + { + return URLDecoder.decode(url, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + return url; + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/BeanUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/BeanUtilsTest.java new file mode 100644 index 00000000..334a8b24 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/BeanUtilsTest.java @@ -0,0 +1,77 @@ +package com.xdc.basic.api.apache.commons.beanutils; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.beanutils.BeanUtils; +import org.junit.Test; + +/** + * bean必须实现get和set方法。 + * + * @author xdc + * + */ +public class BeanUtilsTest +{ + /** + * 把orig中的值copy到dest中。 + * + * @throws Exception + */ + @Test + public void testCopyProperties() throws Exception + { + Person origPerson = new Person("xdc", 21, false, new Date()); + Person destPerson = new Person(); + BeanUtils.copyProperties(destPerson, origPerson); + } + + /** + * 设置Bean对象的名称为name的property的值为value. + * + * @throws Exception + */ + @Test + public void testSetProperty() throws Exception + { + Person person = new Person(); + BeanUtils.setProperty(person, "name", "xdc"); + BeanUtils.setProperty(person, "age", 25); + BeanUtils.setProperty(person, "smoker", false); + BeanUtils.setProperty(person, "birth", new Date()); + } + + /** + * 把Bean的属性值放入到一个Map里面。 + * + * @throws Exception + */ + @Test + public void testDescribe() throws Exception + { + Person person = new Person("xdc", 21, false, new Date()); + + @SuppressWarnings({ "unchecked", "unused" }) + Map map = BeanUtils.describe(person); + } + + /** + * 把map中的properties里面的值放入bean中。 + * + * @throws Exception + */ + @Test + public void testPopulate() throws Exception + { + Map map = new HashMap(); + map.put("name", "xdc"); + map.put("age", 25); + map.put("birth", new Date()); + + Person person = new Person(); + BeanUtils.populate(person, map); + System.out.println(person); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/Person.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/Person.java new file mode 100644 index 00000000..c799dd59 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/Person.java @@ -0,0 +1,73 @@ +package com.xdc.basic.api.apache.commons.beanutils; + +import java.util.Date; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class Person +{ + String name; + int age; + boolean smoker; + Date birth; + + public Person() + { + } + + public Person(String name, int age, boolean smoker, Date birth) + { + super(); + this.name = name; + this.age = age; + this.smoker = smoker; + this.birth = birth; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public int getAge() + { + return age; + } + + public void setAge(int age) + { + this.age = age; + } + + public boolean isSmoker() + { + return smoker; + } + + public void setSmoker(boolean smoker) + { + this.smoker = smoker; + } + + public Date getBirth() + { + return birth; + } + + public void setBirth(Date birth) + { + this.birth = birth; + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/PropertyUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/PropertyUtilsTest.java new file mode 100644 index 00000000..5e17eecd --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/beanutils/PropertyUtilsTest.java @@ -0,0 +1,34 @@ +package com.xdc.basic.api.apache.commons.beanutils; + +public class PropertyUtilsTest +{ + // 除BeanUtils外还有一个名为PropertyUtils的工具类,它也提供copyProperties()方法, + // 作用与BeanUtils的同名方法十分相似,主要的区别在于后者提供类型转换功能, + // 即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换, + // 而前者不支持这个功能,但是速度会更快一些。BeanUtils支持的转换类型如下: + // + // java.lang.BigDecimal + // java.lang.BigInteger + // boolean and java.lang.Boolean + // byte and java.lang.Byte + // char and java.lang.Character + // java.lang.Class + // double and java.lang.Double + // float and java.lang.Float + // int and java.lang.Integer + // long and java.lang.Long + // short and java.lang.Short + // java.lang.String + // java.sql.Date + // java.sql.Time + // java.sql.Timestamp + // + // 这里要注意一点,java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。 + // 因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。 + // 否则在转换时会提示argument mistype异常。 + + public static void main(String[] args) + { + // 大部分与BeanUtil类似,用时再研究 + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/Base64Test.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/Base64Test.java new file mode 100644 index 00000000..b29c1481 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/Base64Test.java @@ -0,0 +1,139 @@ +package com.xdc.basic.api.apache.commons.codec.binary; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.StringUtils; + +/** + * 为什么要使用Base64? + * + * 在设计这个编码的时候,我想设计人员最主要考虑了3个问题: + * 1.是否加密? + * 2.加密算法复杂程度和效率 + * 3.如何处理传输? + * + * 加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是“防君子不防小人”。即达到一眼望去完全看不出内容即可。 + * 基于这个目的加密算法的复杂程度和效率也就不能太大和太低。和上一个理由类似,MIME协议等用于发送Email的协议解决的是如何收发Email, + * 而并不是如何安全的收发Email。因此算法的复杂程度要小,效率要高,否则因为发送Email而大量占用资源,路就有点走歪了。 + * + * 但是,如果是基于以上两点,那么我们使用最简单的恺撒法即可,为什么Base64看起来要比恺撒法复杂呢?这是因为在Email的传送过程中,由于历史原因, + * Email只被允许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通过有“历史问题 + * ”的网关时就可能会出现问题。网关可能会把最高位置为0!很明显,问题就这样产生了!因此,为了能够正常的传送Email,这个问题就必须考虑!所以, + * 单单靠改变字母的位置的恺撒之类的方案也就不行了。关于这一点可以参考RFC2046。 + * 基于以上的一些主要原因产生了Base64编码。 + * + * @author xdc + * + */ +public class Base64Test +{ + public static final String UTF8 = "UTF-8"; // UTF8和UTF-8一样 + public static final String GBK = "GBK"; // 迅雷要用这个 + + private static final Base64 base64 = new Base64(); + + public static void main(String[] args) + { + String plainText = "I love you, but couldn't let you know. So, encode this. --徐大超 "; + System.out.println("plainText: " + plainText); + + // 加密 + String encodeStr = encodeStr(plainText, UTF8); + System.out.println("encodeStr: " + encodeStr); + + // 解密 + String decodeStr = decodeStr(encodeStr, UTF8); + System.out.println("decodeStr: " + decodeStr); + + System.out.println("plainText==decodeStr? : " + plainText.equals(decodeStr)); + + // 简单方式,流程如上 + encodeStr = Base64.encodeBase64String(StringUtils.getBytesUtf8(plainText)); + System.out.println("encodeStr: " + encodeStr); + decodeStr = StringUtils.newStringUtf8(Base64.decodeBase64(encodeStr)); + System.out.println("decodeStr: " + decodeStr); + System.out.println("plainText==decodeStr? : " + plainText.equals(decodeStr)); + + System.out.println("字符集名称:"); + for (String charsetName : Charset.availableCharsets().keySet()) + { + System.out.println(charsetName); + } + } + + /** + * 使用Base64加密 + * + * @param plainText + * @return + */ + public static String encodeStr(String plainText, String charsetName) + { + byte[] b = string2Bytes(plainText, charsetName); + b = base64.encode(b); + return bytes2String(b, charsetName); + } + + /** + * 使用Base64解密 + * + * @param encodeStr + * @return + */ + public static String decodeStr(String encodeStr, String charsetName) + { + byte[] b = string2Bytes(encodeStr, charsetName); + b = base64.decode(b); + return bytes2String(b, charsetName); + } + + /** + * 根据指定编码将字符串转换成字节数组 + * + * @param plainText + * @param charsetName + * @return + */ + private static byte[] string2Bytes(String plainText, String charsetName) + { + // apache提供了专门的方法去获取字符串的utf8编码的字节数组 + // return StringUtils.getBytesUtf8(plainText); + + byte[] b = null; + try + { + b = plainText.getBytes(charsetName); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + return b; + } + + /** + * 根据指定编码将字节数组转换成字符串 + * + * @param charsetName + * @param b + * @return + */ + private static String bytes2String(byte[] b, String charsetName) + { + // apache提供了专门的方法从字节数组转换成utf8编码的字符串 + // return StringUtils.newStringUtf8(b); + + String s = null; + try + { + s = new String(b, charsetName); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + return s; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/BinaryCodecTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/BinaryCodecTest.java new file mode 100644 index 00000000..c62baad6 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/BinaryCodecTest.java @@ -0,0 +1,27 @@ +package com.xdc.basic.api.apache.commons.codec.binary; + +import org.apache.commons.codec.binary.BinaryCodec; +import org.apache.commons.codec.binary.StringUtils; + +public class BinaryCodecTest +{ + public static void main(String[] args) + { + // raw 生的;未加工的;阴冷的;刺痛的 + byte[] raw = StringUtils.getBytesUtf8("You're my baby!"); + + // 将字节数组编码为0、1字符串, 不知道为啥结果原始数组的倒序 + byte[] asciiBytes = BinaryCodec.toAsciiBytes(raw); + char[] asciiChars = BinaryCodec.toAsciiChars(raw); + String asciiString = BinaryCodec.toAsciiString(raw); + + // 将0、1字符串为字节数组编码 + byte[] raw1 = BinaryCodec.fromAscii(asciiBytes); + byte[] raw2 = BinaryCodec.fromAscii(asciiChars); + byte[] raw3 = BinaryCodec.fromAscii(asciiString.toCharArray()); + + System.out.println(raw1); + System.out.println(raw2); + System.out.println(raw3); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/HexTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/HexTest.java new file mode 100644 index 00000000..de6fc279 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/binary/HexTest.java @@ -0,0 +1,29 @@ +package com.xdc.basic.api.apache.commons.codec.binary; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.binary.StringUtils; + +public class HexTest +{ + public static void main(String[] args) + { + byte[] raw = StringUtils.getBytesUtf8("You're my baby!"); + + char[] encodeHex = Hex.encodeHex(raw); + String encodeHexString = Hex.encodeHexString(raw); + + try + { + byte[] decodeHex = Hex.decodeHex(encodeHex); + byte[] decodeHexString = Hex.decodeHex(encodeHexString.toCharArray()); + + System.out.println(StringUtils.newStringUtf8(decodeHex)); + System.out.println(StringUtils.newStringUtf8(decodeHexString)); + } + catch (DecoderException e) + { + e.printStackTrace(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/digest/DigestUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/digest/DigestUtilsTest.java new file mode 100644 index 00000000..d8408acb --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/digest/DigestUtilsTest.java @@ -0,0 +1,47 @@ +package com.xdc.basic.api.apache.commons.codec.digest; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.codec.digest.DigestUtils; + +import com.xdc.basic.skills.GetCurPath; + +public class DigestUtilsTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + + File file = new File(curPath + "data.txt"); + + InputStream inputMd5 = null; + InputStream inputSha1 = null; + InputStream inputSha256 = null; + + String md5Hex; + try + { + // 算法强度小于sha1 + inputMd5 = new FileInputStream(file); + md5Hex = DigestUtils.md5Hex(inputMd5); + System.out.println("MD5值:" + md5Hex); + + // 算法强度小于sha256 + inputSha1 = new FileInputStream(file); + String sha1Hex = DigestUtils.sha1Hex(inputSha1); + System.out.println("SHA1值:" + sha1Hex); + + inputSha256 = new FileInputStream(file); + String sha256Hex = DigestUtils.sha256Hex(inputSha256); + System.out.println("SHA256值:" + sha256Hex); + } + catch (IOException e) + { + e.printStackTrace(); + } + + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/digest/data.txt b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/digest/data.txt new file mode 100644 index 00000000..5d1f3c4d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/codec/digest/data.txt @@ -0,0 +1 @@ +You're my baby! \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/collections/CollectionUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/collections/CollectionUtilsTest.java new file mode 100644 index 00000000..1523d790 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/collections/CollectionUtilsTest.java @@ -0,0 +1,55 @@ +package com.xdc.basic.api.apache.commons.collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.beanutils.BeanPropertyValueEqualsPredicate; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; + +public class CollectionUtilsTest +{ + @SuppressWarnings("unchecked") + public static void main(String[] args) + { + + String[] arrayA = new String[] { "1", "2", "3", "3", "4", "5" }; + String[] arrayB = new String[] { "3", "4", "4", "5", "6", "7" }; + List a = Arrays.asList(arrayA); + List b = Arrays.asList(arrayB); + + // 并集 + Collection union = CollectionUtils.union(a, b); + // 交集 + Collection intersection = CollectionUtils.intersection(a, b); + // 交集的补集 + Collection disjunction = CollectionUtils.disjunction(a, b); + // 集合相减 + Collection subtract = CollectionUtils.subtract(a, b); + + // 排序 + Collections.sort((List) union); + Collections.sort((List) intersection); + Collections.sort((List) disjunction); + Collections.sort((List) subtract); + + System.out.println("A: " + ArrayUtils.toString(a.toArray())); + System.out.println("B: " + ArrayUtils.toString(b.toArray())); + System.out.println("--------------------------------------------"); + System.out.println("Union(A, B): " + ArrayUtils.toString(union.toArray())); + System.out.println("Intersection(A, B): " + ArrayUtils.toString(intersection.toArray())); + System.out.println("Disjunction(A, B): " + ArrayUtils.toString(disjunction.toArray())); + System.out.println("Subtract(A, B): " + ArrayUtils.toString(subtract.toArray())); + + // 查找 + List persons = new ArrayList(); + persons.add(new Person("xudachao", 25, false)); + persons.add(new Person("gengxue", 24, false)); + Person person = (Person) CollectionUtils.find(persons, new BeanPropertyValueEqualsPredicate("name", "xudachao", + true)); + System.out.println(person); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/collections/Person.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/collections/Person.java new file mode 100644 index 00000000..085e96b9 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/collections/Person.java @@ -0,0 +1,55 @@ +package com.xdc.basic.api.apache.commons.collections; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class Person +{ + String name; + int age; + boolean smoker; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public int getAge() + { + return age; + } + + public void setAge(int age) + { + this.age = age; + } + + public boolean isSmoker() + { + return smoker; + } + + public void setSmoker(boolean smoker) + { + this.smoker = smoker; + } + + public Person(String name, int age, boolean smoker) + { + super(); + this.name = name; + this.age = age; + this.smoker = smoker; + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/configuration/ConfigurationLogListener.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/configuration/ConfigurationLogListener.java new file mode 100644 index 00000000..08144c2a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/configuration/ConfigurationLogListener.java @@ -0,0 +1,26 @@ +package com.xdc.basic.api.apache.commons.configuration; + +import org.apache.commons.configuration.event.ConfigurationEvent; +import org.apache.commons.configuration.event.ConfigurationListener; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class ConfigurationLogListener implements ConfigurationListener +{ + // 常量列表,蛋疼的api + // PropertiesConfiguration.EVENT_ADD_PROPERTY 1 + // PropertiesConfiguration.EVENT_CLEAR_PROPERTY 2 + // PropertiesConfiguration.EVENT_SET_PROPERTY 3 + // PropertiesConfiguration.EVENT_CLEAR 4 + // PropertiesConfiguration.EVENT_READ_PROPERTY 5 + // PropertiesConfiguration.EVENT_RELOAD 20 + // PropertiesConfiguration.EVENT_CONFIG_CHANGED 21 + + @Override + public void configurationChanged(ConfigurationEvent event) + { + // only display events after the modification was done + System.out.println("Received event! " + + ToStringBuilder.reflectionToString(event, ToStringStyle.MULTI_LINE_STYLE)); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/configuration/PropertiesConfigurationTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/configuration/PropertiesConfigurationTest.java new file mode 100644 index 00000000..1d7b25b4 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/configuration/PropertiesConfigurationTest.java @@ -0,0 +1,44 @@ +package com.xdc.basic.api.apache.commons.configuration; + +import java.util.Date; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; + +/** + * PropertiesConfiguration 这个类在内存中有缓存,设置文件改变策略后,当文件变化时会重新读取属性文件刷新内存 + * + * @author xdc + * + */ +public class PropertiesConfigurationTest +{ + public static void main(String[] args) throws ConfigurationException, InterruptedException + { + PropertiesConfiguration config = new PropertiesConfiguration(); + config.setReloadingStrategy(new FileChangedReloadingStrategy()); + config.addConfigurationListener(new ConfigurationLogListener()); + config.setEncoding("UTF-8"); + config.setFileName("src/common-logging.properties"); + + // 读取属性 + String log = config.getString("org.apache.commons.logging.Log"); + System.out.println("当前使用的日志: " + log); + + // 设置内存属性 + config.setProperty("org.apache.commons.logging.Log", "otherLog"); + + // 写入文件 + config.save(); + + // 下面不停地打印配置,验证设置的更改策略 + while (true) + { + String curLog = config.getString("org.apache.commons.logging.Log"); + System.out.println("当前使用的日志: " + curLog + " 时间: " + new Date()); + + Thread.sleep(1000L); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/exec/ExecTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/exec/ExecTest.java new file mode 100644 index 00000000..8cb0c563 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/exec/ExecTest.java @@ -0,0 +1,87 @@ +package com.xdc.basic.api.apache.commons.exec; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecuteResultHandler; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.PumpStreamHandler; + +public class ExecTest +{ + public static void main(String[] args) + { + String line = "ping 127.0.0.1"; + CommandLine cmdLine = CommandLine.parse(line); + + DefaultExecutor executor = getExecutor(); + + ByteArrayOutputStream outAndErr = new ByteArrayOutputStream(); // 设置输出流和错误流 + ByteArrayInputStream input = new ByteArrayInputStream("y".getBytes()); // 设置输入流,比如删除文件要确认,当让这个例子用不到 + executor.setStreamHandler(new PumpStreamHandler(outAndErr, outAndErr, input)); + + try + { + System.out.println("同步调用开始。"); + int exitValue = executor.execute(cmdLine); + System.out.println("同步调用结束。"); + System.out.println("同步调用返回值:" + exitValue); + + System.out.println("异步调用开始。"); + DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler(); + executor.execute(cmdLine, resultHandler); + System.out.println("异步调用结束。"); + + // 当前线程阻塞,直到命令行执行完成 + System.out.println("等待异步调用结果。"); + resultHandler.waitFor(); + exitValue = resultHandler.getExitValue(); + System.out.println("异步调用返回值:" + exitValue); + } + catch (ExecuteException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + + try + { + // 获取cmd.exe的编码,打开命令行后能在属性里看到的。 + String cmdEncoding = System.getProperty("sun.jnu.encoding"); + byte[] buf = outAndErr.toByteArray(); + String string = new String(buf, cmdEncoding); + // 这里会输出两次结果,因为同步异步各执行了一次,因此说明执行命令后要及时取出,免得混淆,或者干脆新建DefaultExecutor和ByteArrayOutputStream + System.out.println(string); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + } + + private static DefaultExecutor getExecutor() + { + DefaultExecutor executor = new DefaultExecutor(); + + // 设置超时时间,超时后,kill执行命令行的进程,再抛异常ExecuteException + ExecuteWatchdog watchdog = new ExecuteWatchdog(20 * 1000L); + executor.setWatchdog(watchdog); + + // 设置期望返回值,不符合抛异常ExecuteException + executor.setExitValue(0); + + return executor; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FileSystemUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FileSystemUtilsTest.java new file mode 100644 index 00000000..995e912e --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FileSystemUtilsTest.java @@ -0,0 +1,25 @@ +package com.xdc.basic.api.apache.commons.io; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileSystemUtils; +import org.apache.commons.io.FileUtils; + +public class FileSystemUtilsTest +{ + public static void main(String[] args) + { + try + { + String path = new File(".").getAbsolutePath(); + long freeSpaceKb = FileSystemUtils.freeSpaceKb(path, 5000L); + System.out.println(freeSpaceKb + "KB"); + System.out.println(FileUtils.byteCountToDisplaySize(freeSpaceKb * FileUtils.ONE_KB)); + } + catch (IOException e) + { + e.printStackTrace(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FileUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FileUtilsTest.java new file mode 100644 index 00000000..b5952e39 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FileUtilsTest.java @@ -0,0 +1,51 @@ +package com.xdc.basic.api.apache.commons.io; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +import org.apache.commons.io.Charsets; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.CanReadFileFilter; +import org.apache.commons.io.filefilter.IOFileFilter; +import org.apache.commons.lang.SystemUtils; + +import com.xdc.basic.skills.GetCurPath; + +public class FileUtilsTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + + File fromFile = FileUtils.getFile(curPath + "from.txt"); + File toFile = FileUtils.getFile(curPath + "to.txt"); + + // 列出指定目录的所有目录和文件 + IOFileFilter fileFilter = CanReadFileFilter.CAN_READ; + IOFileFilter dirFilter = CanReadFileFilter.READ_ONLY; + // IOFileFilter fileFilter = TrueFileFilter.INSTANCE; + // IOFileFilter dirFilter = FalseFileFilter.INSTANCE; + + Collection listFilesAndDirs = FileUtils.listFilesAndDirs(new File(curPath), fileFilter, dirFilter); + System.out.println(listFilesAndDirs); + + try + { + String fileString = FileUtils.readFileToString(fromFile, Charsets.UTF_8); + FileUtils.writeStringToFile(toFile, fileString, Charsets.UTF_8, false); + + List lines = FileUtils.readLines(fromFile, Charsets.UTF_8); + FileUtils.writeLines(toFile, "UTF-8", lines, SystemUtils.LINE_SEPARATOR, false); + + // linux下的touch命令 + FileUtils.touch(toFile); + } + catch (IOException e) + { + e.printStackTrace(); + } + + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FilenameUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FilenameUtilsTest.java new file mode 100644 index 00000000..bec36bbd --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/FilenameUtilsTest.java @@ -0,0 +1,26 @@ +package com.xdc.basic.api.apache.commons.io; + +import org.apache.commons.io.FilenameUtils; + +public class FilenameUtilsTest +{ + public static void main(String[] args) + { + // C:\\dev\\project\\file.txt + // the prefix - C:\ + // the path - dev\project\ + // the full path - C:\dev\project\ + // the name - file.txt + // the base name - file + // the extension - txt + + String fileName = "C:\\dev\\project\\file.txt"; + + FilenameUtils.getPrefix(fileName); + FilenameUtils.getPath(fileName); + FilenameUtils.getFullPath(fileName); + FilenameUtils.getName(fileName); + FilenameUtils.getBaseName(fileName); + FilenameUtils.getExtension(fileName); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/IOUitlsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/IOUitlsTest.java new file mode 100644 index 00000000..ed9eccc1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/IOUitlsTest.java @@ -0,0 +1,19 @@ +package com.xdc.basic.api.apache.commons.io; + +public class IOUitlsTest +{ + public static void main(String[] args) + { + // 使用时在具体研究,大部分方法和FileUtils重复 + + // IOUtils.read(input, buffer, offset, length); + // IOUtils.write(data, output); + // + // IOUtils.readLines(input, encoding); + // IOUtils.writeLines(lines, lineEnding, output, encoding); + // + // IOUtils.toByteArray(input); + // + // IOUtils.closeQuietly(input); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/from.txt b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/from.txt new file mode 100644 index 00000000..d68dd403 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/from.txt @@ -0,0 +1,4 @@ +a +b +c +d diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/input/MyTailerListener.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/input/MyTailerListener.java new file mode 100644 index 00000000..b40ee83c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/input/MyTailerListener.java @@ -0,0 +1,11 @@ +package com.xdc.basic.api.apache.commons.io.input; + +import org.apache.commons.io.input.TailerListenerAdapter; + +public class MyTailerListener extends TailerListenerAdapter +{ + public void handle(String line) + { + System.out.println(line); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/input/TailerTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/input/TailerTest.java new file mode 100644 index 00000000..66724c1c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/input/TailerTest.java @@ -0,0 +1,30 @@ +package com.xdc.basic.api.apache.commons.io.input; + +import java.io.File; + +import org.apache.commons.io.input.Tailer; + +import com.xdc.basic.skills.GetCurPath; + +public class TailerTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + + Tailer tailer = Tailer.create(new File(curPath + "from.txt"), new MyTailerListener()); + + try + { + Thread.sleep(100000L); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + finally + { + tailer.stop(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/monitor/FileListener.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/monitor/FileListener.java new file mode 100644 index 00000000..d2a4b4b7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/monitor/FileListener.java @@ -0,0 +1,60 @@ +package com.xdc.basic.api.apache.commons.io.monitor; + +import java.io.File; +import java.text.MessageFormat; + +import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; +import org.apache.commons.io.monitor.FileAlterationObserver; + +public class FileListener extends FileAlterationListenerAdaptor +{ + private static int checkConter = 0; + + @Override + public void onStart(FileAlterationObserver observer) + { + System.out.println(MessageFormat.format("目录改变第{0}次检查中...", ++checkConter)); + } + + @Override + public void onStop(FileAlterationObserver observer) + { + System.out.println(MessageFormat.format("目录改变第{0}次检查完成.", checkConter)); + } + + @Override + public void onDirectoryCreate(File directory) + { + System.out.println("fold: " + directory.getAbsolutePath() + " is created."); + } + + @Override + public void onDirectoryChange(File directory) + { + System.out.println("fold: " + directory.getAbsolutePath() + " is changed."); + } + + @Override + public void onDirectoryDelete(File directory) + { + System.out.println("fold: " + directory.getAbsolutePath() + " is deleted."); + } + + @Override + public void onFileCreate(File file) + { + System.out.println("file: " + file.getAbsolutePath() + " is created."); + } + + @Override + public void onFileChange(File file) + { + System.out.println("file: " + file.getAbsolutePath() + " is changed."); + } + + @Override + public void onFileDelete(File file) + { + System.out.println("file: " + file.getAbsolutePath() + " is deleted"); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/monitor/MonitorTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/monitor/MonitorTest.java new file mode 100644 index 00000000..09b71ccb --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/monitor/MonitorTest.java @@ -0,0 +1,35 @@ +package com.xdc.basic.api.apache.commons.io.monitor; + +import org.apache.commons.io.filefilter.FileFilterUtils; +import org.apache.commons.io.filefilter.HiddenFileFilter; +import org.apache.commons.io.filefilter.IOFileFilter; +import org.apache.commons.io.monitor.FileAlterationMonitor; +import org.apache.commons.io.monitor.FileAlterationObserver; + +public class MonitorTest +{ + public static void main(String[] args) throws Exception + { + // 构造过滤器,只监视可见目录和*.java文件 + IOFileFilter directories = FileFilterUtils.and(FileFilterUtils.directoryFileFilter(), HiddenFileFilter.VISIBLE); + IOFileFilter files = FileFilterUtils.and(FileFilterUtils.fileFileFilter(), + FileFilterUtils.suffixFileFilter(".java")); + IOFileFilter filter = FileFilterUtils.or(directories, files); + + //构造观察类主要提供要观察的文件或目录 + String directory = "src"; + FileAlterationObserver observer = new FileAlterationObserver(directory, filter); + + //构造收听类 没啥好说的 + FileListener listener = new FileListener(); + + //为观察对象添加收听对象 + observer.addListener(listener); + + //配置Monitor,第一个参数单位是毫秒,是监听的间隔;第二个参数就是绑定我们之前的观察对象。 + FileAlterationMonitor fileMonitor = new FileAlterationMonitor(5000, observer); + + //启动开始监听 + fileMonitor.start(); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/to.txt b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/to.txt new file mode 100644 index 00000000..d68dd403 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/io/to.txt @@ -0,0 +1,4 @@ +a +b +c +d diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/ArrayUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/ArrayUtilsTest.java new file mode 100644 index 00000000..ef36c20f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/ArrayUtilsTest.java @@ -0,0 +1,38 @@ +package com.xdc.basic.api.apache.commons.lang3; + +import org.apache.commons.lang3.ArrayUtils; + +/** + * 待整理 + * + * @author xdc + * + */ +public class ArrayUtilsTest +{ + @SuppressWarnings("unused") + public static void main(String[] args) + { + // 在ArrayUtils中public static final String[] EMPTY_STRING_ARRAY = new String[0]; + String[] EMPTY_STRING_ARRAY = ArrayUtils.EMPTY_STRING_ARRAY; + String[] strs = null; + String[] strs2 = new String[10]; + + // Checks if an array of primitive ints is empty or null. + System.out.println(ArrayUtils.isEmpty(EMPTY_STRING_ARRAY)); // true + System.out.println(ArrayUtils.isEmpty(strs)); // true + System.out.println(ArrayUtils.isEmpty(strs2)); // false + + strs = ArrayUtils.nullToEmpty(strs); + + // Compares two arrays, using equals(), handling multi-dimensional arrays correctly. + // Multi-dimensional primitive arrays are also handled correctly by this method. + ArrayUtils.isEquals(strs, EMPTY_STRING_ARRAY); + + int[] array = new int[5]; + // 基本数组 --> 对象数组 + Integer[] array2 = ArrayUtils.toObject(array); + // 对象数组 --> 基本数组 + int[] array3 = ArrayUtils.toPrimitive(array2); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/CharUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/CharUtilsTest.java new file mode 100644 index 00000000..7848d6cb --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/CharUtilsTest.java @@ -0,0 +1,25 @@ +package com.xdc.basic.api.apache.commons.lang3; + +import org.apache.commons.lang3.CharUtils; + +public class CharUtilsTest +{ + public static void main(String[] args) + { + char ch = 'a'; + + // Checks whether the character is ASCII 7 bit. + CharUtils.isAscii(ch); + + // 字母 + CharUtils.isAsciiAlpha(ch); + CharUtils.isAsciiAlphaLower(ch); + CharUtils.isAsciiAlphaUpper(ch); + + // 数字 + CharUtils.isAsciiNumeric(ch); + + // 字母或数字 + CharUtils.isAsciiAlphanumeric(ch); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/ObjectUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/ObjectUtilsTest.java new file mode 100644 index 00000000..85b68ef1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/ObjectUtilsTest.java @@ -0,0 +1,32 @@ +package com.xdc.basic.api.apache.commons.lang3; + +import org.apache.commons.lang3.ObjectUtils; + +public class ObjectUtilsTest +{ + public static void main(String[] args) + { + System.out.println("Returns a default value if the object passed is null."); + Object obj = null; + System.out.println(ObjectUtils.defaultIfNull(obj, "空")); + System.out.println(); + + /* + ObjectUtils.equals(null, null) = true + ObjectUtils.equals(null, "") = false + ObjectUtils.equals("", null) = false + ObjectUtils.equals("", "") = true + ObjectUtils.equals(Boolean.TRUE, null) = false + ObjectUtils.equals(Boolean.TRUE, "true") = false + ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE) = true + ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false + */ + System.out.println("Compares two objects for equality, where either one or both objects may be null."); + Object a = new Object(); + Object b = a; + Object c = new Object(); + System.out.println(ObjectUtils.equals(a, b)); + System.out.println(ObjectUtils.equals(a, c)); + System.out.println(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/RandomStringUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/RandomStringUtilsTest.java new file mode 100644 index 00000000..083b05ce --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/RandomStringUtilsTest.java @@ -0,0 +1,26 @@ +package com.xdc.basic.api.apache.commons.lang3; + +import org.apache.commons.lang3.RandomStringUtils; + +/** + * 随机生成字符串 + * + * @author xdc + * + */ +public class RandomStringUtilsTest +{ + public static void main(String[] args) + { + // 生成6位随机ascii串 + System.out.println(RandomStringUtils.randomAscii(6)); + // 生成6位随机字母串 + System.out.println(RandomStringUtils.randomAlphabetic(6)); + // 生成6位随机字母数字串 + System.out.println(RandomStringUtils.randomAlphanumeric(6)); + // 生成6位随机数字串 + System.out.println(RandomStringUtils.randomNumeric(6)); + // 生成6位随机数字串,指定字符 + System.out.println(RandomStringUtils.random(6, "xdc0209")); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/SerializationUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/SerializationUtilsTest.java new file mode 100644 index 00000000..6b49f5fb --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/SerializationUtilsTest.java @@ -0,0 +1,59 @@ +package com.xdc.basic.api.apache.commons.lang3; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.util.Date; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.SerializationUtils; + +import com.xdc.basic.skills.GetCurPath; + +public class SerializationUtilsTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + + // ========================================================================= + Date date = new Date(); + // Serializes an Object to a byte array for storage/serialization. + byte[] bytes = SerializationUtils.serialize(date); + System.out.println("date to bytes: " + ArrayUtils.toString(bytes)); + System.out.println("date: " + date); + + // Deserializes a single Object from an array of bytes. + Date reDate = (Date) SerializationUtils.deserialize(bytes); + System.out.println("reDate: " + reDate); + + System.out.println("ObjectUtils.equals(date, reDate): " + ObjectUtils.equals(date, reDate)); + System.out.println("date == reDate: " + (date == reDate)); + + // ========================================================================= + FileOutputStream fos = null; + FileInputStream fis = null; + try + { + fos = new FileOutputStream(new File(curPath + "test.txt")); + fis = new FileInputStream(new File(curPath + "test.txt")); + // Serializes an Object to the specified stream. + SerializationUtils.serialize(date, fos); + // Deserializes an Object from the specified stream. + Date reDate2 = (Date) SerializationUtils.deserialize(fis); + System.out.println("date.equals(reDate2): " + date.equals(reDate2)); + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + finally + { + IOUtils.closeQuietly(fos); + IOUtils.closeQuietly(fis); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/StringUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/StringUtilsTest.java new file mode 100644 index 00000000..fa4bc80f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/StringUtilsTest.java @@ -0,0 +1,53 @@ +package com.xdc.basic.api.apache.commons.lang3; + +import java.util.Locale; + +import org.apache.commons.lang3.StringUtils; + +/** + * 字符串常用操作 + * + * @author xdc + * + */ +public class StringUtilsTest +{ + public static void main(String[] args) + { + // 判断某字符串是否为空,为空的标准是 str==null 或 str.length()==0 + StringUtils.isEmpty(null); + StringUtils.isEmpty(""); + + // 判断某字符串是否为空或长度为0或由空白符(whitespace) 构成 + StringUtils.isBlank(null); + StringUtils.isBlank(""); + StringUtils.isBlank(" "); + StringUtils.isBlank("\t \n \f \r"); // 对于制表符、换行符、换页符和回车符 + + // 字符串变成小写,要设置区域,防止不同语言转换结果不一样,是程序有不一样的行为 + String name = "XuDachao"; + String lowerCaseName = StringUtils.lowerCase(name, Locale.US); + + // 比较两字符串是相等 + StringUtils.equals(lowerCaseName, name); // false + StringUtils.equals(lowerCaseName, "xudachao"); // true + + // 忽略大小写,比较字符串 + StringUtils.equalsIgnoreCase(lowerCaseName, name); // true + + String[] ips = StringUtils.split("127.0.0.1;10.10.10.10", ';'); + for (String ip : ips) + { + System.out.println(ip); + } + + // 获得之间的字符串 + StringUtils.substringBetween("name[xudachao]", "[", "]"); + + // 去除前缀 + StringUtils.removeStart("http://127.0.0.1", "http://"); + + // 去除前缀2 + StringUtils.substringAfter("http://127.0.0.1", "http://"); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/SystemUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/SystemUtilsTest.java new file mode 100644 index 00000000..99db5af3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/SystemUtilsTest.java @@ -0,0 +1,20 @@ +package com.xdc.basic.api.apache.commons.lang3; + +import org.apache.commons.lang3.SystemUtils; + +public class SystemUtilsTest +{ + public static void main(String[] args) + { + // 判断操作系统类型 + System.out.println(SystemUtils.IS_OS_LINUX); + System.out.println(SystemUtils.IS_OS_WINDOWS); + + // 换行符 + System.out.println(SystemUtils.LINE_SEPARATOR); + // 路径中的文件分隔符 + System.out.println(SystemUtils.FILE_SEPARATOR); + // 环境变量中的路径分隔符 + System.out.println(SystemUtils.PATH_SEPARATOR); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/BuilderTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/BuilderTest.java new file mode 100644 index 00000000..ee867316 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/BuilderTest.java @@ -0,0 +1,40 @@ +package com.xdc.basic.api.apache.commons.lang3.builder; + +public class BuilderTest +{ + public static void main(String[] args) + { + // Person ======================================== + Person person = new Person("xdc", 25, false); + Person person2 = new Person("xdc", 25, false); + Person person3 = new Person("gx", 25, false); + + System.out.println(person.equals(person2)); + System.out.println(person.equals(person3)); + + System.out.println(person.toString()); + System.out.println(person3.toString()); + + // PersonNotApache =============================== + PersonNotApache personNotApache = new PersonNotApache("xdc", 25, false); + System.out.println(personNotApache.toString()); + System.out.println(personNotApache.toString2()); + + // PersonReflection ============================== + PersonReflection personReflection = new PersonReflection("xdc", 25, false); + PersonReflection personReflection2 = new PersonReflection("xdc", 25, false); + PersonReflection personReflection3 = new PersonReflection("gx", 25, false); + + System.out.println(personReflection.equals(personReflection2)); + System.out.println(personReflection.equals(personReflection3)); + + System.out.println(personReflection.toString()); + System.out.println(personReflection3.toString()); + + // PersonReflectionToStringBuilder =============== + PersonReflectionToStringBuilder p = new PersonReflectionToStringBuilder("xdc", 25, false); + System.out.println(p.toString()); + System.out.println(p.toString2()); + System.out.println(p.toString3()); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/Person.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/Person.java new file mode 100644 index 00000000..1582c763 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/Person.java @@ -0,0 +1,82 @@ +package com.xdc.basic.api.apache.commons.lang3.builder; + +import org.apache.commons.lang3.builder.CompareToBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class Person implements Comparable +{ + String name; + int age; + boolean smoker; + + public Person(String name, int age, boolean smoker) + { + super(); + this.name = name; + this.age = age; + this.smoker = smoker; + } + + @Override + public int hashCode() + { + // you pick a hard-coded, randomly chosen, non-zero, odd number + // ideally different for each class + return new HashCodeBuilder(17, 37).append(name).append(age).append(smoker).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + Person that = (Person) obj; + return new EqualsBuilder().append(name, that.name).append(age, that.age).append(smoker, that.smoker).isEquals(); + } + + public boolean equals2(Object obj) + { + if (obj == this) + { + return true; + } + if (!(obj instanceof Person)) + { + return false; + } + Person that = (Person) obj; + return new EqualsBuilder().append(name, that.name).append(age, that.age).append(smoker, that.smoker).isEquals(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("name", name).append("age", age) + .append("smoker", smoker).toString(); + } + + // Two Objects that compare equal using equals(Object) should normally also + // compare equal using compareTo(Object). + // 先比较年龄,再比较姓名,再比较是否抽烟 + @Override + public int compareTo(Person o) + { + // 用不用判断null呢? + Person that = o; + return new CompareToBuilder().append(this.age, that.age).append(this.name, that.name) + .append(this.smoker, that.smoker).toComparison(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonNotApache.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonNotApache.java new file mode 100644 index 00000000..fdc397e9 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonNotApache.java @@ -0,0 +1,36 @@ +package com.xdc.basic.api.apache.commons.lang3.builder; + +public class PersonNotApache +{ + String name; + int age; + boolean smoker; + + public PersonNotApache(String name, int age, boolean smoker) + { + super(); + this.name = name; + this.age = age; + this.smoker = smoker; + } + + @Override + public String toString() + { + // eclipse 自动生成的 + return "PersonNotApache [name=" + name + ", age=" + age + ", smoker=" + smoker + "]"; + } + + public String toString2() + { + // 普通的方式,这种写法比eclipse生成的效率要高 + StringBuilder sb = new StringBuilder(); + sb.append(this.getClass().getSimpleName()); + sb.append(" [name=").append(name); + sb.append(", age=").append(age); + sb.append(", smoker=").append(smoker); + sb.append("]"); + + return sb.toString(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonReflection.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonReflection.java new file mode 100644 index 00000000..8a0f3de0 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonReflection.java @@ -0,0 +1,59 @@ +package com.xdc.basic.api.apache.commons.lang3.builder; + +import org.apache.commons.lang3.builder.CompareToBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * ReflectionToStringBuilder 继承自 ToStringBuilder,所以更加强大,具有排除功能 + * + * @author xdc + * + */ +public class PersonReflection implements Comparable +{ + String name; + int age; + boolean smoker; + + public PersonReflection(String name, int age, boolean smoker) + { + super(); + this.name = name; + this.age = age; + this.smoker = smoker; + } + + @Override + public int hashCode() + { + return HashCodeBuilder.reflectionHashCode(this); + // 根据反射获取hashcode ,除去某些字段 + // HashCodeBuilder.reflectionHashCode(this, new String[]{"age","smoker"}) + } + + @Override + public boolean equals(Object obj) + { + return EqualsBuilder.reflectionEquals(this, obj); + // 根据反射比较对象 ,除去某些字段 + // EqualsBuilder.reflectionEquals(this, obj, new String[]{"age","smoker"}); + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + // 不具有除去某些字段的功能,如果有需求请使用ReflectionToStringBuilder + } + + // Two Objects that compare equal using equals(Object) should normally also compare equal using compareTo(Object). + // 不推荐。由于该类涉及到比较字段的顺序,所以并不推荐使用该族中的方法自动映射字段,而最好自己决定那些字段参与比较及它们的顺序。该族方法的返回值为一整数,意义同Comparable接口的compareTo方法。 + @Override + public int compareTo(PersonReflection o) + { + return CompareToBuilder.reflectionCompare(this, o); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonReflectionToStringBuilder.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonReflectionToStringBuilder.java new file mode 100644 index 00000000..4562f26d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/builder/PersonReflectionToStringBuilder.java @@ -0,0 +1,39 @@ +package com.xdc.basic.api.apache.commons.lang3.builder; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class PersonReflectionToStringBuilder +{ + String name; + int age; + boolean smoker; + + public PersonReflectionToStringBuilder(String name, int age, boolean smoker) + { + super(); + this.name = name; + this.age = age; + this.smoker = smoker; + } + + @Override + public String toString() + { + return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE); + } + + public String toString2() + { + // 这个排除某些字段,但是不能指定风格 + return ReflectionToStringBuilder.toStringExclude(this, new String[] { "age", "smoker" }); + } + + public String toString3() + { + // 这个排除某些字段,又指定风格 + ReflectionToStringBuilder builder = new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + builder.setExcludeFieldNames(new String[] { "age", "smoker" }); + return builder.toString(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/math/NumberUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/math/NumberUtilsTest.java new file mode 100644 index 00000000..afec241c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/math/NumberUtilsTest.java @@ -0,0 +1,48 @@ +package com.xdc.basic.api.apache.commons.lang3.math; + +import org.apache.commons.lang3.math.NumberUtils; + +public class NumberUtilsTest +{ + public static void main(String[] args) + { + String str = "12345678901234567890"; + String str2 = "12345678901234567890.123"; + String str3 = "-12345678901234567890"; + String str4 = "0x12345678901234567890af"; + String str5 = "0x12345678901234567890aF"; + String str6 = "12345678901234567890L"; + String str7 = "12345678901234567890F"; + + // Checks whether the String contains only digit characters, [0-9]+. + // Null and empty String will return false. + System.out.println(NumberUtils.isDigits(str)); // true + System.out.println(NumberUtils.isDigits(str2)); // false + System.out.println(NumberUtils.isDigits(str3)); // false + System.out.println(NumberUtils.isDigits(str4)); // false + System.out.println(NumberUtils.isDigits(str5)); // false + System.out.println(NumberUtils.isDigits(str6)); // false + System.out.println(NumberUtils.isDigits(str7)); // false + + // Checks whether the String a valid Java number. + // Valid numbers include hexadecimal marked with the 0x qualifier, scientific notation and numbers marked with a type qualifier (e.g. 123L). + // Null and empty String will return false. + System.out.println(NumberUtils.isNumber(str)); // true + System.out.println(NumberUtils.isNumber(str2)); // true + System.out.println(NumberUtils.isNumber(str3)); // true + System.out.println(NumberUtils.isNumber(str4)); // true + System.out.println(NumberUtils.isNumber(str5)); // true + System.out.println(NumberUtils.isNumber(str6)); // true + System.out.println(NumberUtils.isNumber(str7)); // true + + int[] array = { 1, 2, 5, 3, 4 }; + // 获取数组最大值 + System.out.println(NumberUtils.max(array)); + + int a = 0; + int b = 2; + int c = 1; + // 获取参数最大值 + System.out.println(NumberUtils.max(a, b, c)); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/time/DateFormatUtilsTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/time/DateFormatUtilsTest.java new file mode 100644 index 00000000..f2bf1f26 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/time/DateFormatUtilsTest.java @@ -0,0 +1,15 @@ +package com.xdc.basic.api.apache.commons.lang3.time; + +import org.apache.commons.lang3.time.DateFormatUtils; + +public class DateFormatUtilsTest +{ + public static void main(String[] args) + { + System.out.println("本地格式日期输出:"); + System.out.println(DateFormatUtils.format(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss")); + + System.out.println("UTC格式日期输出:"); + System.out.println(DateFormatUtils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/time/StopWatchTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/time/StopWatchTest.java new file mode 100644 index 00000000..6988fa9e --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/lang3/time/StopWatchTest.java @@ -0,0 +1,59 @@ +package com.xdc.basic.api.apache.commons.lang3.time; + +import org.apache.commons.lang3.time.StopWatch; + +public class StopWatchTest +{ + + public static void main(String[] args) + { + /* + * NOTE: As from v2.1, the methods protect against inappropriate calls. + * Thus you cannot now call stop before start, resume before suspend or + * unsplit before split. if not, it throws IllegalStateException + * + * 1. split(), suspend(), or stop() cannot be invoked twice + * 2. unsplit() may only be called if the watch has been split() + * 3. resume() may only be called if the watch has been suspend() + * 4. start() cannot be called twice without calling reset() + */ + + System.out.println("秒表:"); + StopWatch sw = new StopWatch(); + + // 计时开始 + sw.start(); + doSomething(); + System.out.println("秒表计时(ms):" + sw.getTime()); + System.out.println("秒表计时(ns):" + sw.getNanoTime()); + + // 暂停计时 + sw.suspend(); + doSomething(); + System.out.println("秒表计时(ms):" + sw.getTime()); + System.out.println("秒表计时(ns):" + sw.getNanoTime()); + + // 恢复计时 + sw.resume(); + doSomething(); + System.out.println("秒表计时(ms):" + sw.getTime()); + System.out.println("秒表计时(ns):" + sw.getNanoTime()); + + // 计时结束 + sw.stop(); + System.out.println("秒表计时(ms):" + sw.getTime()); + System.out.println("秒表计时(ns):" + sw.getNanoTime()); + } + + private static void doSomething() + { + try + { + Thread.sleep(1000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/logging/LogTest.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/logging/LogTest.java new file mode 100644 index 00000000..2e6363d7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/logging/LogTest.java @@ -0,0 +1,77 @@ +package com.xdc.basic.api.apache.commons.logging; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class LogTest +{ + private static Log log = LogFactory.getLog(LogTest.class); + + public static void main(String[] args) + { + // log.isFatalEnabled(); // true + // log.isErrorEnabled(); // true + // log.isWarnEnabled(); // true + // log.isInfoEnabled(); // true + // log.isDebugEnabled(); // false + // log.isTraceEnabled(); // false + // + // log.fatal("fatal."); + // log.error("error."); + // log.warn("warn."); + // log.info("info"); + // log.debug("debug."); + // log.trace("trace."); + + List nums = new ArrayList(); + for (int i = 0; i < 2; i++) + { + nums.add(new Person("xdc-" + i, i, false)); + } + getTop3(nums); + } + + public static List getTop3(List nums) + { + log.info("Get top 3 bigin."); + List result = new ArrayList(); + result.addAll(nums); + + if (nums.size() < 3) + { + log.warn("The size of persons is " + nums.size() + " and < 3."); + } + + if (log.isDebugEnabled()) + { + log.debug("Persons are " + nums); + } + + Collections.sort(result, new Comparator() + { + @Override + public int compare(Person o1, Person o2) + { + return o2.age - o1.age; + } + }); + + if (result.size() > 3) + { + result = result.subList(0, 3); + } + + if (log.isDebugEnabled()) + { + log.debug("Top 3 of persons are " + result); + } + + log.info("Get top 3 end."); + return result; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/commons/logging/Person.java b/basicKnowledge/src/com/xdc/basic/api/apache/commons/logging/Person.java new file mode 100644 index 00000000..1218b182 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/commons/logging/Person.java @@ -0,0 +1,81 @@ +package com.xdc.basic.api.apache.commons.logging; + +import org.apache.commons.lang3.builder.CompareToBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class Person implements Comparable +{ + String name; + int age; + boolean smoker; + + public Person(String name, int age, boolean smoker) + { + super(); + this.name = name; + this.age = age; + this.smoker = smoker; + } + + @Override + public int hashCode() + { + // you pick a hard-coded, randomly chosen, non-zero, odd number + // ideally different for each class + return new HashCodeBuilder(17, 37).append(name).append(age).append(smoker).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + Person that = (Person) obj; + return new EqualsBuilder().append(name, that.name).append(age, that.age).append(smoker, that.smoker).isEquals(); + } + + public boolean equals2(Object obj) + { + if (obj == this) + { + return true; + } + if (!(obj instanceof Person)) + { + return false; + } + Person that = (Person) obj; + return new EqualsBuilder().append(name, that.name).append(age, that.age).append(smoker, that.smoker).isEquals(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("name", name).append("age", age) + .append("smoker", smoker).toString(); + } + + //Two Objects that compare equal using equals(Object) should normally also compare equal using compareTo(Object). + // 先比较年龄,再比较姓名,再比较是否抽烟 + @Override + public int compareTo(Object o) + { + // 用不用判断null呢? + Person that = (Person) o; + return new CompareToBuilder().append(this.age, that.age).append(this.name, that.name) + .append(this.smoker, that.smoker).toComparison(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientAbortMethod.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientAbortMethod.java new file mode 100644 index 00000000..02d5b48a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientAbortMethod.java @@ -0,0 +1,70 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package com.xdc.basic.api.apache.http.client; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; + +/** + * This example demonstrates how to abort an HTTP method before its normal completion. + */ +public class ClientAbortMethod { + + public final static void main(String[] args) throws Exception { + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + HttpGet httpget = new HttpGet("http://www.apache.org/"); + + System.out.println("executing request " + httpget.getURI()); + CloseableHttpResponse response = httpclient.execute(httpget); + try { + HttpEntity entity = response.getEntity(); + + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + if (entity != null) { + System.out.println("Response content length: " + entity.getContentLength()); + } + System.out.println("----------------------------------------"); + + // Do not feel like reading the response body + // Call abort on the request object + httpget.abort(); + } finally { + response.close(); + } + } finally { + httpclient.close(); + } + } + +} + diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientAuthentication.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientAuthentication.java new file mode 100644 index 00000000..45481b99 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientAuthentication.java @@ -0,0 +1,74 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import org.apache.http.HttpEntity; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +/** + * A simple example that uses HttpClient to execute an HTTP request against + * a target site that requires user authentication. + */ +public class ClientAuthentication { + + public static void main(String[] args) throws Exception { + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + new AuthScope("localhost", 443), + new UsernamePasswordCredentials("username", "password")); + CloseableHttpClient httpclient = HttpClients.custom() + .setDefaultCredentialsProvider(credsProvider).build(); + try { + HttpGet httpget = new HttpGet("https://localhost/protected"); + + System.out.println("executing request" + httpget.getRequestLine()); + CloseableHttpResponse response = httpclient.execute(httpget); + try { + HttpEntity entity = response.getEntity(); + + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + if (entity != null) { + System.out.println("Response content length: " + entity.getContentLength()); + } + EntityUtils.consume(entity); + } finally { + response.close(); + } + } finally { + httpclient.close(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientChunkEncodedPost.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientChunkEncodedPost.java new file mode 100644 index 00000000..e47200db --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientChunkEncodedPost.java @@ -0,0 +1,89 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import java.io.File; +import java.io.FileInputStream; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.InputStreamEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +/** + * Example how to use unbuffered chunk-encoded POST request. + */ +public class ClientChunkEncodedPost { + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.out.println("File path not given"); + System.exit(1); + } + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + HttpPost httppost = new HttpPost("http://localhost:8080" + + "/servlets-examples/servlet/RequestInfoExample"); + + File file = new File(args[0]); + + InputStreamEntity reqEntity = new InputStreamEntity( + new FileInputStream(file), -1); + reqEntity.setContentType("binary/octet-stream"); + reqEntity.setChunked(true); + // It may be more appropriate to use FileEntity class in this particular + // instance but we are using a more generic InputStreamEntity to demonstrate + // the capability to stream out data from any arbitrary source + // + // FileEntity entity = new FileEntity(file, "binary/octet-stream"); + + httppost.setEntity(reqEntity); + + System.out.println("executing request " + httppost.getRequestLine()); + CloseableHttpResponse response = httpclient.execute(httppost); + try { + HttpEntity resEntity = response.getEntity(); + + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + if (resEntity != null) { + System.out.println("Response content length: " + resEntity.getContentLength()); + System.out.println("Chunked?: " + resEntity.isChunked()); + } + EntityUtils.consume(resEntity); + } finally { + response.close(); + } + } finally { + httpclient.close(); + } + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientConnectionRelease.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientConnectionRelease.java new file mode 100644 index 00000000..22b3b832 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientConnectionRelease.java @@ -0,0 +1,86 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package com.xdc.basic.api.apache.http.client; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; + +/** + * This example demonstrates the recommended way of using API to make sure + * the underlying connection gets released back to the connection manager. + */ +public class ClientConnectionRelease { + + public final static void main(String[] args) throws Exception { + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + HttpGet httpget = new HttpGet("http://www.apache.org/"); + + // Execute HTTP request + System.out.println("executing request " + httpget.getURI()); + CloseableHttpResponse response = httpclient.execute(httpget); + try { + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + System.out.println("----------------------------------------"); + + // Get hold of the response entity + HttpEntity entity = response.getEntity(); + + // If the response does not enclose an entity, there is no need + // to bother about connection release + if (entity != null) { + InputStream instream = entity.getContent(); + try { + instream.read(); + // do something useful with the response + } catch (IOException ex) { + // In case of an IOException the connection will be released + // back to the connection manager automatically + throw ex; + } finally { + // Closing the input stream will trigger connection release + instream.close(); + } + } + } finally { + response.close(); + } + } finally { + httpclient.close(); + } + } + +} + diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientCustomContext.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientCustomContext.java new file mode 100644 index 00000000..b99b8797 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientCustomContext.java @@ -0,0 +1,92 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package com.xdc.basic.api.apache.http.client; + +import java.util.List; + +import org.apache.http.HttpEntity; +import org.apache.http.client.CookieStore; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +/** + * This example demonstrates the use of a local HTTP context populated with + * custom attributes. + */ +public class ClientCustomContext { + + public final static void main(String[] args) throws Exception { + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + // Create a local instance of cookie store + CookieStore cookieStore = new BasicCookieStore(); + + // Create local HTTP context + HttpClientContext localContext = HttpClientContext.create(); + // Bind custom cookie store to the local context + localContext.setCookieStore(cookieStore); + + HttpGet httpget = new HttpGet("http://www.google.com/"); + + System.out.println("executing request " + httpget.getURI()); + + // Pass local context as a parameter + CloseableHttpResponse response = httpclient.execute(httpget, localContext); + try { + HttpEntity entity = response.getEntity(); + + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + if (entity != null) { + System.out.println("Response content length: " + entity.getContentLength()); + } + List cookies = cookieStore.getCookies(); + for (int i = 0; i < cookies.size(); i++) { + System.out.println("Local cookie: " + cookies.get(i)); + } + + // Consume response content + EntityUtils.consume(entity); + + System.out.println("----------------------------------------"); + } finally { + response.close(); + } + } finally { + httpclient.close(); + } + } + +} + diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientCustomSSL.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientCustomSSL.java new file mode 100644 index 00000000..6be97892 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientCustomSSL.java @@ -0,0 +1,91 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import java.io.File; +import java.io.FileInputStream; +import java.security.KeyStore; + +import javax.net.ssl.SSLContext; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.ssl.SSLContexts; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +/** + * This example demonstrates how to create secure connections with a custom SSL + * context. + */ +public class ClientCustomSSL { + + public final static void main(String[] args) throws Exception { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + FileInputStream instream = new FileInputStream(new File("my.keystore")); + try { + trustStore.load(instream, "nopassword".toCharArray()); + } finally { + instream.close(); + } + SSLContext sslcontext = SSLContexts.custom() + .loadTrustMaterial(trustStore) + .build(); + + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, + SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + CloseableHttpClient httpclient = HttpClients.custom() + .setSSLSocketFactory(sslsf) + .build(); + try { + + HttpGet httpget = new HttpGet("https://localhost/"); + + System.out.println("executing request" + httpget.getRequestLine()); + + CloseableHttpResponse response = httpclient.execute(httpget); + try { + HttpEntity entity = response.getEntity(); + + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + if (entity != null) { + System.out.println("Response content length: " + entity.getContentLength()); + } + EntityUtils.consume(entity); + } finally { + response.close(); + } + } finally { + httpclient.close(); + } + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientEvictExpiredConnections.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientEvictExpiredConnections.java new file mode 100644 index 00000000..1c44c043 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientEvictExpiredConnections.java @@ -0,0 +1,136 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import java.util.concurrent.TimeUnit; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +/** + * Example demonstrating how to evict expired and idle connections + * from the connection pool. + */ +public class ClientEvictExpiredConnections { + + public static void main(String[] args) throws Exception { + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); + cm.setMaxTotal(100); + CloseableHttpClient httpclient = HttpClients.custom() + .setConnectionManager(cm).build(); + try { + // create an array of URIs to perform GETs on + String[] urisToGet = { + "http://jakarta.apache.org/", + "http://jakarta.apache.org/commons/", + "http://jakarta.apache.org/commons/httpclient/", + "http://svn.apache.org/viewvc/jakarta/httpcomponents/" + }; + + IdleConnectionEvictor connEvictor = new IdleConnectionEvictor(cm); + connEvictor.start(); + + for (int i = 0; i < urisToGet.length; i++) { + String requestURI = urisToGet[i]; + HttpGet request = new HttpGet(requestURI); + + System.out.println("executing request " + requestURI); + + CloseableHttpResponse response = httpclient.execute(request); + try { + HttpEntity entity = response.getEntity(); + + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + if (entity != null) { + System.out.println("Response content length: " + entity.getContentLength()); + } + System.out.println("----------------------------------------"); + + EntityUtils.consume(entity); + } finally { + response.close(); + } + } + + // Sleep 10 sec and let the connection evictor do its job + Thread.sleep(20000); + + // Shut down the evictor thread + connEvictor.shutdown(); + connEvictor.join(); + + } finally { + httpclient.close(); + } + } + + public static class IdleConnectionEvictor extends Thread { + + private final HttpClientConnectionManager connMgr; + + private volatile boolean shutdown; + + public IdleConnectionEvictor(HttpClientConnectionManager connMgr) { + super(); + this.connMgr = connMgr; + } + + @Override + public void run() { + try { + while (!shutdown) { + synchronized (this) { + wait(5000); + // Close expired connections + connMgr.closeExpiredConnections(); + // Optionally, close connections + // that have been idle longer than 5 sec + connMgr.closeIdleConnections(5, TimeUnit.SECONDS); + } + } + } catch (InterruptedException ex) { + // terminate + } + } + + public void shutdown() { + shutdown = true; + synchronized (this) { + notifyAll(); + } + } + + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientFormLogin.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientFormLogin.java new file mode 100644 index 00000000..938cfcaf --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientFormLogin.java @@ -0,0 +1,111 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.Consts; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +/** + * A example that demonstrates how HttpClient APIs can be used to perform + * form-based logon. + */ +public class ClientFormLogin { + + public static void main(String[] args) throws Exception { + BasicCookieStore cookieStore = new BasicCookieStore(); + CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build(); + try { + HttpGet httpget = new HttpGet("https://portal.sun.com/portal/dt"); + + CloseableHttpResponse response1 = httpclient.execute(httpget); + try { + HttpEntity entity = response1.getEntity(); + + System.out.println("Login form get: " + response1.getStatusLine()); + EntityUtils.consume(entity); + + System.out.println("Initial set of cookies:"); + List cookies = cookieStore.getCookies(); + if (cookies.isEmpty()) { + System.out.println("None"); + } else { + for (int i = 0; i < cookies.size(); i++) { + System.out.println("- " + cookies.get(i).toString()); + } + } + } finally { + response1.close(); + } + + HttpPost httpost = new HttpPost("https://portal.sun.com/amserver/UI/Login?" + + "org=self_registered_users&" + + "goto=/portal/dt&" + + "gotoOnFail=/portal/dt?error=true"); + List nvps = new ArrayList (); + nvps.add(new BasicNameValuePair("IDToken1", "username")); + nvps.add(new BasicNameValuePair("IDToken2", "password")); + + httpost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); + + CloseableHttpResponse response2 = httpclient.execute(httpost); + try { + HttpEntity entity = response2.getEntity(); + + System.out.println("Login form get: " + response2.getStatusLine()); + EntityUtils.consume(entity); + + System.out.println("Post logon cookies:"); + List cookies = cookieStore.getCookies(); + if (cookies.isEmpty()) { + System.out.println("None"); + } else { + for (int i = 0; i < cookies.size(); i++) { + System.out.println("- " + cookies.get(i).toString()); + } + } + } finally { + response2.close(); + } + } finally { + httpclient.close(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientInteractiveAuthentication.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientInteractiveAuthentication.java new file mode 100644 index 00000000..314cda25 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientInteractiveAuthentication.java @@ -0,0 +1,124 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.HttpStatus; +import org.apache.http.auth.AuthScheme; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.AuthState; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.RouteInfo; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +/** + * A simple example that uses HttpClient to execute an HTTP request against + * a target site that requires user authentication. + */ +public class ClientInteractiveAuthentication { + + public static void main(String[] args) throws Exception { + BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + CloseableHttpClient httpclient = HttpClients.custom() + .setDefaultCredentialsProvider(credsProvider).build(); + try { + // Create local execution context + HttpClientContext localContext = HttpClientContext.create(); + + HttpGet httpget = new HttpGet("http://localhost/test"); + + boolean trying = true; + while (trying) { + System.out.println("executing request " + httpget.getRequestLine()); + CloseableHttpResponse response = httpclient.execute(httpget, localContext); + try { + System.out.println("----------------------------------------"); + System.out.println(response.getStatusLine()); + + // Consume response content + HttpEntity entity = response.getEntity(); + EntityUtils.consume(entity); + + int sc = response.getStatusLine().getStatusCode(); + + RouteInfo route = localContext.getHttpRoute(); + AuthState authState = null; + HttpHost authhost = null; + if (sc == HttpStatus.SC_UNAUTHORIZED) { + // Target host authentication required + authState = localContext.getTargetAuthState(); + authhost = route.getTargetHost(); + } + if (sc == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) { + // Proxy authentication required + authState = localContext.getProxyAuthState(); + authhost = route.getProxyHost(); + } + + if (authState != null) { + System.out.println("----------------------------------------"); + AuthScheme authscheme = authState.getAuthScheme(); + System.out.println("Please provide credentials for " + + authscheme.getRealm() + "@" + authhost.toHostString()); + + BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); + + System.out.print("Enter username: "); + String user = console.readLine(); + System.out.print("Enter password: "); + String password = console.readLine(); + + if (user != null && user.length() > 0) { + Credentials creds = new UsernamePasswordCredentials(user, password); + credsProvider.setCredentials(new AuthScope(authhost), creds); + trying = true; + } else { + trying = false; + } + } else { + trying = false; + } + } finally { + response.close(); + } + } + } finally { + httpclient.close(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientWithRequestFuture.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientWithRequestFuture.java new file mode 100644 index 00000000..0fa233ae --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientWithRequestFuture.java @@ -0,0 +1,117 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import java.io.IOException; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.concurrent.FutureCallback; +import org.apache.http.impl.client.FutureRequestExecutionService; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpRequestFutureTask; + +public class ClientWithRequestFuture { + + public static void main(String[] args) throws Exception { + // the simplest way to create a HttpAsyncClientWithFuture + HttpClient httpclient = HttpClientBuilder.create() + .setMaxConnPerRoute(5) + .setMaxConnTotal(5).build(); + ExecutorService execService = Executors.newFixedThreadPool(5); + FutureRequestExecutionService requestExecService = new FutureRequestExecutionService( + httpclient, execService); + try { + // Because things are asynchronous, you must provide a ResponseHandler + ResponseHandler handler = new ResponseHandler() { + public Boolean handleResponse(HttpResponse response) throws ClientProtocolException, IOException { + // simply return true if the status was OK + return response.getStatusLine().getStatusCode() == 200; + } + }; + + // Simple request ... + HttpGet request1 = new HttpGet("http://google.com"); + HttpRequestFutureTask futureTask1 = requestExecService.execute(request1, + HttpClientContext.create(), handler); + Boolean wasItOk1 = futureTask1.get(); + System.out.println("It was ok? " + wasItOk1); + + // Cancel a request + try { + HttpGet request2 = new HttpGet("http://google.com"); + HttpRequestFutureTask futureTask2 = requestExecService.execute(request2, + HttpClientContext.create(), handler); + futureTask2.cancel(true); + Boolean wasItOk2 = futureTask2.get(); + System.out.println("It was cancelled so it should never print this: " + wasItOk2); + } catch (CancellationException e) { + System.out.println("We cancelled it, so this is expected"); + } + + // Request with a timeout + HttpGet request3 = new HttpGet("http://google.com"); + HttpRequestFutureTask futureTask3 = requestExecService.execute(request3, + HttpClientContext.create(), handler); + Boolean wasItOk3 = futureTask3.get(10, TimeUnit.SECONDS); + System.out.println("It was ok? " + wasItOk3); + + FutureCallback callback = new FutureCallback() { + public void completed(Boolean result) { + System.out.println("completed with " + result); + } + + public void failed(Exception ex) { + System.out.println("failed with " + ex.getMessage()); + } + + public void cancelled() { + System.out.println("cancelled"); + } + }; + + // Simple request with a callback + HttpGet request4 = new HttpGet("http://google.com"); + // using a null HttpContext here since it is optional + // the callback will be called when the task completes, fails, or is cancelled + HttpRequestFutureTask futureTask4 = requestExecService.execute(request4, + HttpClientContext.create(), handler, callback); + Boolean wasItOk4 = futureTask4.get(10, TimeUnit.SECONDS); + System.out.println("It was ok? " + wasItOk4); + } finally { + requestExecService.close(); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientWithResponseHandler.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientWithResponseHandler.java new file mode 100644 index 00000000..508735cc --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/ClientWithResponseHandler.java @@ -0,0 +1,80 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package com.xdc.basic.api.apache.http.client; + +import java.io.IOException; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +/** + * This example demonstrates the use of the {@link ResponseHandler} to simplify + * the process of processing the HTTP response and releasing associated resources. + */ +public class ClientWithResponseHandler { + + public final static void main(String[] args) throws Exception { + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + HttpGet httpget = new HttpGet("http://www.google.com/"); + + System.out.println("executing request " + httpget.getURI()); + + // Create a custom response handler + ResponseHandler responseHandler = new ResponseHandler() { + + public String handleResponse( + final HttpResponse response) throws ClientProtocolException, IOException { + int status = response.getStatusLine().getStatusCode(); + if (status >= 200 && status < 300) { + HttpEntity entity = response.getEntity(); + return entity != null ? EntityUtils.toString(entity) : null; + } else { + throw new ClientProtocolException("Unexpected response status: " + status); + } + } + + }; + String responseBody = httpclient.execute(httpget, responseHandler); + System.out.println("----------------------------------------"); + System.out.println(responseBody); + System.out.println("----------------------------------------"); + + } finally { + httpclient.close(); + } + } + +} + diff --git a/basicKnowledge/src/com/xdc/basic/api/apache/http/client/QuickStart.java b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/QuickStart.java new file mode 100644 index 00000000..2dc2d3c7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/apache/http/client/QuickStart.java @@ -0,0 +1,89 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package com.xdc.basic.api.apache.http.client; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +public class QuickStart { + + public static void main(String[] args) throws Exception { + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + HttpGet httpGet = new HttpGet("http://www.baidu.com/"); + CloseableHttpResponse response1 = httpclient.execute(httpGet); + // The underlying HTTP connection is still held by the response object + // to allow the response content to be streamed directly from the network socket. + // In order to ensure correct deallocation of system resources + // the user MUST either fully consume the response content or abort request + // execution by calling CloseableHttpResponse#close(). + + try { + System.out.println(response1.getStatusLine()); + HttpEntity entity1 = response1.getEntity(); + // do something useful with the response body + // and ensure it is fully consumed + String body = EntityUtils.toString(entity1); + System.out.println(body); + // EntityUtils.consume(entity1); + } finally { + response1.close(); + } + + HttpPost httpPost = new HttpPost("http://targethost/login"); + List nvps = new ArrayList (); + nvps.add(new BasicNameValuePair("username", "vip")); + nvps.add(new BasicNameValuePair("password", "secret")); + httpPost.setEntity(new UrlEncodedFormEntity(nvps)); + CloseableHttpResponse response2 = httpclient.execute(httpPost); + + try { + System.out.println(response2.getStatusLine()); + HttpEntity entity2 = response2.getEntity(); + // do something useful with the response body + // and ensure it is fully consumed + EntityUtils.consume(entity2); + } finally { + response2.close(); + } + } finally { + httpclient.close(); + } + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/easymock/add/Add.java b/basicKnowledge/src/com/xdc/basic/api/easymock/add/Add.java new file mode 100644 index 00000000..7381be3c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/easymock/add/Add.java @@ -0,0 +1,6 @@ +package com.xdc.basic.api.easymock.add; + +public interface Add +{ + public int add(int a, int b); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/easymock/add/AddTest.java b/basicKnowledge/src/com/xdc/basic/api/easymock/add/AddTest.java new file mode 100644 index 00000000..9bfa556b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/easymock/add/AddTest.java @@ -0,0 +1,29 @@ +package com.xdc.basic.api.easymock.add; + +import static org.junit.Assert.assertEquals; + +import org.easymock.EasyMock; +import org.junit.Test; + +public class AddTest +{ + @Test + public void testAdd() + { + //1、创建mock对象,以接口形式创建 + Add add = EasyMock.createMock(Add.class); + + //2、设定参预期和返回,查询预期值得到所设定的预期结果 + EasyMock.expect(add.add(1, 1)).andReturn(2); + EasyMock.expect(add.add(1, 2)).andReturn(3); + + //3、结束录制 + EasyMock.replay(add); + + assertEquals(2, add.add(1, 1)); + assertEquals(3, add.add(1, 2)); + + //4、回放录制 + EasyMock.verify(add); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/easymock/stock/Portfolio.java b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/Portfolio.java new file mode 100644 index 00000000..5b27791d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/Portfolio.java @@ -0,0 +1,61 @@ +package com.xdc.basic.api.easymock.stock; + +import java.util.ArrayList; +import java.util.List; + +public class Portfolio +{ + private String name; + private StockMarket stockMarket; + + private List stocks = new ArrayList(); + + /* + * this method gets the market value for each stock, sums it up and returns + * the total value of the portfolio. + */ + public Double getTotalValue() + { + Double value = 0.0; + for (Stock stock : this.stocks) + { + value += (stockMarket.getPrice(stock.getName()) * stock.getQuantity()); + } + return value; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public List getStocks() + { + return stocks; + } + + public void setStocks(List stocks) + { + this.stocks = stocks; + } + + public void addStock(Stock stock) + { + stocks.add(stock); + } + + public StockMarket getStockMarket() + { + return stockMarket; + } + + public void setStockMarket(StockMarket stockMarket) + { + this.stockMarket = stockMarket; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/easymock/stock/PortfolioTest.java b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/PortfolioTest.java new file mode 100644 index 00000000..029add7c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/PortfolioTest.java @@ -0,0 +1,41 @@ +package com.xdc.basic.api.easymock.stock; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +/** + * http://blog.jobbole.com/24453/ + * + * @author xdc + * + */ +public class PortfolioTest extends TestCase +{ + private Portfolio portfolio; + private StockMarket marketMock; + + @Before + public void setUp() + { + portfolio = new Portfolio(); + portfolio.setName("Veera's portfolio."); + marketMock = EasyMock.createMock(StockMarket.class); + portfolio.setStockMarket(marketMock); + } + + @Test + public void testGetTotalValue() + { + /* = Setup our mock object with the expected values */ + EasyMock.expect(marketMock.getPrice("EBAY")).andReturn(42.00); + EasyMock.replay(marketMock); + + /* = Now start testing our portfolio */ + Stock ebayStock = new Stock("EBAY", 2); + portfolio.addStock(ebayStock); + assertEquals(84.00, portfolio.getTotalValue()); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/easymock/stock/Stock.java b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/Stock.java new file mode 100644 index 00000000..0b107578 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/Stock.java @@ -0,0 +1,33 @@ +package com.xdc.basic.api.easymock.stock; + +public class Stock +{ + private String name; + private int quantity; + + public Stock(String name, int quantity) + { + this.name = name; + this.quantity = quantity; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public int getQuantity() + { + return quantity; + } + + public void setQuantity(int quantity) + { + this.quantity = quantity; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/easymock/stock/StockMarket.java b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/StockMarket.java new file mode 100644 index 00000000..f736e6a5 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/easymock/stock/StockMarket.java @@ -0,0 +1,6 @@ +package com.xdc.basic.api.easymock.stock; + +public interface StockMarket +{ + public Double getPrice(String stockName); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/hibernate/validator/Car.java b/basicKnowledge/src/com/xdc/basic/api/hibernate/validator/Car.java new file mode 100644 index 00000000..7fa72190 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/hibernate/validator/Car.java @@ -0,0 +1,27 @@ +package com.xdc.basic.api.hibernate.validator; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class Car +{ + @NotNull + private String manufacturer; + + @NotNull + @Size(min = 2, max = 14) + private String licensePlate; + + @Min(2) + private int seatCount; + + public Car(String manufacturer, String licencePlate, int seatCount) + { + this.manufacturer = manufacturer; + this.licensePlate = licencePlate; + this.seatCount = seatCount; + } + + //getters and setters ... +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/hibernate/validator/CarTest.java b/basicKnowledge/src/com/xdc/basic/api/hibernate/validator/CarTest.java new file mode 100644 index 00000000..bf37dba5 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/hibernate/validator/CarTest.java @@ -0,0 +1,69 @@ +package com.xdc.basic.api.hibernate.validator; + +import static org.junit.Assert.assertEquals; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class CarTest +{ + + private static Validator validator; + + @BeforeClass + public static void setUp() + { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + } + + @Test + public void manufacturerIsNull() + { + Car car = new Car(null, "DD-AB-123", 4); + + Set> constraintViolations = validator.validate(car); + + assertEquals(1, constraintViolations.size()); + assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); + } + + @Test + public void licensePlateTooShort() + { + Car car = new Car("Morris", "D", 4); + + Set> constraintViolations = validator.validate(car); + + assertEquals(1, constraintViolations.size()); + assertEquals("size must be between 2 and 14", constraintViolations.iterator().next().getMessage()); + } + + @Test + public void seatCountTooLow() + { + Car car = new Car("Morris", "DD-AB-123", 1); + + Set> constraintViolations = validator.validate(car); + + assertEquals(1, constraintViolations.size()); + assertEquals("must be greater than or equal to 2", constraintViolations.iterator().next().getMessage()); + } + + @Test + public void carIsValid() + { + Car car = new Car("Morris", "DD-AB-123", 2); + + Set> constraintViolations = validator.validate(car); + + assertEquals(0, constraintViolations.size()); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/java4android/collection/ArrayListTest.java b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/ArrayListTest.java similarity index 82% rename from basicKnowledge/src/com/xdc/basic/java4android/collection/ArrayListTest.java rename to basicKnowledge/src/com/xdc/basic/api/java4android/collection/ArrayListTest.java index 4fbf2fbe..6edf0f2d 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/collection/ArrayListTest.java +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/ArrayListTest.java @@ -1,7 +1,13 @@ -package com.xdc.basic.java4android.collection; +package com.xdc.basic.api.java4android.collection; import java.util.ArrayList; +/** + * 数组列表测试类 + * + * @author xdc + * + */ public class ArrayListTest { diff --git a/basicKnowledge/src/com/xdc/basic/java4android/collection/HashMapTest.java b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/HashMapTest.java similarity index 78% rename from basicKnowledge/src/com/xdc/basic/java4android/collection/HashMapTest.java rename to basicKnowledge/src/com/xdc/basic/api/java4android/collection/HashMapTest.java index 8cdf4727..fd17a123 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/collection/HashMapTest.java +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/HashMapTest.java @@ -1,8 +1,14 @@ -package com.xdc.basic.java4android.collection; +package com.xdc.basic.api.java4android.collection; import java.util.HashMap; import java.util.Map; +/** + * 哈希映射测试类 + * + * @author xdc + * + */ public class HashMapTest { diff --git a/basicKnowledge/src/com/xdc/basic/java4android/collection/HashSetTest.java b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/HashSetTest.java similarity index 89% rename from basicKnowledge/src/com/xdc/basic/java4android/collection/HashSetTest.java rename to basicKnowledge/src/com/xdc/basic/api/java4android/collection/HashSetTest.java index 06361be2..c797a333 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/collection/HashSetTest.java +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/HashSetTest.java @@ -1,4 +1,4 @@ -package com.xdc.basic.java4android.collection; +package com.xdc.basic.api.java4android.collection; import java.util.HashSet; import java.util.Iterator; @@ -6,7 +6,6 @@ public class HashSetTest { - public static void main(String[] args) { diff --git "a/basicKnowledge/bin/com/xdc/basic/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.gif" "b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.gif" similarity index 100% rename from "basicKnowledge/bin/com/xdc/basic/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.gif" rename to "basicKnowledge/src/com/xdc/basic/api/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.gif" diff --git "a/basicKnowledge/bin/com/xdc/basic/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.jpg" "b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.jpg" similarity index 100% rename from "basicKnowledge/bin/com/xdc/basic/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.jpg" rename to "basicKnowledge/src/com/xdc/basic/api/java4android/collection/Java2\347\256\200\345\214\226\351\233\206\345\220\210\347\261\273\346\241\206\346\236\266\345\233\276.jpg" diff --git a/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Maps.java b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Maps.java new file mode 100644 index 00000000..67c6b4b6 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Maps.java @@ -0,0 +1,153 @@ +package com.xdc.basic.api.java4android.collection; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; + +/** + * 改自:http://blog.csdn.net/limin2928/article/details/8079446 + * + * + * @author xdc + * + */ +public class Maps +{ + // Java为数据结构中的映射定义了一个接口java.util.Map,它有四个实现类,分别是HashMap、HashTable、LinkedHashMap和TreeMap。本节实例主要介绍这4中实例的用法和区别。 + // + // 关键技术剖析: + // Map用于存储键值对,根据键得到值,因此不允许键重复,值可以重复。 + // (1)HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要同步,可以用Collections.synchronizedMap(HashMap map)方法使HashMap具有同步的能力。 + // (2)Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,然而,这也导致了Hashtable在写入时会比较慢。 + // (3)LinkedHashMap保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的。在遍历的时候会比HashMap慢。有HashMap的全部特性。 + // (4)TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iteraor遍历TreeMap时,得到的记录是排过序的。TreeMap的键不能为空。 + + public static void init(Map map) + { + if (map == null) + { + return; + } + + for (int i = 5; i > 0; i--) + { + String key = String.valueOf(i); + map.put(key, key); + // Map中的键是不重复的,如果插入两个键值一样的记录,那么后插入的记录会覆盖先插入的记录 + map.put(key, key + key); + } + } + + public static void output(Map map) + { + if (map == null) + { + return; + } + + // 使用迭代器遍历Map的键,根据键取值 + Iterator kit = map.keySet().iterator(); + while (kit.hasNext()) + { + String key = kit.next(); + String value = map.get(key); + System.out.println("key: " + key + "; value: " + value); + } + + // // 或者使用迭代器遍历Map的记录Map.Entry + // Iterator> eit = map.entrySet().iterator(); + // while (eit.hasNext()) + // { + // // 一个Map.Entry代表一条记录 + // Entry entry = eit.next(); + // String key = entry.getKey(); + // String value = entry.getValue(); + // System.out.println("key: " + key + "; value: " + value); + // } + } + + public static void testHashMap() + { + Map hashMap = new HashMap(); + init(hashMap); + + // HashMap的键可以为null + hashMap.put(null, "key is null"); + hashMap.put(null, "key is null 2"); + + // HashMap的值可以为null + hashMap.put("value is null", null); + hashMap.put("value is null 2", null); + + output(hashMap); + } + + public static void testHashtable() + { + Map hashtable = new Hashtable(); + init(hashtable); + + // // Hashtable的键不能为null + // hashtable.put(null, "key is null"); + // hashtable.put(null, "key is null 2"); + + // // Hashtable的值不能为null + // hashtable.put("value is null", null); + // hashtable.put("value is null 2", null); + + output(hashtable); + } + + public static void testLinkedHashMap() + { + Map linkedHashMap = new LinkedHashMap(); + init(linkedHashMap); + + // LinkedHashMap的键可以为null + linkedHashMap.put(null, "key is null"); + linkedHashMap.put(null, "key is null 2"); + + // LinkedHashMap的值可以为null + linkedHashMap.put("value is null", null); + linkedHashMap.put("value is null 2", null); + + output(linkedHashMap); + } + + public static void testTreeMap() + { + Map treeMap = new TreeMap(); + init(treeMap); + + // // TreeMap的键不能为null + // treeMap.put(null, "key is null"); + + // TreeMap的值可以为null + treeMap.put("value is null", null); + treeMap.put("value is null 2", null); + + output(treeMap); + } + + public static void main(String[] args) + { + System.out.println("采用HashMap --非线程安全,较快"); + Maps.testHashMap(); + System.out.println(); + + System.out.println("采用Hashtable --线程安全,较慢"); + Maps.testHashtable(); + System.out.println(); + + System.out.println("采用LinkedHashMap --保持放入顺序"); + Maps.testLinkedHashMap(); + System.out.println(); + + System.out.println("采用TreeMap --按key排序"); + Maps.testTreeMap(); + System.out.println(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Sets.java b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Sets.java new file mode 100644 index 00000000..871f6f23 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/collection/Sets.java @@ -0,0 +1,93 @@ +package com.xdc.basic.api.java4android.collection; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.TreeSet; + +public class Sets +{ + public static void init(Set set) + { + if (set == null) + { + return; + } + + for (int i = 5; i > 0; i--) + { + String elememt = String.valueOf(i); + + set.add(elememt); + // set中的元素是不重复的,第二次插入set无变化,并且add返回值为false + set.add(elememt); + } + } + + public static void output(Set set) + { + if (set == null) + { + return; + } + + Iterator it = set.iterator(); + while (it.hasNext()) + { + String elememt = it.next(); + System.out.println("elememt: " + elememt); + } + } + + public static void testHashSet() + { + Set hashSet = new HashSet(); + init(hashSet); + + // 元素允许为null + hashSet.add(null); + hashSet.add(null); + + output(hashSet); + } + + public static void testLinkedHashSet() + { + Set linkedHashSet = new LinkedHashSet(); + init(linkedHashSet); + + // 元素允许为null + linkedHashSet.add(null); + linkedHashSet.add(null); + + output(linkedHashSet); + } + + public static void testTreeSet() + { + Set treeSet = new TreeSet(); + init(treeSet); + + // // 元素不允许为null + // treeSet.add(null); + // treeSet.add(null); + + output(treeSet); + } + + public static void main(String[] args) + { + System.out.println("采用HashSet"); + Sets.testHashSet(); + System.out.println(); + + System.out.println("采用LinkedHashSet --保持放入顺序"); + Sets.testLinkedHashSet(); + System.out.println(); + + System.out.println("采用TreeSet --按元素排序"); + Sets.testTreeSet(); + System.out.println(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/java4android/equals/EqualsTest.java b/basicKnowledge/src/com/xdc/basic/api/java4android/equals/EqualsTest.java similarity index 84% rename from basicKnowledge/src/com/xdc/basic/java4android/equals/EqualsTest.java rename to basicKnowledge/src/com/xdc/basic/api/java4android/equals/EqualsTest.java index fe6097a9..13173622 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/equals/EqualsTest.java +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/equals/EqualsTest.java @@ -1,25 +1,30 @@ -package com.xdc.basic.java4android.equals; - -//测试代码 -public class EqualsTest -{ - public static void main(String[] args) - { - User u1 = new User(); - User u2 = new User(); - User u3 = u1; - - u1.name = "gengxue"; - u1.age = 23; - u2.name = "xudachao"; - u2.age = 24; - - System.out.println("u1 == u2 : " + (u1 == u2)); - System.out.println("u1 == u3 : " + (u1 == u3)); - System.out.println("u2 == u3 : " + (u2 == u3)); - - System.out.println("u1.equals(u2) : " + u1.equals(u2)); - System.out.println("u1.equals(u3) : " + u1.equals(u3)); - System.out.println("u2.equals(u3) : " + u2.equals(u3)); - } -} +package com.xdc.basic.api.java4android.equals; + +/** + * equals方法测试类 + * + * @author xdc + * + */ +public class EqualsTest +{ + public static void main(String[] args) + { + User u1 = new User(); + User u2 = new User(); + User u3 = u1; + + u1.name = "gengxue"; + u1.age = 23; + u2.name = "xudachao"; + u2.age = 24; + + System.out.println("u1 == u2 : " + (u1 == u2)); + System.out.println("u1 == u3 : " + (u1 == u3)); + System.out.println("u2 == u3 : " + (u2 == u3)); + + System.out.println("u1.equals(u2) : " + u1.equals(u2)); + System.out.println("u1.equals(u3) : " + u1.equals(u3)); + System.out.println("u2.equals(u3) : " + u2.equals(u3)); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/java4android/equals/User.java b/basicKnowledge/src/com/xdc/basic/api/java4android/equals/User.java new file mode 100644 index 00000000..fb0ae32b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/equals/User.java @@ -0,0 +1,31 @@ +package com.xdc.basic.api.java4android.equals; + +//equals()的重写 +public class User +{ + String name; + int age; + + public boolean equals(Object obj) + { + if (this == obj) + return true; + + if (obj instanceof User) + { + User user = (User) obj; + if (this.name.equals(user.name) && this.age == user.age) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/java4android/io/BufferedReaderTest.java b/basicKnowledge/src/com/xdc/basic/api/java4android/io/BufferedReaderTest.java similarity index 71% rename from basicKnowledge/src/com/xdc/basic/java4android/io/BufferedReaderTest.java rename to basicKnowledge/src/com/xdc/basic/api/java4android/io/BufferedReaderTest.java index 25b3c707..0eaf8adc 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/io/BufferedReaderTest.java +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/io/BufferedReaderTest.java @@ -1,38 +1,47 @@ -package com.xdc.basic.java4android.io; - -import java.io.BufferedReader; -import java.io.FileReader; - -// 处理流示例 -class BufferedReaderTest -{ - public static void main(String[] args) - { - FileReader fileReader = null; - BufferedReader bufferedReader = null; - try - { - fileReader = new FileReader("src\\com\\xdc\\basic\\java4android\\io\\from.txt"); - bufferedReader = new BufferedReader(fileReader); - String line = null; - while ((line = bufferedReader.readLine()) != null) - System.out.println(line); - } - catch (Exception e) - { - System.out.println(e); - } - finally - { - try - { - bufferedReader.close(); - fileReader.close(); - } - catch (Exception e) - { - System.out.println(e); - } - } - } -} +package com.xdc.basic.api.java4android.io; + +import java.io.BufferedReader; +import java.io.FileReader; + +import com.xdc.basic.skills.GetCurPath; + +/** + * 处理流示例 + * + * @author xdc + * + */ +class BufferedReaderTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + + FileReader fileReader = null; + BufferedReader bufferedReader = null; + try + { + fileReader = new FileReader(curPath + "from.txt"); + bufferedReader = new BufferedReader(fileReader); + String line = null; + while ((line = bufferedReader.readLine()) != null) + System.out.println(line); + } + catch (Exception e) + { + System.out.println(e); + } + finally + { + try + { + bufferedReader.close(); + fileReader.close(); + } + catch (Exception e) + { + System.out.println(e); + } + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/java4android/io/IOByteStreamTest.java b/basicKnowledge/src/com/xdc/basic/api/java4android/io/IOByteStreamTest.java similarity index 74% rename from basicKnowledge/src/com/xdc/basic/java4android/io/IOByteStreamTest.java rename to basicKnowledge/src/com/xdc/basic/api/java4android/io/IOByteStreamTest.java index 8f98bb35..49f8789f 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/io/IOByteStreamTest.java +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/io/IOByteStreamTest.java @@ -1,21 +1,30 @@ -package com.xdc.basic.java4android.io; +package com.xdc.basic.api.java4android.io; import java.io.FileInputStream; import java.io.FileOutputStream; -// io字节流示例 +import com.xdc.basic.skills.GetCurPath; + +/** + * io字节流示例 + * + * @author xdc + * + */ class IOByteStreamTest { public static void main(String[] args) { + String curPath = GetCurPath.getCurPath(); + // 声明输入流、输出流引用 FileInputStream fis = null; FileOutputStream fos = null; try { // 生成代表输入流、输出流的对象 - fis = new FileInputStream("src\\com\\xdc\\basic\\java4android\\io\\from.txt"); - fos = new FileOutputStream("src\\com\\xdc\\basic\\java4android\\io\\to.txt"); + fis = new FileInputStream(curPath + "from.txt"); + fos = new FileOutputStream(curPath + "to.txt"); // 生成一个字节数组 byte[] buffer = new byte[1024]; int len; diff --git a/basicKnowledge/src/com/xdc/basic/java4android/io/IOCharStreamTest.java b/basicKnowledge/src/com/xdc/basic/api/java4android/io/IOCharStreamTest.java similarity index 68% rename from basicKnowledge/src/com/xdc/basic/java4android/io/IOCharStreamTest.java rename to basicKnowledge/src/com/xdc/basic/api/java4android/io/IOCharStreamTest.java index cb3bf6e8..b1b8e937 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/io/IOCharStreamTest.java +++ b/basicKnowledge/src/com/xdc/basic/api/java4android/io/IOCharStreamTest.java @@ -1,44 +1,53 @@ -package com.xdc.basic.java4android.io; - -import java.io.FileReader; -import java.io.FileWriter; - -// io字符流测试 -class IOCharStreamTest -{ - public static void main(String[] args) - { - FileReader fr = null; - FileWriter fw = null; - try - { - fr = new FileReader("src\\com\\xdc\\basic\\java4android\\io\\from.txt"); - fw = new FileWriter("src\\com\\xdc\\basic\\java4android\\io\\to.txt"); - char[] buffer = new char[1024]; - int len; - while ((len = fr.read(buffer, 0, buffer.length)) != -1) - { - fw.write(buffer, 0, len); - String s = new String(buffer); - s = s.trim(); - System.out.println(s); - } - } - catch (Exception e) - { - System.out.println(e); - } - finally - { - try - { - fr.close(); - fw.close(); - } - catch (Exception e) - { - System.out.println(e); - } - } - } -} +package com.xdc.basic.api.java4android.io; + +import java.io.FileReader; +import java.io.FileWriter; + +import com.xdc.basic.skills.GetCurPath; + +/** + * io字符流测试 + * + * @author xdc + * + */ +class IOCharStreamTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + + FileReader fr = null; + FileWriter fw = null; + try + { + fr = new FileReader(curPath + "from.txt"); + fw = new FileWriter(curPath + "to.txt"); + char[] buffer = new char[1024]; + int len; + while ((len = fr.read(buffer, 0, buffer.length)) != -1) + { + fw.write(buffer, 0, len); + String s = new String(buffer); + s = s.trim(); + System.out.println(s); + } + } + catch (Exception e) + { + System.out.println(e); + } + finally + { + try + { + fr.close(); + fw.close(); + } + catch (Exception e) + { + System.out.println(e); + } + } + } +} diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/io/from.txt b/basicKnowledge/src/com/xdc/basic/api/java4android/io/from.txt similarity index 100% rename from basicKnowledge/bin/com/xdc/basic/java4android/io/from.txt rename to basicKnowledge/src/com/xdc/basic/api/java4android/io/from.txt diff --git a/basicKnowledge/bin/com/xdc/basic/java4android/io/to.txt b/basicKnowledge/src/com/xdc/basic/api/java4android/io/to.txt similarity index 100% rename from basicKnowledge/bin/com/xdc/basic/java4android/io/to.txt rename to basicKnowledge/src/com/xdc/basic/api/java4android/io/to.txt diff --git a/basicKnowledge/src/com/xdc/basic/api/jaxb/XMLConvertor.java b/basicKnowledge/src/com/xdc/basic/api/jaxb/XMLConvertor.java new file mode 100644 index 00000000..c3e84392 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/jaxb/XMLConvertor.java @@ -0,0 +1,86 @@ +package com.xdc.basic.api.jaxb; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +public class XMLConvertor +{ + private JAXBContext jaxbContext = null; + private Marshaller marshaller = null; + private Unmarshaller unmarshaller = null; + + public XMLConvertor(String conextPath) throws JAXBException + { + jaxbContext = JAXBContext.newInstance(conextPath); + marshaller = jaxbContext.createMarshaller(); + unmarshaller = jaxbContext.createUnmarshaller(); + } + + public Object xml2Java(Reader rd) throws JAXBException + { + return unmarshaller.unmarshal(rd); + } + + public void java2Xml(Object obj, Writer wt) throws JAXBException + { + marshaller.marshal(obj, wt); + } + + public Object xml2Java(InputStream is) throws JAXBException + { + return unmarshaller.unmarshal(is); + } + + public void java2Xml(Object obj, OutputStream os) throws JAXBException + { + marshaller.marshal(obj, os); + } + + public Object xml2Java(File file) throws JAXBException + { + return unmarshaller.unmarshal(file); + } + + public void java2Xml(Object obj, File file) throws JAXBException + { + marshaller.marshal(obj, file); + } + + public Object xmlString2Java(String xmlString) throws JAXBException + { + StringReader stringReader = new StringReader(xmlString); + return this.xml2Java(stringReader); + } + + public String java2XmlString(Object obj) throws JAXBException + { + StringWriter stringWriter = new StringWriter(); + this.java2Xml(obj, stringWriter); + return stringWriter.toString(); + } + + public Object xmlByte2Java(byte[] xmlByte) throws JAXBException + { + ByteArrayInputStream inputStream = new ByteArrayInputStream(xmlByte); + return this.xml2Java(inputStream); + } + + public byte[] java2XmlByte(Object obj) throws JAXBException + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + this.java2Xml(obj, outputStream); + return outputStream.toByteArray(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/jaxb/XMLTest.java b/basicKnowledge/src/com/xdc/basic/api/jaxb/XMLTest.java new file mode 100644 index 00000000..79e297a1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/jaxb/XMLTest.java @@ -0,0 +1,55 @@ +package com.xdc.basic.api.jaxb; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.bind.JAXBException; + +import org.junit.Test; + +import com.xdc.basic.api.jaxb.user.Users; + +/** + * xml解析 + * + * @author xdc + * + */ +public class XMLTest +{ + private final String usersXML = "小李24小丽18小王22"; + + @Test + public void xmlString2Java() throws JAXBException + { + final String XML_MODEL_MEMBER = Users.class.getPackage().getName(); + + XMLConvertor xmlConvertor = new XMLConvertor(XML_MODEL_MEMBER); + + StringReader stringReader = new StringReader(usersXML); + Users users = (Users) xmlConvertor.xml2Java(stringReader); + System.out.println(users); + + StringWriter stringWriter = new StringWriter(); + xmlConvertor.java2Xml(users, stringWriter); + System.out.println(stringWriter); + } + + @Test + public void xmlBytes2Java() throws JAXBException + { + final String XML_MODEL_MEMBER = Users.class.getPackage().getName(); + + XMLConvertor xmlConvertor = new XMLConvertor(XML_MODEL_MEMBER); + + ByteArrayInputStream inputStream = new ByteArrayInputStream(usersXML.getBytes()); + Users users = (Users) xmlConvertor.xml2Java(inputStream); + System.out.println(users); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + xmlConvertor.java2Xml(users, outputStream); + System.out.println(outputStream.toString()); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/jaxb/user/ObjectFactory.java b/basicKnowledge/src/com/xdc/basic/api/jaxb/user/ObjectFactory.java new file mode 100644 index 00000000..fc0105d3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/jaxb/user/ObjectFactory.java @@ -0,0 +1,93 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2013.04.15 at 12:59:25 AM CST +// + + +package com.xdc.basic.api.jaxb.user; + +import java.math.BigInteger; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the com.xdc.basic.example.jaxb.user package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _Sex_QNAME = new QName("", "sex"); + private final static QName _Age_QNAME = new QName("", "age"); + private final static QName _Name_QNAME = new QName("", "name"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.xdc.basic.example.jaxb.user + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link Users } + * + */ + public Users createUsers() { + return new Users(); + } + + /** + * Create an instance of {@link User } + * + */ + public User createUser() { + return new User(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} + * + */ + @XmlElementDecl(namespace = "", name = "sex") + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + public JAXBElement createSex(String value) { + return new JAXBElement(_Sex_QNAME, String.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link BigInteger }{@code >}} + * + */ + @XmlElementDecl(namespace = "", name = "age") + public JAXBElement createAge(BigInteger value) { + return new JAXBElement(_Age_QNAME, BigInteger.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} + * + */ + @XmlElementDecl(namespace = "", name = "name") + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + public JAXBElement createName(String value) { + return new JAXBElement(_Name_QNAME, String.class, null, value); + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/jaxb/user/User.java b/basicKnowledge/src/com/xdc/basic/api/jaxb/user/User.java new file mode 100644 index 00000000..c76b7e98 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/jaxb/user/User.java @@ -0,0 +1,140 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2013.04.15 at 12:59:25 AM CST +// + +package com.xdc.basic.api.jaxb.user; + +import java.math.BigInteger; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + *

+ * Java class for anonymous complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element ref="{}name"/>
+ *         <element ref="{}sex"/>
+ *         <element ref="{}age"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { "name", "sex", "age" }) +@XmlRootElement(name = "user") +public class User +{ + + @XmlElement(required = true) + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + @XmlSchemaType(name = "NCName") + protected String name; + @XmlElement(required = true) + @XmlJavaTypeAdapter(CollapsedStringAdapter.class) + @XmlSchemaType(name = "NCName") + protected String sex; + @XmlElement(required = true) + protected BigInteger age; + + /** + * Gets the value of the name property. + * + * @return possible object is {@link String } + * + */ + public String getName() + { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is {@link String } + * + */ + public void setName(String value) + { + this.name = value; + } + + /** + * Gets the value of the sex property. + * + * @return possible object is {@link String } + * + */ + public String getSex() + { + return sex; + } + + /** + * Sets the value of the sex property. + * + * @param value + * allowed object is {@link String } + * + */ + public void setSex(String value) + { + this.sex = value; + } + + /** + * Gets the value of the age property. + * + * @return possible object is {@link BigInteger } + * + */ + public BigInteger getAge() + { + return age; + } + + /** + * Sets the value of the age property. + * + * @param value + * allowed object is {@link BigInteger } + * + */ + public void setAge(BigInteger value) + { + this.age = value; + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/jaxb/user/Users.java b/basicKnowledge/src/com/xdc/basic/api/jaxb/user/Users.java new file mode 100644 index 00000000..c047afdb --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/jaxb/user/Users.java @@ -0,0 +1,89 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2013.04.15 at 12:59:25 AM CST +// + +package com.xdc.basic.api.jaxb.user; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + *

+ * Java class for anonymous complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element ref="{}user" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { "user" }) +@XmlRootElement(name = "users") +public class Users +{ + + @XmlElement(required = true) + protected List user; + + /** + * Gets the value of the user property. + * + *

+ * This accessor method returns a reference to the live list, not a + * snapshot. Therefore any modification you make to the returned list will + * be present inside the JAXB object. This is why there is not a + * set method for the user property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getUser().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link User } + * + * + */ + public List getUser() + { + if (user == null) + { + user = new ArrayList(); + } + return this.user; + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git "a/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/trang.jar" "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/trang.jar" new file mode 100644 index 00000000..672d65c4 Binary files /dev/null and "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/trang.jar" differ diff --git a/jdom2.format/users.xml "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/users.xml" similarity index 84% rename from jdom2.format/users.xml rename to "basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/users.xml" index 3a400259..af30b881 100644 --- a/jdom2.format/users.xml +++ "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/users.xml" @@ -1,6 +1,6 @@ - 小李 + 小李 24 小丽 diff --git "a/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/xml2xsd.bat" "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/xml2xsd.bat" new file mode 100644 index 00000000..47a7ba53 --- /dev/null +++ "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/xml2xsd.bat" @@ -0,0 +1 @@ +java -jar trang.jar "users.xml" "users.xsd" \ No newline at end of file diff --git "a/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/xsd2java.bat" "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/xsd2java.bat" new file mode 100644 index 00000000..689c04a1 --- /dev/null +++ "b/basicKnowledge/src/com/xdc/basic/api/jaxb/\350\207\252\345\212\250\347\224\237\346\210\220\345\267\245\345\205\267/xsd2java.bat" @@ -0,0 +1 @@ +xjc -xmlschema "users.xsd" -p com.xdc.basic.example.jaxb.user \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/json/jackson/JsonTool.java b/basicKnowledge/src/com/xdc/basic/api/json/jackson/JsonTool.java new file mode 100644 index 00000000..50195882 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/json/jackson/JsonTool.java @@ -0,0 +1,96 @@ +package com.xdc.basic.api.json.jackson; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonTool +{ + private static final ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally + static + { + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + public static void main(String[] args) + { + // ---------------------------------------------------------- + // json object ---------------------------------------------- + String jsonString = "{\"name\":{\"first\":\"Joe\",\"last\":\"Sixpack\"},\"gender\":\"MALE\",\"verified\":false,\"userImage\":\"Rm9vYmFyIQ==\"}"; + + // json string --> object + User user = JsonTool.parse(jsonString, User.class); + System.out.println(user); + + // object --> json string + String jsonString2 = JsonTool.toJSONString(user); + System.out.println(jsonString2); + + // ---------------------------------------------------------- + // json array ----------------------------------------------- + ArrayList users = new ArrayList(); + users.add(user); + users.add(user); + + // array --> json string + String jsonString3 = JsonTool.toJSONString(users); + System.out.println(jsonString3); + + // json string --> array + User[] parsedUsers = JsonTool.parse(jsonString3, User[].class); + System.out.println(parsedUsers); + } + + public static String toJSONString(Object o) + { + String s = null; + try + { + s = mapper.writeValueAsString(o); + + // 漂亮的输出 + // mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o); + } + catch (JsonProcessingException e) + { + e.printStackTrace(); + } + return s; + } + + public static T parse(String s, Class clazz) + { + T t = null; + try + { + t = mapper.readValue(s, clazz); + } + catch (JsonParseException e) + { + e.printStackTrace(); + } + catch (JsonMappingException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + return t; + } + + public static List parseArray(String s, Class clazz) + { + // TODO 待研究 + // List result = mapper.readValue(s, TypeFactory.collectionType(ArrayList.class, clazz)); + // return result; + return null; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/json/jackson/User.java b/basicKnowledge/src/com/xdc/basic/api/json/jackson/User.java new file mode 100644 index 00000000..b2f0ee16 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/json/jackson/User.java @@ -0,0 +1,79 @@ +package com.xdc.basic.api.json.jackson; + +public class User +{ + public enum Gender + { + MALE, FEMALE + }; + + public static class Name + { + private String _first, _last; + + public String getFirst() + { + return _first; + } + + public String getLast() + { + return _last; + } + + public void setFirst(String s) + { + _first = s; + } + + public void setLast(String s) + { + _last = s; + } + } + + private Gender _gender; + private Name _name; + private boolean _isVerified; + private byte[] _userImage; + + public Name getName() + { + return _name; + } + + public boolean isVerified() + { + return _isVerified; + } + + public Gender getGender() + { + return _gender; + } + + public byte[] getUserImage() + { + return _userImage; + } + + public void setName(Name n) + { + _name = n; + } + + public void setVerified(boolean b) + { + _isVerified = b; + } + + public void setGender(Gender g) + { + _gender = g; + } + + public void setUserImage(byte[] b) + { + _userImage = b; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/JsonDemo.java b/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/JsonDemo.java new file mode 100644 index 00000000..84fb6053 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/JsonDemo.java @@ -0,0 +1,138 @@ +package com.xdc.basic.api.json.jsonsmart; + +import java.util.ArrayList; +import java.util.List; + +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import net.minidev.json.JSONStyle; +import net.minidev.json.JSONValue; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; + +import org.junit.Test; + +/* + * Home page: http://code.google.com/p/json-smart/ + * + */ + +public class JsonDemo +{ + @Test + public void EncodeJsonObject() + { + // Json Object is an HashMap extends + JSONObject obj = new JSONObject(); + obj.put("name", "foo"); + obj.put("num", 100); + obj.put("balance", 1000.21); + obj.put("is_vip", true); + obj.put("nickname", null); + + System.out.println("Standard RFC4627 JSON"); + System.out.println(obj.toJSONString()); + System.out.println("Compacted JSON Value"); + System.out.println(obj.toJSONString(JSONStyle.MAX_COMPRESS)); + + // if obj is an common map you can use: + System.out.println("Standard RFC4627 JSON"); + System.out.println(JSONValue.toJSONString(obj)); + System.out.println("Compacted JSON Value"); + System.out.println(JSONValue.toJSONString(obj, JSONStyle.MAX_COMPRESS)); + } + + @Test + public void DecodingJsonText() throws ParseException + { + System.out.println("=======decode======="); + + String s = "[0,{'1':{'2':{'3':{'4':[5,{'6':7}]}}}}]"; + Object obj = JSONValue.parse(s); + JSONArray array = (JSONArray) obj; + System.out.println("======the 2nd element of array======"); + System.out.println(array.get(1)); + System.out.println(); + + JSONObject obj2 = (JSONObject) array.get(1); + System.out.println("======field \"1\"=========="); + System.out.println(obj2.get("1")); + + s = "{}"; + obj = JSONValue.parse(s); + System.out.println(obj); + + s = "{\"key\":\"Value\"}"; + // JSONValue.parseStrict() + // can be use to be sure that the input is wellformed + obj = JSONValue.parseStrict(s); + JSONObject obj3 = (JSONObject) obj; + System.out.println("====== Object content ======"); + System.out.println(obj3.get("key")); + System.out.println(); + } + + @Test + public void DecodingJsonText2() throws ParseException + { + Student student = new Student("xudachao", 100, 25); + List goodFriends = new ArrayList(); + goodFriends.add("chenchong"); + goodFriends.add("duquan"); + student.setGoodFriends(goodFriends); + + String studentString = JSONValue.toJSONString(student); + System.out.println(studentString); + + // Student必须有无参构造函数,因为利用反射获取对象 + Student parsedStudent = JSONValue.parse(studentString, Student.class); + System.out.println(parsedStudent); + + // smart json 还没提供直接数组串转会数组的方法 + String goodFriendsString = JSONValue.toJSONString(goodFriends); + System.out.println(goodFriendsString); + + // parse的结果只有两种可能 JSONObject或JSONArray + Object object = JSONValue.parse(studentString); + if (object instanceof JSONObject) + { + System.out.println("It,s a json object."); + } + else + { + System.out.println("It,s a json array."); + } + } + + @Test + public void Merge2JsonObject() throws ParseException + { + String json1 = "{'car':{'color':'blue'}}"; + String json2 = "{'car':{'size':'3.5m'}}"; + + @SuppressWarnings("deprecation") + JSONParser p = new JSONParser(); + JSONObject o1 = (JSONObject) p.parse(json1); + JSONObject o2 = (JSONObject) p.parse(json2); + + o1.merge(o2); + + System.out.println(o1); + } + + @Test + public void ValidatingJsonInput() throws ParseException + { + // JSONValue.isValidJson(String) To validate a string that conforms to the (non-strict) JSON Smart mode. + // JSONValue.isValidStrictJson(String) To validate a string of JSON for strict conformance to RFC4627. + + String s = "{intValue:123}"; + if (JSONValue.isValidJson(s)) + System.out.println(s + " validates as Smart JSON"); + + if (JSONValue.isValidJsonStrict(s)) + System.out.println(s + " validates as strict JSON"); + else + System.out.println(s + " does not validate as strict JSON"); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/JsonTool.java b/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/JsonTool.java new file mode 100644 index 00000000..fd5629f3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/JsonTool.java @@ -0,0 +1,76 @@ +package com.xdc.basic.api.json.jsonsmart; + +import java.util.ArrayList; +import java.util.List; + +import net.minidev.json.JSONArray; +import net.minidev.json.JSONValue; + +import org.junit.Test; + +public class JsonTool +{ + @Test + public void jsonTest() + { + // ---------------------------------------------------------- + // json object ---------------------------------------------- + Student student = new Student("xudachao", 100, 25); + List goodFriends = new ArrayList(); + goodFriends.add("chenchong"); + goodFriends.add("duquan"); + student.setGoodFriends(goodFriends); + + // object --> json string + String studentString = JsonTool.toJSONString(student); + System.out.println(studentString); + + // json string --> object + Student parsedStudent = JsonTool.parse(studentString, Student.class); + System.out.println(parsedStudent); + + // ---------------------------------------------------------- + // json array ----------------------------------------------- + List students = new ArrayList(); + students.add(student); + students.add(student); + + // array --> json string + String studentsString = JSONValue.toJSONString(students); + System.out.println(studentsString); + + // json string --> array + List parsedArray = JsonTool.parseArray(studentsString, Student.class); + System.out.println(parsedArray); + + // json string --> array + Student[] parsedStudents = JsonTool.parse(studentsString, Student[].class); + System.out.println(parsedStudents); + } + + public static String toJSONString(Object o) + { + return JSONValue.toJSONString(o); + } + + public static T parse(String s, Class clazz) + { + return JSONValue.parse(s, clazz); + } + + public static List parseArray(String s, Class clazz) + { + List result = new ArrayList(); + Object object = JSONValue.parse(s); + if (object instanceof JSONArray) + { + JSONArray jsonArray = (JSONArray) object; + for (Object object2 : jsonArray) + { + String string = JSONValue.toJSONString(object2); + result.add(JSONValue.parse(string, clazz)); + } + } + return result; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/Student.java b/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/Student.java new file mode 100644 index 00000000..f0d44d27 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/json/jsonsmart/Student.java @@ -0,0 +1,74 @@ +package com.xdc.basic.api.json.jsonsmart; + +import java.util.List; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class Student +{ + private String name; + private int score; + private int age; + private List goodFriends; + + public Student() + { + super(); + } + + public Student(String name, int score, int age) + { + super(); + this.setName(name); + this.setScore(score); + this.setAge(age); + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public int getScore() + { + return score; + } + + public void setScore(int score) + { + this.score = score; + } + + public int getAge() + { + return age; + } + + public void setAge(int age) + { + this.age = age; + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } + + public List getGoodFriends() + { + return goodFriends; + } + + public void setGoodFriends(List goodFriends) + { + this.goodFriends = goodFriends; + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/mq/Recv.java b/basicKnowledge/src/com/xdc/basic/api/mq/Recv.java new file mode 100644 index 00000000..ac7ff1e5 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mq/Recv.java @@ -0,0 +1,43 @@ +package com.xdc.basic.api.mq; + +import java.io.IOException; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.ConsumerCancelledException; +import com.rabbitmq.client.QueueingConsumer; +import com.rabbitmq.client.ShutdownSignalException; + +/** + * mq消息接收示例 (需在开启RabbitMQ Server才能看到结果) + * + * @author xdc + * + */ +public class Recv +{ + private final static String QUEUE_NAME = "hello"; + + public static void main(String[] argv) throws IOException, ShutdownSignalException, ConsumerCancelledException, + InterruptedException + { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost("localhost"); + Connection connection = factory.newConnection(); + Channel channel = connection.createChannel(); + + channel.queueDeclare(QUEUE_NAME, false, false, false, null); + System.out.println(" [*] Waiting for messages. To exit press CTRL+C"); + + QueueingConsumer consumer = new QueueingConsumer(channel); + channel.basicConsume(QUEUE_NAME, true, consumer); + + while (true) + { + QueueingConsumer.Delivery delivery = consumer.nextDelivery(); + String message = new String(delivery.getBody()); + System.out.println(" [x] Received '" + message + "'"); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mq/Send.java b/basicKnowledge/src/com/xdc/basic/api/mq/Send.java new file mode 100644 index 00000000..b94c8fc3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mq/Send.java @@ -0,0 +1,36 @@ +package com.xdc.basic.api.mq; + +import java.io.IOException; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; + +/** + * mq消息发送示例 + * + * @author xdc + * + */ +public class Send +{ + private final static String QUEUE_NAME = "hello"; + + public static void main(String[] args) throws IOException + { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost("localhost"); + Connection connection = factory.newConnection(); + Channel channel = connection.createChannel(); + + channel.queueDeclare(QUEUE_NAME, false, false, false, null); + for (int i = 0; i < 5; i++) + { + String message = "Hello World!" + i; + channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); + System.out.println(" [x] Sent '" + message + "'"); + } + channel.close(); + connection.close(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/MyBatisTest.java b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/MyBatisTest.java new file mode 100644 index 00000000..a619080e --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/MyBatisTest.java @@ -0,0 +1,64 @@ +package com.xdc.basic.api.mybatis.generator; + +import java.io.IOException; +import java.io.Reader; + +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; + +import com.xdc.basic.api.mybatis.generator.data.StudentMapper; +import com.xdc.basic.api.mybatis.generator.model.Student; + +public class MyBatisTest +{ + public static void main(String[] args) throws IOException + { + String resource = "com/xdc/basic/example/mybatis/generator/data/mybatis-config.xml"; + Reader reader = Resources.getResourceAsReader(resource); + + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + + /* + * http://mybatis.github.io/mybatis-3/zh/java-api.html#sqlSessions + * 默认的 openSession()方法没有参数,它会创建有如下特性的 SqlSession: + * 1.会开启一个事务(也就是不自动提交)。 + * 2.连接对象会从由活动环境配置的数据源实例中得到。 + * 3.事务隔离级别将会使用驱动或数据源的默认设置。 + * 4.预处理语句不会被复用,也不会批量处理更新。 + */ + SqlSession sqlSession = sqlSessionFactory.openSession(); + + try + { + StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); + + Student student = studentMapper.selectByPrimaryKey(4); + System.out.println("插入前:" + student); + + studentMapper.insert(new Student(4, "耿雪", "女", "计算机科学与技术", "2008")); + + student = studentMapper.selectByPrimaryKey(4); + System.out.println("提交前:" + student); + + // 提交的意义在于:在其他的sqlSession中能够看见语句的结果,而在本身的sqlSession中,无论提交与否,都是可见的。 + sqlSession.commit(); + + student = studentMapper.selectByPrimaryKey(4); + System.out.println("提交后:" + student); + + studentMapper.deleteByPrimaryKey(4); + + sqlSession.commit(); + + student = studentMapper.selectByPrimaryKey(4); + System.out.println("删除后:" + student); + } + finally + { + // 如果在关闭前都没有提交,那么前面的内容将自动回滚。 + sqlSession.close(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/StudentMapper.java b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/StudentMapper.java new file mode 100644 index 00000000..23da8dd1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/StudentMapper.java @@ -0,0 +1,32 @@ +package com.xdc.basic.api.mybatis.generator.data; + +import com.xdc.basic.api.mybatis.generator.model.Student; +import com.xdc.basic.api.mybatis.generator.model.StudentExample; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +public interface StudentMapper { + int countByExample(StudentExample example); + + int deleteByExample(StudentExample example); + + int deleteByPrimaryKey(Integer id); + + int insert(Student record); + + int insertSelective(Student record); + + List selectByExample(StudentExample example); + + Student selectByPrimaryKey(Integer id); + + int updateByExampleSelective(@Param("record") Student record, @Param("example") StudentExample example); + + int updateByExample(@Param("record") Student record, @Param("example") StudentExample example); + + int updateByPrimaryKeySelective(Student record); + + int updateByPrimaryKey(Student record); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/StudentMapper.xml b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/StudentMapper.xml new file mode 100644 index 00000000..20e8a577 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/StudentMapper.xml @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + id, name, gender, major, grade + + + + + delete from student + where id = #{id,jdbcType=INTEGER} + + + delete from student + + + + + + insert into student (id, name, gender, + major, grade) + values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR}, + #{major,jdbcType=VARCHAR}, #{grade,jdbcType=CHAR}) + + + insert into student + + + id, + + + name, + + + gender, + + + major, + + + grade, + + + + + #{id,jdbcType=INTEGER}, + + + #{name,jdbcType=VARCHAR}, + + + #{gender,jdbcType=CHAR}, + + + #{major,jdbcType=VARCHAR}, + + + #{grade,jdbcType=CHAR}, + + + + + + update student + + + id = #{record.id,jdbcType=INTEGER}, + + + name = #{record.name,jdbcType=VARCHAR}, + + + gender = #{record.gender,jdbcType=CHAR}, + + + major = #{record.major,jdbcType=VARCHAR}, + + + grade = #{record.grade,jdbcType=CHAR}, + + + + + + + + update student + set id = #{record.id,jdbcType=INTEGER}, + name = #{record.name,jdbcType=VARCHAR}, + gender = #{record.gender,jdbcType=CHAR}, + major = #{record.major,jdbcType=VARCHAR}, + grade = #{record.grade,jdbcType=CHAR} + + + + + + update student + + + name = #{name,jdbcType=VARCHAR}, + + + gender = #{gender,jdbcType=CHAR}, + + + major = #{major,jdbcType=VARCHAR}, + + + grade = #{grade,jdbcType=CHAR}, + + + where id = #{id,jdbcType=INTEGER} + + + update student + set name = #{name,jdbcType=VARCHAR}, + gender = #{gender,jdbcType=CHAR}, + major = #{major,jdbcType=VARCHAR}, + grade = #{grade,jdbcType=CHAR} + where id = #{id,jdbcType=INTEGER} + + \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/mybatis-config.xml b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/mybatis-config.xml new file mode 100644 index 00000000..b5dc8b1b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/data/mybatis-config.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/model/Student.java b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/model/Student.java new file mode 100644 index 00000000..7eadd5a2 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/model/Student.java @@ -0,0 +1,86 @@ +package com.xdc.basic.api.mybatis.generator.model; + +public class Student +{ + private Integer id; + + private String name; + + private String gender; + + private String major; + + private String grade; + + public Student() + { + super(); + } + + public Student(Integer id, String name, String gender, String major, String grade) + { + super(); + this.id = id; + this.name = name; + this.gender = gender; + this.major = major; + this.grade = grade; + } + + public Integer getId() + { + return id; + } + + public void setId(Integer id) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name == null ? null : name.trim(); + } + + public String getGender() + { + return gender; + } + + public void setGender(String gender) + { + this.gender = gender == null ? null : gender.trim(); + } + + public String getMajor() + { + return major; + } + + public void setMajor(String major) + { + this.major = major == null ? null : major.trim(); + } + + public String getGrade() + { + return grade; + } + + public void setGrade(String grade) + { + this.grade = grade == null ? null : grade.trim(); + } + + @Override + public String toString() + { + return "Student [id=" + id + ", name=" + name + ", gender=" + gender + ", major=" + major + ", grade=" + grade + + "]"; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/model/StudentExample.java b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/model/StudentExample.java new file mode 100644 index 00000000..4503c428 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/model/StudentExample.java @@ -0,0 +1,540 @@ +package com.xdc.basic.api.mybatis.generator.model; + +import java.util.ArrayList; +import java.util.List; + +public class StudentExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + public StudentExample() { + oredCriteria = new ArrayList(); + } + + public void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + public String getOrderByClause() { + return orderByClause; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public List getOredCriteria() { + return oredCriteria; + } + + public void or(Criteria criteria) { + oredCriteria.add(criteria); + } + + public Criteria or() { + Criteria criteria = createCriteriaInternal(); + oredCriteria.add(criteria); + return criteria; + } + + public Criteria createCriteria() { + Criteria criteria = createCriteriaInternal(); + if (oredCriteria.size() == 0) { + oredCriteria.add(criteria); + } + return criteria; + } + + protected Criteria createCriteriaInternal() { + Criteria criteria = new Criteria(); + return criteria; + } + + public void clear() { + oredCriteria.clear(); + orderByClause = null; + distinct = false; + } + + protected abstract static class GeneratedCriteria { + protected List criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List getCriteria() { + return criteria; + } + + protected void addCriterion(String condition) { + if (condition == null) { + throw new RuntimeException("Value for condition cannot be null"); + } + criteria.add(new Criterion(condition)); + } + + protected void addCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value)); + } + + protected void addCriterion(String condition, Object value1, Object value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value1, value2)); + } + + public Criteria andIdIsNull() { + addCriterion("id is null"); + return (Criteria) this; + } + + public Criteria andIdIsNotNull() { + addCriterion("id is not null"); + return (Criteria) this; + } + + public Criteria andIdEqualTo(Integer value) { + addCriterion("id =", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotEqualTo(Integer value) { + addCriterion("id <>", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThan(Integer value) { + addCriterion("id >", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThanOrEqualTo(Integer value) { + addCriterion("id >=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThan(Integer value) { + addCriterion("id <", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThanOrEqualTo(Integer value) { + addCriterion("id <=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdIn(List values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List values) { + addCriterion("id not in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdBetween(Integer value1, Integer value2) { + addCriterion("id between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andIdNotBetween(Integer value1, Integer value2) { + addCriterion("id not between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andNameIsNull() { + addCriterion("name is null"); + return (Criteria) this; + } + + public Criteria andNameIsNotNull() { + addCriterion("name is not null"); + return (Criteria) this; + } + + public Criteria andNameEqualTo(String value) { + addCriterion("name =", value, "name"); + return (Criteria) this; + } + + public Criteria andNameNotEqualTo(String value) { + addCriterion("name <>", value, "name"); + return (Criteria) this; + } + + public Criteria andNameGreaterThan(String value) { + addCriterion("name >", value, "name"); + return (Criteria) this; + } + + public Criteria andNameGreaterThanOrEqualTo(String value) { + addCriterion("name >=", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLessThan(String value) { + addCriterion("name <", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLessThanOrEqualTo(String value) { + addCriterion("name <=", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLike(String value) { + addCriterion("name like", value, "name"); + return (Criteria) this; + } + + public Criteria andNameNotLike(String value) { + addCriterion("name not like", value, "name"); + return (Criteria) this; + } + + public Criteria andNameIn(List values) { + addCriterion("name in", values, "name"); + return (Criteria) this; + } + + public Criteria andNameNotIn(List values) { + addCriterion("name not in", values, "name"); + return (Criteria) this; + } + + public Criteria andNameBetween(String value1, String value2) { + addCriterion("name between", value1, value2, "name"); + return (Criteria) this; + } + + public Criteria andNameNotBetween(String value1, String value2) { + addCriterion("name not between", value1, value2, "name"); + return (Criteria) this; + } + + public Criteria andGenderIsNull() { + addCriterion("gender is null"); + return (Criteria) this; + } + + public Criteria andGenderIsNotNull() { + addCriterion("gender is not null"); + return (Criteria) this; + } + + public Criteria andGenderEqualTo(String value) { + addCriterion("gender =", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderNotEqualTo(String value) { + addCriterion("gender <>", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderGreaterThan(String value) { + addCriterion("gender >", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderGreaterThanOrEqualTo(String value) { + addCriterion("gender >=", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderLessThan(String value) { + addCriterion("gender <", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderLessThanOrEqualTo(String value) { + addCriterion("gender <=", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderLike(String value) { + addCriterion("gender like", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderNotLike(String value) { + addCriterion("gender not like", value, "gender"); + return (Criteria) this; + } + + public Criteria andGenderIn(List values) { + addCriterion("gender in", values, "gender"); + return (Criteria) this; + } + + public Criteria andGenderNotIn(List values) { + addCriterion("gender not in", values, "gender"); + return (Criteria) this; + } + + public Criteria andGenderBetween(String value1, String value2) { + addCriterion("gender between", value1, value2, "gender"); + return (Criteria) this; + } + + public Criteria andGenderNotBetween(String value1, String value2) { + addCriterion("gender not between", value1, value2, "gender"); + return (Criteria) this; + } + + public Criteria andMajorIsNull() { + addCriterion("major is null"); + return (Criteria) this; + } + + public Criteria andMajorIsNotNull() { + addCriterion("major is not null"); + return (Criteria) this; + } + + public Criteria andMajorEqualTo(String value) { + addCriterion("major =", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorNotEqualTo(String value) { + addCriterion("major <>", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorGreaterThan(String value) { + addCriterion("major >", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorGreaterThanOrEqualTo(String value) { + addCriterion("major >=", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorLessThan(String value) { + addCriterion("major <", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorLessThanOrEqualTo(String value) { + addCriterion("major <=", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorLike(String value) { + addCriterion("major like", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorNotLike(String value) { + addCriterion("major not like", value, "major"); + return (Criteria) this; + } + + public Criteria andMajorIn(List values) { + addCriterion("major in", values, "major"); + return (Criteria) this; + } + + public Criteria andMajorNotIn(List values) { + addCriterion("major not in", values, "major"); + return (Criteria) this; + } + + public Criteria andMajorBetween(String value1, String value2) { + addCriterion("major between", value1, value2, "major"); + return (Criteria) this; + } + + public Criteria andMajorNotBetween(String value1, String value2) { + addCriterion("major not between", value1, value2, "major"); + return (Criteria) this; + } + + public Criteria andGradeIsNull() { + addCriterion("grade is null"); + return (Criteria) this; + } + + public Criteria andGradeIsNotNull() { + addCriterion("grade is not null"); + return (Criteria) this; + } + + public Criteria andGradeEqualTo(String value) { + addCriterion("grade =", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeNotEqualTo(String value) { + addCriterion("grade <>", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeGreaterThan(String value) { + addCriterion("grade >", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeGreaterThanOrEqualTo(String value) { + addCriterion("grade >=", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeLessThan(String value) { + addCriterion("grade <", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeLessThanOrEqualTo(String value) { + addCriterion("grade <=", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeLike(String value) { + addCriterion("grade like", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeNotLike(String value) { + addCriterion("grade not like", value, "grade"); + return (Criteria) this; + } + + public Criteria andGradeIn(List values) { + addCriterion("grade in", values, "grade"); + return (Criteria) this; + } + + public Criteria andGradeNotIn(List values) { + addCriterion("grade not in", values, "grade"); + return (Criteria) this; + } + + public Criteria andGradeBetween(String value1, String value2) { + addCriterion("grade between", value1, value2, "grade"); + return (Criteria) this; + } + + public Criteria andGradeNotBetween(String value1, String value2) { + addCriterion("grade not between", value1, value2, "grade"); + return (Criteria) this; + } + } + + public static class Criteria extends GeneratedCriteria { + + protected Criteria() { + super(); + } + } + + public static class Criterion { + private String condition; + + private Object value; + + private Object secondValue; + + private boolean noValue; + + private boolean singleValue; + + private boolean betweenValue; + + private boolean listValue; + + private String typeHandler; + + public String getCondition() { + return condition; + } + + public Object getValue() { + return value; + } + + public Object getSecondValue() { + return secondValue; + } + + public boolean isNoValue() { + return noValue; + } + + public boolean isSingleValue() { + return singleValue; + } + + public boolean isBetweenValue() { + return betweenValue; + } + + public boolean isListValue() { + return listValue; + } + + public String getTypeHandler() { + return typeHandler; + } + + protected Criterion(String condition) { + super(); + this.condition = condition; + this.typeHandler = null; + this.noValue = true; + } + + protected Criterion(String condition, Object value, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.typeHandler = typeHandler; + if (value instanceof List) { + this.listValue = true; + } else { + this.singleValue = true; + } + } + + protected Criterion(String condition, Object value) { + this(condition, value, null); + } + + protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.secondValue = secondValue; + this.typeHandler = typeHandler; + this.betweenValue = true; + } + + protected Criterion(String condition, Object value, Object secondValue) { + this(condition, value, secondValue, null); + } + } +} \ No newline at end of file diff --git "a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/MyBatis Generator \344\273\243\347\240\201\347\224\237\346\210\220\345\267\245\345\205\267 -- \346\234\254\344\276\213\350\256\276\347\275\256.zip" "b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/MyBatis Generator \344\273\243\347\240\201\347\224\237\346\210\220\345\267\245\345\205\267 -- \346\234\254\344\276\213\350\256\276\347\275\256.zip" new file mode 100644 index 00000000..b6cdee3e Binary files /dev/null and "b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/MyBatis Generator \344\273\243\347\240\201\347\224\237\346\210\220\345\267\245\345\205\267 -- \346\234\254\344\276\213\350\256\276\347\275\256.zip" differ diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/student_mysql.sql b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/student_mysql.sql new file mode 100644 index 00000000..0816d066 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/student_mysql.sql @@ -0,0 +1,25 @@ +/*创建college数据库*/ +drop database if exists college; +create database college; + +/*切换到college数据库*/ +use college; + +/*创建学生表*/ +CREATE TABLE student( + id int NOT NULL AUTO_INCREMENT primary key, + name varchar(10) NOT NULL,/*姓名*/ + gender char(1) NOT NULL,/*性别*/ + major varchar(20) NOT NULL,/*专业*/ + grade char(4) NOT NULL/*年级*/ +); + +/*授予college用户访问college数据库的全部权限。为方便起见,用户名与数据库同名。 +该用户若不存在则被创建,密码为123456*/ +grant all privileges on college.* to college@'%' identified by '123456'; +flush privileges; + +/*添加记录*/ +insert into student(name, gender, major, grade)values('徐大超','男','计算机科学与技术','2008'); +insert into student(name, gender, major, grade)values('王梓维','男','计算机科学与技术','2008'); +insert into student(name, gender, major, grade)values('陈冲','女','计算机科学与技术','2008'); diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/student_oracle.sql b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/student_oracle.sql new file mode 100644 index 00000000..7a42811a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/generator/other/student_oracle.sql @@ -0,0 +1,15 @@ +/*在system用户下执行*/ + +/*添加记录*/ +CREATE TABLE student( + id int NOT NULL primary key, + name varchar(20) NOT NULL,/*姓名*/ + gender char(10) NOT NULL,/*性别*/ + major varchar(50) NOT NULL,/*专业*/ + grade char(4) NOT NULL/*年级*/ +); + +/*添加记录*/ +insert into student(id, name, gender, major, grade)values('1','徐大超','男','计算机科学与技术','2008'); +insert into student(id, name, gender, major, grade)values('2','王梓维','男','计算机科学与技术','2008'); +insert into student(id, name, gender, major, grade)values('3','陈冲','女','计算机科学与技术','2008'); diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/MyBatisTest.java b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/MyBatisTest.java new file mode 100644 index 00000000..96fa9687 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/MyBatisTest.java @@ -0,0 +1,64 @@ +package com.xdc.basic.api.mybatis.manual; + +import java.io.IOException; +import java.io.Reader; + +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; + +import com.xdc.basic.api.mybatis.manual.data.StudentMapper; +import com.xdc.basic.api.mybatis.manual.model.Student; + +public class MyBatisTest +{ + public static void main(String[] args) throws IOException + { + String resource = "com/xdc/basic/example/mybatis/manual/data/mybatis-config.xml"; + Reader reader = Resources.getResourceAsReader(resource); + + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + + /* + * http://mybatis.github.io/mybatis-3/zh/java-api.html#sqlSessions + * 默认的 openSession()方法没有参数,它会创建有如下特性的 SqlSession: + * 1.会开启一个事务(也就是不自动提交)。 + * 2.连接对象会从由活动环境配置的数据源实例中得到。 + * 3.事务隔离级别将会使用驱动或数据源的默认设置。 + * 4.预处理语句不会被复用,也不会批量处理更新。 + */ + SqlSession sqlSession = sqlSessionFactory.openSession(); + + try + { + StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); + + Student student = studentMapper.selectByPrimaryKey(4); + System.out.println("插入前:" + student); + + studentMapper.insert(new Student(4, "耿雪", "女", "计算机科学与技术", "2008")); + + student = studentMapper.selectByPrimaryKey(4); + System.out.println("提交前:" + student); + + // 提交的意义在于:在其他的sqlSession中能够看见语句的结果,而在本身的sqlSession中,无论提交与否,都是可见的。 + sqlSession.commit(); + + student = studentMapper.selectByPrimaryKey(4); + System.out.println("提交后:" + student); + + studentMapper.deleteByPrimaryKey(4); + + sqlSession.commit(); + + student = studentMapper.selectByPrimaryKey(4); + System.out.println("删除后:" + student); + } + finally + { + // 如果在关闭前都没有提交,那么前面的内容将自动回滚。 + sqlSession.close(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/StudentMapper.java b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/StudentMapper.java new file mode 100644 index 00000000..1bea2409 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/StudentMapper.java @@ -0,0 +1,14 @@ +package com.xdc.basic.api.mybatis.manual.data; + +import com.xdc.basic.api.mybatis.manual.model.Student; + +public interface StudentMapper +{ + int insert(Student record); + + int deleteByPrimaryKey(Integer id); + + Student selectByPrimaryKey(Integer id); + + int updateByPrimaryKey(Student record); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/StudentMapper.xml b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/StudentMapper.xml new file mode 100644 index 00000000..c8562e36 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/StudentMapper.xml @@ -0,0 +1,38 @@ + + + + + + insert into + student (id, name, gender, major, grade) + values + (#{id}, #{name}, #{gender}, #{major}, #{grade}) + + + + delete from + student + where id = #{id} + + + + update + student + set + name = #{name}, + gender = #{gender}, + major = #{major}, + grade = #{grade} + where id = #{id} + + + + + \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/mybatis-config.xml b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/mybatis-config.xml new file mode 100644 index 00000000..b52e77b0 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/data/mybatis-config.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/model/Student.java b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/model/Student.java new file mode 100644 index 00000000..2541b673 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/model/Student.java @@ -0,0 +1,86 @@ +package com.xdc.basic.api.mybatis.manual.model; + +public class Student +{ + private Integer id; + + private String name; + + private String gender; + + private String major; + + private String grade; + + public Student() + { + super(); + } + + public Student(Integer id, String name, String gender, String major, String grade) + { + super(); + this.id = id; + this.name = name; + this.gender = gender; + this.major = major; + this.grade = grade; + } + + public Integer getId() + { + return id; + } + + public void setId(Integer id) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name == null ? null : name.trim(); + } + + public String getGender() + { + return gender; + } + + public void setGender(String gender) + { + this.gender = gender == null ? null : gender.trim(); + } + + public String getMajor() + { + return major; + } + + public void setMajor(String major) + { + this.major = major == null ? null : major.trim(); + } + + public String getGrade() + { + return grade; + } + + public void setGrade(String grade) + { + this.grade = grade == null ? null : grade.trim(); + } + + @Override + public String toString() + { + return "Student [id=" + id + ", name=" + name + ", gender=" + gender + ", major=" + major + ", grade=" + grade + + "]"; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/other/student_mysql.sql b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/other/student_mysql.sql new file mode 100644 index 00000000..0816d066 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/other/student_mysql.sql @@ -0,0 +1,25 @@ +/*创建college数据库*/ +drop database if exists college; +create database college; + +/*切换到college数据库*/ +use college; + +/*创建学生表*/ +CREATE TABLE student( + id int NOT NULL AUTO_INCREMENT primary key, + name varchar(10) NOT NULL,/*姓名*/ + gender char(1) NOT NULL,/*性别*/ + major varchar(20) NOT NULL,/*专业*/ + grade char(4) NOT NULL/*年级*/ +); + +/*授予college用户访问college数据库的全部权限。为方便起见,用户名与数据库同名。 +该用户若不存在则被创建,密码为123456*/ +grant all privileges on college.* to college@'%' identified by '123456'; +flush privileges; + +/*添加记录*/ +insert into student(name, gender, major, grade)values('徐大超','男','计算机科学与技术','2008'); +insert into student(name, gender, major, grade)values('王梓维','男','计算机科学与技术','2008'); +insert into student(name, gender, major, grade)values('陈冲','女','计算机科学与技术','2008'); diff --git a/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/other/student_oracle.sql b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/other/student_oracle.sql new file mode 100644 index 00000000..7a42811a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/mybatis/manual/other/student_oracle.sql @@ -0,0 +1,15 @@ +/*在system用户下执行*/ + +/*添加记录*/ +CREATE TABLE student( + id int NOT NULL primary key, + name varchar(20) NOT NULL,/*姓名*/ + gender char(10) NOT NULL,/*性别*/ + major varchar(50) NOT NULL,/*专业*/ + grade char(4) NOT NULL/*年级*/ +); + +/*添加记录*/ +insert into student(id, name, gender, major, grade)values('1','徐大超','男','计算机科学与技术','2008'); +insert into student(id, name, gender, major, grade)values('2','王梓维','男','计算机科学与技术','2008'); +insert into student(id, name, gender, major, grade)values('3','陈冲','女','计算机科学与技术','2008'); diff --git a/basicKnowledge/src/com/xdc/basic/api/nio/CopyFile.java b/basicKnowledge/src/com/xdc/basic/api/nio/CopyFile.java new file mode 100644 index 00000000..e0344fc0 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/nio/CopyFile.java @@ -0,0 +1,46 @@ +package com.xdc.basic.api.nio; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +public class CopyFile +{ + @SuppressWarnings("resource") + static public void main(String args[]) throws Exception + { + if (args.length < 2) + { + System.err.println("Usage: java CopyFile infile outfile"); + System.exit(1); + } + + String infile = args[0]; + String outfile = args[1]; + + FileInputStream fin = new FileInputStream(infile); + FileOutputStream fout = new FileOutputStream(outfile); + + FileChannel fcin = fin.getChannel(); + FileChannel fcout = fout.getChannel(); + + ByteBuffer buffer = ByteBuffer.allocate(1024); + + while (true) + { + buffer.clear(); + + int r = fcin.read(buffer); + + if (r == -1) + { + break; + } + + buffer.flip(); + + fcout.write(buffer); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/nio/ReadAndShow.java b/basicKnowledge/src/com/xdc/basic/api/nio/ReadAndShow.java new file mode 100644 index 00000000..a6e9b8b2 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/nio/ReadAndShow.java @@ -0,0 +1,30 @@ +package com.xdc.basic.api.nio; + +import java.io.FileInputStream; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +public class ReadAndShow +{ + static public void main(String args[]) throws Exception + { + FileInputStream fin = new FileInputStream("readandshow.txt"); + FileChannel fc = fin.getChannel(); + + ByteBuffer buffer = ByteBuffer.allocate(1024); + + fc.read(buffer); + + buffer.flip(); + + int i = 0; + while (buffer.remaining() > 0) + { + byte b = buffer.get(); + System.out.println("Character " + i + ": " + ((char) b)); + i++; + } + + fin.close(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/ReflectionTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/ReflectionTest.java new file mode 100644 index 00000000..5c2182b7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/ReflectionTest.java @@ -0,0 +1,140 @@ +package com.xdc.basic.api.reflection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Test; + +public class ReflectionTest +{ + /** + * 反射基本样例 + */ + @Test + public void reflectionDemo() + { + // 在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中: + // Class类:代表一个类。 + // Field类:代表类的成员变量(成员变量也称为类的属性)。 + // Method类:代表类的方法。 + // Constructor类:代表类的构造方法。 + // Array类:提供了动态创建数组,以及访问数组的元素的静态方法。 + + // 要想使用反射,首先需要获得待处理类或对象所对应的Class对象。 + // 获取某个类或某个对象所对应的class对象的常用的3种方式: + // 1. 使用Class类的静态方法forName:Class.forName(“java.lang.String”); + // 2. 使用类的.class语法:String.class; + // 3. 使用对象的getClass()方法:String s = “abc”; Class clazz = s.getClass(); + + // Class类是Reflection API中的核心类,它有以下方法 + // getName():获得类的完整名字。 + // getFields():获得类的public类型的属性。 + // getDeclaredFields():获得类的所有属性。 + // getMethods():获得类的public类型的方法。 + // getDeclaredMethods():获得类的所有方法。 + // getMethod(String name,Class[]parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。 + // getConstructors():获得类的public类型的构造方法。 + // getDeclaredConstructors:获得类的所有构造方法。 + // getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。 + // newInstance():通过类的不带参数的构造方法创建这个类的一个对象。 + + Class clazz = Student.class; + + String name = clazz.getName(); + System.out.println(name); + + Field[] fields = clazz.getFields(); + System.out.println(ArrayUtils.toString(fields)); + + Field[] declaredFields = clazz.getDeclaredFields(); + System.out.println(ArrayUtils.toString(declaredFields)); + + Method[] methods = clazz.getMethods(); + System.out.println(ArrayUtils.toString(methods)); + + Method[] declaredMethods = clazz.getDeclaredMethods(); + System.out.println(ArrayUtils.toString(declaredMethods)); + + Constructor[] constructors = clazz.getConstructors(); + System.out.println(ArrayUtils.toString(constructors)); + + Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); + System.out.println(ArrayUtils.toString(declaredConstructors)); + } + + /** + * 调用私有方法 + * + * @throws NoSuchMethodException + * @throws SecurityException + * @throws InstantiationException + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + */ + @Test + public void invokePrivateMethod() throws NoSuchMethodException, SecurityException, InstantiationException, + IllegalAccessException, IllegalArgumentException, InvocationTargetException + { + Class clazz = Student.class; + + Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class); + constructor.setAccessible(true); + Student student = constructor.newInstance("xudachao", 25); + System.out.println(student); + + Method method = clazz.getDeclaredMethod("eat", String.class); + method.setAccessible(true); + method.invoke(student, "egg"); + } + + /** + * 修改私有属性(即使没有set和get方法) + * + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws SecurityException + * @throws NoSuchMethodException + * @throws NoSuchFieldException + */ + @Test + public void modifyPrivateField() throws InstantiationException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException + { + Class clazz = Student.class; + + Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class); + constructor.setAccessible(true); + Student student = constructor.newInstance("xudachao", 25); + System.out.println(student); + + Field ageField = clazz.getDeclaredField("age"); + ageField.setAccessible(true); + ageField.set(student, 26); + System.out.println(student); + } + + /** + * 一个类对应的class对象只会加载一次 + * + * @throws ClassNotFoundException + */ + @Test + public void ClassLoaderTest() throws ClassNotFoundException + { + Class c1 = String.class; + + Class c2 = Class.forName("java.lang.String"); + + String str = "Just do it."; + Class c3 = str.getClass(); + + System.out.println(c1 == c2); + System.out.println(c1 == c3); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/Student.java b/basicKnowledge/src/com/xdc/basic/api/reflection/Student.java new file mode 100644 index 00000000..506e5c09 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/Student.java @@ -0,0 +1,47 @@ +package com.xdc.basic.api.reflection; + +public class Student +{ + public String name; + private int age; + + public Student() + { + super(); + } + + @SuppressWarnings("unused") + private Student(String name, int age) + { + super(); + this.name = name; + this.age = age; + } + + public int getAge() + { + return age; + } + + public void setAge(int age) + { + this.age = age; + } + + public void study() + { + System.out.println("I study all day and night."); + } + + @SuppressWarnings("unused") + private void eat(String food) + { + System.out.println("I'm eating " + food + ". I'm a foodie."); + } + + @Override + public String toString() + { + return "Student [name=" + name + ", age=" + age + "]"; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/AnnotationTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/AnnotationTest.java new file mode 100644 index 00000000..30445b08 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/AnnotationTest.java @@ -0,0 +1,46 @@ +package com.xdc.basic.api.reflection.annotation; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; + +/** + * http://blog.csdn.net/sooneasy/article/details/4384888 + * + * @author xdc + * + */ +public class AnnotationTest +{ + /** + * author lighter 说明:具体关天Annotation的API的用法请参见javaDoc文档 + */ + public static void main(String[] args) throws Exception + { + String CLASS_NAME = "com.xdc.basic.apidemo.annotation.JavaEyer"; + Class test = Class.forName(CLASS_NAME); + Method[] method = test.getMethods(); + boolean flag = test.isAnnotationPresent(Description.class); + if (flag) + { + Description des = (Description) test.getAnnotation(Description.class); + System.out.println("描述:" + des.value()); + System.out.println("-----------------"); + } + + // 把JavaEyer这一类有利用到@Name的全部方法保存到Set中去 + Set set = new HashSet(); + for (int i = 0; i < method.length; i++) + { + boolean otherFlag = method[i].isAnnotationPresent(Name.class); + if (otherFlag) + set.add(method[i]); + } + for (Method m : set) + { + Name name = m.getAnnotation(Name.class); + System.out.println(name.originate()); + System.out.println("创建的社区:" + name.community()); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/Description.java b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/Description.java new file mode 100644 index 00000000..5cbcca98 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/Description.java @@ -0,0 +1,15 @@ +package com.xdc.basic.api.reflection.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Description +{ + String value(); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/JavaEyer.java b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/JavaEyer.java new file mode 100644 index 00000000..17495b74 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/JavaEyer.java @@ -0,0 +1,17 @@ +package com.xdc.basic.api.reflection.annotation; + +@Description("javaeye,做最棒的软件开发交流社区") +public class JavaEyer +{ + @Name(originate = "创始人:robbin", community = "javaEye") + public String getName() + { + return null; + } + + @Name(originate = "创始人:江南白衣", community = "springside") + public String getName2() + { + return "借用两位的id一用,写这一个例子,请见谅!"; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/Name.java b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/Name.java new file mode 100644 index 00000000..79899960 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/annotation/Name.java @@ -0,0 +1,18 @@ +package com.xdc.basic.api.reflection.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +//注意这里的@Target与Description里的不同,参数成员也不同 +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Name +{ + String originate(); + + String community(); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessBar.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessBar.java new file mode 100644 index 00000000..00ab3d20 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessBar.java @@ -0,0 +1,6 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxycglib; + +public interface BusinessBar +{ + String bar(String message); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessBarImpl.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessBarImpl.java new file mode 100644 index 00000000..5098d41b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessBarImpl.java @@ -0,0 +1,10 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxycglib; + +public class BusinessBarImpl implements BusinessBar +{ + public String bar(String message) + { + System.out.println("BusinessBarImpl.bar()"); + return message; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessFoo.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessFoo.java new file mode 100644 index 00000000..60c2b385 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessFoo.java @@ -0,0 +1,6 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxycglib; + +public interface BusinessFoo +{ + void foo(); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessFooImpl.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessFooImpl.java new file mode 100644 index 00000000..d8c50801 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessFooImpl.java @@ -0,0 +1,9 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxycglib; + +public class BusinessFooImpl implements BusinessFoo +{ + public void foo() + { + System.out.println("BusinessFooImpl.foo()"); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessImplCglibProxy.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessImplCglibProxy.java new file mode 100644 index 00000000..db0c1111 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/BusinessImplCglibProxy.java @@ -0,0 +1,39 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxycglib; + +import java.lang.reflect.Method; + +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.MethodInterceptor; +import org.springframework.cglib.proxy.MethodProxy; + +class BusinessImplCglibProxy implements MethodInterceptor +{ + @Override + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable + { + doBefore(); + Object result = proxy.invokeSuper(obj, args); + doAfter(); + return result; + } + + private void doBefore() + { + System.out.println("前置处理!"); + } + + private void doAfter() + { + System.out.println("后置处理!"); + } + + public static Object factory(Class clazz) + { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(clazz); + // 回调方法 + enhancer.setCallback(new BusinessImplCglibProxy()); + // 创建代理对象 + return enhancer.create(); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/DynamicProxyTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/DynamicProxyTest.java new file mode 100644 index 00000000..b3f118e6 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxycglib/DynamicProxyTest.java @@ -0,0 +1,16 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxycglib; + +public class DynamicProxyTest +{ + public static void main(String[] args) + { + // 不依赖接口,也无需创建BusinessFooImpl实例,cglib自动创建BusinessFooImpl的子类的实例 + BusinessFooImpl bf = (BusinessFooImpl) BusinessImplCglibProxy.factory(BusinessFooImpl.class); + bf.foo(); + System.out.println(); + + BusinessBarImpl bb = (BusinessBarImpl) BusinessImplCglibProxy.factory(BusinessBarImpl.class); + String message = bb.bar("Hello,World"); + System.out.println(message); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessBar.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessBar.java new file mode 100644 index 00000000..5f78444d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessBar.java @@ -0,0 +1,6 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxyjdk; + +public interface BusinessBar +{ + String bar(String message); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessBarImpl.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessBarImpl.java new file mode 100644 index 00000000..6cbf0b70 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessBarImpl.java @@ -0,0 +1,10 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxyjdk; + +public class BusinessBarImpl implements BusinessBar +{ + public String bar(String message) + { + System.out.println("BusinessBarImpl.bar()"); + return message; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessFoo.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessFoo.java new file mode 100644 index 00000000..f58aeabe --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessFoo.java @@ -0,0 +1,6 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxyjdk; + +public interface BusinessFoo +{ + void foo(); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessFooImpl.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessFooImpl.java new file mode 100644 index 00000000..a4b9b2e3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessFooImpl.java @@ -0,0 +1,9 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxyjdk; + +public class BusinessFooImpl implements BusinessFoo +{ + public void foo() + { + System.out.println("BusinessFooImpl.foo()"); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessImplJdkProxy.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessImplJdkProxy.java new file mode 100644 index 00000000..1243e6ed --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/BusinessImplJdkProxy.java @@ -0,0 +1,49 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxyjdk; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +class BusinessImplJdkProxy implements InvocationHandler +{ + private Object targetObject; + + public BusinessImplJdkProxy() + { + super(); + } + + public BusinessImplJdkProxy(Object obj) + { + super(); + this.targetObject = obj; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + doBefore(); + Object result = method.invoke(targetObject, args); + doAfter(); + return result; + } + + private void doBefore() + { + System.out.println("前置处理!"); + } + + private void doAfter() + { + System.out.println("后置处理!"); + } + + public static Object factory(Object obj) + { + Class clazz = obj.getClass(); + ClassLoader classLoader = clazz.getClassLoader(); + Class[] interfaces = clazz.getInterfaces(); + + //取得代理对象, 要绑定接口(这是jdk动态代理的一个缺陷,cglib动态代理弥补了这一缺陷) + return Proxy.newProxyInstance(classLoader, interfaces, new BusinessImplJdkProxy(obj)); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/DynamicProxyTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/DynamicProxyTest.java new file mode 100644 index 00000000..c15fd85a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/dynamicproxyjdk/DynamicProxyTest.java @@ -0,0 +1,17 @@ +package com.xdc.basic.api.reflection.proxy.comparison.dynamicproxyjdk; + +public class DynamicProxyTest +{ + public static void main(String[] args) + { + BusinessFooImpl bfoo = new BusinessFooImpl(); + BusinessFoo bf = (BusinessFoo) BusinessImplJdkProxy.factory(bfoo); + bf.foo(); + System.out.println(); + + BusinessBarImpl bbar = new BusinessBarImpl(); + BusinessBar bb = (BusinessBar) BusinessImplJdkProxy.factory(bbar); + String message = bb.bar("Hello,World"); + System.out.println(message); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/Business.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/Business.java new file mode 100644 index 00000000..363db0e8 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/Business.java @@ -0,0 +1,8 @@ +package com.xdc.basic.api.reflection.proxy.comparison.staticproxy; + +public interface Business +{ + void doAction(); + + void doAction2(); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/BusinessImpl.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/BusinessImpl.java new file mode 100644 index 00000000..ae4ef052 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/BusinessImpl.java @@ -0,0 +1,16 @@ +package com.xdc.basic.api.reflection.proxy.comparison.staticproxy; + +public class BusinessImpl implements Business +{ + @Override + public void doAction() + { + System.out.println("do action."); + } + + @Override + public void doAction2() + { + System.out.println("do action2."); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/BusinessImplProxy.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/BusinessImplProxy.java new file mode 100644 index 00000000..1042c46a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/BusinessImplProxy.java @@ -0,0 +1,54 @@ +package com.xdc.basic.api.reflection.proxy.comparison.staticproxy; + +class BusinessImplProxy implements Business +{ + private BusinessImpl businessImpl; + + public BusinessImplProxy() + { + super(); + } + + public BusinessImplProxy(BusinessImpl businessImpl) + { + super(); + this.businessImpl = businessImpl; + } + + @Override + public void doAction() + { + if (businessImpl == null) + { + businessImpl = new BusinessImpl(); + } + + doBefore(); + businessImpl.doAction(); + doAfter(); + } + + @Override + public void doAction2() + { + if (businessImpl == null) + { + businessImpl = new BusinessImpl(); + } + + doBefore(); + businessImpl.doAction2(); + doAfter(); + + } + + private void doBefore() + { + System.out.println("前置处理!"); + } + + private void doAfter() + { + System.out.println("后置处理!"); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/StaticProxyTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/StaticProxyTest.java new file mode 100644 index 00000000..6309e734 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/comparison/staticproxy/StaticProxyTest.java @@ -0,0 +1,12 @@ +package com.xdc.basic.api.reflection.proxy.comparison.staticproxy; + +public class StaticProxyTest +{ + public static void main(String[] args) + { + BusinessImpl businessImpl = new BusinessImpl(); + BusinessImplProxy businessImplProxy = new BusinessImplProxy(businessImpl); + businessImplProxy.doAction(); + businessImplProxy.doAction2(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/After.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/After.java new file mode 100644 index 00000000..cd3cdba3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/After.java @@ -0,0 +1,9 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +/** + * 后置增强接口 + */ +public interface After +{ + public void after(); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/AopTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/AopTest.java new file mode 100644 index 00000000..ca16cf19 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/AopTest.java @@ -0,0 +1,53 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +public class AopTest +{ + public static void main(String[] args) + { + Before before = new Before() + { + public void before() + { + System.out.println("...before..."); + } + }; + + After after = new After() + { + public void after() + { + System.out.println("...after..."); + } + }; + + Hello hello = null; + + // 普通方法执行 + System.out.println("-------------普通执行-------------"); + hello = new HelloEnglish(); + hello.sayHello("bao110908"); + hello.sayHi("bao110908"); + System.out.println(); + + // 切入方法执行前(前置增强) + System.out.println("-------------前置增强-------------"); + hello = HelloAopManager.getHelloProxy(new HelloEnglish(), before); + hello.sayHello("bao110908"); + hello.sayHi("bao110908"); // sayHi 方法没有标注 @Enhancement 所以不会进行代码切入 + System.out.println(); + + // 切入方法执行后(后置增强) + System.out.println("-------------后置增强-------------"); + hello = HelloAopManager.getHelloProxy(new HelloEnglish(), after); + hello.sayHello("bao110908"); + hello.sayHi("bao110908"); + System.out.println(); + + // 切入方法执行前和执行后(环绕增强) + System.out.println("-------------环绕增强-------------"); + hello = HelloAopManager.getHelloProxy(new HelloEnglish(), before, after); + hello.sayHello("bao110908"); + hello.sayHi("bao110908"); + System.out.println(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Before.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Before.java new file mode 100644 index 00000000..9e0a26ae --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Before.java @@ -0,0 +1,9 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +/** + * 前置增强接口 + */ +public interface Before +{ + public void before(); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Enhancement.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Enhancement.java new file mode 100644 index 00000000..941777b9 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Enhancement.java @@ -0,0 +1,16 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * 有此注解的方法,才需要被增强 + * + * @author xdc + * + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface Enhancement +{ + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Hello.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Hello.java new file mode 100644 index 00000000..3c636ff3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/Hello.java @@ -0,0 +1,9 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +public interface Hello +{ + @Enhancement + public void sayHello(String name); + + public void sayHi(String name); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloAopManager.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloAopManager.java new file mode 100644 index 00000000..f1cb006a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloAopManager.java @@ -0,0 +1,32 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +public class HelloAopManager +{ + private HelloAopManager() + { + } + + public static Hello getHelloProxy(Hello hello, Before before) + { + return getHelloProxy(hello, before, null); + } + + public static Hello getHelloProxy(Hello hello, After after) + { + return getHelloProxy(hello, null, after); + } + + public static Hello getHelloProxy(Hello hello, Before before, After after) + { + HelloHandler handler = new HelloHandler(); + if (before != null) + { + handler.setBefore(before); + } + if (after != null) + { + handler.setAfter(after); + } + return handler.bind(hello); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloChinese.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloChinese.java new file mode 100644 index 00000000..f8a97ba5 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloChinese.java @@ -0,0 +1,14 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +public class HelloChinese implements Hello +{ + public void sayHello(String name) + { + System.out.println(name + ",您好"); + } + + public void sayHi(String name) + { + System.out.println("哈啰," + name); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloEnglish.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloEnglish.java new file mode 100644 index 00000000..3cf55785 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloEnglish.java @@ -0,0 +1,14 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +public class HelloEnglish implements Hello +{ + public void sayHello(String name) + { + System.out.println("Hello, " + name); + } + + public void sayHi(String name) + { + System.out.println("hi, " + name); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloHandler.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloHandler.java new file mode 100644 index 00000000..406928e8 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo1/HelloHandler.java @@ -0,0 +1,75 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo1; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +public class HelloHandler implements InvocationHandler +{ + /** + * 需要进行代理的实例 + */ + private Hello hello = null; + + /** + * 前置增强 + */ + private Before before = null; + + /** + * 后置增强 + */ + private After after = null; + + /** + * InvocationHandler 接口的实现方法,进行动态代理 + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + // 看看接口中方法是否标注了需要 Enhancement, 有的话需要增强 + boolean needEnhancement = method.isAnnotationPresent(Enhancement.class); + if (!needEnhancement) + { + // 没有标注的话,按原方法执行 + return method.invoke(hello, args); + } + + // 有标注的话,进行方法的前置和后置增强 + if (before != null) + { + before.before(); + } + Object obj = method.invoke(hello, args); + if (after != null) + { + after.after(); + } + + return obj; + } + + /** + * 将传入的 Hello 与 InvocationHandler 进行绑定,以获得代理类的实例 + * + * @param hello + * @return + */ + public Hello bind(Hello hello) + { + this.hello = hello; + Hello helloProxy = (Hello) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass() + .getInterfaces(), this); + return helloProxy; + } + + public void setAfter(After after) + { + this.after = after; + } + + public void setBefore(Before before) + { + this.before = before; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/AOPTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/AOPTest.java new file mode 100644 index 00000000..3166d04f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/AOPTest.java @@ -0,0 +1,18 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo2; + +public class AOPTest +{ + public static void main(String[] args) + { + // 使用Proxy类实现: + // 1. 拦截所有业务方法 + // 2. 判断用户是否有权限,有权限就允许他执行业务方法,没有权限不允许他执行业务方法(是否有权限是根据user是否为null作为判断依据) + JDKProxyFactory factory = new JDKProxyFactory(); + + BankService service = (BankService) factory.createProxyInstance(new BankServiceImpl()); + service.payMoneyInto(100); + + BankService servicewithUser = (BankService) factory.createProxyInstance(new BankServiceImpl("xudachao")); + servicewithUser.payMoneyInto(100); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/BankService.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/BankService.java new file mode 100644 index 00000000..c93a529a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/BankService.java @@ -0,0 +1,18 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo2; + +public interface BankService +{ + /** + * 存钱 + * + * @param money + */ + void payMoneyInto(int money); + + /** + * 取钱 + * + * @param money + */ + void drawMoneyOut(int money); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/BankServiceImpl.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/BankServiceImpl.java new file mode 100644 index 00000000..f7e6bc75 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/BankServiceImpl.java @@ -0,0 +1,32 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo2; + +public class BankServiceImpl implements BankService +{ + private String user = null; + + public BankServiceImpl() + { + } + + public BankServiceImpl(String user) + { + this.user = user; + } + + public String getUser() + { + return user; + } + + @Override + public void payMoneyInto(int money) + { + System.out.println("存入:" + money + "元."); + } + + @Override + public void drawMoneyOut(int money) + { + System.out.println("取出:" + money + "元."); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/JDKProxyFactory.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/JDKProxyFactory.java new file mode 100644 index 00000000..916ec1e0 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/aop/demo2/JDKProxyFactory.java @@ -0,0 +1,34 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.aop.demo2; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +public class JDKProxyFactory implements InvocationHandler +{ + private Object targetObject; + + public Object createProxyInstance(Object targetObject) + { + this.targetObject = targetObject; + return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), + targetObject.getClass().getInterfaces(), this); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + BankServiceImpl bankServiceImpl = (BankServiceImpl) targetObject; + Object result = null; + if (bankServiceImpl.getUser() != null) + { + // 用户名不为空,说明有权限 + result = method.invoke(targetObject, args); + } + else + { + System.out.println("用户不能为空."); + } + return result; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/DynamicProxyTest.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/DynamicProxyTest.java new file mode 100644 index 00000000..748b30e7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/DynamicProxyTest.java @@ -0,0 +1,20 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.demo; + +import java.lang.reflect.Proxy; + +public class DynamicProxyTest +{ + public static void main(String[] args) + { + HelloImpl helloImpl = new HelloImpl(); + LogHandler handler = new LogHandler(helloImpl); + + // 这里把handler与impl新生成的代理类相关联 + Hello hello = (Hello) Proxy.newProxyInstance(helloImpl.getClass().getClassLoader(), helloImpl.getClass() + .getInterfaces(), handler); + + // 这里无论访问哪个方法,都是会把请求转发到handler.invoke + hello.sayHello("Denny"); + hello.sayHi("Tom"); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/Hello.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/Hello.java new file mode 100644 index 00000000..7d47d4de --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/Hello.java @@ -0,0 +1,8 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.demo; + +public interface Hello +{ + public void sayHello(String name); + + public void sayHi(String name); +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/HelloImpl.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/HelloImpl.java new file mode 100644 index 00000000..7919bad9 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/HelloImpl.java @@ -0,0 +1,14 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.demo; + +public class HelloImpl implements Hello +{ + public void sayHello(String name) + { + System.out.println("Hello, " + name); + } + + public void sayHi(String name) + { + System.out.println("hi, " + name); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/LogHandler.java b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/LogHandler.java new file mode 100644 index 00000000..beb12fca --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/reflection/proxy/dynamicproxy/demo/LogHandler.java @@ -0,0 +1,32 @@ +package com.xdc.basic.api.reflection.proxy.dynamicproxy.demo; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class LogHandler implements InvocationHandler +{ + private Object targetObject; + + public LogHandler(Object obj) + { + this.targetObject = obj; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + doBefore(); + Object result = method.invoke(targetObject, args); + doAfter(); + return result; + } + + private void doBefore() + { + System.out.println("log: 要开始执行了!"); + } + + private void doAfter() + { + System.out.println("log: 已经执行完了!"); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/regex/ExpressionParse.java b/basicKnowledge/src/com/xdc/basic/api/regex/ExpressionParse.java new file mode 100644 index 00000000..52c0cd83 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/regex/ExpressionParse.java @@ -0,0 +1,52 @@ +package com.xdc.basic.api.regex; + +import java.util.ArrayList; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 表达式解析: 整数1 加或乘 整数2 用正则表达式进行输入验证 + * + * @author xdc + * + */ +public class ExpressionParse +{ + public static void main(String[] args) + { + @SuppressWarnings("resource") + Scanner cin = new Scanner(System.in); + + // \s:代表空白,-?:代表0个或一个减号,\d:代表数字 + String regex = "^\\s*(-?\\d+)\\s*([+*])\\s*(-?\\d+)\\s*$"; + Pattern pattern = Pattern.compile(regex); + + while (true) + { + String line = cin.nextLine(); + line = line.trim(); + if (line.isEmpty()) + { + continue; + } + + Matcher matcher = pattern.matcher(line); + if (matcher.find()) + { + ArrayList items = new ArrayList(); + // 下面的循环中,先加入整表达式,在依次放入:整数1, 加或乘, 整数2。 + for (int i = 0; i <= matcher.groupCount(); i++) + { + String item = matcher.group(i); + items.add(item); + } + System.out.println(items); + } + else + { + System.out.println("表达式不合法!"); + } + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/regex/RegexTest.java b/basicKnowledge/src/com/xdc/basic/api/regex/RegexTest.java new file mode 100644 index 00000000..907e07c6 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/regex/RegexTest.java @@ -0,0 +1,186 @@ +package com.xdc.basic.api.regex; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Test; + +public class RegexTest +{ + @Test + public void searchWord() + { + String word = "there"; + + String regex = "\\b" + word + "\\b"; + String input = "Where there is a will there is a way."; + + regexSearch(regex, input); + } + + @Test + public void searchWordPrefix() + { + String wordPrefix = "the"; + + String regex = "\\b" + wordPrefix + "[a-zA-Z]+\\b"; + String input = "Where there is a will there is a way."; + + regexSearch(regex, input); + } + + @Test + public void getAllWord() + { + String regex = "\\b[a-zA-Z]+\\b"; + String input = "Where there is a will there is a way."; + + regexSearch(regex, input); + } + + @Test + public void ExpressionParse() + { + // 表达式解析: 整数1 加或乘 整数2 + // \s:代表空白,-?:代表0个或一个减号,\d:代表数字 + String regex = "^\\s*(-?\\d+)\\s*([+*])\\s*(-?\\d+)\\s*$"; + String input = " 11 * 12 "; + + regexSearch(regex, input); + } + + @Test + public void searchWordCaseInsensitive1() + { + String word = "thERE"; + + String regex = "(?i)\\b" + word + "\\b"; + String input = "Where there is a will there is a way."; + + regexSearch(regex, input); + } + + @Test + public void searchWordCaseInsensitive2() + { + String word = "thERE"; + + String regex = "\\b" + word + "\\b"; + String input = "Where there is a will there is a way."; + + int flags = Pattern.CASE_INSENSITIVE; + regexSearch(regex, input, flags); + } + + @Test + public void patternFlags() + { + String word = "thERE"; + + String regex = "\\b" + word + "\\b"; + String input = "Where there is a will there is a way."; + + // 常用的标志 + // 常量-----------------------等价的内嵌标志表达式--意义 + // Pattern.CASE_INSENSITIVE (?i) 启用不区分大小写匹配。默认情况下,仅匹配 US-ASCII 字符集中的字符。 + // Pattern.COMMENTS (?x) 模式中允许存在空白和注释。在这种模式下,空白和以#开始的直到行尾的内嵌注释会被忽略。 + // Pattern.MULTILINE (?m) 启用多行(multiline)模式。在多行模式下,表达式^和$分别匹配输入序列行结束符前面和行结束符的前面。默认情况下,表达式仅匹配整个输入序列的开始和结尾。 + // Pattern.DOTALL (?s) 启用 dotall 模式。在 dotall 模式下,表达式.匹配包括行结束符在内的任意字符。 + // Pattern.UNICODE_CASE (?u) 配合CASE_INSENSITIVE标志来启用,使 Unicode字符不区分大小写匹配 + + int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; + regexSearch(regex, input, flags); + } + + @Test + public void patternSplit() + { + String regex = "\\d"; + String input = "one9two4three7four1five"; + + Pattern pattern = Pattern.compile(regex); + String[] items = pattern.split(input); + for (String item : items) + { + System.out.println(item); + } + } + + /** + * 比matcher.replaceAll(replacement)灵活,可以在每个匹配出替换为不同的值。 用哪个是需求而定。 + */ + @Test + public void matcherReplacement() + { + String regex = "\\d"; + String input = "one9two4three7four1five"; + + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(input); // 获得匹配器对象 + + StringBuffer sb = new StringBuffer(); + while (matcher.find()) + { + String replace = RandomStringUtils.random(1, "!@#$"); + // 处理特殊字符\和$,在前面添加转义符\ + replace = Matcher.quoteReplacement(replace); + System.out.println("Random char: " + replace); + matcher.appendReplacement(sb, replace); + } + matcher.appendTail(sb); + System.out.println(sb.toString()); + } + + private void regexSearch(String regex, String input) + { + regexSearch(regex, input, 0); + } + + private void regexSearch(String regex, String input, int flags) + { + Pattern pattern = null; + Matcher matcher = null; + try + { + pattern = Pattern.compile(regex, flags); + matcher = pattern.matcher(input); + } + catch (PatternSyntaxException pse) + { + System.out.println("There is a problem with the regular expression!"); + System.out.println("The pattern in question is: " + pse.getPattern()); + System.out.println("The description is: " + pse.getDescription()); + System.out.println("The message is: " + pse.getMessage()); + System.out.println("The index is: " + pse.getIndex()); + System.exit(0); + } + + int count = 0; + // 一直不停的找,直到结尾 + while (matcher.find()) + { + System.out.println("======================================"); + count++; + System.out.println("Match number : " + count); + System.out.println("Match text : " + matcher.group()); + System.out.println("Match start index : " + matcher.start()); + System.out.println("Match end index : " + matcher.end()); + + // matcher.groupCount()方法返回int类型值,表示当前 Matcher模式中捕获组的数量。 + // 有一个特别的组——组 0,它表示整个表达式。这个组不包括在groupCount的报告范围内。因此注意下面需使用<=号。 + // 因此matcher.group(0)与matcher.group()是等效的。 + for (int i = 0; i <= matcher.groupCount(); i++) + { + System.out.println(" Group number : " + i); + System.out.println(" Group text : " + matcher.group(i)); + System.out.println(" Group start index : " + matcher.start(i)); + System.out.println(" Group end index : " + matcher.end(i)); + System.out.println(); + } + + System.out.println(); + } + } +} diff --git "a/basicKnowledge/src/com/xdc/basic/api/regex/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.txt" "b/basicKnowledge/src/com/xdc/basic/api/regex/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.txt" new file mode 100644 index 00000000..afaf1ef0 --- /dev/null +++ "b/basicKnowledge/src/com/xdc/basic/api/regex/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.txt" @@ -0,0 +1,69 @@ +引自:http://www.jb51.net/tools/regex.htm + +正则表达式通常用于两种任务:1.验证,2.搜索/替换。用于验证时,通常需要在前后分别加上^和$,以匹配整个待验证字符串;搜索/替换时是否加上此限定则根据搜索的要求而定,此外,也有可能要在前后加上\b而不是^和$。 + + +========================================================================================================== +引自:http://www.jb51.net/tools/zhengze.htm?1352600907 + +各式各样的正则表达式参考大全: +^\d+$   //匹配非负整数(正整数 + 0)   +//匹配整数 ^\d+(\.\d+)?$   //匹配非负浮点数(正浮点数 + 0) +^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$   //匹配正浮点数 +^((-\d+(\.\d+)?)|(0+(\.0+)?))$    //匹配非正浮点数(负浮点数 + 0) +^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ //匹配负浮点数 +^(-?\d+)(\.\d+)?$   //匹配浮点数 +^[A-Za-z]+$ //匹配由26个英文字母组成的字符串 +^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串 +^[a-z]+$   //匹配由26个英文字母的小写组成的字符串 +^[A-Za-z0-9]+$   //匹配由数字和26个英文字母组成的字符串 +^\w+$   //匹配由数字、26个英文字母或者下划线组成的字符串 +^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$     //匹配email地址 +^[a-zA-z]+://匹配(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$   //匹配url + +匹配中文字符的正则表达式: [\u4e00-\u9fa5] +匹配双字节字符(包括汉字在内):[^\x00-\xff] +匹配空行的正则表达式: \n[\s| ]*\r +匹配HTML标记的正则表达式: /<(.*)>.*<\/>|<(.*) \/>/ +匹配首尾空格的正则表达式: (^\s*)|(\s*$) +匹配Email地址的正则表达式: \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* +匹配网址URL的正则表达式: ^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$ +匹配国内电话号码: (\d{3}-|\d{4}-)?(\d{8}|\d{7})? +匹配腾讯QQ号: ^[1-9]*[1-9][0-9]*$ +匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ + +下表是元字符及其在正则表达式上下文中的行为的一个完整列表,具体到每个正则表达式符号: +\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。 +^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的Multiline 属性,^ 也匹配 ’\n’ 或 ’\r’ 之后的位置。 +$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的Multiline 属性,$ 也匹配 ’\n’ 或 ’\r’ 之前的位置。 +* 匹配前面的子表达式零次或多次。 ++ 匹配前面的子表达式一次或多次。+ 等价于 {1,}。 +? 匹配前面的子表达式零次或一次。? 等价于 {0,1}。 +{n} n 是一个非负整数,匹配确定的n 次。 +{n,} n 是一个非负整数,至少匹配n 次。 +{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。在逗号和两个数之间不能有空格。 +? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。 +. 匹配除 "\n" 之外的任何单个字符。要匹配包括 ’\n’ 在内的任何字符,请使用象 ’[.\n]’ 的模式。 +(pattern) 匹配pattern 并获取这一匹配。 (?:pattern) 匹配pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。 (?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。 (?!pattern) 负向预查,与(?=pattern)作用相反 x|y 匹配 x 或 y。 +[xyz] 字符集合。 +[^xyz] 负值字符集合。 +[a-z] 字符范围,匹配指定范围内的任意字符。 +[^a-z] 负值字符范围,匹配任何不在指定范围内的任意字符。 +\b 匹配一个单词边界,也就是指单词和空格间的位置。 +\B 匹配非单词边界。 +\cx 匹配由x指明的控制字符。 +\d 匹配一个数字字符。等价于 [0-9]。 +\D 匹配一个非数字字符。等价于 [^0-9]。 +\f 匹配一个换页符。等价于 \x0c 和 \cL。 +\n 匹配一个换行符。等价于 \x0a 和 \cJ。 +\r 匹配一个回车符。等价于 \x0d 和 \cM。 +\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 +\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 +\t 匹配一个制表符。等价于 \x09 和 \cI。 +\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。 +\w 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。 +\W 匹配任何非单词字符。等价于 ’[^A-Za-z0-9_]’。 +\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。 +\num 匹配 num,其中num是一个正整数。对所获取的匹配的引用。 +\n 标识一个八进制转义值或一个后向引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。 +\nm 标识一个八进制转义值或一个后向引用。如果 \nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。 \nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八. diff --git a/basicKnowledge/src/com/xdc/basic/api/rmi/client/RMIClient.java b/basicKnowledge/src/com/xdc/basic/api/rmi/client/RMIClient.java new file mode 100644 index 00000000..4e360bdb --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/rmi/client/RMIClient.java @@ -0,0 +1,57 @@ +package com.xdc.basic.api.rmi.client; + +import java.net.MalformedURLException; +import java.rmi.Naming; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.util.Scanner; + +import com.xdc.basic.api.rmi.intf.IHelloRMI; + +/** + * 客户端程序 + * + * @author xdc + * + */ +public class RMIClient +{ + + public static void main(String[] args) + { + Scanner cin = new Scanner(System.in); + try + { + String ip = new String(); + int port; + System.out.print("请输入服务器ip:"); + ip = cin.nextLine(); + System.out.print("请输入服务器端口号:"); + port = cin.nextInt(); + + com.xdc.basic.api.rmi.intf.IHelloRMI iRmi = (IHelloRMI) Naming.lookup("rmi://" + ip + ":" + port + + "/My_RMI"); + + System.out.println(iRmi.sayHello()); + + } + catch (MalformedURLException e) + { + e.printStackTrace(); + } + catch (RemoteException e) + { + e.printStackTrace(); + } + catch (NotBoundException e) + { + e.printStackTrace(); + } + finally + { + cin.close(); + } + + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/rmi/intf/IHelloRMI.java b/basicKnowledge/src/com/xdc/basic/api/rmi/intf/IHelloRMI.java new file mode 100644 index 00000000..170addd2 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/rmi/intf/IHelloRMI.java @@ -0,0 +1,15 @@ +package com.xdc.basic.api.rmi.intf; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +/** + * 远程接口 + * + * @author xdc + * + */ +public interface IHelloRMI extends Remote +{ + public String sayHello() throws RemoteException; +} diff --git a/basicKnowledge/src/com/xdc/basic/api/rmi/server/HelloRMIImpl.java b/basicKnowledge/src/com/xdc/basic/api/rmi/server/HelloRMIImpl.java new file mode 100644 index 00000000..4f6cb69c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/rmi/server/HelloRMIImpl.java @@ -0,0 +1,30 @@ +package com.xdc.basic.api.rmi.server; + +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; + +import com.xdc.basic.api.rmi.intf.IHelloRMI; + +/** + * 接口的实现 + * + * @author xdc + * + */ +public class HelloRMIImpl extends UnicastRemoteObject implements IHelloRMI +{ + + private static final long serialVersionUID = 1455115818555556704L; + + public HelloRMIImpl() throws RemoteException + { + super(); + } + + @Override + public String sayHello() throws RemoteException + { + return "Hello RMI"; + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/rmi/server/RMIServer.java b/basicKnowledge/src/com/xdc/basic/api/rmi/server/RMIServer.java new file mode 100644 index 00000000..73f91136 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/rmi/server/RMIServer.java @@ -0,0 +1,44 @@ +package com.xdc.basic.api.rmi.server; + +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.util.Scanner; + +/** + * 服务器端 + * + * RMI,远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱, + * 是建立分布式Java应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。 + * + * RMI的基础是接口,RMI构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。 + * + * @author xdc + * + */ +public class RMIServer +{ + public static void main(String[] args) + { + Scanner cin = new Scanner(System.in); + try + { + int port; + System.out.print("请输入监听端口号:"); + port = cin.nextInt(); + HelloRMIImpl rmi = new HelloRMIImpl(); + Registry r = LocateRegistry.createRegistry(port); + r.rebind("My_RMI", rmi); + System.out.println("服务运行中..."); + System.out.println("服务端口号为:" + port); + } + catch (RemoteException e) + { + e.printStackTrace(); + } + finally + { + cin.close(); + } + } +} diff --git "a/basicKnowledge/src/com/xdc/basic/api/rmi/\346\211\223\345\214\205\345\217\212\346\265\213\350\257\225\346\226\271\346\263\225.txt" "b/basicKnowledge/src/com/xdc/basic/api/rmi/\346\211\223\345\214\205\345\217\212\346\265\213\350\257\225\346\226\271\346\263\225.txt" new file mode 100644 index 00000000..c0973305 --- /dev/null +++ "b/basicKnowledge/src/com/xdc/basic/api/rmi/\346\211\223\345\214\205\345\217\212\346\265\213\350\257\225\346\226\271\346\263\225.txt" @@ -0,0 +1,8 @@ +(1)用eclipse分别将两工程打包: +方法一:导出--java--jar文件,写好文件名和选好Main类,其他默认。(推荐) +方法二:导出--java--jar文件,写好文件名和选好启动配置,其他默认。 +方法三:手工执行jar打包,略。 + +(2)在两个命令行窗口分别执行: + java -jar rmiServer + jave -jar rmiClient diff --git a/basicKnowledge/src/com/xdc/basic/api/serialization/SerializationTest.java b/basicKnowledge/src/com/xdc/basic/api/serialization/SerializationTest.java new file mode 100644 index 00000000..0fe493b1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/serialization/SerializationTest.java @@ -0,0 +1,55 @@ +package com.xdc.basic.api.serialization; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import com.xdc.basic.skills.GetCurPath; + +public class SerializationTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + + // Object serialization + try + { + Student student1 = new Student("xdc", 25); + System.out.println("student1: " + student1); + + FileOutputStream fos = new FileOutputStream(curPath + "serial"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + + oos.writeObject(student1); + + oos.flush(); + oos.close(); + } + catch (Exception e) + { + System.out.println("Exception during serialization:" + e); + System.exit(0); + } + + // Object deserialization + try + { + Student student2; + FileInputStream fis = new FileInputStream(curPath + "serial"); + ObjectInputStream ois = new ObjectInputStream(fis); + + student2 = (Student) ois.readObject(); + + ois.close(); + System.out.println("student2: " + student2); + } + catch (Exception e) + { + System.out.println("Exception during deserialization:" + e); + System.exit(0); + } + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/serialization/Student.java b/basicKnowledge/src/com/xdc/basic/api/serialization/Student.java new file mode 100644 index 00000000..a6b7f550 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/serialization/Student.java @@ -0,0 +1,48 @@ +package com.xdc.basic.api.serialization; + +import java.io.Serializable; + +public class Student implements Serializable +{ + // 序列化标志 + // Add generated serial version ID + // 添加已生成的串行版本标识 + + private static final long serialVersionUID = -5104809987465264163L; + + private String name; + private int age; + + public Student(String name, int age) + { + super(); + this.name = name; + this.age = age; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public int getAge() + { + return age; + } + + public void setAge(int age) + { + this.age = age; + } + + @Override + public String toString() + { + return "Student [name=" + name + ", age=" + age + "]"; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/serialization/serial b/basicKnowledge/src/com/xdc/basic/api/serialization/serial new file mode 100644 index 00000000..51a53e76 Binary files /dev/null and b/basicKnowledge/src/com/xdc/basic/api/serialization/serial differ diff --git "a/basicKnowledge/src/com/xdc/basic/api/socket/Socket\347\274\226\347\250\213\347\256\200\350\256\260.docx" "b/basicKnowledge/src/com/xdc/basic/api/socket/Socket\347\274\226\347\250\213\347\256\200\350\256\260.docx" new file mode 100644 index 00000000..dfb49151 Binary files /dev/null and "b/basicKnowledge/src/com/xdc/basic/api/socket/Socket\347\274\226\347\250\213\347\256\200\350\256\260.docx" differ diff --git a/basicKnowledge/src/com/xdc/basic/api/socket/tcp/MyClient.java b/basicKnowledge/src/com/xdc/basic/api/socket/tcp/MyClient.java new file mode 100644 index 00000000..37ecaa95 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/socket/tcp/MyClient.java @@ -0,0 +1,34 @@ +package com.xdc.basic.api.socket.tcp; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.net.Socket; + +public class MyClient +{ + public static void main(String[] args) + { + try + { + // 创建连接到服务器的Socket对象 + Socket sc = new Socket("127.0.0.1", 9876); + // 获取当前连接的输入流,并使用处理流进行封装 + DataInputStream din = new DataInputStream(sc.getInputStream()); + // 获取当前连接的输出流,并使用处理流进行封装 + DataOutputStream dout = new DataOutputStream(sc.getOutputStream()); + // 向服务器发送消息 + dout.writeUTF("请问你那现在几点?"); + // 读取服务器的返回消息并打印 + System.out.println(din.readUTF()); + // 关闭流 + din.close(); + dout.close(); + // 关闭此Socket连接 + sc.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/socket/tcp/MyServer.java b/basicKnowledge/src/com/xdc/basic/api/socket/tcp/MyServer.java new file mode 100644 index 00000000..ea5cb51b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/socket/tcp/MyServer.java @@ -0,0 +1,61 @@ +package com.xdc.basic.api.socket.tcp; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Date; + +public class MyServer +{ + public static void main(String[] args) + { + int count = 0;// 声明用来计数的int局部变量 + ServerSocket server = null; + try + { + // 创建绑定到9876端口的ServerSocket对象 + server = new ServerSocket(9876); + System.out.println("服务器对9876端口正在进行监听..."); + // 服务器循环接收客户端的请求,为不同的客户端提供服务 + while (true) + { + // 接收客户端的连接请求,若有连接请求返回连接对应的Socket对象 + Socket sc = server.accept(); + // 获取当前连接的输入流,并使用处理流进行封装 + DataInputStream din = new DataInputStream(sc.getInputStream()); + // 获取当前连接的输出流,并使用处理流进行封装 + DataOutputStream dout = new DataOutputStream(sc.getOutputStream()); + // 打印客户端的信息 + System.out.println("这是第" + (++count) + "个客户访问"); + System.out.println("客户端IP地址:" + sc.getInetAddress().getHostAddress()); + System.out.println("本地端口号:" + sc.getLocalPort()); + System.out.println("客户端信息:" + din.readUTF()); + // 向客户端发送回应信息 + dout.writeUTF("服务器的时间为:" + (new Date())); + // 关闭流 + din.close(); + dout.close(); + // 关闭此Socket连接 + sc.close(); + } + + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + try + { + server.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/socket/udp/FortuneClient.java b/basicKnowledge/src/com/xdc/basic/api/socket/udp/FortuneClient.java new file mode 100644 index 00000000..01f90f3d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/socket/udp/FortuneClient.java @@ -0,0 +1,53 @@ +package com.xdc.basic.api.socket.udp; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.UnknownHostException; + +class FortuneClient +{ + public String getMessage() + { + String fortune; + try + { + // 创建数据报套接字 + DatagramSocket socket = new DatagramSocket(); + + // 创建缓冲区 + byte[] data = new byte[256]; + // 创建发送数据包 + DatagramPacket sendPacket = new DatagramPacket(data, data.length, InetAddress.getByName("127.0.0.1"), 1114); + // 发送报文 + socket.send(sendPacket); + + // 创建接收数据包 + DatagramPacket resivePacket = new DatagramPacket(data, data.length); + // 等待接收报文 + socket.receive(resivePacket); + + // 将数据内容由字节转换成字符 + fortune = new String(resivePacket.getData()); + // 关闭套接字 + socket.close(); + } + catch (UnknownHostException e) + { + System.err.println("Exception: host could not be found!"); + return null; + } + catch (Exception e) + { + e.printStackTrace(); + return null; + } + return fortune; + } + + public static void main(String args[]) + { + FortuneClient client = new FortuneClient(); + System.out.println(client.getMessage()); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/socket/udp/FortuneServer.java b/basicKnowledge/src/com/xdc/basic/api/socket/udp/FortuneServer.java new file mode 100644 index 00000000..b88c9072 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/socket/udp/FortuneServer.java @@ -0,0 +1,81 @@ +package com.xdc.basic.api.socket.udp; + +import java.io.File; +import java.io.FileInputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.SocketException; + +import org.apache.commons.io.IOUtils; + +import com.xdc.basic.skills.GetCurPath; + +class FortuneServer extends Thread +{ + DatagramSocket ServerSocket; + + public FortuneServer() + { + super("FortuneServer"); + try + { + ServerSocket = new DatagramSocket(1114); + System.out.println("FortuneServer up and running..."); + } + catch (SocketException e) + { + System.err.println("Exception: couldn't create datagram sockter"); + System.exit(1); + } + } + + public static void main(String args[]) + { + FortuneServer server = new FortuneServer(); + server.start(); + } + + public void run() + { + String curPath = GetCurPath.getCurPath(); + + FileInputStream inStream = null; + while (true) + { + try + { + // 创建缓冲区 + byte[] data = new byte[256]; + // 创建接收数据包 + DatagramPacket rPacket = new DatagramPacket(data, data.length); + + System.out.println("等待客户端连接..."); + // 等待接收数据包 + ServerSocket.receive(rPacket); + System.out.println("已有客户端发来请求: " + rPacket.getAddress().getHostAddress() + ":" + rPacket.getPort()); + + // 读取待发送的内容 + inStream = new FileInputStream(new File(curPath + "Fortunes.txt")); + if (inStream.read(data) <= 0) + { + System.err.println("Error: couldn't read fortunes"); + } + + // 创建发送数据包 + DatagramPacket sPacket = new DatagramPacket(data, data.length, rPacket.getAddress(), rPacket.getPort()); + // 发送报文 + ServerSocket.send(sPacket); + } + catch (Exception e) + { + System.err.println("Exception: " + e); + e.printStackTrace(); + } + finally + { + // 大师鸟悄的关闭输入流 + IOUtils.closeQuietly(inStream); + } + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/socket/udp/Fortunes.txt b/basicKnowledge/src/com/xdc/basic/api/socket/udp/Fortunes.txt new file mode 100644 index 00000000..e3df38d1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/socket/udp/Fortunes.txt @@ -0,0 +1,4 @@ +This is a test. +Here is all what I want to send your message: +Facts speak plainer than words. +I love this game very much. \ No newline at end of file diff --git "a/basicKnowledge/src/com/xdc/basic/api/socket/\346\225\260\346\215\256\346\212\245\351\200\232\344\277\241\345\222\214\346\265\201\345\274\217\351\200\232\344\277\241\347\232\204\345\214\272\345\210\253.docx" "b/basicKnowledge/src/com/xdc/basic/api/socket/\346\225\260\346\215\256\346\212\245\351\200\232\344\277\241\345\222\214\346\265\201\345\274\217\351\200\232\344\277\241\347\232\204\345\214\272\345\210\253.docx" new file mode 100644 index 00000000..2e5aaf22 Binary files /dev/null and "b/basicKnowledge/src/com/xdc/basic/api/socket/\346\225\260\346\215\256\346\212\245\351\200\232\344\277\241\345\222\214\346\265\201\345\274\217\351\200\232\344\277\241\347\232\204\345\214\272\345\210\253.docx" differ diff --git "a/basicKnowledge/src/com/xdc/basic/api/socket/\346\265\201\345\274\217\345\245\227\346\216\245\345\255\227\357\274\210TCP\357\274\211\345\222\214 \346\225\260\346\215\256\346\212\245\345\245\227\346\216\245\345\255\227\357\274\210UDP\357\274\211\347\232\204\345\214\272\345\210\253.docx" "b/basicKnowledge/src/com/xdc/basic/api/socket/\346\265\201\345\274\217\345\245\227\346\216\245\345\255\227\357\274\210TCP\357\274\211\345\222\214 \346\225\260\346\215\256\346\212\245\345\245\227\346\216\245\345\255\227\357\274\210UDP\357\274\211\347\232\204\345\214\272\345\210\253.docx" new file mode 100644 index 00000000..bdd67728 Binary files /dev/null and "b/basicKnowledge/src/com/xdc/basic/api/socket/\346\265\201\345\274\217\345\245\227\346\216\245\345\255\227\357\274\210TCP\357\274\211\345\222\214 \346\225\260\346\215\256\346\212\245\345\245\227\346\216\245\345\255\227\357\274\210UDP\357\274\211\347\232\204\345\214\272\345\210\253.docx" differ diff --git a/basicKnowledge/src/com/xdc/basic/api/sort/CompareTest.java b/basicKnowledge/src/com/xdc/basic/api/sort/CompareTest.java new file mode 100644 index 00000000..af71abc2 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/sort/CompareTest.java @@ -0,0 +1,77 @@ +package com.xdc.basic.api.sort; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class CompareTest +{ + /** + * 本例所有排序:分数降序,年龄降序 + * + * @param args + */ + public static void main(String[] args) + { + // 列表 + List students = new ArrayList(); + students.add(new Student("xudachao", 100, 25)); + students.add(new Student("wangzhiwei", 88, 24)); + students.add(new Student("gengxue", 98, 24)); + + listSort(students); + + // 数组 + Student[] studentArr = students.toArray(new Student[students.size()]); + + arraySort(studentArr); + } + + private static void arraySort(Student[] studentArr) + { + // 方式一 + Arrays.sort(studentArr, new Comparator() + { + @Override + public int compare(Student o1, Student o2) + { + int scoreDiff = o1.getScore() - o2.getScore(); + if (scoreDiff != 0) + return scoreDiff; + + int ageDiff = o1.getAge() - o2.getAge(); + return ageDiff; + } + }); + + // 方式二 + Arrays.sort(studentArr); + + System.out.println(Arrays.toString(studentArr)); + } + + private static void listSort(List students) + { + // 方式一 + Collections.sort(students, new Comparator() + { + @Override + public int compare(Student o1, Student o2) + { + int scoreDiff = o1.getScore() - o2.getScore(); + if (scoreDiff != 0) + return scoreDiff; + + int ageDiff = o1.getAge() - o2.getAge(); + return ageDiff; + } + }); + + // 方式二 + Collections.sort(students); + + System.out.println(students); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/sort/Student.java b/basicKnowledge/src/com/xdc/basic/api/sort/Student.java new file mode 100644 index 00000000..0769de6d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/sort/Student.java @@ -0,0 +1,75 @@ +package com.xdc.basic.api.sort; + +import org.apache.commons.lang3.builder.CompareToBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class Student implements Comparable +{ + private String name; + private int score; + private int age; + + public Student(String name, int score, int age) + { + super(); + this.setName(name); + this.setScore(score); + this.setAge(age); + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public int getScore() + { + return score; + } + + public void setScore(int score) + { + this.score = score; + } + + public int getAge() + { + return age; + } + + public void setAge(int age) + { + this.age = age; + } + + @Override + public String toString() + { + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); + } + + // Two Objects that compare equal using equals(Object) should normally also + // compare equal using compareTo(Object). + // 先比较年龄,再比较姓名,再比较是否抽烟 + @Override + public int compareTo(Student o) + { + // 用不用判断null呢? + Student that = o; + return new CompareToBuilder().append(this.score, that.score).append(this.age, that.age).toComparison(); + } + + // Two Objects that compare equal using equals(Object) should normally also + // compare equal using compareTo(Object). + // 不推荐。由于该类涉及到比较字段的顺序,所以并不推荐使用该族中的方法自动映射字段,而最好自己决定那些字段参与比较及它们的顺序。该族方法的返回值为一整数,意义同Comparable接口的compareTo方法。 + public int compareTo2(Student o) + { + return CompareToBuilder.reflectionCompare(this, o); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/DeadLockTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/DeadLockTest.java new file mode 100644 index 00000000..e91f98ad --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/DeadLockTest.java @@ -0,0 +1,83 @@ +package com.xdc.basic.api.thread; + +/** + * 死锁样例演示 + * + * @author xdc + * + */ +public class DeadLockTest +{ + public static void main(String[] args) + { + DeadlockRisk dead = new DeadlockRisk(); + MyThread t1 = new MyThread(dead, 1, 2); + MyThread t2 = new MyThread(dead, 3, 4); + MyThread t3 = new MyThread(dead, 5, 6); + MyThread t4 = new MyThread(dead, 7, 8); + + t1.start(); + t2.start(); + t3.start(); + t4.start(); + } +} + +class MyThread extends Thread +{ + private DeadlockRisk dead; + private int a; + private int b; + + MyThread(DeadlockRisk dead, int a, int b) + { + this.dead = dead; + this.a = a; + this.b = b; + } + + @Override + public void run() + { + dead.read(); + dead.write(a, b); + } +} + +class DeadlockRisk +{ + private static class Resource + { + public int value; + } + + private Resource resourceA = new Resource(); + private Resource resourceB = new Resource(); + + public int read() + { + synchronized (resourceA) + { + System.out.println("read():" + Thread.currentThread().getName() + "获取了resourceA的锁!"); + synchronized (resourceB) + { + System.out.println("read():" + Thread.currentThread().getName() + "获取了resourceB的锁!"); + return resourceB.value + resourceA.value; + } + } + } + + public void write(int a, int b) + { + synchronized (resourceB) + { + System.out.println("write():" + Thread.currentThread().getName() + "获取了resourceB的锁!"); + synchronized (resourceA) + { + System.out.println("write():" + Thread.currentThread().getName() + "获取了resourceA的锁!"); + resourceA.value = a; + resourceB.value = b; + } + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/InterruptTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/InterruptTest.java new file mode 100644 index 00000000..d529bdf1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/InterruptTest.java @@ -0,0 +1,40 @@ +package com.xdc.basic.api.thread; + +public class InterruptTest +{ + + public static void main(String[] args) + { + Thread t = new Thread() + { + public void run() + { + System.out.println("执行run方法"); + try + { + Thread.sleep(10000); + System.out.println("线程完成休眠"); + } + catch (InterruptedException e) + { + System.out.println("休眠被打断"); + return; // 返回到程序的调用处 + } + System.out.println("线程正常终止"); + } + }; + + t.start(); + + try + { + Thread.sleep(2000L); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + + t.interrupt(); // 2s后中断线程 + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/JoinTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/JoinTest.java new file mode 100644 index 00000000..0263b560 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/JoinTest.java @@ -0,0 +1,40 @@ +package com.xdc.basic.api.thread; + +import java.io.IOException; + +public class JoinTest +{ + public static void main(String[] args) + { + // 启动一线程,等待控制台输入,使用join()方法来暂停当前线程,直到其他线程调用 + Thread t = new Thread() + { + public void run() + { + System.out.println("Reading"); + try + { + System.in.read(); + } + catch (IOException e) + { + System.err.println(e); + } + System.out.println("Thread finished."); + } + }; + System.out.println("Starting"); + t.start(); + + try + { + System.out.println("Joining"); + t.join(); + } + catch (InterruptedException e) + { + System.out.println("Who dares imterrupt my sleep?"); + } + System.out.println("Main finished."); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/java4android/thread/extendsthead/Test.java b/basicKnowledge/src/com/xdc/basic/api/thread/basic/extendsthead/Test.java similarity index 77% rename from basicKnowledge/src/com/xdc/basic/java4android/thread/extendsthead/Test.java rename to basicKnowledge/src/com/xdc/basic/api/thread/basic/extendsthead/Test.java index 763375cc..fab9e2ef 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/thread/extendsthead/Test.java +++ b/basicKnowledge/src/com/xdc/basic/api/thread/basic/extendsthead/Test.java @@ -1,16 +1,16 @@ -package com.xdc.basic.java4android.thread.extendsthead; - -class Test -{ - public static void main(String[] args) - { - // 生成线程类的对象 - MyThread t = new MyThread(); - // 启动线程 不能用t.run(); 这样的话,不会启动新的线程还是在当前线程中执行,因为咱们重写的run()函数和其他的成员函数没有区别 - t.start(); - for (int i = 0; i < 100; i++) - { - System.out.println("main-->" + i); - } - } -} +package com.xdc.basic.api.thread.basic.extendsthead; + +class Test +{ + public static void main(String[] args) + { + // 生成线程类的对象 + ThreadExt t = new ThreadExt(); + // 启动线程 不能用t.run(); 这样的话,不会启动新的线程还是在当前线程中执行,因为咱们重写的run()函数和其他的成员函数没有区别 + t.start(); + for (int i = 0; i < 100; i++) + { + System.out.println("main-->" + i); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/java4android/thread/extendsthead/MyThread.java b/basicKnowledge/src/com/xdc/basic/api/thread/basic/extendsthead/ThreadExt.java similarity index 52% rename from basicKnowledge/src/com/xdc/basic/java4android/thread/extendsthead/MyThread.java rename to basicKnowledge/src/com/xdc/basic/api/thread/basic/extendsthead/ThreadExt.java index 6f3898f6..1e7d21e3 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/thread/extendsthead/MyThread.java +++ b/basicKnowledge/src/com/xdc/basic/api/thread/basic/extendsthead/ThreadExt.java @@ -1,9 +1,9 @@ -package com.xdc.basic.java4android.thread.extendsthead; - -class MyThread extends Thread{ - public void run(){ - for(int i = 0; i < 100;i++){ - System.out.println("MyThread-->" + i); - } - } -} +package com.xdc.basic.api.thread.basic.extendsthead; + +class ThreadExt extends Thread{ + public void run(){ + for(int i = 0; i < 100;i++){ + System.out.println("MyThread-->" + i); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/basic/implcallable/CallableImpl.java b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implcallable/CallableImpl.java new file mode 100644 index 00000000..9ab5d7ec --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implcallable/CallableImpl.java @@ -0,0 +1,12 @@ +package com.xdc.basic.api.thread.basic.implcallable; + +import java.util.concurrent.Callable; + +public class CallableImpl implements Callable +{ + @Override + public String call() throws Exception + { + return "I'm in callable."; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/basic/implcallable/Test.java b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implcallable/Test.java new file mode 100644 index 00000000..013ccd25 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implcallable/Test.java @@ -0,0 +1,17 @@ +package com.xdc.basic.api.thread.basic.implcallable; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +class Test +{ + public static void main(String[] args) throws InterruptedException, ExecutionException + { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future future = executor.submit(new CallableImpl()); + String result = future.get(); + System.out.println(result); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/basic/implrunable/RunnableImpl.java b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implrunable/RunnableImpl.java new file mode 100644 index 00000000..5bab0cff --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implrunable/RunnableImpl.java @@ -0,0 +1,39 @@ +package com.xdc.basic.api.thread.basic.implrunable; + +class RunnableImpl implements Runnable +{ + int i = 100; + + public void run() + { + while (true) + { + System.out.println(Thread.currentThread().getName() + "-->" + i); + i--; + Thread.yield(); + if (i < 0) + { + break; + } + } + + } + + // 这个应该是规范的写法,如果不这么写,出错很难发现 + // public void run() + // { + // try + // { + // // dosomething + // } + // catch (Throwable e) + // { + // // log and throw + // throw e; + // } + // finally + // { + // // do some cleaning, close io and so on + // } + // } +} diff --git a/basicKnowledge/src/com/xdc/basic/java4android/thread/synclock/Test.java b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implrunable/Test.java similarity index 84% rename from basicKnowledge/src/com/xdc/basic/java4android/thread/synclock/Test.java rename to basicKnowledge/src/com/xdc/basic/api/thread/basic/implrunable/Test.java index f1214c67..cfa15c06 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/thread/synclock/Test.java +++ b/basicKnowledge/src/com/xdc/basic/api/thread/basic/implrunable/Test.java @@ -1,20 +1,20 @@ -package com.xdc.basic.java4android.thread.synclock; - -class Test -{ - public static void main(String[] args) - { - // 生成一个Runnable接口的实现类的对象 - RunnableImpl r = new RunnableImpl(); - // 生成一个Thread对象,并将Runnalbe接口的实 - // 现类的对象作为参数传递给该Thread对象 - - Thread t = new Thread(r); - t.setName("t1"); - t.start(); - - Thread t2 = new Thread(r); - t2.setName("t2"); - t2.start(); - } -} +package com.xdc.basic.api.thread.basic.implrunable; + +class Test +{ + public static void main(String[] args) + { + // 生成一个Runnable接口的实现类的对象 + RunnableImpl r = new RunnableImpl(); + // 生成一个Thread对象,并将Runnalbe接口的实 + // 现类的对象作为参数传递给该Thread对象 + + Thread t = new Thread(r); + t.setName("t1"); + t.start(); + + Thread t2 = new Thread(r); + t2.setName("t2"); + t2.start(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/executor/ScheduledThreadPoolExecutorTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/executor/ScheduledThreadPoolExecutorTest.java new file mode 100644 index 00000000..784b2fcf --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/executor/ScheduledThreadPoolExecutorTest.java @@ -0,0 +1,139 @@ +package com.xdc.basic.api.thread.executor; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +/** + * http://ketqi.blog.51cto.com/1130608/687681 + * + * @author xdc + * + */ +public class ScheduledThreadPoolExecutorTest +{ + private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + public static void main(String[] args) + { + // 参数corePoolSize代表线程最小个数,即使它们空闲,线程数最大值无限制,动态增加 + ScheduledExecutorService exec = Executors.newScheduledThreadPool(2); + + long initialDelay = 0; + long period = 5000; + scheduleAtFixedRate(exec, initialDelay, period); + scheduleWithFixedDelay(exec, initialDelay, period); + + long delay = 10000; + schedule(exec, delay); + + cancelSchedule(exec, initialDelay, period); + + try + { + Thread.sleep(50000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + + exec.shutdown(); + System.out.println("定时器关闭!"); + } + + private static void cancelSchedule(ScheduledExecutorService exec, long initialDelay, long period) + { + ScheduledFuture scheduledFuture = exec.scheduleAtFixedRate(new Runnable() + { + public void run() + { + System.out.println("cancelSchedule: " + format.format(new Date())); + } + }, initialDelay, period, TimeUnit.MILLISECONDS); + + try + { + Thread.sleep(20000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + + scheduledFuture.cancel(false); + System.out.println("cancelSchedule: the schedule has been canceled!" + format.format(new Date())); + } + + /** + * @param exec + * @param initialDelay + * @param period + */ + private static void scheduleAtFixedRate(ScheduledExecutorService exec, long initialDelay, long period) + { + /** + * 每隔一段时间打印系统时间,互不影响的
+ * 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;
+ * 也就是将在 initialDelay 后开始执行,然后在initialDelay+period 后执行,
+ * 接着在 initialDelay + 2 * period 后执行,依此类推。 + */ + exec.scheduleAtFixedRate(new Runnable() + { + public void run() + { + System.out.println("scheduleAtFixedRate: " + format.format(new Date())); + } + }, initialDelay, period, TimeUnit.MILLISECONDS); + } + + /** + * @param exec + * @param initialDelay + * @param period + */ + private static void scheduleWithFixedDelay(ScheduledExecutorService exec, long initialDelay, long period) + { + /** + * 创建并执行一个在给定初始延迟后首次启用的定期操作,
+ * 随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。 + */ + exec.scheduleWithFixedDelay(new Runnable() + { + public void run() + { + System.out.println("scheduleWithFixedDelay-begin: " + format.format(new Date())); + try + { + Thread.sleep(2000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + System.out.println("scheduleWithFixedDelay-end: " + format.format(new Date())); + } + }, initialDelay, period, TimeUnit.MILLISECONDS); + } + + /** + * @param exec + * @param delay + */ + private static void schedule(ScheduledExecutorService exec, long delay) + { + /** + * 创建并执行在给定延迟后启用的一次性操作。 + */ + exec.schedule(new Runnable() + { + public void run() + { + System.out.println("The thread can only run once!"); + } + }, delay, TimeUnit.MILLISECONDS); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/executor/ThreadFactoryTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/executor/ThreadFactoryTest.java new file mode 100644 index 00000000..a1964573 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/executor/ThreadFactoryTest.java @@ -0,0 +1,67 @@ +package com.xdc.basic.api.thread.executor; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; + +/** + * + * @author xdc + * + */ +public class ThreadFactoryTest +{ + public static void main(String[] args) + { + ThreadFactory threadFactory = new ThreadFactory() + { + private AtomicLong seq = new AtomicLong(0); + + @Override + public Thread newThread(Runnable r) + { + Thread t = new Thread(r); + t.setName("MyThread-" + seq.getAndIncrement()); + return t; + } + }; + + // 创建一个可重用固定线程数的线程池 + ExecutorService pool = Executors.newFixedThreadPool(3, threadFactory); + + // 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口 + Thread t1 = new MyThread2(); + Thread t2 = new MyThread2(); + Thread t3 = new MyThread2(); + Thread t4 = new MyThread2(); + Thread t5 = new MyThread2(); + + // 将线程放入池中进行执行 + pool.execute(t1); + pool.execute(t2); + pool.execute(t3); + pool.execute(t4); + pool.execute(t5); + + // 关闭线程池 + pool.shutdown(); + } +} + +class MyThread2 extends Thread +{ + @Override + public void run() + { + try + { + System.out.println(Thread.currentThread().getName() + "正在执行。。。"); + Thread.sleep(1000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/executor/ThreadPoolExecutorTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/executor/ThreadPoolExecutorTest.java new file mode 100644 index 00000000..cd10d83f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/executor/ThreadPoolExecutorTest.java @@ -0,0 +1,53 @@ +package com.xdc.basic.api.thread.executor; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * http://www.cnblogs.com/jersey/archive/2011/03/30/2000231.html + * + * @author xdc + * + */ +public class ThreadPoolExecutorTest +{ + public static void main(String[] args) + { + // 创建一个可重用固定线程数的线程池 + ExecutorService pool = Executors.newFixedThreadPool(3); + + // 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口 + Thread t1 = new MyThread(); + Thread t2 = new MyThread(); + Thread t3 = new MyThread(); + Thread t4 = new MyThread(); + Thread t5 = new MyThread(); + + // 将线程放入池中进行执行 + pool.execute(t1); + pool.execute(t2); + pool.execute(t3); + pool.execute(t4); + pool.execute(t5); + + // 关闭线程池 + pool.shutdown(); + } +} + +class MyThread extends Thread +{ + @Override + public void run() + { + try + { + System.out.println(Thread.currentThread().getName() + "正在执行。。。"); + Thread.sleep(1000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/ExecutorThreadFactory.java b/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/ExecutorThreadFactory.java new file mode 100644 index 00000000..31f94c44 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/ExecutorThreadFactory.java @@ -0,0 +1,19 @@ +package com.xdc.basic.api.thread.executor.asyncprocess; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; + +public class ExecutorThreadFactory implements ThreadFactory +{ + private static final String THREAD_NAME_PREFIX = "MyThread-"; + + private AtomicLong seq = new AtomicLong(0); + + @Override + public Thread newThread(Runnable r) + { + Thread t = new Thread(r); + t.setName(THREAD_NAME_PREFIX + seq.getAndIncrement()); + return t; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/ThreadExecutor.java b/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/ThreadExecutor.java new file mode 100644 index 00000000..7ce5d666 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/ThreadExecutor.java @@ -0,0 +1,37 @@ +package com.xdc.basic.api.thread.executor.asyncprocess; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ThreadExecutor +{ + private ExecutorService threadPool; + private static final ThreadExecutor instance = new ThreadExecutor(); + + private ThreadExecutor() + { + threadPool = Executors.newFixedThreadPool(20, new ExecutorThreadFactory()); + } + + public static ThreadExecutor getInstance() + { + return instance; + } + + public void asyncExec(Runnable task) + { + threadPool.execute(task); + } + + public static void sleepSecond(long second) + { + try + { + Thread.sleep(second); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/abstractProcess.java b/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/abstractProcess.java new file mode 100644 index 00000000..e6ce16d7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/executor/asyncprocess/abstractProcess.java @@ -0,0 +1,27 @@ +package com.xdc.basic.api.thread.executor.asyncprocess; + +public abstract class abstractProcess +{ + public String asyncProcess(final String para) + { + ThreadExecutor.getInstance().asyncExec(new Runnable() + { + @Override + public void run() + { + try + { + process(para); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + }); + return "success!"; + } + + abstract void process(String para); +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CoutDownLatchTest1.java b/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CoutDownLatchTest1.java new file mode 100644 index 00000000..9d7ad75a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CoutDownLatchTest1.java @@ -0,0 +1,39 @@ +package com.xdc.basic.api.thread.flowcontrol; + +import java.util.concurrent.CountDownLatch; + +/** + * 当你启动了一个线程,你需要等它执行结束,此时,CountDownLatch也许是一个很好的选择。 + * + * @author xdc + * + */ +public class CoutDownLatchTest1 +{ + public static void main(String[] args) throws InterruptedException + { + final int COUNT = 10; + final CountDownLatch completeLatch = new CountDownLatch(COUNT); + for (int i = 0; i < COUNT; ++i) + { + Thread thread = new Thread("worker thread " + i) + { + public void run() + { + System.out.println("子线程开始执行:" + Thread.currentThread().getName()); + // do something + System.out.println("子线程完成执行:" + Thread.currentThread().getName()); + + // 计数器减1 + completeLatch.countDown(); + } + }; + thread.start(); + } + + System.out.println("主线程开始等待。。"); + // 计数减为0时,继续向下执行 + completeLatch.await(); + System.out.println("主线程完成等待。。"); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CoutDownLatchTest2.java b/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CoutDownLatchTest2.java new file mode 100644 index 00000000..4cdd7d20 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CoutDownLatchTest2.java @@ -0,0 +1,42 @@ +package com.xdc.basic.api.thread.flowcontrol; + +import java.util.concurrent.CountDownLatch; + +/** + * 当你启动很多线程,你需要这些线程等到通知后才真正开始,CountDownLatch也许是一个很好的选择。 + * + * @author xdc + * + */ +public class CoutDownLatchTest2 +{ + public static void main(String[] args) throws InterruptedException + { + final CountDownLatch startLatch = new CountDownLatch(1); + for (int i = 0; i < 10; ++i) + { + Thread thread = new Thread("worker thread " + i) + { + public void run() + { + try + { + System.out.println("子线程开始等待主线程命令:" + Thread.currentThread().getName()); + startLatch.await(); + System.out.println("子线程完成等待主线程命令:" + Thread.currentThread().getName()); + } + catch (InterruptedException e) + { + return; + } + // do xxxx + } + }; + thread.start(); + } + + // do xxx + System.out.println("主线程马上其他线程可以继续执行了。"); + startLatch.countDown(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CyclicBarrierTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CyclicBarrierTest.java new file mode 100644 index 00000000..e948517b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/flowcontrol/CyclicBarrierTest.java @@ -0,0 +1,70 @@ +package com.xdc.basic.api.thread.flowcontrol; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +/** + * 循环障碍,可以用于性能测试 + * + * @author xdc + * + */ +class CyclicBarrierTest +{ + public static void main(String[] args) + { + int threadCount = 3; + final int loopCount = 10; + + final CyclicBarrier barrier = new CyclicBarrier(threadCount, new Runnable() + { + public void run() + { + // 等待所有子线程完成 + collectTestResult(); + } + }); + + for (int i = 0; i < threadCount; ++i) + { + Thread thread = new Thread("test-thread " + i) + { + public void run() + { + for (int j = 0; j < loopCount; ++j) + { + doTest(); + try + { + // 通知barrier已经完成 + System.out.println("子线程已完成:" + Thread.currentThread().getName()); + barrier.await(); + } + catch (InterruptedException e) + { + return; + } + catch (BrokenBarrierException e) + { + return; + } + } + } + }; + thread.start(); + } + + } + + private static void doTest() + { + System.out.println("PerformaceTest.doTest()"); + /* do xxx */ + } + + private static void collectTestResult() + { + System.out.println("PerformaceTest.collectTestResult()"); + /* do xxx */ + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lock/ReentrantLockTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/lock/ReentrantLockTest.java new file mode 100644 index 00000000..e9b9a3b1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lock/ReentrantLockTest.java @@ -0,0 +1,92 @@ +package com.xdc.basic.api.thread.lock; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Lockers 在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性, + * 在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作, + * 从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的。 + */ +public class ReentrantLockTest +{ + public static class LockTest + { + Lock lock = new ReentrantLock(); + double value = 0d; + int addtimes = 0; + + /** + * 增加value的值,该方法的操作分为2步,而且相互依赖,必须实现在一个事务中 + * 所以该方法必须同步,以前的做法是在方法声明中使用Synchronized关键字。 + */ + public void addValue(double v) + { + lock.lock();// 取得锁 + try + { + System.out.println("ReentrantLockTest.LockTest.addValue()"); + Thread.sleep(1000); + this.value += v; + this.addtimes++; + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + lock.unlock();// 释放锁 + } + } + + public double getValue() + { + System.out.println("ReentrantLockTest.LockTest.getValue()"); + return this.value; + } + } + + public static void main(String[] args) throws Exception + { + final LockTest lockTest = new LockTest(); + + // 新建任务1,调用lockTest的addValue方法 + Runnable task1 = new Runnable() + { + public void run() + { + lockTest.addValue(55.55); + } + }; + // 新建任务2,调用lockTest的getValue方法 + Runnable task2 = new Runnable() + { + public void run() + { + System.out.println("value: " + lockTest.getValue()); + } + }; + + ExecutorService cachedService = Executors.newCachedThreadPool(); + + Future future = null; + // 同时执行任务1三次,由于addValue方法使用了锁机制,所以,实质上会顺序执行 + for (int i = 0; i < 3; i++) + { + future = cachedService.submit(task1); + } + // 等待最后一个任务1被执行完 + future.get(); + + // 再执行任务2,输出结果 + future = cachedService.submit(task2); + // 等待任务2执行完后,关闭任务执行服务 + future.get(); + + cachedService.shutdownNow(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lock/ReentrantReadWriteLockTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/lock/ReentrantReadWriteLockTest.java new file mode 100644 index 00000000..4cc5d39f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lock/ReentrantReadWriteLockTest.java @@ -0,0 +1,140 @@ +package com.xdc.basic.api.thread.lock; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * 读写分离锁测试 + * Lockers 在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性, + * 在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作, + * 从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的。 + */ +public class ReentrantReadWriteLockTest +{ + /** + * ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock。 + * 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock, + * 而且写的Lock被锁定后,任何线程都不能得到Lock。ReadWriteLock提供的方法有: readLock(): 返回一个读的lock + * writeLock(): 返回一个写的lock, 此lock是排他的。 ReadWriteLockTest很适合处理类似文件的读写操作。 + * 读的时候可以同时读,但不能写;写的时候既不能同时写也不能读。 + * + * 总结: + * 先 后 + * 读 读 不阻塞 + * 读 写 阻塞 + * 写 读 阻塞 + * 写 写 阻塞 + */ + public static class ReadWriteLockTest + { + ReadWriteLock lock = new ReentrantReadWriteLock(); + double value = 0d; + int addtimes = 0; + + /** + * 增加value的值,不允许多个线程同时进入该方法 + */ + public void addValue(double v) + { + // 得到writeLock并锁定 + lock.writeLock().lock(); + try + { + System.out.println("ReentrantReadWriteLockTest.ReadWriteLockTest.addValue()"); + Thread.sleep(1000); + // 做写的工作 + this.value += v; + this.addtimes++; + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + // 释放writeLock锁 + lock.writeLock().unlock(); + } + } + + /** + * 获得信息。当有线程在调用addValue方法时,getInfo得到的信息可能是不正确的。 + * 所以,也必须保证该方法在被调用时,没有方法在调用addValue方法。 + */ + public String getInfo() + { + // 得到readLock并锁定 + lock.readLock().lock(); + try + { + System.out.println("ReentrantReadWriteLockTest.ReadWriteLockTest.getInfo()"); + Thread.sleep(1000); + // 做读的工作 + return this.value + " : " + this.addtimes; + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + finally + { + // 释放readLock + lock.readLock().unlock(); + } + return null; + } + } + + public static void main(String[] args) throws Exception + { + final ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest(); + + // 新建任务1,调用lockTest的addValue方法 + Runnable task1 = new Runnable() + { + public void run() + { + readWriteLockTest.addValue(55.55); + } + }; + // 新建任务2,调用lockTest的getValue方法 + Runnable task2 = new Runnable() + { + public void run() + { + System.out.println("info: " + readWriteLockTest.getInfo()); + } + }; + + // 新建任务执行服务 + ExecutorService cachedService = Executors.newCachedThreadPool(); + + Future future = null; + + // 同时执行5个任务,其中前2个任务是task1,后两个任务是task2 + for (int i = 0; i < 2; i++) + { + future = cachedService.submit(task1); + } + for (int i = 0; i < 2; i++) + { + future = cachedService.submit(task2); + } + // 最后一个任务是task1 + future = cachedService.submit(task1); + + // 这5个任务的执行顺序应该是: + // 第一个task1先执行,第二个task1再执行;这是因为不能同时写,所以必须等。 + // 然后2个task2同时执行;这是因为在写的时候,就不能读,所以都等待写结束, + // 又因为可以同时读,所以它们同时执行 + // 最后一个task1再执行。这是因为在读的时候,也不能写,所以必须等待读结束后,才能写。 + + // 等待最后一个task_2被执行完 + future.get(); + cachedService.shutdownNow(); + + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/BankService.java b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/BankService.java new file mode 100644 index 00000000..2d0a8e05 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/BankService.java @@ -0,0 +1,92 @@ +package com.xdc.basic.api.thread.lock.splitinglock; + +import java.util.HashMap; +import java.util.Map; + +public class BankService +{ + private Map bank = new HashMap(); + private SplitingLock lock = new SplitingLock(); + + public BankService() + { + super(); + } + + public Map getBank() + { + return bank; + } + + /** + * 存钱 + * + * @param money + */ + public void deposit(String userId, int money) + { + lock.lock(userId); + try + { + User user = bank.get(userId); + if (user == null) + { + user = new User(userId, 0); + bank.put(userId, user); + } + + System.out.println(Thread.currentThread().getName() + " : " + userId + " 开始存入 " + money + "元。当前值:" + user); + user.deposit(money); + System.out.println(Thread.currentThread().getName() + " : " + userId + " 完成存入 " + money + "元。当前值:" + user); + + try + { + Thread.sleep(10L); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + finally + { + lock.unlock(userId); + } + } + + /** + * 取钱 + * + * @param money + */ + public void withdrawing(String userId, int money) + { + lock.lock(userId); + try + { + User user = bank.get(userId); + if (user == null) + { + user = new User(userId, 0); + bank.put(userId, user); + } + + System.out.println(Thread.currentThread().getName() + " : " + userId + " 开始取出 " + money + "元。当前值:" + user); + user.withdrawing(money); + System.out.println(Thread.currentThread().getName() + " : " + userId + " 开始取出 " + money + "元。当前值:" + user); + + try + { + Thread.sleep(10L); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + finally + { + lock.unlock(userId); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/SplitingLock.java b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/SplitingLock.java new file mode 100644 index 00000000..02c1f74b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/SplitingLock.java @@ -0,0 +1,80 @@ +package com.xdc.basic.api.thread.lock.splitinglock; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * 分拆锁, 根据资源id,通过维护相应的锁,实现更细化的控制,资源之间不会干扰 + * + * @author xdc + * + */ +public class SplitingLock +{ + private Map locks = new HashMap(); + + void lock(T key) + { + CountLock lock = null; + synchronized (locks) + { + lock = locks.get(key); + if (lock == null) + { + lock = new CountLock(); + locks.put(key, lock); + } + lock.increaseCount(); + } + + lock.getLock().lock(); + } + + void unlock(T key) + { + CountLock lock = locks.get(key); + if (lock == null) + { + return; + } + lock.getLock().unlock(); + + synchronized (locks) + { + lock.decreaseCount(); + if (lock.getCount() == 0) + { + locks.remove(key); + } + } + } + + class CountLock + { + private Lock lock = new ReentrantLock(); + + private volatile int count = 0; + + public Lock getLock() + { + return lock; + } + + public int getCount() + { + return count; + } + + void increaseCount() + { + this.count++; + } + + void decreaseCount() + { + this.count--; + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/SplitingLockTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/SplitingLockTest.java new file mode 100644 index 00000000..c34a0fc2 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/SplitingLockTest.java @@ -0,0 +1,72 @@ +package com.xdc.basic.api.thread.lock.splitinglock; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class SplitingLockTest +{ + public static void main(String[] args) throws InterruptedException, ExecutionException + { + // 此处若改为使用Executors.newCachedThreadPool(),下面的其他代码保持不变,不到一会内存将被占满,机器卡死。 + // 这就能看出了两种方法的不同。 + ExecutorService pool = Executors.newFixedThreadPool(20); + + final BankService bankService = new BankService(); + + List> futures = new ArrayList>(); + for (int i = 0; i < 100000; i++) + { + Future future = pool.submit(new Runnable() + { + @Override + public void run() + { + bankService.deposit("xdc", 100); + } + }); + futures.add(future); + + future = pool.submit(new Runnable() + { + @Override + public void run() + { + bankService.withdrawing("xdc", 100); + } + }); + futures.add(future); + + future = pool.submit(new Runnable() + { + @Override + public void run() + { + bankService.deposit("gx", 100); + } + }); + futures.add(future); + + future = pool.submit(new Runnable() + { + @Override + public void run() + { + bankService.withdrawing("gx", 100); + } + }); + futures.add(future); + } + + for (Future future : futures) + { + future.get(); + } + System.out.println("最终结果: " + bankService.getBank()); + + pool.shutdown(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/User.java b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/User.java new file mode 100644 index 00000000..ada8ad6d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lock/splitinglock/User.java @@ -0,0 +1,68 @@ +package com.xdc.basic.api.thread.lock.splitinglock; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class User +{ + private String userId; + private long money; + + public User() + { + super(); + } + + public User(String userId, long money) + { + super(); + this.userId = userId; + this.money = money; + } + + public String getUserId() + { + return userId; + } + + public void setUserId(String userId) + { + this.userId = userId; + } + + public long getMoney() + { + return money; + } + + public void setMoney(long money) + { + this.money = money; + } + + /** + * 存钱 + * + * @param money + */ + public void deposit(int money) + { + this.money += money; + } + + /** + * 取钱 + * + * @param money + */ + public void withdrawing(int money) + { + this.money -= money; + } + + @Override + public String toString() + { + return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/beanmanager/BeanManagerConcurrentMap.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/beanmanager/BeanManagerConcurrentMap.java new file mode 100644 index 00000000..d27ca6dd --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/beanmanager/BeanManagerConcurrentMap.java @@ -0,0 +1,32 @@ +package com.xdc.basic.api.thread.lockfree.beanmanager; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * ConcurrentHashMap并没有实现Lock-Free,只是使用了分离锁的办法使得能够支持多个Writer并发。 + * ConcurrentHashMap需要使用更多的内存。 + * + * @author xdc + * + */ +public class BeanManagerConcurrentMap +{ + private ConcurrentMap map = new ConcurrentHashMap(); + + public Object getBean(String key) + { + Object bean = map.get(key); + if (bean == null) + { + map.putIfAbsent(key, createBean(key)); + bean = map.get(key); + } + return bean; + } + + private Object createBean(String key) + { + return key; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/beanmanager/BeanManagerSync.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/beanmanager/BeanManagerSync.java new file mode 100644 index 00000000..051440ff --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/beanmanager/BeanManagerSync.java @@ -0,0 +1,28 @@ +package com.xdc.basic.api.thread.lockfree.beanmanager; + +import java.util.HashMap; +import java.util.Map; + +public class BeanManagerSync +{ + private Map map = new HashMap(); + + public Object getBean(String key) + { + synchronized (map) + { + Object bean = map.get(key); + if (bean == null) + { + map.put(key, createBean(key)); + bean = map.get(key); + } + return bean; + } + } + + private Object createBean(String key) + { + return key; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/counter/CounterAtomicInteger.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/counter/CounterAtomicInteger.java new file mode 100644 index 00000000..71e677a3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/counter/CounterAtomicInteger.java @@ -0,0 +1,25 @@ +package com.xdc.basic.api.thread.lockfree.counter; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 这是由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。Java.util.concurrent中实现的原子操作类包括: + * AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference + * + * @author xdc + * + */ +public class CounterAtomicInteger +{ + private AtomicInteger count = new AtomicInteger(); + + public void increment() + { + count.incrementAndGet(); + } + + public int getCount() + { + return count.get(); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/counter/CounterSync.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/counter/CounterSync.java new file mode 100644 index 00000000..06381e32 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/counter/CounterSync.java @@ -0,0 +1,16 @@ +package com.xdc.basic.api.thread.lockfree.counter; + +public class CounterSync +{ + private volatile int count = 0; + + public synchronized void increment() + { + count++; + } + + public int getCount() + { + return count; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/optimisticlock/SequenceDao.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/optimisticlock/SequenceDao.java new file mode 100644 index 00000000..8ca4474f --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/optimisticlock/SequenceDao.java @@ -0,0 +1,27 @@ +package com.xdc.basic.api.thread.lockfree.database.optimisticlock; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; + +@SuppressWarnings("deprecation") +public class SequenceDao extends SqlMapClientDaoSupport +{ + public boolean compareAndSet(String name, int value, int expect) + { + Map parameters = new HashMap(); + parameters.put("name", name); + parameters.put("value", value); + parameters.put("expect", expect); + // UPDATE t_sequence SET value = #value# WHERE name = #name# AND value = #expect# + int updateCount = getSqlMapClientTemplate().update("Sequence.compareAndSet", parameters); + return updateCount == 1; + } + + public int getValue(String sequenceName) + { + // 在数据库中查询当前值 + return 0; + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/optimisticlock/SequenceService.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/optimisticlock/SequenceService.java new file mode 100644 index 00000000..296be669 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/optimisticlock/SequenceService.java @@ -0,0 +1,29 @@ +package com.xdc.basic.api.thread.lockfree.database.optimisticlock; + +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +/** + * CAS用于更新数据库-乐观锁 + * + * @author xdc + * + */ +public class SequenceService +{ + private SequenceDao dao; + + // 注意,乐观锁时必须使用:@Transactional(propagation = Propagation.NOT_SUPPORTED) + @Transactional(propagation = Propagation.NOT_SUPPORTED) + public synchronized void increment(String sequenceName) + { + for (;;) + { + int value = dao.getValue(sequenceName); + if (dao.compareAndSet(sequenceName, value + 1, value)) + { + break; + } + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/pessimisticlock/SequenceDao.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/pessimisticlock/SequenceDao.java new file mode 100644 index 00000000..e14c9cdf --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/pessimisticlock/SequenceDao.java @@ -0,0 +1,25 @@ +package com.xdc.basic.api.thread.lockfree.database.pessimisticlock; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; + +@SuppressWarnings("deprecation") +public class SequenceDao extends SqlMapClientDaoSupport +{ + public int getValueForUpdate(String name) + { + // SELECT value FROM t_sequenceWHERE name = #name# FOR UPDATE + return (Integer) getSqlMapClientTemplate().queryForObject("Sequence.getValueForUpdate", name); + } + + public void set(String name, int value) + { + Map parameters = new HashMap(); + parameters.put("name", name); + parameters.put("value", value); + // UPDATE t_sequence SET value = #value# WHERE name = #name# + getSqlMapClientTemplate().update("Sequence.set", parameters); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/pessimisticlock/SequenceService.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/pessimisticlock/SequenceService.java new file mode 100644 index 00000000..52b7faed --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/database/pessimisticlock/SequenceService.java @@ -0,0 +1,22 @@ +package com.xdc.basic.api.thread.lockfree.database.pessimisticlock; + +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +/** + * 使用悲观锁版本 + * + * @author xdc + * + */ +public class SequenceService +{ + private SequenceDao dao; + + @Transactional(propagation = Propagation.REQUIRED) + public synchronized void increment2(String sequenceName) + { + int value = dao.getValueForUpdate(sequenceName); + dao.set(sequenceName, value + 1); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/databuffer/DataBufferBlockingQueue.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/databuffer/DataBufferBlockingQueue.java new file mode 100644 index 00000000..4e04612b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/databuffer/DataBufferBlockingQueue.java @@ -0,0 +1,82 @@ +package com.xdc.basic.api.thread.lockfree.databuffer; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.apache.commons.lang3.RandomStringUtils; + +/** + * http://www.fengfly.com/plus/view-191064-1.html + * + * @author xdc + * + */ +public class DataBufferBlockingQueue +{ + public static void main(String[] args) + { + BlockingQueue dataQueue = new ArrayBlockingQueue(1, true); + + ExecutorService pool = Executors.newCachedThreadPool(); + pool.submit(new Producer(dataQueue)); + pool.submit(new Consumer(dataQueue)); + + // 执行后关闭线程池 + pool.shutdown(); + } +} + +class Producer implements Runnable +{ + private BlockingQueue dataQueue; + + public Producer(BlockingQueue dataQueue) + { + this.dataQueue = dataQueue; + } + + public void run() + { + try + { + for (int i = 0; i < 10; i++) + { + String data = RandomStringUtils.randomAlphanumeric(6); + dataQueue.put(data); + System.out.println(data + " is putted!"); + } + + dataQueue.put("END"); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} + +class Consumer implements Runnable +{ + private BlockingQueue dataQueue; + + public Consumer(BlockingQueue dataQueue) + { + this.dataQueue = dataQueue; + } + + public void run() + { + String msg = null; + try + { + while (!((msg = dataQueue.take()).equals("END"))) + System.out.println(msg + " is token!"); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/databuffer/DataBufferSync.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/databuffer/DataBufferSync.java new file mode 100644 index 00000000..c2913d90 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/databuffer/DataBufferSync.java @@ -0,0 +1,142 @@ +package com.xdc.basic.api.thread.lockfree.databuffer; + +import java.util.Vector; + +import org.apache.commons.lang3.RandomStringUtils; + +public class DataBufferSync +{ + Vector dataBuffer = new Vector(); // 数据缓冲区 + final int MAX_SIZE = 3; // 设置缓冲区大小 + + void addData() + { + synchronized (dataBuffer) + { + String name = Thread.currentThread().getName(); + System.out.println(name + " enter addData()"); + + while (dataBuffer.size() == MAX_SIZE) + { + try + { + System.out.println(name + " data buffer is full, try to wait"); + dataBuffer.wait(); + System.out.println(name + " wake up, continue to add data"); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + String data = "value-" + RandomStringUtils.randomNumeric(2); + dataBuffer.add(data); + dataBuffer.notifyAll(); + + System.out.println(name + " adds " + data + ", ramains " + dataBuffer.size()); + System.out.println(name + " leave addData()"); + } + } + + void removeData() + { + synchronized (dataBuffer) + { + String name = Thread.currentThread().getName(); + System.out.println(name + " enter removeData()"); + + while (dataBuffer.size() == 0) + { + try + { + // 临时释放锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行. + // 其他线程在执行到一定地方后用notify()通知wait()的线程, + // 待notify()所在的同步块运行完之后,wait所在的线程就可以继续执行. + System.out.println(name + " data buffer is empty, try to wait"); + dataBuffer.wait(); + System.out.println(name + " wake up, continue to remove data"); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + String data = dataBuffer.remove(0); + dataBuffer.notifyAll(); + + System.out.println(name + " removes " + data + ", ramains " + dataBuffer.size()); + System.out.println(name + " leave removeData()"); + } + } + + private void start() + { + new Consumer(this).start(); + new Consumer(this).start(); + new Consumer(this).start(); + new Producer(this).start(); + } + + public static void main(String[] args) + { + DataBufferSync wn = new DataBufferSync(); + wn.start(); + } + + class Producer extends Thread + { + DataBufferSync synObject; + + Producer(DataBufferSync synObject) + { + this.synObject = synObject; + } + + public void run() + { + String name = getName(); + while (true) + { + System.out.println(name + " try to add Data ..."); + synObject.addData(); + try + { + Thread.sleep(1000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + } + } + + class Consumer extends Thread + { + DataBufferSync synObject; + + Consumer(DataBufferSync synObject) + { + this.synObject = synObject; + } + + public void run() + { + String name = getName(); + while (true) + { + System.out.println(name + " try to remove Data ..."); + synObject.removeData(); + try + { + Thread.sleep(4000); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/engine/EngineCopyOnWriteArrayList.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/engine/EngineCopyOnWriteArrayList.java new file mode 100644 index 00000000..b30cdee7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/engine/EngineCopyOnWriteArrayList.java @@ -0,0 +1,25 @@ +package com.xdc.basic.api.thread.lockfree.engine; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import com.google.common.util.concurrent.ServiceManager.Listener; + +class EngineCopyOnWriteArrayList +{ + private List listeners = new CopyOnWriteArrayList(); + + public boolean addListener(Listener listener) + { + return listeners.add(listener); + } + + @SuppressWarnings("unused") + public void doXXX() + { + for (Listener listener : listeners) + { + // listener.handle(); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/engine/EngineSync.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/engine/EngineSync.java new file mode 100644 index 00000000..2cd9de39 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/engine/EngineSync.java @@ -0,0 +1,31 @@ +package com.xdc.basic.api.thread.lockfree.engine; + +import java.util.ArrayList; +import java.util.List; + +import com.google.common.util.concurrent.ServiceManager.Listener; + +class Engine +{ + private List listeners = new ArrayList(); + + public boolean addListener(Listener listener) + { + synchronized (listeners) + { + return listeners.add(listener); + } + } + + @SuppressWarnings("unused") + public void doXXX() + { + synchronized (listeners) + { + for (Listener listener : listeners) + { + // listener.handle(); + } + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/maxholder/MaxHolderCAS.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/maxholder/MaxHolderCAS.java new file mode 100644 index 00000000..dde2d9f1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/maxholder/MaxHolderCAS.java @@ -0,0 +1,42 @@ +package com.xdc.basic.api.thread.lockfree.maxholder; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * LockFree算法,不需要加锁。通常都是三个部分组成: ①循环 ②CAS (CompareAndSet) ③回退 + * + * @author xdc + * + */ +public class MaxHolderCAS +{ + private AtomicInteger max = new AtomicInteger(); + + public void set(int value) + { + for (;;) + { + int current = max.get(); + if (value > current) + { + if (max.compareAndSet(current, value)) + { + break; + } + else + { + continue; + } + } + else + { + break; + } + } + } + + public int getMax() + { + return max.get(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/maxholder/MaxHolderSync.java b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/maxholder/MaxHolderSync.java new file mode 100644 index 00000000..64e90c12 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/lockfree/maxholder/MaxHolderSync.java @@ -0,0 +1,19 @@ +package com.xdc.basic.api.thread.lockfree.maxholder; + +public class MaxHolderSync +{ + private volatile int max = 0; + + public synchronized void set(int value) + { + if (value > max) + { + max = value; + } + } + + public int getMax() + { + return max; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo1/RunnableImpl.java b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo1/RunnableImpl.java new file mode 100644 index 00000000..893e02e7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo1/RunnableImpl.java @@ -0,0 +1,25 @@ +package com.xdc.basic.api.thread.synclock.demo1; + +class RunnableImpl implements Runnable +{ + // 火车票张数 + int i = 100000; + + public void run() + { + while (true) + { + synchronized (this) + { + // 如果张数小于等于0,就没有了,不买了 + if (i <= 0) + { + break; + } + System.out.println(Thread.currentThread().getName() + "买到了一张火车票,编号:" + i); + i--; + Thread.yield(); + } + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/java4android/thread/implrunable/Test.java b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo1/Test.java similarity index 84% rename from basicKnowledge/src/com/xdc/basic/java4android/thread/implrunable/Test.java rename to basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo1/Test.java index c7e115c2..0e799f96 100644 --- a/basicKnowledge/src/com/xdc/basic/java4android/thread/implrunable/Test.java +++ b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo1/Test.java @@ -1,20 +1,20 @@ -package com.xdc.basic.java4android.thread.implrunable; - -class Test -{ - public static void main(String[] args) - { - // 生成一个Runnable接口的实现类的对象 - RunnableImpl r = new RunnableImpl(); - // 生成一个Thread对象,并将Runnalbe接口的实 - // 现类的对象作为参数传递给该Thread对象 - - Thread t = new Thread(r); - t.setName("t1"); - t.start(); - - Thread t2 = new Thread(r); - t2.setName("t2"); - t2.start(); - } -} +package com.xdc.basic.api.thread.synclock.demo1; + +class Test +{ + public static void main(String[] args) + { + // 生成一个Runnable接口的实现类的对象 + RunnableImpl r = new RunnableImpl(); + // 生成一个Thread对象,并将Runnalbe接口的实 + // 现类的对象作为参数传递给该Thread对象 + + Thread t = new Thread(r); + t.setName("t1"); + t.start(); + + Thread t2 = new Thread(r); + t2.setName("t2"); + t2.start(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo2/Person.java b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo2/Person.java new file mode 100644 index 00000000..b452012c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo2/Person.java @@ -0,0 +1,104 @@ +package com.xdc.basic.api.thread.synclock.demo2; + +public class Person +{ + public void listenMusic() + { + System.out.println("--------------------------------- I'm listening music."); + sleepHalfSecond(); + } + + public synchronized void study() + { + System.out.println("I will start to study."); + sleep1Second(); + + for (int i = 0; i < 5; i++) + { + System.out.println("+++++++++++++++++++++++++++++++++ I'm studying."); + sleep1Second(); + } + + System.out.println("I have finished my study."); + sleep1Second(); + } + + public synchronized void sleep() + { + System.out.println("I will start to sleep."); + sleep1Second(); + + for (int i = 0; i < 5; i++) + { + System.out.println("================================= I'm sleepping. zzZ..."); + sleep1Second(); + } + + System.out.println("I have finished my sleep."); + sleep1Second(); + } + + public void playFootball() + { + System.out.println("I will start to play football."); + sleep1Second(); + + synchronized (this) + { + for (int i = 0; i < 5; i++) + { + System.out.println("********************************* I'm playing football."); + sleep1Second(); + } + } + + System.out.println("I have finished playing football."); + sleep1Second(); + } + + public void playBasketball() + { + System.out.println("I will start to play basketball."); + sleep1Second(); + + synchronized (this) + { + for (int i = 0; i < 5; i++) + { + System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& I am playing basketball."); + sleep1Second(); + } + } + + System.out.println("I have finished playing basketball."); + sleep1Second(); + } + + private void sleep1Second() + { + try + { + Thread.sleep(1000L); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + private void sleepHalfSecond() + { + try + { + Thread.sleep(500L); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + // Ps: synchronized void f() { /* body */ } + // 和 void f() { synchronized(this) { /* body */ } } + // 是完全等价的。 +} diff --git a/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo2/syncTest.java b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo2/syncTest.java new file mode 100644 index 00000000..28059ebd --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/thread/synclock/demo2/syncTest.java @@ -0,0 +1,76 @@ +package com.xdc.basic.api.thread.synclock.demo2; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class syncTest +{ + + public static void main(String[] args) + { + ExecutorService pool = Executors.newCachedThreadPool(); + + final Person person = new Person(); + + pool.execute(new Runnable() + { + @Override + public void run() + { + while (true) + { + person.listenMusic(); + } + } + }); + + pool.execute(new Runnable() + { + @Override + public void run() + { + while (true) + { + person.study(); + } + } + }); + + pool.execute(new Runnable() + { + @Override + public void run() + { + while (true) + { + person.sleep(); + } + } + }); + + pool.execute(new Runnable() + { + @Override + public void run() + { + while (true) + { + person.playFootball(); + } + } + }); + + pool.execute(new Runnable() + { + @Override + public void run() + { + while (true) + { + person.playBasketball(); + } + } + }); + } + +} diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/Student.java b/basicKnowledge/src/com/xdc/basic/api/xml/Student.java new file mode 100644 index 00000000..14d175d1 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/Student.java @@ -0,0 +1,81 @@ +package com.xdc.basic.api.xml; + +public class Student +{ + private String id; + private String name; + private String age; + private String sex; + private String address; + + public Student() + { + super(); + } + + public Student(String id, String name, String age, String sex, String address) + { + super(); + this.id = id; + this.name = name; + this.age = age; + this.sex = sex; + this.address = address; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getAge() + { + return age; + } + + public void setAge(String age) + { + this.age = age; + } + + public String getSex() + { + return sex; + } + + public void setSex(String sex) + { + this.sex = sex; + } + + public String getAddress() + { + return address; + } + + public void setAddress(String address) + { + this.address = address; + } + + @Override + public String toString() + { + return String.format("Student [id=%s, name=%s, age=%s, sex=%s, address=%s]", id, name, age, sex, address); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/X1_DomTest.java b/basicKnowledge/src/com/xdc/basic/api/xml/X1_DomTest.java new file mode 100644 index 00000000..4827b81a --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/X1_DomTest.java @@ -0,0 +1,53 @@ +package com.xdc.basic.api.xml; + +import java.io.File; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import com.xdc.basic.skills.GetCurPath; + +public class X1_DomTest +{ + public static void main(String arge[]) + { + String curPath = GetCurPath.getCurPath(); + File file = new File(curPath + "students.xml"); + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(file); + + Element element = doc.getDocumentElement(); + NodeList nodeList = element.getElementsByTagName("student"); + for (int i = 0; i < nodeList.getLength(); i++) + { + Element student = (Element) nodeList.item(i); + String id = student.getAttribute("id"); + + Element studentName = (Element) student.getElementsByTagName("name").item(0); + String name = studentName.getFirstChild().getNodeValue(); + + Element studentAge = (Element) student.getElementsByTagName("age").item(0); + String age = studentAge.getFirstChild().getNodeValue(); + + Element studentSex = (Element) student.getElementsByTagName("sex").item(0); + String sex = studentSex.getFirstChild().getNodeValue(); + + Element studentAddress = (Element) student.getElementsByTagName("address").item(0); + String address = studentAddress.getFirstChild().getNodeValue(); + + System.out.println(new Student(id, name, age, sex, address)); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/X2_SaxTest.java b/basicKnowledge/src/com/xdc/basic/api/xml/X2_SaxTest.java new file mode 100644 index 00000000..c207c6a7 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/X2_SaxTest.java @@ -0,0 +1,27 @@ +package com.xdc.basic.api.xml; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; + +import com.xdc.basic.skills.GetCurPath; + +public class X2_SaxTest extends DefaultHandler +{ + public static void main(String[] args) throws Exception + { + String curPath = GetCurPath.getCurPath(); + InputSource is = new InputSource(curPath + "students.xml"); + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + SAXParser parser = parserFactory.newSAXParser(); + X2_StudentHandler studentHandler = new X2_StudentHandler(); + parser.parse(is, studentHandler); + + for (Student student : studentHandler.getStudentList()) + { + System.out.println(student); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/X2_StudentHandler.java b/basicKnowledge/src/com/xdc/basic/api/xml/X2_StudentHandler.java new file mode 100644 index 00000000..09c315ce --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/X2_StudentHandler.java @@ -0,0 +1,82 @@ +package com.xdc.basic.api.xml; + +import java.util.ArrayList; +import java.util.List; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +public class X2_StudentHandler extends DefaultHandler +{ + private Student newStudent; + private String curTag; + private List studentList; + + public List getStudentList() + { + return studentList; + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException + { + String data = new String(ch, start, length); + if (null != curTag) + { + if ("name".equalsIgnoreCase(curTag)) + { + newStudent.setName(data); + } + else if ("age".equalsIgnoreCase(curTag)) + { + newStudent.setAge(data); + } + else if ("sex".equalsIgnoreCase(curTag)) + { + newStudent.setSex(data); + } + else if ("address".equalsIgnoreCase(curTag)) + { + newStudent.setAddress(data); + } + } + } + + @Override + public void startDocument() throws SAXException + { + studentList = new ArrayList(); + } + + @Override + public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException + { + if ("student".equals(name)) + { + newStudent = new Student(); + if (attributes != null) + { + newStudent.setId(attributes.getValue("id")); + } + } + curTag = name; + } + + @Override + public void endDocument() throws SAXException + { + + } + + @Override + public void endElement(String uri, String localName, String name) throws SAXException + { + if ("student".equalsIgnoreCase(name)) + { + studentList.add(newStudent); + newStudent = null; + } + curTag = null; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/X3_JdomTest.java b/basicKnowledge/src/com/xdc/basic/api/xml/X3_JdomTest.java new file mode 100644 index 00000000..8b5ed98c --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/X3_JdomTest.java @@ -0,0 +1,41 @@ +package com.xdc.basic.api.xml; + +import java.io.File; +import java.util.List; + +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.input.SAXBuilder; + +import com.xdc.basic.skills.GetCurPath; + +public class X3_JdomTest +{ + public static void main(String arge[]) + { + String curPath = GetCurPath.getCurPath(); + File file = new File(curPath + "students.xml"); + try + { + SAXBuilder builder = new SAXBuilder(); + Document doc = builder.build(file); + Element root = doc.getRootElement(); + List allChildren = root.getChildren(); + + for (Element element : allChildren) + { + String id = element.getAttribute("id").getValue(); + String name = element.getChild("name").getText(); + String age = element.getChild("age").getText(); + String sex = element.getChild("sex").getText(); + String address = element.getChild("address").getText(); + + System.out.println(new Student(id, name, age, sex, address)); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/X4_Dom4jTest.java b/basicKnowledge/src/com/xdc/basic/api/xml/X4_Dom4jTest.java new file mode 100644 index 00000000..c00bdc84 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/X4_Dom4jTest.java @@ -0,0 +1,43 @@ +package com.xdc.basic.api.xml; + +import java.io.File; +import java.util.List; + +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +import com.xdc.basic.skills.GetCurPath; + +public class X4_Dom4jTest +{ + public static void main(String arge[]) + { + String curPath = GetCurPath.getCurPath(); + File file = new File(curPath + "students.xml"); + try + { + SAXReader reader = new SAXReader(); + Document doc = reader.read(file); + Element root = doc.getRootElement(); + List elements = root.elements("student"); + + for (Object object : elements) + { + Element element = (Element) object; + + String id = element.attribute("id").getValue(); + String name = element.element("name").getText(); + String age = element.element("age").getText(); + String sex = element.element("sex").getText(); + String address = element.element("address").getText(); + + System.out.println(new Student(id, name, age, sex, address)); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/X5_xmlPullTest.java b/basicKnowledge/src/com/xdc/basic/api/xml/X5_xmlPullTest.java new file mode 100644 index 00000000..86df3513 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/X5_xmlPullTest.java @@ -0,0 +1,95 @@ +package com.xdc.basic.api.xml; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import com.xdc.basic.skills.GetCurPath; + +public class X5_xmlPullTest +{ + public static void main(String[] args) + { + String curPath = GetCurPath.getCurPath(); + try + { + XmlPullParserFactory pullParserFactory = XmlPullParserFactory.newInstance(); + XmlPullParser xmlPullParser = pullParserFactory.newPullParser(); + + File file = new File(curPath + "students.xml"); + Reader reader = new FileReader(file); + xmlPullParser.setInput(reader); + + Student student = null; + int eventType = xmlPullParser.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) + { + String nodeName = xmlPullParser.getName(); + switch (eventType) + { + case XmlPullParser.START_DOCUMENT: + break; + + case XmlPullParser.START_TAG: + if ("student".equals(nodeName)) + { + student = new Student(); + student.setId(xmlPullParser.getAttributeValue(0)); + } + else if ("name".equals(nodeName)) + { + student.setName(xmlPullParser.nextText()); + } + else if ("age".equals(nodeName)) + { + student.setAge(xmlPullParser.nextText()); + } + else if ("sex".equals(nodeName)) + { + student.setSex(xmlPullParser.nextText()); + } + + else if ("address".equals(nodeName)) + { + student.setAddress(xmlPullParser.nextText()); + } + break; + + case XmlPullParser.TEXT: + break; + + case XmlPullParser.END_TAG: + if ("student".equals(nodeName)) + { + System.out.println(student); + student = null; + } + break; + + default: + break; + } + xmlPullParser.next(); + eventType = xmlPullParser.getEventType(); + } + } + catch (XmlPullParserException e) + { + e.printStackTrace(); + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } +} diff --git a/jdom2.format/src/com/xdc/PrettyPrinter.java b/basicKnowledge/src/com/xdc/basic/api/xml/formater/PrettyPrinter.java similarity index 75% rename from jdom2.format/src/com/xdc/PrettyPrinter.java rename to basicKnowledge/src/com/xdc/basic/api/xml/formater/PrettyPrinter.java index 574196f7..667b1724 100644 --- a/jdom2.format/src/com/xdc/PrettyPrinter.java +++ b/basicKnowledge/src/com/xdc/basic/api/xml/formater/PrettyPrinter.java @@ -1,4 +1,4 @@ -package com.xdc; +package com.xdc.basic.api.xml.formater; import java.io.File; @@ -7,17 +7,20 @@ import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; +import com.xdc.basic.skills.GetCurPath; + public class PrettyPrinter { public static void main(String[] args) { - String filename = "users.xml"; + String curPath = GetCurPath.getCurPath(); + try { // Build the document with SAX and Xerces, no validation SAXBuilder builder = new SAXBuilder(); // Create the document - Document doc = builder.build(new File(filename)); + Document doc = builder.build(new File(curPath + "users.xml")); // Output the document, use standard formatter XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); outputter.output(doc, System.out); diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/formater/users.xml b/basicKnowledge/src/com/xdc/basic/api/xml/formater/users.xml new file mode 100644 index 00000000..af30b881 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/formater/users.xml @@ -0,0 +1,14 @@ + + + 小李 + 24 + + 小丽 + + 18 + + 小王 + + 22 + + \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/api/xml/students.xml b/basicKnowledge/src/com/xdc/basic/api/xml/students.xml new file mode 100644 index 00000000..8630ec37 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/api/xml/students.xml @@ -0,0 +1,63 @@ + + + + student0 + 10 + +

陕西西安
+ + + student1 + 11 + +
陕西西安
+
+ + student2 + 12 + +
陕西西安
+
+ + student3 + 13 + +
陕西西安
+
+ + student4 + 14 + +
陕西西安
+
+ + student5 + 15 + +
陕西西安
+
+ + student6 + 16 + +
陕西西安
+
+ + student7 + 17 + +
陕西西安
+
+ + student8 + 18 + +
陕西西安
+
+ + student9 + 19 + +
陕西西安
+
+ \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/NameObserver.java b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/NameObserver.java new file mode 100644 index 00000000..c0fe999e --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/NameObserver.java @@ -0,0 +1,21 @@ +package com.xdc.basic.book.designpattern.observer; + +import java.util.Observable; +import java.util.Observer; + +// 观察者NameObserver主要用来对产品名称(name)进行观察的 +public class NameObserver implements Observer +{ + private String name = null; + + @Override + public void update(Observable obj, Object arg) + { + if (arg instanceof String) + { + name = (String) arg; + // 产品名称改变值在name中 + System.out.println("NameObserver: name changet to " + name); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/ObserverTest.java b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/ObserverTest.java new file mode 100644 index 00000000..1c5f8a2d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/ObserverTest.java @@ -0,0 +1,19 @@ +package com.xdc.basic.book.designpattern.observer; + +public class ObserverTest +{ + public static void main(String[] args) + { + Product product = new Product(); + + NameObserver nameobs = new NameObserver(); + PriceObserver priceobs = new PriceObserver(); + + // 加入观察者 + product.addObserver(nameobs); + product.addObserver(priceobs); + + product.setName("橘子红了"); + product.setPrice(9.22f); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/PriceObserver.java b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/PriceObserver.java new file mode 100644 index 00000000..ef4c0a3e --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/PriceObserver.java @@ -0,0 +1,20 @@ +package com.xdc.basic.book.designpattern.observer; + +import java.util.Observable; +import java.util.Observer; + +// 观察者PriceObserver主要用来对产品价格(price)进行观察的 +public class PriceObserver implements Observer +{ + private float price = 0; + + public void update(Observable obj, Object arg) + { + if (arg instanceof Float) + { + price = ((Float) arg).floatValue(); + // 产品价格改变值在price中 + System.out.println("PriceObserver: price changet to " + price); + } + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/Product.java b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/Product.java new file mode 100644 index 00000000..79520df3 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/designpattern/observer/Product.java @@ -0,0 +1,37 @@ +package com.xdc.basic.book.designpattern.observer; + +import java.util.Observable; + +// 产品类 可供Jsp直接使用UseBean调用 该类主要执行产品数据库插入 更新 +public class Product extends Observable +{ + private String name; + private float price; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + // 设置变化点 + setChanged(); + // 变更会通过循环通知给所有观察者,观察者通过判断类型过滤掉他不关心的变更 + notifyObservers(name); + } + + public float getPrice() + { + return price; + } + + public void setPrice(float price) + { + this.price = price; + // 设置变化点 + setChanged(); + notifyObservers(new Float(price)); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/brokenstopthread/StopThread.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/brokenstopthread/StopThread.java new file mode 100644 index 00000000..bcce232b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/brokenstopthread/StopThread.java @@ -0,0 +1,28 @@ +package com.xdc.basic.book.effectivejava.Chapter10.Item66.brokenstopthread; + +// Broken! - How long would you expect this program to run? - Page 259 + +import java.util.concurrent.TimeUnit; + +public class StopThread +{ + private static boolean stopRequested; + + public static void main(String[] args) throws InterruptedException + { + Thread backgroundThread = new Thread(new Runnable() + { + public void run() + { + @SuppressWarnings("unused") + int i = 0; + while (!stopRequested) + i++; + } + }); + backgroundThread.start(); + + TimeUnit.SECONDS.sleep(1); + stopRequested = true; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/fixedstopthread1/StopThread.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/fixedstopthread1/StopThread.java new file mode 100644 index 00000000..eb9c9619 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/fixedstopthread1/StopThread.java @@ -0,0 +1,38 @@ +package com.xdc.basic.book.effectivejava.Chapter10.Item66.fixedstopthread1; + +// Properly synchronized cooperative thread termination - Page 261 + +import java.util.concurrent.TimeUnit; + +public class StopThread +{ + private static boolean stopRequested; + + private static synchronized void requestStop() + { + stopRequested = true; + } + + private static synchronized boolean stopRequested() + { + return stopRequested; + } + + public static void main(String[] args) throws InterruptedException + { + Thread backgroundThread = new Thread(new Runnable() + { + public void run() + { + @SuppressWarnings("unused") + int i = 0; + while (!stopRequested()) + i++; + } + }); + backgroundThread.start(); + + TimeUnit.SECONDS.sleep(1); + requestStop(); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/fixedstopthread2/StopThread.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/fixedstopthread2/StopThread.java new file mode 100644 index 00000000..8cc5717e --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter10/Item66/fixedstopthread2/StopThread.java @@ -0,0 +1,28 @@ +package com.xdc.basic.book.effectivejava.Chapter10.Item66.fixedstopthread2; + +// Cooperative thread termination with a volatile field + +import java.util.concurrent.TimeUnit; + +public class StopThread +{ + private static volatile boolean stopRequested; + + public static void main(String[] args) throws InterruptedException + { + Thread backgroundThread = new Thread(new Runnable() + { + public void run() + { + @SuppressWarnings("unused") + int i = 0; + while (!stopRequested) + i++; + } + }); + backgroundThread.start(); + + TimeUnit.SECONDS.sleep(1); + stopRequested = true; + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter2/Item2/builder/NutritionFacts.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter2/Item2/builder/NutritionFacts.java new file mode 100644 index 00000000..425f01ed --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter2/Item2/builder/NutritionFacts.java @@ -0,0 +1,77 @@ +package com.xdc.basic.book.effectivejava.Chapter2.Item2.builder; + +// Builder Pattern - Pages 14-15 + +@SuppressWarnings("unused") +public class NutritionFacts +{ + private final int servingSize; + private final int servings; + private final int calories; + private final int fat; + private final int sodium; + private final int carbohydrate; + + public static class Builder + { + // Required parameters + private final int servingSize; + private final int servings; + + // Optional parameters - initialized to default values + private int calories = 0; + private int fat = 0; + private int carbohydrate = 0; + private int sodium = 0; + + public Builder(int servingSize, int servings) + { + this.servingSize = servingSize; + this.servings = servings; + } + + public Builder calories(int val) + { + calories = val; + return this; + } + + public Builder fat(int val) + { + fat = val; + return this; + } + + public Builder carbohydrate(int val) + { + carbohydrate = val; + return this; + } + + public Builder sodium(int val) + { + sodium = val; + return this; + } + + public NutritionFacts build() + { + return new NutritionFacts(this); + } + } + + private NutritionFacts(Builder builder) + { + servingSize = builder.servingSize; + servings = builder.servings; + calories = builder.calories; + fat = builder.fat; + sodium = builder.sodium; + carbohydrate = builder.carbohydrate; + } + + public static void main(String[] args) + { + NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build(); + } +} \ No newline at end of file diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter3/Item12/PhoneNumber.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter3/Item12/PhoneNumber.java new file mode 100644 index 00000000..da0e10de --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter3/Item12/PhoneNumber.java @@ -0,0 +1,140 @@ +package com.xdc.basic.book.effectivejava.Chapter3.Item12; + +// Making PhoneNumber comparable - Pages 65-66 + +import java.util.NavigableSet; +import java.util.Random; +import java.util.TreeSet; + +public final class PhoneNumber implements Cloneable, Comparable +{ + private final short areaCode; + private final short prefix; + private final short lineNumber; + + public PhoneNumber(int areaCode, int prefix, int lineNumber) + { + rangeCheck(areaCode, 999, "area code"); + rangeCheck(prefix, 999, "prefix"); + rangeCheck(lineNumber, 9999, "line number"); + this.areaCode = (short) areaCode; + this.prefix = (short) prefix; + this.lineNumber = (short) lineNumber; + } + + private static void rangeCheck(int arg, int max, String name) + { + if (arg < 0 || arg > max) + throw new IllegalArgumentException(name + ": " + arg); + } + + @Override + public boolean equals(Object o) + { + if (o == this) + return true; + if (!(o instanceof PhoneNumber)) + return false; + PhoneNumber pn = (PhoneNumber) o; + return pn.lineNumber == lineNumber && pn.prefix == prefix && pn.areaCode == areaCode; + } + + @Override + public int hashCode() + { + int result = 17; + result = 31 * result + areaCode; + result = 31 * result + prefix; + result = 31 * result + lineNumber; + return result; + } + + /** + * Returns the string representation of this phone number. + * The string consists of fourteen characters whose format + * is "(XXX) YYY-ZZZZ", where XXX is the area code, YYY is + * the prefix, and ZZZZ is the line number. (Each of the + * capital letters represents a single decimal digit.) + * + * If any of the three parts of this phone number is too small + * to fill up its field, the field is padded with leading zeros. + * For example, if the value of the line number is 123, the last + * four characters of the string representation will be "0123". + * + * Note that there is a single space separating the closing + * parenthesis after the area code from the first digit of the + * prefix. + */ + @Override + public String toString() + { + return String.format("(%03d) %03d-%04d", areaCode, prefix, lineNumber); + } + + @Override + public PhoneNumber clone() + { + try + { + return (PhoneNumber) super.clone(); + } + catch (CloneNotSupportedException e) + { + throw new AssertionError(); // Can't happen + } + } + + // Works fine, but can be made faster + // public int compareTo(PhoneNumber pn) { + // // Compare area codes + // if (areaCode < pn.areaCode) + // return -1; + // if (areaCode > pn.areaCode) + // return 1; + // + // // Area codes are equal, compare prefixes + // if (prefix < pn.prefix) + // return -1; + // if (prefix > pn.prefix) + // return 1; + // + // // Area codes and prefixes are equal, compare line numbers + // if (lineNumber < pn.lineNumber) + // return -1; + // if (lineNumber > pn.lineNumber) + // return 1; + // + // return 0; // All fields are equal + // } + + public int compareTo(PhoneNumber pn) + { + // Compare area codes + int areaCodeDiff = areaCode - pn.areaCode; + if (areaCodeDiff != 0) + return areaCodeDiff; + + // Area codes are equal, compare prefixes + int prefixDiff = prefix - pn.prefix; + if (prefixDiff != 0) + return prefixDiff; + + // Area codes and prefixes are equal, compare line numbers + return lineNumber - pn.lineNumber; + } + + public static void main(String[] args) + { + NavigableSet s = new TreeSet(); + for (int i = 0; i < 10; i++) + s.add(randomPhoneNumber()); + System.out.println(s); + } + + private static final Random rnd = new Random(); + + private static PhoneNumber randomPhoneNumber() + { + return new PhoneNumber((short) rnd.nextInt(1000), (short) rnd.nextInt(1000), (short) rnd.nextInt(10000)); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/Operation.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/Operation.java new file mode 100644 index 00000000..35a2a13b --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/Operation.java @@ -0,0 +1,47 @@ +package com.xdc.basic.book.effectivejava.Chapter6.Item30; + +// Enum type with constant-specific class bodies and data - Page 153 + +import java.util.*; + +public enum Operation { + PLUS("+") { + double apply(double x, double y) { return x + y; } + }, + MINUS("-") { + double apply(double x, double y) { return x - y; } + }, + TIMES("*") { + double apply(double x, double y) { return x * y; } + }, + DIVIDE("/") { + double apply(double x, double y) { return x / y; } + }; + private final String symbol; + Operation(String symbol) { this.symbol = symbol; } + @Override public String toString() { return symbol; } + + abstract double apply(double x, double y); + + // Implementing a fromString method on an enum type - Page 154 + private static final Map stringToEnum + = new HashMap(); + static { // Initialize map from constant name to enum constant + for (Operation op : values()) + stringToEnum.put(op.toString(), op); + } + // Returns Operation for string, or null if string is invalid + public static Operation fromString(String symbol) { + return stringToEnum.get(symbol); + } + + + // Test program to perform all operations on given operands + public static void main(String[] args) { + double x = Double.parseDouble(args[0]); + double y = Double.parseDouble(args[1]); + for (Operation op : Operation.values()) + System.out.printf("%f %s %f = %f%n", + x, op, y, op.apply(x, y)); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/PayrollDay.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/PayrollDay.java new file mode 100644 index 00000000..7efd271d --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/PayrollDay.java @@ -0,0 +1,38 @@ +package com.xdc.basic.book.effectivejava.Chapter6.Item30; + +// The strategy enum pattern +enum PayrollDay { + MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), + WEDNESDAY(PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), + FRIDAY(PayType.WEEKDAY), + SATURDAY(PayType.WEEKEND), SUNDAY(PayType.WEEKEND); + + private final PayType payType; + PayrollDay(PayType payType) { this.payType = payType; } + + double pay(double hoursWorked, double payRate) { + return payType.pay(hoursWorked, payRate); + } + // The strategy enum type + private enum PayType { + WEEKDAY { + double overtimePay(double hours, double payRate) { + return hours <= HOURS_PER_SHIFT ? 0 : + (hours - HOURS_PER_SHIFT) * payRate / 2; + } + }, + WEEKEND { + double overtimePay(double hours, double payRate) { + return hours * payRate / 2; + } + }; + private static final int HOURS_PER_SHIFT = 8; + + abstract double overtimePay(double hrs, double payRate); + + double pay(double hoursWorked, double payRate) { + double basePay = hoursWorked * payRate; + return basePay + overtimePay(hoursWorked, payRate); + } + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/Planet.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/Planet.java new file mode 100644 index 00000000..b782a590 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/Planet.java @@ -0,0 +1,34 @@ +package com.xdc.basic.book.effectivejava.Chapter6.Item30; + +// Enum type with data and behavior - Pages 149-150 +public enum Planet { + MERCURY(3.302e+23, 2.439e6), + VENUS (4.869e+24, 6.052e6), + EARTH (5.975e+24, 6.378e6), + MARS (6.419e+23, 3.393e6), + JUPITER(1.899e+27, 7.149e7), + SATURN (5.685e+26, 6.027e7), + URANUS (8.683e+25, 2.556e7), + NEPTUNE(1.024e+26, 2.477e7); + private final double mass; // In kilograms + private final double radius; // In meters + private final double surfaceGravity; // In m / s^2 + + // Universal gravitational constant in m^3 / kg s^2 + private static final double G = 6.67300E-11; + + // Constructor + Planet(double mass, double radius) { + this.mass = mass; + this.radius = radius; + surfaceGravity = G * mass / (radius * radius); + } + + public double mass() { return mass; } + public double radius() { return radius; } + public double surfaceGravity() { return surfaceGravity; } + + public double surfaceWeight(double mass) { + return mass * surfaceGravity; // F = ma + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/WeightTable.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/WeightTable.java new file mode 100644 index 00000000..c18fe366 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item30/WeightTable.java @@ -0,0 +1,13 @@ +package com.xdc.basic.book.effectivejava.Chapter6.Item30; + +// Takes earth-weight and prints table of weights on all planets - Page 150 + +public class WeightTable { + public static void main(String[] args) { + double earthWeight = Double.parseDouble(args[0]); + double mass = earthWeight / Planet.EARTH.surfaceGravity(); + for (Planet p : Planet.values()) + System.out.printf("Weight on %s is %f%n", + p, p.surfaceWeight(mass)); + } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item31/Ensemble.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item31/Ensemble.java new file mode 100644 index 00000000..e710df22 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item31/Ensemble.java @@ -0,0 +1,12 @@ +package com.xdc.basic.book.effectivejava.Chapter6.Item31; + +// Enum with integer data stored in an instance field +public enum Ensemble { + SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5), + SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8), + NONET(9), DECTET(10), TRIPLE_QUARTET(12); + + private final int numberOfMusicians; + Ensemble(int size) { this.numberOfMusicians = size; } + public int numberOfMusicians() { return numberOfMusicians; } +} diff --git a/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item32/Text.java b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item32/Text.java new file mode 100644 index 00000000..90ebdd97 --- /dev/null +++ b/basicKnowledge/src/com/xdc/basic/book/effectivejava/Chapter6/Item32/Text.java @@ -0,0 +1,20 @@ +package com.xdc.basic.book.effectivejava.Chapter6.Item32; + +// EnumSet - a modern replacement for bit fields - Page 160 + +import java.util.*; + +public class Text { + public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH } + + // Any Set could be passed in, but EnumSet is clearly best + public void applyStyles(Set + + + + + ">Contact List + + + + + + + + +
+Search:  +
+
+ +
+ +<% + if(request.getUserPrincipal() != null) { +%> + + + + + + + +
+ Add Contact +
+ +<% + } +%> + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/defError.jsp b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/defError.jsp new file mode 100644 index 00000000..ef1490eb --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/defError.jsp @@ -0,0 +1 @@ +

DEFAULT ERROR

\ No newline at end of file diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/edit.jsp b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/edit.jsp new file mode 100644 index 00000000..8a2e7441 --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/edit.jsp @@ -0,0 +1,20 @@ +<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %> + +

Rolodex settings

+ +
+Contacts per page: + +
+
diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/editContact.jsp b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/editContact.jsp new file mode 100644 index 00000000..aba23239 --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/editContact.jsp @@ -0,0 +1,53 @@ +<%@ taglib prefix="portlet" + uri="http://java.sun.com/portlet" %> +<%@ taglib prefix="spring" + uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" + uri="http://www.springframework.org/tags/form" %> +

Contact Edit

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
First name: + +
Last name: + +
Primary phone #: + +
Alternate phone #: + +
+   + +
+
diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/help.jsp b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/help.jsp new file mode 100644 index 00000000..635a1bbd --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/help.jsp @@ -0,0 +1,7 @@ +

Rolodex Help

+ +

Copyright © 2006 Craig Walls

+ +

This is the example porlet application used in my "Thinking inside +the box" presentation. It demonstrates the use of Spring's Portlet MVC +framework.

diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/notAuthorized.jsp b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/notAuthorized.jsp new file mode 100644 index 00000000..11e6da84 --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/notAuthorized.jsp @@ -0,0 +1 @@ +

NOT AUTHORIZED

\ No newline at end of file diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/notAvailable.jsp b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/notAvailable.jsp new file mode 100644 index 00000000..cb7c066b --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/jsp/notAvailable.jsp @@ -0,0 +1 @@ +

NOT AVAILABLE

diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/portlet.xml b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/portlet.xml new file mode 100644 index 00000000..ded58fb0 --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/portlet.xml @@ -0,0 +1,49 @@ + + + + Hello + + com.springinaction.hello.HelloPortlet + + + text/html + view + + + Hello World + Hello World + Hello,World + + + + + Rolodex + + org.springframework.web.portlet.DispatcherPortlet + + + text/html + view + edit + help + + + My Contacts + My Contacts + Contacts,Rolodex + + + + pageSize + 5 + + + + + diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/web.xml b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..71598752 --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,78 @@ + + + + + Rolodex + + + log4jConfigLocation + /WEB-INF/classes/log4j.properties + + + + contextConfigLocation + + /WEB-INF/Rolodex-service.xml + /WEB-INF/Rolodex-data.xml + + + + + org.springframework.web.context.ContextLoaderListener + + + + + ViewRendererServlet + + org.springframework.web.servlet.ViewRendererServlet + 1 + + + + Rolodex + org.apache.pluto.core.PortletServlet + + portlet-name + Rolodex + + 1 + + + + ViewRendererServlet + /WEB-INF/servlet/view + + + + Rolodex + /PlutoInvoker/Rolodex + + + + diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/images/edit.gif b/springInAction/Portlet/Rolodex/src/main/webapp/images/edit.gif new file mode 100644 index 00000000..0e79cff0 Binary files /dev/null and b/springInAction/Portlet/Rolodex/src/main/webapp/images/edit.gif differ diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/images/trash.gif b/springInAction/Portlet/Rolodex/src/main/webapp/images/trash.gif new file mode 100644 index 00000000..802f0900 Binary files /dev/null and b/springInAction/Portlet/Rolodex/src/main/webapp/images/trash.gif differ diff --git a/springInAction/Portlet/Rolodex/src/main/webapp/images/view.gif b/springInAction/Portlet/Rolodex/src/main/webapp/images/view.gif new file mode 100644 index 00000000..a6a08153 Binary files /dev/null and b/springInAction/Portlet/Rolodex/src/main/webapp/images/view.gif differ diff --git a/springInAction/Portlet/Rolodex/src/test/java/com/springinaction/rolodex/controller/ContactsControllerTest.java b/springInAction/Portlet/Rolodex/src/test/java/com/springinaction/rolodex/controller/ContactsControllerTest.java new file mode 100644 index 00000000..0de43359 --- /dev/null +++ b/springInAction/Portlet/Rolodex/src/test/java/com/springinaction/rolodex/controller/ContactsControllerTest.java @@ -0,0 +1,66 @@ +package com.springinaction.rolodex.controller; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.mock.web.portlet.MockRenderRequest; +import org.springframework.mock.web.portlet.MockRenderResponse; +import org.springframework.web.portlet.ModelAndView; + +import com.springinaction.rolodex.controller.ContactsController; +import com.springinaction.rolodex.domain.Contact; +import com.springinaction.rolodex.service.RolodexService; + + +public class ContactsControllerTest extends TestCase { + public ContactsControllerTest() { + super(); + } + + public ContactsControllerTest(String name) { + super(name); + } + + private ContactsController controller; + + private MockControl control; + private RolodexService rolodexService; + + protected void setUp() throws Exception { + + control = MockControl.createControl(RolodexService.class); + rolodexService = (RolodexService) control.getMock(); + rolodexService.getContacts(null); + List contactList = new ArrayList(); + Contact contact = new Contact(); + contactList.add(contact); + control.expectAndReturn(null, contactList); + control.replay(); + + controller = new ContactsController(); + controller.setRolodexService(rolodexService); + } + + public void testNoAuthRequest() { + MockRenderRequest request = new MockRenderRequest(); + MockRenderResponse response = new MockRenderResponse(); + + try { + ModelAndView mv = controller.handleRenderRequestInternal(request, response); + + assertEquals("contactList", mv.getViewName()); + + Map model = mv.getModel(); + assertNotNull(model); + + List contacts = (List) model.get("contacts"); + assertEquals(1, contacts.size()); + } catch (Exception e) { + fail("Exception thrown from ContactsController.handleRenderRequestInternal() : " + e); + } + } +} diff --git a/springInAction/RoadRantz/.classpath b/springInAction/RoadRantz/.classpath new file mode 100644 index 00000000..7adb0ee0 --- /dev/null +++ b/springInAction/RoadRantz/.classpath @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/.project b/springInAction/RoadRantz/.project new file mode 100644 index 00000000..ffdf58cf --- /dev/null +++ b/springInAction/RoadRantz/.project @@ -0,0 +1,35 @@ + + + RoadRantz + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + org.springframework.ide.eclipse.core.springnature + + diff --git a/springInAction/RoadRantz/.settings/org.eclipse.jdt.core.prefs b/springInAction/RoadRantz/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..abec6ca3 --- /dev/null +++ b/springInAction/RoadRantz/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/springInAction/RoadRantz/.settings/org.eclipse.m2e.core.prefs b/springInAction/RoadRantz/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 00000000..f897a7f1 --- /dev/null +++ b/springInAction/RoadRantz/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/springInAction/RoadRantz/.springBeans b/springInAction/RoadRantz/.springBeans new file mode 100644 index 00000000..0e37a313 --- /dev/null +++ b/springInAction/RoadRantz/.springBeans @@ -0,0 +1,32 @@ + + + + xml + + + src/main/resources/roadrantz-data-jdbc.xml + src/main/resources/roadrantz-cache.xml + src/main/resources/roadrantz-jms.xml + src/main/resources/roadrantz-mbeans.xml + src/main/resources/roadrantz-data-hibernate.xml + src/main/resources/roadrantz-services.xml + src/main/resources/roadrantz-security.xml + src/main/resources/roadrantz-servlet.xml + src/main/resources/roadrantz-views.xml + src/main/resources/roadrantz-data-ibatis.xml + src/main/resources/roadrantz-data.xml + src/main/resources/roadrantz-data-jpa.xml + + + + Servlet, service, and data + false + false + + src/main/resources/roadrantz-data.xml + src/main/resources/roadrantz-services.xml + src/main/resources/roadrantz-servlet.xml + + + + diff --git a/springInAction/RoadRantz/README b/springInAction/RoadRantz/README new file mode 100644 index 00000000..26038380 --- /dev/null +++ b/springInAction/RoadRantz/README @@ -0,0 +1,171 @@ +WHAT THE HECK IS ROADRANTZ? +=========================== +If you've been reading the book, you're probably wondering what RoadRantz is. +Well, I had intended to write a short "About RoadRantz" segment to fit nicely +in between chapters 4 and 5. Unfortunately, due to size and time constraints +that never happened. + +In some attempt to make up for it, I'm going to attempt to settle the question +of what RoadRantz is with this file. + +It started that day I almost died +--------------------------------- +Like many people in today's workforce, I have spent a large portion of my +life driving to and from work. The reality is that most of my jobs have been +nowhere near my home and I've been required to commute up to an hour and a +half each way (worst case). + +Whether you realize it or not, we share the road with a bunch of complete +idiots. I generally don't have any bias against idiots--they can't help it +that their brain capacity is low. But if you're an idiot, I really wish that +you'd recognize your limitations and not try to do more than one thing while +you're driving. And, in fact, I'd really prefer it if that one thing was to +focus on driving your car. + +But apparently idiots (because they're idiots) don't take their limits +into consideration and attempt to do all kinds of things while behind the +wheel. I've seen things ranging from the basic cell-phone talker to the +woman who emptied an entire can of hair spray while engaged in a hopeless +attempt to beautify herself. In all cases, the motorists were putting +themselves and others on the road in danger. + +In short, if you're busy doing anything other than driving, you're not +going to be able to drive that well. Not to mention, that much hair spray +creates a blinding haze that limits your visibility. + +Anyway, on one particular day, one of those idiots almost broad-sided me, +swerving at the last second. I was certain that I had almost died--they were +certain that they had just lost their cell signal. + +At that time, I decided there needed to be a way for me and other drivers to +vent about those idiots on the road that fail to recognize that they're +endangering others lives with their reckless commute-time habits. + +And so on that day, the idea of RoadRantz was born. + +Because I thought that the internet could use another community site +-------------------------------------------------------------------- +RoadRantz is a community site in the same vein as MySpace or Facebook. The +big difference is that instead of building a community of friends (Why do +you need that? If they're you're friends you should just call them or go +get pizza or something.) you're building a community of people you've +encountered in traffic. + +The idea started simple enough: Take note of an idiot's license plate number +and then go online to tell anyone and everyone how this particular motorist +really needs to pull his head out of whatever orifice it has been placed in. +If the driver in question is really that bad, they'll probably rack up a +lengthy list of rants on RoadRantz. + +Then the idea grew a little. It's certainly fun to let off some steam by +ranting about a fellow motorist. But RoadRantz could also be used for more +friendly encounters. Let's say you just pulled up next to a rather toothsome +driver at a red light. It could also be fun to leave a message for him/her +to let them know that they caught your eye. + +The opportunities to hook-up on RoadRantz are endless. Whether you're angry +with a fellow road-hog or simply want to arrange another traffic-light +encounter, RoadRantz can be a lot of fun. + +What's in this project +---------------------- +I decided that RoadRantz would be a fun example for Spring in Action, 2E. +That's because it covers so much of the ground that would also be covered +in the book. No example is perfect and I couldn't easily use RoadRantz for +all sections in the book. But I think it does a good job of demonstrating +most of the topics in SiA2. + +What you'll find in this project is a large portion of the RoadRantz +application. But not all of the application is here. That's because I've +had to focus my energy on getting the book done. Therefore, I've built just +enough of the RoadRantz application to demonstrate the concepts in the book +and only a little more than that. + +The problem with trying to demonstrate a wealth of Spring techniques in +a simple application is that you end up with a hammer in search of nails. +That is, I needed to demonstrate something, so in some cases I shoe-horned +an example into the RoadRantz application, even if I probably wouldn't +actually use that example in the real RoadRantz application. + +Now that the book is done, I intend to continue working on the RoadRantz +application as a toy project. That means that I'll continue to add +functionality and will continue to evolve the design. I'll also clean up +the application, removing some of the examples that don't quite fit. +And eventually I'll deploy it for public consumption. + +If you want to follow along with the changes I make, you can check out the +code from svn://svn.geekisp.com/SiA. The new changes will be made on the +trunk, but you can always retrieve the original book version of the code +from the BOOK-1.0 tag. + +The basic design of RaodRantz +----------------------------- +Lately, I've become captivated by the idea of Domain Driven Design, as +presented at length in Erik Evans' "Domain Driven Design: Tackling Complexity +in the Heart of Software" and other related books and writings. + +Unfortunately, that interest in DDD came too late to impact the design of +the RoadRantz application. + +So, RoadRantz follows a fairly basic layered approach consisting of a +presentation layer, a business layer, and a persistence layer. Transcending +all of those layers is a handful of domain objects, although not exactly +the same rich domain-layer you might find discussed in Eric Evans' book. + +In the presentation layer you'll find things like Spring MVC and, to a +lesser extent, Struts, WebWork, Tapestry, and JSF. + +The business layer consists of the RantService interface and its +implementation. The primary role Spring plays in this layer is to provide +declarative transactions for the service methods. But there are also other +service-related items such as e-mail support that show up here. + +The persistence layer is where you'll find Spring simplifying JDBC, JPA, +Hibernate, and iBATIS to access the database. You'll also find the Spring +Modules' cache implementation playing a part in improving the performance +for frequently performed queries. + +I've come to believe that no matter how much work I put into a design, I'll +always have regrets and end up wishing I had another chance to do it better. +But the 2nd edition is printed and there's little I can do to change that +now. If I do a 3rd edition of Spring in Action, then I suppose I can correct +the design of RoadRantz to fit the DDD approach. Until then, you can follow +along as I rework RoadRantz by checking out the latest code from the trunk +of the Subversion repository (see above). + +Building RoadRantz +------------------ +I'm using Maven 2 to build the RoadRantz application. Everything you need +should already be in the pom.xml file, so you'll only need to type this +to build a WAR file: + + % mvn package + +When it's done, there'll be a RoadRantz.war file in the target directory. +I don't anticipate any problems deploying this in any JEE web container, +but I have only tried it in Tomcat (5.5.x and 6.0.x). If you run into any +trouble getting it to run in any other container, let me know. Even better, +since I may not have access to your container, any patch you can submit to +fix it to work in your container would be welcome. + +Another thing: You'll need a database. In the db directory, you'll find +a create-tables.sql file which includes SQL for creating the tables in +Hypersonic. You'll need to tweak those in order to use a different database. + +The RantService tests (RantServiceTest*.java) are excluded from normal +test execution in the Maven pom.xml file. That's because they're not +really unit-tests and because they require a database to be setup and +running in order to test the RantService implementation. If you want to +run those tests, you'll need to specify the "itest" Maven profile, as +follows: + + % mvc -P itest test + +At the moment, you'll need a running database to run those integration +tests against RantServiceImpl. I intend to eventually rework those tests to +use an in-memory Hypersonic database so they won't need a database otherwise. +But for now, be sure to have a DB going. + +One final detail: Once you've got the database setup, you'll want to tweak +the database connection properties. Those are setup in the db.properties file. + diff --git a/springInAction/RoadRantz/build.xml b/springInAction/RoadRantz/build.xml new file mode 100644 index 00000000..92918789 --- /dev/null +++ b/springInAction/RoadRantz/build.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springInAction/RoadRantz/db/create-tables.sql b/springInAction/RoadRantz/db/create-tables.sql new file mode 100644 index 00000000..4cf55827 --- /dev/null +++ b/springInAction/RoadRantz/db/create-tables.sql @@ -0,0 +1,35 @@ +drop table Rant if exists +drop table Vehicle if exists +drop table Motorist_Privileges if exists +drop table Motorist if exists + +create table Rant ( + id integer identity primary key, + vehicle_id integer not null, + rantText varchar(2000) not null, + postedDate date not null +); + +create table Motorist ( + id integer identity primary key, + email varchar(255) not null, + password varchar(50) not null, + firstName varchar(30) not null, + lastName varchar(30) not null +); + +create table Vehicle ( + id integer identity primary key, + motorist_id integer, + state varchar(2) not null, + plateNumber varchar(10) not null +); + +create table Motorist_Privileges ( + motorist_id integer not null, + privilege varchar(30) not null +); + +alter table Vehicle add constraint vehicle_motorist foreign key (motorist_id) references Motorist; +alter table Rant add constraint rant_vehicle foreign key (vehicle_id) references Vehicle; +alter table Motorist_Privileges add constraint priv_motorist foreign key (motorist_id) references Motorist; diff --git a/springInAction/RoadRantz/lib/ejb3-persistence.jar b/springInAction/RoadRantz/lib/ejb3-persistence.jar new file mode 100644 index 00000000..1ec7f409 Binary files /dev/null and b/springInAction/RoadRantz/lib/ejb3-persistence.jar differ diff --git a/springInAction/RoadRantz/lib/hsqldb.jar b/springInAction/RoadRantz/lib/hsqldb.jar new file mode 100644 index 00000000..35436d6e Binary files /dev/null and b/springInAction/RoadRantz/lib/hsqldb.jar differ diff --git a/springInAction/RoadRantz/lib/incubator-activemq-4.0.1.jar b/springInAction/RoadRantz/lib/incubator-activemq-4.0.1.jar new file mode 100644 index 00000000..10c79da5 Binary files /dev/null and b/springInAction/RoadRantz/lib/incubator-activemq-4.0.1.jar differ diff --git a/springInAction/RoadRantz/license.txt b/springInAction/RoadRantz/license.txt new file mode 100644 index 00000000..83f0ef5f --- /dev/null +++ b/springInAction/RoadRantz/license.txt @@ -0,0 +1,5 @@ + +This work is licensed under the Creative Commons Attribution 3.0 License. To view +a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send +a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, +94105, USA. diff --git a/springInAction/RoadRantz/pom.xml b/springInAction/RoadRantz/pom.xml new file mode 100644 index 00000000..1cb9368b --- /dev/null +++ b/springInAction/RoadRantz/pom.xml @@ -0,0 +1,454 @@ + + + + com.springinaction + sia + 2.0 + + 4.0.0 + com.roadrantz + RoadRantz + war + Spring in Action 2E, RoadRantz Example + 1.0 + http://www.habuma.com + + + + java.net + https://maven-repository.dev.java.net/nonav/repository + legacy + + + + + RoadRantz + + + + org.codehaus.cargo + cargo-maven2-plugin + + + tomcat5x + remote + + + runtime + + localhost + 8080 + admin2 + password + + + + + + + + maven-surefire-plugin + + + **/*RantServiceTest*.java + + + + + + maven-compiler-plugin + + 1.5 + 1.5 + + + + + + + + + + + tomcat5x + + true + + + tomcat5x + + + + + + itest + + + itest + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + surefire-it + integration-test + + test + + + + none + + + **/*RantServiceTest*.java + + + + + + + + + + + + 0.8a + + + + + org.springframework + spring-mock + ${spring.version} + test + + + org.springmodules + spring-modules-validation + ${spring.modules.version} + compile + + + org.springmodules + spring-modules-cache + ${spring.modules.version} + compile + + + + + gigaspaces + gigaspaces-ce + + + jini + webster + + + jboss + jboss-jmx + + + xpp3 + xpp3_min + + + jini + start + + + jboss + jboss-minimal + + + jini + reggie + + + jboss + jboss-cache + + + jcs + jcs + + + jboss + jboss-system + + + jini + jsk-platform + + + jboss + jboss-common + + + jini + mahalo + + + jini + jsk-lib + + + jini + boot + + + + + ehcache + ehcache + + + + + commons-attributes + commons-attributes-compiler + + + + + org.apache.geronimo.specs + geronimo-ejb_2.1_spec + 1.1 + compile + + + commons-validator + commons-validator + 1.1.4 + compile + + + commons-lang + commons-lang + 2.1 + compile + + + commons-digester + commons-digester + 1.5 + compile + + + hsqldb + hsqldb + 1.8.0.7 + compile + + + org.hibernate + hibernate-annotations + 3.2.1.ga + compile + + + org.hibernate + hibernate + 3.2.1.ga + compile + + + com.ibatis + ibatis2-sqlmap + 2.1.7.597 + compile + + + com.ibatis + ibatis2-common + 2.1.7.597 + compile + + + javax.servlet + jstl + 1.1.2 + + + taglibs + standard + 1.1.2 + + + + rome + rome + 0.8 + compile + + + oro + oro + 2.0.8 + compile + + + javax.servlet + servlet-api + 2.4 + provided + + + velocity + velocity + 1.4 + compile + + + freemarker + freemarker + 2.3.4 + compile + + + struts + struts + 1.2.8 + compile + + + poi + poi + 2.5.1-final-20040804 + compile + + + com.lowagie + itext + 1.3.1 + compile + + + org.easymock + easymock + 2.0 + test + + + aspectj + aspectjrt + 1.5.0 + + + aspectj + aspectjweaver + 1.5.0 + + + org.acegisecurity + acegi-security + 1.0.3 + + + org.springframework + spring-aop + + + org.springframework + spring-context + + + org.springframework + spring-dao + + + org.springframework + spring-remoting + + + org.springframework + spring-support + + + org.springframework + spring-jdbc + + + xerces + xercesImpl + + + + + opensymphony + quartz + 1.5.2 + compile + + + commons-dbcp + commons-dbcp + 1.2.1 + compile + + + xerces + xercesImpl + + + + + javax.mail + mail + 1.4 + compile + + + opensymphony + webwork + 2.2.3 + compile + + + tapestry + tapestry + 4.0.2 + compile + + + tapestry + tapestry-annotations + 4.0.2 + compile + + + org.apache.activemq + activemq-core + 4.1.1 + compile + + + org.logicblaze.lingo + lingo + 1.2.1 + + + toplink.essentials + toplink-essentials + 2.0-36 + compile + + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/DaoMain.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/DaoMain.java new file mode 100644 index 00000000..945b3f92 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/DaoMain.java @@ -0,0 +1,39 @@ +package com.roadrantz.dao; + +import java.util.Date; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.FileSystemXmlApplicationContext; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.RantService; + +public class DaoMain { + public static void main(String[] args) { + ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[] { + "src/main/webapp/WEB-INF/services.xml", "src/main/webapp/WEB-INF/dataaccess.xml" + }); + + RantService dao = (RantService) ctx.getBean("rantService"); + + Rant rant = new Rant(); + rant.setPostedDate(new Date()); + rant.setRantText("TEST RANT 3"); + Vehicle vehicle = new Vehicle(); + vehicle.setPlateNumber("J55DNY"); + vehicle.setState("TX"); + rant.setVehicle(vehicle); + dao.addRant(rant); + + rant = new Rant(); + rant.setPostedDate(new Date()); + rant.setRantText("TEST RANT 4"); + vehicle = new Vehicle(); + vehicle.setPlateNumber("G44MNX"); + vehicle.setState("TX"); + rant.setVehicle(vehicle); + dao.addRant(rant); + + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/RantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/RantDao.java new file mode 100644 index 00000000..1456bbb5 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/RantDao.java @@ -0,0 +1,30 @@ +package com.roadrantz.dao; + +import java.util.Date; +import java.util.List; + +import org.springmodules.cache.annotations.CacheFlush; +import org.springmodules.cache.annotations.Cacheable; + +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public interface RantDao { + @CacheFlush(modelId="rantzCacheModel") + public void saveRant(Rant rant); + + @Cacheable(modelId="rantzCacheModel") + public List getAllRants(); + + @Cacheable(modelId="rantzCacheModel") + public List getRantsForDay(Date day); + + public Vehicle findVehicleByPlate(String state, String plateNumber); + public void saveVehicle(Vehicle vehicle); + + public Motorist getMotoristByEmail(String email); + public void saveMotorist(Motorist driver); + + public int getMotoristCount(); +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/UserDaoImpl.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/UserDaoImpl.java new file mode 100644 index 00000000..64d650dc --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/UserDaoImpl.java @@ -0,0 +1,48 @@ +package com.roadrantz.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.userdetails.User; +import org.acegisecurity.userdetails.UserDetails; +import org.acegisecurity.userdetails.UserDetailsService; +import org.acegisecurity.userdetails.UsernameNotFoundException; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.support.JdbcDaoSupport; + +public class UserDaoImpl extends JdbcDaoSupport + implements UserDetailsService { + + public UserDaoImpl() {} + + public UserDetails loadUserByUsername(String userName) + throws UsernameNotFoundException, DataAccessException { + + List users = getJdbcTemplate().query( + "select email, password from driver where email=?", + new Object[] {userName}, + new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) + throws SQLException { + String userName = rs.getString(1); + String password = rs.getString(2); + + return new User(userName, password, true, true, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")}); + }; + } + ); + + if(users.size() > 0) { + return (UserDetails) users.get(0); + } + + throw new UsernameNotFoundException(userName); + } + + +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateContextualSessionsRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateContextualSessionsRantDao.java new file mode 100644 index 00000000..b2bd0a0b --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateContextualSessionsRantDao.java @@ -0,0 +1,100 @@ +package com.roadrantz.dao.hibernate; + +import java.util.Date; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.SessionFactory; +import org.hibernate.type.Type; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * Hibernate contextual session based DAO. + * + * Although the name is different, this is the Hibernate-based DAO that is + * described in section 5.4.4. + * + * Note that since chapter 5 was written, I have learned that this is the + * preferred approach to building Hibernate DAOs. + * + * @author wallsc + */ +public class HibernateContextualSessionsRantDao implements RantDao { + private static final String MOTORIST = Motorist.class.getName(); + private static final String RANT = Rant.class.getName(); + private static final String VEHICLE = Vehicle.class.getName(); + + public HibernateContextualSessionsRantDao() {} + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + List results = sessionFactory + .getCurrentSession() + .find( + "from " + + VEHICLE + + " where state = ? and plateNumber = ?", + new Object[] { state, plateNumber }, + new Type[] { Hibernate.STRING, + Hibernate.STRING }); + + if (results.size() > 0) { + return (Vehicle) results.get(0); + } + + return null; // TODO - Should I throw an exception instead? + } + + public List getAllRants() { + return sessionFactory.getCurrentSession().find("from " + RANT); + } + + public Motorist getMotoristByEmail(String email) { + List results = sessionFactory.getCurrentSession() + .find("from " + MOTORIST + " where email = ?", + new Object[] { email }, + new Type[] { Hibernate.STRING }); + + if (results.size() > 0) { + return (Motorist) results.get(0); + } + return null; // TODO - Should I throw an exception instead? + } + + public void saveRant(Rant rant) { + sessionFactory.getCurrentSession().saveOrUpdate(rant); + } + + public void saveVehicle(Vehicle vehicle) { + sessionFactory.getCurrentSession().saveOrUpdate(vehicle); + } + + public List getRantsForDay(Date day) { + return sessionFactory.getCurrentSession().find( + "from " + RANT + " where postedDate = ?", day, + Hibernate.DATE); + } + + public void saveMotorist(Motorist driver) { + sessionFactory.getCurrentSession().saveOrUpdate(driver); + } + + public Motorist getDriverById(Integer id) { + return (Motorist) sessionFactory.getCurrentSession().load(Motorist.class, + id); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } + + private SessionFactory sessionFactory; + + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateRantDao.java new file mode 100644 index 00000000..6e99ae4b --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateRantDao.java @@ -0,0 +1,85 @@ +package com.roadrantz.dao.hibernate; + +import java.util.Date; +import java.util.List; + +import org.springframework.orm.hibernate3.support.HibernateDaoSupport; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * Hibernate-based implementation of the RantDao interface. + * + * Initially defined in Listing 5.8. But the initial implementation of + * HibernateRantDao evolves in section 5.4.3 to extend HibernateDaoSupport. + * + * If you're looking for the version from section 5.4.2, have a look at + * HibernateRantDaoUsingTemplate.java. + * + * @author wallsc + */ +public class HibernateRantDao extends HibernateDaoSupport implements RantDao { + private static final String MOTORIST = Motorist.class.getName(); + private static final String RANT = Rant.class.getName(); + private static final String VEHICLE = Vehicle.class.getName(); + + public HibernateRantDao() {} + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + List results = getHibernateTemplate() + .find( + "from " + + VEHICLE + + " where state = ? and plateNumber = ?", + new Object[] { state, plateNumber }); + + if (results.size() > 0) { + return (Vehicle) results.get(0); + } + + return null; // TODO - Should I throw an exception instead? + } + + public List getAllRants() { + return getHibernateTemplate().find("from " + RANT); + } + + public Motorist getMotoristByEmail(String email) { + List results = getHibernateTemplate().find( + "from " + MOTORIST + " where email = ?", email); + + if (results.size() > 0) { + return (Motorist) results.get(0); + } + return null; // TODO - Should I throw an exception instead? + } + + public void saveRant(Rant rant) { + getHibernateTemplate().saveOrUpdate(rant); + } + + public void saveVehicle(Vehicle vehicle) { + getHibernateTemplate().saveOrUpdate(vehicle); + } + + public List getRantsForDay(Date day) { + return getHibernateTemplate().find( + "from " + RANT + " where postedDate = ?", day); + } + + public void saveMotorist(Motorist driver) { + getHibernateTemplate().saveOrUpdate(driver); + } + + public Motorist getDriverById(Integer id) { + return (Motorist) getHibernateTemplate().load(Motorist.class, id); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateRantDaoUsingTemplate.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateRantDaoUsingTemplate.java new file mode 100644 index 00000000..7873c908 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/hibernate/HibernateRantDaoUsingTemplate.java @@ -0,0 +1,90 @@ +package com.roadrantz.dao.hibernate; + +import java.util.Date; +import java.util.List; + +import org.springframework.orm.hibernate3.HibernateTemplate; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * This class is an alternate implementation of HibernateRantDao, that more + * closely resembles what was started in Listing 5.8. + * + * Listing 5.8 starts talking about HibernateRantDao by injecting a + * HibernateTemplate into an otherwise POJO-ish DAO. That example eventually + * evolves into one that extends HibernateDaoSupport. + * + * Although the name is different, this class serves as the example for how to + * build Hibernate-based DAOs as described in section 5.4.2. + * + * @author wallsc + */ +public class HibernateRantDaoUsingTemplate implements RantDao { + private static final String MOTORIST = Motorist.class.getName(); + private static final String RANT = Rant.class.getName(); + private static final String VEHICLE = Vehicle.class.getName(); + + public HibernateRantDaoUsingTemplate() {} + + public void saveVehicle(Vehicle vehicle) { + hibernateTemplate.saveOrUpdate(vehicle); + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + List results = hibernateTemplate.find("from " + VEHICLE + + " where state = ? and plateNumber = ?", new Object[] { + state, plateNumber }); + + if (results.size() > 0) { + return (Vehicle) results.get(0); + } + + return null; // TODO - Should I throw an exception instead? + } + + public void saveRant(Rant rant) { + hibernateTemplate.saveOrUpdate(rant); + } + + public List getAllRants() { + return hibernateTemplate.loadAll(Rant.class); + } + + public List getRantsForDay(Date day) { + return hibernateTemplate.loadAll(Rant.class); + } + + public void saveMotorist(Motorist driver) { + hibernateTemplate.saveOrUpdate(driver); + } + + public Motorist getDriverById(Integer id) { + return (Motorist) hibernateTemplate.load(Motorist.class, id); + } + + public Motorist getMotoristByEmail(String email) { + List results = hibernateTemplate.find("from " + MOTORIST + + " where email = ?", email); + + if (results.size() > 0) { + return (Motorist) results.get(0); + } + return null; // TODO - Should I throw an exception instead? + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } + + // injected + private HibernateTemplate hibernateTemplate; + + public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { + this.hibernateTemplate = hibernateTemplate; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/ibatis/IBatisRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/ibatis/IBatisRantDao.java new file mode 100644 index 00000000..dae0f8b3 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/ibatis/IBatisRantDao.java @@ -0,0 +1,58 @@ +package com.roadrantz.dao.ibatis; + +import java.util.Date; +import java.util.List; + +import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class IBatisRantDao extends SqlMapClientDaoSupport implements RantDao { + + public IBatisRantDao() {} + + public void saveRant(Rant rant) { + getSqlMapClientTemplate().insert("insertRant", rant); + } + + @SuppressWarnings("unchecked") + public List getAllRants() { + return getSqlMapClientTemplate().queryForList("getAllRants", null); + } + + @SuppressWarnings("unchecked") + public List getRantsForDay(Date day) { + return getSqlMapClientTemplate().queryForList("getRantsForDay", day); + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + Vehicle queryParam = new Vehicle(); + queryParam.setState(state); + queryParam.setPlateNumber(plateNumber); + + return (Vehicle) getSqlMapClientTemplate().queryForObject( + "findVehicleByPlate", queryParam); + } + + public void saveVehicle(Vehicle vehicle) { + getSqlMapClientTemplate().insert("insertVehicle", vehicle); + } + + public Motorist getMotoristByEmail(String email) { + return (Motorist) getSqlMapClientTemplate().queryForObject( + "findMotoristByEmail", email); + } + + public void saveMotorist(Motorist driver) { + Integer primaryKey = (Integer) getSqlMapClientTemplate().insert( + "insertMotorist", driver); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/ibatis/IBatisTemplateRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/ibatis/IBatisTemplateRantDao.java new file mode 100644 index 00000000..4ef5a9ac --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/ibatis/IBatisTemplateRantDao.java @@ -0,0 +1,64 @@ +package com.roadrantz.dao.ibatis; + +import java.util.Date; +import java.util.List; + +import org.springframework.orm.ibatis.SqlMapClientTemplate; +import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class IBatisTemplateRantDao implements RantDao { + + public IBatisTemplateRantDao() {} + + public void saveRant(Rant rant) { + sqlMapClientTemplate.insert("insertRant", rant); + } + + @SuppressWarnings("unchecked") + public List getAllRants() { + return sqlMapClientTemplate.queryForList("getAllRants", null); + } + + @SuppressWarnings("unchecked") + public List getRantsForDay(Date day) { + return sqlMapClientTemplate.queryForList("getRantsForDay", day); + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + Vehicle queryParam = new Vehicle(); + queryParam.setState(state); + queryParam.setPlateNumber(plateNumber); + + return (Vehicle) sqlMapClientTemplate.queryForObject( + "findVehicleByPlate", queryParam); + } + + public void saveVehicle(Vehicle vehicle) { + sqlMapClientTemplate.insert("insertVehicle", vehicle); + } + + public Motorist getMotoristByEmail(String email) { + return (Motorist) + sqlMapClientTemplate.queryForObject("findMotoristByEmail", email); + } + + public void saveMotorist(Motorist driver) { + Integer primaryKey = (Integer) sqlMapClientTemplate.insert("insertMotorist", driver); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } + + // injected + private SqlMapClientTemplate sqlMapClientTemplate; + public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) { + this.sqlMapClientTemplate = sqlMapClientTemplate; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/ConventionalJdbcRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/ConventionalJdbcRantDao.java new file mode 100644 index 00000000..cb0109ad --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/ConventionalJdbcRantDao.java @@ -0,0 +1,220 @@ +package com.roadrantz.dao.jdbc; + +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; +import java.util.List; + +import javax.sql.DataSource; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class ConventionalJdbcRantDao implements RantDao { + public ConventionalJdbcRantDao() {} + + private static final String RANT_INSERT = "insert into rant (id, rantText, vehicle_id, postedDate) " + + "values (null,?,?,?)"; + + private static final String MOTORIST_INSERT = "insert into motorist (id, email, password, firstName, lastName) " + + "values (null, ?,?,?,?)"; + + public void saveRant(Rant rant) { + try { + Connection conn = dataSource.getConnection(); + PreparedStatement stmt = conn.prepareStatement(""); + stmt.setString(1, rant.getRantText()); + stmt.setInt(2, rant.getVehicle().getId()); + stmt.setDate(3, new java.sql.Date(rant.getPostedDate().getTime())); + stmt.execute(); + } + catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public List getAllRants() { + // TODO Auto-generated method stub + return null; + } + + public List getRantsForDay(Date day) { + // TODO Auto-generated method stub + return null; + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + // TODO Auto-generated method stub + return null; + } + + public void saveVehicle(Vehicle vehicle) { + // TODO Auto-generated method stub + + } + + public Motorist getMotoristByEmail(String email) { + // TODO Auto-generated method stub + return null; + } + + /** + * Inserts a motorist to the database using conventional (e.g., non-Spring) + * JDBC. + * + * From Listing 5.1 + * + * @param motorist + * The Motorist object to insert + */ + public void saveMotorist(Motorist motorist) { + Connection conn = null; + PreparedStatement stmt = null; + try { + conn = dataSource.getConnection(); + stmt = conn.prepareStatement(MOTORIST_INSERT); + + stmt.setString(1, motorist.getEmail()); + stmt.setString(2, motorist.getPassword()); + stmt.setString(3, motorist.getFirstName()); + stmt.setString(4, motorist.getLastName()); + stmt.execute(); + } + catch (SQLException e) { + // deal with exception--somehow + } + finally { + try { + stmt.close(); + conn.close(); + } + catch (SQLException e) {} + } + } + + private static final String MOTORIST_UPDATE = "update motorist " + + "set email=?, password=?, firstName=?, lastName=? " + + "where id=?"; + + /** + * Updates a Motorist object in the database, using convention (e.g., + * non-Spring) JDBC + * + * From Listing 5.2 + * + * @param motorist + * The Motorist object to update + */ + public void updateMotorist(Motorist motorist) { + Connection conn = null; + PreparedStatement stmt = null; + try { + conn = dataSource.getConnection(); + stmt = conn.prepareStatement(MOTORIST_UPDATE); + stmt.setString(1, motorist.getEmail()); + stmt.setString(2, motorist.getPassword()); + stmt.setString(3, motorist.getFirstName()); + stmt.setString(4, motorist.getLastName()); + stmt.setInt(5, motorist.getId()); + stmt.execute(); + } + catch (SQLException e) { + // deal with exception--somehow + } + finally { + try { + if (stmt != null) { + stmt.close(); + } + if (conn != null) { + conn.close(); + } + } + catch (SQLException e) {} + } + } + + private static final String MOTORIST_QUERY = "select id, email, password, firstName, lastName " + + " from motorist where id=?"; + + /** + * Retrieves a Motorist from the database using conventional (e.g., + * non-Spring) JDBC. + * + * From Listing 5.3 + * + * @param id + * The ID of the Motorist to retrieve + * @return + */ + public Motorist getMotoristById(Integer id) { + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = dataSource.getConnection(); + stmt = conn.prepareStatement(MOTORIST_QUERY); + stmt.setInt(1, id); + rs = stmt.executeQuery(); + Motorist motorist = null; + if (rs.next()) { + motorist = new Motorist(); + motorist.setId(rs.getInt("id")); + motorist.setEmail(rs.getString("email")); + motorist.setPassword(rs.getString("password")); + motorist.setFirstName(rs.getString("firstName")); + motorist.setLastName(rs.getString("lastName")); + } + return motorist; + } + catch (SQLException e) {} + finally { + try { + if (rs != null) { + rs.close(); + } + if (stmt != null) { + stmt.close(); + } + if (conn != null) { + conn.close(); + } + } + catch (SQLException e) {} + } + return null; + } + + private int queryForIdentity() { + Connection conn = null; + CallableStatement stmt; + ResultSet rs; + + try { + stmt = conn.prepareCall("call identity()"); + rs = stmt.executeQuery(); + if (rs.next()) { + return rs.getInt(1); + } + } + catch (SQLException e) {} + return 0; + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } + + private DataSource dataSource; + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/IdentityStoredProcedure.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/IdentityStoredProcedure.java new file mode 100644 index 00000000..f0246030 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/IdentityStoredProcedure.java @@ -0,0 +1,32 @@ +package com.roadrantz.dao.jdbc; + +import java.sql.Types; +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.springframework.jdbc.core.SqlOutParameter; +import org.springframework.jdbc.object.StoredProcedure; + +public class IdentityStoredProcedure extends StoredProcedure { + private static final String PROC_NAME = "identity"; + + public IdentityStoredProcedure(DataSource ds) { + setDataSource(ds); + setSql(PROC_NAME); + + // Parameters should be declared in same order here that + // they are declared in the stored procedure. + + declareParameter(new SqlOutParameter( "value", + Types.INTEGER ) ); + compile(); + } + + public Integer getIdentity() { + Map map = execute(new HashMap()); + + return (Integer) map.get("value"); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRant.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRant.java new file mode 100644 index 00000000..91822107 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRant.java @@ -0,0 +1,17 @@ +package com.roadrantz.dao.jdbc; + +import com.roadrantz.domain.Rant; + +public class JdbcRant extends Rant { + public JdbcRant() {} + + private Integer vehicleId; + + public Integer getVehicleId() { + return vehicleId; + } + + public void setVehicleId(Integer vehicleId) { + this.vehicleId = vehicleId; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRantDao.java new file mode 100644 index 00000000..360f2bf8 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRantDao.java @@ -0,0 +1,241 @@ +package com.roadrantz.dao.jdbc; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; +import java.util.List; + +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.support.JdbcDaoSupport; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class JdbcRantDao extends JdbcDaoSupport implements RantDao { + + private static final String RANT_INSERT = "insert into rant (id, rantText, vehicle_id, postedDate) " + + "values (null,?,?,?)"; + + private static final String RANT_SELECT = "select id, rantText, vehicle_id, postedDate from rant"; + + private static final String RANT_FOR_VEHICLE_SELECT = RANT_SELECT + + " where vehicle_id = ?"; + + private static final String RANT_FOR_DAY_SELECT = RANT_SELECT + + " where postedDate=?"; + + private static final String VEHICLE_SELECT = "select id, plateNumber, state from vehicle"; + + private static final String VEHICLE_BY_ID_SELECT = VEHICLE_SELECT + + " where id=?"; + + private static final String VEHICLE_BY_PLATE_SELECT = VEHICLE_SELECT + + " where state=? and plateNumber=?"; + + private static final String VEHICLE_INSERT = "insert into vehicle (id, plateNumber, state, motorist_id) " + + "values (null,?,?,?)"; + + private static final String MOTORIST_SELECT = "select id, email, password, firstName, lastName from motorist"; + + private static final String MOTORIST_BY_EMAIL_SELECT = MOTORIST_SELECT + + " where email=?"; + + private static final String MOTORIST_BY_ID_SELECT = MOTORIST_SELECT + + " where id=?"; + + private static final String MOTORIST_INSERT = "insert into motorist (id, email, password, firstName, lastName) " + + "values (null, ?,?,?,?)"; + + public JdbcRantDao() {} + + /** + * Saves a Motorist using Spring's JDBC template. + * + * From Listing 5.4 + * + * @param motorist + * The Motorist to save + */ + public void saveMotorist(Motorist motorist) { + getJdbcTemplate().update( + MOTORIST_INSERT, + new Object[] { motorist.getEmail(), + motorist.getPassword(), motorist.getFirstName(), + motorist.getLastName() }); + + motorist.setId(queryForIdentity()); + } + + private int queryForIdentity() { + return new Integer(getJdbcTemplate().queryForInt("call identity()")); + } + + public void saveRant(Rant rant) { + getJdbcTemplate() + .update( + RANT_INSERT, + new Object[] { rant.getRantText(), + rant.getVehicle().getId(), + rant.getPostedDate() }); + + rant.setId(queryForIdentity()); + } + + public void saveVehicle(Vehicle vehicle) { + Integer motoristId = vehicle.getMotorist() != null ? vehicle + .getMotorist().getId() : null; + getJdbcTemplate().update( + VEHICLE_INSERT, + new Object[] { vehicle.getPlateNumber(), + vehicle.getState(), motoristId }); + + vehicle.setId(queryForIdentity()); + } + + @SuppressWarnings("unchecked") + public List getAllRants() { + return getJdbcTemplate().query(RANT_SELECT, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + Rant rant = new Rant(); + rant.setId(rs.getInt(1)); + rant.setRantText(rs.getString(2)); + rant.setPostedDate(rs.getDate(4)); + Vehicle vehicle = findVehicleById(rs.getInt(3)); + rant.setVehicle(vehicle); + return rant; + } + }); + } + + @SuppressWarnings("unchecked") + public List getRantsForDay(Date day) { + return getJdbcTemplate().query(RANT_FOR_DAY_SELECT, new Object[] { day }, + new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) + throws SQLException { + Rant rant = new Rant(); + rant.setId(rs.getInt(1)); + rant.setRantText(rs.getString(2)); + rant.setPostedDate(rs.getDate(4)); + Vehicle vehicle = findVehicleById(rs.getInt(3)); + rant.setVehicle(vehicle); + return rant; + } + }); + } + + public Vehicle findVehicleById(Integer id) { + + List matches = getJdbcTemplate().query(VEHICLE_BY_ID_SELECT, + new Object[] { id }, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) + throws SQLException, + DataAccessException { + Vehicle vehicle = new Vehicle(); + vehicle.setId(rs.getInt(1)); + vehicle.setPlateNumber(rs.getString(2)); + vehicle.setState(rs.getString(3)); + return vehicle; + } + }); + + return matches.size() > 0 ? (Vehicle) matches.get(0) : null; + } + + /** + * Retrieves a Motorist by its ID + * + * From Listing 5.5 + * + * @param id + * The ID of the Motorist to retrieve + * @return The Motorist + */ + public Motorist getMotoristById(long id) { + List matches = getJdbcTemplate().query(MOTORIST_BY_ID_SELECT, + new Object[] { Long.valueOf(id) }, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) + throws SQLException, + DataAccessException { + Motorist motorist = new Motorist(); + + motorist.setId(rs.getInt(1)); + motorist.setEmail(rs.getString(2)); + motorist.setPassword(rs.getString(3)); + motorist.setFirstName(rs.getString(4)); + motorist.setLastName(rs.getString(5)); + return motorist; + } + }); + + return matches.size() > 0 ? (Motorist) matches.get(0) : null; + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + + List matches = getJdbcTemplate().query(VEHICLE_BY_PLATE_SELECT, + new Object[] { state, plateNumber }, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) + throws SQLException, + DataAccessException { + Vehicle vehicle = new Vehicle(); + vehicle.setId(rs.getInt(1)); + vehicle.setPlateNumber(rs.getString(2)); + vehicle.setState(rs.getString(3)); + return vehicle; + } + }); + + if (matches.size() == 0) { + return null; + } + + final Vehicle vehicle = (Vehicle) matches.get(0); + + List rants = getJdbcTemplate().query(RANT_FOR_VEHICLE_SELECT, + new Object[] { vehicle.getId() }, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) + throws SQLException { + Rant rant = new Rant(); + rant.setId(rs.getInt(1)); + rant.setRantText(rs.getString(2)); + rant.setPostedDate(rs.getDate(4)); + rant.setVehicle(vehicle); + return rant; + } + }); + + vehicle.setRants(rants); + + return vehicle; + } + + public Motorist getMotoristByEmail(String email) { + List matches = getJdbcTemplate().query(MOTORIST_BY_EMAIL_SELECT, + new Object[] { email }, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) + throws SQLException, + DataAccessException { + Motorist motorist = new Motorist(); + + motorist.setId(rs.getInt(1)); + motorist.setEmail(rs.getString(2)); + motorist.setPassword(rs.getString(3)); + motorist.setFirstName(rs.getString(4)); + motorist.setLastName(rs.getString(5)); + return motorist; + } + }); + + return matches.size() > 0 ? (Motorist) matches.get(0) : null; + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRantDaoWithSqlObjects.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRantDaoWithSqlObjects.java new file mode 100644 index 00000000..9685aa85 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcRantDaoWithSqlObjects.java @@ -0,0 +1,285 @@ +package com.roadrantz.dao.jdbc; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.sql.DataSource; + +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.SqlParameter; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.jdbc.object.MappingSqlQuery; +import org.springframework.jdbc.object.SqlUpdate; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class JdbcRantDaoWithSqlObjects extends JdbcDaoSupport + implements RantDao { + + private static final String RANT_INSERT = + "insert into rant (id, rantText, vehicle_id, postedDate) " + + "values (null,?,?,?)"; + + private static final String RANT_SELECT = + "select id, rantText, vehicle_id, postedDate from rant"; + + private static final String RANT_FOR_DAY_SELECT = + RANT_SELECT + " where postedDate=?"; + + private static final String VEHICLE_SELECT = + "select id, plateNumber, state, motorist_id from vehicle"; + + private static final String VEHICLE_BY_ID_SELECT = + VEHICLE_SELECT + " where id=?"; + + private static final String VEHICLE_BY_PLATE_SELECT = + VEHICLE_SELECT + " where state=:state and plateNumber=:plateNumber"; + + private static final String VEHICLE_INSERT = + "insert into vehicle (id, plateNumber, state, motorist_id) " + + "values (null,?,?,?)"; + + private static final String MOTORIST_SELECT = + "select id, email, password, firstName, lastName from motorist"; + + private static final String MOTORIST_BY_EMAIL_SELECT = + MOTORIST_SELECT + " where email=?"; + + private static final String MOTORIST_BY_ID_SELECT = + MOTORIST_SELECT + " where id=?"; + + private static final String MOTORIST_INSERT = + "insert into motorist (id, email, password, firstName, lastName) " + + "values (null, ?,?,?,?)"; + + private MotoristByIdQuery motoristByIdQuery; + private MotoristByEmailQuery motoristByEmailQuery; + private VehicleByIdQuery vehicleByIdQuery; + private VehicleByPlateQuery vehicleByPlateQuery; + private VehicleInsert vehicleInsert; + private RantForDayQuery rantForDayQuery; + private RantQuery rantQuery; + + protected void initDao() throws Exception { + motoristByIdQuery = new MotoristByIdQuery(getDataSource()); + motoristByEmailQuery = new MotoristByEmailQuery(getDataSource()); + vehicleByIdQuery = new VehicleByIdQuery(getDataSource()); + vehicleByPlateQuery = new VehicleByPlateQuery(getDataSource()); + rantForDayQuery = new RantForDayQuery(getDataSource()); + rantQuery = new RantQuery(getDataSource()); + vehicleInsert = new VehicleInsert(getDataSource()); + } + + public void saveMotorist(Motorist motorist) { + getJdbcTemplate().update(MOTORIST_INSERT, + new Object[] { motorist.getEmail(), motorist.getPassword(), + motorist.getFirstName(), motorist.getLastName() }); + + motorist.setId(queryForIdentity()); + } + + private int queryForIdentity() { + return new Integer(getJdbcTemplate().queryForInt("call identity()")); + } + + public void saveRant(Rant rant) { + getJdbcTemplate().update(RANT_INSERT, + new Object[] { + rant.getRantText(), + rant.getVehicle().getId(), + rant.getPostedDate() + }); + + rant.setId(queryForIdentity()); + } + + public void saveVehicle(Vehicle vehicle) { + vehicleInsert.insert(vehicle); + vehicle.setId(queryForIdentity()); + } + + @SuppressWarnings("unchecked") + public List getAllRants() { + List rants = rantQuery.execute(); + loadVehiclesForRants(rants); + return rants; + } + + @SuppressWarnings("unchecked") + public List getRantsForDay(Date day) { + List rants = rantForDayQuery.execute(new Object[] {day}); + loadVehiclesForRants(rants); + return rants; + } + + private void loadVehiclesForRants(List rants) { + for (Iterator iter = rants.iterator(); iter.hasNext();) { + JdbcRant rant = (JdbcRant) iter.next(); + rant.setVehicle(findVehicleById(rant.getVehicleId())); + } + } + + public Vehicle findVehicleById(Integer id) { + JdbcVehicle vehicle = (JdbcVehicle) vehicleByIdQuery.findObject(id); + + loadMotoristForVehicle(vehicle); + + return vehicle; + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + Map parameters = new HashMap(); + parameters.put("state", state); + parameters.put("plateNumber", plateNumber); + JdbcVehicle vehicle = (JdbcVehicle) + vehicleByPlateQuery.findObjectByNamedParam(parameters); + + loadMotoristForVehicle(vehicle); + + return vehicle; + } + + private void loadMotoristForVehicle(JdbcVehicle vehicle) { + vehicle.setMotorist(getMotoristById(vehicle.getMotoristId())); + } + + public Motorist getMotoristById(Integer id) { + return (Motorist) motoristByIdQuery.findObject(id); + } + + public Motorist getMotoristByEmail(String email) { + return (Motorist) motoristByEmailQuery.findObject(email); + } + + + // SQL Objects + protected class RantQuery extends MappingSqlQuery { + public RantQuery(DataSource dataSource) { + this(dataSource, RANT_SELECT); + } + + public RantQuery(DataSource dataSource, String query) { + super(dataSource, query); + } + + protected Object mapRow(ResultSet rs, int rowNum) throws SQLException { + JdbcRant rant = new JdbcRant(); + rant.setId(rs.getInt(1)); + rant.setRantText(rs.getString(2)); + rant.setVehicleId(rs.getInt(3)); + rant.setPostedDate(rs.getDate(4)); + return rant; + } + } + + protected class RantForDayQuery extends RantQuery { + public RantForDayQuery(DataSource dataSource) { + super(dataSource, RANT_FOR_DAY_SELECT); + declareParameter(new SqlParameter(Types.DATE)); + compile(); + } + } + + + protected class VehicleQuery extends MappingSqlQuery { + public VehicleQuery(DataSource dataSource, String query) { + super(dataSource, query); + } + + protected Object mapRow(ResultSet rs, int rowNum) + throws SQLException { + JdbcVehicle vehicle = new JdbcVehicle(); + vehicle.setId(rs.getInt(1)); + vehicle.setPlateNumber(rs.getString(2)); + vehicle.setState(rs.getString(3)); + vehicle.setMotoristId(rs.getInt(4)); + return vehicle; + } + } + + protected class VehicleByIdQuery extends VehicleQuery { + public VehicleByIdQuery(DataSource dataSource) { + super(dataSource, VEHICLE_BY_ID_SELECT); + declareParameter(new SqlParameter(Types.INTEGER)); + compile(); + } + } + + protected class VehicleByPlateQuery extends VehicleQuery { + public VehicleByPlateQuery(DataSource dataSource) { + super(dataSource, VEHICLE_BY_PLATE_SELECT); + declareParameter(new SqlParameter(Types.VARCHAR)); + declareParameter(new SqlParameter(Types.VARCHAR)); + compile(); + } + } + + + protected class MotoristQuery extends MappingSqlQuery { + public MotoristQuery(DataSource dataSource, String query) { + super(dataSource, query); + } + + protected Object mapRow(ResultSet rs, int rowNum) + throws SQLException { + Motorist motorist = new Motorist(); + + motorist.setId(rs.getInt(1)); + motorist.setEmail(rs.getString(2)); + motorist.setPassword(rs.getString(3)); + motorist.setFirstName(rs.getString(4)); + motorist.setLastName(rs.getString(5)); + + return motorist; + } + } + + protected class MotoristByEmailQuery extends MotoristQuery { + public MotoristByEmailQuery(DataSource dataSource) { + super(dataSource, MOTORIST_BY_EMAIL_SELECT); + declareParameter(new SqlParameter(Types.VARCHAR)); + compile(); + } + } + + protected class MotoristByIdQuery extends MotoristQuery { + public MotoristByIdQuery(DataSource dataSource) { + super(dataSource, MOTORIST_BY_ID_SELECT); + declareParameter(new SqlParameter(Types.INTEGER)); + compile(); + } + } + + protected class VehicleInsert extends SqlUpdate { + public VehicleInsert(DataSource dataSource) { + super(dataSource, VEHICLE_INSERT); + declareParameter(new SqlParameter(Types.VARCHAR)); + declareParameter(new SqlParameter(Types.VARCHAR)); + declareParameter(new SqlParameter(Types.INTEGER)); + compile(); + } + + public void insert(Vehicle vehicle) { + update(new Object[] { + vehicle.getPlateNumber(), + vehicle.getState(), + vehicle.getMotorist().getId() + }); + } + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcVehicle.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcVehicle.java new file mode 100644 index 00000000..2d07fba4 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/JdbcVehicle.java @@ -0,0 +1,17 @@ +package com.roadrantz.dao.jdbc; + +import com.roadrantz.domain.Vehicle; + +public class JdbcVehicle extends Vehicle { + public JdbcVehicle() {} + + private Integer motoristId; + + public Integer getMotoristId() { + return motoristId; + } + + public void setMotoristId(Integer motoristId) { + this.motoristId = motoristId; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/NamedParameterJdbcRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/NamedParameterJdbcRantDao.java new file mode 100644 index 00000000..cb26bf26 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/NamedParameterJdbcRantDao.java @@ -0,0 +1,76 @@ +package com.roadrantz.dao.jdbc; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class NamedParameterJdbcRantDao extends NamedParameterJdbcDaoSupport + implements RantDao { + + private static final String MOTORIST_SELECT = "select id, email, password, firstName, lastName from motorist"; + + private static final String MOTORIST_INSERT = "insert into motorist (id, email, password, firstName, lastName) " + + "values (null, :email, :password, :firstName, :lastName)"; + + public NamedParameterJdbcRantDao() {} + + public void saveRant(Rant rant) { + // TODO Auto-generated method stub + + } + + public List getAllRants() { + // TODO Auto-generated method stub + return null; + } + + public List getRantsForDay(Date day) { + // TODO Auto-generated method stub + return null; + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + // TODO Auto-generated method stub + return null; + } + + public void saveVehicle(Vehicle vehicle) { + // TODO Auto-generated method stub + + } + + public Motorist getMotoristByEmail(String email) { + // TODO Auto-generated method stub + return null; + } + + /** + * Saves a Motorist object using Spring's NamedParameterJdbcTemplate. + * + * From Listing 5.6 + * + * @param motorist + * The Motorist object to be saved. + */ + public void saveMotorist(Motorist motorist) { + Map parameters = new HashMap(); + parameters.put("email", motorist.getEmail()); + parameters.put("password", motorist.getPassword()); + parameters.put("firstName", motorist.getFirstName()); + parameters.put("lastName", motorist.getLastName()); + getNamedParameterJdbcTemplate().update(MOTORIST_INSERT, parameters); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/SimpleJdbcRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/SimpleJdbcRantDao.java new file mode 100644 index 00000000..a2d2b764 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jdbc/SimpleJdbcRantDao.java @@ -0,0 +1,199 @@ +package com.roadrantz.dao.jdbc; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; +import java.util.List; + +import org.springframework.jdbc.core.simple.ParameterizedRowMapper; +import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class SimpleJdbcRantDao extends SimpleJdbcDaoSupport implements RantDao { + private static final String RANT_INSERT = "insert into rant (id, rantText, vehicle_id, postedDate) " + + "values (null,?,?,?)"; + + private static final String RANT_SELECT = "select id, rantText, vehicle_id, postedDate from rant"; + + private static final String RANT_FOR_DAY_SELECT = RANT_SELECT + + " where postedDate=?"; + + private static final String VEHICLE_SELECT = "select id, plateNumber, state from vehicle"; + + private static final String VEHICLE_BY_ID_SELECT = VEHICLE_SELECT + + " where id=?"; + + private static final String VEHICLE_BY_PLATE_SELECT = VEHICLE_SELECT + + " where state=? and plateNumber=?"; + + private static final String VEHICLE_INSERT = "insert into vehicle (id, plateNumber, state) " + + "values (null,?,?)"; + + private static final String MOTORIST_SELECT = "select id, email, password, firstName, lastName from motorist"; + + private static final String MOTORIST_BY_EMAIL_SELECT = MOTORIST_SELECT + + " where email=?"; + + private static final String MOTORIST_BY_ID_SELECT = MOTORIST_SELECT + + " where id=?"; + + private static final String MOTORIST_INSERT = "insert into motorist (id, email, password, firstName, lastName) " + + "values (null, ?,?,?,?)"; + + public SimpleJdbcRantDao() {} + + public void saveRant(Rant rant) { + getSimpleJdbcTemplate().update(RANT_INSERT, rant.getRantText(), + rant.getVehicle().getId(), rant.getPostedDate()); + + rant.setId(queryForIdentity()); + } + + public List getAllRants() { + return getSimpleJdbcTemplate().query(RANT_SELECT, + new ParameterizedRowMapper() { + public Rant mapRow(ResultSet rs, int rowNum) + throws SQLException { + Rant rant = new Rant(); + + rant.setId(rs.getInt(1)); + rant.setRantText(rs.getString(2)); + rant.setPostedDate(rs.getDate(4)); + Vehicle vehicle = findVehicleById(rs.getInt(3)); + rant.setVehicle(vehicle); + return rant; + } + }); + } + + public Vehicle findVehicleById(Integer id) { + return getSimpleJdbcTemplate().queryForObject(VEHICLE_BY_ID_SELECT, + new ParameterizedRowMapper() { + public Vehicle mapRow(ResultSet rs, int rowNum) + throws SQLException { + Vehicle vehicle = new Vehicle(); + + vehicle.setId(rs.getInt(1)); + vehicle.setPlateNumber(rs.getString(2)); + vehicle.setState(rs.getString(3)); + + return vehicle; + } + }, new Object[] { id }); + } + + public List getRantsForDay(Date day) { + return getSimpleJdbcTemplate().query(RANT_FOR_DAY_SELECT, + // TODO - THIS IS COMMON...SHOULDN'T BE AN AIC + new ParameterizedRowMapper() { + public Rant mapRow(ResultSet rs, int rowNum) + throws SQLException { + Rant rant = new Rant(); + + rant.setId(rs.getInt(1)); + rant.setRantText(rs.getString(2)); + rant.setPostedDate(rs.getDate(4)); + Vehicle vehicle = findVehicleById(rs.getInt(3)); + rant.setVehicle(vehicle); + return rant; + } + }, day); + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + List matches = getSimpleJdbcTemplate().query( + VEHICLE_BY_PLATE_SELECT, + new ParameterizedRowMapper() { + public Vehicle mapRow(ResultSet rs, int rowNum) + throws SQLException { + Vehicle vehicle = new Vehicle(); + + vehicle.setId(rs.getInt(1)); + vehicle.setPlateNumber(rs.getString(2)); + vehicle.setState(rs.getString(3)); + + return vehicle; + } + }, new Object[] { state, plateNumber }); + + return (matches.size() > 0) ? matches.get(0) : null; + } + + public void saveVehicle(Vehicle vehicle) { + getSimpleJdbcTemplate().update(VEHICLE_INSERT, vehicle.getPlateNumber(), + vehicle.getState()); + vehicle.setId(queryForIdentity()); + } + + public Motorist getMotoristByEmail(String email) { + List matches = getSimpleJdbcTemplate().query( + MOTORIST_BY_EMAIL_SELECT, + new ParameterizedRowMapper() { + public Motorist mapRow(ResultSet rs, int rowNum) + throws SQLException { + Motorist motorist = new Motorist(); + + motorist.setId(rs.getInt(1)); + motorist.setEmail(rs.getString(2)); + motorist.setPassword(rs.getString(3)); + motorist.setFirstName(rs.getString(4)); + motorist.setLastName(rs.getString(5)); + + return motorist; + } + }, email); + + return (matches.size() > 0) ? matches.get(0) : null; + } + + /** + * Retrieves a Motorist from the database using Spring's SimpleJdbcTemplate, + * which allows for handy Java 5 features such as generics, autoboxing, and + * variable arguments. + * + * From Listing 5.7 + * + * @param id + * The ID of the Motorist to be retrieved + * @return The Motorist + */ + public Motorist getMotoristById(long id) { + List matches = getSimpleJdbcTemplate().query( + MOTORIST_BY_ID_SELECT, + new ParameterizedRowMapper() { + public Motorist mapRow(ResultSet rs, int rowNum) + throws SQLException { + Motorist motorist = new Motorist(); + + motorist.setId(rs.getInt(1)); + motorist.setEmail(rs.getString(2)); + motorist.setPassword(rs.getString(3)); + motorist.setFirstName(rs.getString(4)); + motorist.setLastName(rs.getString(5)); + return motorist; + } + }, id); + + return matches.size() > 0 ? matches.get(0) : null; + } + + public void saveMotorist(Motorist motorist) { + getSimpleJdbcTemplate().update(MOTORIST_INSERT, motorist.getEmail(), + motorist.getPassword(), motorist.getFirstName(), + motorist.getLastName()); + motorist.setId(queryForIdentity()); + } + + private Integer queryForIdentity() { + return new Integer(getJdbcTemplate().queryForInt("call Identity()")); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jpa/JpaRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jpa/JpaRantDao.java new file mode 100644 index 00000000..73eb1ae6 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jpa/JpaRantDao.java @@ -0,0 +1,74 @@ +package com.roadrantz.dao.jpa; + +import java.util.Date; +import java.util.List; + +import org.springframework.orm.jpa.support.JpaDaoSupport; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * RantDao implementation that uses JPA by extending Spring's JpaDaoSupport + * class and using the supplied JpaTemplate. + * + * Among other things, JpaTemplate offers several convenience methods (such as + * find()) as well as throwing subclasses of Spring's + * platform-neutral DataAccessException. + * + * The downside of using JpaTemplate (and JpaDaoSupport) is that JpaRantDao is + * coupled to the Spring API. For an almost Spring-free approach, take a look at + * PureJpaRantDao. + * + * @author wallsc + */ +public class JpaRantDao extends JpaDaoSupport implements RantDao { + + public JpaRantDao() {} + + public void saveRant(Rant rant) { + getJpaTemplate().persist(rant); + } + + @SuppressWarnings("unchecked") + public List getAllRants() { + return getJpaTemplate().find("select r from Rant r"); + } + + @SuppressWarnings("unchecked") + public List getRantsForDay(Date day) { + return getJpaTemplate().find( + "select r from Rant r where r.postedDate=?1", day); + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + List matches = getJpaTemplate() + .find( + "select v from Vehicle v where v.state=?1 and v.plateNumber=?2", + state, plateNumber); + + return (matches.size() > 0) ? (Vehicle) matches.get(0) : null; + } + + public void saveVehicle(Vehicle vehicle) { + getJpaTemplate().persist(vehicle); + } + + public Motorist getMotoristByEmail(String email) { + List matches = getJpaTemplate().find( + "select d from Motorist d where d.email=?1", email); + + return (matches.size() > 0) ? (Motorist) matches.get(0) : null; + } + + public void saveMotorist(Motorist driver) { + getJpaTemplate().persist(driver); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jpa/PureJpaRantDao.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jpa/PureJpaRantDao.java new file mode 100644 index 00000000..02836c6e --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/dao/jpa/PureJpaRantDao.java @@ -0,0 +1,90 @@ +package com.roadrantz.dao.jpa; + +import java.util.Date; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.springframework.stereotype.Repository; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * RantDao implementation that only uses JPA. Contrast this to JpaRantDao which + * extends JpaDaoSupport and uses JpaTemplate from Spring's API. The only tie to + * Spring in PureJpaRantDao is the Repository annotation, which is used to guide + * Spring in converting JPA-specific exceptions to subclasses of Spring's + * platform-neutral DataAccessException. + * + * The EntityManager is injected here by PersistenceAnnotationBeanPostProcessor, + * configured in the Spring context along with the entity manager factory. + * + * Upon looking back at the book, I discovered that I don't discuss this + * implementation at all in the book. That's unfortunate, since the Pure JPA + * approach is considered the preferred approach to using JPA in Spring. + * Nevertheless, here's the implementation for your enjoyment. + * + * @author wallsc + */ +@Repository +public class PureJpaRantDao implements RantDao { + public PureJpaRantDao() {} + + private EntityManager entityManager; + + @PersistenceContext + public void setEntityManager(EntityManager entityManager) { + this.entityManager = entityManager; + } + + public void saveRant(Rant rant) { + entityManager.persist(rant); + } + + @SuppressWarnings("unchecked") + public List getAllRants() { + return entityManager.createQuery("select r from Rant r").getResultList(); + } + + @SuppressWarnings("unchecked") + public List getRantsForDay(Date day) { + return entityManager.createQuery( + "select r from Rant r where r.postedDate=?1") + .setParameter(1, day).getResultList(); + } + + public Vehicle findVehicleByPlate(String state, String plateNumber) { + List matches = entityManager.createQuery( + "select v from Vehicle v where v.state=?1 " + + "and v.plateNumber=?2") + .setParameter(1, state).setParameter(2, plateNumber) + .getResultList(); + + return (matches.size() > 0) ? (Vehicle) matches.get(0) : null; + } + + public void saveVehicle(Vehicle vehicle) { + entityManager.persist(vehicle); + } + + public Motorist getMotoristByEmail(String email) { + List matches = entityManager.createQuery( + "select d from Motorist d where d.email=?1") + .setParameter(1, email).getResultList(); + + return (matches.size() > 0) ? (Motorist) matches.get(0) : null; + } + + public void saveMotorist(Motorist driver) { + entityManager.persist(driver); + } + + public int getMotoristCount() { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Motorist.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Motorist.java new file mode 100644 index 00000000..3f4833cb --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Motorist.java @@ -0,0 +1,112 @@ +package com.roadrantz.domain; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Transient; + +import org.apache.commons.lang.builder.ToStringBuilder; + +@Entity +@SuppressWarnings("serial") +public class Motorist implements Serializable { + private Integer id; + private String firstName; + private String lastName; + private String email; + private String password; + private List vehicles; + private Set privileges; + + public Motorist() { + privileges = new HashSet(); + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @OneToMany(cascade=CascadeType.ALL, + mappedBy="motorist") + public List getVehicles() { + return vehicles; + } + + public void setVehicles(List vehicles) { + this.vehicles = vehicles; + } + + @Transient + public List getRants() { + List allRants = new ArrayList(); + + for (Vehicle vehicle : vehicles) { + allRants.addAll(vehicle.getRants()); + } + + return allRants; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @OneToMany(cascade=CascadeType.ALL, + fetch=FetchType.LAZY, + mappedBy="motorist") + public Set getPrivileges() { + return privileges; + } + + public void setPrivileges(Set privileges) { + this.privileges = privileges; + } + + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/MotoristPrivilege.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/MotoristPrivilege.java new file mode 100644 index 00000000..9d461867 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/MotoristPrivilege.java @@ -0,0 +1,52 @@ +package com.roadrantz.domain; + +import java.io.Serializable; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name="MOTORIST_PRIVILEGES") +@SuppressWarnings("serial") +public class MotoristPrivilege implements Serializable { + private Integer id; + private Motorist motorist; + private String privilege; + + public MotoristPrivilege() {} + + public MotoristPrivilege(String privilege) { + this.privilege = privilege; + } + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @ManyToOne + public Motorist getMotorist() { + return motorist; + } + + public void setMotorist(Motorist motorist) { + this.motorist = motorist; + } + + public String getPrivilege() { + return privilege; + } + + public void setPrivilege(String privilege) { + this.privilege = privilege; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Rant.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Rant.java new file mode 100644 index 00000000..5bcec282 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Rant.java @@ -0,0 +1,73 @@ +package com.roadrantz.domain; + +import java.io.Serializable; +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +@Entity +@SuppressWarnings("serial") +public class Rant implements Serializable{ + private Integer id; + private Vehicle vehicle; + private String rantText; + private Date postedDate; + + public Rant() {} + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getRantText() { + return rantText; + } + + public void setRantText(String rantText) { + this.rantText = rantText; + } + + @Temporal(TemporalType.DATE) + public Date getPostedDate() { + return postedDate; + } + + public void setPostedDate(Date postedDate) { + this.postedDate = postedDate; + } + + @ManyToOne + public Vehicle getVehicle() { + return vehicle; + } + + public void setVehicle(Vehicle vehicle) { + this.vehicle = vehicle; + } + + public boolean equals(Object o) { + if (o instanceof Rant) { + Rant rant = (Rant) o; + return rant.id.equals(this.id); + } else { + return false; + } + } + + public int hashCode() { + // TODO Auto-generated method stub + return super.hashCode(); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Vehicle.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Vehicle.java new file mode 100644 index 00000000..f84c135d --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/domain/Vehicle.java @@ -0,0 +1,97 @@ +package com.roadrantz.domain; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +@Entity +@SuppressWarnings("serial") +public class Vehicle implements Serializable { + private Integer id; + private String state; + private String plateNumber; + private Motorist motorist; + private List rants; + + public Vehicle() {} + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getPlateNumber() { + return plateNumber; + } + + public void setPlateNumber(String plateNumber) { + this.plateNumber = stripNonAlphanumeric(plateNumber); + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state.toUpperCase(); + } + + + @ManyToOne + public Motorist getMotorist() { + return motorist; + } + + public void setMotorist(Motorist motorist) { + this.motorist = motorist; + } + + @OneToMany(targetEntity=Rant.class, + cascade=CascadeType.ALL, + mappedBy="vehicle") + public List getRants() { + return rants; + } + + public void setRants(List rants) { + this.rants = rants; + } + + private String stripNonAlphanumeric(String in) { + if(in == null) { return null; } + + StringBuffer outBuffer = new StringBuffer(in.length()); + + for(int i = 0; i < in.length(); i++) { + char c = in.charAt(i); + if(Character.isLetter(c) || Character.isDigit(c)) { + outBuffer.append(Character.toUpperCase(c)); + } + } + + return outBuffer.toString(); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/ejb/RantServiceEjb.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/ejb/RantServiceEjb.java new file mode 100644 index 00000000..4b33427b --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/ejb/RantServiceEjb.java @@ -0,0 +1,54 @@ +package com.roadrantz.ejb; + +import java.util.Date; +import java.util.List; + +import javax.ejb.CreateException; + +import org.springframework.ejb.support.AbstractStatelessSessionBean; + +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.MotoristAlreadyExistsException; +import com.roadrantz.service.RantService; + +public class RantServiceEjb + extends AbstractStatelessSessionBean + implements RantService { + public RantServiceEjb() {} + + private RantService rantService; + protected void onEjbCreate() throws CreateException { + rantService = (RantService) getBeanFactory().getBean("rantService"); + } + + public void addMotorist(Motorist motorist) + throws MotoristAlreadyExistsException { + rantService.addMotorist(motorist); + } + + public void addRant(Rant rant) { + rantService.addRant(rant); + } + + public List getRantsForDay(Date date) { + return rantService.getRantsForDay(date); + } + + public List getRantsForVehicle(Vehicle vehicle) { + return rantService.getRantsForVehicle(vehicle); + } + + public List getRecentRants() { + return rantService.getRecentRants(); + } + + public void sendDailyRantEmails() { + rantService.sendDailyRantEmails(); + } + + public void sendEmailForVehicle(Vehicle vehicle) { + rantService.sendEmailForVehicle(vehicle); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdb.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdb.java new file mode 100644 index 00000000..c537b389 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdb.java @@ -0,0 +1,42 @@ +package com.roadrantz.marketing; + +import javax.ejb.EJBException; +import javax.ejb.MessageDrivenBean; +import javax.ejb.MessageDrivenContext; +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.MessageListener; + +public class MarketingMdb + implements MessageDrivenBean, MessageListener { + + private transient MessageDrivenContext ctx; + + public void setMessageDrivenContext(MessageDrivenContext ctx) + throws EJBException { + this.ctx = ctx; + } + + public void ejbRemove() throws EJBException { + } + + public void onMessage(Message message) { + MapMessage mapMessage = (MapMessage) message; + + try { + SpammedMotorist driver = new SpammedMotorist(); + driver.setFirstName(mapMessage.getString("firstName")); + driver.setLastName(mapMessage.getString("lastName")); + driver.setEmail(mapMessage.getString("email")); + + processDriverInfo(driver); + } catch (JMSException e) { + // handle--somehow + } + } + + private void processDriverInfo(SpammedMotorist driver) { + // ... + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp.java new file mode 100644 index 00000000..a57fd244 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp.java @@ -0,0 +1,12 @@ +package com.roadrantz.marketing; + +/** + * Marketing message-driven POJO, as it appears in listing 10.9. + * + * @author wallsc + */ +public class MarketingMdp implements MarketingService { + public MarketingMdp() {} + + public void processDriverInfo(SpammedMotorist driver) {} +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp10_7.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp10_7.java new file mode 100644 index 00000000..f060769c --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp10_7.java @@ -0,0 +1,34 @@ +package com.roadrantz.marketing; + +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.MessageListener; + +/** + * MarketingMdp message-driven POJO, as it appeared in listing 10.7. + * + * @author wallsc + */ +public class MarketingMdp10_7 implements MessageListener { + + public void onMessage(Message message) { + MapMessage mapMessage = (MapMessage) message; + + try { + SpammedMotorist motorist = new SpammedMotorist(); + motorist.setFirstName(mapMessage.getString("firstName")); + motorist.setLastName(mapMessage.getString("lastName")); + motorist.setEmail(mapMessage.getString("email")); + + processMotoristInfo(motorist); + } + catch (JMSException e) { + // handle--somehow + } + } + + private void processMotoristInfo(SpammedMotorist motorist) { + // ... + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp10_8.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp10_8.java new file mode 100644 index 00000000..c445dff2 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingMdp10_8.java @@ -0,0 +1,25 @@ +package com.roadrantz.marketing; + +import javax.jms.JMSException; +import javax.jms.MapMessage; + +/** + * MarketingMdp, as it appeared in listing 10.8. + * + * @author wallsc + */ +public class MarketingMdp10_8 { + public MarketingMdp10_8() {} + + public void processMotoristInfo(MapMessage message) { + SpammedMotorist motorist = new SpammedMotorist(); + try { + motorist.setFirstName(message.getString("firstName")); + motorist.setLastName(message.getString("lastName")); + motorist.setEmail(message.getString("email")); + } + catch (JMSException e) { + // handle this...somehow + } + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingReceiverGatewayImpl.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingReceiverGatewayImpl.java new file mode 100644 index 00000000..27905d2a --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingReceiverGatewayImpl.java @@ -0,0 +1,17 @@ +package com.roadrantz.marketing; + +import org.springframework.jms.core.JmsTemplate; + +public class MarketingReceiverGatewayImpl { + public MarketingReceiverGatewayImpl() {} + + public SpammedMotorist receivedSpammedDriver() { + return (SpammedMotorist) jmsTemplate.receiveAndConvert(); + } + + //injected + private JmsTemplate jmsTemplate; + public void setJmsTemplate(JmsTemplate jmsTemplate) { + this.jmsTemplate = jmsTemplate; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingReceiverGatewayImpl10_4.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingReceiverGatewayImpl10_4.java new file mode 100644 index 00000000..33d74dda --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingReceiverGatewayImpl10_4.java @@ -0,0 +1,38 @@ +package com.roadrantz.marketing; + +import javax.jms.JMSException; +import javax.jms.MapMessage; +import org.springframework.jms.core.JmsTemplate; +import org.springframework.jms.support.JmsUtils; + +/** + * The original version of MarketingReceiverGatewayImpl, as shown in Listing + * 10.4. This example evolves as chapter 10 progresses, so this class serves as + * a memory of what MarketingReceiverGatewayImpl looked like in listing 10.4. + * + * @author wallsc + */ +public class MarketingReceiverGatewayImpl10_4 { + public MarketingReceiverGatewayImpl10_4() {} + + public SpammedMotorist receiveSpammedMotorist() { + MapMessage message = (MapMessage) jmsTemplate.receive(); + SpammedMotorist motorist = new SpammedMotorist(); + try { + motorist.setFirstName(message.getString("firstName")); + motorist.setLastName(message.getString("lastName")); + motorist.setEmail(message.getString("email")); + } + catch (JMSException e) { + throw JmsUtils.convertJmsAccessException(e); + } + return motorist; + } + + // injected + private JmsTemplate jmsTemplate; + + public void setJmsTemplate(JmsTemplate jmsTemplate) { + this.jmsTemplate = jmsTemplate; + } +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingService.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingService.java new file mode 100644 index 00000000..58cc27bd --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MarketingService.java @@ -0,0 +1,5 @@ +package com.roadrantz.marketing; + +public interface MarketingService { + public void processDriverInfo(SpammedMotorist driver); +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MotoristMessageConverter.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MotoristMessageConverter.java new file mode 100644 index 00000000..1c12a402 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/MotoristMessageConverter.java @@ -0,0 +1,55 @@ +package com.roadrantz.marketing; + +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.Session; + +import org.springframework.jms.support.converter.MessageConversionException; +import org.springframework.jms.support.converter.MessageConverter; + +import com.roadrantz.domain.Motorist; + +/** + * A message converter to convert MapMessages to/from Motorist objects. + * + * As shown in listing 10.5. + * + * @author wallsc + */ +public class MotoristMessageConverter implements MessageConverter { + public MotoristMessageConverter() {} + + public Object fromMessage(Message message) throws JMSException, + MessageConversionException { + + if (!(message instanceof MapMessage)) { + throw new MessageConversionException("Message isn't a MapMessage"); + } + + MapMessage mapMessage = (MapMessage) message; + SpammedMotorist motorist = new SpammedMotorist(); + + motorist.setFirstName(mapMessage.getString("firstName")); + motorist.setLastName(mapMessage.getString("lastName")); + motorist.setEmail(mapMessage.getString("email")); + + return motorist; + } + + public Message toMessage(Object object, Session session) + throws JMSException, MessageConversionException { + + if (!(object instanceof Motorist)) { + throw new MessageConversionException("Object isn't a Motorist"); + } + + Motorist motorist = (Motorist) object; + MapMessage message = session.createMapMessage(); + message.setString("firstName", motorist.getFirstName()); + message.setString("lastName", motorist.getLastName()); + message.setString("email", motorist.getEmail()); + + return message; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGateway.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGateway.java new file mode 100644 index 00000000..e1c5a473 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGateway.java @@ -0,0 +1,7 @@ +package com.roadrantz.marketing; + +import com.roadrantz.domain.Motorist; + +public interface RantzMarketingGateway { + public void sendMotoristInfo(Motorist driver); +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl.java new file mode 100644 index 00000000..d9f7ada4 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl.java @@ -0,0 +1,22 @@ +package com.roadrantz.marketing; + +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.Session; + +import org.springframework.jms.core.MessageCreator; +import org.springframework.jms.core.support.JmsGatewaySupport; + +import com.roadrantz.domain.Motorist; + +public class RantzMarketingGatewayImpl + extends JmsGatewaySupport + implements RantzMarketingGateway { + public RantzMarketingGatewayImpl() {} + + public void sendMotoristInfo(final Motorist motorist) { + getJmsTemplate().convertAndSend(motorist); + } + +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl10_3.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl10_3.java new file mode 100644 index 00000000..d055d7ad --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl10_3.java @@ -0,0 +1,45 @@ +package com.roadrantz.marketing; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.Session; +import org.springframework.jms.core.JmsTemplate; +import org.springframework.jms.core.MessageCreator; +import com.roadrantz.domain.Motorist; + +/** + * The original implementation of RantzMarkingGatewayImpl from Listing 10.3. + * This class evolves as chapter 10 progresses, so this class serves as a memory + * of what it looked like in Listing 10.3. + * + * @author wallsc + */ +public class RantzMarketingGatewayImpl10_3 implements RantzMarketingGateway { + public RantzMarketingGatewayImpl10_3() {} + + public void sendMotoristInfo(final Motorist motorist) { + jmsTemplate.send(destination, new MessageCreator() { + public Message createMessage(Session session) throws JMSException { + MapMessage message = session.createMapMessage(); + message.setString("lastName", motorist.getLastName()); + message.setString("firstName", motorist.getFirstName()); + message.setString("email", motorist.getEmail()); + return message; + } + }); + } + + private JmsTemplate jmsTemplate; + + public void setJmsTemplate(JmsTemplate jmsTemplate) { + this.jmsTemplate = jmsTemplate; + } + + private Destination destination; + + public void setDestination(Destination destination) { + this.destination = destination; + } +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl10_6.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl10_6.java new file mode 100644 index 00000000..ba04ed61 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/RantzMarketingGatewayImpl10_6.java @@ -0,0 +1,33 @@ +package com.roadrantz.marketing; + +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.Session; + +import org.springframework.jms.core.MessageCreator; +import org.springframework.jms.core.support.JmsGatewaySupport; + +import com.roadrantz.domain.Motorist; + +/** + * RantzMarketingGatewayImpl as it appeared in listing 10.6. + * + * @author wallsc + */ +public class RantzMarketingGatewayImpl10_6 extends JmsGatewaySupport implements + RantzMarketingGateway { + public RantzMarketingGatewayImpl10_6() {} + + public void sendMotoristInfo(final Motorist motorist) { + getJmsTemplate().send("rantz.marketing.queue", new MessageCreator() { + public Message createMessage(Session session) throws JMSException { + MapMessage message = session.createMapMessage(); + message.setString("lastName", motorist.getLastName()); + message.setString("firstName", motorist.getFirstName()); + message.setString("email", motorist.getEmail()); + return message; + } + }); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/SpammedMotorist.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/SpammedMotorist.java new file mode 100644 index 00000000..edcfb9a7 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/marketing/SpammedMotorist.java @@ -0,0 +1,37 @@ +package com.roadrantz.marketing; + +import java.io.Serializable; + +public class SpammedMotorist implements Serializable { + private String firstName; + private String lastName; + private String email; + + public SpammedMotorist() {} + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/AddRantFormController.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/AddRantFormController.java new file mode 100644 index 00000000..41a726ee --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/AddRantFormController.java @@ -0,0 +1,62 @@ +package com.roadrantz.mvc; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.validation.BindException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.SimpleFormController; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.RantService; + +public class AddRantFormController extends SimpleFormController { + private static final String[] ALL_STATES = { "AL", "AK", "AZ", "AR", "CA", + "CO", "CT", "DE", "DC", "FL", "GA", "HI", "ID", "IL", "IN", "IA", + "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", + "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", + "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA", "WV", + "WI", "WY" }; + + public AddRantFormController() { + setCommandClass(Rant.class); + setCommandName("rant"); + } + + @Override + protected Object formBackingObject(HttpServletRequest request) + throws Exception { + Rant rantForm = (Rant) super.formBackingObject(request); + rantForm.setVehicle(new Vehicle()); + return rantForm; + } + + @Override + protected Map referenceData(HttpServletRequest request) throws Exception { + Map referenceData = new HashMap(); + + referenceData.put("states", ALL_STATES); + + return referenceData; + } + + @Override + protected ModelAndView onSubmit(Object command, BindException bindException) + throws Exception { + + Rant rant = (Rant) command; + rantService.addRant(rant); + + return new ModelAndView(getSuccessView()); + } + + // injected + private RantService rantService; + + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/DayForm.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/DayForm.java new file mode 100644 index 00000000..a83d6439 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/DayForm.java @@ -0,0 +1,16 @@ +package com.roadrantz.mvc; + +import java.util.Date; + +public class DayForm { + private Date day; + public DayForm() {} + + public Date getDay() { + return day; + } + + public void setDay(Date day) { + this.day = day; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/HomePageController.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/HomePageController.java new file mode 100644 index 00000000..a13f9ac1 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/HomePageController.java @@ -0,0 +1,30 @@ +package com.roadrantz.mvc; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +import com.roadrantz.service.RantService; + +public class HomePageController extends AbstractController { + public HomePageController() {} + + protected ModelAndView handleRequestInternal( + HttpServletRequest request, HttpServletResponse response) + throws Exception { + + List recentRants = rantService.getRecentRants(); + + return new ModelAndView("home", "rants", recentRants); + } + + // injected + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/MotoristRegistrationController.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/MotoristRegistrationController.java new file mode 100644 index 00000000..8da7294d --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/MotoristRegistrationController.java @@ -0,0 +1,82 @@ +package com.roadrantz.mvc; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.validation.BindException; +import org.springframework.validation.Errors; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractWizardFormController; + +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.RantService; + +public class MotoristRegistrationController extends AbstractWizardFormController { + public MotoristRegistrationController() { + setCommandClass(Motorist.class); + setCommandName("motorist"); + } + + protected Object formBackingObject(HttpServletRequest request) + throws Exception { + Motorist formMotorist = new Motorist(); + List vehicles = new ArrayList(); + vehicles.add(new Vehicle()); + formMotorist.setVehicles(vehicles); + return formMotorist; + } + + protected Map referenceData(HttpServletRequest request, + Object command, Errors errors, int page) throws Exception { + + Motorist motorist = (Motorist) command; + Map refData = new HashMap(); + + if(page == 1 && request.getParameter("_target1") != null) { + refData.put("nextVehicle", motorist.getVehicles().size() - 1); + } + + return refData; + } + + protected void postProcessPage(HttpServletRequest request, + Object command, Errors errors, int page) throws Exception { + + Motorist motorist = (Motorist) command; + + if(page == 1 && request.getParameter("_target1") != null) { + motorist.getVehicles().add(new Vehicle()); + } } + + protected ModelAndView processFinish(HttpServletRequest request, + HttpServletResponse response, Object command, BindException errors) + throws Exception { + + Motorist motorist = (Motorist) command; + + // the last vehicle is always blank...remove it + motorist.getVehicles().remove(motorist.getVehicles().size() - 1); + + rantService.addMotorist(motorist); + + return new ModelAndView(getSuccessView(), "motorist", motorist); + } + + // injected + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } + + // returns the last page as the success view + private String getSuccessView() { + return getPages()[getPages().length-1]; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/OldRantsForDayController.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/OldRantsForDayController.java new file mode 100644 index 00000000..b7d008ef --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/OldRantsForDayController.java @@ -0,0 +1,32 @@ +package com.roadrantz.mvc; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.validation.BindException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractCommandController; + +import com.roadrantz.service.RantService; + +public class OldRantsForDayController extends AbstractCommandController { + public OldRantsForDayController() { + setCommandClass(DayForm.class); + } + + protected ModelAndView handle(HttpServletRequest request, + HttpServletResponse response, Object command, + BindException errors) throws Exception { + + DayForm day = (DayForm) command; + + return new ModelAndView("dayRants", "rants", + rantService.getRantsForDay(day.getDay())); + } + + // injected + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantExcelView.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantExcelView.java new file mode 100644 index 00000000..d88f9f65 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantExcelView.java @@ -0,0 +1,59 @@ +package com.roadrantz.mvc; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.poi.hssf.usermodel.HSSFCellStyle; +import org.apache.poi.hssf.usermodel.HSSFDataFormat; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.springframework.web.servlet.view.document.AbstractExcelView; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +public class RantExcelView extends AbstractExcelView { + protected void buildExcelDocument(Map model, HSSFWorkbook workbook, + HttpServletRequest request, HttpServletResponse response) + throws Exception { + + Collection rants = (Collection) model.get("rants"); + Vehicle vehicle = (Vehicle) model.get("vehicle"); + + HSSFSheet sheet = createSheet(workbook, vehicle.getPlateNumber()); + + HSSFCellStyle cellStyle = workbook.createCellStyle(); + cellStyle.setDataFormat( + HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm")); + + int rowNum = 1; + for (Iterator iter = rants.iterator(); iter.hasNext();) { + Rant rant = (Rant) iter.next(); + rowNum = addRantRow(sheet, cellStyle, rowNum, rant); + } + } + + private int addRantRow(HSSFSheet sheet, HSSFCellStyle cellStyle, + int rowNum, Rant rant) { + HSSFRow row = sheet.createRow(rowNum++); + row.createCell((short) 0).setCellValue(rant.getPostedDate()); + row.createCell((short) 1).setCellValue(rant.getRantText()); + row.getCell((short) 1).setCellStyle(cellStyle); + return rowNum; + } + + private HSSFSheet createSheet(HSSFWorkbook workbook, + String plateNumber) { + HSSFSheet sheet = workbook.createSheet("Rants for " + plateNumber); + + HSSFRow header = sheet.createRow(0); + header.createCell((short) 0).setCellValue("Date"); + header.createCell((short) 1).setCellValue("Text"); + return sheet; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantPdfView.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantPdfView.java new file mode 100644 index 00000000..e36ea651 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantPdfView.java @@ -0,0 +1,43 @@ +package com.roadrantz.mvc; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.view.document.AbstractPdfView; + +import com.lowagie.text.Document; +import com.lowagie.text.Table; +import com.lowagie.text.pdf.PdfWriter; +import com.roadrantz.domain.Rant; + +public class RantPdfView extends AbstractPdfView { + protected void buildPdfDocument(Map model, Document document, + PdfWriter pdfWriter, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + List rants = (List) model.get("rants"); + Table rantTable = new Table(4); + rantTable.setWidth(90); + rantTable.setBorderWidth(1); + + rantTable.addCell("State"); + rantTable.addCell("Plate"); + rantTable.addCell("Date Posted"); + rantTable.addCell("Text"); + + for (Iterator iter = rants.iterator(); iter.hasNext();) { + Rant rant = (Rant) iter.next(); + + rantTable.addCell(rant.getVehicle().getState()); + rantTable.addCell(rant.getVehicle().getPlateNumber()); + rantTable.addCell(rant.getPostedDate().toString()); + rantTable.addCell(rant.getRantText()); + } + + document.add(rantTable); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantRssView.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantRssView.java new file mode 100644 index 00000000..9bed1644 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantRssView.java @@ -0,0 +1,106 @@ +package com.roadrantz.mvc; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.view.AbstractView; + +import com.roadrantz.domain.Rant; +import com.sun.syndication.feed.synd.SyndContent; +import com.sun.syndication.feed.synd.SyndContentImpl; +import com.sun.syndication.feed.synd.SyndEntry; +import com.sun.syndication.feed.synd.SyndEntryImpl; +import com.sun.syndication.feed.synd.SyndFeed; +import com.sun.syndication.feed.synd.SyndFeedImpl; +import com.sun.syndication.io.SyndFeedOutput; + +public class RantRssView extends AbstractView { + private String author; + private String title; + private String description; + private String link; + + public RantRssView() {} + + protected void renderMergedOutputModel(Map model, + HttpServletRequest request, HttpServletResponse response) + throws Exception { + + SyndFeed feed = createFeed(); + List rants = (List)model.get("rants"); + List entries = new ArrayList(); + + for (Iterator iter = rants.iterator(); iter.hasNext();) { + Rant rant = (Rant) iter.next(); + entries.add(createEntry(rant)); + } + + feed.setEntries(entries); + + SyndFeedOutput output = new SyndFeedOutput(); + output.output(feed, response.getWriter()); + } + + private SyndEntry createEntry(Rant rant) { + SyndEntry entry = new SyndEntryImpl(); + + entry.setTitle("title?"); + entry.setLink("link"); + entry.setPublishedDate(rant.getPostedDate()); + SyndContent content = new SyndContentImpl(); + content.setType("text/html"); + content.setValue(rant.getRantText()); + entry.setDescription(content); + + return entry; + } + + private SyndFeed createFeed() { + SyndFeed feed = new SyndFeedImpl(); + feed.setFeedType("rss_1.0"); + feed.setAuthor(author); + feed.setTitle(title); + feed.setDescription(description); + feed.setLink(link); + + return feed; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantValidator.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantValidator.java new file mode 100644 index 00000000..668ec9da --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantValidator.java @@ -0,0 +1,43 @@ +package com.roadrantz.mvc; + +import org.apache.oro.text.perl.Perl5Util; +import org.springframework.validation.Errors; +import org.springframework.validation.ValidationUtils; +import org.springframework.validation.Validator; + +import com.roadrantz.domain.Rant; + +public class RantValidator implements Validator { + public boolean supports(Class clazz) { + return clazz.equals(Rant.class); + } + + public void validate(Object command, Errors errors) { + Rant rant = (Rant) command; + + ValidationUtils.rejectIfEmpty( + errors, "vehicle.state", "required.state", + "State is required."); + + ValidationUtils.rejectIfEmpty( + errors, "vehicle.plateNumber", "required.plateNumber", + "The license plate number is required."); + + ValidationUtils.rejectIfEmptyOrWhitespace( + errors, "rantText", "required.rantText", + "You must enter some rant text."); + + validatePlateNumber(rant.getVehicle().getPlateNumber(), errors); + } + + private static final String PLATE_REGEXP = + "/[a-z0-9]{2,6}/i"; + + private void validatePlateNumber(String plateNumber, Errors errors) { + Perl5Util perl5Util = new Perl5Util(); + if(!perl5Util.match(PLATE_REGEXP, plateNumber)) { + errors.reject("invalid.plateNumber", + "Invalid license plate number."); + } + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantsForDayController.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantsForDayController.java new file mode 100644 index 00000000..f2eccd48 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantsForDayController.java @@ -0,0 +1,43 @@ +package com.roadrantz.mvc; + +import java.util.Date; +import java.util.List; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.throwaway.ThrowawayController; + +import com.roadrantz.domain.Rant; +import com.roadrantz.service.RantService; + +public class RantsForDayController implements ThrowawayController { + private int month; + private int day; + private int year; + + public ModelAndView execute() throws Exception { + Date date = new Date(month, day, year); + + List dayRants = rantService.getRantsForDay(date); + + return new ModelAndView("dayRants", "rants", + dayRants); + } + + public void setDay(int day) { + this.day = day; + } + + public void setMonth(int month) { + this.month = month; + } + + public void setYear(int year) { + this.year = year; + } + + // injected + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantsForVehicleController.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantsForVehicleController.java new file mode 100644 index 00000000..025d40f4 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/mvc/RantsForVehicleController.java @@ -0,0 +1,50 @@ +package com.roadrantz.mvc; + +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.validation.BindException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.mvc.AbstractCommandController; + +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.RantService; + +public class RantsForVehicleController extends AbstractCommandController { + private static final String BASE_VIEW_NAME = "vehicleRants"; + + public RantsForVehicleController() { + setCommandClass(Vehicle.class); + setCommandName("vehicle"); + } + + protected ModelAndView handle(HttpServletRequest request, + HttpServletResponse response, Object command, + BindException errors) throws Exception { + + Vehicle vehicle = (Vehicle) command; + + Map model = errors.getModel(); + model.put("rants", rantService.getRantsForVehicle(vehicle)); + model.put("vehicle", vehicle); + + return new ModelAndView(getViewName(request), model); + } + + private String getViewName(HttpServletRequest request) { + String requestUri = request.getRequestURI(); + String extension = "." + requestUri.substring(requestUri.length() - 3); + if(".htm".equals(extension)) { extension=""; } + return BASE_VIEW_NAME + extension; + } + + // injected + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/security/PasswordEncodingAdvice.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/security/PasswordEncodingAdvice.java new file mode 100644 index 00000000..104ae1fb --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/security/PasswordEncodingAdvice.java @@ -0,0 +1,47 @@ +package com.roadrantz.security; + +import org.acegisecurity.providers.dao.SaltSource; +import org.acegisecurity.providers.encoding.PasswordEncoder; +import org.apache.log4j.Logger; +import org.aspectj.lang.ProceedingJoinPoint; + +import com.roadrantz.domain.Motorist; + +public class PasswordEncodingAdvice { + private static final Logger LOGGER = + Logger.getLogger(PasswordEncodingAdvice.class); + + public PasswordEncodingAdvice() {} + + public Object encodeMotoristPassword(ProceedingJoinPoint pjp) + throws Throwable { + + Object[] args = pjp.getArgs(); + if(args.length != 1 || !(args[0] instanceof Motorist)) { + return pjp.proceed(); + } + + Motorist motorist = (Motorist) args[0]; + String encodedPassword = + passwordEncoder.encodePassword(motorist.getPassword().trim(), + saltSource.getSalt(null)); + + LOGGER.debug("SALT: " + saltSource.getSalt(null)); + LOGGER.debug("UNENCODED: " + motorist.getPassword()); + LOGGER.debug("ENCODED: " + encodedPassword); + + motorist.setPassword(encodedPassword); + return pjp.proceed(new Object[] {motorist}); +} + + // injected + private PasswordEncoder passwordEncoder; + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + + private SaltSource saltSource; + public void setSaltSource(SaltSource saltSource) { + this.saltSource = saltSource; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/DailyRantEmailJob.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/DailyRantEmailJob.java new file mode 100644 index 00000000..c01378be --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/DailyRantEmailJob.java @@ -0,0 +1,27 @@ +package com.roadrantz.service; + +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.scheduling.quartz.QuartzJobBean; + +/** + * A Quartz job bean to call the RantService's sendDailyRantEmails() method. + * + * As shown in Listing 12.4, page 460. + * + * @author craig.walls + */ +public class DailyRantEmailJob extends QuartzJobBean { + public DailyRantEmailJob() {} + + protected void executeInternal(JobExecutionContext jobContext) + throws JobExecutionException { + rantService.sendDailyRantEmails(); + } + + // injected + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/DailyRantEmailTask.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/DailyRantEmailTask.java new file mode 100644 index 00000000..8e9c604b --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/DailyRantEmailTask.java @@ -0,0 +1,24 @@ +package com.roadrantz.service; + +import java.util.TimerTask; + +/** + * Java timer task to call the RantService's sendDailyRantEmails. + * + * As shown in Listing 12.3, page 458. + * + * @author craig.walls + */ +public class DailyRantEmailTask extends TimerTask { + public DailyRantEmailTask() {} + + public void run() { + rantService.sendDailyRantEmails(); + } + + // injected + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/MotoristAlreadyExistsException.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/MotoristAlreadyExistsException.java new file mode 100644 index 00000000..f4dbaa03 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/MotoristAlreadyExistsException.java @@ -0,0 +1,5 @@ +package com.roadrantz.service; + +public class MotoristAlreadyExistsException extends Exception { + public MotoristAlreadyExistsException() {} +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/RantService.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/RantService.java new file mode 100644 index 00000000..460052e1 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/RantService.java @@ -0,0 +1,24 @@ +package com.roadrantz.service; + +import java.util.Date; +import java.util.List; + +import org.springframework.jmx.export.annotation.ManagedOperation; +import org.springframework.jmx.export.annotation.ManagedResource; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.Vehicle; + +@ManagedResource(objectName="rantz:name=RantService") // Annotation added in Listing 12.5 +public interface RantService { + public void addRant(Rant rant); + public List getRecentRants(); + public void addMotorist(Motorist motorist) throws MotoristAlreadyExistsException; + public List getRantsForVehicle(Vehicle vehicle); + public List getRantsForDay(Date date); + public void sendEmailForVehicle(Vehicle vehicle); + + @ManagedOperation(description="Send the daily rant e-mail.") // Annotation added in Listing 12.5 + public void sendDailyRantEmails(); +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/RantServiceImpl.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/RantServiceImpl.java new file mode 100644 index 00000000..39f7d2bd --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/RantServiceImpl.java @@ -0,0 +1,180 @@ +package com.roadrantz.service; + +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.management.Notification; + +import org.apache.commons.lang.StringUtils; +import org.springframework.jmx.export.notification.NotificationPublisher; +import org.springframework.jmx.export.notification.NotificationPublisherAware; +import org.springframework.mail.MailSender; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import com.roadrantz.dao.RantDao; +import com.roadrantz.domain.Motorist; +import com.roadrantz.domain.MotoristPrivilege; +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +@Transactional(propagation = Propagation.SUPPORTS, readOnly = true) +public class RantServiceImpl implements RantService, NotificationPublisherAware { + public RantServiceImpl() {} + + /** + * The addRant() method, as originally described in Listing 6.1. Eventually + * evolved to use the Transactional annotation in Listing 6.4. + */ + @Transactional(propagation = Propagation.REQUIRED) + public void addRant(Rant rant) { + rant.setPostedDate(new Date()); + + Vehicle rantVehicle = rant.getVehicle(); + + // check for existing vehicle with same plates + Vehicle existingVehicle = rantDao.findVehicleByPlate(rantVehicle + .getState(), rantVehicle.getPlateNumber()); + + if (existingVehicle != null) { + // associate existing vehicle with rant + rant.setVehicle(existingVehicle); + sendEmailForVehicle(existingVehicle); + } else { + rantDao.saveVehicle(rantVehicle); + } + + rantDao.saveRant(rant); + + if (notificationPublisher != null) { + notificationPublisher.sendNotification(new Notification("rantAdded", + this, 0)); + } + } + + public List getRecentRants() { + return rantDao.getAllRants(); + } + + @Transactional(propagation = Propagation.REQUIRED) + public void addMotorist(Motorist motorist) + throws MotoristAlreadyExistsException { + Motorist existingMotorist = rantDao.getMotoristByEmail(motorist + .getEmail()); + if (existingMotorist != null) { + throw new MotoristAlreadyExistsException(); + } + + MotoristPrivilege privilege = new MotoristPrivilege("MOTORIST"); + privilege.setMotorist(motorist); + motorist.getPrivileges().add(privilege); + + rantDao.saveMotorist(motorist); + + for (Vehicle vehicle : motorist.getVehicles()) { + Vehicle existingVehicle = rantDao.findVehicleByPlate(vehicle + .getState(), vehicle.getPlateNumber()); + + if (existingVehicle == null) { + vehicle.setMotorist(motorist); + rantDao.saveVehicle(vehicle); + } else { + motorist.getVehicles().remove(vehicle); + motorist.getVehicles().add(existingVehicle); + } + } + } + + private void checkForOneMillionthMotorist() { + if (notificationPublisher != null + && rantDao.getMotoristCount() == 1000000) { + notificationPublisher.sendNotification(new Notification( + "RantService.OneMillionMotorists", this, 0)); + } + } + + @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.READ_UNCOMMITTED, readOnly = true) + public List getRantsForVehicle(Vehicle requestedVehicle) { + Vehicle vehicle = rantDao.findVehicleByPlate(requestedVehicle.getState(), + requestedVehicle.getPlateNumber()); + + return vehicle.getRants(); + } + + public List getRantsForDay(Date day) { + return rantDao.getRantsForDay(day); + } + + /** + * Sends an e-mail to tell a motorist that they have new rants + * + * From Listing 12.1 + */ + public void sendEmailForVehicle(Vehicle vehicle) { + Motorist motorist = vehicle.getMotorist(); + if (motorist == null) { + return; + } + + SimpleMailMessage message = new SimpleMailMessage(mailMessage); + message.setTo(motorist.getEmail()); + + String text = message.getText(); + text = StringUtils.replace(text, "%STATE%", vehicle.getState()); + text = StringUtils.replace(text, "%PLATE%", vehicle.getPlateNumber()); + message.setText(text); + + mailSender.send(message); + } + + /** + * Sends a daily e-mail to motorists who have been ranted about. + * + * From Listing 12.2. + */ + public void sendDailyRantEmails() { + List rantsForToday = getRantsForDay(new Date()); + + Set vehiclesRantedAboutToday = new HashSet(); + + // extract vehicles and place into set (for uniqueness) + for (Rant rant : rantsForToday) { + vehiclesRantedAboutToday.add(rant.getVehicle()); + } + + for (Vehicle vehicle : vehiclesRantedAboutToday) { + sendEmailForVehicle(vehicle); + } + } + + // injected + private RantDao rantDao; + + public void setRantDao(RantDao rantDao) { + this.rantDao = rantDao; + } + + private MailSender mailSender; + + public void setMailSender(MailSender mailSender) { + this.mailSender = mailSender; + } + + private SimpleMailMessage mailMessage; + + public void setMailMessage(SimpleMailMessage mailMessage) { + this.mailMessage = mailMessage; + } + + // injected by JMX implementation + private NotificationPublisher notificationPublisher; + + public void setNotificationPublisher( + NotificationPublisher notificationPublisher) { + this.notificationPublisher = notificationPublisher; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/VehicleAlreadyExistsException.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/VehicleAlreadyExistsException.java new file mode 100644 index 00000000..03f7fe10 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/VehicleAlreadyExistsException.java @@ -0,0 +1,5 @@ +package com.roadrantz.service; + +public class VehicleAlreadyExistsException extends Exception { + public VehicleAlreadyExistsException() {} +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/ManagedCronTrigger.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/ManagedCronTrigger.java new file mode 100644 index 00000000..9deffdcb --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/ManagedCronTrigger.java @@ -0,0 +1,10 @@ +package com.roadrantz.service.mbean; + +import java.util.Date; + +public interface ManagedCronTrigger { + public void setCronExpression(String ce); + public String getCronExpression(); + public void setNextFireTime(Date date); + public Date getNextFireTime(); +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/ManagedRantService.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/ManagedRantService.java new file mode 100644 index 00000000..a002ba17 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/ManagedRantService.java @@ -0,0 +1,7 @@ +package com.roadrantz.service.mbean; + +import java.util.Date; + +public interface ManagedRantService { + public void sendDailyRantEmails(); +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/MyNotificationListener.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/MyNotificationListener.java new file mode 100644 index 00000000..c49de7b9 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/MyNotificationListener.java @@ -0,0 +1,13 @@ +package com.roadrantz.service.mbean; + +import javax.management.Notification; +import javax.management.NotificationListener; + +public class MyNotificationListener implements NotificationListener { + public MyNotificationListener() {} + + public void handleNotification(Notification notification, + Object handback) { + // do something + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/RantServiceRemoteMBean.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/RantServiceRemoteMBean.java new file mode 100644 index 00000000..bdfec12a --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/service/mbean/RantServiceRemoteMBean.java @@ -0,0 +1,5 @@ +package com.roadrantz.service.mbean; + +public interface RantServiceRemoteMBean { + public void sendDailyRantEmails(); +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/HomeAction.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/HomeAction.java new file mode 100644 index 00000000..96257274 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/HomeAction.java @@ -0,0 +1,38 @@ +package com.roadrantz.struts; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import com.roadrantz.service.RantService; + +public class HomeAction extends Action { + public ActionForward execute(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) + throws Exception { + + ApplicationContext ctx = + WebApplicationContextUtils.getRequiredWebApplicationContext( + getServlet().getServletContext()); + + RantService rantService = (RantService) ctx.getBean("rantService"); + + List recentRants = rantService.getRecentRants(); + request.setAttribute("rants", recentRants); + + return mapping.findForward("home"); + } + + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/RantsForVehicleAction.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/RantsForVehicleAction.java new file mode 100644 index 00000000..55d7b8e9 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/RantsForVehicleAction.java @@ -0,0 +1,36 @@ +package com.roadrantz.struts; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.springframework.web.struts.ActionSupport; + +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.RantService; + +public class RantsForVehicleAction extends ActionSupport { + public ActionForward execute(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) + throws Exception { + + VehicleForm vehicleForm = (VehicleForm) form; + Vehicle vehicle = vehicleForm.getVehicle(); + + RantService rantService = + (RantService) getWebApplicationContext().getBean("rantService"); + + request.setAttribute("rants", + rantService.getRantsForVehicle(vehicleForm.getVehicle())); + request.setAttribute("vehicle", vehicle); + + return mapping.findForward("rantList"); + } + + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/VehicleForm.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/VehicleForm.java new file mode 100644 index 00000000..c15fe2b3 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/struts/VehicleForm.java @@ -0,0 +1,20 @@ +package com.roadrantz.struts; + +import org.apache.struts.action.ActionForm; + +import com.roadrantz.domain.Vehicle; + +@SuppressWarnings("serial") +public class VehicleForm extends ActionForm { + public VehicleForm() {} + + private Vehicle vehicle; + + public Vehicle getVehicle() { + return vehicle; + } + + public void setVehicle(Vehicle vehicle) { + this.vehicle = vehicle; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/tapestry/HomePage.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/tapestry/HomePage.java new file mode 100644 index 00000000..29cfe6ec --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/tapestry/HomePage.java @@ -0,0 +1,21 @@ +package com.roadrantz.tapestry; + +import java.util.List; + +import org.apache.tapestry.annotations.InjectObject; +import org.apache.tapestry.html.BasePage; + +import com.roadrantz.domain.Rant; +import com.roadrantz.service.RantService; + +public abstract class HomePage extends BasePage { + @InjectObject("spring:rantService") + public abstract RantService getRantService(); + + public abstract Rant getRant(); + public abstract void setRant(Rant rant); + + public List getRants() { + return getRantService().getRecentRants(); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/tiles/HeaderTileController.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/tiles/HeaderTileController.java new file mode 100644 index 00000000..f95cde0a --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/tiles/HeaderTileController.java @@ -0,0 +1,37 @@ +package com.roadrantz.tiles; + +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.tiles.ComponentContext; +import org.springframework.web.servlet. + view.tiles.ComponentControllerSupport; +import com.roadrantz.domain.Motorist; +import com.roadrantz.service.RantService; + +public class HeaderTileController extends ComponentControllerSupport { + public HeaderTileController() {} + + protected void doPerform(ComponentContext componentContext, + HttpServletRequest request, HttpServletResponse response) + throws Exception { + + RantService rantService = getRantService(); + + int rantsToday = rantService.getRantsForDay(new Date()).size(); + componentContext.putAttribute("rantsToday", rantsToday); + + String state = "tx"; + Motorist driver = (Motorist)request.getSession().getAttribute("driver"); + if(driver != null) { + state = driver.getVehicles().get(0).getState(); + } + componentContext.putAttribute("driverState", state); + } + + private RantService getRantService() { + return (RantService) getApplicationContext().getBean("rantService"); + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/util/LoggingAdvisor.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/util/LoggingAdvisor.java new file mode 100644 index 00000000..66205a5f --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/util/LoggingAdvisor.java @@ -0,0 +1,22 @@ +package com.roadrantz.util; + +import org.apache.log4j.Logger; +import org.aspectj.lang.ProceedingJoinPoint; + +public class LoggingAdvisor { + private static final Logger LOGGER = + Logger.getLogger(LoggingAdvisor.class); + + public Object log(ProceedingJoinPoint pjp) throws Throwable { + LOGGER.error("**********************************************"); + LOGGER.error("LOGGING BEFORE: " + pjp.getSignature().toLongString()); + LOGGER.error("**********************************************"); + + Object result = pjp.proceed(); + LOGGER.error("**********************************************"); + LOGGER.error("LOGGING AFTER: " + pjp.getSignature().toLongString() + ", RETURNING: " + result); + LOGGER.error("**********************************************"); + + return result; + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/util/LoggingAspect.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/util/LoggingAspect.java new file mode 100644 index 00000000..566fdb76 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/util/LoggingAspect.java @@ -0,0 +1,32 @@ +package com.roadrantz.util; + +import org.apache.log4j.Logger; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; + +@Aspect +public class LoggingAspect { + private static final Logger LOGGER = Logger.getLogger(LoggingAspect.class); + + @Pointcut("execution(* org.acegisecurity.providers.encoding.Md5PasswordEncoder.*(..))") + public void Md5Methods() {} + + @Around("Md5Methods()") + public void logIt(ProceedingJoinPoint joinpoint) { + try { + LOGGER.error("**********************************"); + LOGGER.error(joinpoint.getSignature().toLongString()); + LOGGER.error("**********************************"); + Object o = joinpoint.proceed(); + LOGGER.error("**********************************"); + LOGGER.error("o: " + o); + LOGGER.error("**********************************"); + } catch (Throwable t) { + LOGGER.error("**********************************"); + LOGGER.error("t: " + t); + LOGGER.error("**********************************"); + } + } +} diff --git a/springInAction/RoadRantz/src/main/java/com/roadrantz/webwork/RantsForDayAction.java b/springInAction/RoadRantz/src/main/java/com/roadrantz/webwork/RantsForDayAction.java new file mode 100644 index 00000000..8e650830 --- /dev/null +++ b/springInAction/RoadRantz/src/main/java/com/roadrantz/webwork/RantsForDayAction.java @@ -0,0 +1,46 @@ +package com.roadrantz.webwork; + +import java.util.Date; +import java.util.List; + +import com.opensymphony.xwork.Action; +import com.roadrantz.domain.Rant; +import com.roadrantz.service.RantService; + +public class RantsForDayAction implements Action { + private int month; + private int day; + private int year; + private List rants; + + public String execute() throws Exception { + // Yeah...I know...it's deprecated...sorry. + // But I refuse to use the ridiculous Calendar class + Date date = new Date(month, day, year); + + rants = rantService.getRantsForDay(date); + + return SUCCESS; + } + + public List getRants() { + return rants; + } + + public void setDay(int day) { + this.day = day; + } + + public void setMonth(int month) { + this.month = month; + } + + public void setYear(int year) { + this.year = year; + } + + private RantService rantService; + public void setRantService(RantService rantService) { + this.rantService = rantService; + } +} diff --git a/springInAction/RoadRantz/src/main/resources/META-INF/persistence.xml b/springInAction/RoadRantz/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..542e3421 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,9 @@ + + + com.roadrantz.domain.Motorist + com.roadrantz.domain.Rant + com.roadrantz.domain.Vehicle + com.roadrantz.domain.MotoristPrivilege + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/motorist-sql.xml b/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/motorist-sql.xml new file mode 100644 index 00000000..91720a65 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/motorist-sql.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + call identity() + + + insert into Motorist (id, firstName, lastName, email, password) + values (null, #firstName#, #lastName#, #email#, #password#) + + diff --git a/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/rant-sql.xml b/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/rant-sql.xml new file mode 100644 index 00000000..403b2b5d --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/rant-sql.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + call identity() + + + insert into Rant (id, rantText, postedDate, vehicle_id) + values (null, #rantText#, #postedDate#, #vehicle.id#) + + diff --git a/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/vehicle-sql.xml b/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/vehicle-sql.xml new file mode 100644 index 00000000..85572732 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/com/roadrantz/domain/vehicle-sql.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + call identity() + + + insert into Vehicle (id, state, plateNumber) + values (null, #state#, #plateNumber#) + + diff --git a/springInAction/RoadRantz/src/main/resources/db.properties b/springInAction/RoadRantz/src/main/resources/db.properties new file mode 100644 index 00000000..98ab2943 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/db.properties @@ -0,0 +1,6 @@ +db.driver=org.hsqldb.jdbcDriver +db.url=jdbc:hsqldb:hsql://localhost/roadrantz/roadrantz +db.username=sa +db.password= + +hibernate.dialect=org.hibernate.dialect.HSQLDialect diff --git a/springInAction/RoadRantz/src/main/resources/ehcache.xml b/springInAction/RoadRantz/src/main/resources/ehcache.xml new file mode 100644 index 00000000..4d4de5e8 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/ehcache.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/errors.properties b/springInAction/RoadRantz/src/main/resources/errors.properties new file mode 100644 index 00000000..eb3e7de2 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/errors.properties @@ -0,0 +1,4 @@ +required.state=State is required. +required.plateNumber=License plate number is required. +required.rantText=Rant text is required. +invalid.plateNumber={0} is an invalid license plate number. \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/resources/log4j.properties b/springInAction/RoadRantz/src/main/resources/log4j.properties new file mode 100644 index 00000000..a75d81c0 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/log4j.properties @@ -0,0 +1,11 @@ +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=[%5p] %d{HH:mm:ss} %c{1} - %m%n + +log4j.rootLogger=WARN,stdout + +log4j.category.com.roadrantz=DEBUG +log4j.category.org.springframework=WARN +log4j.category.org.hibernate=WARN +log4j.category.org.acegisecurity=WARN +log4j.category.oracle.toplink=DEBUG diff --git a/springInAction/RoadRantz/src/main/resources/messages.properties b/springInAction/RoadRantz/src/main/resources/messages.properties new file mode 100644 index 00000000..729cc395 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/messages.properties @@ -0,0 +1,10 @@ +title.addRant=Add a rant + +field.state=State: +field.plateNumber=Plate #: +field.rantText:Rant text: +field.email=E-mail: +field.password=Password: +field.firstName=First: +field.lastName=Last: + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-cache.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-cache.xml new file mode 100644 index 00000000..423ffa0c --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-cache.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-data-hibernate.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-data-hibernate.xml new file mode 100644 index 00000000..e32f751f --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-data-hibernate.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + com.roadrantz.domain.Rant + com.roadrantz.domain.Motorist + com.roadrantz.domain.Vehicle + + + + + ${hibernate.dialect} + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-data-ibatis.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-data-ibatis.xml new file mode 100644 index 00000000..b41892cf --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-data-ibatis.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-data-jdbc.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-data-jdbc.xml new file mode 100644 index 00000000..321ba99c --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-data-jdbc.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-data-jpa-pure.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-data-jpa-pure.xml new file mode 100644 index 00000000..f23a7941 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-data-jpa-pure.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${db.driver} + ${db.url} + ${db.username} + ${db.password} + INFO + HSQL + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-data-jpa.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-data-jpa.xml new file mode 100644 index 00000000..ae502a60 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-data-jpa.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${db.driver} + ${db.url} + ${db.username} + ${db.password} + INFO + HSQL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-data.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-data.xml new file mode 100644 index 00000000..5ed8831c --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-data.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-email.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-email.xml new file mode 100644 index 00000000..af5e7515 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-email.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + ]]> + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-jms-common.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-jms-common.xml new file mode 100644 index 00000000..25231b7a --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-jms-common.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-jms.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-jms.xml new file mode 100644 index 00000000..d62dcda0 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-jms.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-mbeans.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-mbeans.xml new file mode 100644 index 00000000..3904765d --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-mbeans.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.roadrantz.service.mbean.ManagedRantService + com.roadrantz.service.mbean.ManagedCronTrigger + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-scheduler.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-scheduler.xml new file mode 100644 index 00000000..9c1775c0 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-scheduler.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-security.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-security.xml new file mode 100644 index 00000000..ff5087ba --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-security.xml @@ -0,0 +1,347 @@ + + + + + + + + + + + + CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + PATTERN_TYPE_APACHE_ANT + /**=channelProcessingFilter,concurrentSessionFilter,httpSessionIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT email as username, password, 'true' + FROM Motorist + WHERE email=? + + + + + SELECT email as username, privilege + FROM Motorist_Privileges mp, Motorist m + WHERE mp.motorist_id = m.id + AND m.email=? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + PATTERN_TYPE_APACHE_ANT + /booger.htm=ROLE_BOOGER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + PATTERN_TYPE_APACHE_ANT + /login.htm=REQUIRES_SECURE_CHANNEL + /j_acegi_security_check*=REQUIRES_SECURE_CHANNEL + /**=REQUIRES_INSECURE_CHANNEL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-services.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-services.xml new file mode 100644 index 00000000..b6f0f8dc --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-services.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-servlet.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-servlet.xml new file mode 100644 index 00000000..7f086f92 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-servlet.xml @@ -0,0 +1,162 @@ + + + + + + + + messages + errors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + motoristDetailForm + motoristVehicleForm + motoristConfirmation + redirect:home.htm + + + + + + + + + + + + + + + + loginController + homePageController + errorController + rantsForVehicleController + rantsForVehicleController + rantsForVehicleController + rantsForVehicleController + rantsForDayController + registerMotoristController + addRantController + + + + + + + + + + + + + + + + /WEB-INF/roadrantz-tiles.xml + + + + + + + + + + + + + + + + + + + + WEB-INF/validator-rules.xml + WEB-INF/validation.xml + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-struts.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-struts.xml new file mode 100644 index 00000000..14a9d59b --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-struts.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-transactions.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-transactions.xml new file mode 100644 index 00000000..ab948a88 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-transactions.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/resources/roadrantz-views.xml b/springInAction/RoadRantz/src/main/resources/roadrantz-views.xml new file mode 100644 index 00000000..3d8c1003 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/roadrantz-views.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/resources/sql-map-config.xml b/springInAction/RoadRantz/src/main/resources/sql-map-config.xml new file mode 100644 index 00000000..115628e3 --- /dev/null +++ b/springInAction/RoadRantz/src/main/resources/sql-map-config.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/freemarker/addRant.ftl b/springInAction/RoadRantz/src/main/webapp/WEB-INF/freemarker/addRant.ftl new file mode 100644 index 00000000..2c3ee76d --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/freemarker/addRant.ftl @@ -0,0 +1,22 @@ +<#import "/spring.ftl" as spring /> + + + Add Rant + + + + +

Enter a rant...

+
+ State: <@spring.formInput "rant.vehicle.state", "" />
+ Plate #: <@spring.formInput "rant.vehicle.plateNumber", "" />
+ <@spring.formTextarea "rant.rantText", "row='5' cols='50'" /> + +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/freemarker/home.ftl b/springInAction/RoadRantz/src/main/webapp/WEB-INF/freemarker/home.ftl new file mode 100644 index 00000000..e90428fa --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/freemarker/home.ftl @@ -0,0 +1,17 @@ + + Rantz + + +

Rantz:

+ + Add rant
+ Register new motorist
+
    + <#list rants as rant> +
  • ${rant.vehicle.state}/ + ${rant.vehicle.plateNumber} -- + ${rant.rantText} + +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/addRant.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/addRant.jsp new file mode 100644 index 00000000..456bc163 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/addRant.jsp @@ -0,0 +1,33 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="rr" tagdir="/WEB-INF/tags" %> + + + + Add Rant + + + + +

Enter a rant...

+ + + +
+ + +
+ +
+ + +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/error.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/error.jsp new file mode 100644 index 00000000..4370d521 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/error.jsp @@ -0,0 +1 @@ +

Error authorizing

\ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/footer.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/footer.jsp new file mode 100644 index 00000000..b1fa0425 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/footer.jsp @@ -0,0 +1,2 @@ +
+Copyright © <%= new java.util.Date().getYear() + 1900 %> RoadRantz.com \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/header.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/header.jsp new file mode 100644 index 00000000..b64cb29c --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/header.jsp @@ -0,0 +1,24 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="tiles" + uri="http://jakarta.apache.org/struts/tags-tiles" %> + + + + + + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/home.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/home.jsp new file mode 100644 index 00000000..5e6398d3 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/home.jsp @@ -0,0 +1,12 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +

Recent Rantz:

+ +
    + +
  • / + -- + + +
diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/login.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/login.jsp new file mode 100644 index 00000000..0226b71b --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/login.jsp @@ -0,0 +1,20 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + Login + + +
+ + Login failed...try again

+
+ +
+ Username:
+ Password:
+ Remember Me
+ +
+
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristConfirmation.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristConfirmation.jsp new file mode 100644 index 00000000..fabe4e12 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristConfirmation.jsp @@ -0,0 +1,28 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + + + + Motorist Confirmation + + + +

Motorist Confirmation Confirmation (Step 3 of 3)

+ + + Motorist:  
+ E-mail:
+ Vehicles:
+
    + +
  • -
  • +
    +
+ +

Click "Finish" to add motorist.

+   +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristDetailForm.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristDetailForm.jsp new file mode 100644 index 00000000..ae33b5ea --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristDetailForm.jsp @@ -0,0 +1,23 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + + + + Motorist Detail + + + +

Motorist info (Step 1 of 3)

+ + +
+
+ :
+
+
+ +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristVehicleForm.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristVehicleForm.jsp new file mode 100644 index 00000000..8cd028c1 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/motoristVehicleForm.jsp @@ -0,0 +1,36 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="rr" tagdir="/WEB-INF/tags" %> + + + + + Motorist Vehicles + + + +

Motorist Vehicles vehicles (Step 2 of 3)

+ + +
+ " />
+ Motorist Vehicles:  
+ E-mail:
+ Vehicles:
+
    + +
  • -
  • +
    +
+ +
+ State:
+ Plate:
+   +   + +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/rantAdded.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/rantAdded.jsp new file mode 100644 index 00000000..735ef50f --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/rantAdded.jsp @@ -0,0 +1,9 @@ + + Rant added + + +

Rant added

+ + Return to home + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/rantzTemplate.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/rantzTemplate.jsp new file mode 100644 index 00000000..19da5325 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/rantzTemplate.jsp @@ -0,0 +1,36 @@ +<%@ taglib prefix="tiles" + uri="http://jakarta.apache.org/struts/tags-tiles" %> +<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %> + + + + <tiles:getAsString name="title"/> + + + +
+
+ +
+ + + +
+ +
+ + +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/vehicleRants.jsp b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/vehicleRants.jsp new file mode 100644 index 00000000..10dc0439 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/jsp/vehicleRants.jsp @@ -0,0 +1,16 @@ +<%@ page contentType="text/html" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + Rantz For Vehicle + + +

Rantz for: ${vehicle.state} ${vehicle.plateNumber}

+ +
    + +
  • / -- + +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/roadrantz-tiles.xml b/springInAction/RoadRantz/src/main/webapp/WEB-INF/roadrantz-tiles.xml new file mode 100644 index 00000000..1ca0d558 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/roadrantz-tiles.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/tags/stateSelection.tag b/springInAction/RoadRantz/src/main/webapp/WEB-INF/tags/stateSelection.tag new file mode 100644 index 00000000..2f694ac2 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/tags/stateSelection.tag @@ -0,0 +1,56 @@ +<%@ attribute name="path" required="true" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/validation.xml b/springInAction/RoadRantz/src/main/webapp/WEB-INF/validation.xml new file mode 100644 index 00000000..6240f68a --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/validation.xml @@ -0,0 +1,26 @@ + + + + + +
+ + + + + + + + + + mask + ^[0-9A-Za-z]{2,6}$ + + +
+
+
diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/validator-rules.xml b/springInAction/RoadRantz/src/main/webapp/WEB-INF/validator-rules.xml new file mode 100644 index 00000000..b52811e6 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/validator-rules.xml @@ -0,0 +1,1044 @@ + + + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (trim(value).length == 0) { + + if (i == 0) { + focusField = field; + } + fields[i++] = oRequired[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + } + + // Trim whitespace from left and right sides of s. + function trim(s) { + return s.replace( /^\s*/, "" ).replace( /\s*$/, "" ); + } + + ]]> + + + + + + + + + + 0) && (field.value.length < iMin)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oMinLength[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + iMax) { + if (i == 0) { + focusField = field; + } + fields[i++] = oMaxLength[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + + 0)) { + + if (!matchPattern(field.value, oMasked[x][2]("mask"))) { + if (i == 0) { + focusField = field; + } + fields[i++] = oMasked[x][1]; + isValid = false; + } + } + } + + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + } + + function matchPattern(value, mask) { + return mask.exec(value); + }]]> + + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + if (!isAllDigits(value)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oByte[x][1]; + + } else { + + var iValue = parseInt(value); + if (isNaN(iValue) || !(iValue >= -128 && iValue <= 127)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oByte[x][1]; + bValid = false; + } + } + } + + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + }]]> + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + if (!isAllDigits(value)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oShort[x][1]; + + } else { + + var iValue = parseInt(value); + if (isNaN(iValue) || !(iValue >= -32768 && iValue <= 32767)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oShort[x][1]; + bValid = false; + } + } + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + }]]> + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + + if (!isAllDigits(value)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oInteger[x][1]; + + } else { + var iValue = parseInt(value); + if (isNaN(iValue) || !(iValue >= -2147483648 && iValue <= 2147483647)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oInteger[x][1]; + bValid = false; + } + } + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + function isAllDigits(argvalue) { + argvalue = argvalue.toString(); + var validChars = "0123456789"; + var startFrom = 0; + if (argvalue.substring(0, 2) == "0x") { + validChars = "0123456789abcdefABCDEF"; + startFrom = 2; + } else if (argvalue.charAt(0) == "0") { + validChars = "01234567"; + startFrom = 1; + } else if (argvalue.charAt(0) == "-") { + startFrom = 1; + } + + for (var n = startFrom; n < argvalue.length; n++) { + if (validChars.indexOf(argvalue.substring(n, n+1)) == -1) return false; + } + return true; + }]]> + + + + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + // remove '.' before checking digits + var tempArray = value.split('.'); + var joinedString= tempArray.join(''); + + if (!isAllDigits(joinedString)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oFloat[x][1]; + + } else { + var iValue = parseFloat(value); + if (isNaN(iValue)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oFloat[x][1]; + bValid = false; + } + } + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + }]]> + + + + + + + + + + + + 0) && + (datePattern.length > 0)) { + var MONTH = "MM"; + var DAY = "dd"; + var YEAR = "yyyy"; + var orderMonth = datePattern.indexOf(MONTH); + var orderDay = datePattern.indexOf(DAY); + var orderYear = datePattern.indexOf(YEAR); + if ((orderDay < orderYear && orderDay > orderMonth)) { + var iDelim1 = orderMonth + MONTH.length; + var iDelim2 = orderDay + DAY.length; + var delim1 = datePattern.substring(iDelim1, iDelim1 + 1); + var delim2 = datePattern.substring(iDelim2, iDelim2 + 1); + if (iDelim1 == orderDay && iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})(\\d{4})$"); + } else if (iDelim1 == orderDay) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$"); + } else if (iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$"); + } else { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$"); + } + var matched = dateRegexp.exec(value); + if(matched != null) { + if (!isValidDate(matched[2], matched[1], matched[3])) { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else if ((orderMonth < orderYear && orderMonth > orderDay)) { + var iDelim1 = orderDay + DAY.length; + var iDelim2 = orderMonth + MONTH.length; + var delim1 = datePattern.substring(iDelim1, iDelim1 + 1); + var delim2 = datePattern.substring(iDelim2, iDelim2 + 1); + if (iDelim1 == orderMonth && iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})(\\d{4})$"); + } else if (iDelim1 == orderMonth) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$"); + } else if (iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$"); + } else { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$"); + } + var matched = dateRegexp.exec(value); + if(matched != null) { + if (!isValidDate(matched[1], matched[2], matched[3])) { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else if ((orderMonth > orderYear && orderMonth < orderDay)) { + var iDelim1 = orderYear + YEAR.length; + var iDelim2 = orderMonth + MONTH.length; + var delim1 = datePattern.substring(iDelim1, iDelim1 + 1); + var delim2 = datePattern.substring(iDelim2, iDelim2 + 1); + if (iDelim1 == orderMonth && iDelim2 == orderDay) { + dateRegexp = new RegExp("^(\\d{4})(\\d{2})(\\d{2})$"); + } else if (iDelim1 == orderMonth) { + dateRegexp = new RegExp("^(\\d{4})(\\d{2})[" + delim2 + "](\\d{2})$"); + } else if (iDelim2 == orderDay) { + dateRegexp = new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})(\\d{2})$"); + } else { + dateRegexp = new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{2})$"); + } + var matched = dateRegexp.exec(value); + if(matched != null) { + if (!isValidDate(matched[3], matched[2], matched[1])) { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + function isValidDate(day, month, year) { + if (month < 1 || month > 12) { + return false; + } + if (day < 1 || day > 31) { + return false; + } + if ((month == 4 || month == 6 || month == 9 || month == 11) && + (day == 31)) { + return false; + } + if (month == 2) { + var leap = (year % 4 == 0 && + (year % 100 != 0 || year % 400 == 0)); + if (day>29 || (day == 29 && !leap)) { + return false; + } + } + return true; + }]]> + + + + + + + + + + + + + + + 0)) { + + var iMin = parseInt(oRange[x][2]("min")); + var iMax = parseInt(oRange[x][2]("max")); + var iValue = parseInt(field.value); + if (!(iValue >= iMin && iValue <= iMax)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oRange[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + 0)) { + + var fMin = parseFloat(oRange[x][2]("min")); + var fMax = parseFloat(oRange[x][2]("max")); + var fValue = parseFloat(field.value); + if (!(fValue >= fMin && fValue <= fMax)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oRange[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + 0)) { + if (!luhnCheck(form[oCreditCard[x][0]].value)) { + if (i == 0) { + focusField = form[oCreditCard[x][0]]; + } + fields[i++] = oCreditCard[x][1]; + bValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + /** + * Reference: http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl + */ + function luhnCheck(cardNumber) { + if (isLuhnNum(cardNumber)) { + var no_digit = cardNumber.length; + var oddoeven = no_digit & 1; + var sum = 0; + for (var count = 0; count < no_digit; count++) { + var digit = parseInt(cardNumber.charAt(count)); + if (!((count & 1) ^ oddoeven)) { + digit *= 2; + if (digit > 9) digit -= 9; + }; + sum += digit; + }; + if (sum == 0) return false; + if (sum % 10 == 0) return true; + }; + return false; + } + + function isLuhnNum(argvalue) { + argvalue = argvalue.toString(); + if (argvalue.length == 0) { + return false; + } + for (var n = 0; n < argvalue.length; n++) { + if ((argvalue.substring(n, n+1) < "0") || + (argvalue.substring(n,n+1) > "9")) { + return false; + } + } + return true; + }]]> + + + + + + + + 0)) { + if (!checkEmail(form[oEmail[x][0]].value)) { + if (i == 0) { + focusField = form[oEmail[x][0]]; + } + fields[i++] = oEmail[x][1]; + bValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + /** + * Reference: Sandeep V. Tamhankar (stamhankar@hotmail.com), + * http://javascript.internet.com + */ + function checkEmail(emailStr) { + if (emailStr.length == 0) { + return true; + } + var emailPat=/^(.+)@(.+)$/; + var specialChars="\\(\\)<>@,;:\\\\\\\"\\.\\[\\]"; + var validChars="\[^\\s" + specialChars + "\]"; + var quotedUser="(\"[^\"]*\")"; + var ipDomainPat=/^(\d{1,3})[.](\d{1,3})[.](\d{1,3})[.](\d{1,3})$/; + var atom=validChars + '+'; + var word="(" + atom + "|" + quotedUser + ")"; + var userPat=new RegExp("^" + word + "(\\." + word + ")*$"); + var domainPat=new RegExp("^" + atom + "(\\." + atom + ")*$"); + var matchArray=emailStr.match(emailPat); + if (matchArray == null) { + return false; + } + var user=matchArray[1]; + var domain=matchArray[2]; + if (user.match(userPat) == null) { + return false; + } + var IPArray = domain.match(ipDomainPat); + if (IPArray != null) { + for (var i = 1; i <= 4; i++) { + if (IPArray[i] > 255) { + return false; + } + } + return true; + } + var domainArray=domain.match(domainPat); + if (domainArray == null) { + return false; + } + var atomPat=new RegExp(atom,"g"); + var domArr=domain.match(atomPat); + var len=domArr.length; + if ((domArr[domArr.length-1].length < 2) || + (domArr[domArr.length-1].length > 3)) { + return false; + } + if (len < 2) { + return false; + } + return true; + }]]> + + + + + + + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/addRant.vm b/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/addRant.vm new file mode 100644 index 00000000..db7ce6bf --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/addRant.vm @@ -0,0 +1,21 @@ + + + Add Rant + + + + +

Enter a rant...

+
+ State: #springFormInput("rant.vehicle.state" "")
+ Plate #: #springFormInput("rant.vehicle.plateNumber" "")
+ #springFormTextarea("rant.rantText" "row='5' cols='50'") + +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/home.vm b/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/home.vm new file mode 100644 index 00000000..139d6327 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/home.vm @@ -0,0 +1,17 @@ + + Rantz + + +

Rantz:

+ + Add rant
+ Register new motorist
+
    + #foreach($rant in $rants) +
  • ${rant.vehicle.state}/ + ${rant.vehicle.plateNumber} -- + ${rant.rantText} + #end +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/vehicleRants.vm b/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/vehicleRants.vm new file mode 100644 index 00000000..377dc73d --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/velocity/vehicleRants.vm @@ -0,0 +1,15 @@ + + Rantz For Vehicle + + +

Rantz for: ${vehicle.state} ${vehicle.plateNumber}

+ +
    + #foreach($rant in $rants) +
  • ${rant.vehicle.state}/ + ${rant.vehicle.plateNumber} -- + ${rant.rantText} + #end +
+ + diff --git a/springInAction/RoadRantz/src/main/webapp/WEB-INF/web.xml b/springInAction/RoadRantz/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..b454eaef --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,81 @@ + + + + + + contextConfigLocation + + classpath:roadrantz-security.xml + classpath:roadrantz-services.xml + classpath:roadrantz-email.xml + classpath:roadrantz-data.xml + classpath:roadrantz-data-jpa-pure.xml + classpath:roadrantz-transactions.xml + classpath:roadrantz-cache.xml + classpath:roadrantz-mbeans.xml + + + + + + org.springframework.web.context.ContextLoaderListener + + + + org.acegisecurity.ui.session.HttpSessionEventPublisher + + + + roadrantz + org.springframework.web.servlet.DispatcherServlet + + + contextConfigLocation + classpath:roadrantz-servlet.xml + + 1 + + + + roadrantz + *.htm + + + + roadrantz + *.rss + + + + roadrantz + *.xls + + + + roadrantz + *.pdf + + + + + Acegi Filter Chain Proxy + org.acegisecurity.util.FilterToBeanProxy + + targetClass + org.acegisecurity.util.FilterChainProxy + + + + Acegi Filter Chain Proxy + /* + + + index.html + + diff --git a/springInAction/RoadRantz/src/main/webapp/css/main.css b/springInAction/RoadRantz/src/main/webapp/css/main.css new file mode 100644 index 00000000..c4e9f92e --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/css/main.css @@ -0,0 +1,46 @@ +body { + font-family: "Lucida Grande", verdana, arial, helvetica, sans-serif; + font-size: 9pt; + background-color: #000033; + margin-top: 0px; + text-align: center; +} + +div#container { + margin-left: 10px; + text-align: left; +} + +.header { + width:748px; + background-image: url("../images/traffic-strip3.jpg"); + background-repeat: repeat-x; + background-color: #ffffff; + border-bottom: 1px, dotted, #660000; + font-size: 8pt; + color: #FFFFFF; +} + +.menuBar { + background-color: #660000; + color: #FFFFFF; + width:748px; +} + +.menuBar a { + color: #FFFFFF; + text-decoration: none; + font-weight: bold; + vertical-align: middle; +} + +.contentArea { + background-color: #FFFFFF; + width:748px; +} + +.footer { + width:748px; + background-color: #660000; + color: #FFFFFF; +} diff --git a/springInAction/RoadRantz/src/main/webapp/images/grgrad.gif b/springInAction/RoadRantz/src/main/webapp/images/grgrad.gif new file mode 100644 index 00000000..72a0d3ee Binary files /dev/null and b/springInAction/RoadRantz/src/main/webapp/images/grgrad.gif differ diff --git a/springInAction/RoadRantz/src/main/webapp/images/rantz-logo.png b/springInAction/RoadRantz/src/main/webapp/images/rantz-logo.png new file mode 100644 index 00000000..3a143fc8 Binary files /dev/null and b/springInAction/RoadRantz/src/main/webapp/images/rantz-logo.png differ diff --git a/springInAction/RoadRantz/src/main/webapp/images/rantz-tx-2.jpg b/springInAction/RoadRantz/src/main/webapp/images/rantz-tx-2.jpg new file mode 100644 index 00000000..6befc541 Binary files /dev/null and b/springInAction/RoadRantz/src/main/webapp/images/rantz-tx-2.jpg differ diff --git a/springInAction/RoadRantz/src/main/webapp/images/rantz-tx.jpg b/springInAction/RoadRantz/src/main/webapp/images/rantz-tx.jpg new file mode 100644 index 00000000..88d4f5c7 Binary files /dev/null and b/springInAction/RoadRantz/src/main/webapp/images/rantz-tx.jpg differ diff --git a/springInAction/RoadRantz/src/main/webapp/images/traffic-strip2.jpg b/springInAction/RoadRantz/src/main/webapp/images/traffic-strip2.jpg new file mode 100644 index 00000000..08bb5745 Binary files /dev/null and b/springInAction/RoadRantz/src/main/webapp/images/traffic-strip2.jpg differ diff --git a/springInAction/RoadRantz/src/main/webapp/images/traffic-strip3.jpg b/springInAction/RoadRantz/src/main/webapp/images/traffic-strip3.jpg new file mode 100644 index 00000000..4b55d881 Binary files /dev/null and b/springInAction/RoadRantz/src/main/webapp/images/traffic-strip3.jpg differ diff --git a/springInAction/RoadRantz/src/main/webapp/index.html b/springInAction/RoadRantz/src/main/webapp/index.html new file mode 100644 index 00000000..22305882 --- /dev/null +++ b/springInAction/RoadRantz/src/main/webapp/index.html @@ -0,0 +1,14 @@ + + + Spring Training + + + + + + + \ No newline at end of file diff --git a/springInAction/RoadRantz/src/test/java/com/roadrantz/mvc/RantsForVehicleControllerTest.java b/springInAction/RoadRantz/src/test/java/com/roadrantz/mvc/RantsForVehicleControllerTest.java new file mode 100644 index 00000000..8e48bb12 --- /dev/null +++ b/springInAction/RoadRantz/src/test/java/com/roadrantz/mvc/RantsForVehicleControllerTest.java @@ -0,0 +1,99 @@ +package com.roadrantz.mvc; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import junit.framework.TestCase; + +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.web.servlet.ModelAndView; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.RantService; + +/** + * Tests RantsForVehicleController + * + * From Listing B.1 + * + * @author wallsc + */ +public class RantsForVehicleControllerTest extends TestCase { + private static final String TEST_STATE = "TX"; + private static final String TEST_PLATE_NUMBER = "ABC123"; + private RantsForVehicleController controller; + + public RantsForVehicleControllerTest() {} + + /** + * Setups up the test with a mock rant service. + * + * From Listing B.2 + */ + @Override + protected void setUp() throws Exception { + controller = new RantsForVehicleController(); + controller.setCommandClass(Vehicle.class); + RantService rantService = createMock(RantService.class); + Vehicle testVehicle = new Vehicle(); + testVehicle.setState(TEST_STATE); + testVehicle.setPlateNumber(TEST_PLATE_NUMBER); + List expectedRants = new ArrayList(); + Rant rant = new Rant(); + rant.setVehicle(testVehicle); + rant.setRantText("Rant 1"); + expectedRants.add(rant); + rant = new Rant(); + rant.setVehicle(testVehicle); + rant.setRantText("Rant 2"); + expectedRants.add(rant); + expect(rantService.getRantsForVehicle(testVehicle)).andReturn( + expectedRants); + replay(rantService); + controller.setRantService(rantService); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSimpleCase() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.addParameter("state", TEST_STATE); + request.addParameter("plateNumber", TEST_PLATE_NUMBER); + request + .setRequestURI("http://localhost:8080/roadrantz/rantsForVehicle.htm"); + HttpServletResponse response = new MockHttpServletResponse(); + + ModelAndView modelAndView = controller.handleRequest(request, response); + assertNotNull("ModelAndView should not be null", modelAndView); + assertEquals("View name should be 'vehicleRants'", "vehicleRants", + modelAndView.getViewName()); + Map model = modelAndView.getModel(); + assertTrue("Model should contain 'rants' key", model.containsKey("rants")); + List rants = (List) model.get("rants"); + assertNotNull("Model element 'rants' should not be null", rants); + assertEquals("Model element 'rants' should contain 2 items", 2, rants + .size()); + for (Iterator iter = rants.iterator(); iter.hasNext();) { + Rant rant = (Rant) iter.next(); + assertEquals("Rant's Vehicle state is incorrect", TEST_STATE, rant + .getVehicle().getState()); + assertEquals("Rant's Vehicle plateNumber is incorrect", + TEST_PLATE_NUMBER, rant.getVehicle() + .getPlateNumber()); + } + } +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/test/java/com/roadrantz/mvc/RantsForVehicleControllerTest2.java b/springInAction/RoadRantz/src/test/java/com/roadrantz/mvc/RantsForVehicleControllerTest2.java new file mode 100644 index 00000000..2f85e334 --- /dev/null +++ b/springInAction/RoadRantz/src/test/java/com/roadrantz/mvc/RantsForVehicleControllerTest2.java @@ -0,0 +1,92 @@ +package com.roadrantz.mvc; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.web.AbstractModelAndViewTests; +import org.springframework.web.servlet.ModelAndView; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; +import com.roadrantz.service.RantService; + +/** + * Tests RantsForVehicleController + * + * Originally from Listing B.1, but tweaked to extend AbstractModelAndViewTest + * on page 691. + * + * @author wallsc + */ +public class RantsForVehicleControllerTest2 extends AbstractModelAndViewTests { + private static final String TEST_STATE = "TX"; + private static final String TEST_PLATE_NUMBER = "ABC123"; + private RantsForVehicleController controller; + + public RantsForVehicleControllerTest2() {} + + private List expectedRants; + + /** + * Setups up the test with a mock rant service. + * + * From Listing B.2 + */ + @Override + protected void setUp() throws Exception { + controller = new RantsForVehicleController(); + controller.setCommandClass(Vehicle.class); + RantService rantService = createMock(RantService.class); + Vehicle testVehicle = new Vehicle(); + testVehicle.setState(TEST_STATE); + testVehicle.setPlateNumber(TEST_PLATE_NUMBER); + expectedRants = new ArrayList(); + Rant rant = new Rant(); + rant.setVehicle(testVehicle); + rant.setRantText("Rant 1"); + expectedRants.add(rant); + rant = new Rant(); + rant.setVehicle(testVehicle); + rant.setRantText("Rant 2"); + expectedRants.add(rant); + expect(rantService.getRantsForVehicle(testVehicle)).andReturn( + expectedRants); + replay(rantService); + controller.setRantService(rantService); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSimpleCase() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + request.addParameter("state", TEST_STATE); + request.addParameter("plateNumber", TEST_PLATE_NUMBER); + request + .setRequestURI("http://localhost:8080/roadrantz/rantsForVehicle.htm"); + HttpServletResponse response = new MockHttpServletResponse(); + ModelAndView modelAndView = controller.handleRequest(request, response); + Rant rant = new Rant(); + rant.setId(1); + Vehicle vehicle = new Vehicle(); + vehicle.setState("TX"); + vehicle.setPlateNumber("ABC123"); + rant.setVehicle(vehicle); + rant.setRantText("This is a test rant"); + assertNotNull("ModelAndView should not be null", modelAndView); + assertViewName(modelAndView, "vehicleRants"); + assertModelAttributeAvailable(modelAndView, "rants"); + assertCompareListModelAttribute(modelAndView, "rants", expectedRants); + } +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest.java b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest.java new file mode 100644 index 00000000..f242982b --- /dev/null +++ b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest.java @@ -0,0 +1,42 @@ +package com.roadrantz.service; + +import java.util.List; + +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * Tests the RantService from the Spring context along with its dependencies. + * Strictly speaking, this is an integration test, not a unit-test, as it tests + * the service and its dependencies, as wired in Spring. + * + * Listing B.3 + * + * @author wallsc + */ +public class RantServiceTest extends + AbstractDependencyInjectionSpringContextTests { + public RantServiceTest() {} + + @Override + protected String[] getConfigLocations() { + return new String[] { "roadrantz-services.xml", "roadrantz-data.xml", + "roadrantz-data-jdbc.xml", "roadrantz-email.xml" }; + } + + public void testAddRant() throws Exception { + RantService rantService = (RantService) applicationContext + .getBean("rantService"); + Rant newRant = new Rant(); + newRant.setRantText("TEST RANT TEXT"); + Vehicle vehicle = new Vehicle(); + vehicle.setPlateNumber("ABC123"); + vehicle.setState("TX"); + newRant.setVehicle(vehicle); + rantService.addRant(newRant); + List rants = rantService.getRantsForVehicle(vehicle); + assertTrue(rants.contains(newRant)); + } +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest2.java b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest2.java new file mode 100644 index 00000000..622fd4ed --- /dev/null +++ b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest2.java @@ -0,0 +1,41 @@ +package com.roadrantz.service; + +import java.util.List; + +import org.springframework.test.AbstractTransactionalSpringContextTests; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * Tests the RantService from the Spring context along with its dependencies. + * Strictly speaking, this is an integration test, not a unit-test, as it tests + * the service and its dependencies, as wired in Spring. + * + * Listing B.4 + * + * @author wallsc + */ +public class RantServiceTest2 extends AbstractTransactionalSpringContextTests { + public RantServiceTest2() {} + + @Override + protected String[] getConfigLocations() { + return new String[] { "roadrantz-services.xml", "roadrantz-data.xml", + "roadrantz-data-jdbc.xml", "roadrantz-email.xml" }; + } + + public void testAddRant() throws Exception { + RantService rantService = (RantService) applicationContext + .getBean("rantService"); + Rant newRant = new Rant(); + newRant.setRantText("TEST RANT TEXT"); + Vehicle vehicle = new Vehicle(); + vehicle.setPlateNumber("FOOBAR"); + vehicle.setState("TX"); + newRant.setVehicle(vehicle); + rantService.addRant(newRant); + List rants = rantService.getRantsForVehicle(vehicle); + assertTrue(rants.contains(newRant)); + } +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest3.java b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest3.java new file mode 100644 index 00000000..a0b3101f --- /dev/null +++ b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest3.java @@ -0,0 +1,50 @@ +package com.roadrantz.service; + +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * Tests the RantService from the Spring context along with its dependencies. + * Strictly speaking, this is an integration test, not a unit-test, as it tests + * the service and its dependencies, as wired in Spring. + * + * This version adds transactional support to the test, ensuring that any + * changes to the DB get rolled back after each test (assuming that the DB + * supports rollbacks). + * + * Listing B.5 + * + * @author wallsc + */ +public class RantServiceTest3 extends + AbstractTransactionalDataSourceSpringContextTests { + public RantServiceTest3() {} + + @Override + protected String[] getConfigLocations() { + return new String[] { "roadrantz-services.xml", "roadrantz-data.xml", + "roadrantz-data-jdbc.xml", "roadrantz-email.xml" }; + } + + public void testAddRant() throws Exception { + RantService rantService = (RantService) applicationContext + .getBean("rantService"); + Rant newRant = new Rant(); + newRant.setRantText("TEST RANT TEXT"); + Vehicle vehicle = new Vehicle(); + vehicle.setPlateNumber("FOOBAR"); + vehicle.setState("TX"); + newRant.setVehicle(vehicle); + int before = jdbcTemplate.queryForInt("select count(*) from rant"); + rantService.addRant(newRant); + int after = jdbcTemplate.queryForInt("select count(*) from rant"); + assertEquals("There should be one more row in rant table.", after, + before + 1); + String testRantText = (String) jdbcTemplate.queryForObject( + "select rantText from rant where id=?", + new Object[] { newRant.getId() }, String.class); + assertEquals("TEST RANT TEXT", testRantText); + } +} \ No newline at end of file diff --git a/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest4.java.gienah b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest4.java.gienah new file mode 100644 index 00000000..00414dab --- /dev/null +++ b/springInAction/RoadRantz/src/test/java/com/roadrantz/service/RantServiceTest4.java.gienah @@ -0,0 +1,47 @@ +package com.roadrantz.service; + +import java.util.List; + +import junit.framework.Assert; + +import org.springframework.transaction.annotation.Transactional; + +import com.roadrantz.domain.Rant; +import com.roadrantz.domain.Vehicle; + +/** + * Tests the RantService from the Spring context along with its dependencies. + * Strictly speaking, this is an integration test, not a unit-test, as it tests + * the service and its dependencies, as wired in Spring. + * + * This version uses Gienah Testing to be able to take advantage of JUnit 4. + * + * Listing B.6 + * + * @author wallsc + */ +@RunWith(value = SpringRunner.class) +@Configuration(locations = { "/src/main/webapp/WEB-INF/roadrantz-services.xml", + "/src/main/webapp/WEB-INF/roadrantz-data.xml" }) +public class RantServiceTest4 { + + @Dependency + public RantService rantService; + + @Transactional + @Test + public void testAddRant() throws Exception { + + Rant newRant = new Rant(); + newRant.setRantText("TEST RANT TEXT"); + Vehicle vehicle = new Vehicle(); + vehicle.setPlateNumber("ABC123"); + vehicle.setState("TX"); + newRant.setVehicle(vehicle); + rantService.addRant(newRant); + + List rants = rantService.getRantsForVehicle(vehicle); + + Assert.assertTrue(rants.contains(newRant)); + } +} diff --git a/springInAction/RoadRantz/startdb.bat b/springInAction/RoadRantz/startdb.bat new file mode 100644 index 00000000..ad3be995 --- /dev/null +++ b/springInAction/RoadRantz/startdb.bat @@ -0,0 +1,4 @@ +hsqlPath=c:/roadrantz/roadrantz +hsqlName=roadrantz +java -cp c:/downloads/spring-framework-2.0.6/lib/hsqldb/hsqldb.jar org.hsqldb.Server -database.0 $hsqlPath -dbname.0 $hsqlName & + diff --git a/springInAction/RoadRantz/startdb.sh b/springInAction/RoadRantz/startdb.sh new file mode 100644 index 00000000..751e17d3 --- /dev/null +++ b/springInAction/RoadRantz/startdb.sh @@ -0,0 +1,5 @@ +#!/bin/sh +hsqlPath=/Users/wallsc/db/roadrantz/roadrantz +hsqlName=roadrantz +java -cp $SPRING_HOME/lib/hsqldb/hsqldb.jar org.hsqldb.Server -database.0 $hsqlPath -dbname.0 $hsqlName & + diff --git a/springInAction/pom.xml b/springInAction/pom.xml new file mode 100644 index 00000000..c2d62b7c --- /dev/null +++ b/springInAction/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + com.springinaction + sia + 2.0 + pom + Spring in Action 2E, Examples + http://www.springframework.org/osgi + + + 2.0.6 + + + + + org.springframework + spring + ${spring.version} + compile + + + log4j + log4j + 1.2.13 + compile + + + junit + junit + 3.8.1 + test + + + junit-addons + junit-addons + 1.4 + test + + + + + Chapter01 + Chapter02 + Chapter03 + Chapter04 + Chapter09 + Chapter16 + RoadRantz + + \ No newline at end of file