| author | David W. Miller | 2012-06-21 20:04:27 (EDT) |
|---|---|---|
| committer | Roberto E. Escobar | 2012-06-21 20:04:27 (EDT) |
| commit | c1bbd91635f303f556efc6d29c2fd94f2954b027 (patch) (side-by-side diff) | |
| tree | ea37b1e5e0e4ed975055d74d4c8c5d1fa733efb4 | |
| parent | 7c060c6101484502458793b483a71845b6e9e2f5 (diff) | |
| download | org.eclipse.osee-c1bbd91635f303f556efc6d29c2fd94f2954b027.zip org.eclipse.osee-c1bbd91635f303f556efc6d29c2fd94f2954b027.tar.gz org.eclipse.osee-c1bbd91635f303f556efc6d29c2fd94f2954b027.tar.bz2 | |
bug: Fix deletion of attributes/relations across branches in ChangeArtifactType
2 files changed, 142 insertions, 148 deletions
diff --git a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java index 6ed7659..de5de03 100644 --- a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java +++ b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java @@ -12,36 +12,43 @@ package org.eclipse.osee.framework.skynet.core.artifact; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.logging.Level; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.osee.framework.core.data.IArtifactType; import org.eclipse.osee.framework.core.data.IAttributeType; +import org.eclipse.osee.framework.core.data.IOseeBranch; +import org.eclipse.osee.framework.core.data.IRelationType; import org.eclipse.osee.framework.core.enums.DeletionFlag; +import org.eclipse.osee.framework.core.enums.TxChange; import org.eclipse.osee.framework.core.exception.OseeArgumentException; import org.eclipse.osee.framework.core.exception.OseeCoreException; import org.eclipse.osee.framework.core.exception.OseeDataStoreException; +import org.eclipse.osee.framework.core.exception.OseeExceptions; import org.eclipse.osee.framework.core.model.type.ArtifactType; -import org.eclipse.osee.framework.database.core.ConnectionHandler; +import org.eclipse.osee.framework.database.IOseeDatabaseService; import org.eclipse.osee.framework.database.core.IOseeStatement; import org.eclipse.osee.framework.database.core.IdJoinQuery; import org.eclipse.osee.framework.database.core.JoinUtility; -import org.eclipse.osee.framework.jdk.core.type.MutableBoolean; -import org.eclipse.osee.framework.jdk.core.type.Pair; import org.eclipse.osee.framework.logging.OseeLog; +import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery; import org.eclipse.osee.framework.skynet.core.event.OseeEventManager; import org.eclipse.osee.framework.skynet.core.event.model.ArtifactEvent; import org.eclipse.osee.framework.skynet.core.event.model.EventBasicGuidArtifact; import org.eclipse.osee.framework.skynet.core.event.model.EventChangeTypeBasicGuidArtifact; import org.eclipse.osee.framework.skynet.core.internal.Activator; +import org.eclipse.osee.framework.skynet.core.internal.ServiceUtil; import org.eclipse.osee.framework.skynet.core.relation.RelationLink; import org.eclipse.osee.framework.skynet.core.relation.RelationManager; import org.eclipse.osee.framework.skynet.core.relation.RelationTypeManager; +import org.eclipse.osee.framework.skynet.core.transaction.SkynetTransaction; +import org.eclipse.osee.framework.skynet.core.transaction.TransactionManager; /** * Changes the descriptor type of an artifact to the provided descriptor. @@ -49,43 +56,105 @@ import org.eclipse.osee.framework.skynet.core.relation.RelationTypeManager; * @author Jeff C. Phillips */ public class ChangeArtifactType { - private static List<Attribute<?>> attributesToPurge; - private static List<RelationLink> relationsToDelete; - private static final IStatus promptStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, 256, "", null); - private static boolean userAnsweredYesToAll = false; + private final HashSet<IAttributeType> attributeTypes = new HashSet<IAttributeType>(); + private final HashSet<IRelationType> relationTypes = new HashSet<IRelationType>(); + private final HashMap<IOseeBranch, SkynetTransaction> txMap = new HashMap<IOseeBranch, SkynetTransaction>(); + private final Set<EventBasicGuidArtifact> artifactChanges = new HashSet<EventBasicGuidArtifact>(); + private final List<Artifact> modifiedArtifacts = new ArrayList<Artifact>(); + private static final IStatus promptStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, 257, "", null); + + public static void changeArtifactType(Collection<? extends Artifact> inputArtifacts, IArtifactType newArtifactTypeToken) throws OseeCoreException { + + ChangeArtifactType app = new ChangeArtifactType(); + if (inputArtifacts.isEmpty()) { + throw new OseeArgumentException("The artifact list can not be empty"); + } + + if (newArtifactTypeToken == null) { + throw new OseeArgumentException("The new artifact type can not be empty"); + } + + ArtifactType newArtifactType = ArtifactTypeManager.getType(newArtifactTypeToken); + + try { + app.internalChangeArtifactType(inputArtifacts, newArtifactType); + } catch (Exception ex) { + ArtifactQuery.reloadArtifacts(app.modifiedArtifacts); + OseeExceptions.wrapAndThrow(ex); + } + + } /** - * Changes the descriptor of the artifacts to the provided artifact descriptor + * the order of operations for this BLAM is important. Since the representations for the Attribute Type and the + * associated attributes and relations are both in memory and in the database, it is important complete both + * memory/database changes in such a manner that they stay in sync therefore, if any part of this blam fails, then + * the type should not be changed */ - public static void changeArtifactType(Collection<? extends Artifact> artifacts, IArtifactType artifactTypeToken) throws OseeCoreException { - if (artifacts.isEmpty()) { - throw new OseeArgumentException("The artifact list can not be empty"); + private void internalChangeArtifactType(Collection<? extends Artifact> inputArtifacts, ArtifactType newArtifactType) throws OseeDataStoreException, OseeCoreException { + + createAttributeRelationTransactions(inputArtifacts, newArtifactType); + boolean changeOk = doesUserAcceptArtifactChange(newArtifactType); + + if (!changeOk) { + ArtifactQuery.reloadArtifacts(modifiedArtifacts); + return; } - ArtifactType artifactType = ArtifactTypeManager.getType(artifactTypeToken); - List<Artifact> artifactsUserAccepted = new ArrayList<Artifact>(); - Set<EventBasicGuidArtifact> artifactChanges = new HashSet<EventBasicGuidArtifact>(); - for (Artifact artifact : artifacts) { - processAttributes(artifact, artifactType); - processRelations(artifact, artifactType); - artifactsUserAccepted.add(artifact); - if (userAnsweredYesToAll || doesUserAcceptArtifactChange(artifact, artifactType)) { - ArtifactType originalType = artifact.getArtifactType(); - boolean success = changeArtifactTypeThroughHistory(artifact, artifactType); - if (success) { - artifactChanges.add(new EventChangeTypeBasicGuidArtifact(artifact.getBranch().getGuid(), - originalType.getGuid(), artifactType.getGuid(), artifact.getGuid())); - } - } + for (SkynetTransaction transaction : txMap.values()) { + transaction.execute(); } - // Kick Local and Remote Events + changeArtifactTypeOutsideofHistory(inputArtifacts, newArtifactType); + + sendLocalAndRemoteEvents(modifiedArtifacts); + } + + private void sendLocalAndRemoteEvents(Collection<? extends Artifact> artifacts) throws OseeCoreException { ArtifactEvent artifactEvent = new ArtifactEvent(artifacts.iterator().next().getBranch()); for (EventBasicGuidArtifact guidArt : artifactChanges) { artifactEvent.getArtifacts().add(guidArt); } + OseeEventManager.kickPersistEvent(ChangeArtifactType.class, artifactEvent); + } + + private void createAttributeRelationTransactions(Collection<? extends Artifact> inputArtifacts, ArtifactType newArtifactType) throws OseeDataStoreException, OseeCoreException { + IdJoinQuery artifactJoin = populateJoinIdTable(inputArtifacts); + IOseeDatabaseService database = ServiceUtil.getOseeDatabaseService(); + IOseeStatement chStmt = database.getStatement(); + + try { + chStmt.runPreparedQuery( + "select art_id, branch_id from osee_join_id jid, osee_artifact art, osee_txs txs where jid.query_id = ? and jid.id = art.art_id and art.gamma_id = txs.gamma_id and txs.tx_current = ?", + artifactJoin.getQueryId(), TxChange.CURRENT.getValue()); + + while (chStmt.next()) { + int artId = chStmt.getInt("art_id"); + int branchId = chStmt.getInt("branch_id"); + IOseeBranch branch = BranchManager.getBranch(branchId); + Artifact artifact = ArtifactQuery.getArtifactFromId(artId, branch); + deleteInvalidAttributes(artifact, newArtifactType); + deleteInvalidRelations(artifact, newArtifactType); + addTransaction(artifact, txMap); + artifactChanges.add(new EventChangeTypeBasicGuidArtifact(artifact.getBranch().getGuid(), + newArtifactType.getGuid(), newArtifactType.getGuid(), artifact.getGuid())); + } + } finally { + chStmt.close(); + artifactJoin.delete(); + } + } + private void addTransaction(Artifact artifact, HashMap<IOseeBranch, SkynetTransaction> txMap) throws OseeCoreException { + IOseeBranch branch = artifact.getBranch(); + SkynetTransaction transaction = txMap.get(branch); + if (transaction == null) { + transaction = TransactionManager.createTransaction(branch, "Change Artifact Type"); + txMap.put(branch, transaction); + } + transaction.addArtifact(artifact); + modifiedArtifacts.add(artifact); } public static void handleRemoteChangeType(EventChangeTypeBasicGuidArtifact guidArt) { @@ -103,166 +172,91 @@ public class ChangeArtifactType { } } - public static void changeArtifactTypeReportOnly(StringBuffer results, Collection<Artifact> artifacts, IArtifactType artifactType) throws OseeCoreException { - if (artifacts.isEmpty()) { - throw new OseeArgumentException("The artifact list can not be empty"); - } - - for (Artifact artifact : artifacts) { - processAttributes(artifact, artifactType); - processRelations(artifact, artifactType); - - if (!relationsToDelete.isEmpty() || !attributesToPurge.isEmpty()) { - getConflictString(results, artifact, artifactType); - } - } - } - - private static void getConflictString(StringBuffer results, Artifact artifact, IArtifactType artifactType) { - results.append("There has been a conflict in changing artifact " + artifact.getGuid() + " - \"" + artifact.getName() + "\"" + - // - " to \"" + artifactType.getName() + "\" type. \n" + "The following data will need to be purged "); - for (RelationLink relationLink : relationsToDelete) { - results.append("([Relation][" + relationLink + "])"); - } - for (Attribute<?> attribute : attributesToPurge) { - results.append("([Attribute][" + attribute.getAttributeType().getName() + "][" + attribute.toString() + "])"); - } - results.append("\n\n"); + private void getConflictString(StringBuilder message, IArtifactType artifactType) { + message.append("The following types are not supported on the artifact type " + artifactType.getName() + ":\n"); + message.append("\n"); + message.append("Attribute Types:\n" + attributeTypes + "\n"); + message.append("\n"); + message.append("Relation Types:\n" + relationTypes + "\n"); } - /** - * Splits the attributes of the current artifact into two groups. The attributes that are compatible for the new type - * and the attributes that will need to be purged. - */ - private static void processAttributes(Artifact artifact, IArtifactType artifactType) throws OseeCoreException { - attributesToPurge = new LinkedList<Attribute<?>>(); + private void deleteInvalidAttributes(Artifact artifact, IArtifactType artifactType) throws OseeCoreException { for (IAttributeType attributeType : artifact.getAttributeTypes()) { ArtifactType aType = ArtifactTypeManager.getType(artifactType); if (!aType.isValidAttributeType(attributeType, artifact.getFullBranch())) { - attributesToPurge.addAll(artifact.getAttributes(attributeType)); + artifact.deleteAttributes(attributeType); + attributeTypes.add(attributeType); } } } - /** - * Splits the relationLinks of the current artifact into Two groups. The links that are compatible for the new type - * and the links that will need to be purged. - */ - private static void processRelations(Artifact artifact, IArtifactType artifactType) throws OseeCoreException { - relationsToDelete = new LinkedList<RelationLink>(); + private void deleteInvalidRelations(Artifact artifact, IArtifactType artifactType) throws OseeCoreException { for (RelationLink link : artifact.getRelationsAll(DeletionFlag.EXCLUDE_DELETED)) { if (RelationTypeManager.getRelationSideMax(link.getRelationType(), artifactType, link.getSide(artifact)) == 0) { - relationsToDelete.add(link); + link.delete(false); + relationTypes.add(link.getRelationType()); } } } /** - * @return true if the user accepts the purging of the attributes and relations that are not compatible for the new + * @return true if the user accepts the deletion of the attributes and relations that are not compatible for the new * artifact type else false. */ - private static boolean doesUserAcceptArtifactChange(final Artifact artifact, final ArtifactType artifactType) { - if ((!relationsToDelete.isEmpty() || !attributesToPurge.isEmpty()) && !userAnsweredYesToAll) { - - StringBuffer sb = new StringBuffer(50); - getConflictString(sb, artifact, artifactType); - try { - Object result = - DebugPlugin.getDefault().getStatusHandler(promptStatus).handleStatus(promptStatus, sb.toString()); + private boolean doesUserAcceptArtifactChange(IArtifactType artifactType) throws OseeCoreException { + if (!relationTypes.isEmpty() || !attributeTypes.isEmpty()) { - MutableBoolean answer = null; + StringBuilder sb = new StringBuilder(1024); + getConflictString(sb, artifactType); - if (result instanceof Pair<?, ?>) { - Pair<?, ?> value = (Pair<?, ?>) result; - answer = (MutableBoolean) value.getFirst(); - Integer kindOfAnswer = (Integer) value.getSecond(); - - userAnsweredYesToAll = kindOfAnswer == 1 && answer.getValue(); - } - return answer == null ? false : answer.getValue(); - } catch (Exception ex) { - OseeLog.log(Activator.class, Level.SEVERE, ex); + Object result; + try { + result = DebugPlugin.getDefault().getStatusHandler(promptStatus).handleStatus(promptStatus, sb.toString()); + } catch (CoreException ex) { + OseeExceptions.wrapAndThrow(ex); + // the following will never execute - above line always exceptions return false; } + + return (Boolean) result; + } else { return true; } } - /** - * Sets the artifact descriptor. - */ - private static boolean changeArtifactTypeThroughHistory(Artifact artifact, ArtifactType newArtifactType) throws OseeCoreException { - for (Attribute<?> attribute : attributesToPurge) { - attribute.purge(); - } - purgeAttributes(); + private void changeArtifactTypeOutsideofHistory(Collection<? extends Artifact> inputArtifacts, ArtifactType newArtifactType) throws OseeCoreException { + List<Object[]> insertData = new ArrayList<Object[]>(); + + String UPDATE = "UPDATE osee_artifact SET art_type_id = ? WHERE art_id = ?"; - for (RelationLink relation : relationsToDelete) { - relation.delete(true); + for (Artifact artifact : inputArtifacts) { + insertData.add(toUpdate(newArtifactType.getId(), artifact.getArtId())); } - ArtifactCache.deCache(artifact); - RelationManager.deCache(artifact); - ArtifactType originalType = artifact.getArtifactType(); - artifact.setArtifactType(newArtifactType); - try { - ConnectionHandler.runPreparedUpdate("UPDATE osee_artifact SET art_type_id = ? WHERE art_id = ?", - newArtifactType.getId(), artifact.getArtId()); - } catch (OseeDataStoreException ex) { - OseeLog.log(Activator.class, Level.SEVERE, ex); - artifact.setArtifactType(originalType); - return false; - } finally { + ServiceUtil.getOseeDatabaseService().runBatchUpdate(UPDATE, insertData); + + for (Artifact artifact : modifiedArtifacts) { + artifact.setArtifactType(newArtifactType); artifact.clearEditState(); } - return true; } - private static void purgeAttributes() throws OseeCoreException { - IdJoinQuery txsJoin = populateTxsJoinTable(); - - try { - String delete_txs = - "DELETE FROM osee_txs txs1 WHERE EXISTS (select 1 from osee_join_id jt1 WHERE jt1.query_id = ? AND jt1.id = txs1.gamma_id)"; - String delete_attr = - "DELETE FROM osee_attribute attr1 WHERE EXISTS (select 1 from osee_join_id jt1 WHERE jt1.query_id = ? AND jt1.id = attr1.gamma_id)"; - ConnectionHandler.runPreparedUpdate(delete_txs, txsJoin.getQueryId()); - ConnectionHandler.runPreparedUpdate(delete_attr, txsJoin.getQueryId()); - } finally { - txsJoin.delete(); - } + private Object[] toUpdate(int art_type_id, int art_id) { + return new Object[] {art_type_id, art_id}; } - private static IdJoinQuery populateTxsJoinTable() throws OseeDataStoreException, OseeCoreException { - IdJoinQuery attributeJoin = JoinUtility.createIdJoinQuery(); + private IdJoinQuery populateJoinIdTable(Collection<? extends Artifact> inputArtifacts) throws OseeDataStoreException, OseeCoreException { + IdJoinQuery artifactJoin = JoinUtility.createIdJoinQuery(); - for (Attribute<?> attribute : attributesToPurge) { - attributeJoin.add(attribute.getId()); + for (Artifact artifact : inputArtifacts) { + artifactJoin.add(artifact.getArtId()); } - IdJoinQuery txsJoin = JoinUtility.createIdJoinQuery(); - try { - attributeJoin.store(); - IOseeStatement chStmt = ConnectionHandler.getStatement(); - String selectAttrGammas = - "select gamma_id from osee_attribute t1, osee_join_id t2 where t1.attr_id = t2.id and t2.query_id = ?"; + artifactJoin.store(); - try { - chStmt.runPreparedQuery(10000, selectAttrGammas, attributeJoin.getQueryId()); - while (chStmt.next()) { - txsJoin.add(chStmt.getInt("gamma_id")); - } - txsJoin.store(); - } finally { - chStmt.close(); - } - } finally { - attributeJoin.delete(); - } - return txsJoin; + return artifactJoin; } } diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java index 997a000..44bae2c 100644 --- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java +++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java @@ -40,6 +40,6 @@ public class ChangeArtifactTypeBlam extends AbstractBlam { @Override public Collection<String> getCategories() { - return Arrays.asList("Admin"); + return Arrays.asList("Util"); } }
\ No newline at end of file |

