/*******************************************************************************
 * Copyright (c) 2000, 2013 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *     Technical University Berlin - extended API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IParent;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.objectteams.otdt.internal.core.SourceMethodMappingInfo;

/**
 * OTDT changes:
 * What: during lookup of infos for a given IJavaElement handle IOTJavaElements via their corresponding java element
 * Why:  couldn't detect, e.g., removal of callin mappings.
 * Note: two locations still abort handling of IOTJavaElements (CCE).
 *
 * A java element delta builder creates a java element delta on
 * a java element between the version of the java element
 * at the time the comparator was created and the current version
 * of the java element.
 *
 * It performs this operation by locally caching the contents of
 * the java element when it is created. When the method
 * createDeltas() is called, it creates a delta over the cached
 * contents and the new contents.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class JavaElementDeltaBuilder {
	/**
	 * The java element handle
	 */
	IJavaElement javaElement;

	/**
	 * The maximum depth in the java element children we should look into
	 */
	int maxDepth = Integer.MAX_VALUE;

	/**
	 * The old handle to info relationships
	 */
	Map infos;
	Map annotationInfos;

	/**
	 * The old position info
	 */
	Map oldPositions;

	/**
	 * The new position info
	 */
	Map newPositions;

	/**
	 * Change delta
	 */
	public JavaElementDelta delta = null;

	/**
	 * List of added elements
	 */
	HashSet added;

	/**
	 * List of removed elements
	 */
	HashSet removed;

	/**
	 * Doubly linked list item
	 */
	static class ListItem {
		public IJavaElement previous;
		public IJavaElement next;

		public ListItem(IJavaElement previous, IJavaElement next) {
			this.previous = previous;
			this.next = next;
		}
	}
/**
 * Creates a java element comparator on a java element
 * looking as deep as necessary.
 */
public JavaElementDeltaBuilder(IJavaElement javaElement) {
	this.javaElement = javaElement;
	initialize();
	recordElementInfo(
		javaElement,
		(JavaModel)this.javaElement.getJavaModel(),
		0);
}
/**
 * Creates a java element comparator on a java element
 * looking only 'maxDepth' levels deep.
 */
public JavaElementDeltaBuilder(IJavaElement javaElement, int maxDepth) {
	this.javaElement = javaElement;
	this.maxDepth = maxDepth;
	initialize();
	recordElementInfo(
		javaElement,
		(JavaModel)this.javaElement.getJavaModel(),
		0);
}
/**
 * Repairs the positioning information
 * after an element has been added
 */
private void added(IJavaElement element) {
	this.added.add(element);
	ListItem current = getNewPosition(element);
	ListItem previous = null, next = null;
	if (current.previous != null)
		previous = getNewPosition(current.previous);
	if (current.next != null)
		next = getNewPosition(current.next);
	if (previous != null)
		previous.next = current.next;
	if (next != null)
		next.previous = current.previous;
}
/**
 * Builds the java element deltas between the old content of the compilation
 * unit and its new content.
 */
public void buildDeltas() {
	this.delta = new JavaElementDelta(this.javaElement);
	// if building a delta on a compilation unit or below,
	// it's a fine grained delta
	if (this.javaElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
		this.delta.fineGrained();
	}
	recordNewPositions(this.javaElement, 0);
	findAdditions(this.javaElement, 0);
	findDeletions();
	findChangesInPositioning(this.javaElement, 0);
	trimDelta(this.delta);
	if (this.delta.getAffectedChildren().length == 0) {
		// this is a fine grained but not children affected -> mark as content changed
		this.delta.contentChanged();
	}
}
private boolean equals(char[][][] first, char[][][] second) {
	if (first == second)
		return true;
	if (first == null || second == null)
		return false;
	if (first.length != second.length)
		return false;

	for (int i = first.length; --i >= 0;)
		if (!CharOperation.equals(first[i], second[i]))
			return false;
	return true;
}
/**
 * Finds elements which have been added or changed.
 */
private void findAdditions(IJavaElement newElement, int depth) {
	JavaElementInfo oldInfo = getElementInfo(newElement);
	if (oldInfo == null && depth < this.maxDepth) {
		this.delta.added(newElement);
		added(newElement);
	} else {
		removeElementInfo(newElement);
	}

	if (depth >= this.maxDepth) {
		// mark element as changed
		this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
		return;
	}

	JavaElementInfo newInfo = null;
	try {
		newInfo = (JavaElementInfo)((JavaElement)newElement).getElementInfo();
	} catch (JavaModelException npe) {
		return;
	}

	findContentChange(oldInfo, newInfo, newElement);

	if (oldInfo != null && newElement instanceof IParent) {
		IJavaElement[] children = newInfo.getChildren();
		if (children != null) {
			int length = children.length;
			for(int i = 0; i < length; i++) {
				findAdditions(children[i], depth + 1);
			}
		}
	}
}

/**
 * Looks for changed positioning of elements.
 */
private void findChangesInPositioning(IJavaElement element, int depth) {
	if (depth >= this.maxDepth || this.added.contains(element) || this.removed.contains(element))
		return;

	if (!isPositionedCorrectly(element)) {
		this.delta.changed(element, IJavaElementDelta.F_REORDER);
	}

	if (element instanceof IParent) {
		JavaElementInfo info = null;
		try {
			info = (JavaElementInfo)((JavaElement)element).getElementInfo();
		} catch (JavaModelException npe) {
			return;
		}
		IJavaElement[] children = info.getChildren();
		if (children != null) {
			int length = children.length;
			for(int i = 0; i < length; i++) {
				findChangesInPositioning(children[i], depth + 1);
			}
		}
	}
}
private void findAnnotationChanges(IAnnotation[] oldAnnotations, IAnnotation[] newAnnotations, IJavaElement parent) {
	ArrayList annotationDeltas = null;
	for (int i = 0, length = newAnnotations.length; i < length; i++) {
		IAnnotation newAnnotation = newAnnotations[i];
		Object oldInfo = this.annotationInfos.remove(newAnnotation);
		if (oldInfo == null) {
			JavaElementDelta annotationDelta = new JavaElementDelta(newAnnotation);
			annotationDelta.added();
			if (annotationDeltas == null) annotationDeltas = new ArrayList();
			annotationDeltas.add(annotationDelta);
			continue;
		} else {
			AnnotationInfo newInfo = null;
			try {
				newInfo = (AnnotationInfo) ((JavaElement) newAnnotation).getElementInfo();
			} catch (JavaModelException npe) {
				return;
			}
			if (!Util.equalArraysOrNull(((AnnotationInfo) oldInfo).members, newInfo.members)) {
				JavaElementDelta annotationDelta = new JavaElementDelta(newAnnotation);
				annotationDelta.changed(IJavaElementDelta.F_CONTENT);
				if (annotationDeltas == null) annotationDeltas = new ArrayList();
				annotationDeltas.add(annotationDelta);
			}
		}
	}
	for (int i = 0, length = oldAnnotations.length; i < length; i++) {
		IAnnotation oldAnnotation = oldAnnotations[i];
		if (this.annotationInfos.remove(oldAnnotation) != null) {
			JavaElementDelta annotationDelta = new JavaElementDelta(oldAnnotation);
			annotationDelta.removed();
			if (annotationDeltas == null) annotationDeltas = new ArrayList();
			annotationDeltas.add(annotationDelta);		}
	}
	if (annotationDeltas == null)
		return;
	int size = annotationDeltas.size();
	if (size > 0) {
		JavaElementDelta parentDelta = this.delta.changed(parent, IJavaElementDelta.F_ANNOTATIONS);
		parentDelta.annotationDeltas = (IJavaElementDelta[]) annotationDeltas.toArray(new IJavaElementDelta[size]);
	}
}
/**
 * The elements are equivalent, but might have content changes.
 */
private void findContentChange(JavaElementInfo oldInfo, JavaElementInfo newInfo, IJavaElement newElement) {
	if (oldInfo instanceof MemberElementInfo && newInfo instanceof MemberElementInfo) {
		if (((MemberElementInfo)oldInfo).getModifiers() != ((MemberElementInfo)newInfo).getModifiers()) {
			this.delta.changed(newElement, IJavaElementDelta.F_MODIFIERS);
		}
		if (oldInfo instanceof AnnotatableInfo && newInfo instanceof AnnotatableInfo) {
			findAnnotationChanges(((AnnotatableInfo) oldInfo).annotations, ((AnnotatableInfo) newInfo).annotations, newElement);
		}
		if (oldInfo instanceof SourceMethodElementInfo && newInfo instanceof SourceMethodElementInfo) {
			SourceMethodElementInfo oldSourceMethodInfo = (SourceMethodElementInfo)oldInfo;
			SourceMethodElementInfo newSourceMethodInfo = (SourceMethodElementInfo)newInfo;
			if (!CharOperation.equals(oldSourceMethodInfo.getReturnTypeName(), newSourceMethodInfo.getReturnTypeName())
					|| !CharOperation.equals(oldSourceMethodInfo.getTypeParameterNames(), newSourceMethodInfo.getTypeParameterNames())
					|| !equals(oldSourceMethodInfo.getTypeParameterBounds(), newSourceMethodInfo.getTypeParameterBounds())) {
				this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
			}
		} else if (oldInfo instanceof SourceFieldElementInfo && newInfo instanceof SourceFieldElementInfo) {
			if (!CharOperation.equals(
					((SourceFieldElementInfo)oldInfo).getTypeName(),
					((SourceFieldElementInfo)newInfo).getTypeName())) {
				this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
			}
//{ObjectTeams: compare SourceMethodMappingInfo:
		} else if (oldInfo instanceof SourceMethodMappingInfo && newInfo instanceof SourceMethodMappingInfo) {
			SourceMethodMappingInfo oldMappingInfo = (SourceMethodMappingInfo) oldInfo;
			SourceMethodMappingInfo newMappingInfo = (SourceMethodMappingInfo) newInfo;
			if (!oldMappingInfo.modifiersEqual(newMappingInfo))
				this.delta.changed(newElement, IJavaElementDelta.F_MODIFIERS);
			char[] oldName = oldMappingInfo.getCallinName();
			char[] newName = newMappingInfo.getCallinName();
			if (   oldMappingInfo.isCallin()
				&& !(oldName[0] == '<' && newName[0] == '<') // if both are generated don't bother to compare 
				&& !CharOperation.equals(oldName, newName))
				this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
			if (!oldMappingInfo.signaturesEqual(newMappingInfo))
				this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
// SH}
		} else if (oldInfo instanceof SourceTypeElementInfo && newInfo instanceof SourceTypeElementInfo) {
			SourceTypeElementInfo oldSourceTypeInfo = (SourceTypeElementInfo)oldInfo;
			SourceTypeElementInfo newSourceTypeInfo = (SourceTypeElementInfo)newInfo;
			if (!CharOperation.equals(oldSourceTypeInfo.getSuperclassName(), newSourceTypeInfo.getSuperclassName())
					|| !CharOperation.equals(oldSourceTypeInfo.getInterfaceNames(), newSourceTypeInfo.getInterfaceNames())) {
				this.delta.changed(newElement, IJavaElementDelta.F_SUPER_TYPES);
			}
//{ObjectTeams: handle baseclass in analogy to superclass:
			if (!CharOperation.equals(oldSourceTypeInfo.getBaseclassName(), newSourceTypeInfo.getBaseclassName())) {
				this.delta.changed(newElement, IJavaElementDelta.F_SUPER_TYPES);
			}
// SH}
			if (!CharOperation.equals(oldSourceTypeInfo.getTypeParameterNames(), newSourceTypeInfo.getTypeParameterNames())
					|| !equals(oldSourceTypeInfo.getTypeParameterBounds(), newSourceTypeInfo.getTypeParameterBounds())) {
				this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
			}
			HashMap oldTypeCategories = oldSourceTypeInfo.categories;
			HashMap newTypeCategories = newSourceTypeInfo.categories;
			if (oldTypeCategories != null) {
				// take the union of old and new categories elements (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=125675)
				Set elements;
				if (newTypeCategories != null) {
					elements = new HashSet(oldTypeCategories.keySet());
					elements.addAll(newTypeCategories.keySet());
				} else
					elements = oldTypeCategories.keySet();
				Iterator iterator = elements.iterator();
				while (iterator.hasNext()) {
					IJavaElement element = (IJavaElement) iterator.next();
					String[] oldCategories = (String[]) oldTypeCategories.get(element);
					String[] newCategories = newTypeCategories == null ? null : (String[]) newTypeCategories.get(element);
					if (!Util.equalArraysOrNull(oldCategories, newCategories)) {
						this.delta.changed(element, IJavaElementDelta.F_CATEGORIES);
					}
				}
			} else if (newTypeCategories != null) {
				Iterator elements = newTypeCategories.keySet().iterator();
				while (elements.hasNext()) {
					IJavaElement element = (IJavaElement) elements.next();
					this.delta.changed(element, IJavaElementDelta.F_CATEGORIES); // all categories for this element were removed
				}
			}
		}
	}
}
/**
 * Adds removed deltas for any handles left in the table
 */
private void findDeletions() {
	Iterator iter = this.infos.keySet().iterator();
	while(iter.hasNext()) {
		IJavaElement element = (IJavaElement)iter.next();
		this.delta.removed(element);
		removed(element);
	}
}
private JavaElementInfo getElementInfo(IJavaElement element) {
	return (JavaElementInfo)this.infos.get(element);
}
private ListItem getNewPosition(IJavaElement element) {
	return (ListItem)this.newPositions.get(element);
}
private ListItem getOldPosition(IJavaElement element) {
	return (ListItem)this.oldPositions.get(element);
}
private void initialize() {
	this.infos = new HashMap(20);
	this.oldPositions = new HashMap(20);
	this.newPositions = new HashMap(20);
	this.oldPositions.put(this.javaElement, new ListItem(null, null));
	this.newPositions.put(this.javaElement, new ListItem(null, null));
	this.added = new HashSet(5);
	this.removed = new HashSet(5);
}
/**
 * Inserts position information for the elements into the new or old positions table
 */
private void insertPositions(IJavaElement[] elements, boolean isNew) {
	int length = elements.length;
	IJavaElement previous = null, current = null, next = (length > 0) ? elements[0] : null;
	for(int i = 0; i < length; i++) {
		previous = current;
		current = next;
		next = (i + 1 < length) ? elements[i + 1] : null;
		if (isNew) {
			this.newPositions.put(current, new ListItem(previous, next));
		} else {
			this.oldPositions.put(current, new ListItem(previous, next));
		}
	}
}
/**
 * Returns whether the elements position has not changed.
 */
private boolean isPositionedCorrectly(IJavaElement element) {
	ListItem oldListItem = getOldPosition(element);
	if (oldListItem == null) return false;

	ListItem newListItem = getNewPosition(element);
	if (newListItem == null) return false;

	IJavaElement oldPrevious = oldListItem.previous;
	IJavaElement newPrevious = newListItem.previous;
	if (oldPrevious == null) {
		return newPrevious == null;
	} else {
		return oldPrevious.equals(newPrevious);
	}
}
/**
 * Records this elements info, and attempts
 * to record the info for the children.
 */
private void recordElementInfo(IJavaElement element, JavaModel model, int depth) {
	if (depth >= this.maxDepth) {
		return;
	}
	JavaElementInfo info = (JavaElementInfo)JavaModelManager.getJavaModelManager().getInfo(element);
	if (info == null) // no longer in the java model.
		return;
	this.infos.put(element, info);

	if (element instanceof IParent) {
		IJavaElement[] children = info.getChildren();
		if (children != null) {
			insertPositions(children, false);
			for(int i = 0, length = children.length; i < length; i++)
				recordElementInfo(children[i], model, depth + 1);
		}
	}
	IAnnotation[] annotations = null;
	if (info instanceof AnnotatableInfo)
		annotations = ((AnnotatableInfo) info).annotations;
	if (annotations != null) {
		if (this.annotationInfos == null)
			this.annotationInfos = new HashMap();
		JavaModelManager manager = JavaModelManager.getJavaModelManager();
		for (int i = 0, length = annotations.length; i < length; i++) {
			this.annotationInfos.put(annotations[i], manager.getInfo(annotations[i]));
		}
	}
}
/**
 * Fills the newPositions hashtable with the new position information
 */
private void recordNewPositions(IJavaElement newElement, int depth) {
	if (depth < this.maxDepth && newElement instanceof IParent) {
		JavaElementInfo info = null;
		try {
			info = (JavaElementInfo)((JavaElement)newElement).getElementInfo();
		} catch (JavaModelException npe) {
			return;
		}

		IJavaElement[] children = info.getChildren();
		if (children != null) {
			insertPositions(children, true);
			for(int i = 0, length = children.length; i < length; i++) {
				recordNewPositions(children[i], depth + 1);
			}
		}
	}
}
/**
 * Repairs the positioning information
 * after an element has been removed
 */
private void removed(IJavaElement element) {
	this.removed.add(element);
	ListItem current = getOldPosition(element);
	ListItem previous = null, next = null;
	if (current.previous != null)
		previous = getOldPosition(current.previous);
	if (current.next != null)
		next = getOldPosition(current.next);
	if (previous != null)
		previous.next = current.next;
	if (next != null)
		next.previous = current.previous;

}
private void removeElementInfo(IJavaElement element) {
	this.infos.remove(element);
}
public String toString() {
	StringBuffer buffer = new StringBuffer();
	buffer.append("Built delta:\n"); //$NON-NLS-1$
	buffer.append(this.delta == null ? "<null>" : this.delta.toString()); //$NON-NLS-1$
	return buffer.toString();
}
/**
 * Trims deletion deltas to only report the highest level of deletion
 */
private void trimDelta(JavaElementDelta elementDelta) {
	if (elementDelta.getKind() == IJavaElementDelta.REMOVED) {
		IJavaElementDelta[] children = elementDelta.getAffectedChildren();
		for(int i = 0, length = children.length; i < length; i++) {
			elementDelta.removeAffectedChild((JavaElementDelta)children[i]);
		}
	} else {
		IJavaElementDelta[] children = elementDelta.getAffectedChildren();
		for(int i = 0, length = children.length; i < length; i++) {
			trimDelta((JavaElementDelta)children[i]);
		}
	}
}
}
