Merge branch 'unit-of-work-pattern' of github.com:piyushchaudhari04/java-design-patterns into unit-of-work-pattern
This commit is contained in:
		
							
								
								
									
										126
									
								
								chain/README.md
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								chain/README.md
									
									
									
									
									
								
							| @@ -16,7 +16,131 @@ Avoid coupling the sender of a request to its receiver by giving | ||||
| more than one object a chance to handle the request. Chain the receiving | ||||
| objects and pass the request along the chain until an object handles it. | ||||
|  | ||||
|  | ||||
| ## Explanation | ||||
|  | ||||
| Real world example | ||||
|  | ||||
| > The Orc King gives loud orders to his army. The closest one to react is the commander, then officer and then soldier. The commander, officer and soldier here form a chain of responsibility. | ||||
|  | ||||
| In plain words | ||||
|  | ||||
| > It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler. | ||||
|  | ||||
| Wikipedia says | ||||
|  | ||||
| > In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. | ||||
|  | ||||
| **Programmatic Example** | ||||
|  | ||||
| Translating our example with orcs from above. First we have the request class | ||||
|  | ||||
| ``` | ||||
| public class Request { | ||||
|  | ||||
|   private final RequestType requestType; | ||||
|   private final String requestDescription; | ||||
|   private boolean handled; | ||||
|  | ||||
|   public Request(final RequestType requestType, final String requestDescription) { | ||||
|     this.requestType = Objects.requireNonNull(requestType); | ||||
|     this.requestDescription = Objects.requireNonNull(requestDescription); | ||||
|   } | ||||
|  | ||||
|   public String getRequestDescription() { return requestDescription; } | ||||
|  | ||||
|   public RequestType getRequestType() { return requestType; } | ||||
|  | ||||
|   public void markHandled() { this.handled = true; } | ||||
|  | ||||
|   public boolean isHandled() { return this.handled; } | ||||
|  | ||||
|   @Override | ||||
|   public String toString() { return getRequestDescription(); } | ||||
| } | ||||
|  | ||||
| public enum RequestType { | ||||
|   DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Then the request handler hierarchy | ||||
|  | ||||
| ``` | ||||
| public abstract class RequestHandler { | ||||
|   private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class); | ||||
|   private RequestHandler next; | ||||
|  | ||||
|   public RequestHandler(RequestHandler next) { | ||||
|     this.next = next; | ||||
|   } | ||||
|  | ||||
|   public void handleRequest(Request req) { | ||||
|     if (next != null) { | ||||
|       next.handleRequest(req); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected void printHandling(Request req) { | ||||
|     LOGGER.info("{} handling request \"{}\"", this, req); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public abstract String toString(); | ||||
| } | ||||
|  | ||||
| public class OrcCommander extends RequestHandler { | ||||
|   public OrcCommander(RequestHandler handler) { | ||||
|     super(handler); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void handleRequest(Request req) { | ||||
|     if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) { | ||||
|       printHandling(req); | ||||
|       req.markHandled(); | ||||
|     } else { | ||||
|       super.handleRequest(req); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String toString() { | ||||
|     return "Orc commander"; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // OrcOfficer and OrcSoldier are defined similarly as OrcCommander | ||||
|  | ||||
| ``` | ||||
|  | ||||
| Then we have the Orc King who gives the orders and forms the chain | ||||
|  | ||||
| ``` | ||||
| public class OrcKing { | ||||
|   RequestHandler chain; | ||||
|  | ||||
|   public OrcKing() { | ||||
|     buildChain(); | ||||
|   } | ||||
|  | ||||
|   private void buildChain() { | ||||
|     chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null))); | ||||
|   } | ||||
|  | ||||
|   public void makeRequest(Request req) { | ||||
|     chain.handleRequest(req); | ||||
|   } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Then it is used as follows | ||||
|  | ||||
| ``` | ||||
| OrcKing king = new OrcKing(); | ||||
| king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle" | ||||
| king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner" | ||||
| king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax" | ||||
| ``` | ||||
|  | ||||
| ## Applicability | ||||
| Use Chain of Responsibility when | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 30 KiB | 
| @@ -1,109 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"  | ||||
|   realizations="true" associations="true" dependencies="false" nesting-relationships="true">   | ||||
|   <class id="1" language="java" name="com.iluwatar.chain.Request" project="chain"  | ||||
|     file="/chain/src/main/java/com/iluwatar/chain/Request.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="196" width="228" x="168" y="182"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="2" language="java" name="com.iluwatar.chain.OrcOfficer" project="chain"  | ||||
|     file="/chain/src/main/java/com/iluwatar/chain/OrcOfficer.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="124" width="194" x="168" y="609"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="3" language="java" name="com.iluwatar.chain.OrcCommander" project="chain"  | ||||
|     file="/chain/src/main/java/com/iluwatar/chain/OrcCommander.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="124" width="217" x="402" y="609"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="4" language="java" name="com.iluwatar.chain.RequestHandler" project="chain"  | ||||
|     file="/chain/src/main/java/com/iluwatar/chain/RequestHandler.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="141" width="218" x="451" y="418"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="5" language="java" name="com.iluwatar.chain.OrcSoldier" project="chain"  | ||||
|     file="/chain/src/main/java/com/iluwatar/chain/OrcSoldier.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="124" width="194" x="659" y="609"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="6" language="java" name="com.iluwatar.chain.OrcKing" project="chain"  | ||||
|     file="/chain/src/main/java/com/iluwatar/chain/OrcKing.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="124" width="188" x="451" y="182"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <enumeration id="7" language="java" name="com.iluwatar.chain.RequestType" project="chain"  | ||||
|     file="/chain/src/main/java/com/iluwatar/chain/RequestType.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="142" width="243" x="168" y="418"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </enumeration>   | ||||
|   <association id="8">     | ||||
|     <end type="SOURCE" refId="6" navigable="false">       | ||||
|       <attribute id="9" name="chain"/>       | ||||
|       <multiplicity id="10" minimum="0" maximum="1"/>     | ||||
|     </end>     | ||||
|     <end type="TARGET" refId="4" navigable="true"/>     | ||||
|     <display labels="true" multiplicity="true"/>   | ||||
|   </association>   | ||||
|   <association id="11">     | ||||
|     <end type="SOURCE" refId="4" navigable="false">       | ||||
|       <attribute id="12" name="next"/>       | ||||
|       <multiplicity id="13" minimum="0" maximum="1"/>     | ||||
|     </end>     | ||||
|     <end type="TARGET" refId="4" navigable="true"/>     | ||||
|     <display labels="true" multiplicity="true"/>   | ||||
|   </association>   | ||||
|   <generalization id="14">     | ||||
|     <end type="SOURCE" refId="5"/>     | ||||
|     <end type="TARGET" refId="4"/>   | ||||
|   </generalization>   | ||||
|   <association id="15">     | ||||
|     <end type="SOURCE" refId="1" navigable="false">       | ||||
|       <attribute id="16" name="requestType"/>       | ||||
|       <multiplicity id="17" minimum="0" maximum="1"/>     | ||||
|     </end>     | ||||
|     <end type="TARGET" refId="7" navigable="true"/>     | ||||
|     <display labels="true" multiplicity="true"/>   | ||||
|   </association>   | ||||
|   <generalization id="18">     | ||||
|     <end type="SOURCE" refId="2"/>     | ||||
|     <end type="TARGET" refId="4"/>   | ||||
|   </generalization>   | ||||
|   <generalization id="19">     | ||||
|     <end type="SOURCE" refId="3"/>     | ||||
|     <end type="TARGET" refId="4"/>   | ||||
|   </generalization>   | ||||
|   <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|     sort-features="false" accessors="true" visibility="true">     | ||||
|     <attributes public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     <operations public="true" package="true" protected="true" private="true" static="true"/>   | ||||
|   </classifier-display>   | ||||
|   <association-display labels="true" multiplicity="true"/> | ||||
| </class-diagram> | ||||
| @@ -1,61 +0,0 @@ | ||||
| @startuml | ||||
| package com.iluwatar.chain { | ||||
|   class App { | ||||
|     + App() | ||||
|     + main(args : String[]) {static} | ||||
|   } | ||||
|   class OrcCommander { | ||||
|     + OrcCommander(handler : RequestHandler) | ||||
|     + handleRequest(req : Request) | ||||
|     + toString() : String | ||||
|   } | ||||
|   class OrcKing { | ||||
|     ~ chain : RequestHandler | ||||
|     + OrcKing() | ||||
|     - buildChain() | ||||
|     + makeRequest(req : Request) | ||||
|   } | ||||
|   class OrcOfficer { | ||||
|     + OrcOfficer(handler : RequestHandler) | ||||
|     + handleRequest(req : Request) | ||||
|     + toString() : String | ||||
|   } | ||||
|   class OrcSoldier { | ||||
|     + OrcSoldier(handler : RequestHandler) | ||||
|     + handleRequest(req : Request) | ||||
|     + toString() : String | ||||
|   } | ||||
|   class Request { | ||||
|     - handled : boolean | ||||
|     - requestDescription : String | ||||
|     - requestType : RequestType | ||||
|     + Request(requestType : RequestType, requestDescription : String) | ||||
|     + getRequestDescription() : String | ||||
|     + getRequestType() : RequestType | ||||
|     + isHandled() : boolean | ||||
|     + markHandled() | ||||
|     + toString() : String | ||||
|   } | ||||
|   abstract class RequestHandler { | ||||
|     - LOGGER : Logger {static} | ||||
|     - next : RequestHandler | ||||
|     + RequestHandler(next : RequestHandler) | ||||
|     + handleRequest(req : Request) | ||||
|     # printHandling(req : Request) | ||||
|     + toString() : String {abstract} | ||||
|   } | ||||
|   enum RequestType { | ||||
|     + COLLECT_TAX {static} | ||||
|     + DEFEND_CASTLE {static} | ||||
|     + TORTURE_PRISONER {static} | ||||
|     + valueOf(name : String) : RequestType {static} | ||||
|     + values() : RequestType[] {static} | ||||
|   } | ||||
| } | ||||
| RequestHandler -->  "-next" RequestHandler | ||||
| Request -->  "-requestType" RequestType | ||||
| OrcKing -->  "-chain" RequestHandler | ||||
| OrcCommander --|> RequestHandler  | ||||
| OrcOfficer --|> RequestHandler  | ||||
| OrcSoldier --|> RequestHandler  | ||||
| @enduml | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 60 KiB | 
							
								
								
									
										43
									
								
								dao/src/main/java/com/iluwatar/dao/CustomException.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								dao/src/main/java/com/iluwatar/dao/CustomException.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| /** | ||||
|  * The MIT License | ||||
|  * Copyright (c) 2014 Ilkka Seppälä | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| package com.iluwatar.dao; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * Custom exception | ||||
|  * | ||||
|  */ | ||||
| public class CustomException extends Exception { | ||||
|  | ||||
|   private static final long serialVersionUID = 1L; | ||||
|  | ||||
|   public CustomException() {} | ||||
|  | ||||
|   public CustomException(String message) { | ||||
|     super(message); | ||||
|   } | ||||
|    | ||||
|   public CustomException(String message, Throwable cause) { | ||||
|     super(message, cause); | ||||
|   } | ||||
| } | ||||
| @@ -36,12 +36,16 @@ import java.util.stream.StreamSupport; | ||||
|  | ||||
| import javax.sql.DataSource; | ||||
|  | ||||
| import org.apache.log4j.Logger; | ||||
|  | ||||
| /** | ||||
|  * An implementation of {@link CustomerDao} that persists customers in RDBMS.  | ||||
|  * An implementation of {@link CustomerDao} that persists customers in RDBMS. | ||||
|  * | ||||
|  */ | ||||
| public class DbCustomerDao implements CustomerDao { | ||||
|  | ||||
|   private static final Logger LOGGER = Logger.getLogger(DbCustomerDao.class); | ||||
|  | ||||
|   private final DataSource dataSource; | ||||
|  | ||||
|   /** | ||||
| @@ -65,8 +69,8 @@ public class DbCustomerDao implements CustomerDao { | ||||
|     Connection connection; | ||||
|     try { | ||||
|       connection = getConnection(); | ||||
|       PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");  //NOSONAR | ||||
|       ResultSet resultSet = statement.executeQuery(); //NOSONAR | ||||
|       PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS"); // NOSONAR | ||||
|       ResultSet resultSet = statement.executeQuery(); // NOSONAR | ||||
|       return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE,  | ||||
|           Spliterator.ORDERED) { | ||||
|  | ||||
| @@ -79,12 +83,12 @@ public class DbCustomerDao implements CustomerDao { | ||||
|             action.accept(createCustomer(resultSet)); | ||||
|             return true; | ||||
|           } catch (SQLException e) { | ||||
|             throw new RuntimeException(e); | ||||
|             throw new RuntimeException(e); // NOSONAR | ||||
|           } | ||||
|         } | ||||
|       }, false).onClose(() -> mutedClose(connection, statement, resultSet)); | ||||
|     } catch (SQLException e) { | ||||
|       throw new Exception(e.getMessage(), e); | ||||
|       throw new CustomException(e.getMessage(), e); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -98,7 +102,7 @@ public class DbCustomerDao implements CustomerDao { | ||||
|       statement.close(); | ||||
|       connection.close(); | ||||
|     } catch (SQLException e) { | ||||
|       e.printStackTrace(); | ||||
|       LOGGER.info("Exception thrown " + e.getMessage()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -113,19 +117,26 @@ public class DbCustomerDao implements CustomerDao { | ||||
|    */ | ||||
|   @Override | ||||
|   public Optional<Customer> getById(int id) throws Exception { | ||||
|  | ||||
|     ResultSet resultSet = null; | ||||
|  | ||||
|     try (Connection connection = getConnection(); | ||||
|         PreparedStatement statement =  | ||||
|             connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) { | ||||
|  | ||||
|       statement.setInt(1, id); | ||||
|       ResultSet resultSet = statement.executeQuery(); | ||||
|       resultSet = statement.executeQuery(); | ||||
|       if (resultSet.next()) { | ||||
|         return Optional.of(createCustomer(resultSet)); | ||||
|       } else { | ||||
|         return Optional.empty(); | ||||
|       } | ||||
|     } catch (SQLException ex) { | ||||
|       throw new Exception(ex.getMessage(), ex); | ||||
|       throw new CustomException(ex.getMessage(), ex); | ||||
|     } finally { | ||||
|       if (resultSet != null) { | ||||
|         resultSet.close(); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -147,7 +158,7 @@ public class DbCustomerDao implements CustomerDao { | ||||
|       statement.execute(); | ||||
|       return true; | ||||
|     } catch (SQLException ex) { | ||||
|       throw new Exception(ex.getMessage(), ex); | ||||
|       throw new CustomException(ex.getMessage(), ex); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -164,7 +175,7 @@ public class DbCustomerDao implements CustomerDao { | ||||
|       statement.setInt(3, customer.getId()); | ||||
|       return statement.executeUpdate() > 0; | ||||
|     } catch (SQLException ex) { | ||||
|       throw new Exception(ex.getMessage(), ex); | ||||
|       throw new CustomException(ex.getMessage(), ex); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -179,7 +190,7 @@ public class DbCustomerDao implements CustomerDao { | ||||
|       statement.setInt(1, customer.getId()); | ||||
|       return statement.executeUpdate() > 0; | ||||
|     } catch (SQLException ex) { | ||||
|       throw new Exception(ex.getMessage(), ex); | ||||
|       throw new CustomException(ex.getMessage(), ex); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										29
									
								
								partial-response/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								partial-response/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| --- | ||||
| layout: pattern | ||||
| title: Partial Response | ||||
| folder: partial-response | ||||
| permalink: /patterns/partial-response/ | ||||
| categories: Architectural | ||||
| tags: | ||||
|  - Java | ||||
|  - KISS | ||||
|  - YAGNI | ||||
|  - Difficulty-Beginner | ||||
| --- | ||||
|  | ||||
| ## Intent | ||||
| Send partial response from server to client on need basis. Client will specify the the fields | ||||
| that it need to server, instead of serving all details for resource.  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Applicability | ||||
| Use the Partial Response pattern when | ||||
|  | ||||
| * Client need only subset of data from resource. | ||||
| * To avoid too much data transfer over wire | ||||
|  | ||||
| ## Credits | ||||
|  | ||||
| * [Common Design Patterns](https://cloud.google.com/apis/design/design_patterns) | ||||
| * [Partial Response in RESTful API Design](http://yaoganglian.com/2013/07/01/partial-response/) | ||||
							
								
								
									
										65
									
								
								partial-response/etc/partial-response.ucls
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								partial-response/etc/partial-response.ucls
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <class-diagram version="1.2.1" icons="true" always-add-relationships="false" generalizations="true" realizations="true"  | ||||
|   associations="true" dependencies="false" nesting-relationships="true" router="FAN">   | ||||
|   <class id="1" language="java" name="com.iluwatar.partialresponse.Video" project="partial-response"  | ||||
|     file="/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="-1" width="-1" x="322" y="457"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="2" language="java" name="com.iluwatar.partialresponse.FieldJsonMapper" project="partial-response"  | ||||
|     file="/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java" binary="false"  | ||||
|     corner="BOTTOM_RIGHT">     | ||||
|     <position height="-1" width="-1" x="772" y="412"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="3" language="java" name="com.iluwatar.partialresponse.VideoClientApp" project="partial-response"  | ||||
|     file="/partial-response/src/main/java/com/iluwatar/partialresponse/VideoClientApp.java" binary="false"  | ||||
|     corner="BOTTOM_RIGHT">     | ||||
|     <position height="-1" width="-1" x="215" y="125"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="4" language="java" name="com.iluwatar.partialresponse.VideoResource" project="partial-response"  | ||||
|     file="/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java" binary="false"  | ||||
|     corner="BOTTOM_RIGHT">     | ||||
|     <position height="101" width="319" x="476" y="66"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <association id="5">     | ||||
|     <end type="SOURCE" refId="4" navigable="false">       | ||||
|       <attribute id="6" name="videos"/>       | ||||
|       <multiplicity id="7" minimum="0" maximum="2147483647"/>     | ||||
|     </end>     | ||||
|     <end type="TARGET" refId="1" navigable="true"/>     | ||||
|     <display labels="true" multiplicity="true"/>   | ||||
|   </association>   | ||||
|   <association id="8">     | ||||
|     <end type="SOURCE" refId="4" navigable="false">       | ||||
|       <attribute id="9" name="fieldJsonMapper"/>       | ||||
|       <multiplicity id="10" minimum="0" maximum="1"/>     | ||||
|     </end>     | ||||
|     <end type="TARGET" refId="2" navigable="true"/>     | ||||
|     <display labels="true" multiplicity="true"/>   | ||||
|   </association>   | ||||
|   <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|     sort-features="false" accessors="true" visibility="true">     | ||||
|     <attributes public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     <operations public="true" package="true" protected="true" private="true" static="true"/>   | ||||
|   </classifier-display>   | ||||
|   <association-display labels="true" multiplicity="true"/> | ||||
| </class-diagram> | ||||
							
								
								
									
										
											BIN
										
									
								
								partial-response/etc/partial-response.urm.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								partial-response/etc/partial-response.urm.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 27 KiB | 
							
								
								
									
										31
									
								
								partial-response/etc/partial-response.urm.puml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								partial-response/etc/partial-response.urm.puml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| @startuml | ||||
| package com.iluwatar.partialresponse { | ||||
|   class FieldJsonMapper { | ||||
|     + FieldJsonMapper() | ||||
|     - getString(video : Video, declaredField : Field) : String | ||||
|     + toJson(video : Video, fields : String[]) : String | ||||
|   } | ||||
|   class Video { | ||||
|     - description : String | ||||
|     - director : String | ||||
|     - id : Integer | ||||
|     - language : String | ||||
|     - length : Integer | ||||
|     - title : String | ||||
|     + Video(id : Integer, title : String, length : Integer, description : String, director : String, language : String) | ||||
|     + toString() : String | ||||
|   } | ||||
|   class VideoClientApp { | ||||
|     - LOGGER : Logger {static} | ||||
|     + VideoClientApp() | ||||
|     + main(args : String[]) {static} | ||||
|   } | ||||
|   class VideoResource { | ||||
|     - fieldJsonMapper : FieldJsonMapper | ||||
|     - videos : Map<Integer, Video> | ||||
|     + VideoResource(fieldJsonMapper : FieldJsonMapper, videos : Map<Integer, Video>) | ||||
|     + getDetails(id : Integer, fields : String[]) : String | ||||
|   } | ||||
| } | ||||
| VideoResource -->  "-fieldJsonMapper" FieldJsonMapper | ||||
| @enduml | ||||
							
								
								
									
										49
									
								
								partial-response/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								partial-response/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|  | ||||
|     The MIT License | ||||
|     Copyright (c) 2014 Ilkka Seppälä | ||||
|  | ||||
|     Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|     of this software and associated documentation files (the "Software"), to deal | ||||
|     in the Software without restriction, including without limitation the rights | ||||
|     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|     copies of the Software, and to permit persons to whom the Software is | ||||
|     furnished to do so, subject to the following conditions: | ||||
|  | ||||
|     The above copyright notice and this permission notice shall be included in | ||||
|     all copies or substantial portions of the Software. | ||||
|  | ||||
|     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|     THE SOFTWARE. | ||||
|  | ||||
| --> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <parent> | ||||
|         <artifactId>java-design-patterns</artifactId> | ||||
|         <groupId>com.iluwatar</groupId> | ||||
|         <version>1.17.0-SNAPSHOT</version> | ||||
|     </parent> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|  | ||||
|     <artifactId>partial-response</artifactId> | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>junit</groupId> | ||||
|             <artifactId>junit</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.mockito</groupId> | ||||
|             <artifactId>mockito-core</artifactId> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|  | ||||
| </project> | ||||
| @@ -0,0 +1,74 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2014-2017 Gopinath Langote | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package com.iluwatar.partialresponse; | ||||
|  | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * The Partial response pattern is a design pattern in which client specifies fields to fetch to serve. | ||||
|  * Here {@link App} is playing as client for {@link VideoResource} server. | ||||
|  * Client ask for specific fields information in video to server. | ||||
|  * <p> | ||||
|  * <p> | ||||
|  * {@link VideoResource} act as server to serve video information. | ||||
|  */ | ||||
|  | ||||
| public class App { | ||||
|   private static final Logger LOGGER = LoggerFactory.getLogger(App.class); | ||||
|  | ||||
|   /** | ||||
|    * Method as act client and request to server for video details. | ||||
|    * | ||||
|    * @param args program argument. | ||||
|    */ | ||||
|   public static void main(String[] args) throws Exception { | ||||
|     Map<Integer, Video> videos = new HashMap<>(); | ||||
|     videos.put(1, new Video(1, "Avatar", 178, "epic science fiction film", "James Cameron", "English")); | ||||
|     videos.put(2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese")); | ||||
|     videos.put(3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", "Christopher Nolan", "English")); | ||||
|     VideoResource videoResource = new VideoResource(new FieldJsonMapper(), videos); | ||||
|  | ||||
|  | ||||
|     LOGGER.info("Retrieving full response from server:-"); | ||||
|     LOGGER.info("Get all video information:"); | ||||
|     String videoDetails = videoResource.getDetails(1); | ||||
|     LOGGER.info(videoDetails); | ||||
|  | ||||
|     LOGGER.info("----------------------------------------------------------"); | ||||
|  | ||||
|     LOGGER.info("Retrieving partial response from server:-"); | ||||
|     LOGGER.info("Get video @id, @title, @director:"); | ||||
|     String specificFieldsDetails = videoResource.getDetails(3, "id", "title", "director"); | ||||
|     LOGGER.info(specificFieldsDetails); | ||||
|  | ||||
|     LOGGER.info("Get video @id, @length:"); | ||||
|     String videoLength = videoResource.getDetails(3, "id", "length"); | ||||
|     LOGGER.info(videoLength); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,60 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2014-2017 Gopinath Langote | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package com.iluwatar.partialresponse; | ||||
|  | ||||
| import java.lang.reflect.Field; | ||||
|  | ||||
| /** | ||||
|  * Map a video to json | ||||
|  */ | ||||
| public class FieldJsonMapper { | ||||
|  | ||||
|   /** | ||||
|    * @param video  object containing video information | ||||
|    * @param fields fields information to get | ||||
|    * @return json of required fields from video | ||||
|    */ | ||||
|   public String toJson(Video video, String[] fields) throws Exception { | ||||
|     StringBuilder json = new StringBuilder().append("{"); | ||||
|  | ||||
|     for (int i = 0, fieldsLength = fields.length; i < fieldsLength; i++) { | ||||
|       json.append(getString(video, Video.class.getDeclaredField(fields[i]))); | ||||
|       if (i != fieldsLength - 1) { | ||||
|         json.append(","); | ||||
|       } | ||||
|     } | ||||
|     json.append("}"); | ||||
|     return json.toString(); | ||||
|   } | ||||
|  | ||||
|   private String getString(Video video, Field declaredField) throws IllegalAccessException { | ||||
|     declaredField.setAccessible(true); | ||||
|     Object value = declaredField.get(video); | ||||
|     if (declaredField.get(video) instanceof Integer) { | ||||
|       return "\"" + declaredField.getName() + "\"" + ": " + value; | ||||
|     } | ||||
|     return "\"" + declaredField.getName() + "\"" + ": " + "\"" + value.toString() + "\""; | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,70 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2014-2017 Gopinath Langote | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package com.iluwatar.partialresponse; | ||||
|  | ||||
| /** | ||||
|  * {@link Video} is a entity to serve from server.It contains all video related information.. | ||||
|  * <p> | ||||
|  */ | ||||
| public class Video { | ||||
|   private final Integer id; | ||||
|   private final String title; | ||||
|   private final Integer length; | ||||
|   private final String description; | ||||
|   private final String director; | ||||
|   private final String language; | ||||
|  | ||||
|   /** | ||||
|    * @param id          video unique id | ||||
|    * @param title       video title | ||||
|    * @param length      video length in minutes | ||||
|    * @param description video description by publisher | ||||
|    * @param director    video director name | ||||
|    * @param language    video language {private, public} | ||||
|    */ | ||||
|   public Video(Integer id, String title, Integer length, String description, String director, String language) { | ||||
|     this.id = id; | ||||
|     this.title = title; | ||||
|     this.length = length; | ||||
|     this.description = description; | ||||
|     this.director = director; | ||||
|     this.language = language; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * @return json representaion of video | ||||
|    */ | ||||
|   @Override | ||||
|   public String toString() { | ||||
|     return "{" | ||||
|         + "\"id\": " + id + "," | ||||
|         + "\"title\": \"" + title + "\"," | ||||
|         + "\"length\": " + length + "," | ||||
|         + "\"description\": \"" + description + "\"," | ||||
|         + "\"director\": \"" + director + "\"," | ||||
|         + "\"language\": \"" + language + "\"," | ||||
|         + "}"; | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2014-2017 Gopinath Langote | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package com.iluwatar.partialresponse; | ||||
|  | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * The resource class which serves video information. | ||||
|  * This class act as server in the demo. Which has all video details. | ||||
|  */ | ||||
| public class VideoResource { | ||||
|   private FieldJsonMapper fieldJsonMapper; | ||||
|   private Map<Integer, Video> videos; | ||||
|  | ||||
|   /** | ||||
|    * @param fieldJsonMapper map object to json. | ||||
|    * @param videos          initialize resource with existing videos. Act as database. | ||||
|    */ | ||||
|   public VideoResource(FieldJsonMapper fieldJsonMapper, Map<Integer, Video> videos) { | ||||
|     this.fieldJsonMapper = fieldJsonMapper; | ||||
|     this.videos = videos; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * @param id     video id | ||||
|    * @param fields fields to get information about | ||||
|    * @return full response if no fields specified else partial response for given field. | ||||
|    */ | ||||
|   public String getDetails(Integer id, String... fields) throws Exception { | ||||
|     if (fields.length == 0) { | ||||
|       return videos.get(id).toString(); | ||||
|     } | ||||
|     return fieldJsonMapper.toJson(videos.get(id), fields); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2014-2017 Gopinath Langote | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package com.iluwatar.partialresponse; | ||||
|  | ||||
| import org.junit.Test; | ||||
|  | ||||
| /** | ||||
|  * Application test | ||||
|  */ | ||||
| public class AppTest { | ||||
|  | ||||
|   @Test | ||||
|   public void main() throws Exception { | ||||
|     String[] args = {}; | ||||
|     App.main(args); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2014-2017 Gopinath Langote | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package com.iluwatar.partialresponse; | ||||
|  | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
|  | ||||
| import static org.junit.Assert.assertEquals; | ||||
|  | ||||
| /** | ||||
|  * tests {@link FieldJsonMapper}. | ||||
|  */ | ||||
| public class FieldJsonMapperTest { | ||||
|   private FieldJsonMapper mapper; | ||||
|  | ||||
|   @Before | ||||
|   public void setUp() { | ||||
|     mapper = new FieldJsonMapper(); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void shouldReturnJsonForSpecifiedFieldsInVideo() throws Exception { | ||||
|     String[] fields = new String[]{"id", "title", "length"}; | ||||
|     Video video = new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese"); | ||||
|  | ||||
|     String jsonFieldResponse = mapper.toJson(video, fields); | ||||
|  | ||||
|     String expectedDetails = "{\"id\": 2,\"title\": \"Godzilla Resurgence\",\"length\": 120}"; | ||||
|     assertEquals(expectedDetails, jsonFieldResponse); | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,80 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2014-2017 Gopinath Langote | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package com.iluwatar.partialresponse; | ||||
|  | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.mockito.Mock; | ||||
| import org.mockito.runners.MockitoJUnitRunner; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.mockito.Matchers.any; | ||||
| import static org.mockito.Matchers.eq; | ||||
| import static org.mockito.Mockito.when; | ||||
|  | ||||
| /** | ||||
|  * tests {@link VideoResource}. | ||||
|  */ | ||||
| @RunWith(MockitoJUnitRunner.class) | ||||
| public class VideoResourceTest { | ||||
|   @Mock | ||||
|   private FieldJsonMapper fieldJsonMapper; | ||||
|  | ||||
|   private VideoResource resource; | ||||
|  | ||||
|   @Before | ||||
|   public void setUp() { | ||||
|     Map<Integer, Video> videos = new HashMap<>(); | ||||
|     videos.put(1, new Video(1, "Avatar", 178, "epic science fiction film", "James Cameron", "English")); | ||||
|     videos.put(2, new Video(2, "Godzilla Resurgence", 120, "Action & drama movie|", "Hideaki Anno", "Japanese")); | ||||
|     videos.put(3, new Video(3, "Interstellar", 169, "Adventure & Sci-Fi", "Christopher Nolan", "English")); | ||||
|     resource = new VideoResource(fieldJsonMapper, videos); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void shouldGiveVideoDetailsById() throws Exception { | ||||
|     String actualDetails = resource.getDetails(1); | ||||
|  | ||||
|     String expectedDetails = "{\"id\": 1,\"title\": \"Avatar\",\"length\": 178,\"description\": " | ||||
|         + "\"epic science fiction film\",\"director\": \"James Cameron\",\"language\": \"English\",}"; | ||||
|     assertEquals(expectedDetails, actualDetails); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void shouldGiveSpecifiedFieldsInformationOfVideo() throws Exception { | ||||
|     String[] fields = new String[]{"id", "title", "length"}; | ||||
|  | ||||
|     String expectedDetails = "{\"id\": 1,\"title\": \"Avatar\",\"length\": 178}"; | ||||
|     when(fieldJsonMapper.toJson(any(Video.class), eq(fields))).thenReturn(expectedDetails); | ||||
|  | ||||
|     String actualFieldsDetails = resource.getDetails(2, fields); | ||||
|  | ||||
|     assertEquals(expectedDetails, actualFieldsDetails); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										5
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -145,8 +145,9 @@ | ||||
|         <module>cqrs</module> | ||||
|         <module>event-sourcing</module> | ||||
|         <module>data-transfer-object</module> | ||||
|     <module>throttling</module> | ||||
|         <module>throttling</module> | ||||
|         <module>unit-of-work</module> | ||||
|         <module>partial-response</module> | ||||
|     </modules> | ||||
|  | ||||
|     <dependencyManagement> | ||||
| @@ -474,6 +475,8 @@ | ||||
|                         <param>decorator</param> | ||||
|                         <param>facade</param> | ||||
|                         <param>flyweight</param> | ||||
|                         <param>proxy</param> | ||||
|                         <param>chain</param> | ||||
|                     </skipForProjects> | ||||
|                 </configuration> | ||||
|             </plugin> | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 22 KiB | 
| @@ -1,72 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <class-diagram version="1.1.11" icons="true" automaticImage="PNG" always-add-relationships="false"  | ||||
|   generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true"  | ||||
|   router="FAN">   | ||||
|   <class id="1" language="java" name="com.iluwatar.proxy.WizardTowerProxy" project="proxy"  | ||||
|     file="/proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="149" width="191" x="388" y="271"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="2" language="java" name="com.iluwatar.proxy.Wizard" project="proxy"  | ||||
|     file="/proxy/src/main/java/com/iluwatar/proxy/Wizard.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="113" width="102" x="619" y="271"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <interface id="3" language="java" name="com.iluwatar.proxy.WizardTower" project="proxy"  | ||||
|     file="/proxy/src/main/java/com/iluwatar/proxy/WizardTower.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="77" width="116" x="388" y="460"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </interface>   | ||||
|   <class id="4" language="java" name="com.iluwatar.proxy.IvoryTower" project="proxy"  | ||||
|     file="/proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="113" width="116" x="761" y="271"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="5" language="java" name="com.iluwatar.proxy.App" project="proxy"  | ||||
|     file="/proxy/src/main/java/com/iluwatar/proxy/App.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="95" width="114" x="917" y="271"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <association id="6">     | ||||
|     <end type="SOURCE" refId="1" navigable="false">       | ||||
|       <attribute id="7" name="tower"/>       | ||||
|       <multiplicity id="8" minimum="0" maximum="1"/>     | ||||
|     </end>     | ||||
|     <end type="TARGET" refId="3" navigable="true"/>     | ||||
|     <display labels="true" multiplicity="true"/>   | ||||
|   </association>   | ||||
|   <realization id="9">     | ||||
|     <end type="SOURCE" refId="4"/>     | ||||
|     <end type="TARGET" refId="3"/>   | ||||
|   </realization>   | ||||
|   <realization id="10">     | ||||
|     <end type="SOURCE" refId="1"/>     | ||||
|     <end type="TARGET" refId="3"/>   | ||||
|   </realization>   | ||||
|   <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|     sort-features="false" accessors="true" visibility="true">     | ||||
|     <attributes public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     <operations public="true" package="true" protected="true" private="true" static="true"/>   | ||||
|   </classifier-display>   | ||||
|   <association-display labels="true" multiplicity="true"/> | ||||
| </class-diagram> | ||||
| @@ -1,32 +0,0 @@ | ||||
| @startuml | ||||
| package com.iluwatar.proxy { | ||||
|   class App { | ||||
|     + App() | ||||
|     + main(args : String[]) {static} | ||||
|   } | ||||
|   class IvoryTower { | ||||
|     - LOGGER : Logger {static} | ||||
|     + IvoryTower() | ||||
|     + enter(wizard : Wizard) | ||||
|   } | ||||
|   class Wizard { | ||||
|     - name : String | ||||
|     + Wizard(name : String) | ||||
|     + toString() : String | ||||
|   } | ||||
|   interface WizardTower { | ||||
|     + enter(Wizard) {abstract} | ||||
|   } | ||||
|   class WizardTowerProxy { | ||||
|     - LOGGER : Logger {static} | ||||
|     - NUM_WIZARDS_ALLOWED : int {static} | ||||
|     - numWizards : int | ||||
|     - tower : WizardTower | ||||
|     + WizardTowerProxy(tower : WizardTower) | ||||
|     + enter(wizard : Wizard) | ||||
|   } | ||||
| } | ||||
| WizardTowerProxy -->  "-tower" WizardTower | ||||
| IvoryTower ..|> WizardTower  | ||||
| WizardTowerProxy ..|> WizardTower  | ||||
| @enduml | ||||
		Reference in New Issue
	
	Block a user