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