org.ambraproject.views.AnnotationView.java Source code

Java tutorial

Introduction

Here is the source code for org.ambraproject.views.AnnotationView.java

Source

/*
 * $HeadURL$
 * $Id$
 * Copyright (c) 2006-2012 by Public Library of Science http://plos.org http://ambraproject.org
 * 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.0Unless 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 org.ambraproject.views;

import org.ambraproject.models.Annotation;
import org.ambraproject.models.AnnotationType;
import org.ambraproject.models.UserProfile;
import org.ambraproject.util.TextUtils;
import org.apache.commons.lang.StringUtils;

import javax.annotation.Nullable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.SimpleTimeZone;

/**
 * Immutable view wrapper around annotations
 *
 * @author Alex Kudlick 3/12/12
 */
public class AnnotationView {
    private static final int TRUNCATED_COMMENT_LENGTH = 256;
    private static final AnnotationView[] EMPTY_ARRAY = new AnnotationView[0];
    public static final Comparator<Annotation> REPLY_COMPARATOR = new Comparator<Annotation>() {
        @Override
        public int compare(Annotation reply1, Annotation reply2) {
            return reply1.getCreated().compareTo(reply2.getCreated());
        }
    };
    private final String originalTitle;
    private final String title;
    private final String body;
    private final String originalBody;
    private final String truncatedBody;
    private final String bodyWithUrlLinkingNoPTags;
    private final String truncatedBodyWithUrlLinkingNoPTags;
    private final String bodyWithHighlightedText;
    private final String competingInterestStatement;
    private final String truncatedCompetingInterestStatement;
    private final String annotationUri;
    private final Long ID;
    private final Long creatorID;
    private final String creatorDisplayName;
    private final String creatorFormattedName;
    private final Long articleID;
    private final Long parentID;
    private final String articleDoi;
    private final String articleTitle;
    private final Date created;
    private final String createdFormatted;
    private final AnnotationType type;
    private final AnnotationView[] replies;
    private final Date lastReplyDate;
    private final int totalNumReplies;

    /**
     * Create a new AnnotationView
     *
     * @param annotation    the annotation being wrapped
     * @param articleTitle  the title of the article that is annotated
     * @param articleDoi    the doi of the article that is annotated
     * @param fullReplyTree a full map of all child replies, from Id -> all replies to the annotation with that id.
     *                      Allowed to be null or empty
     */
    public AnnotationView(Annotation annotation, String articleDoi, String articleTitle,
            @Nullable Map<Long, List<Annotation>> fullReplyTree) {
        this.ID = annotation.getID();
        this.articleDoi = articleDoi;
        this.articleTitle = articleTitle;
        if (annotation.getAnnotationUri() != null) {
            this.annotationUri = annotation.getAnnotationUri().replaceFirst("info:doi/", "");
        } else {
            this.annotationUri = null;
        }
        this.originalTitle = annotation.getTitle();
        String escapedTitle = TextUtils.escapeHtml(annotation.getTitle());
        this.title = escapedTitle;

        if (annotation.getBody() == null) {
            this.originalBody = "";
            this.body = "";
            this.truncatedBody = "";
            this.bodyWithUrlLinkingNoPTags = "";
            this.truncatedBodyWithUrlLinkingNoPTags = "";
            this.bodyWithHighlightedText = "";
        } else {
            this.originalBody = annotation.getBody();
            this.body = TextUtils.hyperlinkEnclosedWithPTags(TextUtils.escapeHtml(annotation.getBody()), 25);
            this.truncatedBody = TextUtils.hyperlinkEnclosedWithPTags(
                    TextUtils.truncateText(TextUtils.escapeHtml(annotation.getBody()), TRUNCATED_COMMENT_LENGTH),
                    25);
            this.bodyWithUrlLinkingNoPTags = TextUtils.hyperlink(TextUtils.escapeHtml(annotation.getBody()), 25);
            this.truncatedBodyWithUrlLinkingNoPTags = TextUtils.hyperlink(
                    TextUtils.truncateText(TextUtils.escapeHtml(annotation.getBody()), TRUNCATED_COMMENT_LENGTH),
                    25);
            if (annotation.getHighlightedText() != null) {
                // highlighted text contains the highlighted text
                // and a link to the paragraph location of where the highlighted text is located
                String bodyWithHt = annotation.getHighlightedText() + "\n\n" + annotation.getBody();
                this.bodyWithHighlightedText = TextUtils
                        .hyperlinkEnclosedWithPTags(TextUtils.escapeHtml(bodyWithHt), 150);
            } else {
                this.bodyWithHighlightedText = this.body;
            }
        }

        if (annotation.getCompetingInterestBody() == null) {
            this.competingInterestStatement = "";
            this.truncatedCompetingInterestStatement = "";
        } else {
            this.competingInterestStatement = TextUtils.escapeHtml(annotation.getCompetingInterestBody());
            this.truncatedCompetingInterestStatement = TextUtils.truncateText(
                    TextUtils.escapeHtml(annotation.getCompetingInterestBody()), TRUNCATED_COMMENT_LENGTH);
        }

        this.creatorID = annotation.getCreator().getID();
        this.creatorDisplayName = annotation.getCreator().getDisplayName();
        this.creatorFormattedName = createFormattedName(annotation.getCreator());
        this.articleID = annotation.getArticleID();
        this.parentID = annotation.getParentID();
        this.type = annotation.getType();

        //Defensive copy
        Calendar date = Calendar.getInstance();
        date.setTime(annotation.getCreated());
        this.created = date.getTime();

        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        fmt.setTimeZone(new SimpleTimeZone(0, "UTC"));
        this.createdFormatted = fmt.format(created);

        if (fullReplyTree == null || fullReplyTree.isEmpty()) {
            this.replies = EMPTY_ARRAY;
            this.lastReplyDate = this.created;
            this.totalNumReplies = 0;
        } else {
            List<Annotation> repliesToThis = fullReplyTree.get(annotation.getID());
            if (repliesToThis == null || repliesToThis.isEmpty()) {
                this.replies = EMPTY_ARRAY;
            } else {
                //sort the replies by date so our reply list will be ordered, earliest first
                Collections.sort(repliesToThis, REPLY_COMPARATOR);
                this.replies = new AnnotationView[repliesToThis.size()];
                for (int i = 0; i < repliesToThis.size(); i++) {
                    this.replies[i] = new AnnotationView(repliesToThis.get(i), articleDoi, articleTitle,
                            fullReplyTree);
                }
            }
            //now populate lastReplyDate and totalNumReplies
            this.totalNumReplies = calculateTotalNumReplies();
            this.lastReplyDate = calculateMostRecentReplyDate();
        }
    }

    private int calculateTotalNumReplies() {
        int replyCount = 0;
        replyCount += this.replies.length;
        for (AnnotationView reply : this.replies) {
            replyCount += reply.calculateTotalNumReplies();
        }
        return replyCount;
    }

    //since all the replies have been sorted by the time we call this method, we can just check the last entry in the reply array
    private Date calculateMostRecentReplyDate() {
        Date replyDate = this.created;
        if (this.replies.length > 0) {
            replyDate = this.replies[this.replies.length - 1].calculateMostRecentReplyDate();
        }
        return replyDate;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        AnnotationView that = (AnnotationView) o;

        if (ID != null ? !ID.equals(that.ID) : that.ID != null)
            return false;
        if (annotationUri != null ? !annotationUri.equals(that.annotationUri) : that.annotationUri != null)
            return false;
        if (articleDoi != null ? !articleDoi.equals(that.articleDoi) : that.articleDoi != null)
            return false;
        if (articleTitle != null ? !articleTitle.equals(that.articleTitle) : that.articleTitle != null)
            return false;
        if (articleID != null ? !articleID.equals(that.articleID) : that.articleID != null)
            return false;
        if (parentID != null ? !parentID.equals(that.parentID) : that.parentID != null)
            return false;
        if (body != null ? !body.equals(that.body) : that.body != null)
            return false;
        if (competingInterestStatement != null ? !competingInterestStatement.equals(that.competingInterestStatement)
                : that.competingInterestStatement != null)
            return false;
        if (creatorID != null ? !creatorID.equals(that.creatorID) : that.creatorID != null)
            return false;
        if (creatorDisplayName != null ? !creatorDisplayName.equals(that.creatorDisplayName)
                : that.creatorDisplayName != null)
            return false;
        if (creatorFormattedName != null ? !creatorFormattedName.equals(that.creatorFormattedName)
                : that.creatorFormattedName != null)
            return false;
        if (title != null ? !title.equals(that.title) : that.title != null)
            return false;
        if (type != that.type)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = title != null ? title.hashCode() : 0;
        result = 31 * result + (body != null ? body.hashCode() : 0);
        result = 31 * result + (competingInterestStatement != null ? competingInterestStatement.hashCode() : 0);
        result = 31 * result + (annotationUri != null ? annotationUri.hashCode() : 0);
        result = 31 * result + (ID != null ? ID.hashCode() : 0);
        result = 31 * result + (creatorID != null ? creatorID.hashCode() : 0);
        result = 31 * result + (creatorDisplayName != null ? creatorDisplayName.hashCode() : 0);
        result = 31 * result + (creatorFormattedName != null ? creatorFormattedName.hashCode() : 0);
        result = 31 * result + (articleID != null ? articleID.hashCode() : 0);
        result = 31 * result + (parentID != null ? parentID.hashCode() : 0);
        result = 31 * result + (articleDoi != null ? articleDoi.hashCode() : 0);
        result = 31 * result + (articleTitle != null ? articleTitle.hashCode() : 0);
        result = 31 * result + (type != null ? type.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "AnnotationView{" + "title='" + title + '\'' + ", body='" + body + '\''
                + ", competingInterestStatement='" + competingInterestStatement + '\'' + ", annotationUri='"
                + annotationUri + '\'' + ", creatorID=" + creatorID + ", creatorDisplayName='" + creatorDisplayName
                + '\'' + ", articleID=" + articleID + ", parentID=" + parentID + ", articleDoi='" + articleDoi
                + '\'' + ", articleTitle='" + articleTitle + '\'' + ", type=" + type + '}';
    }

    public String getTitle() {
        return title;
    }

    private String createFormattedName(UserProfile up) {
        StringBuilder name = new StringBuilder();

        if (up.getGivenNames() != null && !up.getGivenNames().equals("")) {
            name.append(up.getGivenNames());
        }

        if (up.getSurname() != null && !up.getSurname().equals("")) {
            if (name.length() > 0) {
                name.append(' ');
            }

            name.append(up.getSurname());
        }

        if (name.length() == 0)
            name.append(up.getDisplayName());

        return name.toString();
    }

    public String getBody() {
        return body;
    }

    public String getTruncatedBody() {
        return this.truncatedBody;
    }

    public String getBodyWithUrlLinkingNoPTags() {
        return bodyWithUrlLinkingNoPTags;
    }

    public String getTruncatedBodyWithUrlLinkingNoPTags() {
        return truncatedBodyWithUrlLinkingNoPTags;
    }

    public String getCompetingInterestStatement() {
        return competingInterestStatement;
    }

    public String getTruncatedCompetingInterestStatement() {
        return truncatedCompetingInterestStatement;
    }

    public AnnotationView[] getReplies() {
        return replies.clone();
    }

    public String getAnnotationUri() {
        return annotationUri;
    }

    public Long getID() {
        return ID;
    }

    public Long getCreatorID() {
        return creatorID;
    }

    public String getCreatorDisplayName() {
        return creatorDisplayName;
    }

    public String getCreatorFormattedName() {
        return creatorFormattedName;
    }

    public Long getArticleID() {
        return articleID;
    }

    public Long getParentID() {
        return parentID;
    }

    public Date getCreated() {
        //Defensive copy
        Calendar date = Calendar.getInstance();
        date.setTime(created);
        return date.getTime();
    }

    public String getCreatedFormatted() {
        return createdFormatted;
    }

    public long getCreatedAsMillis() {
        return created.getTime();
    }

    public AnnotationType getType() {
        return type;
    }

    public String getArticleDoi() {
        return articleDoi;
    }

    public String getArticleTitle() {
        return articleTitle;
    }

    public String getOriginalBody() {
        return originalBody;
    }

    public String getOriginalTitle() {
        return originalTitle;
    }

    public Date getLastReplyDate() {
        return lastReplyDate;
    }

    public int getTotalNumReplies() {
        return totalNumReplies;
    }

    public String getBodyWithHighlightedText() {
        return bodyWithHighlightedText;
    }
}