]> git.mxchange.org Git - pizzaservice-war.git/blob - src/java/org/mxchange/pizzaapplication/application/PizzaServiceApplication.java
f858eb5a58e135b80f815cb23ca02b34e2dfb966
[pizzaservice-war.git] / src / java / org / mxchange / pizzaapplication / application / PizzaServiceApplication.java
1 /*
2  * Copyright (C) 2015 Roland Haeder
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 package org.mxchange.pizzaapplication.application;
18
19 import java.io.IOException;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.InvocationTargetException;
22 import java.sql.SQLException;
23 import java.text.MessageFormat;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.SortedMap;
27 import java.util.TreeMap;
28 import javax.servlet.ServletContext;
29 import javax.servlet.ServletException;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpSession;
32 import org.mxchange.jcore.contact.Gender;
33 import org.mxchange.jcore.exceptions.BadTokenException;
34 import org.mxchange.jcore.exceptions.UnsupportedDatabaseBackendException;
35 import org.mxchange.pizzaapplication.BasePizzaServiceSystem;
36 import org.mxchange.pizzaapplication.customer.Customer;
37 import org.mxchange.pizzaapplication.customer.PizzaServiceCustomer;
38 import org.mxchange.pizzaapplication.database.frontend.product.PizzaProductDatabaseFrontend;
39 import org.mxchange.pizzaapplication.database.frontend.product.ProductFrontend;
40 import org.mxchange.pizzaapplication.product.Product;
41
42 /**
43  *
44  * @author Roland Haeder
45  */
46 public class PizzaServiceApplication extends BasePizzaServiceSystem implements PizzaApplication {
47         /**
48          * Main title
49          */
50         public static final String MAIN_TITLE = "Pizza-Service";
51
52         /**
53          * Some singleton getter for this instance. If the instance is not set in
54          * given application, it will be created.
55          *
56          * @param context Servlet context
57          * @return This instance
58          * @throws javax.servlet.ServletException If object is not set correctly
59          */
60         public static final PizzaApplication getInstance (final ServletContext context) throws ServletException {
61                 // Check application instance
62                 if (context == null) {
63                         // Not set
64                         throw new NullPointerException("application is null"); //NOI18N
65                 }
66
67                 // Init instance
68                 PizzaApplication instance = null;
69
70                 // Get instance from servlet application (aka. "application scope")
71                 Object object = context.getAttribute("app"); //NOI18N
72
73                 // Is it set?
74                 if (object instanceof PizzaApplication) {
75                         // Instance is set, so casting should work
76                         instance = (PizzaApplication) object;
77                 } else if (object instanceof Object) {
78                         // Not correct instance
79                         throw new ServletException("app is not set correctly"); //NOI18N
80                 } else {
81                         try {
82                                 // "service" is null, so initialize it
83                                 instance = new PizzaServiceApplication(context);
84                         } catch (final UnsupportedDatabaseBackendException | SQLException | IOException | BadTokenException ex) {
85                                 throw new ServletException(ex);
86                         }
87
88                         // And set it here
89                         context.setAttribute("app", instance); //NOI18N
90                 }
91
92                 // Trace message
93                 instance.getLogger().trace(MessageFormat.format("instance={0} - EXIT!", instance)); //NOI18N
94
95                 // Return it
96                 return instance;
97         }
98
99         /**
100          * For debugging purpose
101          *
102          * @param args Arguments
103          */
104         public static void main (String[] args) {
105                 // Get instance and start it
106                 new PizzaServiceApplication().start();
107         }
108
109         /**
110          * Product list 
111          */
112         private final SortedMap<String, Product> products;
113
114         /**
115          * Private constructor
116          */
117         private PizzaServiceApplication () {
118                 // Init products instance
119                 this.products = new TreeMap<>();
120         }
121
122         /**
123          * Constructor with servet configuration
124          * @param context Servlet context
125          */
126         private PizzaServiceApplication (final ServletContext context) throws UnsupportedDatabaseBackendException, SQLException, IOException, BadTokenException {
127                 // Call other constructor first
128                 this();
129
130                 // Initialize properties from config
131                 this.initProperties(context);
132
133                 // Load available products
134                 this.fillProductsList();
135         }
136
137         /**
138          * Calculates total amount of all choosen products
139          *
140          * @param request Request instance
141          * @param session Session instance
142          * @return Total amount of all choosen products
143          */
144         @Override
145         public int calculateTotalAmount (final HttpServletRequest request, final HttpSession session) {
146                 // Trace message
147                 this.getLogger().trace(MessageFormat.format("request={0},session={1} - CALLED!", request, session)); //NOI18N
148
149                 // Is product and session set?
150                 if (request == null) {
151                         // Not set
152                         throw new NullPointerException("request is null"); //NOI18N
153                 } else if (session == null) {
154                         // Not set
155                         throw new NullPointerException("session is null"); //NOI18N
156                 }
157
158                 // Init total price
159                 int totalAmount = 0;
160
161                 // "Walk" over all products
162                 for (final Product product : this.getProducts()) {
163                         // Is this choosen?
164                         if (this.isProductChoosen(product, request, session)) {
165                                 // Then add ordered amount
166                                 this.getLogger().debug(MessageFormat.format("Counting {0} ...", product.getName())); //NOI18N
167
168                                 // Getting amount
169                                 String amount = this.getAmountFromSession(product, session);
170
171                                 // Add it up
172                                 this.getLogger().debug(MessageFormat.format("amount={0}", amount)); //NOI18N
173                                 totalAmount += Integer.valueOf(amount);
174                         }
175                         this.getLogger().debug(MessageFormat.format("product={0},totalAmount={1}", product.getName(), totalAmount)); //NOI18N
176                 }
177
178                 // Trace message
179                 this.getLogger().trace(MessageFormat.format("totalAmount={0} - EXIT!", totalAmount)); //NOI18N
180
181                 // Return total price
182                 return totalAmount;
183         }
184
185         /**
186          * Calculates total price of all choosen products
187          *
188          * @param request Request instance
189          * @param session Session instance
190          * @return Total price of all choosen products
191          */
192         @Override
193         public float calculateTotalPrice (final HttpServletRequest request, final HttpSession session) {
194                 // Trace message
195                 this.getLogger().trace(MessageFormat.format("request={0},session={1} - CALLED!", request, session)); //NOI18N
196
197                 // Is product and session set?
198                 if (request == null) {
199                         // Not set
200                         throw new NullPointerException("request is null"); //NOI18N
201                 } else if (session == null) {
202                         // Not set
203                         throw new NullPointerException("session is null"); //NOI18N
204                 }
205
206                 // Init total price
207                 float totalPrice = 0.00f;
208
209                 // "Walk" over all products
210                 for (final Product product : this.getProducts()) {
211                         // Is this choosen?
212                         if (this.isProductChoosen(product, request, session)) {
213                                 // Then add product's total price
214                                 this.getLogger().debug(MessageFormat.format("Calling getTotalPositionPriceFromRequestSession({0},request,session) ...", product.getName())); //NOI18N
215                                 totalPrice += this.getTotalPositionPriceFromRequestSession(product, request, session);
216                         }
217                         this.getLogger().debug(MessageFormat.format("product={0},totalPrice={1}", product.getName(), totalPrice)); //NOI18N
218                 }
219
220                 // Trace message
221                 this.getLogger().trace(MessageFormat.format(" totalPrice={0} - EXIT!", totalPrice)); //NOI18N
222
223                 // Return total price
224                 return totalPrice;
225         }
226
227         @Override
228         public void doBootstrap () {
229                 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
230         }
231
232         @Override
233         public void doMainLoop () {
234                 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
235         }
236
237         @Override
238         public void doShutdown () {
239                 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
240         }
241
242         /**
243          * Some "getter" for amount from session
244          *
245          * @param product Product instance
246          * @param session Session instance
247          * @return Amount as string
248          */
249         @Override
250         public String getAmountFromSession (final Product product, final HttpSession session) {
251                 // Trace message
252                 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
253
254                 // Is product and session set?
255                 if (product == null) {
256                         // Not set
257                         throw new NullPointerException("product is null"); //NOI18N
258                 } else if (session == null) {
259                         // Not set
260                         throw new NullPointerException("session is null"); //NOI18N
261                 }
262
263                 // Get attribute
264                 Object object = this.getValueFromSession(product, session, HTTP_PARAM_AMOUNT);
265
266                 // Is the object null?
267                 if (object == null) {
268                         // Trace message
269                         this.getLogger().trace("Returning 0 - EXIT!"); //NOI18N
270
271                         // Not found
272                         return "0"; //NOI18N
273                 }
274
275                 // Trace message
276                 this.getLogger().trace(MessageFormat.format("object={0} - EXIT!", object)); //NOI18N
277
278                 // Cast to string and return it
279                 return (String) object;
280         }
281
282         /**
283          * Some "getter" for HTML code 'checked="checked"' if the product is choosen
284          * 
285          * @param product Product instance
286          * @param request Request instance
287          * @param session Session instance
288          * @return Whether the product is choosen
289          */
290         @Override
291         public String getCheckedHtmlFromProduct (final Product product, final HttpServletRequest request, final HttpSession session) {
292                 // Trace message
293                 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
294
295                 // Is product and session set?
296                 if (product == null) {
297                         // Not set
298                         throw new NullPointerException("product is null"); //NOI18N
299                 } else if (request == null) {
300                         // Not set
301                         throw new NullPointerException("request is null"); //NOI18N
302                 } else if (session == null) {
303                         // Not set
304                         throw new NullPointerException("session is null"); //NOI18N
305                 }
306
307                 // First let's check if the product is choosen
308                 if (this.isProductChoosen(product, request, session)) {
309                         // Trace message
310                         this.getLogger().trace("Returning checked=\"checked\" - EXIT!"); //NOI18N
311
312                         // Is choosen
313                         return "checked=\"checked\""; //NOI18N
314                 } else {
315                         // Trace message
316                         this.getLogger().trace("Returning empty string - EXIT!"); //NOI18N
317
318                         // Not choosen
319                         return ""; //NOI18N
320                 }
321         }
322
323         /**
324          * Some "getter" for choose from session
325          * 
326          * @param product Product instance
327          * @param session Session instance
328          * @return Choose as string
329          */
330         @Override
331         public String getChooseFromSession (final Product product, final HttpSession session) {
332                 // Trace message
333                 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
334
335                 // Is product and session set?
336                 if (product == null) {
337                         // Not set
338                         throw new NullPointerException("product is null"); //NOI18N
339                 } else if (session == null) {
340                         // Not set
341                         throw new NullPointerException("session is null"); //NOI18N
342                 }
343
344                 // Get attribute
345                 Object object = this.getValueFromSession(product, session, HTTP_PARAM_CHOOSE);
346
347                 // Is the object null?
348                 if (object == null) {
349                         // Not found
350                         this.getLogger().debug(MessageFormat.format("Returning empty string for product={0} ...", product.getName())); //NOI18N
351                         return ""; //NOI18N
352                 }
353
354                 // Trace message
355                 this.getLogger().trace(MessageFormat.format("object={0} - CALLED!", object)); //NOI18N
356
357                 // Cast to string and return it
358                 return (String) object;
359         }
360
361         /**
362          * Some "getter" for HTML code 'disabled="disabled"' for e.g. submit buttons
363          *
364          * @param request Request instance
365          * @param session Session instance
366          * @return Whether the product is choosen
367          */
368         @Override
369         public String getDisabledHtmlFromSession (final HttpServletRequest request, final HttpSession session) {
370                 // Trace message
371                 this.getLogger().trace(MessageFormat.format("request={0},session={1} - CALLED!", request, session)); //NOI18N
372
373                 // Is product and session set?
374                 if (request == null) {
375                         // Not set
376                         throw new NullPointerException("request is null"); //NOI18N
377                 } else if (session == null) {
378                         // Not set
379                         throw new NullPointerException("session is null"); //NOI18N
380                 }
381
382                 // Is something selected?
383                 if (this.calculateTotalAmount(request, session) > 0) {
384                         // Trace message
385                         this.getLogger().trace("Returning empty string - EXIT!"); //NOI18N
386
387                         // Something has been choosen
388                         return ""; //NOI18N
389                 } else {
390                         // Trace message
391                         this.getLogger().trace("Returning disabled=\"disabled\" - EXIT!"); //NOI18N
392
393                         // Nothing choosen yet
394                         return "disabled=\"disabled\""; //NOI18N
395                 }
396         }
397
398         /**
399          * Some "getter" for choosen (checkbox) from session
400          *
401          * @param product Product instance
402          * @param request Request instance
403          * @param session Session instance
404          * @return Amount as string
405          */
406         @Override
407         public String getPrintableChoosenFromRequestSession (final Product product, final HttpServletRequest request, final HttpSession session) {
408                 // Trace message
409                 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
410
411                 // Is product and session set?
412                 if (product == null) {
413                         // Not set
414                         throw new NullPointerException("product is null"); //NOI18N
415                 } else if (request == null) {
416                         // Not set
417                         throw new NullPointerException("request is null"); //NOI18N
418                 } else if (session == null) {
419                         // Not set
420                         throw new NullPointerException("session is null"); //NOI18N
421                 }
422
423                 // Get element
424                 this.getLogger().debug(MessageFormat.format("Calling handleChooseFromRequestSession({0},{1},{2}) ...", product.getName(), request, session)); //NOI18N
425                 String choosen = this.handleChooseFromRequestSession(product, request, session);
426                 this.getLogger().debug(MessageFormat.format("product={0},choosen={1}", product.getName(), choosen)); //NOI18N
427
428                 // Must not be null
429                 assert(choosen instanceof String): "choosen is null"; //NOI18N
430
431                 // Is it empty?
432                 if (choosen.isEmpty()) {
433                         // Not choosen
434                         return "Nein";
435                 }
436
437                 // Get amount
438                 String amount = this.handleAmountFromRequestSession(product, request, session);
439                 this.getLogger().debug(MessageFormat.format("product={0},amount={1}", product.getName(), amount)); //NOI18N
440
441                 // Must not be null
442                 assert(amount instanceof String): "amount is null"; //NOI18N
443
444                 // Is it empty?
445                 if (amount.isEmpty() || "0".equals(amount)) { //NOI18N
446                         // Choosen, but no amount
447                         return "Nein";
448                 } else {
449                         // Is choosen
450                         return "Ja";
451                 }
452         }
453
454         /**
455          * Some getter for printable value from session or an empty string for null.
456          *
457          * @param session Session instance
458          * @param key Key to get
459          * @return Value from key, empty string for null
460          */
461         @Override
462         public Object getPrintableValeFromSession (final HttpSession session, final String key) {
463                 // Trace message
464                 this.getLogger().trace(MessageFormat.format("session={0},key={1} - CALLED", session, key)); //NOI18N
465
466                 // Are both parameter not null?
467                 if (session == null) {
468                         // Abort here
469                         throw new NullPointerException("session is null"); //NOI18N
470                 } else  if (key == null) {
471                         // Abort here
472                         throw new NullPointerException("key is null"); //NOI18N
473                 }
474
475                 // Now get it
476                 Object value = this.getValueFromSession(session, key);
477
478                 // Debug message
479                 this.getLogger().debug(MessageFormat.format("value={0}", value)); //NOI18N
480
481                 // Trace message
482                 this.getLogger().trace(MessageFormat.format("Calling this.convertNullToEmpty({0}) ... - EXIT!", value)); //NOI18N
483
484                 // Return actual value
485                 return this.convertNullToEmpty(value);
486         }
487
488         /**
489          * Some "getter" for a an array of all products
490          *
491          * @return Unmarked products
492          */
493         @Override
494         public Product[] getProducts () {
495                 return this.products.values().toArray(new Product[this.products.size()]);
496         }
497
498         /**
499          * Some "getter" for total price of position from request or session.
500          * Single price and amount is multiplyed.
501          *
502          * @param product Product instance
503          * @param request Request instance
504          * @param session Session instance
505          * @return Amount as string
506          */
507         @Override
508         public float getTotalPositionPriceFromRequestSession (final Product product, final HttpServletRequest request, final HttpSession session) {
509                 // Trace message
510                 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
511
512                 // Is product and session set?
513                 if (product == null) {
514                         // Not set
515                         throw new NullPointerException("product is null"); //NOI18N
516                 } else if (request == null) {
517                         // Not set
518                         throw new NullPointerException("request is null"); //NOI18N
519                 } else if (session == null) {
520                         // Not set
521                         throw new NullPointerException("session is null"); //NOI18N
522                 }
523
524                 // Get choosen
525                 this.getLogger().debug(MessageFormat.format("Calling handleChooseFromRequestSession({0},{1},{2}) ...", product.getName(), request, session)); //NOI18N
526                 String choosen = this.handleChooseFromRequestSession(product, request, session);
527                 this.getLogger().debug(MessageFormat.format("product={0},choosen={1}", product.getName(), choosen)); //NOI18N
528
529                 // Must not be null
530                 assert(choosen instanceof String): "choosen is null"; //NOI18N
531
532                 // Is it set?
533                 if (choosen.isEmpty()) {
534                         // Is empty
535                         this.getLogger().debug(MessageFormat.format("product={0},choosen={1} - returning zero ...", product.getName(), choosen)); //NOI18N
536                         return 0.00f;
537                 }
538
539                 // Get amount
540                 String amount = this.handleAmountFromRequestSession(product, request, session);
541                 this.getLogger().debug(MessageFormat.format("product={0},amount={1}", product.getName(), amount)); //NOI18N
542
543                 // Must not be null
544                 assert(amount instanceof String): "amount is null"; //NOI18N
545
546                 // Is it empty?
547                 if (amount.isEmpty() || "0".equals(amount)) { //NOI18N
548                         // Is empty
549                         this.getLogger().debug(MessageFormat.format("product={0},amount={1} - returning zero ...", product.getName(), amount)); //NOI18N
550                         return 0.00f;
551                 }
552
553                 // Init variable
554                 Integer value = null;
555
556                 // Try it
557                 try {
558                         // Get amount as integer
559                         value = Integer.valueOf(amount);
560                 } catch (final NumberFormatException e) {
561                         // Bat input
562                         throw new IllegalArgumentException(e);
563                 }
564
565                 // Calculate price
566                 float price = (product.getPrice() * value);
567
568                 // Trace message
569                 this.getLogger().trace(MessageFormat.format("product={0},price={1} - EXIT!", product.getName(), price)); //NOI18N
570
571                 // Then multiply it with price
572                 return price;
573         }
574
575         /**
576          * Gets an array of products from product iterator and unmarks them as ordered
577          *
578          * @param session HttpSession instance
579          * @return Unmarked products
580          */
581         @Override
582         public Product[] getUnmarkedProducts (final HttpSession session) {
583                 // Init array
584                 Product[] array = this.getProducts();
585
586                 // Unmark are all as ordered
587                 for (final Product product : array) {
588                         this.unmarkProductAsOrdered(product, session);
589                 }
590
591                 // Return finished array
592                 return array;
593         }
594
595         /**
596          * Handler for amount from request or session
597          *
598          * @param product Product instance
599          * @param request Request instance
600          * @param session Session instance
601          * @return Amount as string
602          */
603         @Override
604         public String handleAmountFromRequestSession (final Product product, final HttpServletRequest request, final HttpSession session) {
605                 // Trace message
606                 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
607
608                 // Is product and session set?
609                 if (product == null) {
610                         // Not set
611                         throw new NullPointerException("product is null"); //NOI18N
612                 } else if (request == null) {
613                         // Not set
614                         throw new NullPointerException("request is null"); //NOI18N
615                 } else if (session == null) {
616                         // Not set
617                         throw new NullPointerException("session is null"); //NOI18N
618                 }
619
620                 // Init variabke
621                 Object object;
622
623                 // Check request method
624                 if (!"POST".equals(request.getMethod())) { //NOI18N
625                         // Not POST, so get from session
626                         return this.getAmountFromSession(product, session);
627                 } else if (this.handleChooseFromRequestSession(product, request, session).isEmpty()) {
628                         // Not choosen
629                         this.clearSessionAttribute(product, session, HTTP_PARAM_AMOUNT);
630                         this.getLogger().debug(MessageFormat.format("Unsetting for product={0} in session, returning zero ...", product.getName())); //NOI18N
631                         return "0"; //NOI18N
632                 }
633
634                 // Get attribute from request
635                 object = request.getParameter(String.format(HTTP_PARAM_MASK, HTTP_PARAM_AMOUNT, product.getName()));
636
637                 // Is it set?
638                 if (object instanceof String) {
639                         // Try to parse it to integer
640                         try {
641                                 Integer value = Integer.valueOf((String) object);
642                         } catch (final NumberFormatException ex) {
643                                 // Not valid input
644                                 this.getLogger().warn(ex);
645                                 return "0"; //NOI18N
646                         }
647
648                         // Then set it in session
649                         this.setValueInSession(product, session, HTTP_PARAM_AMOUNT, object);
650
651                         // And return it
652                         return (String) object;
653                 }
654
655                 // Trace message
656                 this.getLogger().trace("Calling getAmountFromSession() ..."); //NOI18N
657
658                 // Get attribute from session
659                 return this.getAmountFromSession(product, session);
660         }
661
662         /**
663          * Checks whether the given product is choosen, request overules session.
664          *
665          * @param product Product instance
666          * @param request Request instance
667          * @param session Session instance
668          * @return Whether the product is choosen
669          */
670         @Override
671         public boolean isProductChoosen (final Product product, final HttpServletRequest request, final HttpSession session) {
672                 // Trace message
673                 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
674
675                 // Is product and session set?
676                 if (product == null) {
677                         // Not set
678                         throw new NullPointerException("product is null"); //NOI18N
679                 } else if (request == null) {
680                         // Not set
681                         throw new NullPointerException("request is null"); //NOI18N
682                 } else if (session == null) {
683                         // Not set
684                         throw new NullPointerException("session is null"); //NOI18N
685                 }
686
687                 // Get choosen
688                 this.getLogger().debug(MessageFormat.format("Calling handleChooseFromRequestSession({0},{1},{2}) ...", product.getName(), request, session)); //NOI18N
689                 String choosen = this.handleChooseFromRequestSession(product, request, session);
690                 this.getLogger().debug(MessageFormat.format("product={0},choosen={1}", product.getName(), choosen)); //NOI18N
691
692                 // Must not be null
693                 assert(choosen instanceof String): "choosen is null"; //NOI18N
694
695                 // Is it not choosen?
696                 if (choosen.isEmpty()) {
697                         // Not choosen
698                         return false;
699                 }
700
701                 // Get amount
702                 String amount = this.handleAmountFromRequestSession(product, request, session);
703
704                 // Must not be null
705                 assert(amount instanceof String): "amount is not set"; //NOI18N
706
707                 // Trace message
708                 this.getLogger().trace(MessageFormat.format("amount={0} - EXIT!", amount)); //NOI18N
709
710                 // Must not be empty and not 0
711                 return (!amount.isEmpty() && !"0".equals(amount)); //NOI18N
712         }
713
714         /**
715          * Marks given product as choosen in session
716          *
717          * @param product Product to mark as ordered
718          * @param session Session instance
719          */
720         @Override
721         public void markProductAsChoosen (final Product product, final HttpSession session) {
722                 // Trace message
723                 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
724
725                 // Is product and session set?
726                 if (product == null) {
727                         // Not set
728                         throw new NullPointerException("product is null"); //NOI18N
729                 } else if (session == null) {
730                         // Not set
731                         throw new NullPointerException("session is null"); //NOI18N
732                 }
733
734                 // Mark it as ordered by setting flag
735                 this.getLogger().debug(MessageFormat.format("Marking product={0} as choosen.", product.getName())); //NOI18N
736                 this.setValueInSession(product, session, HTTP_PARAM_CHOOSE, "1"); //NOI18N
737
738                 // Trace message
739                 this.getLogger().trace("EXIT!"); //NOI18N
740         }
741
742         /**
743          * Marks given product as ordered in session
744          *
745          * @param product Product to mark as ordered
746          * @param session Session instance
747          */
748         @Override
749         public void markProductAsOrdered (final Product product, final HttpSession session) {
750                 // Trace message
751                 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
752
753                 // Is product and session set?
754                 if (product == null) {
755                         // Not set
756                         throw new NullPointerException("product is null"); //NOI18N
757                 } else if (session == null) {
758                         // Not set
759                         throw new NullPointerException("session is null"); //NOI18N
760                 }
761
762                 // Mark it as ordered by setting flag
763                 this.getLogger().debug(MessageFormat.format("Marking product={0} as ordered.", product.getName())); //NOI18N
764                 this.setValueInSession(product, session, SESSION_ORDERED, "true"); //NOI18N
765
766                 // Trace message
767                 this.getLogger().trace("EXIT!"); //NOI18N
768         }
769
770         /**
771          * Somewhat setter in session
772          *
773          * @param session Session instance
774          * @param key Session key to set
775          * @param value Value to set
776          */
777         @Override
778         public void setValueInSession (final HttpSession session, final String key, final Object value) {
779                 // Trace message
780                 this.getLogger().trace(MessageFormat.format("session={0},key={1},value={2} - CALLED!", session, key, value)); //NOI18N
781
782                 synchronized(session) {
783                         // Set it synced
784                         session.setAttribute(key, value);
785                 }
786
787                 // Trace message
788                 this.getLogger().trace("EXIT!"); //NOI18N
789         }
790
791         /**
792          * Unmarks given product as choosen in session
793          *
794          * @param product Product to unmark as choosen
795          * @param session Session instance
796          */
797         @Override
798         public void unmarkProductAsChoosen (final Product product, final HttpSession session) {
799                 // Trace message
800                 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
801
802                 // Is product and session set?
803                 if (product == null) {
804                         // Not set
805                         throw new NullPointerException("product is null"); //NOI18N
806                 } else if (session == null) {
807                         // Not set
808                         throw new NullPointerException("session is null"); //NOI18N
809                 }
810
811                 // Mark it as ordered by setting flag
812                 this.getLogger().debug(MessageFormat.format("Unmarking product={0} as choosen.", product.getName())); //NOI18N
813                 this.clearSessionAttribute(product, session, HTTP_PARAM_CHOOSE);
814
815                 // Trace message
816                 this.getLogger().trace("EXIT!"); //NOI18N
817         }
818
819         /**
820          * Unmarks given product as ordered in session
821          *
822          * @param product Product to unmark as ordered
823          * @param session Session instance
824          */
825         @Override
826         public void unmarkProductAsOrdered (final Product product, final HttpSession session) {
827                 // Trace message
828                 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
829
830                 // Is product and session set?
831                 if (product == null) {
832                         // Not set
833                         throw new NullPointerException("product is null"); //NOI18N
834                 } else if (session == null) {
835                         // Not set
836                         throw new NullPointerException("session is null"); //NOI18N
837                 }
838
839                 // Mark it as ordered by setting flag
840                 this.getLogger().debug(MessageFormat.format("Unmarking product={0} as ordered.", product.getName())); //NOI18N
841                 this.clearSessionAttribute(product, session, SESSION_ORDERED);
842
843                 // Trace message
844                 this.getLogger().trace("EXIT!"); //NOI18N
845         }
846
847         /**
848          * Adds given product to list or throws an exception if name is already found
849          *
850          * @param product Product instance to add
851          */
852         private void addProduct (final Product product) {
853                 // Trace message
854                 this.getLogger().trace(MessageFormat.format("product={0} - CALLED!", product)); //NOI18N
855
856                 // Get all data from it
857                 String name = product.getName();
858
859                 // Is the name already used?
860                 if (this.isProductNameUsed(name)) {
861                         // Something went wrong
862                         throw new IllegalArgumentException(MessageFormat.format("product {0} is already used.", name)); //NOI18N
863                 }
864
865                 // Debug message
866                 this.getLogger().debug(MessageFormat.format("Adding product={0} ...", product)); //NOI18N
867
868                 // Add it
869                 this.products.put(product.getName(), product);
870
871                 // Trace message
872                 this.getLogger().trace("EXIT!"); //NOI18N
873         }
874
875         /**
876          * Clears given parameter for product in session
877          *
878          * @param product Product instance
879          * @param session Session instance
880          * @param parameter Parameter to clear
881          */
882         private void clearSessionAttribute (final Product product, final HttpSession session, final String parameter) {
883                 // Trace message
884                 this.getLogger().trace(MessageFormat.format("produce={0},parameter={1},session={2} - CALLED!", product, parameter, session)); //NOI18N
885
886                 // Clear in session
887                 this.getLogger().debug(MessageFormat.format("Clearing product={0},parameter={1} ...", product.getName(), parameter)); //NOI18N
888                 this.setValueInSession(product, session, parameter, null);
889
890                 // Trace message
891                 this.getLogger().trace("EXIT!"); //NOI18N
892         }
893
894         /**
895          * Fills products list
896          * @todo Very hard-coded stuff ...
897          */
898         private void fillProductsList () throws UnsupportedDatabaseBackendException, SQLException, IOException, BadTokenException {
899                 // Trace message
900                 this.getLogger().trace("CALLED!"); //NOI18N
901
902                 // Get a product frontend
903                 ProductFrontend frontend = new PizzaProductDatabaseFrontend();
904
905                 // Get iterator
906                 Iterator<Product> iterator = frontend.getProducts();
907
908                 // Get all products
909                 while (iterator.hasNext()) {
910                         // Get it
911                         Product product = iterator.next();
912
913                         // Add it
914                         this.addProduct(product);
915                 }
916
917                 // Trace message
918                 this.getLogger().trace("EXIT!"); //NOI18N
919         }
920
921         /**
922          * Some getter for value from session
923          *
924          * @param product Product instance
925          * @param session Session instance
926          * @param attribute Attribute to get value from
927          * @return Value from session
928          */
929         private Object getValueFromSession (final Product product, final HttpSession session, final String attribute) {
930                 // Trace message
931                 this.getLogger().trace(MessageFormat.format("product={0},session={1},attribute={2} - CALLED!", product, session, attribute)); //NOI18N
932
933                 // Init variable
934                 Object value = this.getValueFromSession(session, String.format(HTTP_PARAM_MASK, attribute, product.getName()));
935                 
936                 this.getLogger().debug(MessageFormat.format("product={0},attribute={1},value={2}", product.getName(), attribute, value)); //NOI18N
937
938                 // Trace message
939                 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
940
941                 // Return it
942                 return value;
943         }
944
945         /**
946          * Some getter for value from session
947          *
948          * @param session Session instance
949          * @param key Key to get value from
950          * @return Value from session
951          */
952         private Object getValueFromSession (final HttpSession session, final String key) {
953                 // Trace message
954                 this.getLogger().trace(MessageFormat.format("session={0},key={1} - CALLED!", session, key)); //NOI18N
955
956                 // Init value
957                 Object value = null;
958
959                 // Get it synchronized from session
960                 synchronized (session) {
961                         value = session.getAttribute(key);
962                 }
963
964                 // Trace message
965                 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
966
967                 // Return it
968                 return value;
969         }
970
971         /**
972          * Handler for choosen (checkbox) from request or session
973          *
974          * @param product Product instance
975          * @param request Request instance
976          * @param session Session instance
977          * @return Amount as string
978          */
979         private String handleChooseFromRequestSession(final Product product, final HttpServletRequest request, final HttpSession session) {
980                 // Trace message
981                 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
982
983                 // Is product and session set?
984                 if (product == null) {
985                         // Not set
986                         throw new NullPointerException("product is null"); //NOI18N
987                 } else if (request == null) {
988                         // Not set
989                         throw new NullPointerException("request is null"); //NOI18N
990                 } else if (session == null) {
991                         // Not set
992                         throw new NullPointerException("session is null"); //NOI18N
993                 }
994
995                 // Init variabke
996                 Object object;
997
998                 // Check request method
999                 if (!"POST".equals(request.getMethod())) { //NOI18N
1000                         // Not POST, so get from session
1001                         this.getLogger().trace(MessageFormat.format("Calling this.getChooseFromSession({0},{1}) ... - EXIT!", product.getName(), session));
1002                         return this.getChooseFromSession(product, session);
1003                 } else if (this.isProductOrdered(product, session)) {
1004                         // Product is ordered
1005                         this.getLogger().trace(MessageFormat.format("Calling this.getChooseFromSession({0},{1}) ... - EXIT!", product.getName(), session));
1006                         return this.getChooseFromSession(product, session);
1007                 } else if (!this.getChooseFromSession(product, session).isEmpty()) {
1008                         // Found in session
1009                         this.getLogger().trace(MessageFormat.format("Calling this.getChooseFromSession({0},{1}) ... - EXIT!", product.getName(), session));
1010                         return this.getChooseFromSession(product, session);
1011                 }
1012
1013                 // Get reqzest element
1014                 object = request.getParameter(String.format(HTTP_PARAM_MASK, HTTP_PARAM_CHOOSE, product.getName()));
1015                 this.getLogger().debug(MessageFormat.format("product={0},object={1}", product.getName(), object)); //NOI18N
1016
1017                 // Is it null?
1018                 if (object == null) {
1019                         // Unset session
1020                         this.getLogger().debug(MessageFormat.format("Unsetting session for product={0} ...", product.getName())); //NOI18N
1021                         this.clearSessionAttribute(product, session, HTTP_PARAM_CHOOSE);
1022                         this.clearSessionAttribute(product, session, HTTP_PARAM_AMOUNT);
1023
1024                         // Return empty string
1025                         return ""; //NOI18N
1026                 }
1027
1028                 // Then set it in session
1029                 this.setValueInSession(product, session, HTTP_PARAM_CHOOSE, object);
1030
1031                 // Cast to string and return it
1032                 this.getLogger().debug(MessageFormat.format("product={0} - Returning {1} ...", product.getName(), object)); //NOI18N
1033                 return (String) object;
1034         }
1035
1036         /**
1037          * Checks whether given product is already used
1038          *
1039          * @param name Name of product
1040          * @return Whether the given product's name is already used
1041          */
1042         private boolean isProductNameUsed(final String name) {
1043                 // Trace message
1044                 this.getLogger().trace(MessageFormat.format("name={0} - CALLED!", name)); //NOI18N
1045
1046                 // Is it found?
1047                 return this.products.containsKey(name);
1048         }
1049
1050         /**
1051          * Checks if the product ordered?
1052          *
1053          * @param product
1054          * @param session
1055          * @return
1056          */
1057         private boolean isProductOrdered(final Product product, final HttpSession session) {
1058                 // Trace message
1059                 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
1060
1061                 // Get session
1062                 Object isOrdered = this.getValueFromSession(product, session, SESSION_ORDERED);
1063                 this.getLogger().debug(MessageFormat.format("product={0},isOrdered={1}", product.getName(), isOrdered)); //NOI18N
1064
1065                 // Return result
1066                 return ("true".equals(isOrdered)); //NOI18N
1067         }
1068
1069         /**
1070          * Somewhat setter in session
1071          *
1072          * @param product Product instance
1073          * @param session Session instance
1074          * @param keyPart Key part to include in final key
1075          * @param value Value to set
1076          */
1077         private void setValueInSession (final Product product, final HttpSession session, final String keyPart, final Object value) {
1078                 // Trace message
1079                 this.getLogger().trace(MessageFormat.format("product={0},session={1},keyPart={2},value={3} - CALLED!", product, session, keyPart, value)); //NOI18N
1080
1081                 // Set it synced
1082                 this.getLogger().debug(MessageFormat.format("Setting value={0} for product={1},keyPart={2}", value, product.getName(), keyPart)); //NOI18N
1083                 this.setValueInSession(session, String.format(HTTP_PARAM_MASK, keyPart, product.getName()), value);
1084
1085                 // Trace message
1086                 this.getLogger().trace("EXIT!"); //NOI18N
1087         }
1088         
1089         /**
1090          * Application starter
1091          */
1092         private void start () {
1093                 // Init bundle
1094                 this.initBundle();
1095
1096                 try {
1097                         // Init properties
1098                         this.initProperties();
1099
1100                         // Fill products list
1101                         this.fillProductsList();
1102                 } catch (final IOException | UnsupportedDatabaseBackendException | SQLException | BadTokenException ex) {
1103                         // Abort here
1104                         this.abortProgramWithException(ex);
1105                 }
1106
1107                 // "Walk" over all products
1108                 for (final Product product : this.getProducts()) {
1109                         // Output data
1110                         this.getLogger().debug(MessageFormat.format("Product {0}, {1}: {2}", product.getName(), product.getTitle(), product.getPrice())); //NOI18N
1111                 }
1112
1113                 // Generate fake Customer instance
1114                 Customer customer = new PizzaServiceCustomer();
1115
1116                 /*
1117                  * Need a least a gender ... :( See, that is why I don't like default
1118                  * constructors, you can easily miss something important and bam! You
1119                  * get an NPE. The fix here is, to have construtors (or factories) which
1120                  * requires all required instances that needs to be set to get a
1121                  * consitent object back.
1122                  */
1123
1124                 // Gender is MALE now
1125                 customer.setGender(Gender.MALE);
1126
1127                 // Init iterator
1128                 Iterator<Map.Entry<Field, Object>> it = null;
1129
1130                 try {
1131                         // Get iterator on all its fields
1132                         it = customer.iterator();
1133                 } catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
1134                         this.abortProgramWithException(ex);
1135                 }
1136
1137                 // Output it
1138                 while ((it instanceof Iterator) && (it.hasNext())) {
1139                         Map.Entry<Field, Object> entry = it.next();
1140                         this.getLogger().debug(MessageFormat.format("entry {0}={1}", entry.getKey(), entry.getValue())); //NOI18N
1141                 }
1142         }
1143 }