/* Copyright 2006 - 2010 Under Dusken Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package no.dusken.aranea.model; import no.dusken.aranea.constraints.NoSlash; import org.compass.annotations.Searchable; import org.compass.annotations.SearchableBoostProperty; import org.compass.annotations.SearchableComponent; import org.compass.annotations.SearchableProperty; import javax.persistence.*; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; import static javax.persistence.CascadeType.ALL; import static javax.persistence.FetchType.LAZY; /** * * @author Erlend Hamnaberg<erlenha@underdusken.no> * @author Marvin B. Lillehaug <lillehau@underdusken.no> */ @Entity @Table(name = "page", uniqueConstraints = {@UniqueConstraint(columnNames = {"externalid"})}) @SequenceGenerator(name = "page_seq", sequenceName = "page_id_seq") @NamedQueries({ @NamedQuery(name = "page_bysection", query = "select p from Page p where (p.parent = :section or p.parent.parent = :section) " + " order by p.timePublished asc"), @NamedQuery(name = "page_bysection_published", query = "select p from Page p, SectionPage sp where (sp.section = :section and sp.page = p) " + "and p.published = true and p.visibleFrom <= :time and p.visibleTo >= :time order by sp.ordering asc"), @NamedQuery(name = "page_bydate", query = "select p from Page p where p.timePublished >= :from and p.timePublished <= :to order by p.timePublished desc"), @NamedQuery(name = "page_all", query = "select p from Page p order by p.timePublished desc"), @NamedQuery(name = "page_all_published", query = "select p from Page p where p.published = true order by p.timeCreated desc"), @NamedQuery(name = "page_all_not_published", query = "select p from Page p where p.published = false order by p.timeCreated desc") }) @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name = "type") @Searchable(root = false) public abstract class Page extends AraneaObject { /** * The Page's title */ @Column(nullable = false) @SearchableProperty(boost = 5) @Size(max = 255, min = 1) @NotNull @NoSlash private String title; /** * URLEncoded title */ @Transient private String safeTitle; /** * Alternative title (for frontpage use) */ @SearchableProperty @Size(max = 255) @NoSlash private String altTitle; /** * Typically the ingress of an article, description of a gallery etc */ @Column(length = 500) @SearchableProperty(boost = 3) @Size(max = 500) @NotNull private String summary; /** * Alternaltive summary (for frontpage use) */ @Column(length = 500) @SearchableProperty(boost = 3) @Size(max = 500) private String alternaltiveSummary; /** * date this Page was last modified */ @Temporal(TemporalType.TIMESTAMP) private Calendar modified = new GregorianCalendar(); /** * Is this page published by a editor? * Default is false */ @Column @SearchableProperty private Boolean published = false; /** * Date this page was published */ @Temporal(TemporalType.TIMESTAMP) @SearchableProperty private Calendar timePublished; /** * Before this date the article should not be visible */ @Temporal(TemporalType.TIMESTAMP) private Calendar visibleFrom = null; /** * After this date the article should not be visible */ @Temporal(TemporalType.TIMESTAMP) private Calendar visibleTo = null; /** * The parent section or subsection */ @ManyToOne @JoinColumn(name = "parent_id", nullable = false) private Section parent; /** * Who has written this. */ @ManyToMany(fetch = LAZY) @JoinTable(name = "page_author") @OrderBy("surname") @SearchableComponent private List<Person> authors = new LinkedList<Person>(); /** * If an external person has written this. */ @Column @SearchableProperty private String externalAuthor; /** * This page's relations */ @OneToMany(fetch = LAZY, mappedBy = "page1", cascade = ALL) private List<PageRelation> pageRelationsAsPage1 = new LinkedList<PageRelation>(); /** * This page's relations */ @OneToMany(fetch = LAZY, mappedBy = "page2", cascade = ALL) private List<PageRelation> pageRelationsAsPage2 = new LinkedList<PageRelation>(); /** * This pages's mediarescources */ @OneToMany(cascade = ALL, mappedBy = "page", fetch = LAZY) @OrderBy("paragraph") private List<PageMediaResource> mediaResources = new ArrayList<PageMediaResource>(); /** * The Image to use on the frontpage and as main image */ @OneToOne(cascade = ALL, fetch = LAZY) private PageImage frontpageImage; /** * Images assigned to the page */ @OneToMany(cascade = ALL, mappedBy = "page", fetch = LAZY) @OrderBy("paragraph") private List<PageImage> pageImages = new ArrayList<PageImage>(); /** * A list of tags assigned to the article */ @ManyToMany(fetch = LAZY) @SearchableComponent private List<Tag> tags = new LinkedList<Tag>(); public Page() { } @PreRemove public void preRemove(){ removePersons(); } private void removePersons() { for(Person author : authors){ author.getPages().remove(this); } authors = null; } public Page(Long ID) { super(ID); } public String getTitle() { return title == null ? "" : title; } public void setTitle(String title) { // reset safeTitle safeTitle = null; this.title = title; } public String getAltTitle() { return altTitle; } public void setAltTitle(String altTitle) { this.altTitle = altTitle; } public String getSafeTitle() { if (safeTitle == null) { try { safeTitle = URLEncoder.encode(getTitle().toLowerCase(), "UTF-8"); } catch (UnsupportedEncodingException e) { // do nothing } } return safeTitle; } public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public Calendar getModified() { return modified; } public void setModified(Calendar modified) { this.modified = modified; } public Calendar getTimePublished() { return timePublished; } public void setTimePublished(Calendar timePublished) { this.timePublished = timePublished; } public Section getParent() { return parent; } public void setParent(Section parent) { this.parent = parent; } public List<Person> getAuthors() { return authors; } public void setAuthors(List<Person> authors) { this.authors = authors; } public String getExternalAuthor() { return externalAuthor; } public void setExternalAuthor(String externalAuthor){ this.externalAuthor = externalAuthor; } @Override public int compareTo(Object o) { Page p = (Page) o; return p.getTimePublished().compareTo(this.getTimePublished()); } public List<PageRelation> getPageRelationsAsPage1() { return pageRelationsAsPage1; } public void setPageRelationsAsPage1(List<PageRelation> pageRelations) { this.pageRelationsAsPage1 = pageRelations; } /** * This adds a new relation to this page. * you only need to run this method on one of the Pages, the relation is made both ways at once. * * @param otherPage The other page in the relation * @param description1 The description of the relation this page has to the other page, ie if this page is background * to the other page, this would be background * @param description2 the description of the relation the otherpage has to this page. see description1 * @param onFrontPage decides if the relation is shown on the front page. */ public void addRelation(Page otherPage, String description1, String description2, boolean onFrontPage) { if (!this.isRelatedTo(otherPage) && otherPage != this) { //adding the relatin to the other Page PageRelation pageRelation = new PageRelation(this, description1, otherPage, description2, onFrontPage); pageRelationsAsPage1.add(pageRelation); otherPage.getPageRelationsAsPage2().add(pageRelation); } } /** * Removes the given pagerelation, if it is a existing relation * * @param relation */ public void removeRelation(PageRelation relation) { if (getPageRelations().contains(relation)) { getPageRelations().remove(relation); //removing the relation in the other page //relation.getPageRelatedTo(this).removeRelation(relation); } } /** * If this page is related to the given page, remove the relation * * @param page */ public void removeRelation(Page page) { //goes through the relation to see if this page is related to the given page for (PageRelation r : getPageRelations()) { if (r.getPageRelatedTo(page).equals(this)) { //if it is, remove it from both pages. this.removeRelation(r); r.getPageRelatedTo(this).removeRelation(r); } } } /** * @param page the page you want to know if is related to this * @return true if related, false if not */ public boolean isRelatedTo(Page page) { if (page.equals(this)) { return true; } for (PageRelation pr : getPageRelations()) { if (pr.getPageRelatedTo(page) == null) { continue; } if (pr.getPageRelatedTo(page).equals(this)) { return true; } } return false; } /** * return the pagerelation between this and page * * @param page * @return pagerelation if present */ public PageRelation getRelation(Page page) { if (page != this && isRelatedTo(page)) { for (PageRelation pr : getPageRelations()) { if (pr.getPageRelatedTo(page) == null) { continue; } if (pr.getPageRelatedTo(page).equals(this)) { return pr; } } } return null; } public Calendar getVisibleFrom() { return this.visibleFrom; } public void setVisibleFrom(Calendar visibleFrom) { this.visibleFrom = visibleFrom; } public Calendar getVisibleTo() { return this.visibleTo; } public void setVisibleTo(Calendar visibleTo) { this.visibleTo = visibleTo; } public List<PageMediaResource> getMediaRescources() { return mediaResources; } public void setMediaRescources(List<PageMediaResource> mediaRescources) { this.mediaResources = mediaRescources; } public String getAlternaltiveSummary() { return alternaltiveSummary; } public void setAlternaltiveSummary(String alternaltiveSummary) { this.alternaltiveSummary = alternaltiveSummary; } public List<PageImage> getPageImages() { return pageImages; } public void setPageImages(List<PageImage> pageImages) { this.pageImages = pageImages; } /** * @param entry , the entry you are adding to the gallery */ public void addEntry(PageImage entry) { pageImages.add(entry); } /** * removes the entry * * @param entry */ public void removeEntry(PageImage entry) { pageImages.remove(entry); } public PageImage getFrontpageImage() { return frontpageImage; } public void setFrontpageImage(PageImage frontpageImage) { this.frontpageImage = frontpageImage; } public List<Tag> getTags() { return tags; } public void setTags(List<Tag> tags) { this.tags = tags; } public List<PageRelation> getPageRelationsAsPage2() { return pageRelationsAsPage2; } public void setPageRelationsAsPage2(List<PageRelation> pageRelationsAsPage2) { this.pageRelationsAsPage2 = pageRelationsAsPage2; } /** * @return All pagerelations */ public List<PageRelation> getPageRelations() { List<PageRelation> all = new LinkedList<PageRelation>(); all.addAll(pageRelationsAsPage1); all.addAll(pageRelationsAsPage2); return all; } public Boolean getPublished() { return published; } public void setPublished(Boolean published) { this.published = published; } /** * @return a boostvalue that is higher the closer to now the * page is published. */ @SearchableBoostProperty(defaultValue = 0.0f) public float getCalendarBoost(){ float ret = 0.0f; if (timePublished != null) { Calendar nowCal = new GregorianCalendar(); long now = nowCal.getTimeInMillis(); long difference = now - timePublished.getTimeInMillis(); //map the difference to the interval [0, 10] ret = 10.0f - ((float) difference / (float) now) * 10.0f; } return ret; } }