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