001/*
002 * Copyright 2018-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2018-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2018-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.logs;
037
038
039
040import java.util.Collections;
041import java.util.List;
042
043import com.unboundid.ldap.sdk.ChangeType;
044import com.unboundid.ldap.sdk.ReadOnlyEntry;
045import com.unboundid.ldap.sdk.unboundidds.controls.SoftDeleteRequestControl;
046import com.unboundid.ldif.LDIFAddChangeRecord;
047import com.unboundid.ldif.LDIFChangeRecord;
048import com.unboundid.ldif.LDIFDeleteChangeRecord;
049import com.unboundid.ldif.LDIFException;
050import com.unboundid.ldif.LDIFReader;
051import com.unboundid.util.Debug;
052import com.unboundid.util.NotNull;
053import com.unboundid.util.Nullable;
054import com.unboundid.util.StaticUtils;
055import com.unboundid.util.ThreadSafety;
056import com.unboundid.util.ThreadSafetyLevel;
057
058import static com.unboundid.ldap.sdk.unboundidds.logs.LogMessages.*;
059
060
061
062/**
063 * This class provides a data structure that holds information about an audit
064 * log message that represents an add operation.
065 * <BR>
066 * <BLOCKQUOTE>
067 *   <B>NOTE:</B>  This class, and other classes within the
068 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
069 *   supported for use against Ping Identity, UnboundID, and
070 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
071 *   for proprietary functionality or for external specifications that are not
072 *   considered stable or mature enough to be guaranteed to work in an
073 *   interoperable way with other types of LDAP servers.
074 * </BLOCKQUOTE>
075 */
076@ThreadSafety(level= ThreadSafetyLevel.COMPLETELY_THREADSAFE)
077public final class AddAuditLogMessage
078       extends AuditLogMessage
079{
080  /**
081   * Retrieves the serial version UID for this serializable class.
082   */
083  private static final long serialVersionUID = -4103749134439291911L;
084
085
086
087  // Indicates whether the add operation represents an undelete of a
088  // soft-deleted entry.
089  @Nullable private final Boolean isUndelete;
090
091  // An LDIF change record that encapsulates the change represented by this add
092  // audit log message.
093  @NotNull private final LDIFAddChangeRecord addChangeRecord;
094
095  // The entry included in the undelete request.
096  @Nullable private final ReadOnlyEntry undeleteRequestEntry;
097
098
099
100  /**
101   * Creates a new add audit log message from the provided set of lines.
102   *
103   * @param  logMessageLines  The lines that comprise the log message.  It must
104   *                          not be {@code null} or empty, and it must not
105   *                          contain any blank lines, although it may contain
106   *                          comments.  In fact, it must contain at least one
107   *                          comment line that appears before any non-comment
108   *                          lines (but possibly after other comment lines)
109   *                          that serves as the message header.
110   *
111   * @throws  AuditLogException  If a problem is encountered while processing
112   *                             the provided list of log message lines.
113   */
114  public AddAuditLogMessage(@NotNull final String... logMessageLines)
115         throws AuditLogException
116  {
117    this(StaticUtils.toList(logMessageLines), logMessageLines);
118  }
119
120
121
122  /**
123   * Creates a new add audit log message from the provided set of lines.
124   *
125   * @param  logMessageLines  The lines that comprise the log message.  It must
126   *                          not be {@code null} or empty, and it must not
127   *                          contain any blank lines, although it may contain
128   *                          comments.  In fact, it must contain at least one
129   *                          comment line that appears before any non-comment
130   *                          lines (but possibly after other comment lines)
131   *                          that serves as the message header.
132   *
133   * @throws  AuditLogException  If a problem is encountered while processing
134   *                             the provided list of log message lines.
135   */
136  public AddAuditLogMessage(@NotNull final List<String> logMessageLines)
137         throws AuditLogException
138  {
139    this(logMessageLines, StaticUtils.toArray(logMessageLines, String.class));
140  }
141
142
143
144  /**
145   * Creates a new add audit log message from the provided information.
146   *
147   * @param  logMessageLineList   The lines that comprise the log message as a
148   *                              list.
149   * @param  logMessageLineArray  The lines that comprise the log message as an
150   *                              array.
151   *
152   * @throws  AuditLogException  If a problem is encountered while processing
153   *                             the provided list of log message lines.
154   */
155  private AddAuditLogMessage(@NotNull final List<String> logMessageLineList,
156                             @NotNull final String[] logMessageLineArray)
157          throws AuditLogException
158  {
159    super(logMessageLineList);
160
161    try
162    {
163      final LDIFChangeRecord changeRecord =
164           LDIFReader.decodeChangeRecord(logMessageLineArray);
165      if (!(changeRecord instanceof LDIFAddChangeRecord))
166      {
167        throw new AuditLogException(logMessageLineList,
168             ERR_ADD_AUDIT_LOG_MESSAGE_CHANGE_TYPE_NOT_ADD.get(
169                  changeRecord.getChangeType().getName(),
170                  ChangeType.ADD.getName()));
171      }
172
173      addChangeRecord = (LDIFAddChangeRecord) changeRecord;
174    }
175    catch (final LDIFException e)
176    {
177      Debug.debugException(e);
178      throw new AuditLogException(logMessageLineList,
179           ERR_ADD_AUDIT_LOG_MESSAGE_LINES_NOT_CHANGE_RECORD.get(
180                StaticUtils.getExceptionMessage(e)),
181           e);
182    }
183
184    isUndelete = getNamedValueAsBoolean("isUndelete", getHeaderNamedValues());
185    undeleteRequestEntry = decodeCommentedEntry("Undelete request entry",
186         logMessageLineList, null);
187  }
188
189
190
191  /**
192   * Creates a new add audit log message from the provided set of lines.
193   *
194   * @param  logMessageLines  The lines that comprise the log message.  It must
195   *                          not be {@code null} or empty, and it must not
196   *                          contain any blank lines, although it may contain
197   *                          comments.  In fact, it must contain at least one
198   *                          comment line that appears before any non-comment
199   *                          lines (but possibly after other comment lines)
200   *                          that serves as the message header.
201   * @param  addChangeRecord  The LDIF add change record that is described by
202   *                          the provided log message lines.
203   *
204   * @throws  AuditLogException  If a problem is encountered while processing
205   *                             the provided list of log message lines.
206   */
207  AddAuditLogMessage(@NotNull final List<String> logMessageLines,
208                     @NotNull final LDIFAddChangeRecord addChangeRecord)
209       throws AuditLogException
210  {
211    super(logMessageLines);
212
213    this.addChangeRecord = addChangeRecord;
214
215    isUndelete = getNamedValueAsBoolean("isUndelete", getHeaderNamedValues());
216    undeleteRequestEntry = decodeCommentedEntry("Undelete request entry",
217         logMessageLines, null);
218  }
219
220
221
222  /**
223   * {@inheritDoc}
224   */
225  @Override()
226  @NotNull()
227  public String getDN()
228  {
229    return addChangeRecord.getDN();
230  }
231
232
233
234  /**
235   * Retrieves a read-only representation of the entry that was added.
236   *
237   * @return  A read-only representation of the entry that was added.
238   */
239  @NotNull()
240  public ReadOnlyEntry getEntry()
241  {
242    return new ReadOnlyEntry(addChangeRecord.getEntryToAdd());
243  }
244
245
246
247  /**
248   * Retrieves the value of the "isUndelete" flag from this log message, which
249   * indicates whether the add operation attempted to undelete a previously
250   * soft-deleted entry, if available.
251   *
252   * @return  The value of the "isUndelete" flag from this log message, or
253   *          {@code null} if it is not available.
254   */
255  @Nullable()
256  public Boolean getIsUndelete()
257  {
258    return isUndelete;
259  }
260
261
262
263  /**
264   * Retrieves the entry that comprised the undelete request, available.
265   *
266   * @return  The entry that comprised the undelete request, or {@code null} if
267   *          it is not available.
268   */
269  @Nullable()
270  public ReadOnlyEntry getUndeleteRequestEntry()
271  {
272    return undeleteRequestEntry;
273  }
274
275
276
277  /**
278   * {@inheritDoc}
279   */
280  @Override()
281  @NotNull()
282  public ChangeType getChangeType()
283  {
284    return ChangeType.ADD;
285  }
286
287
288
289  /**
290   * {@inheritDoc}
291   */
292  @Override()
293  @NotNull()
294  public LDIFAddChangeRecord getChangeRecord()
295  {
296    return addChangeRecord;
297  }
298
299
300
301  /**
302   * {@inheritDoc}
303   */
304  @Override()
305  public boolean isRevertible()
306  {
307    // Add audit log messages are always reversible.
308    return true;
309  }
310
311
312
313  /**
314   * {@inheritDoc}
315   */
316  @Override()
317  @NotNull()
318  public List<LDIFChangeRecord> getRevertChangeRecords()
319  {
320    if ((isUndelete != null) && isUndelete)
321    {
322      return Collections.<LDIFChangeRecord>singletonList(
323           new LDIFDeleteChangeRecord(
324                SoftDeleteRequestControl.createSoftDeleteRequest(
325                     addChangeRecord.getDN(), false, true)));
326    }
327    else
328    {
329      return Collections.<LDIFChangeRecord>singletonList(
330           new LDIFDeleteChangeRecord(addChangeRecord.getDN()));
331    }
332  }
333
334
335
336  /**
337   * {@inheritDoc}
338   */
339  @Override()
340  public void toString(@NotNull final StringBuilder buffer)
341  {
342    buffer.append(getUncommentedHeaderLine());
343    buffer.append("; changeType=add; dn=\"");
344    buffer.append(addChangeRecord.getDN());
345    buffer.append('\"');
346  }
347}