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 2009-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.guitools.controlpanel.task; 018 019import static org.opends.messages.AdminToolMessages.*; 020import static org.opends.server.util.CollectionUtils.*; 021 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.Collections; 025import java.util.HashSet; 026import java.util.LinkedHashSet; 027import java.util.List; 028import java.util.Map; 029import java.util.Set; 030 031import javax.swing.SwingUtilities; 032 033import org.forgerock.i18n.LocalizableMessage; 034import org.forgerock.opendj.ldap.schema.AttributeType; 035import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 036import org.opends.guitools.controlpanel.ui.ColorAndFontConstants; 037import org.opends.guitools.controlpanel.ui.ProgressDialog; 038import org.opends.guitools.controlpanel.util.Utilities; 039import org.opends.server.schema.SomeSchemaElement; 040import org.opends.server.types.ObjectClass; 041import org.opends.server.types.OpenDsException; 042import org.opends.server.types.Schema; 043 044/** 045 * The task that is in charge of modifying an attribute definition (and all 046 * the references to this attribute). 047 */ 048public class ModifyAttributeTask extends Task 049{ 050 private AttributeType oldAttribute; 051 private AttributeType newAttribute; 052 053 /** 054 * The constructor of the task. 055 * @param info the control panel info. 056 * @param dlg the progress dialog that shows the progress of the task. 057 * @param oldAttribute the old attribute definition. 058 * @param newAttribute the new attribute definition. 059 */ 060 public ModifyAttributeTask(ControlPanelInfo info, ProgressDialog dlg, 061 AttributeType oldAttribute, AttributeType newAttribute) 062 { 063 super(info, dlg); 064 if (oldAttribute == null) 065 { 066 throw new IllegalArgumentException("oldAttribute cannot be null."); 067 } 068 if (newAttribute == null) 069 { 070 throw new IllegalArgumentException("newAttribute cannot be null."); 071 } 072 this.oldAttribute = oldAttribute; 073 this.newAttribute = newAttribute; 074 } 075 076 /** {@inheritDoc} */ 077 public Type getType() 078 { 079 return Type.MODIFY_SCHEMA_ELEMENT; 080 } 081 082 /** {@inheritDoc} */ 083 public LocalizableMessage getTaskDescription() 084 { 085 return INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TASK_DESCRIPTION.get( 086 oldAttribute.getNameOrOID()); 087 } 088 089 /** {@inheritDoc} */ 090 public boolean canLaunch(Task taskToBeLaunched, 091 Collection<LocalizableMessage> incompatibilityReasons) 092 { 093 boolean canLaunch = true; 094 if (state == State.RUNNING && 095 (taskToBeLaunched.getType() == Task.Type.DELETE_SCHEMA_ELEMENT || 096 taskToBeLaunched.getType() == Task.Type.MODIFY_SCHEMA_ELEMENT || 097 taskToBeLaunched.getType() == Task.Type.NEW_SCHEMA_ELEMENT)) 098 { 099 incompatibilityReasons.add(getIncompatibilityMessage(this, 100 taskToBeLaunched)); 101 canLaunch = false; 102 } 103 return canLaunch; 104 } 105 106 /** {@inheritDoc} */ 107 public Set<String> getBackends() 108 { 109 return Collections.emptySet(); 110 } 111 112 /** {@inheritDoc} */ 113 protected List<String> getCommandLineArguments() 114 { 115 return Collections.emptyList(); 116 } 117 118 /** {@inheritDoc} */ 119 protected String getCommandLinePath() 120 { 121 return null; 122 } 123 124 /** {@inheritDoc} */ 125 public void runTask() 126 { 127 try 128 { 129 updateSchema(); 130 state = State.FINISHED_SUCCESSFULLY; 131 } 132 catch (Throwable t) 133 { 134 // TODO 135 //revertChanges(); 136 lastException = t; 137 state = State.FINISHED_WITH_ERROR; 138 } 139 } 140 141 private AttributeType getAttributeToAdd(AttributeType attrToDelete) 142 { 143 if (attrToDelete.equals(oldAttribute)) 144 { 145 return newAttribute; 146 } 147 else if (oldAttribute.equals(attrToDelete.getSuperiorType())) 148 { 149 // get a new attribute with the new superior type 150 return SomeSchemaElement.changeSuperiorType(attrToDelete, newAttribute); 151 } 152 else 153 { 154 // Nothing to be changed in the definition of the attribute itself. 155 return attrToDelete; 156 } 157 } 158 159 private ObjectClass getObjectClassToAdd(ObjectClass ocToDelete) 160 { 161 boolean containsAttribute = 162 ocToDelete.getRequiredAttributeChain().contains(oldAttribute) || 163 ocToDelete.getOptionalAttributeChain().contains(oldAttribute); 164 if (containsAttribute) 165 { 166 ArrayList<String> allNames = new ArrayList<>(ocToDelete.getNormalizedNames()); 167 Map<String, List<String>> extraProperties = 168 DeleteSchemaElementsTask.cloneExtraProperties(ocToDelete); 169 Set<AttributeType> required = new HashSet<>(ocToDelete.getRequiredAttributes()); 170 Set<AttributeType> optional = new HashSet<>(ocToDelete.getOptionalAttributes()); 171 if (required.contains(oldAttribute)) 172 { 173 required.remove(oldAttribute); 174 required.add(newAttribute); 175 } 176 else if (optional.contains(oldAttribute)) 177 { 178 optional.remove(oldAttribute); 179 optional.add(newAttribute); 180 } 181 return new ObjectClass("", 182 ocToDelete.getPrimaryName(), 183 allNames, 184 ocToDelete.getOID(), 185 ocToDelete.getDescription(), 186 ocToDelete.getSuperiorClasses(), 187 required, 188 optional, 189 ocToDelete.getObjectClassType(), 190 ocToDelete.isObsolete(), 191 extraProperties); 192 } 193 else 194 { 195 // Nothing to be changed in the definition of the object class itself. 196 return ocToDelete; 197 } 198 } 199 200 /** 201 * Updates the schema. 202 * @throws OpenDsException if an error occurs. 203 */ 204 private void updateSchema() throws OpenDsException 205 { 206 Schema schema = getInfo().getServerDescriptor().getSchema(); 207 ArrayList<AttributeType> attrs = newArrayList(oldAttribute); 208 LinkedHashSet<AttributeType> attrsToDelete = 209 DeleteSchemaElementsTask.getOrderedAttributesToDelete(attrs, schema); 210 LinkedHashSet<ObjectClass> ocsToDelete = 211 DeleteSchemaElementsTask.getOrderedObjectClassesToDeleteFromAttrs( 212 attrsToDelete, schema); 213 214 LinkedHashSet<AttributeType> attrsToAdd = new LinkedHashSet<>(); 215 ArrayList<AttributeType> lAttrsToDelete = new ArrayList<>(attrsToDelete); 216 for (int i = lAttrsToDelete.size() - 1; i >= 0; i--) 217 { 218 AttributeType attrToAdd = getAttributeToAdd(lAttrsToDelete.get(i)); 219 if (attrToAdd != null) 220 { 221 attrsToAdd.add(attrToAdd); 222 } 223 } 224 225 ArrayList<ObjectClass> lOcsToDelete = new ArrayList<>(ocsToDelete); 226 LinkedHashSet<ObjectClass> ocsToAdd = new LinkedHashSet<>(); 227 for (int i = lOcsToDelete.size() - 1; i >= 0; i--) 228 { 229 ocsToAdd.add(getObjectClassToAdd(lOcsToDelete.get(i))); 230 } 231 232 SwingUtilities.invokeLater(new Runnable() 233 { 234 public void run() 235 { 236 getProgressDialog().appendProgressHtml(Utilities.applyFont( 237 INFO_CTRL_PANEL_EXPLANATION_TO_MODIFY_ATTRIBUTE.get( 238 oldAttribute.getNameOrOID())+"<br><br>", 239 ColorAndFontConstants.progressFont)); 240 } 241 }); 242 243 DeleteSchemaElementsTask deleteTask = 244 new DeleteSchemaElementsTask(getInfo(), getProgressDialog(), ocsToDelete, 245 attrsToDelete); 246 deleteTask.runTask(); 247 248 SwingUtilities.invokeLater(new Runnable() 249 { 250 public void run() 251 { 252 getProgressDialog().appendProgressHtml(Utilities.applyFont("<br><br>", 253 ColorAndFontConstants.progressFont)); 254 } 255 }); 256 257 NewSchemaElementsTask createTask = 258 new NewSchemaElementsTask(getInfo(), getProgressDialog(), ocsToAdd, 259 attrsToAdd); 260 createTask.runTask(); 261 262 notifyConfigurationElementCreated(newAttribute); 263 } 264}