001/* 002 * Copyright 2019-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2019-2020 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) 2019-2020 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.util; 037 038 039 040import java.io.Serializable; 041import java.util.Collections; 042import java.util.SortedMap; 043import java.util.TreeMap; 044 045import com.unboundid.ldap.sdk.DN; 046import com.unboundid.ldap.sdk.LDAPResult; 047import com.unboundid.ldap.sdk.SearchResult; 048 049 050 051/** 052 * This class provides a data structure with information about the results of 053 * a subtree delete attempt. 054 * 055 * @see SubtreeDeleter 056 */ 057@NotMutable() 058@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 059public final class SubtreeDeleterResult 060 implements Serializable 061{ 062 /** 063 * The serial version UID for this serializable class. 064 */ 065 private static final long serialVersionUID = -4801520019525316763L; 066 067 068 069 // Indicates whether the target subtree is inaccessible. 070 private final boolean subtreeInaccessible; 071 072 // An error that occurred during an attempt to make the target subtree 073 // inaccessible. 074 private final LDAPResult setSubtreeAccessibilityError; 075 076 // The number of entries that were successfully deleted. 077 private final long entriesDeleted; 078 079 // An error that occurred during search processing that prevented identifying 080 // all of the entries in the target subtree. 081 private final SearchResult searchError; 082 083 // A map that contains the DNs of the entries that could not be deleted, 084 // associated with a result indicating the reason for the delete failure. 085 // It will be sorted in descending order 086 private final TreeMap<DN,LDAPResult> deleteErrors; 087 088 089 090 /** 091 * Creates a new subtree deleter result with the provided information. 092 * 093 * @param setSubtreeAccessibilityError 094 * An {@code LDAPResult} object with information about an error 095 * that occurred while trying to make the target subtree 096 * inaccessible, or while trying to remove that accessibility 097 * restriction after all other processing completed successfully 098 * (and the two cases can be differentiated using the value of 099 * the {@code subtreeInaccessible} argument). This may be 100 * {@code null} if no attempt was made to alter the accessibility 101 * of the target subtree, or if its accessibility was 102 * successfully altered. 103 * @param subtreeInaccessible 104 * Indicates whether the target subtree was left inaccessible 105 * after processing completed. If the subtree was made 106 * inaccessible, it will be left in an inaccessible state if any 107 * error occurs during search or delete processing. The 108 * accessibility restriction will be removed if all processing 109 * completes successfully. 110 * @param searchError 111 * A search result with information about an error that occurred 112 * during search processing that prevented identifying all of the 113 * entries in the target subtree. It may be {@code null} if 114 * there was no error during search processing. 115 * @param entriesDeleted 116 * The number of entries that were successfully deleted. 117 * @param deleteErrors 118 * A map that contains the DNs of entries that could not be 119 * deleted, associated with a result indicating the reason for 120 * the delete failure. It must not be {@code null} but may be 121 * empty. 122 */ 123 SubtreeDeleterResult(final LDAPResult setSubtreeAccessibilityError, 124 final boolean subtreeInaccessible, 125 final SearchResult searchError, 126 final long entriesDeleted, 127 final TreeMap<DN,LDAPResult> deleteErrors) 128 { 129 this.setSubtreeAccessibilityError = setSubtreeAccessibilityError; 130 this.subtreeInaccessible = subtreeInaccessible; 131 this.searchError = searchError; 132 this.entriesDeleted = entriesDeleted; 133 this.deleteErrors = deleteErrors; 134 } 135 136 137 138 /** 139 * Indicates whether the {@link SubtreeDeleter} processing was completely 140 * successful. 141 * 142 * @return {@code true} if the subtree deleter processing was completely 143 * successful, or {@code false} if not. 144 */ 145 public boolean completelySuccessful() 146 { 147 return ((setSubtreeAccessibilityError == null) && 148 (! subtreeInaccessible) && 149 (searchError == null) && 150 deleteErrors.isEmpty()); 151 } 152 153 154 155 /** 156 * Retrieves an {@code LDAPResult} that provides information about an error 157 * that occurred while trying to make the target subtree inaccessible before 158 * subtree delete processing, or if an error occurred while trying to remove 159 * the subtree accessibility restriction after all other processing had 160 * completed successfully. This may be {@code null} if no attempts was made 161 * to alter the subtree accessibility, or if no error occurred during 162 * processing. 163 * <BR><BR> 164 * If the return value is non-{@code null} and {@link #subtreeInaccessible} 165 * returns {@code false}, then the error occurred while attempting to make the 166 * target subtree inaccessible. If the return value is non-{@code null} and 167 * {@code isSubtreeInaccessible} returns {@code true}, then the error occurred 168 * while attempting to remove the subtree accessibility restriction. 169 * 170 * @return An {@code LDAPResult} that provides information about an error 171 * that occurred while attempting to alter the accessibility of the 172 * target subtree, or {@code null} if no such error occurred. 173 */ 174 public LDAPResult getSetSubtreeAccessibilityError() 175 { 176 return setSubtreeAccessibilityError; 177 } 178 179 180 181 /** 182 * Indicates whether the target subtree was left in an inaccessible state 183 * after some error occurred during subtree delete processing. 184 * 185 * @return {@code true} if the subtree was set inaccessible at the start of 186 * subtree delete processing and remains inaccessible after an error 187 * occurred during processing, or {@code false} if the subtree 188 * accessibility was not altered or if the accessibility restriction 189 * was removed after all processing completed successfully. 190 */ 191 public boolean subtreeInaccessible() 192 { 193 return subtreeInaccessible; 194 } 195 196 197 198 /** 199 * Retrieves a search result with information about an error that occurred 200 * during search processing that prevented identifying all of the entries in 201 * the target subtree. 202 * 203 * @return A search result with information about an error that occurred 204 * during search processing that prevented identifying all of the 205 * entries in the target subtree, or {@code null} if no error 206 * occurred during search processing. 207 */ 208 public SearchResult getSearchError() 209 { 210 return searchError; 211 } 212 213 214 215 /** 216 * Retrieves the number of entries that were successfully deleted. 217 * 218 * @return The number of entries that were successfully deleted. 219 */ 220 public long getEntriesDeleted() 221 { 222 return entriesDeleted; 223 } 224 225 226 227 /** 228 * Retrieves an unmodifiable sorted map of the DNs of entries that could not 229 * be successfully deleted, each of which is associated with an 230 * {@code LDAPResult} indicating the reason for the delete failure. The map 231 * will be ordered in ascending order using the comparator provided by the 232 * {@code DN} class (that is, with ancestor entries before their descendants). 233 * 234 * @return An unmodifiable sorted map of the DNs of the entries that could 235 * not be deleted, each of which is associated with an 236 * {@code LDAPResult} indicating the reason for the delete failure. 237 */ 238 public SortedMap<DN,LDAPResult> getDeleteErrors() 239 { 240 return Collections.unmodifiableSortedMap(deleteErrors); 241 } 242 243 244 245 /** 246 * Retrieves an unmodifiable sorted map of the DNs of entries that could not 247 * be successfully deleted, each of which is associated with an 248 * {@code LDAPResult} indicating the reason for the delete failure. The map 249 * will be ordered in descending order using the comparator provided by the 250 * {@code DN} class (that is, with descendant entries before their ancestors). 251 * 252 * @return An unmodifiable sorted map of the DNs of the entries that could 253 * not be deleted, each of which is associated with an 254 * {@code LDAPResult} indicating the reason for the delete failure. 255 */ 256 public SortedMap<DN,LDAPResult> getDeleteErrorsDescendingMap() 257 { 258 return Collections.unmodifiableSortedMap(deleteErrors.descendingMap()); 259 } 260 261 262 263 /** 264 * Retrieves the delete errors as a {@code TreeMap}. 265 * 266 * @return Retrieves the delete errors as a {@code TreeMap}. 267 */ 268 TreeMap<DN,LDAPResult> getDeleteErrorsTreeMap() 269 { 270 return deleteErrors; 271 } 272 273 274 275 /** 276 * Retrieves a string representation of this subtree deleter result. 277 * 278 * @return A string representation of this subtree deleter result. 279 */ 280 @Override() 281 public String toString() 282 { 283 final StringBuilder buffer = new StringBuilder(); 284 toString(buffer); 285 return buffer.toString(); 286 } 287 288 289 290 /** 291 * Appends a string representation of this subtree deleter result to the 292 * provided buffer. 293 * 294 * @param buffer The buffer to which the string representation should be 295 * appended. 296 */ 297 public void toString(final StringBuilder buffer) 298 { 299 buffer.append("SubtreeDeleterResult=(completelySuccessful="); 300 buffer.append(completelySuccessful()); 301 302 if (setSubtreeAccessibilityError != null) 303 { 304 buffer.append(", setSubtreeAccessibilityError="); 305 setSubtreeAccessibilityError.toString(buffer); 306 } 307 308 if (subtreeInaccessible) 309 { 310 buffer.append(", subtreeInaccessible=true"); 311 } 312 313 if (searchError != null) 314 { 315 buffer.append(", searchError="); 316 searchError.toString(buffer); 317 } 318 319 buffer.append(", entriesDeleted="); 320 buffer.append(entriesDeleted); 321 322 if (! deleteErrors.isEmpty()) 323 { 324 buffer.append(", deleteErrors="); 325 buffer.append(deleteErrors); 326 } 327 } 328}