From: Roland Häder Date: Sat, 15 Apr 2017 21:57:41 +0000 (+0200) Subject: Continued and discontinued: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=84b81e29fe243cb5e0310bcc954baeba5ccecf5c;p=pizzaservice-ejb.git Continued and discontinued: - jshop-ejb and jshop-receipt-ejb had persistence unit files which would make it impossible to have two shops at the same system. Well, mostly not what you want because you want performance, but who knows? Signed-off-by: Roland Häder --- diff --git a/lib/gnu-jpdf/gnujpdf-1.7.0.jar b/lib/gnu-jpdf/gnujpdf-1.7.0.jar new file mode 100644 index 0000000..8b325ea Binary files /dev/null and b/lib/gnu-jpdf/gnujpdf-1.7.0.jar differ diff --git a/lib/jproduct-core.jar b/lib/jproduct-core.jar new file mode 100644 index 0000000..af98d89 Binary files /dev/null and b/lib/jproduct-core.jar differ diff --git a/lib/jshop-receipt-lib.jar b/lib/jshop-receipt-lib.jar new file mode 100644 index 0000000..eb2f505 Binary files /dev/null and b/lib/jshop-receipt-lib.jar differ diff --git a/lib/nblibraries.properties b/lib/nblibraries.properties index 1aac91b..3eaecf1 100644 --- a/lib/nblibraries.properties +++ b/lib/nblibraries.properties @@ -13,3 +13,8 @@ libs.eclipselinkmodelgen.classpath=\ ${base}/eclipselinkmodelgen/org.eclipse.persistence.jpa.modelgen_2.5.2.v20140319-9ad6abd.jar libs.eclipselinkmodelgen.displayName=EclipseLink-ModelGen (JPA 2.1) libs.eclipselinkmodelgen.prop-maven-dependencies=org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor:2.5.2:jar +libs.GNU_JPDF_1.7.0.classpath=\ + ${base}/gnu-jpdf/gnujpdf-1.7.0.jar +libs.GNU_JPDF_1.7.0.displayName=GNU JPDF 1.7.0 +libs.GNU_JPDF_1.7.0.javadoc=\ + http://www.aip.de/~granzer/javadoc/jpdf/ diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml index 4c1f755..2a4528f 100644 --- a/nbproject/build-impl.xml +++ b/nbproject/build-impl.xml @@ -858,9 +858,12 @@ exists or setup the property manually. For example like this: + + + @@ -881,15 +884,18 @@ exists or setup the property manually. For example like this: + + + - + @@ -904,13 +910,16 @@ exists or setup the property manually. For example like this: - - - - - - - + + + + + + + + + + @@ -928,9 +937,12 @@ exists or setup the property manually. For example like this: + + + diff --git a/nbproject/project.properties b/nbproject/project.properties index 9cdbf0b..5f9b6b8 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -33,8 +33,10 @@ file.reference.jcustomer-lib.jar=lib/jcustomer-lib.jar file.reference.jmailer-ee.jar=lib/jmailer-ee.jar file.reference.jphone-core.jar=lib/jphone-core.jar file.reference.jphone-lib.jar=lib/jphone-lib.jar +file.reference.jproduct-core.jar=lib/jproduct-core.jar file.reference.jshop-core.jar=lib/jshop-core.jar file.reference.jshop-ee-lib.jar=lib/jshop-ee-lib.jar +file.reference.jshop-receipt-lib.jar=lib/jshop-receipt-lib.jar file.reference.juser-core.jar=lib/juser-core.jar file.reference.juser-lib.jar=lib/juser-lib.jar file.reference.juser-activity-core.jar=lib/juser-activity-core.jar @@ -69,9 +71,12 @@ javac.classpath=\ ${file.reference.jcustomer-lib.jar}:\ ${file.reference.jphone-core.jar}:\ ${file.reference.jphone-lib.jar}:\ + ${file.reference.jproduct-core.jar}:\ ${file.reference.jshop-core.jar}:\ ${file.reference.jshop-ee-lib.jar}:\ + ${file.reference.jshop-receipt-lib.jar}:\ ${file.reference.jmailer-ee.jar}:\ + ${libs.GNU_JPDF_1.7.0.classpath}:\ ${reference.pizzaservice-core.jar}:\ ${reference.pizzaservice-lib.jar}:\ ${reference.pizzaservice-mailer.jar}:\ @@ -131,8 +136,10 @@ source.reference.jcustomer-lib.jar=../jcustomer-lib/src/ source.reference.jmailer-ee.jar=../jmailer-ee/src/ source.reference.jphone-core.jar=../jphone-core/src/ source.reference.jphone-lib.jar=../jphone-lib/src/ +source.reference.jproduct-core.jar=../jproduct-core/src/ source.reference.jshop-core.jar=../../jshop-core/src/ source.reference.jshop-ee-lib.jar=../../jshop-ee-lib/src/ +source.reference.jshop-receipt-lib.jar=../jshop-receipt-lib/src/ source.reference.juser-core.jar=../juser-core/src/ source.reference.juser-lib.jar=../juser-lib/src/ source.reference.juser-activity-core.jar=../juser-activity-core/src/ diff --git a/nbproject/project.xml b/nbproject/project.xml index 3282b42..06b9cc4 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -19,9 +19,12 @@ file.reference.jcustomer-lib.jar file.reference.jphone-core.jar file.reference.jphone-lib.jar + file.reference.jproduct-core.jar file.reference.jshop-core.jar file.reference.jshop-ee-lib.jar + file.reference.jshop-receipt-lib.jar file.reference.jmailer-ee.jar + libs.GNU_JPDF_1.7.0.classpath reference.pizzaservice-core.jar reference.pizzaservice-lib.jar reference.pizzaservice-mailer.jar diff --git a/src/java/org/mxchange/pizzaservice/beans/checkout/CheckoutMessageBean.java b/src/java/org/mxchange/pizzaservice/beans/checkout/CheckoutMessageBean.java new file mode 100644 index 0000000..7d2b021 --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/beans/checkout/CheckoutMessageBean.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.beans.checkout; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.List; +import javax.ejb.ActivationConfigProperty; +import javax.ejb.EJB; +import javax.ejb.MessageDriven; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.ObjectMessage; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import org.mxchange.jcoreeelogger.beans.local.logger.Log; +import org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal; +import org.mxchange.jcustomercore.exceptions.CustomerAlreadyRegisteredException; +import org.mxchange.jcustomercore.model.customer.Customer; +import org.mxchange.jcustomercore.model.customer.CustomerSessionBeanRemote; +import org.mxchange.jshopcore.model.basket.AddableBasketItem; +import org.mxchange.jshopcore.model.basket.BasketSessionBeanRemote; +import org.mxchange.jshopcore.model.receipt.ReceiptBeanRemote; +import org.mxchange.jshopcore.wrapper.WrapableCheckout; + +/** + * A message-driven bean for checkouts + *

+ * @author Roland Häder + */ +@MessageDriven ( + name = "checkout", + description = "A message bean for shop checkouts", + activationConfig = { + @ActivationConfigProperty (propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty (propertyName = "destinationLookup", propertyValue = "jms/shopCheckoutQueue") + } +) +public class CheckoutMessageBean implements MessageListener { + + /** + * Basket bean + */ + @EJB + private BasketSessionBeanRemote basketBean; + + /** + * Customer instance + */ + @EJB + private CustomerSessionBeanRemote customerBean; + + /** + * Logger bean + */ + @Log + private LoggerBeanLocal loggerBeanLocal; + + /** + * Receipt bean + */ + @EJB + private ReceiptBeanRemote receiptBean; + + /** + * Default constructor + */ + public CheckoutMessageBean () { + try { + // Get initial context + Context context = new InitialContext(); + + // Lookup logger + this.loggerBeanLocal = (LoggerBeanLocal) context.lookup("java:global/jcore-logger-ejb/logger!org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal"); //NOI18N + } catch (final NamingException ex) { + // Continue to throw + throw new RuntimeException(MessageFormat.format("context.lookup() failed: {0}", ex.getMessage()), ex); //NOI18N + } + } + + @Override + public void onMessage (final Message message) { + // Trace message + this.loggerBeanLocal.logTrace(MessageFormat.format("onMessage: message={0} - CALLED!", message)); //NOI18N + + // Is the message castable to ObjectMessage? + if (null == message) { + // message is null + throw new NullPointerException("message is null"); //NOI18N + } else if (!(message instanceof ObjectMessage)) { + // Not castable + throw new ClassCastException(MessageFormat.format("message cannot be casted to ObjectMessage: {0}", message)); //NOI18N + } + + // Securely cast it + ObjectMessage objectMessage = (ObjectMessage) message; + + // Init instance + Serializable object; + + try { + // Get object from it + object = objectMessage.getObject(); + } catch (final JMSException ex) { + // Log exception ... + this.loggerBeanLocal.logException(ex); + + // ... and don't continue + return; + } + + // Debug message + this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: object={0}", object)); //NOI18N + + // Does this object implement WrapableCheckout ? + if (null == object) { + // object cannot be null + throw new NullPointerException("object is null"); //NOI18N + } else if (!(object instanceof WrapableCheckout)) { + // Not proper interface used + throw new ClassCastException(MessageFormat.format("object does not implement WrapableCheckout: {0}", object)); //NOI18N + } + + // Securely cast it + WrapableCheckout checkout = (WrapableCheckout) object; + + // Get customer and list from it + Customer customer = checkout.getCustomer(); + List orderedItems = checkout.getList(); + + // Debug message + this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: customerInstance={0},itemList={1}", customer, orderedItems)); //NOI18N + + // Check both on null + if (null == customer) { + // customer is null + throw new NullPointerException("customer is null"); //NOI18N + } else if (null == orderedItems) { + // list is null + throw new NullPointerException("list is null"); //NOI18N + } + + try { + // Is the customer already registered? + if (this.customerBean.isRegistered(customer)) { + // Already registered, so get all data + customer = this.customerBean.fillCustomerData(customer); + } else { + // Register customer first, this generates a customer number + customer = this.customerBean.registerCustomer(customer); + } + } catch (final CustomerAlreadyRegisteredException ex) { + // Log exception and abort + this.loggerBeanLocal.logException(ex); + return; + } + + // Is the instance set? + if (null == customer) { + // Customer is null + throw new NullPointerException("customer is null"); //NOI18N + } + + // Make sure the number has been regenerated + if (customer.getCustomerNumber() == null) { + // Not assigned + throw new NullPointerException(MessageFormat.format("registerCustomer() did not create a custome number: customerInstance={0}", customer)); //NOI18N + } + + // Now add the ordered item list + String accessKey = this.basketBean.registerItems(customer, orderedItems); + + // Debug message + this.loggerBeanLocal.logDebug(MessageFormat.format("onMessage: accessKey={0}", accessKey)); //NOI18N + + // Should not be null + if (null == accessKey) { + // Abort here + throw new NullPointerException("accessKey is null"); //NOI18N + } + + // Set access key and customer + this.receiptBean.setAccessKey(accessKey); + this.receiptBean.setCustomer(customer); + + // Trace message + this.loggerBeanLocal.logTrace("onMessage: EXIT!"); //NOI18N + } + +} diff --git a/src/java/org/mxchange/pizzaservice/model/basket/BasketSessionBean.java b/src/java/org/mxchange/pizzaservice/model/basket/BasketSessionBean.java new file mode 100644 index 0000000..07f7148 --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/model/basket/BasketSessionBean.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.model.basket; + +import java.text.MessageFormat; +import java.util.GregorianCalendar; +import java.util.List; +import javax.ejb.Stateless; +import javax.persistence.EntityExistsException; +import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jcustomercore.model.customer.Customer; +import org.mxchange.jshopcore.model.basket.AddableBasketItem; +import org.mxchange.jshopcore.model.basket.BasketSessionBeanRemote; +import org.mxchange.jshopcore.model.customer.CustomerUtils; +import org.mxchange.jshopcore.model.order.Orderable; +import org.mxchange.jshopcore.model.order.ShopOrder; + +/** + * A basket for orderable items + *

+ * @author Roland Häder + */ +@Stateless (name = "basket", description = "A bean handling persisting baskets of logged-in customers") +public class BasketSessionBean extends BaseDatabaseBean implements BasketSessionBeanRemote { + + /** + * Serial number + */ + private static final long serialVersionUID = 4_384_123_923_163_957L; + + /** + * Default constructor + */ + public BasketSessionBean () { + } + + @Override + public void clear () { + // @TODO Nothing done so far + } + + @Override + public String registerItems (final Customer customer, final List orderedItems) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("registerItems: customer={0},itemList={1} - CALLED!", customer, orderedItems)); //NOI18N + + // Init variable for access key + String accessKey; + + // customer/itemList should not be null + if (null == customer) { + // Abort here + throw new NullPointerException("customer is null"); //NOI18N + } else if (null == orderedItems) { + // Abort here + throw new NullPointerException("itemList is null"); //NOI18N + } else if (customer.getCustomerId() == null) { + // null pointer found + throw new NullPointerException(MessageFormat.format("customer {0} id is null", customer)); //NOI18N + } else if (customer.getCustomerId() == 0) { + // id not set + throw new IllegalArgumentException(MessageFormat.format("customer {0} has no id set", customer)); //NOI18N + } else if (orderedItems.isEmpty()) { + // Empty list + throw new IllegalArgumentException("item list is empty"); //NOI18N + } + + // First try to register the order (to get an id number from it) + try { + // Generate access key + accessKey = CustomerUtils.generateAccessKey(this.getEntityManager(), customer); + + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("registerItems: accessKey={0}", accessKey)); //NOI18N + + // Create order object + Orderable order = new ShopOrder(); + order.setCustomer(customer); + order.setAccessKey(accessKey); + order.setOrderedItems(orderedItems); + order.setOrderCreated(new GregorianCalendar()); + + // Persist it + this.getEntityManager().persist(order); + } catch (final EntityExistsException ex) { + // Log exception + this.getLoggerBeanLocal().logException(ex); + + /* + * Don't return an access key as the exception should never be + * thrown. + */ + accessKey = null; + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("registerItems: accessKey={0} - EXIT!", accessKey)); //NOI18N + + // Return it + return accessKey; + } + +} diff --git a/src/java/org/mxchange/pizzaservice/model/category/AdminCategorySessionBean.java b/src/java/org/mxchange/pizzaservice/model/category/AdminCategorySessionBean.java new file mode 100644 index 0000000..afce2c3 --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/model/category/AdminCategorySessionBean.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.model.category; + +import java.text.MessageFormat; +import javax.ejb.Stateless; +import javax.persistence.EntityNotFoundException; +import javax.persistence.NoResultException; +import javax.persistence.Query; +import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jproduct.exceptions.CannotAddCategoryException; +import org.mxchange.jproduct.exceptions.CategoryTitleAlreadyUsedException; +import org.mxchange.jproduct.model.category.Category; +import org.mxchange.jproduct.model.category.ProductCategory; +import org.mxchange.jshopcore.model.category.AdminCategorySessionBeanRemote; + +/** + * An EJB for administrative access on categories + *

+ * @author Roland Häder + */ +@Stateless (name = "admin_category", description = "An administrative bean handling product categories") +public class AdminCategorySessionBean extends BaseDatabaseBean implements AdminCategorySessionBeanRemote { + + /** + * Serial number + */ + private static final long serialVersionUID = 26_143_895_789_581L; + + @Override + public Category doAdminAddCategory (final Category category) throws CategoryTitleAlreadyUsedException, CannotAddCategoryException { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddCategory: category={0} - CALLED!", category)); //NOI18N + + if (null == category) { + // category is null + throw new NullPointerException("category is null"); //NOI18N + } else if (this.getEntityManager() == null) { + // Connection is not there + throw new NullPointerException("connection is null"); //NOI18N + } + + // The connection must be there + if (this.isCategoryTitleUsed(category)) { + // Then abort here + throw new CategoryTitleAlreadyUsedException(category); + } + + // Perist the category + this.getEntityManager().persist(category); + + // Flush it + this.getEntityManager().flush(); + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddCategory: category={0} - EXIT!", category)); //NOI18N + + // Return it + return category; + } + + /** + * Checks if the category's title has already been used as they need to be + * unique. This method works case-insensitive. Any spaces, new-line, + * carriage-return or tabulator characters are trimmed away. If the title + * has been used already, for performance reasons, the id and parent id are + * set in the category object. + *

+ * @param category Category instance + *

+ * @return Whether the category's title has been used + */ + private boolean isCategoryTitleUsed (final Category category) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("isCategoryTitleUsed: category={0} - CALLED!", category)); //NOI18N + + // The connection must be there + if (null == category) { + // category is null + throw new NullPointerException("category is null"); //NOI18N + } else if (this.getEntityManager() == null) { + // Connection is not there + throw new NullPointerException("connection is null"); //NOI18N + } + + // Default is not found + boolean isUsed = false; + + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("isCategoryTitleUsed: category.id={0},category.title={1},category.parentId={2}", category.getCategoryId(), category.getCategoryTitle(), category.getParentCategory())); //NOI18N + + // Try to locate it + try { + // Get query instance + Query query = this.getEntityManager().createQuery("SELECT c FROM category AS c WHERE LOWER(c.categoryTitle) = LOWER(:param)", ProductCategory.class); //NOI18N + query.setParameter("param", category.getCategoryTitle()); //NOI18N + Category cat = (Category) query.getSingleResult(); + + // Is found, so copy the object + category.copyAll(cat); + + // Mark as found + isUsed = true; + } catch (final EntityNotFoundException | NoResultException e) { + // Not found + this.getLoggerBeanLocal().logWarning(e.getMessage()); + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("isCategoryTitleUsed: isUsed={0} - EXIT!", isUsed)); //NOI18N + + // Return it + return isUsed; + } + +} diff --git a/src/java/org/mxchange/pizzaservice/model/category/CategorySessionBean.java b/src/java/org/mxchange/pizzaservice/model/category/CategorySessionBean.java new file mode 100644 index 0000000..9f95f44 --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/model/category/CategorySessionBean.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.model.category; + +import java.text.MessageFormat; +import java.util.List; +import javax.ejb.Stateless; +import javax.persistence.Query; +import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jproduct.model.category.Category; +import org.mxchange.jproduct.model.category.ProductCategory; +import org.mxchange.jshopcore.model.category.CategorySessionBeanRemote; + +/** + * Main shop class + *

+ * @author Roland Häder + */ +@Stateless (name = "category", description = "A bean handling categories for all others (non-admin)") +public class CategorySessionBean extends BaseDatabaseBean implements CategorySessionBeanRemote { + + /** + * Serial number + */ + private static final long serialVersionUID = 58_137_539_530_279L; + + /** + * Default constructor + */ + public CategorySessionBean () { + } + + @Override + @SuppressWarnings ("unchecked") + public List getAllCategories () { + // Trace message + this.getLoggerBeanLocal().logTrace("getAllCategories: CALLED!"); //NOI18N + + // The connection must be there + if (this.getEntityManager() == null) { + // Connection is not there + throw new NullPointerException("connection is null"); //NOI18N + } + + // Create statement + Query query = this.getEntityManager().createQuery("SELECT c FROM category AS c ORDER BY c.categoryId ASC", ProductCategory.class); + + // Get result + List list = query.getResultList(); + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAllCategories: list({0})={1} - EXIT!", list.size(), list)); //NOI18N + + // Return it + return list; + } + +} diff --git a/src/java/org/mxchange/pizzaservice/model/customer/ShopCustomerSessionBean.java b/src/java/org/mxchange/pizzaservice/model/customer/ShopCustomerSessionBean.java new file mode 100644 index 0000000..d0274fd --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/model/customer/ShopCustomerSessionBean.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.model.customer; + +import java.text.MessageFormat; +import java.util.GregorianCalendar; +import javax.ejb.Stateless; +import javax.persistence.EntityNotFoundException; +import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jcustomercore.exceptions.CustomerAlreadyRegisteredException; +import org.mxchange.jcustomercore.exceptions.CustomerNotFoundException; +import org.mxchange.jcustomercore.model.customer.Customer; +import org.mxchange.jcustomercore.model.customer.CustomerSessionBeanRemote; + +/** + * A customer bean which hides the customer instance + *

+ * @author Roland Häder + */ +@Stateless (name = "shop_customer", description = "A bean handling the customer data") +public class ShopCustomerSessionBean extends BaseDatabaseBean implements CustomerSessionBeanRemote { + + /** + * Serial number + */ + private static final long serialVersionUID = 542_145_347_916L; + + /** + * Default constructor + */ + public ShopCustomerSessionBean () { + } + + @Override + public Customer fillCustomerData (final Customer customer) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("fillCustomerData: customer={0} - CALLED!", customer)); //NOI18N + + // customer should not be null + if (null == customer) { + // Abort here + throw new NullPointerException("customer is null"); //NOI18N + } + + // Try it + try { + // Try to locate it + Customer cat = this.getEntityManager().getReference(Customer.class, customer); + + // Copy all data + customer.copyAll(cat); + } catch (final EntityNotFoundException ex) { + // Log it + this.getLoggerBeanLocal().logException(ex); + + // Return null + return null; + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("fillCustomerData: customer={0} - EXIT!", customer)); //NOI18N + + // Return prepared instance + return customer; + } + + @Override + public Customer findCustomerById (final Long customerId) throws CustomerNotFoundException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public boolean isRegistered (final Customer customer) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("isRegistered: customer={0} - CALLED!", customer)); //NOI18N + + // customer should not be null + if (null == customer) { + // Abort here + throw new NullPointerException("customer is null"); //NOI18N + } + + // Try this + try { + Customer c = this.getEntityManager().getReference(Customer.class, customer); + } catch (final EntityNotFoundException ex) { + // Log it + this.getLoggerBeanLocal().logException(ex); + + // Did not finish + return false; + } + + // Found it + return true; + } + + @Override + public Customer registerCustomer (final Customer customer) throws CustomerAlreadyRegisteredException { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("registerCustomer: customer={0} - CALLED!", customer)); //NOI18N + + // customer should not be null + if (null == customer) { + // Abort here + throw new NullPointerException("customer is null"); //NOI18N + } + + // Is the customer registered? + if (this.isRegistered(customer)) { + // Already registered + throw new CustomerAlreadyRegisteredException(customer); + } + + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("registerCustomer: Preparing statement for customer={0}", customer)); //NOI18N + + // Set creation timestamp + customer.setCustomerCreated(new GregorianCalendar()); + + // Try to persist it + this.getEntityManager().persist(customer); + + // Flush it as the id might be needed + this.getEntityManager().flush(); + + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("registerCustomer: customer.id={0}", customer.getCustomerId())); //NOI18N + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("registerCustomer: customer={0} - CALLED!", customer)); //NOI18N + + // Return prepared instance + return customer; + } + +} diff --git a/src/java/org/mxchange/pizzaservice/model/product/AdminProductSessionBean.java b/src/java/org/mxchange/pizzaservice/model/product/AdminProductSessionBean.java new file mode 100644 index 0000000..ae0f909 --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/model/product/AdminProductSessionBean.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.model.product; + +import java.text.MessageFormat; +import java.util.List; +import javax.ejb.Stateless; +import javax.persistence.EntityExistsException; +import javax.persistence.EntityNotFoundException; +import javax.persistence.NoResultException; +import javax.persistence.Query; +import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jproduct.exceptions.CannotAddProductException; +import org.mxchange.jproduct.exceptions.ProductTitleAlreadyUsedException; +import org.mxchange.jproduct.model.product.GenericProduct; +import org.mxchange.jproduct.model.product.Product; +import org.mxchange.jshopcore.model.product.AdminProductSessionBeanRemote; + +/** + * A session bean for non-administrative roles for products + *

+ * @author Roland Häder + */ +@Stateless (name = "admin_product", description = "An administrative bean handling products") +public class AdminProductSessionBean extends BaseDatabaseBean implements AdminProductSessionBeanRemote { + + /** + * Serial number + */ + private static final long serialVersionUID = 65_173_487_394_812L; + + /** + * Default constructor + */ + public AdminProductSessionBean () { + } + + @Override + public Product doAdminAddProduct (final Product product) throws ProductTitleAlreadyUsedException, CannotAddProductException { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddProduct: product={0} - CALLED!", product)); //NOI18N + + // Check if product's title is used + if (null == product) { + // product is null + throw new NullPointerException("product is null"); //NOI18N + } else if (this.getEntityManager() == null) { + // Connection is not there + throw new NullPointerException("connection is null"); //NOI18N + } else if (this.isProductTitleUsed(product)) { + // Throw exception + throw new ProductTitleAlreadyUsedException(product); + } + + try { + // Persist it + this.getEntityManager().persist(product); + + // Flush it as the id might be needed immediately + this.getEntityManager().flush(); + } catch (final EntityExistsException ex) { + // Continue to throw + throw new CannotAddProductException(ex); + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("doAdminAddProduct: product={0} - EXIT!", product)); //NOI18N + + // Return it + return product; + } + + @Override + @SuppressWarnings ("unchecked") + public List getAllProducts () { + // Trace message + this.getLoggerBeanLocal().logTrace("getAllProducts: CALLED!"); //NOI18N + + // The connection must be there + if (this.getEntityManager() == null) { + // Connection is not there + throw new NullPointerException("connection is null"); //NOI18N + } + + // Create statement + Query query = this.getEntityManager().createQuery("SELECT p FROM products AS p ORDER BY p.productId ASC", GenericProduct.class); //NOI18N + + // Get list + List list = query.getResultList(); + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAllProducts: list({0})={1} - EXIT!", list.size(), list)); //NOI18N + + // Return it + return list; + } + + /** + * Checks if the product's title has already been used as they need to be + * unique. This method works case-insensitive. Any spaces, new-line, + * carriage-return or tabulator characters are trimmed away. If the title + * has been used already, for performance reasons, the whole data is set in + * the product object. + *

+ * @param product Product instance + *

+ * @return Whether the product's title has been used + */ + private boolean isProductTitleUsed (final Product product) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("isProductTitleUsed: Product={0} - CALLED!", product)); //NOI18N + + // The connection must be there + if (null == product) { + // product is null + throw new NullPointerException("product is null"); //NOI18N + } else if (this.getEntityManager() == null) { + // Connection is not there + throw new NullPointerException("connection is null"); //NOI18N + } + + // Default is not found + boolean isUsed = false; + + // Try to locate it + try { + // Get query instance + Query query = this.getEntityManager().createQuery("SELECT p FROM products AS p WHERE LOWER(p.productTitle) = LOWER(:param)", GenericProduct.class); //NOI18N + query.setParameter("param", product.getProductTitle()); //NOI18N + Product pro = (Product) query.getSingleResult(); + + // Is found, so copy the object + product.copyAll(pro); + + // Mark as found + isUsed = true; + } catch (final EntityNotFoundException | NoResultException e) { + // Not found + this.getLoggerBeanLocal().logWarning(e.getMessage()); + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("isProductTitleUsed: isUsed={0} - EXIT!", isUsed)); //NOI18N + + // Return it + return isUsed; + } + +} diff --git a/src/java/org/mxchange/pizzaservice/model/product/ProductSessionBean.java b/src/java/org/mxchange/pizzaservice/model/product/ProductSessionBean.java new file mode 100644 index 0000000..d7d0eef --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/model/product/ProductSessionBean.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.model.product; + +import java.text.MessageFormat; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import javax.ejb.EJB; +import javax.ejb.Stateless; +import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jproduct.model.product.Product; +import org.mxchange.jshopcore.model.product.AdminProductSessionBeanRemote; +import org.mxchange.jshopcore.model.product.ProductSessionBeanRemote; + +/** + * A session bean for non-administrative roles for products + *

+ * @author Roland Häder + */ +@Stateless (name = "product", description = "A bean handling products for all others (non-admin)") +public class ProductSessionBean extends BaseDatabaseBean implements ProductSessionBeanRemote { + + /** + * Serial number + */ + private static final long serialVersionUID = 65_173_487_394_812L; + + /** + * Administrative bean + */ + @EJB + private AdminProductSessionBeanRemote productBean; + + /** + * Default constructor + */ + public ProductSessionBean () { + } + + @Override + public List getAvailableProducts () { + // Trace message + this.getLoggerBeanLocal().logTrace("getAvailableProducts: CALLED!"); //NOI18N + + // The connection must be there + if (this.getEntityManager() == null) { + // Connection is not there + throw new NullPointerException("connection is null"); //NOI18N + } + + // Get all products + List allProducts = this.productBean.getAllProducts(); + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAvailableProducts: allProducts({0})={1}", allProducts.size(), allProducts)); //NOI18N + + // Init deque + List deque = new LinkedList<>(); + + // Get iterator + Iterator iterator = allProducts.iterator(); + + // Walk through all and add only available + while (iterator.hasNext()) { + // Get element + Product localProduct = iterator.next(); + + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("getAvailableProducts: localProduct={0}", localProduct)); //NOI18N + + // Is this available? + if (localProduct.getProductAvailability()) { + // Debug message + this.getLoggerBeanLocal().logDebug(MessageFormat.format("getAvailableProducts: localProduct={0} - ADDED!", localProduct)); //NOI18N + + // Add it + deque.add(localProduct); + } + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("getAvailableProducts: deque({0})={1} - EXIT!", deque.size(), deque)); //NOI18N + + // Return it + return deque; + } + +} diff --git a/src/java/org/mxchange/pizzaservice/model/receipt/PdfReceiptSessionBean.java b/src/java/org/mxchange/pizzaservice/model/receipt/PdfReceiptSessionBean.java new file mode 100644 index 0000000..34267c4 --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/model/receipt/PdfReceiptSessionBean.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.model.receipt; + +import java.text.MessageFormat; +import javax.ejb.Stateless; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jcustomercore.model.customer.Customer; +import org.mxchange.jshopcore.model.receipt.ReceiptBeanRemote; +import org.mxchange.jshopcore.model.receipt.WrapableReceipt; +import org.mxchange.jshopreceipt.receipt.PdfReceiptBeanLocal; +import org.mxchange.jshopreceipt.receipt.Receipt; + +/** + * A stateless session bean for producing official receipts in Abobe's whacky + * binary format. This class uses GNUjpdf which allows using ordinary graphic + * libraries. + *

+ * @author Roland Häder + */ +@Stateless (name = "pdf", description = "A bean creating PDF receipts") +public class PdfReceiptSessionBean extends BaseDatabaseBean implements ReceiptBeanRemote { + + /** + * Serial number + */ + private static final long serialVersionUID = 384_578_171_659_628L; + + /** + * Access key + */ + private String accessKey; + + /** + * Customer instance + */ + private Customer customer; + + /** + * PDF receipt injection + */ + @Receipt + private PdfReceiptBeanLocal pdfReceiptBeanLocal; + + /** + * Default constructor + */ + public PdfReceiptSessionBean () { + try { + // Get initial context + Context context = new InitialContext(); + + // Lookup pdf receipt + this.pdfReceiptBeanLocal = (PdfReceiptBeanLocal) context.lookup("java:global/jshop-receipt-ejb/pdf-receipt!org.mxchange.jshopreceipt.receipt.PdfReceiptBeanLocal"); //NOI18N + } catch (final NamingException ex) { + // Continue to throw + throw new RuntimeException(MessageFormat.format("context.lookup() failed: {0}", ex.getMessage()), ex); //NOI18N + } + } + + @Override + public WrapableReceipt createReceiptFromAccessKey (final String accessKey) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("createReceiptFromAccessKey: accessKey={0} - CALLED!", accessKey)); //NOI18N + + return null; + } + + @Override + public String fetchAccessKey (final Customer customer) { + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("fetchAccessKey: customer={0} - EXIT!", customer)); //NOI18N + + // customer should not be null + if (null == customer) { + // Abort here + throw new NullPointerException("customer is null"); //NOI18N + } else if (this.getCustomer() == null) { + // Don't continue, too. + throw new NullPointerException("this.getCustomer() returns null"); //NOI18N + } + + // Default is null + String key = null; + + // Is customer the same? + if (customer.equals(this.getCustomer())) { + // Set access key + key = this.getAccessKey(); + } + + // Trace message + this.getLoggerBeanLocal().logTrace(MessageFormat.format("fetchAccessKey: key={0} - EXIT!", key)); //NOI18N + + // Return it + return key; + } + + @Override + public String getAccessKey () { + return this.accessKey; + } + + @Override + public void setAccessKey (final String accessKey) { + this.accessKey = accessKey; + } + + @Override + public Customer getCustomer () { + return this.customer; + } + + @Override + public void setCustomer (final Customer customer) { + this.customer = customer; + } + +} diff --git a/src/java/org/mxchange/pizzaservice/receipt/PdfReceiptBean.java b/src/java/org/mxchange/pizzaservice/receipt/PdfReceiptBean.java new file mode 100644 index 0000000..1650329 --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/receipt/PdfReceiptBean.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.receipt; + +import gnu.jpdf.PDFJob; +import javax.ejb.Singleton; +import javax.ejb.Startup; +import javax.inject.Inject; +import org.mxchange.jshopreceipt.receipt.PdfReceiptBeanLocal; +import org.mxchange.jshopreceipt.receipt.Receipt; + +/** + * A "centralized" logger bean + *

+ * @author Roland Häder + */ +@Startup +@Singleton (name = "pdf-receipt", description = "An EJB for producing PDF receipts") +public class PdfReceiptBean implements PdfReceiptBeanLocal { + + /** + * PDF job instance + */ + @Inject + @Receipt + private PDFJob job; + + /** + * Default constructor + */ + public PdfReceiptBean () { + } + + /** + * Getter for PDF job + *

+ * @return PDF job + */ + private PDFJob getJob () { + return this.job; + } +} diff --git a/src/java/org/mxchange/pizzaservice/receipt/ReceiptFactory.java b/src/java/org/mxchange/pizzaservice/receipt/ReceiptFactory.java new file mode 100644 index 0000000..120a61d --- /dev/null +++ b/src/java/org/mxchange/pizzaservice/receipt/ReceiptFactory.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Roland Häder + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.mxchange.pizzaservice.receipt; + +import gnu.jpdf.PDFJob; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; +import org.mxchange.jshopreceipt.receipt.Receipt; + +/** + * A logger factory + *

+ * @author Roland Häder + */ +public class ReceiptFactory { + + /** + * Own job + */ + private final PDFJob job; + + /** + * Factory method + */ + public ReceiptFactory () { + this.job = new PDFJob(); + } + + /** + * Produces a PDF job instance + *

+ * @param caller Injection point + *

+ * @return PDF job + */ + @Produces + @Receipt + public PDFJob getJob (final InjectionPoint caller) { + return this.job; + } +}