From 7ff88026bb0684bb829c960ae14ae667e40f3178 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 18:22:46 +0800 Subject: [PATCH 01/22] Updated README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 24735a590..cb11999e5 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,12 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi * [Null Object](#null-object) * [Callback](#callback) +### Presentation Tier Pattern + +Presentation Tier patterns are the top-most level of the application, this is concerned with translating tasks and results to something the user can understand. + +* [Intercepting Filter](#intercepting-filter) + ## Abstract Factory [↑](#list-of-design-patterns) **Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes. From 97c5c13f2d8d075e79f7f50c7ee58ecb782f0d21 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 18:27:01 +0800 Subject: [PATCH 02/22] Updated README.md --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index cb11999e5..4806b01c6 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,19 @@ Presentation Tier patterns are the top-most level of the application, this is co * [Intercepting Filter](#intercepting-filter) +## Intercepting Filter [↑](#list-of-design-patterns) +**Intent:** Provide an interfa + +![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/abstract-factory/etc/abstract-factory_1.png "Abstract Factory") + +**Applicability:** Use the Intercepting Filter pattern when +* Used when system uses pre-processing or post-processing requests +* a family of related product objects is designed to be used together, and you need to enforce this constraint +* you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations + +**Real world examples:** +* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) + ## Abstract Factory [↑](#list-of-design-patterns) **Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes. From f64480d7316c8c9862902562ca7df0e49d08d9e0 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 18:35:55 +0800 Subject: [PATCH 03/22] Updated README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4806b01c6..2be8eecd2 100644 --- a/README.md +++ b/README.md @@ -59,14 +59,14 @@ Presentation Tier patterns are the top-most level of the application, this is co * [Intercepting Filter](#intercepting-filter) ## Intercepting Filter [↑](#list-of-design-patterns) -**Intent:** Provide an interfa +**Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target -![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/abstract-factory/etc/abstract-factory_1.png "Abstract Factory") +![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/abstract-factory/etc/abstract-factory_1.png "Intercepting Filter") **Applicability:** Use the Intercepting Filter pattern when -* Used when system uses pre-processing or post-processing requests -* a family of related product objects is designed to be used together, and you need to enforce this constraint -* you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations +* a system uses pre-processing or post-processing requests +* a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers +* you want a modular approach to configuring pre-processing and post-processing schemes **Real world examples:** * [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) From efb032adbbfb755c6899cea22eb4e87323a6f3c2 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 18:36:15 +0800 Subject: [PATCH 04/22] Updated README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 2be8eecd2..71225c87f 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,6 @@ Presentation Tier patterns are the top-most level of the application, this is co * a system uses pre-processing or post-processing requests * a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers * you want a modular approach to configuring pre-processing and post-processing schemes - **Real world examples:** * [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) From b4aed8fbe0944b5783d2ea92284c5ba04e7efa02 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:21:10 +0800 Subject: [PATCH 05/22] Updated README.md --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 71225c87f..ddfd3f30c 100644 --- a/README.md +++ b/README.md @@ -56,19 +56,6 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi Presentation Tier patterns are the top-most level of the application, this is concerned with translating tasks and results to something the user can understand. -* [Intercepting Filter](#intercepting-filter) - -## Intercepting Filter [↑](#list-of-design-patterns) -**Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target - -![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/abstract-factory/etc/abstract-factory_1.png "Intercepting Filter") - -**Applicability:** Use the Intercepting Filter pattern when -* a system uses pre-processing or post-processing requests -* a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers -* you want a modular approach to configuring pre-processing and post-processing schemes -**Real world examples:** -* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) ## Abstract Factory [↑](#list-of-design-patterns) **Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes. @@ -439,6 +426,19 @@ Presentation Tier patterns are the top-most level of the application, this is co **Applicability:** Use the Callback pattern when * When some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity. +* [Intercepting Filter](#intercepting-filter) + +## Intercepting Filter [↑](#list-of-design-patterns) +**Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target + +![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/abstract-factory/etc/abstract-factory_1.png "Intercepting Filter") + +**Applicability:** Use the Intercepting Filter pattern when +* a system uses pre-processing or post-processing requests +* a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers +* you want a modular approach to configuring pre-processing and post-processing schemes + + # Frequently asked questions From 543c062066080115ad333435fb7fed08ef3997a4 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:21:23 +0800 Subject: [PATCH 06/22] Updated README.md From 4118aab1396449f5cfb50df30abed99903e9c116 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:22:23 +0800 Subject: [PATCH 07/22] Updated README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index ddfd3f30c..ef5412a37 100644 --- a/README.md +++ b/README.md @@ -426,8 +426,6 @@ Presentation Tier patterns are the top-most level of the application, this is co **Applicability:** Use the Callback pattern when * When some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity. -* [Intercepting Filter](#intercepting-filter) - ## Intercepting Filter [↑](#list-of-design-patterns) **Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target From 092e6ef9c13feb1e58ea528745a3fd04c6afa7d1 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:22:34 +0800 Subject: [PATCH 08/22] Updated README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ef5412a37..24dcc7052 100644 --- a/README.md +++ b/README.md @@ -437,7 +437,6 @@ Presentation Tier patterns are the top-most level of the application, this is co * you want a modular approach to configuring pre-processing and post-processing schemes - # Frequently asked questions **Q: What is the difference between State and Strategy patterns?** From 915145e12a9fb30cfc19f6dd1bffd4e6194a02d6 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:22:54 +0800 Subject: [PATCH 09/22] Updated README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 24dcc7052..f8f65514c 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi * [Null Object](#null-object) * [Callback](#callback) -### Presentation Tier Pattern +### Presentation Tier Patterns Presentation Tier patterns are the top-most level of the application, this is concerned with translating tasks and results to something the user can understand. @@ -436,7 +436,6 @@ Presentation Tier patterns are the top-most level of the application, this is co * a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers * you want a modular approach to configuring pre-processing and post-processing schemes - # Frequently asked questions **Q: What is the difference between State and Strategy patterns?** From 5e939a2d8bbd518038e4f74ee85780cdf15d37cd Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:23:14 +0800 Subject: [PATCH 10/22] Updated README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f8f65514c..c48d202cc 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi Presentation Tier patterns are the top-most level of the application, this is concerned with translating tasks and results to something the user can understand. +* [Intercepting Filter](#intercepting-filter) ## Abstract Factory [↑](#list-of-design-patterns) **Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes. From 24ea7ff325217bf0b4a9110a21d730963f556ff8 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:23:36 +0800 Subject: [PATCH 11/22] Updated README.md From bc98c11d94a439fcad5c0a918d9690f577689d1d Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:24:08 +0800 Subject: [PATCH 12/22] Updated README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c48d202cc..20db2d8f6 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Presentation Tier patterns are the top-most level of the application, this is co * [Intercepting Filter](#intercepting-filter) + ## Abstract Factory [↑](#list-of-design-patterns) **Intent:** Provide an interface for creating families of related or dependent objects without specifying their concrete classes. From aca75584d7fbf384b9462b67710b7d59d1590629 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 20:55:13 +0800 Subject: [PATCH 13/22] Updated README.md --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 20db2d8f6..6e6f4b732 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # Design pattern samples in Java. ## Build status: @@ -431,7 +430,7 @@ Presentation Tier patterns are the top-most level of the application, this is co ## Intercepting Filter [↑](#list-of-design-patterns) **Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target -![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/abstract-factory/etc/abstract-factory_1.png "Intercepting Filter") +![alt text](https://github.com/joshzambales/java-design-patterns/blob/master/intercepting-filter/etc/intercepting-filter.png "Intercepting Filter") **Applicability:** Use the Intercepting Filter pattern when * a system uses pre-processing or post-processing requests @@ -461,7 +460,7 @@ The difference is the intent of the patterns. While Proxy controls access to the 1. Fork the repository. 2. Implement the code changes in your fork. Remember to add sufficient comments documenting the implementation. 3. Create a simple class diagram from your example code. -4. Add description of the pattern in README.md and link to the class diagram. +4. Add description of the pattern in README.md and link to the class diagram. 5. Create a pull request. **For creating/editing UML diagrams** you need one of the following: @@ -482,9 +481,9 @@ The difference is the intent of the patterns. While Proxy controls access to the * [Let’s Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf) * [Pattern Languages of Program Design](http://www.amazon.com/Pattern-Languages-Program-Design-Coplien/dp/0201607344/ref=sr_1_1) * [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html) - - +* [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm) +* [Presentation Tier Pattern](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns) # License -This project is licensed under the terms of the MIT license. +This project is licensed under the terms of the MIT license. \ No newline at end of file From 2392d6caac000a4095ea083a905f83700de9d6eb Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 3 Apr 2015 22:24:37 +0800 Subject: [PATCH 14/22] added intercepting filter and changes --- .../etc/Intercepting-filter.png | Bin 0 -> 83868 bytes intercepting-filter/pom.xml | 74 ++++++ intercepting-filter/src/main/App.java | 245 ++++++++++++++++++ 3 files changed, 319 insertions(+) create mode 100644 intercepting-filter/etc/Intercepting-filter.png create mode 100644 intercepting-filter/pom.xml create mode 100644 intercepting-filter/src/main/App.java diff --git a/intercepting-filter/etc/Intercepting-filter.png b/intercepting-filter/etc/Intercepting-filter.png new file mode 100644 index 0000000000000000000000000000000000000000..5a97db09caff4d0e49505e5b55f7286230056c0a GIT binary patch literal 83868 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 + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.0-SNAPSHOT + pom + + + UTF-8 + + + abstract-factory + builder + factory-method + prototype + singleton + adapter + bridge + composite + decorator + facade + flyweight + proxy + chain + command + interpreter + iterator + mediator + memento + model-view-presenter + observer + state + strategy + template-method + visitor + double-checked-locking + servant + service-locator + null-object + event-aggregator + callback + execute-around + property + + + + + + junit + junit + 4.11 + test + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.0 + + 1.7 + 1.7 + + + + + + \ No newline at end of file diff --git a/intercepting-filter/src/main/App.java b/intercepting-filter/src/main/App.java new file mode 100644 index 000000000..a41e623bc --- /dev/null +++ b/intercepting-filter/src/main/App.java @@ -0,0 +1,245 @@ + import java.util.*; +import javax.swing.*; +import javax.swing.table.*; +import java.awt.*; +import java.awt.event.*; +public class App{ + public static void main(String[] args){ + FilterManager filterManager = new FilterManager(new Target()); + filterManager.setFilter(new NameFilter()); + filterManager.setFilter(new ContactFilter()); + filterManager.setFilter(new AddressFilter()); + filterManager.setFilter(new DepositFilter()); + filterManager.setFilter(new OrderFilter()); + + Client client = new Client(); + client.setFilterManager(filterManager); + } +} + +interface Filter{ + public String execute(String[] request); +} + +class NameFilter implements Filter{ + public String execute(String[] request){ + if(request[0].equals("") || request[0].matches(".*[^\\w|\\s]+.*")){ + return null; + }else return request[0]; + } +} + +class ContactFilter implements Filter{ + public String execute(String[] request){ + if(request[1].equals("") || request[1].matches(".*[^\\d]+.*") || request[1].length() != 11){ + return null; + }else return request[1]; + } +} + +class AddressFilter implements Filter{ + public String execute(String[] request){ + if(request[2].equals("")){ + return null; + }else return request[2]; + } +} + +class DepositFilter implements Filter{ + public String execute(String[] request){ + if(request[3].equals("")){ + return null; + }else return request[3]; + } +} + +class OrderFilter implements Filter{ + public String execute(String[] request){ + if(request[4].equals("")){ + return null; + }else return request[4]; + } +} + +class Target extends JFrame{ + JTable jt; + JScrollPane jsp; + DefaultTableModel dtm; + JButton del; + public Target(){ + super("Order System"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + setSize(640,480); + dtm = new DefaultTableModel(new Object[]{"Name", "Contact Number", "Address", "Deposit Number", "Order"},0); + jt = new JTable(dtm); + del = new JButton("Delete"); + setup(); + } + private void setup(){ + setLayout(new BorderLayout()); + JPanel bot = new JPanel(); + add(jt.getTableHeader(), BorderLayout.NORTH); + bot.setLayout(new BorderLayout()); + bot.add(del, BorderLayout.EAST); + add(bot, BorderLayout.SOUTH); + jsp = new JScrollPane(jt); + jsp.setPreferredSize(new Dimension(500,250)); + add(jsp, BorderLayout.CENTER); + + del.addActionListener(new DListener()); + + JRootPane rootPane = SwingUtilities.getRootPane(del); + rootPane.setDefaultButton(del); + setVisible(true); + } + public void execute(String[] request){ + //System.out.println(request[4]); + dtm.addRow(new Object[]{request[0],request[1],request[2],request[3],request[4]}); + } + + class DListener implements ActionListener{ + @Override + public void actionPerformed(ActionEvent e){ + int temp = jt.getSelectedRow(); + if(temp == -1) return; + int temp2 = jt.getSelectedRowCount(); + for(int i = 0; i < temp2; i++){ + dtm.removeRow(temp); + } + } + } +} + +class FilterChain{ + private ArrayList filters = new ArrayList(); + private Target target; + + public void addFilter(Filter filter){ + filters.add(filter); + } + + public String execute(String request){ + String tempout[] = new String[filters.size()]; + + String tempin[] = request.split("&"); + int i = 0; + try{ + for(Filter filter:filters){ + tempout[i] = null; + tempout[i++] = filter.execute(tempin); + //System.out.println(tempout[i]); + } + }catch(Exception e){ + return "NOT ENOUGHT INPUT"; + } + + if(tempout[4] == null){ + return "INVALID ORDER!"; + }else if(tempout[3] == null){ + return "INVALID DEPOSIT NUMBER!"; + }else if(tempout[2] == null){ + return "INVALID ADRDESS!"; + }else if(tempout[1] == null){ + return "INVALID Contact Number!"; + }else if(tempout[0] == null){ + return "INVALID Name!"; + }else{ + target.execute(tempout); + return "RUNNING..."; + } + } + + public void setTarget(Target target){ + this.target = target; + } +} + +class FilterManager{ + FilterChain filterChain; + + public FilterManager(Target target){ + filterChain = new FilterChain(); + filterChain.setTarget(target); + } + public void setFilter(Filter filter){ + filterChain.addFilter(filter); + } + public String filterRequest(String request){ + return filterChain.execute(request); + } +} + +class Client extends JFrame{ + FilterManager filterManager; + JLabel jl; + JTextField[] jtfarr; + JTextArea[] jtaarr; + JButton[] buttarr; + public Client(){ + super("Client System"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + setSize(300,300); + jl = new JLabel("RUNNING..."); + jtfarr = new JTextField[3]; + for(int i = 0; i < 3; i++){ + jtfarr[i] = new JTextField(); + } + jtaarr = new JTextArea[2]; + for(int i = 0; i < 2; i++){ + jtaarr[i] = new JTextArea(); + } + buttarr = new JButton[2]; + buttarr[0] = new JButton("Clear"); + buttarr[1] = new JButton("Process"); + + setup(); + } + private void setup(){ + setLayout(new BorderLayout()); + JPanel panel = new JPanel(); + add(jl,BorderLayout.SOUTH); + add(panel, BorderLayout.CENTER); + panel.setLayout(new GridLayout(6,2)); + panel.add(new JLabel("Name")); + panel.add(jtfarr[0]); + panel.add(new JLabel("Contact Number")); + panel.add(jtfarr[1]); + panel.add(new JLabel("Address")); + panel.add(jtaarr[0]); + panel.add(new JLabel("Deposit Number")); + panel.add(jtfarr[2]); + panel.add(new JLabel("Order")); + panel.add(jtaarr[1]); + panel.add(buttarr[0]); + panel.add(buttarr[1]); + + buttarr[0].addActionListener(new ActionListener(){ + @Override + public void actionPerformed(ActionEvent e){ + for(JTextArea i : jtaarr){ + i.setText(""); + } + for(JTextField i : jtfarr){ + i.setText(""); + } + } + }); + + buttarr[1].addActionListener(new ActionListener(){ + @Override + public void actionPerformed(ActionEvent e){ + jl.setText(sendRequest(jtfarr[0].getText()+"&"+jtfarr[1].getText()+"&"+jtaarr[0].getText()+"&"+jtfarr[2].getText()+"&"+jtaarr[1].getText())); + } + }); + + JRootPane rootPane = SwingUtilities.getRootPane(buttarr[1]); + rootPane.setDefaultButton(buttarr[1]); + setVisible(true); + } + public void setFilterManager(FilterManager filterManager){ + this.filterManager = filterManager; + } + public String sendRequest(String request){ + return filterManager.filterRequest(request); + } +} \ No newline at end of file From f753d68d1b84d69ec8bcff628565ac0f98b3ec00 Mon Sep 17 00:00:00 2001 From: joshzambales Date: Fri, 3 Apr 2015 22:27:32 +0800 Subject: [PATCH 15/22] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6e6f4b732..b1eb8b87a 100644 --- a/README.md +++ b/README.md @@ -430,7 +430,7 @@ Presentation Tier patterns are the top-most level of the application, this is co ## Intercepting Filter [↑](#list-of-design-patterns) **Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target -![alt text](https://github.com/joshzambales/java-design-patterns/blob/master/intercepting-filter/etc/intercepting-filter.png "Intercepting Filter") +![alt text](https://github.com/joshzambales/java-design-patterns/blob/master/intercepting-filter/etc/Intercepting-filter.png "Intercepting Filter") **Applicability:** Use the Intercepting Filter pattern when * a system uses pre-processing or post-processing requests @@ -486,4 +486,4 @@ The difference is the intent of the patterns. While Proxy controls access to the # License -This project is licensed under the terms of the MIT license. \ No newline at end of file +This project is licensed under the terms of the MIT license. From 6d4e47311a1a9afd889eff193d2e21bb4bddd7eb Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 4 Apr 2015 04:54:56 +0800 Subject: [PATCH 16/22] added intercepting filter --- README.md | 2 +- intercepting-filter/pom.xml | 92 ++------ .../src/main/AddressFilter.java | 14 ++ intercepting-filter/src/main/App.java | 221 +----------------- intercepting-filter/src/main/Client.java | 86 +++++++ .../src/main/ContactFilter.java | 13 ++ .../src/main/DepositFilter.java | 13 ++ intercepting-filter/src/main/Filter.java | 8 + intercepting-filter/src/main/FilterChain.java | 48 ++++ .../src/main/FilterManager.java | 23 ++ intercepting-filter/src/main/NameFilter.java | 7 + intercepting-filter/src/main/OrderFilter.java | 13 ++ intercepting-filter/src/main/Target.java | 58 +++++ pom.xml | 1 + 14 files changed, 310 insertions(+), 289 deletions(-) create mode 100644 intercepting-filter/src/main/AddressFilter.java create mode 100644 intercepting-filter/src/main/Client.java create mode 100644 intercepting-filter/src/main/ContactFilter.java create mode 100644 intercepting-filter/src/main/DepositFilter.java create mode 100644 intercepting-filter/src/main/Filter.java create mode 100644 intercepting-filter/src/main/FilterChain.java create mode 100644 intercepting-filter/src/main/FilterManager.java create mode 100644 intercepting-filter/src/main/NameFilter.java create mode 100644 intercepting-filter/src/main/OrderFilter.java create mode 100644 intercepting-filter/src/main/Target.java diff --git a/README.md b/README.md index b1eb8b87a..d5c2a2e82 100644 --- a/README.md +++ b/README.md @@ -430,7 +430,7 @@ Presentation Tier patterns are the top-most level of the application, this is co ## Intercepting Filter [↑](#list-of-design-patterns) **Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target -![alt text](https://github.com/joshzambales/java-design-patterns/blob/master/intercepting-filter/etc/Intercepting-filter.png "Intercepting Filter") +![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/intercepting-filter/etc/Intercepting-filter.png "Intercepting Filter") **Applicability:** Use the Intercepting Filter pattern when * a system uses pre-processing or post-processing requests diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml index 72c37c3ed..19ebdfbe2 100644 --- a/intercepting-filter/pom.xml +++ b/intercepting-filter/pom.xml @@ -1,74 +1,18 @@ - - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.0-SNAPSHOT - pom - - - UTF-8 - - - abstract-factory - builder - factory-method - prototype - singleton - adapter - bridge - composite - decorator - facade - flyweight - proxy - chain - command - interpreter - iterator - mediator - memento - model-view-presenter - observer - state - strategy - template-method - visitor - double-checked-locking - servant - service-locator - null-object - event-aggregator - callback - execute-around - property - - - - - - junit - junit - 4.11 - test - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.0 - - 1.7 - 1.7 - - - - - - \ No newline at end of file + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.0-SNAPSHOT + + intercepting-filter + + + junit + junit + test + + + diff --git a/intercepting-filter/src/main/AddressFilter.java b/intercepting-filter/src/main/AddressFilter.java new file mode 100644 index 000000000..68a4b5eff --- /dev/null +++ b/intercepting-filter/src/main/AddressFilter.java @@ -0,0 +1,14 @@ + +/** + * Concrete implementation of filter + * + * @author joshzambales + * + */ +public class AddressFilter implements Filter{ + public String execute(String[] request){ + if(request[2].equals("")){ + return null; + }else return request[2]; + } +} \ No newline at end of file diff --git a/intercepting-filter/src/main/App.java b/intercepting-filter/src/main/App.java index a41e623bc..c3bc3cd0d 100644 --- a/intercepting-filter/src/main/App.java +++ b/intercepting-filter/src/main/App.java @@ -3,6 +3,13 @@ import javax.swing.*; import javax.swing.table.*; import java.awt.*; import java.awt.event.*; +/** + * + * This is an app that checks whether the order request is valid through pre-processing done via Filters + * Each field has its own corresponding Filter + * @author joshzambales + * + */ public class App{ public static void main(String[] args){ FilterManager filterManager = new FilterManager(new Target()); @@ -17,229 +24,15 @@ public class App{ } } -interface Filter{ - public String execute(String[] request); -} -class NameFilter implements Filter{ - public String execute(String[] request){ - if(request[0].equals("") || request[0].matches(".*[^\\w|\\s]+.*")){ - return null; - }else return request[0]; - } -} -class ContactFilter implements Filter{ - public String execute(String[] request){ - if(request[1].equals("") || request[1].matches(".*[^\\d]+.*") || request[1].length() != 11){ - return null; - }else return request[1]; - } -} -class AddressFilter implements Filter{ - public String execute(String[] request){ - if(request[2].equals("")){ - return null; - }else return request[2]; - } -} -class DepositFilter implements Filter{ - public String execute(String[] request){ - if(request[3].equals("")){ - return null; - }else return request[3]; - } -} -class OrderFilter implements Filter{ - public String execute(String[] request){ - if(request[4].equals("")){ - return null; - }else return request[4]; - } -} -class Target extends JFrame{ - JTable jt; - JScrollPane jsp; - DefaultTableModel dtm; - JButton del; - public Target(){ - super("Order System"); - setDefaultCloseOperation(EXIT_ON_CLOSE); - setSize(640,480); - dtm = new DefaultTableModel(new Object[]{"Name", "Contact Number", "Address", "Deposit Number", "Order"},0); - jt = new JTable(dtm); - del = new JButton("Delete"); - setup(); - } - private void setup(){ - setLayout(new BorderLayout()); - JPanel bot = new JPanel(); - add(jt.getTableHeader(), BorderLayout.NORTH); - bot.setLayout(new BorderLayout()); - bot.add(del, BorderLayout.EAST); - add(bot, BorderLayout.SOUTH); - jsp = new JScrollPane(jt); - jsp.setPreferredSize(new Dimension(500,250)); - add(jsp, BorderLayout.CENTER); - del.addActionListener(new DListener()); - JRootPane rootPane = SwingUtilities.getRootPane(del); - rootPane.setDefaultButton(del); - setVisible(true); - } - public void execute(String[] request){ - //System.out.println(request[4]); - dtm.addRow(new Object[]{request[0],request[1],request[2],request[3],request[4]}); - } - class DListener implements ActionListener{ - @Override - public void actionPerformed(ActionEvent e){ - int temp = jt.getSelectedRow(); - if(temp == -1) return; - int temp2 = jt.getSelectedRowCount(); - for(int i = 0; i < temp2; i++){ - dtm.removeRow(temp); - } - } - } -} -class FilterChain{ - private ArrayList filters = new ArrayList(); - private Target target; - public void addFilter(Filter filter){ - filters.add(filter); - } - public String execute(String request){ - String tempout[] = new String[filters.size()]; - - String tempin[] = request.split("&"); - int i = 0; - try{ - for(Filter filter:filters){ - tempout[i] = null; - tempout[i++] = filter.execute(tempin); - //System.out.println(tempout[i]); - } - }catch(Exception e){ - return "NOT ENOUGHT INPUT"; - } - - if(tempout[4] == null){ - return "INVALID ORDER!"; - }else if(tempout[3] == null){ - return "INVALID DEPOSIT NUMBER!"; - }else if(tempout[2] == null){ - return "INVALID ADRDESS!"; - }else if(tempout[1] == null){ - return "INVALID Contact Number!"; - }else if(tempout[0] == null){ - return "INVALID Name!"; - }else{ - target.execute(tempout); - return "RUNNING..."; - } - } - - public void setTarget(Target target){ - this.target = target; - } -} - -class FilterManager{ - FilterChain filterChain; - - public FilterManager(Target target){ - filterChain = new FilterChain(); - filterChain.setTarget(target); - } - public void setFilter(Filter filter){ - filterChain.addFilter(filter); - } - public String filterRequest(String request){ - return filterChain.execute(request); - } -} - -class Client extends JFrame{ - FilterManager filterManager; - JLabel jl; - JTextField[] jtfarr; - JTextArea[] jtaarr; - JButton[] buttarr; - public Client(){ - super("Client System"); - setDefaultCloseOperation(EXIT_ON_CLOSE); - setSize(300,300); - jl = new JLabel("RUNNING..."); - jtfarr = new JTextField[3]; - for(int i = 0; i < 3; i++){ - jtfarr[i] = new JTextField(); - } - jtaarr = new JTextArea[2]; - for(int i = 0; i < 2; i++){ - jtaarr[i] = new JTextArea(); - } - buttarr = new JButton[2]; - buttarr[0] = new JButton("Clear"); - buttarr[1] = new JButton("Process"); - - setup(); - } - private void setup(){ - setLayout(new BorderLayout()); - JPanel panel = new JPanel(); - add(jl,BorderLayout.SOUTH); - add(panel, BorderLayout.CENTER); - panel.setLayout(new GridLayout(6,2)); - panel.add(new JLabel("Name")); - panel.add(jtfarr[0]); - panel.add(new JLabel("Contact Number")); - panel.add(jtfarr[1]); - panel.add(new JLabel("Address")); - panel.add(jtaarr[0]); - panel.add(new JLabel("Deposit Number")); - panel.add(jtfarr[2]); - panel.add(new JLabel("Order")); - panel.add(jtaarr[1]); - panel.add(buttarr[0]); - panel.add(buttarr[1]); - - buttarr[0].addActionListener(new ActionListener(){ - @Override - public void actionPerformed(ActionEvent e){ - for(JTextArea i : jtaarr){ - i.setText(""); - } - for(JTextField i : jtfarr){ - i.setText(""); - } - } - }); - - buttarr[1].addActionListener(new ActionListener(){ - @Override - public void actionPerformed(ActionEvent e){ - jl.setText(sendRequest(jtfarr[0].getText()+"&"+jtfarr[1].getText()+"&"+jtaarr[0].getText()+"&"+jtfarr[2].getText()+"&"+jtaarr[1].getText())); - } - }); - - JRootPane rootPane = SwingUtilities.getRootPane(buttarr[1]); - rootPane.setDefaultButton(buttarr[1]); - setVisible(true); - } - public void setFilterManager(FilterManager filterManager){ - this.filterManager = filterManager; - } - public String sendRequest(String request){ - return filterManager.filterRequest(request); - } -} \ No newline at end of file diff --git a/intercepting-filter/src/main/Client.java b/intercepting-filter/src/main/Client.java new file mode 100644 index 000000000..a62d34702 --- /dev/null +++ b/intercepting-filter/src/main/Client.java @@ -0,0 +1,86 @@ + import java.util.*; +import javax.swing.*; +import javax.swing.table.*; +import java.awt.*; +import java.awt.event.*; +/** + * The Client class is responsible for handling the input and running them through filters inside the filterManager + * + * This is where Filters come to play as the client pre-processes the request before being displayed in the Target + * + * @author joshzambales + * + */ +public class Client extends JFrame{ + FilterManager filterManager; + JLabel jl; + JTextField[] jtFields; + JTextArea[] jtAreas; + JButton clearButton, processButton; + public Client(){ + super("Client System"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + setSize(300,300); + jl = new JLabel("RUNNING..."); + jtFields = new JTextField[3]; + for(int i = 0; i < 3; i++){ + jtFields[i] = new JTextField(); + } + jtAreas = new JTextArea[2]; + for(int i = 0; i < 2; i++){ + jtAreas[i] = new JTextArea(); + } + clearButton = new JButton("Clear"); + processButton = new JButton("Process"); + + setup(); + } + private void setup(){ + setLayout(new BorderLayout()); + JPanel panel = new JPanel(); + add(jl,BorderLayout.SOUTH); + add(panel, BorderLayout.CENTER); + panel.setLayout(new GridLayout(6,2)); + panel.add(new JLabel("Name")); + panel.add(jtFields[0]); + panel.add(new JLabel("Contact Number")); + panel.add(jtFields[1]); + panel.add(new JLabel("Address")); + panel.add(jtAreas[0]); + panel.add(new JLabel("Deposit Number")); + panel.add(jtFields[2]); + panel.add(new JLabel("Order")); + panel.add(jtAreas[1]); + panel.add(clearButton); + panel.add(processButton); + + clearButton.addActionListener(new ActionListener(){ + @Override + public void actionPerformed(ActionEvent e){ + for(JTextArea i : jtAreas){ + i.setText(""); + } + for(JTextField i : jtFields){ + i.setText(""); + } + } + }); + + processButton.addActionListener(new ActionListener(){ + @Override + public void actionPerformed(ActionEvent e){ + jl.setText(sendRequest(jtFields[0].getText()+"&"+jtFields[1].getText()+"&"+jtAreas[0].getText()+"&"+jtFields[2].getText()+"&"+jtAreas[1].getText())); + } + }); + + JRootPane rootPane = SwingUtilities.getRootPane(processButton); + rootPane.setDefaultButton(processButton); + setVisible(true); + } + public void setFilterManager(FilterManager filterManager){ + this.filterManager = filterManager; + } + public String sendRequest(String request){ + return filterManager.filterRequest(request); + } +} \ No newline at end of file diff --git a/intercepting-filter/src/main/ContactFilter.java b/intercepting-filter/src/main/ContactFilter.java new file mode 100644 index 000000000..f44398963 --- /dev/null +++ b/intercepting-filter/src/main/ContactFilter.java @@ -0,0 +1,13 @@ +/** + * Concrete implementation of filter + * + * @author joshzambales + * + */ +public class ContactFilter implements Filter{ + public String execute(String[] request){ + if(request[1].equals("") || request[1].matches(".*[^\\d]+.*") || request[1].length() != 11){ + return null; + }else return request[1]; + } +} \ No newline at end of file diff --git a/intercepting-filter/src/main/DepositFilter.java b/intercepting-filter/src/main/DepositFilter.java new file mode 100644 index 000000000..8d1b9303e --- /dev/null +++ b/intercepting-filter/src/main/DepositFilter.java @@ -0,0 +1,13 @@ +/** + * Concrete implementation of filter + * + * @author joshzambales + * + */ +public class DepositFilter implements Filter{ + public String execute(String[] request){ + if(request[3].equals("")){ + return null; + }else return request[3]; + } +} diff --git a/intercepting-filter/src/main/Filter.java b/intercepting-filter/src/main/Filter.java new file mode 100644 index 000000000..578f1c5fd --- /dev/null +++ b/intercepting-filter/src/main/Filter.java @@ -0,0 +1,8 @@ +/** + * Filter interface + * @author joshzambales + * + */ +public interface Filter{ + public String execute(String[] request); +} diff --git a/intercepting-filter/src/main/FilterChain.java b/intercepting-filter/src/main/FilterChain.java new file mode 100644 index 000000000..04b991c2c --- /dev/null +++ b/intercepting-filter/src/main/FilterChain.java @@ -0,0 +1,48 @@ + import java.util.*; +/** + * Filter Chain carries multiple filters and help to execute them in defined order on target. + * + * @author joshzambales + */ +public class FilterChain{ + private ArrayList filters = new ArrayList(); + private Target target; + + public FilterChain(Target target){ + this.target = target; + } + public void addFilter(Filter filter){ + filters.add(filter); + } + + public String execute(String request){ + String tempout[] = new String[filters.size()]; + + String tempin[] = request.split("&"); + int i = 0; + try{ + for(Filter filter:filters){ + tempout[i] = null; + tempout[i++] = filter.execute(tempin); + } + }catch(Exception e){ + return "NOT ENOUGHT INPUT"; + } + + if(tempout[4] == null){ + return "INVALID ORDER!"; + }else if(tempout[3] == null){ + return "INVALID DEPOSIT NUMBER!"; + }else if(tempout[2] == null){ + return "INVALID ADRDESS!"; + }else if(tempout[1] == null){ + return "INVALID Contact Number!"; + }else if(tempout[0] == null){ + return "INVALID Name!"; + }else{ + target.execute(tempout); + return "RUNNING..."; + } + } + +} diff --git a/intercepting-filter/src/main/FilterManager.java b/intercepting-filter/src/main/FilterManager.java new file mode 100644 index 000000000..380222a75 --- /dev/null +++ b/intercepting-filter/src/main/FilterManager.java @@ -0,0 +1,23 @@ + import java.util.*; +import javax.swing.*; +import javax.swing.table.*; +import java.awt.*; +import java.awt.event.*; +/** + * Filter Manager manages the filters and Filter Chain. + * @author joshzambales + * + */ +public class FilterManager{ + FilterChain filterChain; + + public FilterManager(Target target){ + filterChain = new FilterChain(target); + } + public void setFilter(Filter filter){ + filterChain.addFilter(filter); + } + public String filterRequest(String request){ + return filterChain.execute(request); + } +} \ No newline at end of file diff --git a/intercepting-filter/src/main/NameFilter.java b/intercepting-filter/src/main/NameFilter.java new file mode 100644 index 000000000..61d368ce2 --- /dev/null +++ b/intercepting-filter/src/main/NameFilter.java @@ -0,0 +1,7 @@ +public class NameFilter implements Filter{ + public String execute(String[] request){ + if(request[0].equals("") || request[0].matches(".*[^\\w|\\s]+.*")){ + return null; + }else return request[0]; + } +} \ No newline at end of file diff --git a/intercepting-filter/src/main/OrderFilter.java b/intercepting-filter/src/main/OrderFilter.java new file mode 100644 index 000000000..8ccf5a67d --- /dev/null +++ b/intercepting-filter/src/main/OrderFilter.java @@ -0,0 +1,13 @@ +/** + * Concrete implementation of filter + * + * @author joshzambales + * + */ +public class OrderFilter implements Filter{ + public String execute(String[] request){ + if(request[4].equals("")){ + return null; + }else return request[4]; + } +} \ No newline at end of file diff --git a/intercepting-filter/src/main/Target.java b/intercepting-filter/src/main/Target.java new file mode 100644 index 000000000..93c7d93f7 --- /dev/null +++ b/intercepting-filter/src/main/Target.java @@ -0,0 +1,58 @@ + import java.util.*; +import javax.swing.*; +import javax.swing.table.*; +import java.awt.*; +import java.awt.event.*; +/** + * This is where the requests are displayed after being validated by filters. + * + * @author mjoshzambales + * + */ +public class Target extends JFrame{ + JTable jt; + JScrollPane jsp; + DefaultTableModel dtm; + JButton del; + public Target(){ + super("Order System"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + setSize(640,480); + dtm = new DefaultTableModel(new Object[]{"Name", "Contact Number", "Address", "Deposit Number", "Order"},0); + jt = new JTable(dtm); + del = new JButton("Delete"); + setup(); + } + private void setup(){ + setLayout(new BorderLayout()); + JPanel bot = new JPanel(); + add(jt.getTableHeader(), BorderLayout.NORTH); + bot.setLayout(new BorderLayout()); + bot.add(del, BorderLayout.EAST); + add(bot, BorderLayout.SOUTH); + jsp = new JScrollPane(jt); + jsp.setPreferredSize(new Dimension(500,250)); + add(jsp, BorderLayout.CENTER); + + del.addActionListener(new DListener()); + + JRootPane rootPane = SwingUtilities.getRootPane(del); + rootPane.setDefaultButton(del); + setVisible(true); + } + public void execute(String[] request){ + dtm.addRow(new Object[]{request[0],request[1],request[2],request[3],request[4]}); + } + + class DListener implements ActionListener{ + @Override + public void actionPerformed(ActionEvent e){ + int temp = jt.getSelectedRow(); + if(temp == -1) return; + int temp2 = jt.getSelectedRowCount(); + for(int i = 0; i < temp2; i++){ + dtm.removeRow(temp); + } + } + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7cfff29c4..80f25c549 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,7 @@ null-object event-aggregator callback + intercepting-filter From 68f02c12d11525386dabbb0d220396d58e2130f6 Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 4 Apr 2015 05:47:54 +0800 Subject: [PATCH 17/22] revised --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 58cf19777..4e5b131c5 100644 --- a/pom.xml +++ b/pom.xml @@ -41,8 +41,8 @@ null-object event-aggregator callback -<<<<<<< HEAD intercepting-filter +<<<<<<< HEAD ======= execute-around From ee37e10382b4e0690a318a86fbda2ceedcd44972 Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 4 Apr 2015 11:21:27 +0800 Subject: [PATCH 18/22] fix travis CI --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4e5b131c5..2928df18f 100644 --- a/pom.xml +++ b/pom.xml @@ -41,8 +41,9 @@ null-object event-aggregator callback - intercepting-filter <<<<<<< HEAD + + intercepting-filter ======= execute-around From 5383eb9f56a4fc40ec4ff85b322682b2af88f05d Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 4 Apr 2015 11:28:42 +0800 Subject: [PATCH 19/22] fix travis CI --- pom.xml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 2928df18f..d61129e9e 100644 --- a/pom.xml +++ b/pom.xml @@ -41,15 +41,11 @@ null-object event-aggregator callback -<<<<<<< HEAD - - intercepting-filter - -======= execute-around property + + intercepting-filter ->>>>>>> origin/master From 10be0b0b10f69dbc5e46257a89f4b1baf3e082ca Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 4 Apr 2015 21:37:36 +0800 Subject: [PATCH 20/22] made changes according to 2nd batch of comments --- README.md | 8 ++++---- intercepting-filter/src/main/AddressFilter.java | 2 +- intercepting-filter/src/main/Client.java | 14 ++++++++------ intercepting-filter/src/main/ContactFilter.java | 2 +- intercepting-filter/src/main/DepositFilter.java | 3 ++- intercepting-filter/src/main/Filter.java | 4 +++- intercepting-filter/src/main/FilterChain.java | 2 +- intercepting-filter/src/main/FilterManager.java | 2 +- intercepting-filter/src/main/NameFilter.java | 7 +++++++ intercepting-filter/src/main/OrderFilter.java | 1 + intercepting-filter/src/main/Target.java | 8 ++++---- pom.xml | 1 - 12 files changed, 33 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 2118fb5ef..3455c11c2 100644 --- a/README.md +++ b/README.md @@ -437,7 +437,7 @@ Presentation Tier patterns are the top-most level of the application, this is co **Applicability:** Use the Callback pattern when * When some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity. -<<<<<<< HEAD + ## Intercepting Filter [↑](#list-of-design-patterns) **Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target @@ -469,7 +469,7 @@ Presentation Tier patterns are the top-most level of the application, this is co **Real world examples:** * [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) prototype inheritance ->>>>>>> origin/master + # Frequently asked questions @@ -515,14 +515,14 @@ The difference is the intent of the patterns. While Proxy controls access to the * [Let’s Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf) * [Pattern Languages of Program Design](http://www.amazon.com/Pattern-Languages-Program-Design-Coplien/dp/0201607344/ref=sr_1_1) * [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html) -<<<<<<< HEAD + * [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm) * [Presentation Tier Pattern](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns) ======= * [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](http://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/ref=sr_1_1) ->>>>>>> origin/master + # License diff --git a/intercepting-filter/src/main/AddressFilter.java b/intercepting-filter/src/main/AddressFilter.java index 68a4b5eff..4b45eb3ee 100644 --- a/intercepting-filter/src/main/AddressFilter.java +++ b/intercepting-filter/src/main/AddressFilter.java @@ -1,7 +1,7 @@ /** * Concrete implementation of filter - * + * This filter is responsible for checking/filtering the input in the address field, returns null if field is empty * @author joshzambales * */ diff --git a/intercepting-filter/src/main/Client.java b/intercepting-filter/src/main/Client.java index a62d34702..aadf57a77 100644 --- a/intercepting-filter/src/main/Client.java +++ b/intercepting-filter/src/main/Client.java @@ -12,11 +12,11 @@ import java.awt.event.*; * */ public class Client extends JFrame{ - FilterManager filterManager; - JLabel jl; - JTextField[] jtFields; - JTextArea[] jtAreas; - JButton clearButton, processButton; + private FilterManager filterManager; + private JLabel jl; + private JTextField[] jtFields; + private JTextArea[] jtAreas; + private JButton clearButton, processButton; public Client(){ super("Client System"); setDefaultCloseOperation(EXIT_ON_CLOSE); @@ -69,7 +69,9 @@ public class Client extends JFrame{ processButton.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e){ - jl.setText(sendRequest(jtFields[0].getText()+"&"+jtFields[1].getText()+"&"+jtAreas[0].getText()+"&"+jtFields[2].getText()+"&"+jtAreas[1].getText())); + String request = String.format("%s&%s&%s&%s&%s",jtFields[0].getText(),jtFields[1].getText(),jtAreas[0].getText(),jtFields[2].getText(),jtAreas[1].getText()); + + jl.setText(sendRequest(request)); } }); diff --git a/intercepting-filter/src/main/ContactFilter.java b/intercepting-filter/src/main/ContactFilter.java index f44398963..8e7c95408 100644 --- a/intercepting-filter/src/main/ContactFilter.java +++ b/intercepting-filter/src/main/ContactFilter.java @@ -1,6 +1,6 @@ /** * Concrete implementation of filter - * + * This filter checks for the contact field in which it checks if the input consist of numbers and it also checks if the input follows the length constraint (11 digits) * @author joshzambales * */ diff --git a/intercepting-filter/src/main/DepositFilter.java b/intercepting-filter/src/main/DepositFilter.java index 8d1b9303e..aae339035 100644 --- a/intercepting-filter/src/main/DepositFilter.java +++ b/intercepting-filter/src/main/DepositFilter.java @@ -1,6 +1,7 @@ /** * Concrete implementation of filter - * +* + * This checks for the deposit code, returns null when deposit field is empty * @author joshzambales * */ diff --git a/intercepting-filter/src/main/Filter.java b/intercepting-filter/src/main/Filter.java index 578f1c5fd..807c8ae21 100644 --- a/intercepting-filter/src/main/Filter.java +++ b/intercepting-filter/src/main/Filter.java @@ -1,5 +1,7 @@ /** - * Filter interface +* Filter interface + * Filters perform certain tasks prior or after execution of request by request handler. + * In this case, before the request is handled by the target, the request undergoes through each Filter * @author joshzambales * */ diff --git a/intercepting-filter/src/main/FilterChain.java b/intercepting-filter/src/main/FilterChain.java index 04b991c2c..57322d3b4 100644 --- a/intercepting-filter/src/main/FilterChain.java +++ b/intercepting-filter/src/main/FilterChain.java @@ -6,7 +6,7 @@ */ public class FilterChain{ private ArrayList filters = new ArrayList(); - private Target target; + private final Target target; public FilterChain(Target target){ this.target = target; diff --git a/intercepting-filter/src/main/FilterManager.java b/intercepting-filter/src/main/FilterManager.java index 380222a75..be6d8e7b4 100644 --- a/intercepting-filter/src/main/FilterManager.java +++ b/intercepting-filter/src/main/FilterManager.java @@ -9,7 +9,7 @@ import java.awt.event.*; * */ public class FilterManager{ - FilterChain filterChain; + private FilterChain filterChain; public FilterManager(Target target){ filterChain = new FilterChain(target); diff --git a/intercepting-filter/src/main/NameFilter.java b/intercepting-filter/src/main/NameFilter.java index 61d368ce2..e602ae0e1 100644 --- a/intercepting-filter/src/main/NameFilter.java +++ b/intercepting-filter/src/main/NameFilter.java @@ -1,3 +1,10 @@ + +/** + * Concrete implementation of filter + * This filter checks if the input in the Name field is valid. (alphanumeric) + * @author joshzambales + * + */ public class NameFilter implements Filter{ public String execute(String[] request){ if(request[0].equals("") || request[0].matches(".*[^\\w|\\s]+.*")){ diff --git a/intercepting-filter/src/main/OrderFilter.java b/intercepting-filter/src/main/OrderFilter.java index 8ccf5a67d..33dc486f7 100644 --- a/intercepting-filter/src/main/OrderFilter.java +++ b/intercepting-filter/src/main/OrderFilter.java @@ -1,5 +1,6 @@ /** * Concrete implementation of filter + * This checks for the order field, returns null when order field is empty * * @author joshzambales * diff --git a/intercepting-filter/src/main/Target.java b/intercepting-filter/src/main/Target.java index 93c7d93f7..0f1ade30d 100644 --- a/intercepting-filter/src/main/Target.java +++ b/intercepting-filter/src/main/Target.java @@ -10,10 +10,10 @@ import java.awt.event.*; * */ public class Target extends JFrame{ - JTable jt; - JScrollPane jsp; - DefaultTableModel dtm; - JButton del; + private JTable jt; + private JScrollPane jsp; + private DefaultTableModel dtm; + private JButton del; public Target(){ super("Order System"); setDefaultCloseOperation(EXIT_ON_CLOSE); diff --git a/pom.xml b/pom.xml index d61129e9e..d81be42c9 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,6 @@ callback execute-around property - intercepting-filter From 2d7e2d1b189a2204a4527ad8c892ed10663e3f4f Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 4 Apr 2015 21:48:50 +0800 Subject: [PATCH 21/22] removed some merge markers --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 3455c11c2..800efa4f5 100644 --- a/README.md +++ b/README.md @@ -447,7 +447,7 @@ Presentation Tier patterns are the top-most level of the application, this is co * a system uses pre-processing or post-processing requests * a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers * you want a modular approach to configuring pre-processing and post-processing schemes -======= + **Real world examples:** * [CyclicBarrier] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept callback that will be triggered every time when barrier is tripped. @@ -515,10 +515,8 @@ The difference is the intent of the patterns. While Proxy controls access to the * [Let’s Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf) * [Pattern Languages of Program Design](http://www.amazon.com/Pattern-Languages-Program-Design-Coplien/dp/0201607344/ref=sr_1_1) * [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html) - * [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm) * [Presentation Tier Pattern](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns) -======= * [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](http://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/ref=sr_1_1) From 57c7a4895c73b4de9386ac209015f0264bf33039 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 5 Apr 2015 01:15:02 +0800 Subject: [PATCH 22/22] fixed folder structure and added package --- .../src/main/{ => java/com/iluwatar}/AddressFilter.java | 2 +- .../src/main/{ => java/com/iluwatar}/App.java | 7 ++----- .../src/main/{ => java/com/iluwatar}/Client.java | 2 ++ .../src/main/{ => java/com/iluwatar}/ContactFilter.java | 1 + .../src/main/{ => java/com/iluwatar}/DepositFilter.java | 1 + .../src/main/{ => java/com/iluwatar}/Filter.java | 1 + .../src/main/{ => java/com/iluwatar}/FilterChain.java | 1 + .../src/main/{ => java/com/iluwatar}/FilterManager.java | 1 + .../src/main/{ => java/com/iluwatar}/NameFilter.java | 2 +- .../src/main/{ => java/com/iluwatar}/OrderFilter.java | 1 + .../src/main/{ => java/com/iluwatar}/Target.java | 1 + 11 files changed, 13 insertions(+), 7 deletions(-) rename intercepting-filter/src/main/{ => java/com/iluwatar}/AddressFilter.java (94%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/App.java (94%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/Client.java (99%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/ContactFilter.java (95%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/DepositFilter.java (93%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/Filter.java (93%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/FilterChain.java (97%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/FilterManager.java (95%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/NameFilter.java (94%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/OrderFilter.java (93%) rename intercepting-filter/src/main/{ => java/com/iluwatar}/Target.java (98%) diff --git a/intercepting-filter/src/main/AddressFilter.java b/intercepting-filter/src/main/java/com/iluwatar/AddressFilter.java similarity index 94% rename from intercepting-filter/src/main/AddressFilter.java rename to intercepting-filter/src/main/java/com/iluwatar/AddressFilter.java index 4b45eb3ee..e99185e26 100644 --- a/intercepting-filter/src/main/AddressFilter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/AddressFilter.java @@ -1,4 +1,4 @@ - +package com.iluwatar; /** * Concrete implementation of filter * This filter is responsible for checking/filtering the input in the address field, returns null if field is empty diff --git a/intercepting-filter/src/main/App.java b/intercepting-filter/src/main/java/com/iluwatar/App.java similarity index 94% rename from intercepting-filter/src/main/App.java rename to intercepting-filter/src/main/java/com/iluwatar/App.java index c3bc3cd0d..af22d9ec3 100644 --- a/intercepting-filter/src/main/App.java +++ b/intercepting-filter/src/main/java/com/iluwatar/App.java @@ -1,4 +1,5 @@ - import java.util.*; +package com.iluwatar; +import java.util.*; import javax.swing.*; import javax.swing.table.*; import java.awt.*; @@ -32,7 +33,3 @@ public class App{ - - - - diff --git a/intercepting-filter/src/main/Client.java b/intercepting-filter/src/main/java/com/iluwatar/Client.java similarity index 99% rename from intercepting-filter/src/main/Client.java rename to intercepting-filter/src/main/java/com/iluwatar/Client.java index aadf57a77..a3bd2137f 100644 --- a/intercepting-filter/src/main/Client.java +++ b/intercepting-filter/src/main/java/com/iluwatar/Client.java @@ -1,8 +1,10 @@ +package com.iluwatar; import java.util.*; import javax.swing.*; import javax.swing.table.*; import java.awt.*; import java.awt.event.*; + /** * The Client class is responsible for handling the input and running them through filters inside the filterManager * diff --git a/intercepting-filter/src/main/ContactFilter.java b/intercepting-filter/src/main/java/com/iluwatar/ContactFilter.java similarity index 95% rename from intercepting-filter/src/main/ContactFilter.java rename to intercepting-filter/src/main/java/com/iluwatar/ContactFilter.java index 8e7c95408..30cb34953 100644 --- a/intercepting-filter/src/main/ContactFilter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/ContactFilter.java @@ -1,3 +1,4 @@ +package com.iluwatar; /** * Concrete implementation of filter * This filter checks for the contact field in which it checks if the input consist of numbers and it also checks if the input follows the length constraint (11 digits) diff --git a/intercepting-filter/src/main/DepositFilter.java b/intercepting-filter/src/main/java/com/iluwatar/DepositFilter.java similarity index 93% rename from intercepting-filter/src/main/DepositFilter.java rename to intercepting-filter/src/main/java/com/iluwatar/DepositFilter.java index aae339035..76bfb9a1a 100644 --- a/intercepting-filter/src/main/DepositFilter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/DepositFilter.java @@ -1,3 +1,4 @@ +package com.iluwatar; /** * Concrete implementation of filter * diff --git a/intercepting-filter/src/main/Filter.java b/intercepting-filter/src/main/java/com/iluwatar/Filter.java similarity index 93% rename from intercepting-filter/src/main/Filter.java rename to intercepting-filter/src/main/java/com/iluwatar/Filter.java index 807c8ae21..f127f79a8 100644 --- a/intercepting-filter/src/main/Filter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/Filter.java @@ -1,3 +1,4 @@ +package com.iluwatar; /** * Filter interface * Filters perform certain tasks prior or after execution of request by request handler. diff --git a/intercepting-filter/src/main/FilterChain.java b/intercepting-filter/src/main/java/com/iluwatar/FilterChain.java similarity index 97% rename from intercepting-filter/src/main/FilterChain.java rename to intercepting-filter/src/main/java/com/iluwatar/FilterChain.java index 57322d3b4..09ca6598f 100644 --- a/intercepting-filter/src/main/FilterChain.java +++ b/intercepting-filter/src/main/java/com/iluwatar/FilterChain.java @@ -1,3 +1,4 @@ + package com.iluwatar; import java.util.*; /** * Filter Chain carries multiple filters and help to execute them in defined order on target. diff --git a/intercepting-filter/src/main/FilterManager.java b/intercepting-filter/src/main/java/com/iluwatar/FilterManager.java similarity index 95% rename from intercepting-filter/src/main/FilterManager.java rename to intercepting-filter/src/main/java/com/iluwatar/FilterManager.java index be6d8e7b4..25b98730b 100644 --- a/intercepting-filter/src/main/FilterManager.java +++ b/intercepting-filter/src/main/java/com/iluwatar/FilterManager.java @@ -1,3 +1,4 @@ + package com.iluwatar; import java.util.*; import javax.swing.*; import javax.swing.table.*; diff --git a/intercepting-filter/src/main/NameFilter.java b/intercepting-filter/src/main/java/com/iluwatar/NameFilter.java similarity index 94% rename from intercepting-filter/src/main/NameFilter.java rename to intercepting-filter/src/main/java/com/iluwatar/NameFilter.java index e602ae0e1..de929fc24 100644 --- a/intercepting-filter/src/main/NameFilter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/NameFilter.java @@ -1,4 +1,4 @@ - +package com.iluwatar; /** * Concrete implementation of filter * This filter checks if the input in the Name field is valid. (alphanumeric) diff --git a/intercepting-filter/src/main/OrderFilter.java b/intercepting-filter/src/main/java/com/iluwatar/OrderFilter.java similarity index 93% rename from intercepting-filter/src/main/OrderFilter.java rename to intercepting-filter/src/main/java/com/iluwatar/OrderFilter.java index 33dc486f7..e33dcd1c6 100644 --- a/intercepting-filter/src/main/OrderFilter.java +++ b/intercepting-filter/src/main/java/com/iluwatar/OrderFilter.java @@ -1,3 +1,4 @@ +package com.iluwatar; /** * Concrete implementation of filter * This checks for the order field, returns null when order field is empty diff --git a/intercepting-filter/src/main/Target.java b/intercepting-filter/src/main/java/com/iluwatar/Target.java similarity index 98% rename from intercepting-filter/src/main/Target.java rename to intercepting-filter/src/main/java/com/iluwatar/Target.java index 0f1ade30d..9068de95f 100644 --- a/intercepting-filter/src/main/Target.java +++ b/intercepting-filter/src/main/java/com/iluwatar/Target.java @@ -1,3 +1,4 @@ + package com.iluwatar; import java.util.*; import javax.swing.*; import javax.swing.table.*;