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 2008 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2015 ForgeRock AS.
016 */
017
018package org.opends.server.admin.client;
019
020
021
022import static org.opends.messages.AdminMessages.*;
023
024import java.util.ArrayList;
025import java.util.Collection;
026import java.util.Collections;
027
028import org.forgerock.i18n.LocalizableMessage;
029import org.forgerock.i18n.LocalizableMessageBuilder;
030import org.forgerock.util.Reject;
031
032
033
034/**
035 * This exception is thrown when the client or server refuses to
036 * create, delete, or modify a managed object due to one or more
037 * constraints that cannot be satisfied.
038 * <p>
039 * Operations can be rejected either by a client-side constraint
040 * violation triggered by {@link ClientConstraintHandler}, or by a
041 * server-side error.
042 * <p>
043 * For example, the Directory Server might not be able perform an
044 * operation due to some OS related problem, such as lack of disk
045 * space, or missing files.
046 */
047public class OperationRejectedException extends AdminClientException {
048
049  /**
050   * The type of operation that caused this exception.
051   */
052  public enum OperationType {
053    /**
054     * A managed object could not be created.
055     */
056    CREATE,
057
058    /**
059     * A managed object could not be deleted.
060     */
061    DELETE,
062
063    /**
064     * A managed object could not be modified.
065     */
066    MODIFY;
067  }
068
069  /**
070   * Serialization ID.
071   */
072  private static final long serialVersionUID = 8547688890613079044L;
073
074
075
076  /** Gets the default message. */
077  private static LocalizableMessage getDefaultMessage(Collection<LocalizableMessage> messages) {
078    Reject.ifNull(messages);
079    Reject.ifFalse(!messages.isEmpty());
080
081    if (messages.size() == 1) {
082      return ERR_OPERATION_REJECTED_EXCEPTION_SINGLE.get(messages.iterator()
083          .next());
084    } else {
085      return ERR_OPERATION_REJECTED_EXCEPTION_PLURAL
086          .get(getSingleMessage(messages));
087    }
088  }
089
090
091
092  /** Merge the messages into a single message. */
093  private static LocalizableMessage getSingleMessage(Collection<LocalizableMessage> messages) {
094    if (messages.size() == 1) {
095      return messages.iterator().next();
096    } else {
097      LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
098
099      boolean isFirst = true;
100      for (LocalizableMessage m : messages) {
101        if (!isFirst) {
102          builder.append(";  ");
103        }
104        builder.append(m);
105        isFirst = false;
106      }
107
108      return builder.toMessage();
109    }
110  }
111
112  /** The messages describing the constraint violations that occurred. */
113  private final Collection<LocalizableMessage> messages;
114
115  /** The type of operation that caused this exception. */
116  private final OperationType type;
117
118  /** The user friendly name of the component that caused this exception. */
119  private final LocalizableMessage ufn;
120
121
122
123  /**
124   * Creates a new operation rejected exception with a default
125   * message.
126   *
127   * @param type
128   *          The type of operation that caused this exception.
129   * @param ufn
130   *          The user friendly name of the component that caused this
131   *          exception.
132   */
133  public OperationRejectedException(OperationType type, LocalizableMessage ufn) {
134    this(type, ufn, ERR_OPERATION_REJECTED_DEFAULT.get());
135  }
136
137
138
139  /**
140   * Creates a new operation rejected exception with the provided
141   * messages.
142   *
143   * @param type
144   *          The type of operation that caused this exception.
145   * @param ufn
146   *          The user friendly name of the component that caused this
147   *          exception.
148   * @param messages
149   *          The messages describing the constraint violations that
150   *          occurred (must be non-<code>null</code> and
151   *          non-empty).
152   */
153  public OperationRejectedException(OperationType type, LocalizableMessage ufn,
154      Collection<LocalizableMessage> messages) {
155    super(getDefaultMessage(messages));
156
157    this.messages = new ArrayList<>(messages);
158    this.type = type;
159    this.ufn = ufn;
160  }
161
162
163
164  /**
165   * Creates a new operation rejected exception with the provided
166   * message.
167   *
168   * @param type
169   *          The type of operation that caused this exception.
170   * @param ufn
171   *          The user friendly name of the component that caused this
172   *          exception.
173   * @param message
174   *          The message describing the constraint violation that
175   *          occurred.
176   */
177  public OperationRejectedException(OperationType type, LocalizableMessage ufn,
178      LocalizableMessage message) {
179    this(type, ufn, Collections.singleton(message));
180  }
181
182
183
184  /**
185   * Gets an unmodifiable collection view of the messages describing
186   * the constraint violations that occurred.
187   *
188   * @return Returns an unmodifiable collection view of the messages
189   *         describing the constraint violations that occurred.
190   */
191  public Collection<LocalizableMessage> getMessages() {
192    return Collections.unmodifiableCollection(messages);
193  }
194
195
196
197  /**
198   * Creates a single message listing all the messages combined into a
199   * single list separated by semi-colons.
200   *
201   * @return Returns a single message listing all the messages
202   *         combined into a single list separated by semi-colons.
203   */
204  public LocalizableMessage getMessagesAsSingleMessage() {
205    return getSingleMessage(messages);
206  }
207
208
209
210  /**
211   * Gets the type of operation that caused this exception.
212   *
213   * @return Returns the type of operation that caused this exception.
214   */
215  public OperationType getOperationType() {
216    return type;
217  }
218
219
220
221  /**
222   * Gets the user friendly name of the component that caused this
223   * exception.
224   *
225   * @return Returns the user friendly name of the component that
226   *         caused this exception.
227   */
228  public LocalizableMessage getUserFriendlyName() {
229    return ufn;
230  }
231
232}