001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2009-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.guitools.controlpanel.task; 028 029import static org.opends.messages.AdminToolMessages.*; 030import static org.opends.server.util.CollectionUtils.*; 031 032import java.util.ArrayList; 033import java.util.Collection; 034import java.util.Collections; 035import java.util.HashSet; 036import java.util.LinkedHashSet; 037import java.util.List; 038import java.util.Map; 039import java.util.Set; 040 041import javax.swing.SwingUtilities; 042 043import org.forgerock.i18n.LocalizableMessage; 044import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 045import org.opends.guitools.controlpanel.ui.ColorAndFontConstants; 046import org.opends.guitools.controlpanel.ui.ProgressDialog; 047import org.opends.guitools.controlpanel.util.Utilities; 048import org.opends.server.types.AttributeType; 049import org.opends.server.types.ObjectClass; 050import org.opends.server.types.OpenDsException; 051import org.opends.server.types.Schema; 052 053/** 054 * The task that is in charge of modifying an attribute definition (and all 055 * the references to this attribute). 056 */ 057public class ModifyAttributeTask extends Task 058{ 059 private AttributeType oldAttribute; 060 private AttributeType newAttribute; 061 062 /** 063 * The constructor of the task. 064 * @param info the control panel info. 065 * @param dlg the progress dialog that shows the progress of the task. 066 * @param oldAttribute the old attribute definition. 067 * @param newAttribute the new attribute definition. 068 */ 069 public ModifyAttributeTask(ControlPanelInfo info, ProgressDialog dlg, 070 AttributeType oldAttribute, AttributeType newAttribute) 071 { 072 super(info, dlg); 073 if (oldAttribute == null) 074 { 075 throw new IllegalArgumentException("oldAttribute cannot be null."); 076 } 077 if (newAttribute == null) 078 { 079 throw new IllegalArgumentException("newAttribute cannot be null."); 080 } 081 this.oldAttribute = oldAttribute; 082 this.newAttribute = newAttribute; 083 } 084 085 /** {@inheritDoc} */ 086 public Type getType() 087 { 088 return Type.MODIFY_SCHEMA_ELEMENT; 089 } 090 091 /** {@inheritDoc} */ 092 public LocalizableMessage getTaskDescription() 093 { 094 return INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TASK_DESCRIPTION.get( 095 oldAttribute.getNameOrOID()); 096 } 097 098 /** {@inheritDoc} */ 099 public boolean canLaunch(Task taskToBeLaunched, 100 Collection<LocalizableMessage> incompatibilityReasons) 101 { 102 boolean canLaunch = true; 103 if (state == State.RUNNING && 104 (taskToBeLaunched.getType() == Task.Type.DELETE_SCHEMA_ELEMENT || 105 taskToBeLaunched.getType() == Task.Type.MODIFY_SCHEMA_ELEMENT || 106 taskToBeLaunched.getType() == Task.Type.NEW_SCHEMA_ELEMENT)) 107 { 108 incompatibilityReasons.add(getIncompatibilityMessage(this, 109 taskToBeLaunched)); 110 canLaunch = false; 111 } 112 return canLaunch; 113 } 114 115 /** {@inheritDoc} */ 116 public Set<String> getBackends() 117 { 118 return Collections.emptySet(); 119 } 120 121 /** {@inheritDoc} */ 122 protected List<String> getCommandLineArguments() 123 { 124 return Collections.emptyList(); 125 } 126 127 /** {@inheritDoc} */ 128 protected String getCommandLinePath() 129 { 130 return null; 131 } 132 133 /** {@inheritDoc} */ 134 public void runTask() 135 { 136 try 137 { 138 updateSchema(); 139 state = State.FINISHED_SUCCESSFULLY; 140 } 141 catch (Throwable t) 142 { 143 // TODO 144 //revertChanges(); 145 lastException = t; 146 state = State.FINISHED_WITH_ERROR; 147 } 148 } 149 150 private AttributeType getAttributeToAdd(AttributeType attrToDelete) 151 { 152 if (attrToDelete.equals(oldAttribute)) 153 { 154 return newAttribute; 155 } 156 else if (oldAttribute.equals(attrToDelete.getSuperiorType())) 157 { 158 ArrayList<String> allNames = new ArrayList<>(attrToDelete.getNormalizedNames()); 159 Map<String, List<String>> extraProperties = 160 DeleteSchemaElementsTask.cloneExtraProperties(attrToDelete); 161 AttributeType newSuperior = newAttribute; 162 return new AttributeType( 163 "", 164 attrToDelete.getPrimaryName(), 165 allNames, 166 attrToDelete.getOID(), 167 attrToDelete.getDescription(), 168 newSuperior, 169 attrToDelete.getSyntax(), 170 attrToDelete.getApproximateMatchingRule(), 171 attrToDelete.getEqualityMatchingRule(), 172 attrToDelete.getOrderingMatchingRule(), 173 attrToDelete.getSubstringMatchingRule(), 174 attrToDelete.getUsage(), 175 attrToDelete.isCollective(), 176 attrToDelete.isNoUserModification(), 177 attrToDelete.isObsolete(), 178 attrToDelete.isSingleValue(), 179 extraProperties); 180 } 181 else 182 { 183 // Nothing to be changed in the definition of the attribute itself. 184 return attrToDelete; 185 } 186 } 187 188 private ObjectClass getObjectClassToAdd(ObjectClass ocToDelete) 189 { 190 boolean containsAttribute = 191 ocToDelete.getRequiredAttributeChain().contains(oldAttribute) || 192 ocToDelete.getOptionalAttributeChain().contains(oldAttribute); 193 if (containsAttribute) 194 { 195 ArrayList<String> allNames = new ArrayList<>(ocToDelete.getNormalizedNames()); 196 Map<String, List<String>> extraProperties = 197 DeleteSchemaElementsTask.cloneExtraProperties(ocToDelete); 198 Set<AttributeType> required = new HashSet<>(ocToDelete.getRequiredAttributes()); 199 Set<AttributeType> optional = new HashSet<>(ocToDelete.getOptionalAttributes()); 200 if (required.contains(oldAttribute)) 201 { 202 required.remove(oldAttribute); 203 required.add(newAttribute); 204 } 205 else if (optional.contains(oldAttribute)) 206 { 207 optional.remove(oldAttribute); 208 optional.add(newAttribute); 209 } 210 return new ObjectClass("", 211 ocToDelete.getPrimaryName(), 212 allNames, 213 ocToDelete.getOID(), 214 ocToDelete.getDescription(), 215 ocToDelete.getSuperiorClasses(), 216 required, 217 optional, 218 ocToDelete.getObjectClassType(), 219 ocToDelete.isObsolete(), 220 extraProperties); 221 } 222 else 223 { 224 // Nothing to be changed in the definition of the object class itself. 225 return ocToDelete; 226 } 227 } 228 229 /** 230 * Updates the schema. 231 * @throws OpenDsException if an error occurs. 232 */ 233 private void updateSchema() throws OpenDsException 234 { 235 Schema schema = getInfo().getServerDescriptor().getSchema(); 236 ArrayList<AttributeType> attrs = newArrayList(oldAttribute); 237 LinkedHashSet<AttributeType> attrsToDelete = 238 DeleteSchemaElementsTask.getOrderedAttributesToDelete(attrs, schema); 239 LinkedHashSet<ObjectClass> ocsToDelete = 240 DeleteSchemaElementsTask.getOrderedObjectClassesToDeleteFromAttrs( 241 attrsToDelete, schema); 242 243 LinkedHashSet<AttributeType> attrsToAdd = new LinkedHashSet<>(); 244 ArrayList<AttributeType> lAttrsToDelete = new ArrayList<>(attrsToDelete); 245 for (int i = lAttrsToDelete.size() - 1; i >= 0; i--) 246 { 247 AttributeType attrToAdd = getAttributeToAdd(lAttrsToDelete.get(i)); 248 if (attrToAdd != null) 249 { 250 attrsToAdd.add(attrToAdd); 251 } 252 } 253 254 ArrayList<ObjectClass> lOcsToDelete = new ArrayList<>(ocsToDelete); 255 LinkedHashSet<ObjectClass> ocsToAdd = new LinkedHashSet<>(); 256 for (int i = lOcsToDelete.size() - 1; i >= 0; i--) 257 { 258 ocsToAdd.add(getObjectClassToAdd(lOcsToDelete.get(i))); 259 } 260 261 SwingUtilities.invokeLater(new Runnable() 262 { 263 public void run() 264 { 265 getProgressDialog().appendProgressHtml(Utilities.applyFont( 266 INFO_CTRL_PANEL_EXPLANATION_TO_MODIFY_ATTRIBUTE.get( 267 oldAttribute.getNameOrOID())+"<br><br>", 268 ColorAndFontConstants.progressFont)); 269 } 270 }); 271 272 DeleteSchemaElementsTask deleteTask = 273 new DeleteSchemaElementsTask(getInfo(), getProgressDialog(), ocsToDelete, 274 attrsToDelete); 275 deleteTask.runTask(); 276 277 SwingUtilities.invokeLater(new Runnable() 278 { 279 public void run() 280 { 281 getProgressDialog().appendProgressHtml(Utilities.applyFont("<br><br>", 282 ColorAndFontConstants.progressFont)); 283 } 284 }); 285 286 NewSchemaElementsTask createTask = 287 new NewSchemaElementsTask(getInfo(), getProgressDialog(), ocsToAdd, 288 attrsToAdd); 289 createTask.runTask(); 290 291 notifyConfigurationElementCreated(newAttribute); 292 } 293}