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