001/*
002* CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *       Copyright 2010 Sun Microsystems, Inc.
025 *       Portions copyright 2013 ForgeRock AS.
026 */
027
028package org.forgerock.opendj.server.core;
029
030/**
031 * Class used to define dynamic typed attachments on {@link AttachmentHolder}
032 * instances. Storing attachment values in {@link AttachmentHolder} has the
033 * advantage of the <tt>Attachment</tt> value being typed when compared to Map
034 * storage:
035 *
036 * @param <T>
037 *            The type of attachment.
038 */
039public final class Attachment<T> {
040    private final T defaultValue;
041    private final String name;
042
043    /**
044     * Construct a new attachment with the specified name and default value.
045     *
046     * @param name
047     *            Attachment name.
048     * @param defaultValue
049     *            Attachment default value, which will be used, if it is not
050     *            set.
051     */
052    public Attachment(final String name, final T defaultValue) {
053        this.name = name;
054        this.defaultValue = defaultValue;
055    }
056
057    /**
058     * Retrieves the attachment value, stored on the {@link AttachmentHolder}.
059     *
060     * @param attachmentHolder
061     *            {@link AttachmentHolder}.
062     * @return attachment value.
063     */
064    public T get(final AttachmentHolder attachmentHolder) {
065        T value = get0(attachmentHolder);
066        if (value == null) {
067            value = defaultValue;
068        }
069        return value;
070    }
071
072    /**
073     * Remove attachment value, stored on the {@link AttachmentHolder}.
074     *
075     * @param attachmentHolder
076     *            {@link AttachmentHolder}.
077     * @return The former value or {@code null} if there was previously no
078     *         value.
079     */
080    public T remove(final AttachmentHolder attachmentHolder) {
081        final T value = get0(attachmentHolder);
082        if (value != null) {
083            set(attachmentHolder, null);
084        }
085        return value;
086    }
087
088    /**
089     * Set attachment value, stored on the {@link AttachmentHolder}. If a value
090     * already exists, it will be replaced.
091     *
092     * @param attachmentHolder
093     *            {@link AttachmentHolder}.
094     * @param value
095     *            attachment value to set.
096     * @return The former value or {@code null} if there was previously no
097     *         value.
098     */
099    public T set(final AttachmentHolder attachmentHolder, final T value) {
100        final T oldValue = get0(attachmentHolder);
101        attachmentHolder.setAttachment(name, value);
102        return oldValue;
103    }
104
105    @SuppressWarnings("unchecked")
106    private T get0(final AttachmentHolder attachmentHolder) {
107        return (T) attachmentHolder.getAttachment(name);
108    }
109}