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 2009 Sun Microsystems, Inc.
015 * Portions Copyright 2016 ForgeRock AS.
016 */
017package org.forgerock.opendj.ldap;
018
019import java.util.Arrays;
020import java.util.Collections;
021import java.util.List;
022
023/**
024 * A Modify operation change type as defined in RFC 4511 section 4.6 is used to
025 * specify the type of modification being performed on an attribute.
026 *
027 * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.6">RFC 4511 -
028 *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
029 * @see <a href="http://tools.ietf.org/html/rfc4525">RFC 4525 - Lightweight
030 *      Directory Access Protocol (LDAP) Modify-Increment Extension </a>
031 */
032public final class ModificationType {
033    /**
034     * Contains equivalent values for the ModificationType values.
035     * This allows easily using ModificationType values with switch statements.
036     */
037    public static enum Enum {
038        //@Checkstyle:off
039        /** @see ModificationType#ADD */
040        ADD,
041        /** @see ModificationType#DELETE */
042        DELETE,
043        /** @see ModificationType#REPLACE */
044        REPLACE,
045        /** @see ModificationType#INCREMENT */
046        INCREMENT,
047        /** Used for unknown modification types. */
048        UNKNOWN;
049        //@Checkstyle:on
050    }
051
052    private static final ModificationType[] ELEMENTS = new ModificationType[4];
053
054    private static final List<ModificationType> IMMUTABLE_ELEMENTS = Collections
055            .unmodifiableList(Arrays.asList(ELEMENTS));
056
057    /**
058     * Add the values listed in the modification to the attribute, creating the
059     * attribute if necessary.
060     */
061    public static final ModificationType ADD = register(0, "add", Enum.ADD);
062
063    /**
064     * Delete the values listed in the modification from the attribute. If no
065     * values are listed, or if all current values of the attribute are listed,
066     * the entire attribute is removed.
067     */
068    public static final ModificationType DELETE = register(1, "delete", Enum.DELETE);
069
070    /**
071     * Replace all existing values of the attribute with the new values listed
072     * in the modification, creating the attribute if it did not already exist.
073     * A replace with no listed values will delete the entire attribute if it
074     * exists, and it is ignored if the attribute does not exist.
075     */
076    public static final ModificationType REPLACE = register(2, "replace", Enum.REPLACE);
077
078    /**
079     * Increment all existing values of the attribute by the amount specified in
080     * the modification value.
081     */
082    public static final ModificationType INCREMENT = register(3, "increment", Enum.INCREMENT);
083
084    /**
085     * Returns the modification change type having the specified integer value
086     * as defined in RFC 4511 section 4.6.
087     *
088     * @param intValue
089     *            The integer value of the modification change type.
090     * @return The modification change type, or {@code null} if there was no
091     *         modification change type associated with {@code intValue}.
092     */
093    public static ModificationType valueOf(final int intValue) {
094        ModificationType result = null;
095        if (0 <= intValue && intValue < ELEMENTS.length) {
096            result = ELEMENTS[intValue];
097        }
098        if (result == null) {
099            result = new ModificationType(intValue, "unknown(" + intValue + ")", Enum.UNKNOWN);
100        }
101        return result;
102    }
103
104    /**
105     * Returns an unmodifiable list containing the set of available modification
106     * change types indexed on their integer value as defined in RFC 4511
107     * section 4.6.
108     *
109     * @return An unmodifiable list containing the set of available modification
110     *         change types.
111     */
112    public static List<ModificationType> values() {
113        return IMMUTABLE_ELEMENTS;
114    }
115
116    /**
117     * Creates and registers a new modification change type with the
118     * application.
119     *
120     * @param intValue
121     *            The integer value of the modification change type as defined
122     *            in RFC 4511 section 4.6.
123     * @param name
124     *            The name of the modification change type.
125     * @param modificationTypeEnum
126     *            The enum equivalent for this modification type
127     * @return The new modification change type.
128     */
129    private static ModificationType register(final int intValue, final String name, final Enum modificationTypeEnum) {
130        final ModificationType t = new ModificationType(intValue, name, modificationTypeEnum);
131        ELEMENTS[intValue] = t;
132        return t;
133    }
134
135    private final int intValue;
136
137    private final String name;
138
139    private final Enum modificationTypeEnum;
140
141    /** Prevent direct instantiation. */
142    private ModificationType(final int intValue, final String name, final Enum modificationTypeEnum) {
143        this.intValue = intValue;
144        this.name = name;
145        this.modificationTypeEnum = modificationTypeEnum;
146    }
147
148    @Override
149    public boolean equals(final Object obj) {
150        if (this == obj) {
151            return true;
152        } else if (obj instanceof ModificationType) {
153            return this.intValue == ((ModificationType) obj).intValue;
154        } else {
155            return false;
156        }
157    }
158
159    @Override
160    public int hashCode() {
161        return intValue;
162    }
163
164    /**
165     * Returns the integer value of this modification change type as defined in
166     * RFC 4511 section 4.6.
167     *
168     * @return The integer value of this modification change type.
169     */
170    public int intValue() {
171        return intValue;
172    }
173
174    /**
175     * Returns the enum equivalent for this modification type.
176     *
177     * @return The enum equivalent for this modification type when a known mapping exists,
178     *         or {@link Enum#UNKNOWN} if this is an unknown modification type.
179     */
180    public Enum asEnum() {
181        return this.modificationTypeEnum;
182    }
183
184    /**
185     * Returns the string representation of this modification change type.
186     *
187     * @return The string representation of this modification change type.
188     */
189    @Override
190    public String toString() {
191        return name;
192    }
193}