blob: 7756e5dcff483d425b3a4e59b57594c52fc02af2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 Boeing.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Boeing - initial API and implementation
*******************************************************************************/
package org.eclipse.osee.disposition.rest.internal.importer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.osee.disposition.model.Discrepancy;
import org.eclipse.osee.disposition.model.DispoAnnotationData;
import org.eclipse.osee.disposition.model.DispoItem;
import org.eclipse.osee.disposition.model.DispoItemData;
import org.eclipse.osee.disposition.model.DispoStrings;
import org.eclipse.osee.disposition.rest.internal.DispoConnector;
import org.eclipse.osee.disposition.rest.internal.report.OperationReport;
import org.eclipse.osee.disposition.rest.util.DispoUtil;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Angel Avila
*/
public class AnnotationCopier {
private final DispoConnector connector;
public AnnotationCopier(DispoConnector connector) {
this.connector = connector;
}
public List<DispoItem> copyEntireSet(List<DispoItemData> destinationItems, Collection<DispoItem> sourceItems, boolean isCopySet, OperationReport report) throws JSONException {
List<DispoItem> modifiedItems = new ArrayList<DispoItem>();
HashMap<String, DispoItemData> nameToDestItems = createNameToItemList(destinationItems);
for (DispoItem sourceItem : sourceItems) {
DispoItemData destItem = nameToDestItems.get(sourceItem.getName());
if (destItem != null) {
JSONArray annotationsList = destItem.getAnnotationsList();
/**
* If item is PASS don't bother copying over Annotations from Source Item, all annotations are Default
* Annotations and already created in the Import
*/
if (!destItem.getStatus().equals(DispoStrings.Item_Pass)) {
DispoItemData newItem = createNewItemWithCopiedAnnotations(destItem, sourceItem, isCopySet, report);
if (newItem != null) {
if (!Strings.isValid(destItem.getGuid())) {
newItem.setGuid(sourceItem.getGuid());
} else {
newItem.setGuid(destItem.getGuid());
}
modifiedItems.add(newItem);
report.addMessageForItem(destItem.getName(), "$$$$Had %s Dispositions$$$$\n",
annotationsList.length());
report.addMessageForItem(destItem.getName(), "$$$$Now has %s Dispositions$$$$",
newItem.getAnnotationsList().length());
}
} else if (!Strings.isValid(destItem.getGuid()) && !sourceItem.getStatus().equals(DispoStrings.Item_Pass)) {
destItem.setGuid(sourceItem.getGuid());
modifiedItems.add(destItem);
}
}
}
return modifiedItems;
}
private DispoItemData createNewItemWithCopiedAnnotations(DispoItemData destItem, DispoItem sourceItem, boolean isCopySet, OperationReport report) throws JSONException {
DispoItemData toReturn;
boolean isSameDiscrepancies = matchAllDiscrepancies(destItem, sourceItem);
if (isSameDiscrepancies) {
toReturn = buildNewItem(destItem, sourceItem, isCopySet, report);
} else {
toReturn = null;
report.addMessageForItem(destItem.getName(),
"Tried to copy from item id: [%s] but discrepancies were not the same", sourceItem.getGuid());
}
return toReturn;
}
private DispoItemData buildNewItem(DispoItemData destItem, DispoItem sourceItem, boolean isSkipDestDefaultAnnotations, OperationReport report) throws JSONException {
boolean isChangesMade = false;
DispoItemData newItem = new DispoItemData();
newItem.setDiscrepanciesList(destItem.getDiscrepanciesList());
JSONArray newList = new JSONArray(destItem.getAnnotationsList().toString());
newItem.setAnnotationsList(newList);
JSONArray newAnnotations = newItem.getAnnotationsList();
JSONArray sourceAnnotations = sourceItem.getAnnotationsList();
Set<String> destDefaultAnntationLocations = getDefaultAnnotations(newItem);
for (int i = 0; i < sourceAnnotations.length(); i++) {
JSONObject annotationJson = sourceAnnotations.getJSONObject(i);
DispoAnnotationData sourceAnnotation = DispoUtil.jsonObjToDispoAnnotationData(annotationJson);
String sourceLocation = sourceAnnotation.getLocationRefs();
if (DispoUtil.isDefaultAnntoation(sourceAnnotation)) {
/**
* This means the source has an annotation that's TEST_UNIT or Exception_Handling, so don't copy it over, we
* might leave an uncovered discrepancy which is intended and need to log
*/
if (!destDefaultAnntationLocations.contains(sourceLocation)) {
report.addMessageForItem(destItem.getName(),
"Did not copy annotations for location(s) [%s] because they are default annotations",
sourceAnnotation.getLocationRefs());
}
} else if (isSkipDestDefaultAnnotations && destDefaultAnntationLocations.contains(sourceLocation)) {
/**
* isSkipDestDefault is true when annotation copier is called by a copy set, this means we do not want to
* copy over source annotations that have the same location as a Dest annotation that's already covered by a
* Default Annotation This means the destination has an annotation that's TEST_UNIT or Exception_Handling,
* so don't copy over a manual Disposition
*/
report.addMessageForItem(
destItem.getName(),
"Did not copy annotations for location(s) [%s] because the destination item already has a default annotations at these locations",
sourceAnnotation.getLocationRefs());
} else if (newAnnotations.toString().contains(sourceAnnotation.getGuid())) {
report.addMessageForItem(
destItem.getName(),
"Did not copy annotations for location(s) [%s] because the destination item already has the same annotations at these locations [%s]",
sourceAnnotation.getLocationRefs());
} else {
DispoAnnotationData newAnnotation = sourceAnnotation;
if (destDefaultAnntationLocations.contains(sourceLocation)) {
/**
* The discrepancy of this manual disposition is now covered by a Default Annotation so this Manual
* Annotation is invalid, mark as such by making the location Ref negative, don't bother connecting the
* annotation
*/
// Make location ref negative to indicate this
String locationRefs = sourceAnnotation.getLocationRefs();
Integer locationRefAsInt = Integer.valueOf(locationRefs);
if (locationRefAsInt > 0) {
newAnnotation.setLocationRefs(String.valueOf(locationRefAsInt * -1));
}
report.addMessageForItem(destItem.getName(),
"The annotation was copied over but is no longer needed: [%s]", locationRefs);
}
connector.connectAnnotation(newAnnotation, newItem.getDiscrepanciesList());
isChangesMade = true;
// Both the source and destination are dispositionable so copy the annotation
int nextIndex = newAnnotations.length();
newAnnotation.setIndex(nextIndex);
newAnnotations.put(nextIndex, DispoUtil.annotationToJsonObj(newAnnotation));
}
}
if (isChangesMade) {
newItem.setAnnotationsList(newAnnotations);
String newStatus = connector.getItemStatus(newItem);
newItem.setStatus(newStatus);
} else {
newItem = null;
}
return newItem;
}
private Set<String> getDefaultAnnotations(DispoItemData item) throws JSONException {
Set<String> defaultAnnotationLocations = new HashSet<String>();
JSONArray annotations = item.getAnnotationsList();
if (annotations == null) {
annotations = new JSONArray();
}
for (int i = 0; i < annotations.length(); i++) {
JSONObject annotationJson = annotations.getJSONObject(i);
DispoAnnotationData annotation = DispoUtil.jsonObjToDispoAnnotationData(annotationJson);
if (DispoUtil.isDefaultAnntoation(annotation)) {
defaultAnnotationLocations.add(annotation.getLocationRefs());
}
}
return defaultAnnotationLocations;
}
private HashMap<String, DispoItemData> createNameToItemList(List<DispoItemData> destinationItems) {
HashMap<String, DispoItemData> nameToItem = new HashMap<String, DispoItemData>();
for (DispoItemData item : destinationItems) {
nameToItem.put(item.getName(), item);
}
return nameToItem;
}
private boolean matchAllDiscrepancies(DispoItemData destItem, DispoItem sourceItem) throws JSONException {
Map<Integer, String> destLocationToText = generateLocationToTextMap(destItem);
boolean toReturn = true;
JSONObject sourceDiscrepancies = sourceItem.getDiscrepanciesList();
@SuppressWarnings("unchecked")
Iterator<String> iterator = sourceDiscrepancies.keys();
while (iterator.hasNext()) {
String key = iterator.next();
JSONObject discrepancyAsJson = sourceDiscrepancies.getJSONObject(key);
Discrepancy sourceDiscrepancy = DispoUtil.jsonObjToDiscrepancy(discrepancyAsJson);
int sourceLocation = sourceDiscrepancy.getLocation();
String destDicrepancyText = destLocationToText.get(sourceLocation);
if (destDicrepancyText == null) {
// No Discrepancy with that location in the destination item, return false
toReturn = false;
break;
} else if (sourceDiscrepancy.getText().equals(destDicrepancyText)) {
continue;
} else {
toReturn = false;
break;
}
}
return toReturn;
}
private Map<Integer, String> generateLocationToTextMap(DispoItem item) throws JSONException {
Map<Integer, String> locationToText = new HashMap<Integer, String>();
JSONObject discrepancies = item.getDiscrepanciesList();
@SuppressWarnings("unchecked")
Iterator<String> iterator = discrepancies.keys();
while (iterator.hasNext()) {
String key = iterator.next();
JSONObject discrepancyAsJson = discrepancies.getJSONObject(key);
Discrepancy discrepancy = DispoUtil.jsonObjToDiscrepancy(discrepancyAsJson);
locationToText.put(discrepancy.getLocation(), discrepancy.getText());
}
return locationToText;
}
}