2 * Copyright (C) 2015 Roland Haeder
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.
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.
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/>.
17 package org.mxchange.pizzaapplication.application;
19 import java.io.IOException;
20 import java.io.UnsupportedEncodingException;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.InvocationTargetException;
23 import java.sql.SQLException;
24 import java.text.MessageFormat;
25 import java.util.Iterator;
27 import javax.servlet.ServletContext;
28 import javax.servlet.ServletException;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
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.CorruptedDatabaseFileException;
35 import org.mxchange.jcore.exceptions.UnsupportedDatabaseBackendException;
36 import org.mxchange.pizzaapplication.BasePizzaServiceSystem;
37 import org.mxchange.pizzaapplication.category.Category;
38 import org.mxchange.pizzaapplication.customer.Customer;
39 import org.mxchange.pizzaapplication.customer.PizzaServiceCustomer;
40 import org.mxchange.pizzaapplication.database.category.PizzaCategoryDatabaseConstants;
41 import org.mxchange.pizzaapplication.database.frontend.category.CategoryFrontend;
42 import org.mxchange.pizzaapplication.database.frontend.category.PizzaCategoryDatabaseFrontend;
43 import org.mxchange.pizzaapplication.database.frontend.product.PizzaProductDatabaseFrontend;
44 import org.mxchange.pizzaapplication.database.frontend.product.ProductFrontend;
45 import org.mxchange.pizzaapplication.database.product.PizzaProductDatabaseConstants;
46 import org.mxchange.pizzaapplication.exceptions.CategoryTitleAlreadyUsedException;
47 import org.mxchange.pizzaapplication.exceptions.ProductTitleAlreadyUsedException;
48 import org.mxchange.pizzaapplication.product.Product;
51 * Main application class
53 * @author Roland Haeder
55 public class PizzaServiceApplication extends BasePizzaServiceSystem implements PizzaApplication {
59 public static final String MAIN_TITLE = "Pizza-Service";
62 * Frontend for products
64 private ProductFrontend productFrontend;
67 * Frontend for categories
69 private CategoryFrontend categoryFrontend;
72 * Some singleton getter for this instance. If the instance is not set in
73 * given application, it will be created.
75 * @param context Servlet context
76 * @return This instance
77 * @throws javax.servlet.ServletException If object is not set correctly
79 public static final PizzaApplication getInstance (final ServletContext context) throws ServletException {
80 // Check application instance
81 if (context == null) {
83 throw new NullPointerException("application is null"); //NOI18N
87 PizzaApplication instance = null;
89 // Get instance from servlet application (aka. "application scope")
90 Object object = context.getAttribute("app"); //NOI18N
93 if (object instanceof PizzaApplication) {
94 // Instance is set, so casting should work
95 instance = (PizzaApplication) object;
96 } else if (object instanceof Object) {
97 // Not correct instance
98 throw new ServletException("app is not set correctly"); //NOI18N
101 // "service" is null, so initialize it
102 instance = new PizzaServiceApplication(context);
103 } catch (final UnsupportedDatabaseBackendException | SQLException | IOException | BadTokenException ex) {
104 throw new ServletException(ex);
108 context.setAttribute("app", instance); //NOI18N
112 instance.getLogger().trace(MessageFormat.format("instance={0} - EXIT!", instance)); //NOI18N
119 * For debugging purpose
121 * @param args Arguments
123 public static void main (String[] args) {
124 // Get instance and start it
125 new PizzaServiceApplication().start();
129 * Constructor with servet configuration
131 * @param context Servlet context
133 private PizzaServiceApplication (final ServletContext context) throws UnsupportedDatabaseBackendException, SQLException, IOException, BadTokenException {
134 // Temporary initialize default bundle
135 // @TODO The JSF may have better internatialization support
138 // Initialize properties from config
139 this.initProperties(context);
141 // Init database frontends
142 this.initDatabaseFrontends();
146 * Default constructor
148 private PizzaServiceApplication () {
152 * Calculates total amount of all choosen products
154 * @param request Request instance
155 * @param session Session instance
156 * @return Total amount of all choosen products
159 public int calculateTotalAmount (final HttpServletRequest request, final HttpSession session) throws ServletException {
161 this.getLogger().trace(MessageFormat.format("request={0},session={1} - CALLED!", request, session)); //NOI18N
163 // Is product and session set?
164 if (request == null) {
166 throw new NullPointerException("request is null"); //NOI18N
167 } else if (session == null) {
169 throw new NullPointerException("session is null"); //NOI18N
172 // Init/declare total price and iterator
174 Iterator<Product> iterator = this.getAvailableProducts();
176 // "Walk" over all products
177 while (iterator.hasNext()) {
179 Product product = iterator.next();
182 if (this.isProductChoosen(product, request, session)) {
183 // Then add ordered amount
184 this.getLogger().debug(MessageFormat.format("Counting {0} ...", product.getId())); //NOI18N
187 String amount = this.getAmountFromSession(product, session);
190 this.getLogger().debug(MessageFormat.format("amount={0}", amount)); //NOI18N
191 totalAmount += Integer.valueOf(amount);
193 this.getLogger().debug(MessageFormat.format("product={0},totalAmount={1}", product.getId(), totalAmount)); //NOI18N
197 this.getLogger().trace(MessageFormat.format("totalAmount={0} - EXIT!", totalAmount)); //NOI18N
199 // Return total price
204 * Calculates total price of all choosen products
206 * @param request Request instance
207 * @param session Session instance
208 * @return Total price of all choosen products
211 public float calculateTotalPrice (final HttpServletRequest request, final HttpSession session) throws ServletException {
213 this.getLogger().trace(MessageFormat.format("request={0},session={1} - CALLED!", request, session)); //NOI18N
215 // Is product and session set?
216 if (request == null) {
218 throw new NullPointerException("request is null"); //NOI18N
219 } else if (session == null) {
221 throw new NullPointerException("session is null"); //NOI18N
225 float totalPrice = 0.00f;
228 Iterator<Product> iterator = this.getAvailableProducts();
230 // "Walk" over all products
231 while (iterator.hasNext()) {
233 Product product = iterator.next();
236 if (this.isProductChoosen(product, request, session)) {
237 // Then add product's total price
238 this.getLogger().debug(MessageFormat.format("Calling getTotalPositionPriceFromRequestSession({0},request,session) ...", product.getId())); //NOI18N
239 totalPrice += this.getTotalPositionPriceFromRequestSession(product, request, session);
241 this.getLogger().debug(MessageFormat.format("product={0},totalPrice={1}", product.getId(), totalPrice)); //NOI18N
245 this.getLogger().trace(MessageFormat.format(" totalPrice={0} - EXIT!", totalPrice)); //NOI18N
247 // Return total price
252 public void doBootstrap () {
253 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
257 public void doMainLoop () {
258 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
262 public void doShutdown () {
263 throw new UnsupportedOperationException("Not supported yet."); //NOI18N
267 * Some "getter" for amount from session
269 * @param product Product instance
270 * @param session Session instance
271 * @return Amount as string
274 public String getAmountFromSession (final Product product, final HttpSession session) {
276 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
278 // Is product and session set?
279 if (product == null) {
281 throw new NullPointerException("product is null"); //NOI18N
282 } else if (session == null) {
284 throw new NullPointerException("session is null"); //NOI18N
288 Object object = this.getValueFromSession(product, session, HTTP_PARAM_AMOUNT);
290 // Is the object null?
291 if (object == null) {
293 this.getLogger().trace("Returning 0 - EXIT!"); //NOI18N
300 this.getLogger().trace(MessageFormat.format("object={0} - EXIT!", object)); //NOI18N
302 // Cast to string and return it
303 return (String) object;
307 * Some "getter" for HTML code 'checked="checked"' if the product is choosen
309 * @param product Product instance
310 * @param request Request instance
311 * @param session Session instance
312 * @return Whether the product is choosen
315 public String getCheckedHtmlFromProduct (final Product product, final HttpServletRequest request, final HttpSession session) {
317 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
319 // Is product and session set?
320 if (product == null) {
322 throw new NullPointerException("product is null"); //NOI18N
323 } else if (request == null) {
325 throw new NullPointerException("request is null"); //NOI18N
326 } else if (session == null) {
328 throw new NullPointerException("session is null"); //NOI18N
331 // First let's check if the product is choosen
332 if (this.isProductChoosen(product, request, session)) {
334 this.getLogger().trace("Returning checked=\"checked\" - EXIT!"); //NOI18N
337 return "checked=\"checked\""; //NOI18N
340 this.getLogger().trace("Returning empty string - EXIT!"); //NOI18N
348 * Some "getter" for choose from session
350 * @param product Product instance
351 * @param session Session instance
352 * @return Choose as string
355 public String getChooseFromSession (final Product product, final HttpSession session) {
357 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
359 // Is product and session set?
360 if (product == null) {
362 throw new NullPointerException("product is null"); //NOI18N
363 } else if (session == null) {
365 throw new NullPointerException("session is null"); //NOI18N
369 Object object = this.getValueFromSession(product, session, HTTP_PARAM_CHOOSE);
371 // Is the object null?
372 if (object == null) {
374 this.getLogger().debug(MessageFormat.format("Returning empty string for product={0} ...", product.getId())); //NOI18N
379 this.getLogger().trace(MessageFormat.format("object={0} - CALLED!", object)); //NOI18N
381 // Cast to string and return it
382 return (String) object;
386 * Some "getter" for HTML code 'disabled="disabled"' for e.g. submit buttons
388 * @param request Request instance
389 * @param session Session instance
390 * @return Whether the product is choosen
393 public String getDisabledHtmlFromSession (final HttpServletRequest request, final HttpSession session) throws ServletException {
395 this.getLogger().trace(MessageFormat.format("request={0},session={1} - CALLED!", request, session)); //NOI18N
397 // Is product and session set?
398 if (request == null) {
400 throw new NullPointerException("request is null"); //NOI18N
401 } else if (session == null) {
403 throw new NullPointerException("session is null"); //NOI18N
406 // Get "enabled" from request scope
407 Boolean enabled = Boolean.parseBoolean((String) request.getAttribute("enabled")); //NOI18N
410 this.getLogger().debug(MessageFormat.format("enabled={0}", enabled)); //NOI18N
412 // Is something selected?
413 if ((enabled) || (this.calculateTotalAmount(request, session) > 0)) {
415 this.getLogger().trace("Returning empty string - EXIT!"); //NOI18N
417 // Something has been choosen
421 this.getLogger().trace("Returning disabled=\"disabled\" - EXIT!"); //NOI18N
423 // Nothing choosen yet
424 return "disabled=\"disabled\""; //NOI18N
429 * Some "getter" for choosen (checkbox) from session
431 * @param product Product instance
432 * @param request Request instance
433 * @param session Session instance
434 * @return Amount as string
437 public String getPrintableChoosenFromRequestSession (final Product product, final HttpServletRequest request, final HttpSession session) {
439 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
441 // Is product and session set?
442 if (product == null) {
444 throw new NullPointerException("product is null"); //NOI18N
445 } else if (request == null) {
447 throw new NullPointerException("request is null"); //NOI18N
448 } else if (session == null) {
450 throw new NullPointerException("session is null"); //NOI18N
454 this.getLogger().debug(MessageFormat.format("Calling handleChooseFromRequestSession({0},{1},{2}) ...", product.getId(), request, session)); //NOI18N
455 String choosen = this.handleChooseFromRequestSession(product, request, session);
456 this.getLogger().debug(MessageFormat.format("product={0},choosen={1}", product.getId(), choosen)); //NOI18N
459 assert(choosen instanceof String): "choosen is null"; //NOI18N
462 if (choosen.isEmpty()) {
468 String amount = this.handleAmountFromRequestSession(product, request, session);
469 this.getLogger().debug(MessageFormat.format("product={0},amount={1}", product.getId(), amount)); //NOI18N
472 assert(amount instanceof String): "amount is null"; //NOI18N
475 if (amount.isEmpty() || "0".equals(amount)) { //NOI18N
476 // Choosen, but no amount
485 * Checks if given Product instance is available and returns a printable
486 * (human-readable) string.
488 * @param product Product instance to check
489 * @return Human-readable version of product availability
492 public String getPrintableProduktAvailability (final Product product) {
494 this.getLogger().trace(MessageFormat.format("product={0} - CALLED!", product)); //NOI18N
497 if (product == null) {
498 // Should not be null
499 throw new NullPointerException("product is null"); //NOI18N
503 if (product.getAvailable() == true) {
507 // Not, not for public
513 * Some getter for printable value from session or an empty string for null.
515 * @param session Session instance
516 * @param key Key to get
517 * @return Value from key, empty string for null
520 public Object getPrintableValeFromSession (final HttpSession session, final String key) {
522 this.getLogger().trace(MessageFormat.format("session={0},key={1} - CALLED", session, key)); //NOI18N
524 // Are both parameter not null?
525 if (session == null) {
527 throw new NullPointerException("session is null"); //NOI18N
528 } else if (key == null) {
530 throw new NullPointerException("key is null"); //NOI18N
534 Object value = this.getValueFromSession(session, key);
537 this.getLogger().debug(MessageFormat.format("value={0}", value)); //NOI18N
540 this.getLogger().trace(MessageFormat.format("Calling this.convertNullToEmpty({0}) ... - EXIT!", value)); //NOI18N
542 // Return actual value
543 return this.convertNullToEmpty(value);
547 * Some "getter" for a an array of only available products
549 * @return All products
552 public Iterator<Product> getAvailableProducts () throws ServletException {
554 // Ask frontend for a list of products
555 return this.productFrontend.getAvailableProducts();
556 } catch (final IOException | BadTokenException | SQLException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
557 throw new ServletException(ex);
562 * Some "getter" for a an array of all products
564 * @return All products
567 public Iterator<Product> getAllProducts () throws ServletException {
569 // Ask frontend for a list of products
570 return this.productFrontend.getAllProducts();
571 } catch (final IOException | BadTokenException | SQLException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
572 throw new ServletException(ex);
577 * Some "getter" for a an array of all categories
579 * @return All categories
582 public Iterator<Category> getCategories () throws ServletException {
584 // Ask frontend for a list of categories
585 return this.categoryFrontend.getCategories();
586 } catch (final IOException | BadTokenException | SQLException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
587 throw new ServletException(ex);
592 * Some "getter" for total price of position from request or session.
593 * Single price and amount is multiplyed.
595 * @param product Product instance
596 * @param request Request instance
597 * @param session Session instance
598 * @return Amount as string
601 public float getTotalPositionPriceFromRequestSession (final Product product, final HttpServletRequest request, final HttpSession session) {
603 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
605 // Is product and session set?
606 if (product == null) {
608 throw new NullPointerException("product is null"); //NOI18N
609 } else if (request == null) {
611 throw new NullPointerException("request is null"); //NOI18N
612 } else if (session == null) {
614 throw new NullPointerException("session is null"); //NOI18N
618 this.getLogger().debug(MessageFormat.format("Calling handleChooseFromRequestSession({0},{1},{2}) ...", product.getId(), request, session)); //NOI18N
619 String choosen = this.handleChooseFromRequestSession(product, request, session);
620 this.getLogger().debug(MessageFormat.format("product={0},choosen={1}", product.getId(), choosen)); //NOI18N
623 assert(choosen instanceof String): "choosen is null"; //NOI18N
626 if (choosen.isEmpty()) {
628 this.getLogger().debug(MessageFormat.format("product={0},choosen={1} - returning zero ...", product.getId(), choosen)); //NOI18N
633 String amount = this.handleAmountFromRequestSession(product, request, session);
634 this.getLogger().debug(MessageFormat.format("product={0},amount={1}", product.getId(), amount)); //NOI18N
637 assert(amount instanceof String): "amount is null"; //NOI18N
640 if (amount.isEmpty() || "0".equals(amount)) { //NOI18N
642 this.getLogger().debug(MessageFormat.format("product={0},amount={1} - returning zero ...", product.getId(), amount)); //NOI18N
647 Integer value = null;
651 // Get amount as integer
652 value = Integer.valueOf(amount);
653 } catch (final NumberFormatException e) {
655 throw new IllegalArgumentException(e);
659 float price = (product.getPrice() * value);
662 this.getLogger().trace(MessageFormat.format("product={0},price={1} - EXIT!", product.getId(), price)); //NOI18N
664 // Then multiply it with price
669 * Handler for amount from request or session
671 * @param product Product instance
672 * @param request Request instance
673 * @param session Session instance
674 * @return Amount as string
677 public String handleAmountFromRequestSession (final Product product, final HttpServletRequest request, final HttpSession session) {
679 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
681 // Is product and session set?
682 if (product == null) {
684 throw new NullPointerException("product is null"); //NOI18N
685 } else if (request == null) {
687 throw new NullPointerException("request is null"); //NOI18N
688 } else if (session == null) {
690 throw new NullPointerException("session is null"); //NOI18N
696 // Check request method
697 if (!"POST".equals(request.getMethod())) { //NOI18N
698 // Not POST, so get from session
699 return this.getAmountFromSession(product, session);
700 } else if (this.handleChooseFromRequestSession(product, request, session).isEmpty()) {
702 this.clearSessionAttribute(product, session, HTTP_PARAM_AMOUNT);
703 this.getLogger().debug(MessageFormat.format("Unsetting for product={0} in session, returning zero ...", product.getId())); //NOI18N
707 // Get attribute from request
708 object = request.getParameter(String.format(HTTP_PARAM_MASK, HTTP_PARAM_AMOUNT, product.getId()));
711 if (object instanceof String) {
712 // Try to parse it to integer
714 Integer value = Integer.valueOf((String) object);
715 } catch (final NumberFormatException ex) {
717 this.getLogger().warn(ex);
721 // Then set it in session
722 this.setValueInSession(product, session, HTTP_PARAM_AMOUNT, object);
725 return (String) object;
729 this.getLogger().trace("Calling getAmountFromSession() ..."); //NOI18N
731 // Get attribute from session
732 return this.getAmountFromSession(product, session);
736 * Checks whether the given product is choosen, request overules session.
738 * @param product Product instance
739 * @param request Request instance
740 * @param session Session instance
741 * @return Whether the product is choosen
744 public boolean isProductChoosen (final Product product, final HttpServletRequest request, final HttpSession session) {
746 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
748 // Is product and session set?
749 if (product == null) {
751 throw new NullPointerException("product is null"); //NOI18N
752 } else if (request == null) {
754 throw new NullPointerException("request is null"); //NOI18N
755 } else if (session == null) {
757 throw new NullPointerException("session is null"); //NOI18N
761 this.getLogger().debug(MessageFormat.format("Calling handleChooseFromRequestSession({0},{1},{2}) ...", product.getId(), request, session)); //NOI18N
762 String choosen = this.handleChooseFromRequestSession(product, request, session);
763 this.getLogger().debug(MessageFormat.format("product={0},choosen={1}", product.getId(), choosen)); //NOI18N
766 assert(choosen instanceof String): "choosen is null"; //NOI18N
768 // Is it not choosen?
769 if (choosen.isEmpty()) {
775 String amount = this.handleAmountFromRequestSession(product, request, session);
778 assert(amount instanceof String): "amount is not set"; //NOI18N
781 this.getLogger().trace(MessageFormat.format("amount={0} - EXIT!", amount)); //NOI18N
783 // Must not be empty and not 0
784 return (!amount.isEmpty() && !"0".equals(amount)); //NOI18N
788 * Marks all choosen products as ordered
790 * @param request Request instance
791 * @param session Session instance
794 public void markAllChoosenProductsAsOrdered (final HttpServletRequest request, final HttpSession session) throws ServletException {
796 this.getLogger().trace(MessageFormat.format("request={0},session={1} - CALLED!", request, session)); //NOI18N
799 Iterator<Product> iterator = this.getAvailableProducts();
801 // "Walk" over all products
802 while (iterator.hasNext()) {
804 Product product = iterator.next();
807 this.getLogger().debug(MessageFormat.format("product={0}", product)); //NOI18N
810 if (this.isProductChoosen(product, request, session)) {
811 // Mark product as ordered
812 this.markProductAsOrdered(product, session);
817 this.getLogger().trace("EXIT!"); //NOI18N
821 * Marks given product as choosen in session
823 * @param product Product to mark as ordered
824 * @param session Session instance
827 public void markProductAsChoosen (final Product product, final HttpSession session) {
829 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
831 // Is product and session set?
832 if (product == null) {
834 throw new NullPointerException("product is null"); //NOI18N
835 } else if (session == null) {
837 throw new NullPointerException("session is null"); //NOI18N
840 // Mark it as ordered by setting flag
841 this.getLogger().debug(MessageFormat.format("Marking product={0} as choosen.", product.getId())); //NOI18N
842 this.setValueInSession(product, session, HTTP_PARAM_CHOOSE, "1"); //NOI18N
845 this.getLogger().trace("EXIT!"); //NOI18N
849 * Marks given product as ordered in session
851 * @param product Product to mark as ordered
852 * @param session Session instance
855 public void markProductAsOrdered (final Product product, final HttpSession session) {
857 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
859 // Is product and session set?
860 if (product == null) {
862 throw new NullPointerException("product is null"); //NOI18N
863 } else if (session == null) {
865 throw new NullPointerException("session is null"); //NOI18N
868 // Mark it as ordered by setting flag
869 this.getLogger().debug(MessageFormat.format("Marking product={0} as ordered.", product.getId())); //NOI18N
870 this.setValueInSession(product, session, SESSION_ORDERED, "true"); //NOI18N
873 this.getLogger().trace("EXIT!"); //NOI18N
877 * Somewhat setter in session
879 * @param session Session instance
880 * @param key Session key to set
881 * @param value Value to set
884 public void setValueInSession (final HttpSession session, final String key, final Object value) {
886 this.getLogger().trace(MessageFormat.format("session={0},key={1},value={2} - CALLED!", session, key, value)); //NOI18N
888 synchronized(session) {
890 session.setAttribute(key, value);
894 this.getLogger().trace("EXIT!"); //NOI18N
898 * Unmarks given product as choosen in session
900 * @param product Product to unmark as choosen
901 * @param session Session instance
904 public void unmarkProductAsChoosen (final Product product, final HttpSession session) {
906 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
908 // Is product and session set?
909 if (product == null) {
911 throw new NullPointerException("product is null"); //NOI18N
912 } else if (session == null) {
914 throw new NullPointerException("session is null"); //NOI18N
917 // Mark it as ordered by setting flag
918 this.getLogger().debug(MessageFormat.format("Unmarking product={0} as choosen.", product.getId())); //NOI18N
919 this.clearSessionAttribute(product, session, HTTP_PARAM_CHOOSE);
922 this.getLogger().trace("EXIT!"); //NOI18N
926 * Unmarks given product as ordered in session
928 * @param product Product to unmark as ordered
929 * @param session Session instance
932 public void unmarkProductAsOrdered (final Product product, final HttpSession session) {
934 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
936 // Is product and session set?
937 if (product == null) {
939 throw new NullPointerException("product is null"); //NOI18N
940 } else if (session == null) {
942 throw new NullPointerException("session is null"); //NOI18N
945 // Mark it as ordered by setting flag
946 this.getLogger().debug(MessageFormat.format("Unmarking product={0} as ordered.", product.getId())); //NOI18N
947 this.clearSessionAttribute(product, session, SESSION_ORDERED);
950 this.getLogger().trace("EXIT!"); //NOI18N
954 * Clears given parameter for product in session
956 * @param product Product instance
957 * @param session Session instance
958 * @param parameter Parameter to clear
960 private void clearSessionAttribute (final Product product, final HttpSession session, final String parameter) {
962 this.getLogger().trace(MessageFormat.format("produce={0},parameter={1},session={2} - CALLED!", product, parameter, session)); //NOI18N
965 this.getLogger().debug(MessageFormat.format("Clearing product={0},parameter={1} ...", product.getId(), parameter)); //NOI18N
966 this.setValueInSession(product, session, parameter, null);
969 this.getLogger().trace("EXIT!"); //NOI18N
973 * Some getter for value from session
975 * @param product Product instance
976 * @param session Session instance
977 * @param attribute Attribute to get value from
978 * @return Value from session
980 private Object getValueFromSession (final Product product, final HttpSession session, final String attribute) {
982 this.getLogger().trace(MessageFormat.format("product={0},session={1},attribute={2} - CALLED!", product, session, attribute)); //NOI18N
985 Object value = this.getValueFromSession(session, String.format(HTTP_PARAM_MASK, attribute, product.getId()));
987 this.getLogger().debug(MessageFormat.format("product={0},attribute={1},value={2}", product.getId(), attribute, value)); //NOI18N
990 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
997 * Some getter for value from session
999 * @param session Session instance
1000 * @param key Key to get value from
1001 * @return Value from session
1003 private Object getValueFromSession (final HttpSession session, final String key) {
1005 this.getLogger().trace(MessageFormat.format("session={0},key={1} - CALLED!", session, key)); //NOI18N
1010 // Get it synchronized from session
1011 synchronized (session) {
1012 value = session.getAttribute(key);
1016 this.getLogger().trace(MessageFormat.format("value={0} - EXIT!", value)); //NOI18N
1023 * Handler for choosen (checkbox) from request or session
1025 * @param product Product instance
1026 * @param request Request instance
1027 * @param session Session instance
1028 * @return Amount as string
1030 private String handleChooseFromRequestSession (final Product product, final HttpServletRequest request, final HttpSession session) {
1032 this.getLogger().trace(MessageFormat.format("product={0},request={1},session={2} - CALLED!", product, request, session)); //NOI18N
1034 // Is product and session set?
1035 if (product == null) {
1037 throw new NullPointerException("product is null"); //NOI18N
1038 } else if (request == null) {
1040 throw new NullPointerException("request is null"); //NOI18N
1041 } else if (session == null) {
1043 throw new NullPointerException("session is null"); //NOI18N
1049 // Check request method
1050 if (!"POST".equals(request.getMethod())) { //NOI18N
1051 // Not POST, so get from session
1052 this.getLogger().trace(MessageFormat.format("Calling this.getChooseFromSession({0},{1}) ... - EXIT!", product.getId(), session)); //NOI18N
1053 return this.getChooseFromSession(product, session);
1054 } else if (this.isProductOrdered(product, session)) {
1055 // Product is ordered
1056 this.getLogger().trace(MessageFormat.format("Calling this.getChooseFromSession({0},{1}) ... - EXIT!", product.getId(), session)); //NOI18N
1057 return this.getChooseFromSession(product, session);
1058 } else if (!this.getChooseFromSession(product, session).isEmpty()) {
1060 this.getLogger().trace(MessageFormat.format("Calling this.getChooseFromSession({0},{1}) ... - EXIT!", product.getId(), session)); //NOI18N
1061 return this.getChooseFromSession(product, session);
1064 // Get reqzest element
1065 object = request.getParameter(String.format(HTTP_PARAM_MASK, HTTP_PARAM_CHOOSE, product.getId()));
1066 this.getLogger().debug(MessageFormat.format("product={0},object={1}", product.getId(), object)); //NOI18N
1069 if (object == null) {
1071 this.getLogger().debug(MessageFormat.format("Unsetting session for product={0} ...", product.getId())); //NOI18N
1072 this.clearSessionAttribute(product, session, HTTP_PARAM_CHOOSE);
1073 this.clearSessionAttribute(product, session, HTTP_PARAM_AMOUNT);
1075 // Return empty string
1079 // Then set it in session
1080 this.setValueInSession(product, session, HTTP_PARAM_CHOOSE, object);
1082 // Cast to string and return it
1083 this.getLogger().debug(MessageFormat.format("product={0} - Returning {1} ...", product.getId(), object)); //NOI18N
1084 return (String) object;
1088 * Initializes database frontends.
1090 private void initDatabaseFrontends () throws UnsupportedDatabaseBackendException, SQLException {
1092 this.productFrontend = new PizzaProductDatabaseFrontend();
1094 // Category frontend
1095 this.categoryFrontend = new PizzaCategoryDatabaseFrontend();
1099 * Checks whether given category title is already used
1101 * @param title Title of category to check
1102 * @return Whether it has been found
1104 private boolean isCategoryTitleUsed(final String title) throws IOException, SQLException, BadTokenException, CorruptedDatabaseFileException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1105 // Delegate to frontend
1106 return this.categoryFrontend.isCategoryTitleUsed(title);
1110 * Checks if given product title is already used
1111 * @param title Product title to check
1112 * @return Whether the product title has already been used
1114 private boolean isProductTitleUsed (final String title) throws IOException, SQLException, BadTokenException, CorruptedDatabaseFileException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1115 // Delegate to frontend
1116 return this.productFrontend.isProductTitleUsed(title);
1120 * Checks if the product ordered?
1122 * @param product Product instance
1123 * @param session HttpSession instance
1124 * @return Whether the product has been ordered
1126 private boolean isProductOrdered (final Product product, final HttpSession session) {
1128 this.getLogger().trace(MessageFormat.format("product={0},session={1} - CALLED!", product, session)); //NOI18N
1131 Object isOrdered = this.getValueFromSession(product, session, SESSION_ORDERED);
1132 this.getLogger().debug(MessageFormat.format("product={0},isOrdered={1}", product.getId(), isOrdered)); //NOI18N
1135 return ("true".equals(isOrdered)); //NOI18N
1139 * Somewhat setter in session
1141 * @param product Product instance
1142 * @param session Session instance
1143 * @param keyPart Key part to include in final key
1144 * @param value Value to set
1146 private void setValueInSession (final Product product, final HttpSession session, final String keyPart, final Object value) {
1148 this.getLogger().trace(MessageFormat.format("product={0},session={1},keyPart={2},value={3} - CALLED!", product, session, keyPart, value)); //NOI18N
1151 this.getLogger().debug(MessageFormat.format("Setting value={0} for product={1},keyPart={2}", value, product.getId(), keyPart)); //NOI18N
1152 this.setValueInSession(session, String.format(HTTP_PARAM_MASK, keyPart, product.getId()), value);
1155 this.getLogger().trace("EXIT!"); //NOI18N
1159 * Application starter
1161 private void start() {
1167 this.initProperties();
1168 } catch (final IOException ex) {
1170 this.abortProgramWithException(ex);
1174 Iterator<Product> iterator = null;
1178 iterator = this.getAvailableProducts();
1179 } catch (final ServletException ex) {
1180 this.abortProgramWithException(ex);
1183 // "Walk" over all products
1184 while ((iterator instanceof Iterator) && (iterator.hasNext())) {
1186 Product product = iterator.next();
1189 this.getLogger().debug(MessageFormat.format("Product {0}, {1}: {2}", product.getId(), product.getTitle(), product.getPrice())); //NOI18N
1192 // Generate fake Customer instance
1193 Customer customer = new PizzaServiceCustomer();
1196 * Need a least a gender ... :( See, that is why I don't like default
1197 * constructors, you can easily miss something important and bam! You
1198 * get an NPE. The fix here is, to have construtors (or factories) which
1199 * requires all required instances that needs to be set to get a
1200 * consitent object back.
1203 // Gender is MALE now
1204 customer.setGender(Gender.MALE);
1207 Iterator<Map.Entry<Field, Object>> it = null;
1210 // Get iterator on all its fields
1211 it = customer.iterator();
1212 } catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
1213 this.abortProgramWithException(ex);
1217 while ((it instanceof Iterator) && (it.hasNext())) {
1218 Map.Entry<Field, Object> entry = it.next();
1219 this.getLogger().debug(MessageFormat.format("entry {0}={1}", entry.getKey(), entry.getValue())); //NOI18N
1224 * Adds given category data from request to database
1226 * @param request Request instance
1229 public void doAdminAddCategory (final HttpServletRequest request) throws ServletException, CategoryTitleAlreadyUsedException {
1231 this.getLogger().trace(MessageFormat.format("request={0} - CALLED!", request)); //NOI18N
1233 // request must not be null
1234 if (request == null) {
1236 throw new NullPointerException("request is null"); //NOI18N
1240 String title = request.getParameter(PizzaCategoryDatabaseConstants.COLUMN_TITLE);
1241 String parent = request.getParameter(PizzaCategoryDatabaseConstants.COLUMN_PARENT);
1244 this.getLogger().debug(MessageFormat.format("title={0},parent={1}", title, parent)); //NOI18N
1246 // Init variables for casting
1250 if (title == null) {
1252 throw new IllegalArgumentException(MessageFormat.format("{0} is not set.", PizzaCategoryDatabaseConstants.COLUMN_TITLE)); //NOI18N
1253 } else if (title.isEmpty()) {
1255 throw new IllegalArgumentException(MessageFormat.format("{0} is empty.", PizzaCategoryDatabaseConstants.COLUMN_TITLE)); //NOI18N
1256 } else if ((parent != null) && (!parent.isEmpty())) {
1257 // "parent" is set, so check it
1259 id = Integer.parseInt(parent);
1260 } catch (final NumberFormatException e) {
1262 throw new IllegalArgumentException(e);
1267 // Try to check if title is used already
1268 if (this.isCategoryTitleUsed(title)) {
1269 // Title already used
1270 throw new CategoryTitleAlreadyUsedException(request);
1272 } catch (final IOException | SQLException | BadTokenException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
1273 throw new ServletException(ex);
1277 // The category is not found, so add it to database
1278 this.categoryFrontend.addCategory(title, id);
1279 } catch (final SQLException | IOException ex) {
1280 // Continue to throw it
1281 throw new ServletException(ex);
1285 this.getLogger().trace("EXIT!"); //NOI18N
1289 * Adds given product data from request to database
1291 * @param request Request instance
1294 public void doAdminAddProduct (final HttpServletRequest request) throws ServletException, ProductTitleAlreadyUsedException {
1296 this.getLogger().trace(MessageFormat.format("request={0} - CALLED!", request)); //NOI18N
1298 // request must not be null
1299 if (request == null) {
1301 throw new NullPointerException("request is null"); //NOI18N
1304 // Get title, price and category id
1305 String title = request.getParameter(PizzaProductDatabaseConstants.COLUMN_TITLE);
1306 String price = request.getParameter(PizzaProductDatabaseConstants.COLUMN_PRICE);
1307 String category = request.getParameter(PizzaProductDatabaseConstants.COLUMN_CATEGORY);
1308 String available = request.getParameter(PizzaProductDatabaseConstants.COLUMN_AVAILABLE);
1311 this.getLogger().debug(MessageFormat.format("title={0},price={1},category={2},available={3}", title, price, category, available)); //NOI18N
1313 // Variables for converting
1318 if (title == null) {
1320 throw new IllegalArgumentException(MessageFormat.format("{0} is not set.", PizzaProductDatabaseConstants.COLUMN_TITLE)); //NOI18N
1321 } else if (title.isEmpty()) {
1323 throw new IllegalArgumentException(MessageFormat.format("{0} is empty.", PizzaProductDatabaseConstants.COLUMN_TITLE)); //NOI18N
1324 } else if (price == null) {
1326 throw new IllegalArgumentException(MessageFormat.format("{0} is not set.", PizzaProductDatabaseConstants.COLUMN_PRICE)); //NOI18N
1327 } else if (price.isEmpty()) {
1329 throw new IllegalArgumentException(MessageFormat.format("{0} is empty.", PizzaProductDatabaseConstants.COLUMN_PRICE)); //NOI18N
1330 } else if (category == null) {
1332 throw new IllegalArgumentException(MessageFormat.format("{0} is not set.", PizzaProductDatabaseConstants.COLUMN_CATEGORY)); //NOI18N
1333 } else if (category.isEmpty()) {
1335 throw new IllegalArgumentException(MessageFormat.format("{0} is empty.", PizzaProductDatabaseConstants.COLUMN_CATEGORY)); //NOI18N
1336 } else if (available == null) {
1338 throw new IllegalArgumentException(MessageFormat.format("{0} is not set.", PizzaProductDatabaseConstants.COLUMN_AVAILABLE)); //NOI18N
1339 } else if (available.isEmpty()) {
1341 throw new IllegalArgumentException(MessageFormat.format("{0} is empty.", PizzaProductDatabaseConstants.COLUMN_AVAILABLE)); //NOI18N
1342 } else if ((!"true".equals(available)) && (!"false".equals(available))) { //NOI18N
1344 throw new IllegalArgumentException(MessageFormat.format("{0} is invalid: {1}", PizzaProductDatabaseConstants.COLUMN_AVAILABLE, available)); //NOI18N
1349 id = Long.parseLong(category);
1350 p = Float.parseFloat(price);
1351 } catch (final NumberFormatException e) {
1353 throw new IllegalArgumentException(e);
1357 Boolean a = Boolean.parseBoolean(available);
1359 // Test on product title
1361 // Try to check if title is used already
1362 if (this.isProductTitleUsed(title)) {
1363 // Title already used
1364 throw new ProductTitleAlreadyUsedException(request);
1366 } catch (final IOException | SQLException | BadTokenException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
1367 throw new ServletException(ex);
1371 // The product is not found, so add it to database
1372 this.productFrontend.addProduct(title, p, id, a);
1373 } catch (final SQLException | IOException ex) {
1374 // Continue to throw it
1375 throw new ServletException(ex);
1379 this.getLogger().trace("EXIT!"); //NOI18N
1383 * Generates link HTML code for given category's parent id, if set. This
1384 * link then points to products.jsp?category_id=x
1386 * @param category Category instance
1390 public String generateLinkForParent (final Category category) {
1392 this.getLogger().trace(MessageFormat.format("category={0} - CALLED!", category)); //NOI18N
1394 // category must not be null
1395 if (category == null) {
1397 throw new NullPointerException("category is null"); //NOI18N
1401 Long parent = category.getParent();
1405 // Product HTML code for link
1406 throw new UnsupportedOperationException(MessageFormat.format("parent={0} - Unfinished!", parent)); //NOI18N
1414 public String getPrintableProduktCategory (final Product product) throws ServletException {
1416 this.getLogger().trace(MessageFormat.format("product={0} - CALLED!", product)); //NOI18N
1418 // product must not be null
1419 if (product == null) {
1421 throw new NullPointerException("product is null"); //NOI18N
1428 // Get Category instance from product over the frontend
1429 category = this.categoryFrontend.getCategory(product);
1430 } catch (final IOException | SQLException | BadTokenException | CorruptedDatabaseFileException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
1431 throw new ServletException(ex);
1435 this.getLogger().debug(MessageFormat.format("category={0}", category)); //NOI18N
1437 String title = null;
1439 // Now get title from it and return it
1440 title = category.decodedTitle();
1441 } catch (final UnsupportedEncodingException ex) {
1442 // Continue to throw as cause
1443 throw new ServletException(ex);
1447 this.getLogger().trace(MessageFormat.format("title={0} - EXIT!", title)); //NOI18N
1454 * Checks if product's title is already used.
1456 * @param request Request instance
1457 * @return Whether the product title is already used
1458 * @throws java.io.IOException If any IO error occurs
1459 * @throws org.mxchange.jcore.exceptions.BadTokenException If a bad token was found in a file-based database backend's file ... ;-)
1460 * @throws java.sql.SQLException If any SQL error occurs
1461 * @throws org.mxchange.jcore.exceptions.CorruptedDatabaseFileException If the database file is damaged
1462 * @throws java.lang.NoSuchMethodException If a method was not found
1463 * @throws java.lang.IllegalAccessException If the method cannot be accessed
1464 * @throws java.lang.reflect.InvocationTargetException Any other problems?
1466 private boolean isProductTitleUsed (final HttpServletRequest request) throws IOException, SQLException, BadTokenException, CorruptedDatabaseFileException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1468 this.getLogger().trace(MessageFormat.format("request={0} - CALLED!", request)); //NOI18N
1471 String title = request.getParameter(PizzaProductDatabaseConstants.COLUMN_TITLE);
1473 // request must not be null and "title" must be found and non-empty
1474 if (request == null) {
1476 throw new NullPointerException("request is null"); //NOI18N
1477 } else if (title == null) {
1479 throw new IllegalArgumentException(MessageFormat.format("{0} is not set.", PizzaProductDatabaseConstants.COLUMN_TITLE)); //NOI18N
1480 } else if (title.isEmpty()) {
1482 throw new IllegalArgumentException(MessageFormat.format("{0} is empty.", PizzaProductDatabaseConstants.COLUMN_TITLE)); //NOI18N
1485 // Default is not used
1486 boolean isUsed = this.isProductTitleUsed(title);
1489 this.getLogger().trace(MessageFormat.format("isUsed={0} - EXIT!", isUsed)); //NOI18N
1496 * Handles admin form requests
1497 * @param request Request instance
1498 * @param response Response instance
1499 * @throws ServletException If something unexpected happened
1502 public void doAdminHandleProductForms (final HttpServletRequest request, final HttpServletResponse response) throws ServletException {
1504 this.getLogger().trace(MessageFormat.format("request={0},response={1} - CALLED!", request, response)); //NOI18N
1506 // request and response must both be set
1507 if (request == null) {
1509 throw new NullPointerException("request is null"); //NOI18N
1510 } else if (response == null) {
1512 throw new NullPointerException("response is null"); //NOI18N
1515 // Try this operations
1518 if ("POST".equals(request.getMethod())) { //NOI18N
1519 // Is "add/edit/delete" set?
1520 if (request.getParameter("add") != null) { //NOI18N
1521 // Is it already added?
1522 if (this.isProductTitleUsed(request)) {
1524 this.getLogger().debug("Already used, redirecting ..."); //NOI18N
1526 // Already added, so redirect here, else a ServletException will be thrown
1527 response.sendRedirect(String.format("%s/admin/product.jsp?already=1", request.getContextPath())); //NOI18N
1530 this.doAdminAddProduct(request);
1532 } else if (request.getParameter("edit") != null) { //NOI18N
1534 } else if (request.getParameter("delete") != null) { //NOI18N
1538 // Redirect to proper URL
1539 // @TODO Commented out for developing:
1540 //response.sendRedirect(request.getContextPath() + "/finished.jsp");
1542 } catch (final IOException | SQLException | BadTokenException | CorruptedDatabaseFileException | ProductTitleAlreadyUsedException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | IllegalArgumentException ex) {
1543 // Throw it as cause
1544 throw new ServletException(ex);
1548 this.getLogger().trace("EXIT!"); //NOI18N
1552 * Handles admin form requests
1553 * @param request Request instance
1554 * @param response Response instance
1555 * @throws ServletException If something unexpected happened
1558 public void doAdminHandleCategoryForms (final HttpServletRequest request, final HttpServletResponse response) throws ServletException {
1560 this.getLogger().trace(MessageFormat.format("request={0},response={1} - CALLED!", request, response)); //NOI18N
1562 // request and response must both be set
1563 if (request == null) {
1565 throw new NullPointerException("request is null"); //NOI18N
1566 } else if (response == null) {
1568 throw new NullPointerException("response is null"); //NOI18N
1571 // Try this operations
1574 if ("POST".equals(request.getMethod())) { //NOI18N
1575 // Is "add/edit/delete" set?
1576 if (request.getParameter("add") != null) { //NOI18N
1577 // Is the category title already used?
1578 if (this.isCategoryTitleUsed(request)) {
1580 this.getLogger().debug("Already used, redirecting ..."); //NOI18N
1582 // Already added, so redirect here, else a ServletException will be thrown
1583 response.sendRedirect(String.format("%s/admin/category.jsp?already=1", request.getContextPath())); //NOI18N
1586 this.doAdminAddCategory(request);
1588 } else if (request.getParameter("edit") != null) { //NOI18N
1590 } else if (request.getParameter("delete") != null) { //NOI18N
1594 // Redirect to proper URL
1595 // @TODO Commented out for developing:
1596 //response.sendRedirect(request.getContextPath() + "/finished.jsp");
1598 } catch (final IOException | SQLException | BadTokenException | CorruptedDatabaseFileException | CategoryTitleAlreadyUsedException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | IllegalArgumentException ex) {
1599 // Throw it as cause
1600 throw new ServletException(ex);
1604 this.getLogger().trace("EXIT!"); //NOI18N
1608 * Checks if category's title is already used.
1610 * @param request Request instance
1611 * @return Whether the product title is already used
1612 * @throws java.io.IOException If any IO error occurs
1613 * @throws org.mxchange.jcore.exceptions.BadTokenException If a bad token was found in a file-based database backend's file ... ;-)
1614 * @throws java.sql.SQLException If any SQL error occurs
1615 * @throws org.mxchange.jcore.exceptions.CorruptedDatabaseFileException If the database file is damaged
1616 * @throws java.lang.NoSuchMethodException If a method was not found
1617 * @throws java.lang.IllegalAccessException If the method cannot be accessed
1618 * @throws java.lang.reflect.InvocationTargetException Any other problems?
1620 private boolean isCategoryTitleUsed (final HttpServletRequest request) throws IOException, SQLException, BadTokenException, CorruptedDatabaseFileException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1622 this.getLogger().trace(MessageFormat.format("request={0} - CALLED!", request)); //NOI18N
1625 String title = request.getParameter(PizzaCategoryDatabaseConstants.COLUMN_TITLE);
1627 // request must not be null and "title" must be found and non-empty
1628 if (request == null) {
1630 throw new NullPointerException("request is null"); //NOI18N
1631 } else if (title == null) {
1633 throw new IllegalArgumentException(MessageFormat.format("{0} is not set.", PizzaCategoryDatabaseConstants.COLUMN_TITLE)); //NOI18N
1634 } else if (title.isEmpty()) {
1636 throw new IllegalArgumentException(MessageFormat.format("{0} is empty.", PizzaCategoryDatabaseConstants.COLUMN_TITLE)); //NOI18N
1639 // Default is not used
1640 boolean isUsed = this.isCategoryTitleUsed(title);
1643 this.getLogger().trace(MessageFormat.format("isUsed={0} - EXIT!", isUsed)); //NOI18N