View Javadoc
1   package com.srv4pos.server.api.category;
2   
3   import com.srv4pos.commons.io.InputStreamConnectionWriter;
4   import com.srv4pos.server.api.infrastructure.EmptyConnectionWriter;
5   import com.srv4pos.server.api.infrastructure.HttpMethod;
6   import com.srv4pos.server.api.infrastructure.IdentifierInfo;
7   import com.srv4pos.server.api.infrastructure.StringConnectionWriter;
8   import com.srv4pos.server.api.infrastructure.credentials.Credentials;
9   import com.srv4pos.server.api.infrastructure.http.HttpHelper;
10  import com.srv4pos.server.api.infrastructure.http.Transport;
11  import com.srv4pos.server.api.infrastructure.picture.CategoryPictureInfo;
12  import com.srv4pos.server.api.infrastructure.request.StreamResponse;
13  import com.srv4pos.server.api.infrastructure.request.StringResponse;
14  import flexjson.JSONDeserializer;
15  
16  import java.io.InputStream;
17  import java.net.URL;
18  import java.util.HashMap;
19  import java.util.List;
20  import java.util.Map;
21  
22  import static com.srv4pos.server.api.infrastructure.http.HttpHelper.CONTENT_TYPE_APPLICATION_JSON;
23  import static com.srv4pos.server.api.infrastructure.http.HttpHelper.CONTENT_TYPE_PNG;
24  import static com.srv4pos.server.api.infrastructure.http.HttpHelper.encodePictureFilename;
25  import static com.srv4pos.server.api.infrastructure.request.RequestHelper.requestStream;
26  import static com.srv4pos.server.api.infrastructure.request.RequestHelper.requestString;
27  import static com.srv4pos.server.api.infrastructure.request.RequestHelper.requestVoid;
28  import static java.lang.String.format;
29  
30  /**
31   * Service of reaching Category entity.
32   * <p>User: Kirill, Date: 05.08.13 18:00</p>.
33   */
34  public class CategoryService {
35      private URL url;
36      private Credentials credentials;
37      private Transport transport;
38  
39      /**
40       * Constructs the service.
41       *
42       * @param url         of the server
43       * @param credentials to work with the server
44       * @param transport   to know the method to reach the server
45       */
46      public CategoryService(URL url, Credentials credentials, Transport transport) {
47          this.url = url;
48          this.credentials = credentials;
49          this.transport = transport;
50      }
51  
52      /**
53       * Returns an entity.
54       *
55       * @param version    latest version of seller, may be null (if latest data needed)
56       * @param identifier identifies entity
57       * @return null if not modified since version or entity. if version is null then return value can not be null
58       * @throws com.srv4pos.server.api.exceptions.VersionConflictJsonException if version mismatch
59       * @throws com.srv4pos.server.api.exceptions.NotFoundJsonException        if entity is not found
60       * @see CategoryServiceSample
61       */
62      public CategoryInfo get(Integer version, String identifier) {
63          StringResponse response = requestString(
64                  format("%s/categories/%s", credentials.getSellerId(), identifier),
65                  HttpMethod.GET,
66                  url,
67                  credentials.toAuthentication(),
68                  HttpHelper.integerToETag(version),
69                  null,
70                  EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
71                  HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
72                  transport
73          );
74          return response == null ? null : CategoryInfo.fromJsonToCategoryInfo(response.getContent());
75      }
76  
77      /**
78       * Put category to the server.
79       *
80       * @param version      expected latest version of seller
81       * @param categoryInfo data to put
82       * @throws com.srv4pos.server.api.exceptions.VersionConflictJsonException if version mismatch
83       */
84      public void put(int version, CategoryInfo categoryInfo) {
85          requestVoid(
86                  credentials.getSellerId() + "/categories/" + categoryInfo.getIdentifier(),
87                  HttpMethod.PUT,
88                  url,
89                  credentials.toAuthentication(),
90                  HttpHelper.integerToETag(version),
91                  null,
92                  new StringConnectionWriter(categoryInfo.toJson()),
93                  HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
94                  transport
95          );
96      }
97  
98      /**
99       * Create category on the server.
100      *
101      * @param version      expected latest version of seller
102      * @param categoryInfo data to put
103      * @return generated unique identifier
104      * @throws com.srv4pos.server.api.exceptions.VersionConflictJsonException if version mismatch
105      */
106     public IdentifierInfo create(int version, CategoryInfo categoryInfo) {
107         return IdentifierInfo.fromJsonToIdentifierInfo(
108                 requestString(
109                         format("%s/categories", credentials.getSellerId()),
110                         HttpMethod.POST,
111                         url,
112                         credentials.toAuthentication(),
113                         HttpHelper.integerToETag(version),
114                         null,
115                         new StringConnectionWriter(categoryInfo.toJson()),
116                         HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
117                         transport
118                 ).getContent()
119         );
120     }
121 
122     /**
123      * Delete category from the server.
124      *
125      * @param version    current version of the entity
126      * @param identifier identifies entity
127      * @throws com.srv4pos.server.api.exceptions.VersionConflictJsonException if version mismatch
128      */
129     public void delete(int version, String identifier) {
130         requestVoid(
131                 format("%s/categories/%s", credentials.getSellerId(), identifier),
132                 HttpMethod.DELETE,
133                 url,
134                 credentials.toAuthentication(),
135                 HttpHelper.integerToETag(version),
136                 null,
137                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
138                 HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
139                 transport
140         );
141     }
142 
143     /**
144      * Returns list of item changes between two versions.
145      *
146      * @param versionFrom version from included
147      * @param versionTo   version to included
148      * @return list of items to be added, edited or deleted ({@link com.srv4pos.server.api.category.CategoryInfo#deleted} = true)
149      */
150     public List<CategoryInfo> listDiff(int versionFrom, int versionTo) {
151         StringResponse response = requestString(
152                 format("%s/categories-diff/%s/%s", credentials.getSellerId(), versionFrom, versionTo),
153                 HttpMethod.GET,
154                 url,
155                 credentials.toAuthentication(),
156                 null,
157                 null,
158                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
159                 HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
160                 transport
161         );
162         return (List<CategoryInfo>) CategoryInfo.fromJsonArrayToCategoryInfoes(response.getContent());
163     }
164 
165     /**
166      * Returns list of entities.
167      *
168      * @param version version or null if fresh data required
169      * @return list of entities which exists on current seller or null if list of entities is not modified since version
170      */
171     public List<CategoryInfo> list(Integer version) {
172         return list(version, null, null, null, null, null);
173     }
174 
175     /**
176      * Returns list of entities.
177      *
178      * @param firstResult when pagination starts or null
179      * @param maxResults  amount of items per page or null
180      * @param like        search string filter or null
181      * @param orderBy     field to order by, possible values are "IDENTIFIER", "NAME"
182      * @param orderDesc   field to direction of ordering
183      * @param version     version or null if fresh data required
184      * @return list of entities which exists on current seller or null if list of entities is not modified since version
185      */
186     public List<CategoryInfo> list(Integer version,
187                                    Integer firstResult,
188                                    Integer maxResults,
189                                    String like,
190                                    CategoryInfo.Fields orderBy,
191                                    Boolean orderDesc) {
192         HashMap<String, String> params = new HashMap<String, String>();
193         if (orderBy != null) {
194             params.put("orderBy", orderBy.name());
195         }
196         if (orderDesc != null) {
197             params.put("orderDesc", orderDesc.toString());
198         }
199         if (firstResult != null) {
200             params.put("firstResult", Integer.toString(firstResult));
201         }
202         if (maxResults != null) {
203             params.put("maxResults", Integer.toString(maxResults));
204         }
205         if (like != null) {
206             params.put("like", like);
207         }
208         StringResponse response = requestString(
209                 format("%s/categories", credentials.getSellerId()),
210                 HttpMethod.GET,
211                 url,
212                 credentials.toAuthentication(),
213                 HttpHelper.integerToETag(version),
214                 params,
215                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
216                 HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
217                 transport
218         );
219         return response == null ? null : (List<CategoryInfo>) CategoryInfo.fromJsonArrayToCategoryInfoes(response.getContent());
220     }
221 
222     /**
223      * Returns list of category pictures changes between two versions.
224      *
225      * @param versionFrom version from included
226      * @param versionTo   version to included
227      * @return list of items to be added, edited or deleted
228      * @see CategoryServiceSample
229      */
230     public List<CategoryPictureInfo> listDiffPicture(int versionFrom, int versionTo) {
231         StringResponse response = requestString(
232                 format("%s/category-images-diff/%s/%s", credentials.getSellerId(), versionFrom, versionTo),
233                 HttpMethod.GET,
234                 url,
235                 credentials.toAuthentication(),
236                 null,
237                 null,
238                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
239                 HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
240                 transport
241         );
242         return (List<CategoryPictureInfo>) CategoryPictureInfo.fromJsonArrayToCategoryPictureInfoes(response.getContent());
243     }
244 
245     /**
246      * Returns body of the picture.
247      *
248      * @param version            picture version or null if fresh content needed
249      * @param categoryIdentifier category identifier
250      * @param pictureFilename    just a normal windows filename according to {@link com.srv4pos.server.api.infrastructure.Constraints#WINDOWS_FILENAME_REGEX}
251      * @return body in bytes or null if not modified (if version parameter is not null and seller has the same version as specified)
252      * @throws com.srv4pos.server.api.exceptions.NotFoundJsonException          if image is not found
253      * @throws com.srv4pos.server.api.exceptions.ReferenceNotFoundJsonException if category is not found
254      * @see CategoryServiceSample
255      */
256     public InputStream getPicture(Integer version, String categoryIdentifier, String pictureFilename) {
257         final StreamResponse img = requestStream(
258                 formatPictureUrl(categoryIdentifier, pictureFilename, null),
259                 HttpMethod.GET,
260                 url,
261                 credentials == null ? null : credentials.toAuthentication(),
262                 HttpHelper.integerToETag(version),
263                 null,
264                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
265                 CONTENT_TYPE_PNG,
266                 transport
267         );
268         return img == null ? null : img.getContent();
269     }
270 
271     /**
272      * Returns list of picture relative paths .
273      *
274      * @param version            picture version or null if fresh content needed
275      * @param categoryIdentifier category identifier
276      * @return list of paths or null if not modified (if version parameter is not null and seller has the same version as specified)
277      * @throws com.srv4pos.server.api.exceptions.ReferenceNotFoundJsonException if seller is not found
278      * @see com.srv4pos.server.api.category.CategoryServiceSample
279      */
280     public List<String> getPicturePath(Integer version, String categoryIdentifier) {
281         final StringResponse response = requestString(
282                 format("%s/categories/%s/images", credentials.getSellerId(), categoryIdentifier),
283                 HttpMethod.GET,
284                 url,
285                 credentials.toAuthentication(),
286                 HttpHelper.integerToETag(version),
287                 null,
288                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
289                 CONTENT_TYPE_APPLICATION_JSON,
290                 transport
291         );
292 
293         return new JSONDeserializer<List<String>>().use("values", String.class).deserialize(response.getContent());
294     }
295 
296     /**
297      * Returns body of the picture for particular version number.
298      *
299      * @param pictureVersion     particular version of picture
300      * @param categoryIdentifier category identifier
301      * @param pictureFilename    just a normal windows filename according to {@link com.srv4pos.server.api.infrastructure.Constraints#WINDOWS_FILENAME_REGEX}
302      * @return body of the picture
303      * @throws com.srv4pos.server.api.exceptions.NotFoundJsonException          if image is not found
304      * @throws com.srv4pos.server.api.exceptions.ReferenceNotFoundJsonException if category is not found
305      * @see CategoryServiceSample
306      */
307     public InputStream getPictureFromHistory(Integer pictureVersion, String categoryIdentifier, String pictureFilename) {
308         final StreamResponse img = requestStream(
309                 formatPictureUrl(categoryIdentifier, pictureFilename, pictureVersion),
310                 HttpMethod.GET,
311                 url,
312                 credentials == null ? null : credentials.toAuthentication(),
313                 null,
314                 null,
315                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
316                 HttpHelper.CONTENT_TYPE_PNG,
317                 transport
318         );
319         return img == null ? null : img.getContent();
320     }
321 
322     /**
323      * Send picture to the server.
324      *
325      * @param version            expected latest version of seller
326      * @param categoryIdentifier identifier of the category. must match to {@link com.srv4pos.server.api.infrastructure.Constraints#WINDOWS_FILENAME_REGEX}
327      * @param pictureFilename    picture filename. must match to {@link com.srv4pos.server.api.infrastructure.Constraints#WINDOWS_FILENAME_REGEX}
328      * @param picture            body of the picture. method doesn't close the stream
329      * @param contentType        content type of the image
330      * @throws com.srv4pos.server.api.exceptions.ReferenceNotFoundJsonException if category is not found
331      * @throws com.srv4pos.server.api.exceptions.VersionConflictJsonException   if version doesn't match to seller version
332      * @see CategoryServiceSample
333      */
334     public void putPicture(int version, String categoryIdentifier, String pictureFilename, InputStream picture, String contentType) {
335         requestVoid(
336                 formatPictureUrl(categoryIdentifier, pictureFilename, null),
337                 HttpMethod.PUT,
338                 url,
339                 credentials.toAuthentication(),
340                 HttpHelper.integerToETag(version),
341                 null,
342                 new InputStreamConnectionWriter(picture),
343                 contentType,
344                 transport
345         );
346     }
347 
348     private String formatPictureUrl(String productIdentifier, String pictureFilename, Integer version) {
349         final String v = version == null ? "current" : version.toString();
350         return format("%s/categories/%s/images/%s/%s", credentials.getSellerId(), productIdentifier, v, encodePictureFilename(pictureFilename));
351     }
352 
353     /**
354      * Deletes specified picture.
355      *
356      * @param version            version of seller, if mismatch {@link com.srv4pos.server.api.exceptions.VersionConflictJsonException} will be thrown
357      * @param categoryIdentifier identifier of the category. must match to {@link com.srv4pos.server.api.infrastructure.Constraints#WINDOWS_FILENAME_REGEX}
358      * @param pictureFilename    picture filename. must match to {@link com.srv4pos.server.api.infrastructure.Constraints#WINDOWS_FILENAME_REGEX}
359      * @throws com.srv4pos.server.api.exceptions.ReferenceNotFoundJsonException if category is not found
360      * @throws com.srv4pos.server.api.exceptions.VersionConflictJsonException   if version doesn't match to seller version
361      * @see CategoryServiceSample
362      */
363     public void deletePicture(int version, String categoryIdentifier, String pictureFilename) {
364         requestVoid(
365                 formatPictureUrl(categoryIdentifier, pictureFilename, null),
366                 HttpMethod.DELETE,
367                 url,
368                 credentials.toAuthentication(),
369                 HttpHelper.integerToETag(version),
370                 null,
371                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
372                 HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
373                 transport
374         );
375     }
376 
377     /**
378      * Returns stats by categories.
379      *
380      * @param period           filters by date period
381      * @param cashRegisterName filters by cash register name
382      * @return {@link com.srv4pos.server.api.category.CategoriesStatsInfo} with stats.
383      * @throws com.srv4pos.server.api.exceptions.TypeMismatchJsonException if {@code period} {@link java.lang.String} isn't convertible to
384      *                                                                     {@link java.util.Date}.
385      */
386     public CategoriesStatsInfo stats(String period, String cashRegisterName) {
387 
388         Map<String, String> params = new HashMap<String, String>();
389         if (period != null) {
390             params.put("period", period);
391         }
392         if (cashRegisterName != null) {
393             params.put("cashRegisterName", cashRegisterName);
394         }
395 
396         StringResponse response = requestString(
397                 format("%s/categories/stats", credentials.getSellerId()),
398                 HttpMethod.GET,
399                 url,
400                 credentials.toAuthentication(),
401                 null,
402                 params,
403                 EmptyConnectionWriter.EMPTY_CONNECTION_WRITER,
404                 HttpHelper.CONTENT_TYPE_APPLICATION_JSON,
405                 transport
406         );
407         return response == null ? null : CategoriesStatsInfo.fromJsonToCategoriesStatsInfo(response.getContent());
408     }
409 
410 }