]> git.mxchange.org Git - jproduct-core.git/blob - src/org/mxchange/jproduct/model/product/GenericProduct.java
bc357b637d0f9caf0f17ff4bee82967c5f9fdb60
[jproduct-core.git] / src / org / mxchange / jproduct / model / product / GenericProduct.java
1 /*
2  * Copyright (C) 2016 - 2018 Free Software Foundation
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 package org.mxchange.jproduct.model.product;
18
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;
51
52 /**
53  * Generic product class
54  * <p>
55  * @author Roland Häder<roland@mxchange.org>
56  * TODO: Find a better name
57  */
58 @Entity (name = "generic_products")
59 @Table (
60                 name = "generic_products",
61                 indexes = {
62                         @Index (
63                                         name = "idx_i18n_age_size",
64                                         columnList = "product_i18n_key,product_age_group,product_size",
65                                         unique = true
66                         )
67                 }
68 )
69 @NamedQueries (
70                 {
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")
73                 }
74 )
75 @SuppressWarnings ("PersistenceUnitPresent")
76 public class GenericProduct implements Product {
77
78         /**
79          * Serial number
80          */
81         @Transient
82         private static final long serialVersionUID = 54_578_571_769_283L;
83
84         /**
85          * Product's age group (if any)
86          */
87         @Column (name = "product_age_group")
88         @Enumerated (EnumType.STRING)
89         private AgeGroup productAgeGroup;
90
91         /**
92          * Availability of product
93          */
94         @Basic (optional = false)
95         @Column (name = "product_availability", nullable = false)
96         private Boolean productAvailability;
97
98         /**
99          * Product productCategory
100          */
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;
104
105         /**
106          * When this product has been created
107          */
108         @Basic (optional = false)
109         @Column (name = "product_created", nullable = false, updatable = false)
110         @Temporal (TemporalType.TIMESTAMP)
111         private Date productCreated;
112
113         /**
114          * Currency code for both prices, like EUR or USD
115          */
116         @Basic (optional = false)
117         @Column (name = "product_currency_code", nullable = false, length = 3)
118         private String productCurrencyCode;
119
120         /**
121          * Gross price of product
122          */
123         @Basic (optional = false)
124         @Column (name = "product_gross_price", nullable = false, precision = 10, scale = 4)
125         private BigDecimal productGrossPrice;
126
127         /**
128          * I18n key of product
129          */
130         @Basic (optional = false)
131         @Column (name = "product_i18n_key", length = 100, nullable = false)
132         private String productI18nKey;
133
134         /**
135          * Id number of product
136          */
137         @Id
138         @GeneratedValue (strategy = GenerationType.IDENTITY)
139         @Column (name = "product_id", nullable = false, updatable = false)
140         private Long productId;
141
142         /**
143          * The company that has manufactured/produced this product
144          */
145         @JoinColumn (name = "product_manufacturer_id", referencedColumnName = "company_data_id")
146         @OneToOne (targetEntity = BusinessBasicData.class, cascade = CascadeType.REFRESH)
147         private BasicData productManufacturer;
148
149         /**
150          * Net price of product
151          */
152         @Column (name = "product_net_price", precision = 10, scale = 4)
153         private BigDecimal productNetPrice;
154
155         /**
156          * Number of product
157          */
158         @Column (name = "product_number")
159         private Long productNumber;
160
161         /**
162          * Product size (like for shoes, clothing)
163          */
164         @Column (name = "product_size", length = 10)
165         private String productSize;
166
167         /**
168          * Tax rate (0-1, by 1=100%)
169          */
170         @Column (name = "product_tax_rate", precision = 3, scale = 1)
171         private BigDecimal productTaxRate;
172
173         /**
174          * Amount of this product (for example 1 for 1 liter)
175          */
176         @Basic (optional = false)
177         @Column (name = "product_unit_amount", nullable = false, precision = 10, scale = 2)
178         private BigDecimal productUnitAmount;
179
180         /**
181          * Unit type (for example liter)
182          */
183         @Basic (optional = false)
184         @Column (name = "product_unit_i18n_key", nullable = false)
185         private String productUnitI18nKey;
186
187         /**
188          * Default constructor
189          */
190         public GenericProduct () {
191         }
192
193         /**
194          * Constructor will all required data
195          * <p>
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
203          * <p>
204          * @throws NullPointerException If a parameter is null
205          * @throws IllegalArgumentException If a parameter is empty (string) or out
206          * of bounds
207          */
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
210                 this();
211
212                 // Validate all parameters
213                 if (null == productAvailability) {
214                         // Throw NPE
215                         throw new NullPointerException("productAvailability is null"); //NOI18N
216                 } else if (null == productCategory) {
217                         // Throw it again
218                         throw new NullPointerException("productCategory is null"); //NOI18N
219                 } else if (productCategory.getCategoryId() == null) {
220                         // Throw it again
221                         throw new NullPointerException("productCategory.categoryId is null"); //NOI18N
222                 } else if (productCategory.getCategoryId() < 1) {
223                         // Throw IAE
224                         throw new IllegalArgumentException(MessageFormat.format("productCategory.categoryId={0} is invalid", productCategory.getCategoryId())); //NOI18N
225                 } else if (null == productCurrencyCode) {
226                         // Throw it again
227                         throw new NullPointerException("productCurrencyCode is null"); //NOI18N
228                 } else if (productCurrencyCode.isEmpty()) {
229                         // Throw IAE
230                         throw new IllegalArgumentException("productCurrencyCode is empty"); //NOI18N
231                 } else if (null == productGrossPrice) {
232                         // Throw it again
233                         throw new NullPointerException("productGrossPrice is null"); //NOI18N
234                 } else if (productGrossPrice.longValue() < 0) {
235                         // Throw IAE
236                         throw new IllegalArgumentException(MessageFormat.format("productGrossPrice={0} is invalid. Do not enter discounts as products.", productGrossPrice)); //NOI18N
237                 } else if (null == productI18nKey) {
238                         // Throw NPE
239                         throw new NullPointerException("productI18nKey is null"); //NOI18N
240                 } else if (productI18nKey.isEmpty()) {
241                         // Throw IAE
242                         throw new IllegalArgumentException("productI18nKey is empty"); //NOI18N
243                 } else if (null == productUnitAmount) {
244                         // Throw it again
245                         throw new NullPointerException("productUnitAmount is null"); //NOI18N
246                 } else if (productUnitAmount.longValue() < 0) {
247                         // Throw IAE
248                         throw new IllegalArgumentException(MessageFormat.format("productUnitAmount={0} is invalid. Do not enter discounts as products.", productUnitAmount)); //NOI18N
249                 } else if (null == productUnitI18nKey) {
250                         // Throw NPE
251                         throw new NullPointerException("productUnitI18nKey is null"); //NOI18N
252                 } else if (productUnitI18nKey.isEmpty()) {
253                         // Throw IAE
254                         throw new IllegalArgumentException("productUnitI18nKey is empty"); //NOI18N
255                 }
256
257                 // Set all here
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;
265         }
266
267         @Override
268         public int compareTo (final Product product) {
269                 // Check parameter on null-reference and equality to this
270                 if (null == product) {
271                         // Should not happen
272                         throw new NullPointerException("product is null"); //NOI18N
273                 } else if (product.equals(this)) {
274                         // Same object
275                         return 0;
276                 }
277
278                 // Init comparators
279                 final int comparators[] = {
280                         // First check product number
281                         SafeNumberUtils.compare(this.getProductNumber(), product.getProductNumber()),
282                         // ... size
283                         StringUtils.compare(this.getProductSize(), product.getProductSize()),
284                         // ... then i18n key
285                         this.getProductI18nKey().compareTo(product.getProductI18nKey()),
286                         // ... gross price
287                         this.getProductGrossPrice().compareTo(product.getProductGrossPrice()),
288                         // ... net price
289                         SafeNumberUtils.compare(this.getProductNetPrice(), product.getProductNetPrice()),
290                         // ... tax rate
291                         SafeNumberUtils.compare(this.getProductTaxRate(), product.getProductTaxRate()),
292                         // ... unit amount
293                         this.getProductUnitAmount().compareTo(product.getProductUnitAmount()),
294                         // ... currency code
295                         this.getProductCurrencyCode().compareTo(product.getProductCurrencyCode()),
296                         // ... manufacturer
297                         BasicDataUtils.compare(this.getProductManufacturer(), product.getProductManufacturer()),
298                         // ... category
299                         Categories.compare(this.getProductCategory(), product.getProductCategory())
300                 };
301
302                 // Check all values
303                 final int comparison = Comparables.checkAll(comparators);
304
305                 // Return value
306                 return comparison;
307         }
308
309         @Override
310         public boolean equals (final Object object) {
311                 if (this == object) {
312                         return true;
313                 } else if (null == object) {
314                         return false;
315                 } else if (this.getClass() != object.getClass()) {
316                         return false;
317                 }
318
319                 final Product product = (Product) object;
320
321                 if (!Objects.equals(this.getProductGrossPrice(), product.getProductGrossPrice())) {
322                         return false;
323                 } else if (!Objects.equals(this.getProductId(), product.getProductId())) {
324                         return false;
325                 } else if (!Objects.equals(this.getProductI18nKey(), product.getProductI18nKey())) {
326                         return false;
327                 } else if (!Objects.equals(this.getProductAgeGroup(), product.getProductAgeGroup())) {
328                         return false;
329                 } else if (!Objects.equals(this.getProductSize(), product.getProductSize())) {
330                         return false;
331                 }
332
333                 return true;
334         }
335
336         @Override
337         public AgeGroup getProductAgeGroup () {
338                 return this.productAgeGroup;
339         }
340
341         @Override
342         public void setProductAgeGroup (final AgeGroup productAgeGroup) {
343                 this.productAgeGroup = productAgeGroup;
344         }
345
346         @Override
347         public Boolean getProductAvailability () {
348                 return this.productAvailability;
349         }
350
351         @Override
352         public void setProductAvailability (final Boolean productAvailability) {
353                 this.productAvailability = productAvailability;
354         }
355
356         @Override
357         public Category getProductCategory () {
358                 return this.productCategory;
359         }
360
361         @Override
362         public void setProductCategory (final Category productCategory) {
363                 this.productCategory = productCategory;
364         }
365
366         @Override
367         @SuppressWarnings ("ReturnOfDateField")
368         public Date getProductCreated () {
369                 return this.productCreated;
370         }
371
372         @Override
373         @SuppressWarnings ("AssignmentToDateFieldFromParameter")
374         public void setProductCreated (final Date productCreated) {
375                 this.productCreated = productCreated;
376         }
377
378         @Override
379         public String getProductCurrencyCode () {
380                 return this.productCurrencyCode;
381         }
382
383         @Override
384         public void setProductCurrencyCode (final String productCurrencyCode) {
385                 this.productCurrencyCode = productCurrencyCode;
386         }
387
388         @Override
389         public BigDecimal getProductGrossPrice () {
390                 return this.productGrossPrice;
391         }
392
393         @Override
394         public void setProductGrossPrice (final BigDecimal productGrossPrice) {
395                 this.productGrossPrice = productGrossPrice;
396         }
397
398         @Override
399         public String getProductI18nKey () {
400                 return this.productI18nKey;
401         }
402
403         @Override
404         public void setProductI18nKey (final String productI18nKey) {
405                 this.productI18nKey = productI18nKey;
406         }
407
408         @Override
409         public Long getProductId () {
410                 return this.productId;
411         }
412
413         @Override
414         public void setProductId (final Long productId) {
415                 this.productId = productId;
416         }
417
418         @Override
419         public BasicData getProductManufacturer () {
420                 return this.productManufacturer;
421         }
422
423         @Override
424         public void setProductManufacturer (final BasicData productManufacturer) {
425                 this.productManufacturer = productManufacturer;
426         }
427
428         @Override
429         public BigDecimal getProductNetPrice () {
430                 return this.productNetPrice;
431         }
432
433         @Override
434         public void setProductNetPrice (final BigDecimal productNetPrice) {
435                 this.productNetPrice = productNetPrice;
436         }
437
438         @Override
439         public Long getProductNumber () {
440                 return this.productNumber;
441         }
442
443         @Override
444         public void setProductNumber (final Long productNumber) {
445                 this.productNumber = productNumber;
446         }
447
448         @Override
449         public String getProductSize () {
450                 return this.productSize;
451         }
452
453         @Override
454         public void setProductSize (final String productSize) {
455                 this.productSize = productSize;
456         }
457
458         @Override
459         public BigDecimal getProductTaxRate () {
460                 return this.productTaxRate;
461         }
462
463         @Override
464         public void setProductTaxRate (final BigDecimal productTaxRate) {
465                 this.productTaxRate = productTaxRate;
466         }
467
468         @Override
469         public BigDecimal getProductUnitAmount () {
470                 return this.productUnitAmount;
471         }
472
473         @Override
474         public void setProductUnitAmount (final BigDecimal productUnitAmount) {
475                 this.productUnitAmount = productUnitAmount;
476         }
477
478         @Override
479         public String getProductUnitI18nKey () {
480                 return this.productUnitI18nKey;
481         }
482
483         @Override
484         public void setProductUnitI18nKey (final String productUnitI18nKey) {
485                 this.productUnitI18nKey = productUnitI18nKey;
486         }
487
488         @Override
489         public int hashCode () {
490                 int hash = 7;
491
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());
497
498                 return hash;
499         }
500
501 }