Java tutorial
/* * Copyright 2005-2015 shopxx.net. All rights reserved. * Support: http://3936242.01p.com/ * License: http://3936242.01p.com/license */ package net.shopxx.entity; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.persistence.AttributeConverter; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Convert; import javax.persistence.Converter; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Lob; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import javax.persistence.Transient; import javax.validation.Valid; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import net.shopxx.BaseAttributeConverter; import net.shopxx.BigDecimalNumericFieldBridge; import net.shopxx.Setting; import net.shopxx.TemplateConfig; import net.shopxx.util.SystemUtils; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.hibernate.search.annotations.Analyze; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.FieldBridge; import org.hibernate.search.annotations.Index; import org.hibernate.search.annotations.Indexed; import org.hibernate.search.annotations.NumericField; import org.hibernate.search.annotations.Store; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; @Indexed @Entity @Table(name = "xx_goods") @SequenceGenerator(name = "sequenceGenerator", sequenceName = "seq_goods") public class Goods extends BaseEntity<Long> { private static final long serialVersionUID = -8781963456943173684L; public static final String HITS_CACHE_NAME = "goodsHits"; public static final int ATTRIBUTE_VALUE_PROPERTY_COUNT = 20; public static final String ATTRIBUTE_VALUE_PROPERTY_NAME_PREFIX = "attributeValue"; public enum Type { general, exchange, gift } public enum GenerateMethod { none, eager, lazy } public enum OrderType { topDesc, priceAsc, priceDesc, salesDesc, scoreDesc, dateDesc } public enum RankingType { score, scoreCount, weekHits, monthHits, hits, weekSales, monthSales, sales } private String sn; private String name; private String caption; private Goods.Type type; private BigDecimal price; private BigDecimal marketPrice; private String image; private String unit; private Integer weight; private Boolean isMarketable; private Boolean isList; private Boolean isTop; private Boolean isDelivery; private String introduction; private String memo; private String keyword; private String seoTitle; private String seoKeywords; private String seoDescription; private Float score; private Long totalScore; private Long scoreCount; private Long weekHits; private Long monthHits; private Long hits; private Long weekSales; private Long monthSales; private Long sales; private Date weekHitsDate; private Date monthHitsDate; private Date weekSalesDate; private Date monthSalesDate; private Goods.GenerateMethod generateMethod; private String attributeValue0; private String attributeValue1; private String attributeValue2; private String attributeValue3; private String attributeValue4; private String attributeValue5; private String attributeValue6; private String attributeValue7; private String attributeValue8; private String attributeValue9; private String attributeValue10; private String attributeValue11; private String attributeValue12; private String attributeValue13; private String attributeValue14; private String attributeValue15; private String attributeValue16; private String attributeValue17; private String attributeValue18; private String attributeValue19; private ProductCategory productCategory; private Brand brand; private List<ProductImage> productImages = new ArrayList<ProductImage>(); private List<ParameterValue> parameterValues = new ArrayList<ParameterValue>(); private List<SpecificationItem> specificationItems = new ArrayList<SpecificationItem>(); private Set<Promotion> promotions = new HashSet<Promotion>(); private Set<Tag> tags = new HashSet<Tag>(); private Set<Review> reviews = new HashSet<Review>(); private Set<Consultation> consultations = new HashSet<Consultation>(); private Set<Member> favoriteMembers = new HashSet<Member>(); private Set<Product> products = new HashSet<Product>(); @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @Pattern(regexp = "^[0-9a-zA-Z_-]+$") @Length(max = 100) @Column(nullable = false, updatable = false, unique = true) public String getSn() { return sn; } public void setSn(String sn) { this.sn = sn; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.YES) @NotEmpty @Length(max = 200) @Column(nullable = false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Field(store = Store.YES, index = Index.NO, analyze = Analyze.NO) @Length(max = 200) public String getCaption() { return caption; } public void setCaption(String caption) { this.caption = caption; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NotNull(groups = Save.class) @Column(nullable = false, updatable = false) public Goods.Type getType() { return type; } public void setType(Goods.Type type) { this.type = type; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NumericField @FieldBridge(impl = BigDecimalNumericFieldBridge.class) @Column(nullable = false, precision = 21, scale = 6) public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } @Field(store = Store.YES, index = Index.NO, analyze = Analyze.NO) @NumericField @FieldBridge(impl = BigDecimalNumericFieldBridge.class) @Column(nullable = false, precision = 21, scale = 6) public BigDecimal getMarketPrice() { return marketPrice; } public void setMarketPrice(BigDecimal marketPrice) { this.marketPrice = marketPrice; } @Field(store = Store.YES, index = Index.NO, analyze = Analyze.NO) @Length(max = 200) @Pattern(regexp = "^(?i)(http:\\/\\/|https:\\/\\/|\\/).*$") public String getImage() { return image; } public void setImage(String image) { this.image = image; } @Field(store = Store.YES, index = Index.NO, analyze = Analyze.NO) @Length(max = 200) public String getUnit() { return unit; } public void setUnit(String unit) { this.unit = unit; } @Field(store = Store.YES, index = Index.NO, analyze = Analyze.NO) @NumericField @Min(0) public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NotNull @Column(nullable = false) public Boolean getIsMarketable() { return isMarketable; } public void setIsMarketable(Boolean isMarketable) { this.isMarketable = isMarketable; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NotNull @Column(nullable = false) public Boolean getIsList() { return isList; } public void setIsList(Boolean isList) { this.isList = isList; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NotNull @Column(nullable = false) public Boolean getIsTop() { return isTop; } public void setIsTop(Boolean isTop) { this.isTop = isTop; } @NotNull @Column(nullable = false) public Boolean getIsDelivery() { return isDelivery; } public void setIsDelivery(Boolean isDelivery) { this.isDelivery = isDelivery; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.YES) @Lob public String getIntroduction() { return introduction; } public void setIntroduction(String introduction) { this.introduction = introduction; } @Length(max = 200) public String getMemo() { return memo; } public void setMemo(String memo) { this.memo = memo; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.YES) @Length(max = 200) public String getKeyword() { return keyword; } public void setKeyword(String keyword) { if (keyword != null) { keyword = keyword.replaceAll("[,\\s]*,[,\\s]*", ",").replaceAll("^,|,$", ""); } this.keyword = keyword; } @Length(max = 200) public String getSeoTitle() { return seoTitle; } public void setSeoTitle(String seoTitle) { this.seoTitle = seoTitle; } @Length(max = 200) public String getSeoKeywords() { return seoKeywords; } public void setSeoKeywords(String seoKeywords) { if (seoKeywords != null) { seoKeywords = seoKeywords.replaceAll("[,\\s]*,[,\\s]*", ",").replaceAll("^,|,$", ""); } this.seoKeywords = seoKeywords; } @Length(max = 200) public String getSeoDescription() { return seoDescription; } public void setSeoDescription(String seoDescription) { this.seoDescription = seoDescription; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NumericField @Column(nullable = false, precision = 12, scale = 6) public Float getScore() { return score; } public void setScore(Float score) { this.score = score; } @Column(nullable = false) public Long getTotalScore() { return totalScore; } public void setTotalScore(Long totalScore) { this.totalScore = totalScore; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NumericField @Column(nullable = false) public Long getScoreCount() { return scoreCount; } public void setScoreCount(Long scoreCount) { this.scoreCount = scoreCount; } @Column(nullable = false) public Long getWeekHits() { return weekHits; } public void setWeekHits(Long weekHits) { this.weekHits = weekHits; } @Column(nullable = false) public Long getMonthHits() { return monthHits; } public void setMonthHits(Long monthHits) { this.monthHits = monthHits; } @Column(nullable = false) public Long getHits() { return hits; } public void setHits(Long hits) { this.hits = hits; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NumericField @Column(nullable = false) public Long getWeekSales() { return weekSales; } public void setWeekSales(Long weekSales) { this.weekSales = weekSales; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NumericField @Column(nullable = false) public Long getMonthSales() { return monthSales; } public void setMonthSales(Long monthSales) { this.monthSales = monthSales; } @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO) @NumericField @Column(nullable = false) public Long getSales() { return sales; } public void setSales(Long sales) { this.sales = sales; } @Column(nullable = false) public Date getWeekHitsDate() { return weekHitsDate; } public void setWeekHitsDate(Date weekHitsDate) { this.weekHitsDate = weekHitsDate; } @Column(nullable = false) public Date getMonthHitsDate() { return monthHitsDate; } public void setMonthHitsDate(Date monthHitsDate) { this.monthHitsDate = monthHitsDate; } @Column(nullable = false) public Date getWeekSalesDate() { return weekSalesDate; } public void setWeekSalesDate(Date weekSalesDate) { this.weekSalesDate = weekSalesDate; } @Column(nullable = false) public Date getMonthSalesDate() { return monthSalesDate; } public void setMonthSalesDate(Date monthSalesDate) { this.monthSalesDate = monthSalesDate; } @Column(nullable = false) public Goods.GenerateMethod getGenerateMethod() { return generateMethod; } public void setGenerateMethod(Goods.GenerateMethod generateMethod) { this.generateMethod = generateMethod; } @Length(max = 200) public String getAttributeValue0() { return attributeValue0; } public void setAttributeValue0(String attributeValue0) { this.attributeValue0 = attributeValue0; } @Length(max = 200) public String getAttributeValue1() { return attributeValue1; } public void setAttributeValue1(String attributeValue1) { this.attributeValue1 = attributeValue1; } @Length(max = 200) public String getAttributeValue2() { return attributeValue2; } public void setAttributeValue2(String attributeValue2) { this.attributeValue2 = attributeValue2; } @Length(max = 200) public String getAttributeValue3() { return attributeValue3; } public void setAttributeValue3(String attributeValue3) { this.attributeValue3 = attributeValue3; } @Length(max = 200) public String getAttributeValue4() { return attributeValue4; } public void setAttributeValue4(String attributeValue4) { this.attributeValue4 = attributeValue4; } @Length(max = 200) public String getAttributeValue5() { return attributeValue5; } public void setAttributeValue5(String attributeValue5) { this.attributeValue5 = attributeValue5; } @Length(max = 200) public String getAttributeValue6() { return attributeValue6; } public void setAttributeValue6(String attributeValue6) { this.attributeValue6 = attributeValue6; } @Length(max = 200) public String getAttributeValue7() { return attributeValue7; } public void setAttributeValue7(String attributeValue7) { this.attributeValue7 = attributeValue7; } @Length(max = 200) public String getAttributeValue8() { return attributeValue8; } public void setAttributeValue8(String attributeValue8) { this.attributeValue8 = attributeValue8; } @Length(max = 200) public String getAttributeValue9() { return attributeValue9; } public void setAttributeValue9(String attributeValue9) { this.attributeValue9 = attributeValue9; } @Length(max = 200) public String getAttributeValue10() { return attributeValue10; } public void setAttributeValue10(String attributeValue10) { this.attributeValue10 = attributeValue10; } @Length(max = 200) public String getAttributeValue11() { return attributeValue11; } public void setAttributeValue11(String attributeValue11) { this.attributeValue11 = attributeValue11; } @Length(max = 200) public String getAttributeValue12() { return attributeValue12; } public void setAttributeValue12(String attributeValue12) { this.attributeValue12 = attributeValue12; } @Length(max = 200) public String getAttributeValue13() { return attributeValue13; } public void setAttributeValue13(String attributeValue13) { this.attributeValue13 = attributeValue13; } @Length(max = 200) public String getAttributeValue14() { return attributeValue14; } public void setAttributeValue14(String attributeValue14) { this.attributeValue14 = attributeValue14; } @Length(max = 200) public String getAttributeValue15() { return attributeValue15; } public void setAttributeValue15(String attributeValue15) { this.attributeValue15 = attributeValue15; } @Length(max = 200) public String getAttributeValue16() { return attributeValue16; } public void setAttributeValue16(String attributeValue16) { this.attributeValue16 = attributeValue16; } @Length(max = 200) public String getAttributeValue17() { return attributeValue17; } public void setAttributeValue17(String attributeValue17) { this.attributeValue17 = attributeValue17; } @Length(max = 200) public String getAttributeValue18() { return attributeValue18; } public void setAttributeValue18(String attributeValue18) { this.attributeValue18 = attributeValue18; } @Length(max = 200) public String getAttributeValue19() { return attributeValue19; } public void setAttributeValue19(String attributeValue19) { this.attributeValue19 = attributeValue19; } @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false) public ProductCategory getProductCategory() { return productCategory; } public void setProductCategory(ProductCategory productCategory) { this.productCategory = productCategory; } @ManyToOne(fetch = FetchType.LAZY) public Brand getBrand() { return brand; } public void setBrand(Brand brand) { this.brand = brand; } @Valid @Column(length = 4000) @Convert(converter = ProductImageConverter.class) public List<ProductImage> getProductImages() { return productImages; } public void setProductImages(List<ProductImage> productImages) { this.productImages = productImages; } @Valid @Column(length = 4000) @Convert(converter = ParameterValueConverter.class) public List<ParameterValue> getParameterValues() { return parameterValues; } public void setParameterValues(List<ParameterValue> parameterValues) { this.parameterValues = parameterValues; } @Valid @Column(length = 4000) @Convert(converter = SpecificationItemConverter.class) public List<SpecificationItem> getSpecificationItems() { return specificationItems; } public void setSpecificationItems(List<SpecificationItem> specificationItems) { this.specificationItems = specificationItems; } @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "xx_goods_promotion") @OrderBy("order asc") public Set<Promotion> getPromotions() { return promotions; } public void setPromotions(Set<Promotion> promotions) { this.promotions = promotions; } @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "xx_goods_tag") @OrderBy("order asc") public Set<Tag> getTags() { return tags; } public void setTags(Set<Tag> tags) { this.tags = tags; } @OneToMany(mappedBy = "goods", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) public Set<Review> getReviews() { return reviews; } public void setReviews(Set<Review> reviews) { this.reviews = reviews; } @OneToMany(mappedBy = "goods", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) public Set<Consultation> getConsultations() { return consultations; } public void setConsultations(Set<Consultation> consultations) { this.consultations = consultations; } @ManyToMany(mappedBy = "favoriteGoods", fetch = FetchType.LAZY) public Set<Member> getFavoriteMembers() { return favoriteMembers; } public void setFavoriteMembers(Set<Member> favoriteMembers) { this.favoriteMembers = favoriteMembers; } @OneToMany(mappedBy = "goods", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE) public Set<Product> getProducts() { return products; } public void setProducts(Set<Product> products) { this.products = products; } @Transient public String getPath() { TemplateConfig templateConfig = SystemUtils.getTemplateConfig("goodsContent"); Map<String, Object> model = new HashMap<String, Object>(); model.put("goods", this); return templateConfig.getRealStaticPath(model); } @Transient public String getUrl() { Setting setting = SystemUtils.getSetting(); return setting.getSiteUrl() + getPath(); } @Transient public String getThumbnail() { if (CollectionUtils.isEmpty(getProductImages())) { return null; } return getProductImages().get(0).getThumbnail(); } @Transient public boolean getIsStockAlert() { return CollectionUtils.exists(getProducts(), new Predicate() { public boolean evaluate(Object object) { Product product = (Product) object; return product != null && product.getIsStockAlert(); } }); } @Transient public boolean getIsOutOfStock() { return CollectionUtils.exists(getProducts(), new Predicate() { public boolean evaluate(Object object) { Product product = (Product) object; return product != null && product.getIsOutOfStock(); } }); } @Transient public List<Integer> getSpecificationItemEntryIds() { List<Integer> specificationItemEntryIds = new ArrayList<Integer>(); if (CollectionUtils.isNotEmpty(getSpecificationItems())) { for (SpecificationItem specificationItem : getSpecificationItems()) { if (CollectionUtils.isNotEmpty(specificationItem.getEntries())) { for (SpecificationItem.Entry entry : specificationItem.getEntries()) { specificationItemEntryIds.add(entry.getId()); } } } Collections.sort(specificationItemEntryIds); } return specificationItemEntryIds; } @Transient public Product getDefaultProduct() { return (Product) CollectionUtils.find(getProducts(), new Predicate() { public boolean evaluate(Object object) { Product product = (Product) object; return product != null && product.getIsDefault(); } }); } @SuppressWarnings("unchecked") @Transient public Set<Promotion> getValidPromotions() { if (!Goods.Type.general.equals(getType()) || CollectionUtils.isEmpty(getPromotions())) { return Collections.emptySet(); } return new HashSet<Promotion>(CollectionUtils.select(getPromotions(), new Predicate() { public boolean evaluate(Object object) { Promotion promotion = (Promotion) object; return promotion != null && promotion.hasBegun() && !promotion.hasEnded() && CollectionUtils.isNotEmpty(promotion.getMemberRanks()); } })); } @Transient public boolean hasSpecification() { return CollectionUtils.isNotEmpty(getSpecificationItems()); } @Transient public boolean isValid(Promotion promotion) { if (!Goods.Type.general.equals(getType()) || promotion == null || !promotion.hasBegun() || promotion.hasEnded() || CollectionUtils.isEmpty(promotion.getMemberRanks())) { return false; } if (getValidPromotions().contains(promotion)) { return true; } return false; } @Transient public String getAttributeValue(Attribute attribute) { if (attribute == null || attribute.getPropertyIndex() == null) { return null; } try { String propertyName = ATTRIBUTE_VALUE_PROPERTY_NAME_PREFIX + attribute.getPropertyIndex(); return (String) PropertyUtils.getProperty(this, propertyName); } catch (IllegalAccessException e) { throw new RuntimeException(e.getMessage(), e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getMessage(), e); } catch (NoSuchMethodException e) { throw new RuntimeException(e.getMessage(), e); } } @Transient public void setAttributeValue(Attribute attribute, String attributeValue) { if (attribute == null || attribute.getPropertyIndex() == null) { return; } try { String propertyName = ATTRIBUTE_VALUE_PROPERTY_NAME_PREFIX + attribute.getPropertyIndex(); PropertyUtils.setProperty(this, propertyName, attributeValue); } catch (IllegalAccessException e) { throw new RuntimeException(e.getMessage(), e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getMessage(), e); } catch (NoSuchMethodException e) { throw new RuntimeException(e.getMessage(), e); } } @Transient public void removeAttributeValue() { for (int i = 0; i < ATTRIBUTE_VALUE_PROPERTY_COUNT; i++) { String propertyName = ATTRIBUTE_VALUE_PROPERTY_NAME_PREFIX + i; try { PropertyUtils.setProperty(this, propertyName, null); } catch (IllegalAccessException e) { throw new RuntimeException(e.getMessage(), e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getMessage(), e); } catch (NoSuchMethodException e) { throw new RuntimeException(e.getMessage(), e); } } } @PrePersist public void prePersist() { if (CollectionUtils.isNotEmpty(getProductImages())) { Collections.sort(getProductImages()); } } @PreUpdate public void preUpdate() { if (getTotalScore() != null && getScoreCount() != null && getScoreCount() > 0) { setScore((float) getTotalScore() / getScoreCount()); } else { setScore(0F); } if (CollectionUtils.isNotEmpty(getProductImages())) { Collections.sort(getProductImages()); } } @PreRemove public void preRemove() { Set<Member> favoriteMembers = getFavoriteMembers(); if (favoriteMembers != null) { for (Member favoriteMember : favoriteMembers) { favoriteMember.getFavoriteGoods().remove(this); } } } @Converter public static class ProductImageConverter extends BaseAttributeConverter<List<ProductImage>> implements AttributeConverter<Object, String> { } @Converter public static class ParameterValueConverter extends BaseAttributeConverter<List<ParameterValue>> implements AttributeConverter<Object, String> { } @Converter public static class SpecificationItemConverter extends BaseAttributeConverter<List<SpecificationItem>> implements AttributeConverter<Object, String> { } }