org.kuali.kra.protocol.noteattachment.NotesAttachmentsHelperBase.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.kra.protocol.noteattachment.NotesAttachmentsHelperBase.java

Source

/*
 * Kuali Coeus, a comprehensive research administration system for higher education.
 * 
 * Copyright 2005-2015 Kuali, Inc.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kuali.kra.protocol.noteattachment;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kuali.coeus.common.framework.attachment.AttachmentFile;
import org.kuali.coeus.common.framework.attachment.KcAttachmentService;
import org.kuali.coeus.common.framework.auth.SystemAuthorizationService;
import org.kuali.coeus.common.framework.auth.task.TaskAuthorizationService;
import org.kuali.coeus.sys.framework.model.KcPersistableBusinessObjectBase;
import org.kuali.coeus.sys.framework.service.KcServiceLocator;
import org.kuali.coeus.sys.framework.util.CollectionUtils;
import org.kuali.kra.infrastructure.Constants;
import org.kuali.kra.protocol.ProtocolBase;
import org.kuali.kra.protocol.ProtocolDocumentBase;
import org.kuali.kra.protocol.ProtocolFormBase;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
import org.kuali.rice.krad.util.GlobalVariables;

import java.util.*;

/**
 * This is the "Helper" class for ProtocolBase Notes And Attachments.
 */
public abstract class NotesAttachmentsHelperBase {

    private static final Log LOG = LogFactory.getLog(NotesAttachmentsHelperBase.class);

    protected static final String NAMESPACE = "KC-UNT";

    protected static final String UNSUPPORTED_ATTACHMENT_TYPE = "unsupported attachment type ";
    protected static final String CONFIRM_YES_DELETE_ATTACHMENT_PERSONNEL = "confirmDeleteAttachmentPersonnel";
    protected static final String CONFIRM_YES_DELETE_ATTACHMENT_PROTOCOL = "confirmDeleteAttachmentProtocol";
    protected static final String CONFIRM_YES_DELETE_NOTE = "confirmDeleteNote";

    protected final ProtocolAttachmentService notesService;
    protected final TaskAuthorizationService authService;
    protected final SystemAuthorizationService systemAuthorizationService;
    protected final DateTimeService dateTimeService;
    protected final ProtocolNotepadService protocolNotepadService;
    protected final ParameterService parameterService;

    protected final ProtocolAttachmentVersioningUtilityBase versioningUtil;

    protected final ProtocolFormBase form;

    protected ProtocolAttachmentProtocolBase newAttachmentProtocol;
    protected ProtocolAttachmentPersonnelBase newAttachmentPersonnel;
    protected ProtocolAttachmentFilterBase newAttachmentFilter;
    protected List<AttachmentFile> FilesToDelete;

    protected ProtocolNotepadBase protocolNotepad;

    protected boolean modifyAttachments;
    protected boolean modifyNotepads;
    protected boolean viewRestricted;

    protected boolean manageNotesOpen;

    /**
     * Constructs a helper.
     * @param form the form
     * @param notesService the notesService
     * @param authService the authService
     * @param versioningUtil the versioning util
     * @throws IllegalArgumentException if the form, notesService, authService, or versioningUtil is null
     */
    protected NotesAttachmentsHelperBase(final ProtocolFormBase form, final ProtocolAttachmentService notesService,
            final TaskAuthorizationService authService, final SystemAuthorizationService systemAuthorizationService,
            final DateTimeService dateTimeService, final ProtocolNotepadService protocolNotepadService,
            final ParameterService parameterService, final ProtocolAttachmentVersioningUtilityBase versioningUtil) {

        if (form == null) {
            throw new IllegalArgumentException("the form was null");
        }

        if (notesService == null) {
            throw new IllegalArgumentException("the notesService was null");
        }

        if (authService == null) {
            throw new IllegalArgumentException("the authService was null");
        }

        if (systemAuthorizationService == null) {
            throw new IllegalArgumentException("the kraAuthorizationService was null");
        }

        if (dateTimeService == null) {
            throw new IllegalArgumentException("the dateTimeService was null.");
        }

        if (protocolNotepadService == null) {
            throw new IllegalArgumentException("the protocolNotepadService was null.");
        }

        if (parameterService == null) {
            throw new IllegalArgumentException("the parameterService was null.");
        }

        if (versioningUtil == null) {
            throw new IllegalArgumentException("the versioningUtil was null");
        }

        this.form = form;
        this.notesService = notesService;
        this.authService = authService;
        this.systemAuthorizationService = systemAuthorizationService;
        this.dateTimeService = dateTimeService;
        this.protocolNotepadService = protocolNotepadService;
        this.parameterService = parameterService;
        this.versioningUtil = versioningUtil;
        this.FilesToDelete = new ArrayList<AttachmentFile>();
        this.manageNotesOpen = false;
    }

    /**
     * Prepare the tab for viewing.
     */
    public void prepareView() {
        this.initializePermissions();
        notesService.setProtocolAttachmentUpdateUsersName(
                form.getProtocolDocument().getProtocol().getAttachmentProtocols());
        protocolNotepadService
                .setProtocolNotepadUpdateUsersName(form.getProtocolDocument().getProtocol().getNotepads());
    }

    /**
     * Initialize the permissions for viewing/editing the Custom Data web page.
     */
    private void initializePermissions() {
        this.modifyAttachments = this.canEditProtocolAttachments();
        this.modifyNotepads = this.canAddProtocolNotepads();
        this.viewRestricted = this.canViewRestrictedProtocolNotepads();
    }

    /**
     * Checks if ProtocolBase Attachments can be modified.
     * @return true if can be modified false if cannot
     */
    public abstract boolean canEditProtocolAttachments();

    /**
     * Get the userName of the user for the current session.
     * @return the current session's userName
     */
    protected String getUserIdentifier() {
        return GlobalVariables.getUserSession().getPrincipalId();
    }

    /**
     * Get the ProtocolBase.
     * @return the ProtocolBase
     * @throws IllegalArgumentException if the {@link ProtocolDocumentBase ProtocolDocumentBase}
     * or {@link ProtocolBase ProtocolBase} is {@code null}.
     */
    public ProtocolBase getProtocol() {

        if (this.form.getProtocolDocument() == null) {
            throw new IllegalArgumentException("the document is null");
        }

        if (this.form.getProtocolDocument().getProtocol() == null) {
            throw new IllegalArgumentException("the protocol is null");
        }

        return this.form.getProtocolDocument().getProtocol();
    }

    /**
     * Gets the new attachment protocol.  This method will not return null.
     * Also, The ProtocolAttachmentProtocolBase should have a valid protocol Id at this point.
     * 
     * @return the new attachment protocol
     */
    public ProtocolAttachmentProtocolBase getNewAttachmentProtocol() {
        if (this.newAttachmentProtocol == null) {
            this.initAttachmentProtocol();
        }

        return this.newAttachmentProtocol;
    }

    /**
     * Sets the new attachment protocol.
     * @param newAttachmentProtocol the new attachment protocol
     */
    public void setNewAttachmentProtocol(final ProtocolAttachmentProtocolBase newAttachmentProtocol) {
        this.newAttachmentProtocol = newAttachmentProtocol;
    }

    /**
     * Gets the new attachment personnel. This method will not return null.
     * Also, The ProtocolAttachmentPersonnelBase should have a valid protocol Id at this point.
     * @return the new attachment personnel
     */
    public ProtocolAttachmentPersonnelBase getNewAttachmentPersonnel() {
        if (this.newAttachmentPersonnel == null) {
            this.initAttachmentPersonnel();
        }

        return this.newAttachmentPersonnel;
    }

    /**
     * Sets the new attachment personnel.
     * @param newAttachmentPersonnel the new attachment personnel
     */
    public void setNewAttachmentPersonnel(final ProtocolAttachmentPersonnelBase newAttachmentPersonnel) {
        this.newAttachmentPersonnel = newAttachmentPersonnel;
    }

    /**
     * returns whether a protocol can be modified.
     * @return true if modification is allowed false if not.
     */
    public boolean isModifyAttachments() {
        return this.modifyAttachments;
    }

    /**
     * sets whether a protocol can be modified.
     * @param modifyAttachments true if modification is allowed false if not.
     */
    public void setModifyAttachments(final boolean modifyAttachments) {
        this.modifyAttachments = modifyAttachments;
    }

    /** 
     * this method handles logic related to saving attachments.
     * Since multiple attachments can change on a single save, this method must handle all attachment types.
     */
    public void processSave() {
        this.refreshAttachmentReferences(this.getProtocol().getAttachmentProtocols());

        this.syncNewFiles(this.getProtocol().getAttachmentProtocols());

        if (this.versioningUtil.versioningRequired()) {
            this.versioningUtil.versionExstingAttachments();
        }

        //process update user fields for note BOs
        for (ProtocolNotepadBase note : this.getProtocol().getNotepads()) {
            updateUserFieldsIfNecessary(note);
        }
    }

    public void fixReloadedAttachments(Map parameterMap) {
        Iterator keys = parameterMap.keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next().toString();
            String fieldNameStarter = "protocolRefreshButtonClicked";
            try {
                if (key.indexOf(fieldNameStarter) > -1) {
                    //we have a refresh button checker field
                    String fieldValue = ((String[]) parameterMap.get(key))[0];
                    if ("T".equals(fieldValue)) {
                        //a refresh button has been clicked, now we just need to update the appropriate attachment status code
                        int numericVal = Integer.valueOf(key.substring(fieldNameStarter.length()));
                        String documentStatusCode = this.getProtocol().getAttachmentProtocols().get(numericVal)
                                .getDocumentStatusCode();
                        if (StringUtils.isBlank(documentStatusCode) || "3".equals(documentStatusCode)) {
                            this.getProtocol().getAttachmentProtocols().get(numericVal).setDocumentStatusCode("1");
                        }
                    }
                }
            } catch (Exception e) {
                //we could get an exception from the getting of the integer, or from the collection not having the integer in it's index/
                //do nothing.
                LOG.error(e.getMessage(), e);
            }
        }
    }

    /**
     * Adds the "new" ProtocolAttachmentProtocolBase to the ProtocolBase Document.  Before
     * adding this method executes validation.  If the validation fails the attachment is not added.
     */
    public void addNewProtocolAttachmentProtocol() {
        this.refreshAttachmentReferences(Collections.singletonList(this.getNewAttachmentProtocol()));
        this.syncNewFiles(Collections.singletonList(this.getNewAttachmentProtocol()));
        /*
         * Since this event isn't created by the framework and this rule isn't executed by the framework,
         * is it necessary to even create a event?  Does the rule have to implement BusinessRule?  There
         * doesn't seem to be many advantages to doing these things...
         */
        final AddProtocolAttachmentProtocolRule rule = getAddProtocolAttachmentProtocolRuleInstanceHook();
        final AddProtocolAttachmentProtocolEvent event = new AddProtocolAttachmentProtocolEvent(
                this.form.getProtocolDocument(), this.newAttachmentProtocol);

        if (rule.processAddProtocolAttachmentProtocolRules(event)) {
            this.addNewAttachment(this.newAttachmentProtocol);
            this.initAttachmentProtocol();
        } else {
            this.newAttachmentProtocol.setFile(null);
        }

    }

    public abstract AddProtocolAttachmentProtocolRule getAddProtocolAttachmentProtocolRuleInstanceHook();

    /**
     * 
     * Deletes an attachment from a protocol based on a type.
     * 
     * @param <T> the type parameter
     * @param attachmentNumber the attachment number
     * @param type the type token
     * @return true if successfully deleted.
     * @throws IllegalArgumentException if the type is null or not recognized
     */
    public <T extends ProtocolAttachmentBase> boolean deleteExistingAttachmentByType(final int attachmentNumber,
            final Class<T> type) {

        final boolean deleted;

        if (getProtocolAttachmentProtocolClassHook().equals(type)) {
            deleted = this.deleteExistingAttachment(attachmentNumber, this.getProtocol().getAttachmentProtocols());
        } else {
            throw new IllegalArgumentException(UNSUPPORTED_ATTACHMENT_TYPE + type);
        }
        return deleted;
    }

    /**
     * retrieves an attachment from a protocol based on a type.
     * 
     * @param <T> the type parameter
     * @param attachmentNumber the attachment number
     * @param type the type token
     * @return the attachment or null if not found
     * @throws IllegalArgumentException if the type is null or not recognized
     */
    @SuppressWarnings("unchecked")
    public <T extends ProtocolAttachmentBase> T retrieveExistingAttachmentByType(final int attachmentNumber,
            final Class<T> type) {

        final T attachment;

        if (getProtocolAttachmentProtocolClassHook().equals(type)) {
            attachment = (T) retrieveExistingAttachment(attachmentNumber,
                    this.getProtocol().getAttachmentProtocols());
        } else {
            throw new IllegalArgumentException(UNSUPPORTED_ATTACHMENT_TYPE + type);
        }
        return attachment;
    }

    /**
     * Retrieves the confirmation method based on a type. This method is highly coupled to the corresponding Action class.
     * This method is here in order to keep the "ByType" methods together.
     * 
     * @param <T> the type parameter
     * @param type the type token
     * @return the confirmation method
     * @throws IllegalArgumentException if the type is null or not recognized
     */
    public <T extends ProtocolAttachmentBase> String retrieveConfirmMethodByType(final Class<T> type) {
        final String confirmMethod;

        if (getProtocolAttachmentProtocolClassHook().equals(type)) {
            confirmMethod = CONFIRM_YES_DELETE_ATTACHMENT_PROTOCOL;
        } else if (getProtocolAttachmentPersonnelClassHook().equals(type)) {
            confirmMethod = CONFIRM_YES_DELETE_ATTACHMENT_PERSONNEL;
        } else if (getProtocolNotepadClassHook().equals(type)) {
            confirmMethod = CONFIRM_YES_DELETE_NOTE;
        } else {
            throw new IllegalArgumentException(UNSUPPORTED_ATTACHMENT_TYPE + type);
        }

        return confirmMethod;
    }

    /** 
     * Removes an attachment from the passed in List if a valid index.
     * @param <T> the attachment type
     * @param index the index
     * @param attachments the attachment list
     * @return true deleted false if not a valid index
     */
    private <T extends ProtocolAttachmentBase> boolean deleteExistingAttachment(final int index,
            final List<T> attachments) {

        if (!CollectionUtils.validIndexForList(index, attachments)) {
            return false;
        }

        if (this.versioningUtil.versioningRequired() && attachments.get(index).supportsVersioning()) {
            ProtocolAttachmentBase attachment = attachments.get(index);
            if (attachment instanceof ProtocolAttachmentProtocolBase
                    && "1".equals(((ProtocolAttachmentProtocolBase) attachment).getDocumentStatusCode())) {
                ((ProtocolAttachmentProtocolBase) attachment).setDocumentStatusCode("3");
                ((ProtocolAttachmentProtocolBase) attachment).setChanged(true);
            } else {
                this.versioningUtil.versionDeletedAttachment(attachments.get(index));
            }
        } else {
            // personnelattachment will reach here
            attachments.remove(index);
        }

        return true;
    }

    /** 
     * Removes an attachment from the passed in List if a valid index.
     * @param <T> the attachment type
     * @param attachment the attachment to add
     */
    private <T extends ProtocolAttachmentBase> void addNewAttachment(final T attachment) {

        if (this.versioningUtil.versioningRequired() && attachment.supportsVersioning()) {
            this.versioningUtil.versionNewAttachment(attachment);
        } else {
            this.getProtocol().addAttachmentsByType(attachment);
        }
    }

    /** 
     * Retrieves an attachment from the passed in List if a valid index.
     * @param <T> the attachment type
     * @param index the index
     * @param attachments the attachment list
     * @return the attachment or null if not a valid index or if the reference at the index is null
     */
    private static <T extends ProtocolAttachmentBase> T retrieveExistingAttachment(final int index,
            final List<T> attachments) {
        return CollectionUtils.getFromList(index, attachments);
    }

    /**
     * initializes a new attachment protocol setting the protocol id.
     */
    private void initAttachmentProtocol() {
        this.setNewAttachmentProtocol(createNewProtocolAttachmentProtocolInstanceHook(this.getProtocol()));
    }

    protected abstract ProtocolAttachmentProtocolBase createNewProtocolAttachmentProtocolInstanceHook(
            ProtocolBase protocol);

    /**
     * initializes a new attachment personnel setting the protocol id.
     */
    private void initAttachmentPersonnel() {
        this.setNewAttachmentPersonnel(createNewProtocolAttachmentPersonnelInstanceHook(this.getProtocol()));
    }

    protected abstract ProtocolAttachmentPersonnelBase createNewProtocolAttachmentPersonnelInstanceHook(
            ProtocolBase protocol);

    /**
     * initializes a new attachment filter
     */
    private void initAttachmentFilter() {
        ProtocolAttachmentFilterBase paFilter = createNewProtocolAttachmentFilterInstanceHook();

        //Lets see if there is a default set for the attachment sort
        try {
            String defaultSortBy = parameterService.getParameterValueAsString(getProtocolDocumentClassHook(),
                    getAttachmentDefaultSortKeyHook());
            if (StringUtils.isNotBlank(defaultSortBy)) {
                paFilter.setSortBy(defaultSortBy);
            }
        } catch (Exception e) {
            //No default found, do nothing.
        }

        this.setNewAttachmentFilter(paFilter);
    }

    protected abstract ProtocolAttachmentFilterBase createNewProtocolAttachmentFilterInstanceHook();

    protected abstract String getAttachmentDefaultSortKeyHook();

    /** 
     * refreshes a given Collection of attachment's references that can change.
     * @param attachments the attachments.
     */
    private void refreshAttachmentReferences(final Collection<? extends ProtocolAttachmentBase> attachments) {
        assert attachments != null : "the attachments was null";

        for (final ProtocolAttachmentBase attachment : attachments) {
            if (attachment instanceof ProtocolAttachmentProtocolBase) {
                attachment.refreshReferenceObject("status");
            }

            if (attachment instanceof ProtocolAttachmentPersonnelBase) {
                attachment.refreshReferenceObject("person");
            }

            if (attachment instanceof TypedAttachment) {
                attachment.refreshReferenceObject("type");
            }
        }
    }

    /** 
     * Syncs all new files for a given Collection of attachments on the protocol.
     * @param attachments the attachments.
     */
    private void syncNewFiles(final Collection<? extends ProtocolAttachmentBase> attachments) {
        assert attachments != null : "the attachments was null";

        for (final ProtocolAttachmentBase attachment : attachments) {
            if (getKcAttachmentService().doesNewFileExist(attachment.getNewFile())) {
                final AttachmentFile newFile = AttachmentFile.createFromFormFile(attachment.getNewFile());
                //setting the sequence number to the old file sequence number
                if (attachment.getFile() != null) {
                    newFile.setSequenceNumber(attachment.getFile().getSequenceNumber());
                }
                attachment.setFile(newFile);
                // set to null, so the subsequent post will not creating new file again
                attachment.setNewFile(null);
            }
        }
    }

    public List<AttachmentFile> getFilesToDelete() {
        return FilesToDelete;
    }

    public void setFilesToDelete(List<AttachmentFile> filesToDelete) {
        FilesToDelete = filesToDelete;
    }

    /**
     * Checks if ProtocolBase Notepads can be modified.
     * @return true if can be modified false if cannot
     */
    public abstract boolean canAddProtocolNotepads();

    /**
     * Checks if restricted ProtocolBase Notepads can be viewed.
     * @return true if can be modified false if cannot
     */
    public abstract boolean canViewRestrictedProtocolNotepads();

    /**
     * Gets the new protocol notepad.  This method will not return null.
     * Also, The ProtocolAttachmentProtocolBase should have a valid protocol Id at this point.
     * 
     * @return the new protocol notepad
     */
    public ProtocolNotepadBase getNewProtocolNotepad() {
        if (this.protocolNotepad == null) {
            this.initProtocolNotepad();
        }

        return this.protocolNotepad;
    }

    /**
     * Sets the new protocol notepad.
     * @param protocolNotepad the new protocol notepad
     */
    public void setNewProtocolNotepad(final ProtocolNotepadBase protocolNotepad) {
        this.protocolNotepad = protocolNotepad;
    }

    /**
     * returns whether a protocol can be modified.
     * @return true if modification is allowed false if not.
     */
    public boolean isModifyNotepads() {
        return this.modifyNotepads;
    }

    /**
     * sets whether a protocol can be modified.
     * @param modifyNotepads true if modification is allowed false if not.
     */
    public void setModifyNotepads(final boolean modifyNotepads) {
        this.modifyNotepads = modifyNotepads;
    }

    /**
     * returns whether a restricted note can be viewed.
     * @return true if viewing is allowed false if not.
     */
    public boolean isViewRestricted() {
        return this.viewRestricted;
    }

    /**
     * sets whether a restricted note can be viewed.
     * @param viewRestricted true if viewing is allowed false if not.
     */
    public void setViewRestricted(final boolean viewRestricted) {
        this.viewRestricted = viewRestricted;
    }

    // Note: Changing the name to make this more generic to work with both irb and iacuc.
    //       Pushing this method down to return true for its respective admin.  This flag
    //       is specifically used in the protocolNotes.tag file to determine if something 
    //       is read only.
    public abstract boolean isProtocolAdmin();

    /**
     * initializes a new attachment protocol setting the protocol id.
     */
    private void initProtocolNotepad() {
        final ProtocolNotepadBase notepad = createNewProtocolNotepadInstanceHook(this.getProtocol());
        notepad.setEntryNumber(this.getNextEntryNumber());
        notepad.setEditable(true);
        this.setNewProtocolNotepad(notepad);
    }

    /**
     * adds a new note to the protocol.  Also performs validation.
     */
    public void addNewNote() {
        final AddProtocolNotepadRule rule = new AddProtocolNotepadRuleImpl();
        final AddProtocolNotepadEvent event = new AddProtocolNotepadEvent(this.form.getProtocolDocument(),
                this.protocolNotepad);

        if (!rule.processAddProtocolNotepadRules(event)) {
            return;
        }
        ProtocolNotepadBase pn = this.protocolNotepad;
        pn.setCreateUser(GlobalVariables.getUserSession().getPrincipalName());
        pn.setCreateTimestamp(((DateTimeService) KcServiceLocator.getService(Constants.DATE_TIME_SERVICE_NAME))
                .getCurrentTimestamp());
        this.addNewNotepad(pn);

        this.initProtocolNotepad();
    }

    /**
     * modifies an existing note in the protocol.
     */
    public void modifyNote(int noteToModify) {

        ProtocolNotepadBase notepadObject = this.getProtocol().getNotepads().get(noteToModify);
        final ModifyProtocolNotepadRule rule = new ModifyProtocolNotepadRuleImpl();
        final ModifyProtocolNotepadEvent event = new ModifyProtocolNotepadEvent(this.form.getProtocolDocument(),
                notepadObject);

        if (!rule.processModifyProtocolNotepadRules(event)) {
            return;
        }
        modifyNotepad(notepadObject);
    }

    /**
     * deletes a note from the protocol.
     */
    public boolean deleteNote(int noteToDelete) {
        final DeleteProtocolNotepadRule rule = new DeleteProtocolNotepadRuleImpl();
        final DeleteProtocolNotepadEvent event = new DeleteProtocolNotepadEvent(this.form.getProtocolDocument(),
                this.protocolNotepad);

        if (!rule.processDeleteProtocolNotepadRules(event)) {
            return false;
        }

        this.deleteNotepad(noteToDelete);
        return true;
    }

    void updateUserFieldsIfNecessary(ProtocolNotepadBase currentNote) {
        if (currentNote.isEditable()) {
            setUpdateFields(currentNote);
        }
    }

    /**
     * Update the User and Timestamp for the business object.
     * @param bo the business object
     */
    private void setUpdateFields(KcPersistableBusinessObjectBase bo) {
        bo.setUpdateUser(GlobalVariables.getUserSession().getPrincipalName());
        bo.setUpdateTimestamp(dateTimeService.getCurrentTimestamp());
    }

    /**
     * Adds the passed in notepad to the list on the protocol.
     * @param notepad the notepad to add.
     */
    private void addNewNotepad(ProtocolNotepadBase notepad) {
        setUpdateFields(notepad);
        // set notepad to be editable
        notepad.setEditable(true);
        this.getProtocol().getNotepads().add(0, notepad);
    }

    /**
     * Adds the passed in notepad to the list on the protocol.
     * @param notepadObject the notepad to add.
     */
    private void modifyNotepad(ProtocolNotepadBase notepadObject) {
        setUpdateFields(notepadObject);
        // set notepad to be editable
        notepadObject.setEditable(true);
    }

    /**
     * Adds the passed in notepad to the list on the protocol.
     * @param noteToDelete the notepad to add.
     */
    private void deleteNotepad(int noteToDelete) {
        this.getProtocol().getNotepads().remove(noteToDelete);
    }

    /** gets the next entry number based on previously generated numbers. */
    private Integer getNextEntryNumber() {
        final Collection<ProtocolNotepadBase> notepads = this.getProtocol().getNotepads();
        final Integer maxEntry = notepads.isEmpty() ? Integer.valueOf(0)
                : Collections.max(notepads, ProtocolNotepadBase.NotepadByEntryNumber.INSTANCE).getEntryNumber();
        return Integer.valueOf(maxEntry.intValue() + 1);
    }

    public void setManageNotesOpen(boolean manageNotesOpen) {
        this.manageNotesOpen = manageNotesOpen;
    }

    public boolean isManageNotesOpen() {
        return this.manageNotesOpen;
    }

    public ProtocolAttachmentFilterBase getNewAttachmentFilter() {
        if (newAttachmentFilter == null) {
            this.initAttachmentFilter();
        }
        return newAttachmentFilter;
    }

    public void setNewAttachmentFilter(ProtocolAttachmentFilterBase newAttachmentFilter) {
        this.newAttachmentFilter = newAttachmentFilter;
    }

    public void addNewProtocolAttachmentFilter() {
        this.getProtocol().setProtocolAttachmentFilter(getNewAttachmentFilter());
    }

    public abstract Class<? extends ProtocolAttachmentProtocolBase> getProtocolAttachmentProtocolClassHook();

    public abstract Class<? extends ProtocolAttachmentPersonnelBase> getProtocolAttachmentPersonnelClassHook();

    public abstract Class<? extends ProtocolNotepadBase> getProtocolNotepadClassHook();

    public abstract Class<? extends ProtocolDocumentBase> getProtocolDocumentClassHook();

    protected abstract ProtocolNotepadBase createNewProtocolNotepadInstanceHook(ProtocolBase protocol);

    private KcAttachmentService getKcAttachmentService() {
        return KcServiceLocator.getService(KcAttachmentService.class);
    }
}