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