/* * JBoss, Home of Professional Open Source * Copyright 2013, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ /* * Image.java * Last modified by: $Author$ * $Revision$ $Date$ */ package org.richfaces.photoalbum.model; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; import javax.validation.constraints.NotNull; import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; import org.codehaus.jackson.annotate.JsonProperty; import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollectionOption; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.OrderBy; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; import org.richfaces.photoalbum.util.DateUtils; @NamedQueries({ @NamedQuery(name = "tag-byName", query = "select m from MetaTag m where m.tag =:tag"), @NamedQuery(name = "tag-popular", query = "select new org.richfaces.photoalbum.model.MetaTag(m.id, m.tag) from MetaTag m join m.images img group by m.id, m.tag order by count(img) desc"), @NamedQuery(name = "user-shelves", query = "select distinct s from Shelf s where (s.shared = true and s.owner.preDefined = true and s.event = null) order by s.name"), @NamedQuery(name = "image-exist", query = "select i from Image i where i.path = :path and i.album = :album"), @NamedQuery(name = "image-countIdenticalImages", query = "select count(i) from Image i where i.path like :path and i.album = :album"), @NamedQuery(name = "tag-suggest", query = "select m from MetaTag m where lower(m.tag) like :tag") }) // cannot use "... like lower(:tag)" /** * Class for representing Image Entity * EJB3 Entity Bean * * @author Andrey Markhel */ @Entity @JsonAutoDetect(fieldVisibility=Visibility.NONE, getterVisibility=Visibility.NONE, isGetterVisibility=Visibility.NONE) public class Image implements Serializable { private static final long serialVersionUID = -7042878411608396483L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonProperty private Long id; @ManyToMany @LazyCollection(LazyCollectionOption.FALSE) @JsonProperty private List<MetaTag> imageTags = new ArrayList<MetaTag>(); @OrderBy(clause = "date asc") @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "image") @LazyCollection(LazyCollectionOption.FALSE) private List<Comment> comments = new ArrayList<Comment>(); @NotNull @ManyToOne @JoinColumn private Album album; @NotNull @NotEmpty @Length(min = 3, max = 200) @Column(length = 255, nullable = false) @JsonProperty private String name; @Transient private boolean covering; @NotNull @NotEmpty @Length(min = 3) @Column(length = 1024, nullable = false) private String path; @Column(length = 255) @JsonProperty private String cameraModel; private int height; private double size; private int width; @Temporal(TemporalType.TIMESTAMP) private Date uploaded; @NotNull @NotEmpty @Length(min = 3) @Column(length = 1024) @JsonProperty private String description; @Temporal(TemporalType.TIMESTAMP) private Date created; @NotNull private boolean allowComments; private Boolean showMetaInfo = true; @Transient private boolean visited; /* * Comma separated tags value */ @Transient private String meta = ""; /** * Getter for property preDefined * * @return is this shelf is predefined */ public boolean isPreDefined() { return getAlbum().isPreDefined(); } // ********************** Accessor Methods ********************** // public Boolean getShowMetaInfo() { return showMetaInfo; } public void setShowMetaInfo(final Boolean showMetaInfo) { this.showMetaInfo = showMetaInfo; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } /** * Getter for property path. Represent file-system structure, relative at uploadRoot dir(determined at startup, by default * is system temp dir) Usually is user.GetLogin() + SLASH + image.getAlbum().getId() + SLASH + fileName, for example * "amarkhel/15/coolPicture.jpg" * * @return relative path of image */ public String getPath() { return path; } /** * Setter for property path * * @param path - relative path to image */ public void setPath(String path) { this.path = path; } public Date getCreated() { return created; } public void setCreated(Date created) { this.created = created; } public Album getAlbum() { return album; } public void setAlbum(Album album) { this.album = album; } public List<Comment> getComments() { return comments; } public List<MetaTag> getImageTags() { return imageTags; } /** * Setter for property meta * * @param meta - string representation of metatags, associated to image. Used at jsf page. */ public void setMeta(String meta) { this.meta = meta; } /** * Getter for property meta * * @return string representation of metatags, associated to image. Used at jsf page. */ public String getMetaString() { return meta; } public String getCameraModel() { return cameraModel; } public void setCameraModel(String cameraModel) { this.cameraModel = cameraModel; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } /** * Getter for property size * * @return size of image in KB */ public double getSize() { return size; } /** * setter for property size * * @param size - size of image in KB */ public void setSize(double size) { this.size = size; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } /** * Getter for property uploaded * * @return date of upload to site of this image */ public Date getUploaded() { return uploaded; } /** * setter for property uploaded * * @param uploaded - date of upload */ public void setUploaded(Date uploaded) { this.uploaded = uploaded; } /** * Getter for property allowComments. If true, other user may comment this image. * * @return is other users may comment this image */ public boolean isAllowComments() { return allowComments; } /** * @param allowComments the allowComments to set */ public void setAllowComments(boolean allowComments) { this.allowComments = allowComments; } /** * @return if this image is covering for containing album */ public boolean isCovering() { return covering; } public void setImageTags(final List<MetaTag> imageTags) { this.imageTags = imageTags; } /** * @param covering - determine if this image is covering for containing album */ public void setCovering(boolean covering) { this.covering = covering; } /** * Getter for property visited * * @return boolean value, that indicated is user visit this image already */ public boolean isVisited() { return visited; } /** * Setter for property visited * * @param visited - boolean value, that indicated is user visit this image already */ public void setVisited(boolean visited) { this.visited = visited; } /** * Determine if this image should be marked as new(on jsf page, for example in tree) * * @return boolean value, that indicated is this image should be marked as new */ public boolean isNew() { if (!visited) { return this.getUploaded().after(DateUtils.getRecentlyDate()); } return false; } // ---------------------------Business methods /** * Add comment to this image. * * @param comment - comment to add */ public void addComment(Comment comment) { if (comment == null) { throw new IllegalArgumentException("Null comment!"); } comment.setImage(this); comments.add(comment); } /** * Remove comment from list of comments, belongs to that image. * * @param comment - comment to delete */ public void removeComment(Comment comment) { if (comment == null) { throw new IllegalArgumentException("Null comment"); } if (comment.getImage().equals(this)) { //comment.setImage(null); comments.remove(comment); } else { throw new IllegalArgumentException("Comment not belongs to this image"); } } /** * Add metatag to this image. * * @param metatag - metatag to add */ public void addMetaTag(MetaTag metatag) { if (metatag == null) { throw new IllegalArgumentException("Null metatag!"); } if (!imageTags.contains(metatag)) { metatag.addImage(this); imageTags.add(metatag); } } /** * Remove metatag from list of metatag, associated to that image. * * @param metatag - metatag to delete */ public void removeMetaTag(MetaTag metatag) { if (metatag == null) { throw new IllegalArgumentException("Null metatag!"); } if (imageTags.contains(metatag)) { metatag.removeImage(this); imageTags.remove(metatag); } } /** * Return MetaTag object by string representation * * @param s - string representation of metatag */ public MetaTag getTagByName(String s) { for (MetaTag t : imageTags) { if (t.getTag().equals(s)) { return t; } } return null; } /** * Return Comma separated tag value for presentation in view */ public String getMeta() { final StringBuilder s = new StringBuilder(); for (MetaTag tag : this.imageTags) { s.append(tag.getTag()).append(", "); } // Remove ',' from end if (s.length() >= 2) { s.delete(s.length() - 2, s.length()); } return s.toString(); } /** * Return relative path of this image in file-system(relative to uploadRoot parameter) */ public String getFullPath() { if (getAlbum().getPath() == null) { return null; } return getAlbum().getPath() + this.path; } public User getOwner() { return getAlbum().getOwner(); } public boolean isOwner(User user) { return user != null && user.equals(getOwner()); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } final Image image = (Image) obj; return (id == null ? image.getId() == null : id.equals(image.getId())) && (path == null ? image.getPath() == null : path.equals(image.getPath())); } @Override public int hashCode() { int result = id != null ? id.hashCode() : 0; result = 31 * result + (path != null ? path.hashCode() : 0); return result; } @Override public String toString() { return "{id : " + getId() + ", name : " + getName() + "}"; } }