/* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2009-2010 Sun Microsystems, Inc. * Portions Copyright 2014-2016 ForgeRock AS. */ package org.opends.guitools.controlpanel.task; import static org.opends.messages.AdminToolMessages.*; import static org.opends.server.util.CollectionUtils.*; import static org.opends.server.util.SchemaUtils.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.SwingUtilities; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.opendj.ldap.schema.AttributeType; import org.forgerock.opendj.ldap.schema.ObjectClass; import org.forgerock.opendj.ldap.schema.SchemaBuilder; import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; import org.opends.guitools.controlpanel.ui.ColorAndFontConstants; import org.opends.guitools.controlpanel.ui.ProgressDialog; import org.opends.guitools.controlpanel.util.Utilities; import org.opends.server.types.OpenDsException; import org.opends.server.types.Schema; /** * The task that is in charge of modifying an attribute definition (and all * the references to this attribute). */ public class ModifyAttributeTask extends Task { private AttributeType oldAttribute; private AttributeType newAttribute; /** * The constructor of the task. * @param info the control panel info. * @param dlg the progress dialog that shows the progress of the task. * @param oldAttribute the old attribute definition. * @param newAttribute the new attribute definition. */ public ModifyAttributeTask(ControlPanelInfo info, ProgressDialog dlg, AttributeType oldAttribute, AttributeType newAttribute) { super(info, dlg); if (oldAttribute == null) { throw new IllegalArgumentException("oldAttribute cannot be null."); } if (newAttribute == null) { throw new IllegalArgumentException("newAttribute cannot be null."); } this.oldAttribute = oldAttribute; this.newAttribute = newAttribute; } @Override public Type getType() { return Type.MODIFY_SCHEMA_ELEMENT; } @Override public LocalizableMessage getTaskDescription() { return INFO_CTRL_PANEL_MODIFY_ATTRIBUTE_TASK_DESCRIPTION.get( oldAttribute.getNameOrOID()); } @Override public boolean canLaunch(Task taskToBeLaunched, Collection incompatibilityReasons) { boolean canLaunch = true; if (state == State.RUNNING && (taskToBeLaunched.getType() == Task.Type.DELETE_SCHEMA_ELEMENT || taskToBeLaunched.getType() == Task.Type.MODIFY_SCHEMA_ELEMENT || taskToBeLaunched.getType() == Task.Type.NEW_SCHEMA_ELEMENT)) { incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); canLaunch = false; } return canLaunch; } @Override public Set getBackends() { return Collections.emptySet(); } @Override protected List getCommandLineArguments() { return Collections.emptyList(); } @Override protected String getCommandLinePath() { return null; } @Override public void runTask() { try { updateSchema(); state = State.FINISHED_SUCCESSFULLY; } catch (Throwable t) { // TODO //revertChanges(); lastException = t; state = State.FINISHED_WITH_ERROR; } } private AttributeType getAttributeToAdd(AttributeType attrToDelete) { if (attrToDelete.equals(oldAttribute)) { return newAttribute; } else if (oldAttribute.equals(attrToDelete.getSuperiorType())) { // get a new attribute with the new superior type return Utilities.updateAttributeTypeWithNewSuperiorType(attrToDelete, newAttribute); } else { // Nothing to be changed in the definition of the attribute itself. return attrToDelete; } } private ObjectClass getObjectClassToAdd(ObjectClass ocToDelete) { boolean containsAttribute = ocToDelete.getRequiredAttributes().contains(oldAttribute) || ocToDelete.getOptionalAttributes().contains(oldAttribute); if (containsAttribute) { Map> extraProperties = DeleteSchemaElementsTask.cloneExtraProperties(ocToDelete); Set required = new HashSet<>(ocToDelete.getDeclaredRequiredAttributes()); Set optional = new HashSet<>(ocToDelete.getDeclaredOptionalAttributes()); if (required.contains(oldAttribute)) { required.remove(oldAttribute); required.add(newAttribute); } else if (optional.contains(oldAttribute)) { optional.remove(oldAttribute); optional.add(newAttribute); } Schema schema = getInfo().getServerDescriptor().getSchema(); String oid = ocToDelete.getOID(); return new SchemaBuilder(schema.getSchemaNG()).buildObjectClass(oid) .names(ocToDelete.getNames()) .description(ocToDelete.getDescription()) .superiorObjectClasses(getNameOrOIDsForOCs(ocToDelete.getSuperiorClasses())) .requiredAttributes(getNameOrOIDsForATs(required)) .optionalAttributes(getNameOrOIDsForATs(optional)) .type(ocToDelete.getObjectClassType()) .obsolete(ocToDelete.isObsolete()) .extraProperties(extraProperties) .addToSchema() .toSchema() .getObjectClass(oid); } else { // Nothing to be changed in the definition of the object class itself. return ocToDelete; } } /** * Updates the schema. * @throws OpenDsException if an error occurs. */ private void updateSchema() throws OpenDsException { Schema schema = getInfo().getServerDescriptor().getSchema(); ArrayList attrs = newArrayList(oldAttribute); LinkedHashSet attrsToDelete = DeleteSchemaElementsTask.getOrderedAttributesToDelete(attrs, schema); LinkedHashSet ocsToDelete = DeleteSchemaElementsTask.getOrderedObjectClassesToDeleteFromAttrs( attrsToDelete, schema); LinkedHashSet attrsToAdd = new LinkedHashSet<>(); ArrayList lAttrsToDelete = new ArrayList<>(attrsToDelete); for (int i = lAttrsToDelete.size() - 1; i >= 0; i--) { AttributeType attrToAdd = getAttributeToAdd(lAttrsToDelete.get(i)); if (attrToAdd != null) { attrsToAdd.add(attrToAdd); } } ArrayList lOcsToDelete = new ArrayList<>(ocsToDelete); LinkedHashSet ocsToAdd = new LinkedHashSet<>(); for (int i = lOcsToDelete.size() - 1; i >= 0; i--) { ocsToAdd.add(getObjectClassToAdd(lOcsToDelete.get(i))); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { getProgressDialog().appendProgressHtml(Utilities.applyFont( INFO_CTRL_PANEL_EXPLANATION_TO_MODIFY_ATTRIBUTE.get( oldAttribute.getNameOrOID())+"

", ColorAndFontConstants.progressFont)); } }); DeleteSchemaElementsTask deleteTask = new DeleteSchemaElementsTask(getInfo(), getProgressDialog(), ocsToDelete, attrsToDelete); deleteTask.runTask(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { getProgressDialog().appendProgressHtml(Utilities.applyFont("

", ColorAndFontConstants.progressFont)); } }); NewSchemaElementsTask createTask = new NewSchemaElementsTask(getInfo(), getProgressDialog(), ocsToAdd, attrsToAdd); createTask.runTask(); notifyConfigurationElementCreated(newAttribute); } }