2 * Copyright (C) 2016 - 2018 Free Software Foundation
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.jproduct.model.product;
19 import java.math.BigDecimal;
20 import java.text.MessageFormat;
21 import java.util.Date;
22 import java.util.Objects;
23 import javax.persistence.Basic;
24 import javax.persistence.CascadeType;
25 import javax.persistence.Column;
26 import javax.persistence.Entity;
27 import javax.persistence.EnumType;
28 import javax.persistence.Enumerated;
29 import javax.persistence.GeneratedValue;
30 import javax.persistence.GenerationType;
31 import javax.persistence.Id;
32 import javax.persistence.Index;
33 import javax.persistence.JoinColumn;
34 import javax.persistence.NamedQueries;
35 import javax.persistence.NamedQuery;
36 import javax.persistence.OneToOne;
37 import javax.persistence.Table;
38 import javax.persistence.Temporal;
39 import javax.persistence.TemporalType;
40 import javax.persistence.Transient;
41 import org.apache.commons.lang3.StringUtils;
42 import org.mxchange.jcontactsbusiness.model.basicdata.BasicData;
43 import org.mxchange.jcontactsbusiness.model.basicdata.BasicDataUtils;
44 import org.mxchange.jcontactsbusiness.model.basicdata.BusinessBasicData;
45 import org.mxchange.jcoreutils.Comparables;
46 import org.mxchange.jcoreutils.SafeNumberUtils;
47 import org.mxchange.jproduct.model.category.Categories;
48 import org.mxchange.jproduct.model.category.Category;
49 import org.mxchange.jproduct.model.category.ProductCategory;
50 import org.mxchange.jproduct.model.product.agegroup.AgeGroup;
53 * Generic product class
55 * @author Roland Häder<roland@mxchange.org>
56 * TODO: Find a better name
58 @Entity (name = "generic_products")
60 name = "generic_products",
63 name = "idx_i18n_age_size",
64 columnList = "product_i18n_key,product_age_group,product_size",
71 @NamedQuery (name = "AllProducts", query = "SELECT p FROM generic_products AS p ORDER BY p.productId ASC"),
72 @NamedQuery (name = "AllAvailableProducts", query = "SELECT p FROM generic_products AS p WHERE p.productAvailability=TRUE ORDER BY p.productId ASC")
75 @SuppressWarnings ("PersistenceUnitPresent")
76 public class GenericProduct implements Product {
82 private static final long serialVersionUID = 54_578_571_769_283L;
85 * Product's age group (if any)
87 @Column (name = "product_age_group")
88 @Enumerated (EnumType.STRING)
89 private AgeGroup productAgeGroup;
92 * Availability of product
94 @Basic (optional = false)
95 @Column (name = "product_availability", nullable = false)
96 private Boolean productAvailability;
99 * Product productCategory
101 @JoinColumn (name = "product_category_id", referencedColumnName = "category_id", nullable = false, updatable = false)
102 @OneToOne (targetEntity = ProductCategory.class, cascade = CascadeType.REFRESH, optional = false)
103 private Category productCategory;
106 * When this product has been created
108 @Basic (optional = false)
109 @Column (name = "product_created", nullable = false, updatable = false)
110 @Temporal (TemporalType.TIMESTAMP)
111 private Date productCreated;
114 * Currency code for both prices, like EUR or USD
116 @Basic (optional = false)
117 @Column (name = "product_currency_code", nullable = false, length = 3)
118 private String productCurrencyCode;
121 * Gross price of product
123 @Basic (optional = false)
124 @Column (name = "product_gross_price", nullable = false, precision = 10, scale = 4)
125 private BigDecimal productGrossPrice;
128 * I18n key of product
130 @Basic (optional = false)
131 @Column (name = "product_i18n_key", length = 100, nullable = false)
132 private String productI18nKey;
135 * Id number of product
138 @GeneratedValue (strategy = GenerationType.IDENTITY)
139 @Column (name = "product_id", nullable = false, updatable = false)
140 private Long productId;
143 * The company that has manufactured/produced this product
145 @JoinColumn (name = "product_manufacturer_id", referencedColumnName = "company_data_id")
146 @OneToOne (targetEntity = BusinessBasicData.class, cascade = CascadeType.REFRESH)
147 private BasicData productManufacturer;
150 * Net price of product
152 @Column (name = "product_net_price", precision = 10, scale = 4)
153 private BigDecimal productNetPrice;
158 @Column (name = "product_number")
159 private Long productNumber;
162 * Product size (like for shoes, clothing)
164 @Column (name = "product_size", length = 10)
165 private String productSize;
168 * Tax rate (0-1, by 1=100%)
170 @Column (name = "product_tax_rate", precision = 3, scale = 1)
171 private BigDecimal productTaxRate;
174 * Amount of this product (for example 1 for 1 liter)
176 @Basic (optional = false)
177 @Column (name = "product_unit_amount", nullable = false, precision = 10, scale = 2)
178 private BigDecimal productUnitAmount;
181 * Unit type (for example liter)
183 @Basic (optional = false)
184 @Column (name = "product_unit_i18n_key", nullable = false)
185 private String productUnitI18nKey;
188 * Default constructor
190 public GenericProduct () {
194 * Constructor will all required data
196 * @param productI18nKey I18n key of product
197 * @param productGrossPrice Product's gross price
198 * @param productCurrencyCode Currency code for both prices
199 * @param productCategory Category instance
200 * @param productAvailability Availability (selectable by customer)
201 * @param productUnitAmount Unit amount
202 * @param productUnitI18nKey Unit's i18n key
204 * @throws NullPointerException If a parameter is null
205 * @throws IllegalArgumentException If a parameter is empty (string) or out
208 public GenericProduct (final String productI18nKey, final BigDecimal productGrossPrice, final String productCurrencyCode, final Category productCategory, final Boolean productAvailability, final BigDecimal productUnitAmount, final String productUnitI18nKey) {
209 // Call other constructor first
212 // Validate all parameters
213 if (null == productAvailability) {
215 throw new NullPointerException("productAvailability is null"); //NOI18N
216 } else if (null == productCategory) {
218 throw new NullPointerException("productCategory is null"); //NOI18N
219 } else if (productCategory.getCategoryId() == null) {
221 throw new NullPointerException("productCategory.categoryId is null"); //NOI18N
222 } else if (productCategory.getCategoryId() < 1) {
224 throw new IllegalArgumentException(MessageFormat.format("productCategory.categoryId={0} is invalid", productCategory.getCategoryId())); //NOI18N
225 } else if (null == productCurrencyCode) {
227 throw new NullPointerException("productCurrencyCode is null"); //NOI18N
228 } else if (productCurrencyCode.isEmpty()) {
230 throw new IllegalArgumentException("productCurrencyCode is empty"); //NOI18N
231 } else if (null == productGrossPrice) {
233 throw new NullPointerException("productGrossPrice is null"); //NOI18N
234 } else if (productGrossPrice.longValue() < 0) {
236 throw new IllegalArgumentException(MessageFormat.format("productGrossPrice={0} is invalid. Do not enter discounts as products.", productGrossPrice)); //NOI18N
237 } else if (null == productI18nKey) {
239 throw new NullPointerException("productI18nKey is null"); //NOI18N
240 } else if (productI18nKey.isEmpty()) {
242 throw new IllegalArgumentException("productI18nKey is empty"); //NOI18N
243 } else if (null == productUnitAmount) {
245 throw new NullPointerException("productUnitAmount is null"); //NOI18N
246 } else if (productUnitAmount.longValue() < 0) {
248 throw new IllegalArgumentException(MessageFormat.format("productUnitAmount={0} is invalid. Do not enter discounts as products.", productUnitAmount)); //NOI18N
249 } else if (null == productUnitI18nKey) {
251 throw new NullPointerException("productUnitI18nKey is null"); //NOI18N
252 } else if (productUnitI18nKey.isEmpty()) {
254 throw new IllegalArgumentException("productUnitI18nKey is empty"); //NOI18N
258 this.productI18nKey = productI18nKey;
259 this.productGrossPrice = productGrossPrice;
260 this.productCurrencyCode = productCurrencyCode.toUpperCase();
261 this.productCategory = productCategory;
262 this.productAvailability = productAvailability;
263 this.productUnitAmount = productUnitAmount;
264 this.productUnitI18nKey = productUnitI18nKey;
268 public int compareTo (final Product product) {
269 // Check parameter on null-reference and equality to this
270 if (null == product) {
272 throw new NullPointerException("product is null"); //NOI18N
273 } else if (product.equals(this)) {
279 final int comparators[] = {
280 // First check product number
281 SafeNumberUtils.compare(this.getProductNumber(), product.getProductNumber()),
283 StringUtils.compare(this.getProductSize(), product.getProductSize()),
285 this.getProductI18nKey().compareTo(product.getProductI18nKey()),
287 this.getProductGrossPrice().compareTo(product.getProductGrossPrice()),
289 SafeNumberUtils.compare(this.getProductNetPrice(), product.getProductNetPrice()),
291 SafeNumberUtils.compare(this.getProductTaxRate(), product.getProductTaxRate()),
293 this.getProductUnitAmount().compareTo(product.getProductUnitAmount()),
295 this.getProductCurrencyCode().compareTo(product.getProductCurrencyCode()),
297 BasicDataUtils.compare(this.getProductManufacturer(), product.getProductManufacturer()),
299 Categories.compare(this.getProductCategory(), product.getProductCategory())
303 final int comparison = Comparables.checkAll(comparators);
310 public boolean equals (final Object object) {
311 if (this == object) {
313 } else if (null == object) {
315 } else if (this.getClass() != object.getClass()) {
319 final Product product = (Product) object;
321 if (!Objects.equals(this.getProductGrossPrice(), product.getProductGrossPrice())) {
323 } else if (!Objects.equals(this.getProductId(), product.getProductId())) {
325 } else if (!Objects.equals(this.getProductI18nKey(), product.getProductI18nKey())) {
327 } else if (!Objects.equals(this.getProductAgeGroup(), product.getProductAgeGroup())) {
329 } else if (!Objects.equals(this.getProductSize(), product.getProductSize())) {
337 public AgeGroup getProductAgeGroup () {
338 return this.productAgeGroup;
342 public void setProductAgeGroup (final AgeGroup productAgeGroup) {
343 this.productAgeGroup = productAgeGroup;
347 public Boolean getProductAvailability () {
348 return this.productAvailability;
352 public void setProductAvailability (final Boolean productAvailability) {
353 this.productAvailability = productAvailability;
357 public Category getProductCategory () {
358 return this.productCategory;
362 public void setProductCategory (final Category productCategory) {
363 this.productCategory = productCategory;
367 @SuppressWarnings ("ReturnOfDateField")
368 public Date getProductCreated () {
369 return this.productCreated;
373 @SuppressWarnings ("AssignmentToDateFieldFromParameter")
374 public void setProductCreated (final Date productCreated) {
375 this.productCreated = productCreated;
379 public String getProductCurrencyCode () {
380 return this.productCurrencyCode;
384 public void setProductCurrencyCode (final String productCurrencyCode) {
385 this.productCurrencyCode = productCurrencyCode;
389 public BigDecimal getProductGrossPrice () {
390 return this.productGrossPrice;
394 public void setProductGrossPrice (final BigDecimal productGrossPrice) {
395 this.productGrossPrice = productGrossPrice;
399 public String getProductI18nKey () {
400 return this.productI18nKey;
404 public void setProductI18nKey (final String productI18nKey) {
405 this.productI18nKey = productI18nKey;
409 public Long getProductId () {
410 return this.productId;
414 public void setProductId (final Long productId) {
415 this.productId = productId;
419 public BasicData getProductManufacturer () {
420 return this.productManufacturer;
424 public void setProductManufacturer (final BasicData productManufacturer) {
425 this.productManufacturer = productManufacturer;
429 public BigDecimal getProductNetPrice () {
430 return this.productNetPrice;
434 public void setProductNetPrice (final BigDecimal productNetPrice) {
435 this.productNetPrice = productNetPrice;
439 public Long getProductNumber () {
440 return this.productNumber;
444 public void setProductNumber (final Long productNumber) {
445 this.productNumber = productNumber;
449 public String getProductSize () {
450 return this.productSize;
454 public void setProductSize (final String productSize) {
455 this.productSize = productSize;
459 public BigDecimal getProductTaxRate () {
460 return this.productTaxRate;
464 public void setProductTaxRate (final BigDecimal productTaxRate) {
465 this.productTaxRate = productTaxRate;
469 public BigDecimal getProductUnitAmount () {
470 return this.productUnitAmount;
474 public void setProductUnitAmount (final BigDecimal productUnitAmount) {
475 this.productUnitAmount = productUnitAmount;
479 public String getProductUnitI18nKey () {
480 return this.productUnitI18nKey;
484 public void setProductUnitI18nKey (final String productUnitI18nKey) {
485 this.productUnitI18nKey = productUnitI18nKey;
489 public int hashCode () {
492 hash = 23 * hash + Objects.hashCode(this.getProductGrossPrice());
493 hash = 23 * hash + Objects.hashCode(this.getProductId());
494 hash = 23 * hash + Objects.hashCode(this.getProductI18nKey());
495 hash = 23 * hash + Objects.hashCode(this.getProductAgeGroup());
496 hash = 23 * hash + Objects.hashCode(this.getProductSize());