EMMA Coverage Report (generated Thu Nov 26 15:54:18 CST 2009)
[all classes][org.eclipse.pde.api.tools.internal.comparator]

COVERAGE SUMMARY FOR SOURCE FILE [ClassFileComparator.java]

nameclass, %method, %block, %line, %
ClassFileComparator.java100% (1/1)89%  (33/37)94%  (7119/7561)95%  (2297.7/2431)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ClassFileComparator100% (1/1)89%  (33/37)94%  (7119/7561)95%  (2297.7/2431)
getStatus (): IStatus 0%   (0/1)0%   (0/3)0%   (0/1)
reportStatus (CoreException): void 0%   (0/1)0%   (0/5)0%   (0/2)
reportStatus (IStatus): void 0%   (0/1)0%   (0/28)0%   (0/5)
setDebug (boolean): void 0%   (0/1)0%   (0/9)0%   (0/2)
getType (String, IApiComponent, IApiBaseline): IApiTypeRoot 100% (1/1)18%  (18/100)38%  (6/16)
isCheckedException (IApiBaseline, IApiComponent, String): boolean 100% (1/1)65%  (55/85)75%  (21/28)
isStatusOk (): boolean 100% (1/1)71%  (5/7)71%  (0.7/1)
checkSuperInterfaces (): void 100% (1/1)76%  (289/378)76%  (92.9/123)
getDataFor (IApiMember, IApiType): String 100% (1/1)85%  (47/55)82%  (9/11)
checkTypeMembers (): void 100% (1/1)87%  (452/517)81%  (118.8/147)
collectAllInterfaces (IApiType, Set): void 100% (1/1)94%  (65/69)90%  (18/20)
getSuperclassList (IApiType, boolean, boolean): List 100% (1/1)95%  (70/74)90%  (19/21)
reportFieldAddition (IApiField, IApiType): void 100% (1/1)96%  (96/100)95%  (35/37)
getDeltaForMethod (IApiMethod): void 100% (1/1)96%  (1921/1993)97%  (612.6/634)
reportMethodAddition (IApiMethod, IApiType): void 100% (1/1)97%  (449/462)96%  (141.6/148)
checkSuperclass (): void 100% (1/1)99%  (168/170)97%  (59/61)
getDelta (IProgressMonitor): IDelta 100% (1/1)99%  (1225/1238)99%  (435.9/441)
getDeltaForField (IApiField): void 100% (1/1)99%  (1106/1115)99%  (402/407)
<static initializer> 100% (1/1)100% (3/3)100% (2/2)
ClassFileComparator (IApiType, IApiTypeRoot, IApiComponent, IApiComponent, IA... 100% (1/1)100% (49/49)100% (17/17)
ClassFileComparator (IApiTypeRoot, IApiTypeRoot, IApiComponent, IApiComponent... 100% (1/1)100% (50/50)100% (17/17)
addDelta (IDelta): void 100% (1/1)100% (5/5)100% (2/2)
addDelta (int, int, int, int, int, int, IApiType, String, String []): void 100% (1/1)100% (19/19)100% (2/2)
addDelta (int, int, int, int, int, int, IApiType, String, String): void 100% (1/1)100% (19/19)100% (2/2)
checkGenericSignature (String, String, IApiMember, IApiMember): void 100% (1/1)100% (797/797)100% (235/235)
createDelta (): Delta 100% (1/1)100% (4/4)100% (1/1)
getElementType (IApiMember): int 100% (1/1)100% (15/15)100% (4/4)
getElementType (IApiMethod): int 100% (1/1)100% (7/7)100% (3/3)
getElementType (IApiType): int 100% (1/1)100% (17/17)100% (7/7)
getInterfacesSet (IApiType): Set 100% (1/1)100% (18/18)100% (6/6)
getKeyForMethod (IApiMethod, IApiType): String 100% (1/1)100% (67/67)100% (14/14)
getMethodDisplayName (IApiMethod, IApiType): String 100% (1/1)100% (32/32)100% (10/10)
getSignatureDescriptor (String): SignatureDescriptor 100% (1/1)100% (17/17)100% (4/4)
getSuperclassList (IApiType): List 100% (1/1)100% (5/5)100% (1/1)
getSuperclassList (IApiType, boolean): List 100% (1/1)100% (6/6)100% (1/1)
getTargetType (IApiMethod): int 100% (1/1)100% (7/7)100% (3/3)
isAPI (int, IApiType): boolean 100% (1/1)100% (16/16)100% (3/3)

1/*******************************************************************************
2 * Copyright (c) 2008, 2009 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *     IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.pde.api.tools.internal.comparator;
12 
13import java.util.ArrayList;
14import java.util.HashSet;
15import java.util.Iterator;
16import java.util.List;
17import java.util.Set;
18 
19import org.eclipse.core.runtime.CoreException;
20import org.eclipse.core.runtime.IProgressMonitor;
21import org.eclipse.core.runtime.IStatus;
22import org.eclipse.core.runtime.MultiStatus;
23import org.eclipse.core.runtime.Status;
24import org.eclipse.core.runtime.SubMonitor;
25import org.eclipse.jdt.core.Flags;
26import org.eclipse.jdt.core.Signature;
27import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
28import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
29import org.eclipse.pde.api.tools.internal.provisional.IApiDescription;
30import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers;
31import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
32import org.eclipse.pde.api.tools.internal.provisional.comparator.ApiComparator;
33import org.eclipse.pde.api.tools.internal.provisional.comparator.IDelta;
34import org.eclipse.pde.api.tools.internal.provisional.descriptors.IMethodDescriptor;
35import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
36import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
37import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement;
38import org.eclipse.pde.api.tools.internal.provisional.model.IApiField;
39import org.eclipse.pde.api.tools.internal.provisional.model.IApiMember;
40import org.eclipse.pde.api.tools.internal.provisional.model.IApiMethod;
41import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
42import org.eclipse.pde.api.tools.internal.provisional.model.IApiTypeRoot;
43import org.eclipse.pde.api.tools.internal.util.Signatures;
44import org.eclipse.pde.api.tools.internal.util.Util;
45import org.objectweb.asm.signature.SignatureReader;
46 
47import com.ibm.icu.text.MessageFormat;
48 
49/**
50 * Compares class files from the workspace to those in the default {@link IApiProfile}
51 * 
52 * @since 1.0.0
53 */
54public class ClassFileComparator {
55        
56        /**
57         * Constant used for controlling tracing in the class file comparator
58         */
59        private static boolean Debug = Util.DEBUG;
60        
61        /**
62         * Method used for initializing tracing in the class file comparator
63         */
64        public static void setDebug(boolean debugValue) {
65                Debug = debugValue || Util.DEBUG;
66        }
67 
68        private boolean isCheckedException(IApiBaseline profile, IApiComponent apiComponent, String exceptionName) {
69                if (profile == null) {
70                        return true;
71                }
72                try {
73                        if (Util.isJavaLangRuntimeException(exceptionName)) {
74                                return false;
75                        }
76                        String packageName = Signatures.getPackageName(exceptionName);
77                        IApiTypeRoot result = Util.getClassFile(
78                                        profile.resolvePackage(apiComponent, packageName),
79                                        exceptionName);
80                        if (result != null) {
81                                // TODO should this be reported as a checked exception
82                                IApiType exception = result.getStructure();
83                                if(exception == null) {
84                                        return false;
85                                }
86                                while (!Util.isJavaLangObject(exception.getName())) {
87                                        String superName = exception.getSuperclassName();
88                                        packageName = Signatures.getPackageName(superName);
89                                        result = Util.getClassFile(
90                                                        profile.resolvePackage(apiComponent, packageName),
91                                                        superName);
92                                        if (result == null) {
93                                                // TODO should we report this failure ?
94                                                if (Debug) {
95                                                        System.err.println("CHECKED EXCEPTION LOOKUP: Could not find " + superName + " in profile " + profile.getName() + " from component " + apiComponent.getId()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
96                                                }
97                                                break;
98                                        }
99                                        exception = result.getStructure();
100                                        if (Util.isJavaLangRuntimeException(exception.getName())) {
101                                                return false;
102                                        }
103                                }
104                        }
105                } catch (CoreException e) {
106                        // by default exception are considered as checked exception 
107                        reportStatus(e);
108                }
109                return true;
110        }
111 
112        private IApiBaseline apiBaseline1 = null;
113        private IApiBaseline apiBaseline2 = null;
114        
115        private IApiComponent component = null;
116        private IApiComponent component2 = null;
117 
118        private Delta delta = null;
119        private IApiType type1 = null;
120 
121        private IApiType type2 = null;
122        
123        private int visibilityModifiers;
124        private int currentDescriptorRestrictions;
125        private int initialDescriptorRestrictions;
126        private MultiStatus status = null;
127 
128        /**
129         * Constructor
130         * @param classFile the class file from the workspace to compare
131         * @param classFile2 the class file from the baseline to compare to
132         * @param component the API component from the workspace
133         * @param component2 the API component from the baseline
134         * @param apiState the workspace API profile
135         * @param apiState2 the baseline API profile
136         * @param visibilityModifiers any modifiers from the class file
137         * @throws CoreException if the contents of the specified class files cannot be acquired
138         */
139        public ClassFileComparator(IApiTypeRoot classFile, IApiTypeRoot classFile2, IApiComponent component, IApiComponent component2, IApiBaseline apiState, IApiBaseline apiState2, int visibilityModifiers) throws CoreException {
140                this.component = component;
141                this.component2 = component2;
142                this.type1 = classFile.getStructure();
143                this.type2 = classFile2.getStructure();
144                this.apiBaseline1 = apiState;
145                this.apiBaseline2 = apiState2;
146                this.visibilityModifiers = visibilityModifiers;
147        }
148 
149        /**
150         * Constructor
151         * @param type the {@link IApiType} from the workspace to compare
152         * @param classFile2 the class file from the baseline to compare to
153         * @param component the API component from the workspace
154         * @param component2 the API component from the baseline
155         * @param apiState the workspace API profile
156         * @param apiState2 the baseline API profile
157         * @param visibilityModifiers any modifiers from the class file
158         * @throws CoreException if the contents of the specified class file cannot be acquired
159         */
160        public ClassFileComparator(IApiType type, IApiTypeRoot classFile2, IApiComponent component, IApiComponent component2, IApiBaseline apiState, IApiBaseline apiState2, int visibilityModifiers) throws CoreException {
161                this.component = component;
162                this.component2 = component2;
163                this.type1 = type;
164                this.type2 = classFile2.getStructure();
165                this.apiBaseline1 = apiState;
166                this.apiBaseline2 = apiState2;
167                this.visibilityModifiers = visibilityModifiers;
168        }
169        private void addDelta(IDelta delta) {
170                this.delta.add(delta);
171        }
172        private void addDelta(int elementType, int kind, int flags, int restrictions, int oldModifiers, int newModifiers, IApiType type, String key, String data) {
173                this.addDelta(new Delta(Util.getDeltaComponentVersionsId(this.component2), elementType, kind, flags, restrictions, oldModifiers, newModifiers, type.getName(), key, data));
174        }
175        private void addDelta(int elementType, int kind, int flags, int restrictions, int oldModifiers, int newModifiers, IApiType type, String key, String[] datas) {
176                this.addDelta(new Delta(Util.getDeltaComponentVersionsId(this.component2), elementType, kind, flags, restrictions, oldModifiers, newModifiers, type.getName(), key, datas));
177        }
178        /**
179         * Checks if the super-class set has been change in any way compared to the baseline (grown or reduced or types changed)
180         */
181        private void checkSuperclass() throws CoreException {
182                // check superclass set
183                List superclassList1 = getSuperclassList(this.type1);
184                if(!isStatusOk()) {
185                        return;
186                }
187                Set superclassNames2 = null;
188                List superclassList2 = getSuperclassList(this.type2);
189                if(!isStatusOk()) {
190                        return;
191                }
192                if (superclassList2 != null) {
193                        superclassNames2 = new HashSet();
194                        Iterator iterator = superclassList2.iterator();
195                        while (iterator.hasNext()) {
196                                superclassNames2.add(((IApiType) iterator.next()).getName());
197                        }
198                }
199                if (superclassList1 == null) {
200                        if (superclassList2 != null) {
201                                // this means the direct super class of descriptor1 is java.lang.Object
202                                this.addDelta(
203                                                getElementType(this.type1),
204                                                IDelta.ADDED,
205                                                IDelta.SUPERCLASS,
206                                                this.currentDescriptorRestrictions,
207                                                this.type1.getModifiers(),
208                                                this.type2.getModifiers(),
209                                                this.type1,
210                                                this.type1.getName(),
211                                                Util.getDescriptorName(type1));
212                        }
213                } else if (superclassList2 == null) {
214                        // this means the direct super class of descriptor2 is java.lang.Object
215                        this.addDelta(
216                                        getElementType(this.type1),
217                                        IDelta.REMOVED,
218                                        IDelta.SUPERCLASS,
219                                        this.currentDescriptorRestrictions,
220                                        this.type1.getModifiers(),
221                                        this.type2.getModifiers(),
222                                        this.type1,
223                                        this.type1.getName(),
224                                        Util.getDescriptorName(type1));
225                }
226                // get superclass of descriptor2
227                if (superclassList1 != null && superclassList2 != null) {
228                        IApiType superclassType2 = (IApiType) superclassList2.get(0);
229                        IApiType superclassType = (IApiType) superclassList1.get(0);
230                        if (!superclassType.getName().equals(superclassType2.getName())) {
231                                if (!superclassNames2.contains(superclassType.getName())) {
232                                        this.addDelta(
233                                                        getElementType(this.type1),
234                                                        IDelta.REMOVED,
235                                                        IDelta.SUPERCLASS,
236                                                        this.currentDescriptorRestrictions,
237                                                        this.type1.getModifiers(),
238                                                        this.type2.getModifiers(),
239                                                        this.type1,
240                                                        this.type1.getName(),
241                                                        Util.getDescriptorName(type1));
242                                } else {
243                                        this.addDelta(
244                                                        getElementType(this.type1),
245                                                        IDelta.ADDED,
246                                                        IDelta.SUPERCLASS,
247                                                        this.currentDescriptorRestrictions,
248                                                        this.type1.getModifiers(),
249                                                        this.type2.getModifiers(),
250                                                        this.type1,
251                                                        this.type1.getName(),
252                                                        Util.getDescriptorName(type1));
253                                }
254                        }
255                }
256        }
257        /**
258         * reports problem status to the comparators' complete status
259         * @param newstatus
260         */
261        protected void reportStatus(IStatus newstatus) {
262                if(this.status == null) {
263                        String msg = MessageFormat.format(ComparatorMessages.ClassFileComparator_0, new String[] {this.type1.getName()});
264                        this.status = new MultiStatus(ApiPlugin.PLUGIN_ID, IStatus.ERROR, msg, null);
265                }
266                this.status.add(newstatus);
267        }
268        
269        /**
270         * Report problem to the comparators' status
271         * @param e
272         */
273        private void reportStatus(CoreException e) {
274                reportStatus(e.getStatus());
275        }
276        
277        /**
278         * @return if the status of the compare is ok
279         */
280        private boolean isStatusOk() {
281                return this.status == null;
282        }
283        
284        /**
285         * @return the status of the compare and delta creation
286         */
287        public IStatus getStatus() {
288                return this.status;
289        }
290        /**
291         * Checks if there are any changes to the super-interface set for the current type descriptor context.
292         * A change is one of:
293         * <ul>
294         * <li>An interface has been added to the current super-interface set compared to the current baseline</li>
295         * <li>An interface has been removed from the current super-interface set compared to the current baseline</li>
296         * <li>An interface has changed (same number of interfaces, but different types) compared to the current baseline</li>
297         * </ul>
298         */
299        private void checkSuperInterfaces() {
300                Set superinterfacesSet1 = getInterfacesSet(this.type1);
301                if(!isStatusOk()) {
302                        return;
303                }
304                Set superinterfacesSet2 = getInterfacesSet(this.type2);
305                if(!isStatusOk()) {
306                        return;
307                }
308                if (superinterfacesSet1 == null) {
309                        if (superinterfacesSet2 != null) {
310                                this.addDelta(
311                                                getElementType(this.type1),
312                                                IDelta.CHANGED,
313                                                IDelta.EXPANDED_SUPERINTERFACES_SET,
314                                                this.currentDescriptorRestrictions,
315                                                this.type1.getModifiers(),
316                                                this.type2.getModifiers(),
317                                                this.type1,
318                                                this.type1.getName(),
319                                                Util.getDescriptorName(type1));
320                                if (this.type1.isInterface()) {
321                                        for (Iterator iterator = superinterfacesSet2.iterator(); iterator.hasNext();) {
322                                                IApiType type = (IApiType)iterator.next();
323                                                IApiMethod[] methods = type.getMethods();
324                                                int length = methods.length;
325                                                if (length != 0) {
326                                                        // we should check if every method defined in the new interface exists in the old hierarchy
327                                                        // could be methods moved up in the hierarchy
328                                                        methodLoop: for (int j = 0; j < length; j++) {
329                                                                IApiMethod method = methods[j];
330                                                                IApiMethod method3 = this.type1.getMethod(method.getName(), method.getSignature());
331                                                                if (method3 == null) {
332                                                                        this.addDelta(
333                                                                                        getElementType(this.type1),
334                                                                                        IDelta.ADDED,
335                                                                                        IDelta.SUPER_INTERFACE_WITH_METHODS,
336                                                                                        this.currentDescriptorRestrictions,
337                                                                                        this.type1.getModifiers(),
338                                                                                        this.type2.getModifiers(),
339                                                                                        this.type1,
340                                                                                        this.type1.getName(),
341                                                                                        new String[] {
342                                                                                                Util.getDescriptorName(type1),
343                                                                                                type.getName(),
344                                                                                                getMethodDisplayName(method, type)
345                                                                                        }
346                                                                        );
347                                                                        break methodLoop;
348                                                                }
349                                                        }
350                                                }
351                                        }
352                                }
353                        }
354                } else if (superinterfacesSet2 == null) {
355                        this.addDelta(
356                                        getElementType(this.type1),
357                                        IDelta.CHANGED,
358                                        IDelta.CONTRACTED_SUPERINTERFACES_SET,
359                                        this.currentDescriptorRestrictions,
360                                        this.type1.getModifiers(),
361                                        this.type2.getModifiers(),
362                                        this.type1,
363                                        this.type1.getName(),
364                                        Util.getDescriptorName(type1));
365                } else {
366                        Set names2 = new HashSet();
367                        for (Iterator iterator = superinterfacesSet2.iterator(); iterator.hasNext();) {
368                                names2.add(((IApiType)iterator.next()).getName());
369                        }
370                        boolean contracted = false;
371                        for (Iterator iterator = superinterfacesSet1.iterator(); iterator.hasNext();) {
372                                IApiType superInterfaceType = (IApiType) iterator.next();
373                                if (!names2.remove(superInterfaceType.getName())) {
374                                        contracted = true;
375                                }
376                        }
377                        if (contracted) {
378                                this.addDelta(
379                                                getElementType(this.type1),
380                                                IDelta.CHANGED,
381                                                IDelta.CONTRACTED_SUPERINTERFACES_SET,
382                                                this.currentDescriptorRestrictions,
383                                                this.type1.getModifiers(),
384                                                this.type2.getModifiers(),
385                                                this.type1,
386                                                this.type1.getName(),
387                                                Util.getDescriptorName(type1));
388                                return;
389                        }
390                        if (names2.size() > 0) {
391                                this.addDelta(
392                                                getElementType(this.type1),
393                                                IDelta.CHANGED,
394                                                IDelta.EXPANDED_SUPERINTERFACES_SET,
395                                                this.currentDescriptorRestrictions,
396                                                this.type1.getModifiers(),
397                                                this.type2.getModifiers(),
398                                                this.type1,
399                                                this.type1.getName(),
400                                                Util.getDescriptorName(type1));
401                                if (this.type1.isInterface()) {
402                                        for (Iterator iterator = names2.iterator(); iterator.hasNext();) {
403                                                String interfaceName = (String) iterator.next();
404                                                try {
405                                                        IApiTypeRoot interfaceClassFile = getType(interfaceName, this.component2, this.apiBaseline2);
406                                                        if (interfaceClassFile == null) continue;
407                                                        IApiType type = interfaceClassFile.getStructure();
408                                                        if(type == null) {
409                                                                continue;
410                                                        }
411                                                        IApiMethod[] methods = type.getMethods();
412                                                        int length = methods.length;
413                                                        if (length > 0) {
414                                                                // we should check if every method defined in the new interface exists in the old hierarchy
415                                                                // could be methods moved up in the hierarchy
416                                                                methodLoop: for (int j = 0; j < length; j++) {
417                                                                        IApiMethod method = methods[j];
418                                                                        boolean found = false;
419                                                                        interfaceLoop: for (Iterator iterator2 = superinterfacesSet1.iterator(); iterator2.hasNext();) {
420                                                                                IApiType superTypeDescriptor = (IApiType) iterator2.next();
421                                                                                IApiMethod method3 = superTypeDescriptor.getMethod(method.getName(), method.getSignature());
422                                                                                if (method3 == null) {
423                                                                                        continue interfaceLoop;
424                                                                                } else {
425                                                                                        found = true;
426                                                                                        break interfaceLoop;
427                                                                                }
428                                                                        }
429                                                                        if (!found) {
430                                                                                this.addDelta(
431                                                                                                getElementType(this.type1),
432                                                                                                IDelta.ADDED,
433                                                                                                IDelta.SUPER_INTERFACE_WITH_METHODS,
434                                                                                                this.currentDescriptorRestrictions,
435                                                                                                this.type1.getModifiers(),
436                                                                                                this.type2.getModifiers(),
437                                                                                                this.type1,
438                                                                                                this.type1.getName(),
439                                                                                                new String[] {
440                                                                                                        Util.getDescriptorName(type1),
441                                                                                                        type.getName(),
442                                                                                                        getMethodDisplayName(method, type)
443                                                                                                }
444                                                                                );
445                                                                                break methodLoop;
446                                                                        }
447                                                                }
448                                                        }
449                                                } catch (CoreException e) {
450                                                        ApiPlugin.log(e);
451                                                }
452                                        }
453                                }
454                        }
455                }
456        }
457 
458        private void checkTypeMembers() throws CoreException {
459                IApiType[] typeMembers = this.type1.getMemberTypes();
460                IApiType[] typeMembers2 = this.type2.getMemberTypes();
461                List added = new ArrayList(typeMembers2.length);
462                for (int i = 0; i < typeMembers2.length; i++) {
463                        added.add(typeMembers2[i].getName());
464                }
465                if (typeMembers.length > 0) {
466                        if (typeMembers2.length == 0) {
467                                loop: for (int i = 0; i < typeMembers.length; i++) {
468                                        try {
469                                                IApiType typeMember = typeMembers[i];
470                                                // check visibility
471                                                IApiDescription apiDescription = this.component.getApiDescription();
472                                                IApiAnnotations memberTypeElementDescription = apiDescription.resolveAnnotations(typeMember.getHandle());
473                                                int memberTypeVisibility = 0;
474                                                if (memberTypeElementDescription != null) {
475                                                        memberTypeVisibility = memberTypeElementDescription.getVisibility();
476                                                }
477                                                if ((memberTypeVisibility & visibilityModifiers) == 0) {
478                                                        // we skip the class file according to their visibility
479                                                        continue loop;
480                                                }
481                                                if (visibilityModifiers == VisibilityModifiers.API) {
482                                                        // if the visibility is API, we only consider public and protected types
483                                                        if (Util.isDefault(typeMember.getModifiers())
484                                                                                || Flags.isPrivate(typeMember.getModifiers())) {
485                                                                continue loop;
486                                                        }
487                                                }
488                                                this.addDelta(
489                                                                getElementType(this.type1),
490                                                                IDelta.REMOVED,
491                                                                IDelta.TYPE_MEMBER,
492                                                                this.currentDescriptorRestrictions,
493                                                                typeMember.getModifiers(),
494                                                                0,
495                                                                this.type1,
496                                                                typeMember.getName(),
497                                                                new String[] { typeMember.getName().replace('$', '.'), Util.getComponentVersionsId(component2)});
498                                        } catch (CoreException e) {
499                                                reportStatus(e);
500                                        }
501                                }
502                                return;
503                        }
504                        // check removed or added type members
505                        List removedTypeMembers = new ArrayList();
506                        loop: for (int i =  0; i < typeMembers.length; i++) {
507                                IApiType typeMember = typeMembers[i];
508                                IApiType typeMember2 = this.type2.getMemberType(typeMember.getSimpleName());
509                                if (typeMember2 == null) {
510                                        removedTypeMembers.add(typeMember);
511                                } else {
512                                        added.remove(typeMember2.getName());
513                                        // check deltas inside the type member
514                                        try {
515                                                // check visibility of member types
516                                                IApiDescription apiDescription = this.component.getApiDescription();
517                                                IApiAnnotations memberTypeElementDescription = apiDescription.resolveAnnotations(typeMember.getHandle());
518                                                int memberTypeVisibility = 0;
519                                                if (memberTypeElementDescription != null) {
520                                                        memberTypeVisibility = memberTypeElementDescription.getVisibility();
521                                                }
522                                                if ((memberTypeVisibility & visibilityModifiers) == 0) {
523                                                        // we skip the class file according to their visibility
524                                                        continue loop;
525                                                }
526                                                IApiDescription apiDescription2 = this.component2.getApiDescription();
527                                                IApiAnnotations memberTypeElementDescription2 = apiDescription2.resolveAnnotations(typeMember2.getHandle());
528                                                int memberTypeVisibility2 = 0;
529                                                if (memberTypeElementDescription2 != null) {
530                                                        memberTypeVisibility2 = memberTypeElementDescription2.getVisibility();
531                                                }
532                                                String deltaComponentID = Util.getDeltaComponentVersionsId(component2);
533                                                int restrictions = memberTypeElementDescription2 != null ? memberTypeElementDescription2.getRestrictions() : RestrictionModifiers.NO_RESTRICTIONS;
534                                                if (Flags.isFinal(this.type2.getModifiers())) {
535                                                        restrictions |= RestrictionModifiers.NO_EXTEND;
536                                                }
537                                                if (isAPI(memberTypeVisibility, typeMember) && !isAPI(memberTypeVisibility2, typeMember2)) {
538                                                        this.addDelta(
539                                                                        new Delta(
540                                                                                        deltaComponentID,
541                                                                                        getElementType(typeMember),
542                                                                                        IDelta.CHANGED,
543                                                                                        IDelta.DECREASE_ACCESS,
544                                                                                        restrictions | this.currentDescriptorRestrictions,
545                                                                                        typeMember.getModifiers(),
546                                                                                        typeMember2.getModifiers(),
547                                                                                        typeMember.getName(),
548                                                                                        typeMember.getName(),
549                                                                                        new String[] { typeMember.getName().replace('$', '.') }));
550                                                        continue;
551                                                }
552                                                if ((memberTypeVisibility2 & visibilityModifiers) == 0) {
553                                                        // we simply report a changed visibility
554                                                        this.addDelta(
555                                                                        new Delta(
556                                                                                        deltaComponentID,
557                                                                                        getElementType(typeMember),
558                                                                                        IDelta.CHANGED,
559                                                                                        IDelta.TYPE_VISIBILITY,
560                                                                                        restrictions | this.currentDescriptorRestrictions,
561                                                                                        typeMember.getModifiers(),
562                                                                                        typeMember2.getModifiers(),
563                                                                                        typeMember.getName(),
564                                                                                        typeMember.getName(),
565                                                                                        new String[] { typeMember.getName().replace('$', '.') }));
566                                                }
567                                                if (this.visibilityModifiers == VisibilityModifiers.API) {
568                                                        // if the visibility is API, we only consider public and protected types
569                                                        if (Util.isDefault(typeMember2.getModifiers())
570                                                                                || Flags.isPrivate(typeMember2.getModifiers())) {
571                                                                continue loop;
572                                                        }
573                                                }
574                                                IApiTypeRoot memberType2 = this.component2.findTypeRoot(typeMember.getName());
575                                                ClassFileComparator comparator = new ClassFileComparator(typeMember, memberType2, this.component, this.component2, this.apiBaseline1, this.apiBaseline2, this.visibilityModifiers);
576                                                IDelta delta2 = comparator.getDelta(null);
577                                                if (delta2 != null && delta2 != ApiComparator.NO_DELTA) {
578                                                        this.addDelta(delta2);
579                                                }
580                                        } catch (CoreException e) {
581                                                reportStatus(e);
582                                        }
583                                }
584                        }
585                        loop: for (Iterator iterator = removedTypeMembers.iterator(); iterator.hasNext();) {
586                                try {
587                                        IApiType typeMember = (IApiType) iterator.next();
588                                        // check visibility
589                                        IApiDescription apiDescription = this.component.getApiDescription();
590                                        IApiAnnotations memberTypeElementDescription = apiDescription.resolveAnnotations(typeMember.getHandle());
591                                        int memberTypeVisibility = 0;
592                                        if (memberTypeElementDescription != null) {
593                                                memberTypeVisibility = memberTypeElementDescription.getVisibility();
594                                        }
595                                        if ((memberTypeVisibility & visibilityModifiers) == 0) {
596                                                // we skip the class file according to their visibility
597                                                continue loop;
598                                        }
599                                        if (this.visibilityModifiers == VisibilityModifiers.API) {
600                                                // if the visibility is API, we only consider public and protected types
601                                                if (Util.isDefault(typeMember.getModifiers())
602                                                                        || Flags.isPrivate(typeMember.getModifiers())) {
603                                                        continue loop;
604                                                }
605                                        }
606                                        this.addDelta(
607                                                        getElementType(this.type1),
608                                                        IDelta.REMOVED,
609                                                        IDelta.TYPE_MEMBER,
610                                                        memberTypeElementDescription != null ? memberTypeElementDescription.getRestrictions() : RestrictionModifiers.NO_RESTRICTIONS,
611                                                        typeMember.getModifiers(),
612                                                        0,
613                                                        this.type1,
614                                                        typeMember.getName(),
615                                                        new String[] { typeMember.getName().replace('$', '.'), Util.getComponentVersionsId(component2)});
616                                } catch (CoreException e) {
617                                        reportStatus(e);
618                                }
619                        }
620                }
621                // report remaining types as addition
622                // Report delta as a breakage
623                loop: for (Iterator iterator = added.iterator(); iterator.hasNext();) {
624                        try {
625                                String name = (String) iterator.next();
626                                int index = name.lastIndexOf('$');
627                                IApiType typeMember = this.type2.getMemberType(name.substring(index+1));
628                                // check visibility
629                                IApiDescription apiDescription2 = this.component2.getApiDescription();
630                                IApiAnnotations memberTypeElementDescription2 = apiDescription2.resolveAnnotations(typeMember.getHandle());
631                                int memberTypeVisibility2 = 0;
632                                if (memberTypeElementDescription2 != null) {
633                                        memberTypeVisibility2 = memberTypeElementDescription2.getVisibility();
634                                }
635                                if ((memberTypeVisibility2 & visibilityModifiers) == 0) {
636                                        // we skip the class file according to their visibility
637                                        continue loop;
638                                }
639                                if (this.visibilityModifiers == VisibilityModifiers.API) {
640                                        // if the visibility is API, we only consider public and protected types
641                                        if (Util.isDefault(typeMember.getModifiers())
642                                                                || Flags.isPrivate(typeMember.getModifiers())) {
643                                                continue loop;
644                                        }
645                                }
646                                this.addDelta(
647                                                getElementType(this.type1),
648                                                IDelta.ADDED,
649                                                IDelta.TYPE_MEMBER,
650                                                this.currentDescriptorRestrictions,
651                                                0,
652                                                typeMember.getModifiers(),
653                                                this.type1,
654                                                typeMember.getSimpleName(),
655                                                typeMember.getSimpleName());
656                        } catch (CoreException e) {
657                                reportStatus(e);
658                        }
659                }
660        }
661 
662        private void checkGenericSignature(String signature1, String signature2, IApiMember element1, IApiMember element2) {
663                if (signature1 == null) {
664                        if (signature2 != null) {
665                                // added type parameter from scratch (none before)
666                                // report delta as compatible
667                                SignatureDescriptor signatureDescriptor2 = getSignatureDescriptor(signature2);
668                                TypeParameterDescriptor[] typeParameterDescriptors = signatureDescriptor2.getTypeParameterDescriptors();
669                                if (typeParameterDescriptors.length != 0) {
670                                        this.addDelta(
671                                                        getElementType(element1),
672                                                        IDelta.ADDED,
673                                                        IDelta.TYPE_PARAMETERS,
674                                                        this.currentDescriptorRestrictions,
675                                                        element1.getModifiers(),
676                                                        element2.getModifiers(),
677                                                        this.type1,
678                                                        element1.getName(),
679                                                        new String[] {getDataFor(element1, this.type1)});
680                                } else if (signatureDescriptor2.getTypeArguments().length != 0) {
681                                        this.addDelta(
682                                                        getElementType(element1),
683                                                        IDelta.ADDED,
684                                                        IDelta.TYPE_ARGUMENTS,
685                                                        this.currentDescriptorRestrictions,
686                                                        element1.getModifiers(),
687                                                        element2.getModifiers(),
688                                                        this.type1,
689                                                        element1.getName(),
690                                                        new String[] {getDataFor(element1, this.type1)});
691                                }
692                        }
693                } else if (signature2 == null) {
694                        // removed type parameters
695                        SignatureDescriptor signatureDescriptor = getSignatureDescriptor(signature1);
696                        TypeParameterDescriptor[] typeParameterDescriptors = signatureDescriptor.getTypeParameterDescriptors();
697                        int length = typeParameterDescriptors.length;
698                        if (length != 0) {
699                                for (int i = 0; i < length; i++) {
700                                        TypeParameterDescriptor typeParameterDescriptor = typeParameterDescriptors[i];
701                                        this.addDelta(
702                                                        getElementType(element1),
703                                                        IDelta.REMOVED,
704                                                        IDelta.TYPE_PARAMETER,
705                                                        this.currentDescriptorRestrictions,
706                                                        element1.getModifiers(),
707                                                        element2.getModifiers(),
708                                                        this.type1,
709                                                        element1.getName(),
710                                                        new String[] {getDataFor(element1, type1), typeParameterDescriptor.name});
711                                }
712                        } else  {
713                                String[] typeArguments = signatureDescriptor.getTypeArguments();
714                                length = typeArguments.length;
715                                if (length != 0) {
716                                        for (int i = 0; i < length; i++) {
717                                                String typeArgument = typeArguments[i];
718                                                        this.addDelta(
719                                                                getElementType(element1),
720                                                                IDelta.REMOVED,
721                                                                IDelta.TYPE_ARGUMENT,
722                                                                this.currentDescriptorRestrictions,
723                                                                element1.getModifiers(),
724                                                                element2.getModifiers(),
725                                                                this.type1,
726                                                                element1.getName(),
727                                                                new String[] {getDataFor(element1, type1), typeArgument});
728                                        }
729                                }
730                        }
731                } else {
732                        // both types have generic signature
733                        // need to check delta for type parameter one by one
734                        SignatureDescriptor signatureDescriptor = getSignatureDescriptor(signature1);
735                        SignatureDescriptor signatureDescriptor2 = getSignatureDescriptor(signature2);
736                        
737                        TypeParameterDescriptor[] typeParameterDescriptors1 = signatureDescriptor.getTypeParameterDescriptors();
738                        TypeParameterDescriptor[] typeParameterDescriptors2 = signatureDescriptor2.getTypeParameterDescriptors();
739                        int length = typeParameterDescriptors1.length;
740                        int length2 =  typeParameterDescriptors2.length;
741                        int min = length;
742                        int max = length2;
743                        if (length > length2) {
744                                min = length2;
745                                max = length;
746                        }
747                        int i = 0;
748                        for (;i < min; i++) {
749                                TypeParameterDescriptor parameterDescriptor1 = typeParameterDescriptors1[i];
750                                TypeParameterDescriptor parameterDescriptor2 = typeParameterDescriptors2[i];
751                                String name = parameterDescriptor1.name;
752                                if (!name.equals(parameterDescriptor2.name)) {
753                                        this.addDelta(
754                                                        IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
755                                                        IDelta.CHANGED,
756                                                        IDelta.TYPE_PARAMETER_NAME,
757                                                        this.currentDescriptorRestrictions,
758                                                        element1.getModifiers(),
759                                                        element2.getModifiers(),
760                                                        this.type1,
761                                                        name,
762                                                        new String[] {getDataFor(element1, type1), name });
763                                }
764                                if (parameterDescriptor1.classBound == null) {
765                                        if (parameterDescriptor2.classBound != null) {
766                                                // report delta added class bound of a type parameter
767                                                this.addDelta(
768                                                                IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
769                                                                IDelta.ADDED,
770                                                                IDelta.CLASS_BOUND,
771                                                                this.currentDescriptorRestrictions,
772                                                                element1.getModifiers(),
773                                                                element2.getModifiers(),
774                                                                this.type1,
775                                                                name,
776                                                                new String[] {getDataFor(element1, type1), name });
777                                        }
778                                } else if (parameterDescriptor2.classBound == null) {
779                                        // report delta removed class bound of a type parameter
780                                        this.addDelta(
781                                                        IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
782                                                        IDelta.REMOVED,
783                                                        IDelta.CLASS_BOUND,
784                                                        this.currentDescriptorRestrictions,
785                                                        element1.getModifiers(),
786                                                        element2.getModifiers(),
787                                                        this.type1,
788                                                        name,
789                                                        new String[] {getDataFor(element1, type1), name});
790                                } else if (!parameterDescriptor1.classBound.equals(parameterDescriptor2.classBound)) {
791                                        // report delta changed class bound of a type parameter
792                                        this.addDelta(
793                                                        IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
794                                                        IDelta.CHANGED,
795                                                        IDelta.CLASS_BOUND,
796                                                        this.currentDescriptorRestrictions,
797                                                        element1.getModifiers(),
798                                                        element2.getModifiers(),
799                                                        this.type1,
800                                                        name,
801                                                        new String[] {getDataFor(element1, type1), name});
802                                }
803                                List interfaceBounds1 = parameterDescriptor1.interfaceBounds;
804                                List interfaceBounds2 = parameterDescriptor2.interfaceBounds;
805                                if (interfaceBounds1 == null) {
806                                        if (interfaceBounds2 != null) {
807                                                for (Iterator iterator = interfaceBounds2.iterator(); iterator.hasNext(); ) {
808                                                        // report delta added interface bounds
809                                                        this.addDelta(
810                                                                        IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
811                                                                        IDelta.ADDED,
812                                                                        IDelta.INTERFACE_BOUND,
813                                                                        this.currentDescriptorRestrictions,
814                                                                        element1.getModifiers(),
815                                                                        element2.getModifiers(),
816                                                                        this.type1,
817                                                                        name,
818                                                                        new String[] {getDataFor(element1, type1), name, (String) iterator.next()});
819                                                }
820                                        }
821                                } else if (interfaceBounds2 == null) {
822                                        // report delta removed interface bounds
823                                        for (Iterator iterator = interfaceBounds1.iterator(); iterator.hasNext(); ) {
824                                                // report delta added interface bounds
825                                                this.addDelta(
826                                                                IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
827                                                                IDelta.REMOVED,
828                                                                IDelta.INTERFACE_BOUND,
829                                                                this.currentDescriptorRestrictions,
830                                                                element1.getModifiers(),
831                                                                element2.getModifiers(),
832                                                                this.type1,
833                                                                name,
834                                                                new String[] {getDataFor(element1, type1), name, (String) iterator.next()});
835                                        }
836                                } else {
837                                        int size1 = interfaceBounds1.size();
838                                        int size2 = interfaceBounds2.size();
839                                        int boundsMin = size1;
840                                        int boundsMax = size2;
841                                        if (size1 > size2) {
842                                                boundsMin = size2;
843                                                boundsMax = size1;
844                                        }
845                                        int index = 0;
846                                        for (;index < boundsMin; index++) {
847                                                String currentInterfaceBound = (String) interfaceBounds1.get(index);
848                                                if (!currentInterfaceBound.equals(interfaceBounds2.get(index))) {
849                                                        // report delta: different interface bounds (or reordered interface bound)
850                                                        this.addDelta(
851                                                                        IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
852                                                                        IDelta.CHANGED,
853                                                                        IDelta.INTERFACE_BOUND,
854                                                                        this.currentDescriptorRestrictions,
855                                                                        element1.getModifiers(),
856                                                                        element2.getModifiers(),
857                                                                        this.type1,
858                                                                        name,
859                                                                        new String[] {getDataFor(element1, type1), name, currentInterfaceBound});
860                                                }
861                                        }
862                                        if (boundsMin != boundsMax) {
863                                                // if max = length2 => addition of type parameter descriptor
864                                                // if max = length => removal of type parameter descriptor
865                                                boolean added = boundsMax == size2;
866                                                for (; index < boundsMax; index++) {
867                                                        String currentInterfaceBound = added ? (String) interfaceBounds2.get(index) : (String) interfaceBounds1.get(index);
868                                                        this.addDelta(
869                                                                        IDelta.TYPE_PARAMETER_ELEMENT_TYPE,
870                                                                        added ? IDelta.ADDED : IDelta.REMOVED,
871                                                                        IDelta.INTERFACE_BOUND,
872                                                                        this.currentDescriptorRestrictions,
873                                                                        element1.getModifiers(),
874                                                                        element2.getModifiers(),
875                                                                        this.type1,
876                                                                        element1.getName(),
877                                                                        new String[] {getDataFor(element1, type1), name, currentInterfaceBound});
878                                                }
879                                        }
880                                }
881                        }
882                        if (min != max) {
883                                // if max = length2 => addition of type parameter descriptor
884                                // if max = length => removal of type parameter descriptor
885                                boolean added = max == length2;
886                                for (; i < max; i++) {
887                                        TypeParameterDescriptor currentTypeParameter = added ? typeParameterDescriptors2[i] : typeParameterDescriptors1[i];
888                                        this.addDelta(
889                                                        getElementType(element1),
890                                                        added ? IDelta.ADDED : IDelta.REMOVED,
891                                                        IDelta.TYPE_PARAMETER,
892                                                        this.currentDescriptorRestrictions,
893                                                        element1.getModifiers(),
894                                                        element2.getModifiers(),
895                                                        this.type1,
896                                                        element1.getName(),
897                                                        new String[] {getDataFor(element1, type1), currentTypeParameter.name});
898                                }
899                        }
900                        if (length2 > 0 || length > 0) return;
901                        String[] typeArguments = signatureDescriptor.getTypeArguments();
902                        String[] typeArguments2 = signatureDescriptor2.getTypeArguments();
903                        length = typeArguments.length;
904                        length2 = typeArguments2.length;
905                        min = length;
906                        max = length2;
907                        if (length > length2) {
908                                min = length2;
909                                max = length;
910                        }
911                        i = 0;
912                        for (;i < min; i++) {
913                                String currentTypeArgument = typeArguments[i];
914                                String newTypeArgument = typeArguments2[i];
915                                if (!currentTypeArgument.equals(newTypeArgument)) {
916                                        this.addDelta(
917                                                        getElementType(element1),
918                                                        IDelta.CHANGED,
919                                                        IDelta.TYPE_ARGUMENT,
920                                                        this.currentDescriptorRestrictions,
921                                                        element1.getModifiers(),
922                                                        element2.getModifiers(),
923                                                        this.type1,
924                                                        element1.getName(),
925                                                        new String[] {getDataFor(element1, type1), currentTypeArgument, newTypeArgument});
926                                }
927                        }
928                        if (min != max) {
929                                // if max = length2 => addition of type arguments
930                                // if max = length => removal of type arguments
931                                boolean added = max == length2;
932                                for (; i < max; i++) {
933                                        String currentTypeArgument = added ? typeArguments2[i] : typeArguments[i];
934                                        this.addDelta(
935                                                        getElementType(element1),
936                                                        added ? IDelta.ADDED : IDelta.REMOVED,
937                                                        IDelta.TYPE_ARGUMENT,
938                                                        this.currentDescriptorRestrictions,
939                                                        element1.getModifiers(),
940                                                        element2.getModifiers(),
941                                                        this.type1,
942                                                        element1.getName(),
943                                                        new String[] {getDataFor(element1, type1), currentTypeArgument});
944                                }
945                        }
946                }
947        }
948 
949        /**
950         * Recursively collects all of the super-interfaces of the given type descriptor within the scope of 
951         * the given API component
952         * @param type
953         * @param apiComponent
954         * @param profile
955         * @param set
956         */
957        private void collectAllInterfaces(IApiType type, Set set) {
958                try {
959                        IApiType[] interfaces = type.getSuperInterfaces();
960                        if (interfaces != null) {
961                                for (int i = 0; i < interfaces.length; i++) {
962                                        IApiType anInterface = interfaces[i];
963                                        int visibility = VisibilityModifiers.PRIVATE;
964                                        IApiComponent ifaceComponent = anInterface.getApiComponent();
965                                        IApiDescription apiDescription = ifaceComponent.getApiDescription();
966                                        IApiAnnotations elementDescription = apiDescription.resolveAnnotations(anInterface.getHandle());
967                                        if (elementDescription != null) {
968                                                visibility = elementDescription.getVisibility();
969                                        }
970                                        if ((visibility & visibilityModifiers) != 0) {
971                                                set.add(anInterface);
972                                        }
973                                        collectAllInterfaces(anInterface, set);
974                                }
975                        }
976                        String superclassName = type.getSuperclassName();
977                        if (superclassName != null && !Util.isJavaLangObject(superclassName)) {
978                                IApiType superclass = type.getSuperclass();
979                                collectAllInterfaces(superclass, set);
980                        }
981                }
982                catch(CoreException e) {
983                        reportStatus(e);
984                }
985        }
986        
987        private String getDataFor(IApiMember member, IApiType type) {
988                switch(member.getType()) {
989                        case IApiElement.TYPE:
990                                if (((IApiType)member).isMemberType()) {
991                                        return member.getName().replace('$', '.');
992                                }
993                                return member.getName();
994                        case IApiElement.METHOD:
995                                StringBuffer buffer = new StringBuffer();
996                                buffer.append(type.getName()).append('.').append(getMethodDisplayName((IApiMethod) member, type));
997                                return String.valueOf(buffer);
998                        case IApiElement.FIELD:
999                                buffer = new StringBuffer();
1000                                buffer.append(type.getName()).append('.').append(member.getName());
1001                                return String.valueOf(buffer);
1002                }
1003                return null;
1004        }
1005 
1006        /**
1007         * Returns a new {@link Delta} to use, and resets the status of creating a delta
1008         * @return
1009         */
1010        private Delta createDelta() {
1011                return new Delta();
1012        }
1013        
1014        /**
1015         * Returns the change(s) between the type descriptor and its equivalent in the current baseline.
1016         * @return the changes in the type descriptor or <code>null</code>
1017         */
1018        public IDelta getDelta(IProgressMonitor monitor) {
1019                SubMonitor localmonitor = SubMonitor.convert(monitor, 10);
1020                try {
1021                        this.delta = createDelta();
1022                        // check visibility
1023                        int typeAccess = this.type1.getModifiers();
1024                        int typeAccess2 = this.type2.getModifiers();
1025                        final IApiDescription component2ApiDescription = component2.getApiDescription();
1026                        IApiAnnotations elementDescription2 = component2ApiDescription.resolveAnnotations(this.type2.getHandle());
1027                        this.initialDescriptorRestrictions = RestrictionModifiers.NO_RESTRICTIONS;
1028                        this.currentDescriptorRestrictions = RestrictionModifiers.NO_RESTRICTIONS;
1029                        if (elementDescription2 != null) {
1030                                int restrictions2 = elementDescription2.getRestrictions();
1031                                IApiDescription apiDescription = this.component.getApiDescription();
1032                                if (this.component.hasApiDescription()) {
1033                                        int restrictions = RestrictionModifiers.NO_RESTRICTIONS;
1034                                        IApiAnnotations componentApiDescription = apiDescription.resolveAnnotations(this.type1.getHandle());
1035                                        if (componentApiDescription != null) {
1036                                                restrictions = componentApiDescription.getRestrictions();
1037                                                this.initialDescriptorRestrictions = restrictions;
1038                                        }
1039                                        if (restrictions2 != restrictions) {
1040                                                // report different restrictions
1041                                                // adding/removing no extend on a final class is ok
1042                                                // adding/removing no instantiate on an abstract class is ok
1043                                                if (this.type1.isInterface()) {
1044                                                        if ((RestrictionModifiers.isImplementRestriction(restrictions2) && !RestrictionModifiers.isImplementRestriction(restrictions)) ||
1045                                                                (RestrictionModifiers.isExtendRestriction(restrictions2) && !RestrictionModifiers.isExtendRestriction(restrictions))) {
1046                                                        this.addDelta(
1047                                                                        getElementType(this.type1),
1048                                                                        IDelta.ADDED,
1049                                                                        IDelta.RESTRICTIONS,
1050                                                                        restrictions2,
1051                                                                        typeAccess,
1052                                                                        typeAccess2,
1053                                                                        this.type2,
1054                                                                        this.type2.getName(),
1055                                                                        Util.getDescriptorName(type1));
1056                                                        }
1057                                                } else {
1058                                                        boolean reportChangedRestrictions = false;
1059                                                        if (!Flags.isFinal(typeAccess2) && !Flags.isFinal(typeAccess)) {
1060                                                                if (RestrictionModifiers.isExtendRestriction(restrictions2)
1061                                                                                && !RestrictionModifiers.isExtendRestriction(restrictions)) {
1062                                                                        reportChangedRestrictions = true;
1063                                                                        this.addDelta(
1064                                                                                        getElementType(this.type1),
1065                                                                                        IDelta.ADDED,
1066                                                                                        IDelta.RESTRICTIONS,
1067                                                                                        restrictions2,
1068                                                                                        typeAccess,
1069                                                                                        typeAccess2,
1070                                                                                        this.type2,
1071                                                                                        this.type2.getName(),
1072                                                                                        Util.getDescriptorName(type1));
1073                                                                }
1074                                                        }
1075                                                        if (!reportChangedRestrictions
1076                                                                        && !Flags.isAbstract(typeAccess2)
1077                                                                        && !Flags.isAbstract(typeAccess)) {
1078                                                                if (RestrictionModifiers.isInstantiateRestriction(restrictions2)
1079                                                                                        && !RestrictionModifiers.isInstantiateRestriction(restrictions)) {
1080                                                                        this.addDelta(
1081                                                                                        getElementType(this.type1),
1082                                                                                        IDelta.ADDED,
1083                                                                                        IDelta.RESTRICTIONS,
1084                                                                                        restrictions2,
1085                                                                                        typeAccess,
1086                                                                                        typeAccess2,
1087                                                                                        this.type2,
1088                                                                                        this.type2.getName(),
1089                                                                                        Util.getDescriptorName(type1));
1090                                                                }
1091                                                        }
1092                                                }
1093                                        }
1094                                }
1095                                this.currentDescriptorRestrictions = restrictions2;
1096                        }
1097                        // first make sure that we compare interface with interface, class with class,
1098                        // annotation with annotation and enum with enums
1099                        if (Flags.isFinal(typeAccess2)) {
1100                                this.currentDescriptorRestrictions |= RestrictionModifiers.NO_EXTEND;
1101                        }
1102                        if (Flags.isFinal(typeAccess)) {
1103                                this.initialDescriptorRestrictions |= RestrictionModifiers.NO_EXTEND;
1104                        }
1105 
1106                        if (Flags.isDeprecated(typeAccess)) {
1107                                if (!Flags.isDeprecated(typeAccess2)) {
1108                                        this.addDelta(
1109                                                        getElementType(this.type1),
1110                                                        IDelta.REMOVED,
1111                                                        IDelta.DEPRECATION,
1112                                                        this.currentDescriptorRestrictions,
1113                                                        typeAccess,
1114                                                        typeAccess2,
1115                                                        this.type1,
1116                                                        this.type1.getName(),
1117                                                        Util.getDescriptorName(type1));
1118                                }
1119                        } else if (Flags.isDeprecated(typeAccess2)) {
1120                                this.addDelta(
1121                                                getElementType(this.type1),
1122                                                IDelta.ADDED,
1123                                                IDelta.DEPRECATION,
1124                                                this.currentDescriptorRestrictions,
1125                                                typeAccess,
1126                                                typeAccess2,
1127                                                this.type1,
1128                                                this.type1.getName(),
1129                                                Util.getDescriptorName(type1));
1130                        }
1131                        if (Flags.isProtected(typeAccess)) {
1132                                if (Flags.isPrivate(typeAccess2) || Util.isDefault(typeAccess2)) {
1133                                        // report delta - decrease access: protected to default or private
1134                                        this.addDelta(
1135                                                        getElementType(this.type1),
1136                                                        IDelta.CHANGED,
1137                                                        IDelta.DECREASE_ACCESS,
1138                                                        this.currentDescriptorRestrictions,
1139                                                        typeAccess,
1140                                                        typeAccess2,
1141                                                        this.type1,
1142                                                        this.type1.getName(),
1143                                                        Util.getDescriptorName(type1));
1144                                        return this.delta;
1145                                } else if (Flags.isPublic(typeAccess2)) {
1146                                        // report delta - increase access: protected to public
1147                                        this.addDelta(
1148                                                        getElementType(this.type1),
1149                                                        IDelta.CHANGED,
1150                                                        IDelta.INCREASE_ACCESS,
1151                                                        this.currentDescriptorRestrictions,
1152                                                        typeAccess,
1153                                                        typeAccess2,
1154                                                        this.type1,
1155                                                        this.type1.getName(),
1156                                                        Util.getDescriptorName(type1));
1157                                        return this.delta;
1158                                }
1159                        } else if (Flags.isPublic(typeAccess)
1160                                        && (Flags.isProtected(typeAccess2)
1161                                                        || Flags.isPrivate(typeAccess2)
1162                                                        || Util.isDefault(typeAccess2))) {
1163                                // report delta - decrease access: public to protected, default or private
1164                                this.addDelta(
1165                                                getElementType(this.type1),
1166                                                IDelta.CHANGED,
1167                                                IDelta.DECREASE_ACCESS,
1168                                                this.currentDescriptorRestrictions,
1169                                                typeAccess,
1170                                                typeAccess2,
1171                                                this.type1,
1172                                                this.type1.getName(),
1173                                                Util.getDescriptorName(type1));
1174                                return this.delta;
1175                        } else if (Util.isDefault(typeAccess)
1176                                        && (Flags.isPublic(typeAccess2)
1177                                                        || Flags.isProtected(typeAccess2))) {
1178                                this.addDelta(
1179                                                getElementType(this.type1),
1180                                                IDelta.CHANGED,
1181                                                IDelta.INCREASE_ACCESS,
1182                                                this.currentDescriptorRestrictions,
1183                                                typeAccess,
1184                                                typeAccess2,
1185                                                this.type1,
1186                                                this.type1.getName(),
1187                                                Util.getDescriptorName(type1));
1188                                return this.delta;
1189                        } else if (Flags.isPrivate(typeAccess)
1190                                        && (Util.isDefault(typeAccess2)
1191                                                        || Flags.isPublic(typeAccess2)
1192                                                        || Flags.isProtected(typeAccess2))) {
1193                                this.addDelta(
1194                                                getElementType(this.type1),
1195                                                IDelta.CHANGED,
1196                                                IDelta.INCREASE_ACCESS,
1197                                                this.currentDescriptorRestrictions,
1198                                                typeAccess,
1199                                                typeAccess2,
1200                                                this.type1,
1201                                                this.type1.getName(),
1202                                                Util.getDescriptorName(type1));
1203                                return this.delta;
1204                        }
1205                        
1206                        if (Flags.isAnnotation(typeAccess)) {
1207                                if (!Flags.isAnnotation(typeAccess2)) {
1208                                        if (Flags.isInterface(typeAccess2)) {
1209                                                // report conversion from annotation to interface
1210                                                this.addDelta(
1211                                                                IDelta.ANNOTATION_ELEMENT_TYPE,
1212                                                                IDelta.CHANGED,
1213                                                                IDelta.TYPE_CONVERSION,
1214                                                                this.currentDescriptorRestrictions,
1215                                                                typeAccess,
1216                                                                typeAccess2,
1217                                                                this.type1,
1218                                                                this.type1.getName(),
1219                                                                new String[] {
1220                                                                                Util.getDescriptorName(type1),
1221                                                                                Integer.toString(IDelta.ANNOTATION_ELEMENT_TYPE),
1222                                                                                Integer.toString(IDelta.INTERFACE_ELEMENT_TYPE)
1223                                                                        });
1224                                        } else if (Flags.isEnum(typeAccess2)) {
1225                                                // report conversion from annotation to enum
1226                                                this.addDelta(
1227                                                                IDelta.ANNOTATION_ELEMENT_TYPE,
1228                                                                IDelta.CHANGED,
1229                                                                IDelta.TYPE_CONVERSION,
1230                                                                this.currentDescriptorRestrictions,
1231                                                                typeAccess,
1232                                                                typeAccess2,
1233                                                                this.type1,
1234                                                                this.type1.getName(),
1235                                                                new String[] {
1236                                                                                Util.getDescriptorName(type1),
1237                                                                                Integer.toString(IDelta.ANNOTATION_ELEMENT_TYPE),
1238                                                                                Integer.toString(IDelta.ENUM_ELEMENT_TYPE)
1239                                                                });
1240                                        } else {
1241                                                // report conversion from annotation to class
1242                                                this.addDelta(
1243                                                                IDelta.ANNOTATION_ELEMENT_TYPE,
1244                                                                IDelta.CHANGED,
1245                                                                IDelta.TYPE_CONVERSION,
1246                                                                this.currentDescriptorRestrictions,
1247                                                                typeAccess,
1248                                                                typeAccess2,
1249                                                                this.type1,
1250                                                                this.type1.getName(),
1251                                                                new String[] {
1252                                                                                Util.getDescriptorName(type1),
1253                                                                                Integer.toString(IDelta.ANNOTATION_ELEMENT_TYPE),
1254                                                                                Integer.toString(IDelta.CLASS_ELEMENT_TYPE)
1255                                                                });
1256                                        }
1257                                        return this.delta;
1258                                }
1259                        } else if (Flags.isInterface(typeAccess)) {
1260                                if (Flags.isAnnotation(typeAccess2)) {
1261                                        // conversion from interface to annotation
1262                                        this.addDelta(
1263                                                        IDelta.INTERFACE_ELEMENT_TYPE,
1264                                                        IDelta.CHANGED,
1265                                                        IDelta.TYPE_CONVERSION,
1266                                                        this.currentDescriptorRestrictions,
1267                                                        typeAccess,
1268                                                        typeAccess2,
1269                                                        this.type1,
1270                                                        this.type1.getName(),
1271                                                        new String[] {
1272                                                                Util.getDescriptorName(type1),
1273                                                                Integer.toString(IDelta.INTERFACE_ELEMENT_TYPE),
1274                                                                Integer.toString(IDelta.ANNOTATION_ELEMENT_TYPE)
1275                                                        });
1276                                        return this.delta;
1277                                } else if (!Flags.isInterface(typeAccess2)) {
1278                                        if (Flags.isEnum(typeAccess2)) {
1279                                                // conversion from interface to enum
1280                                                this.addDelta(
1281                                                                IDelta.INTERFACE_ELEMENT_TYPE,
1282                                                                IDelta.CHANGED,
1283                                                                IDelta.TYPE_CONVERSION,
1284                                                                this.currentDescriptorRestrictions,
1285                                                                typeAccess,
1286                                                                typeAccess2,
1287                                                                this.type1,
1288                                                                this.type1.getName(),
1289                                                                new String[] {
1290                                                                                Util.getDescriptorName(type1),
1291                                                                                Integer.toString(IDelta.INTERFACE_ELEMENT_TYPE),
1292                                                                                Integer.toString(IDelta.ENUM_ELEMENT_TYPE)
1293                                                                });
1294                                        } else {
1295                                                // conversion from interface to class
1296                                                this.addDelta(
1297                                                                IDelta.INTERFACE_ELEMENT_TYPE,
1298                                                                IDelta.CHANGED,
1299                                                                IDelta.TYPE_CONVERSION,
1300                                                                this.currentDescriptorRestrictions,
1301                                                                typeAccess,
1302                                                                typeAccess2,
1303                                                                this.type1,
1304                                                                this.type1.getName(),
1305                                                                new String[] {
1306                                                                                Util.getDescriptorName(type1),
1307                                                                                Integer.toString(IDelta.INTERFACE_ELEMENT_TYPE),
1308                                                                                Integer.toString(IDelta.CLASS_ELEMENT_TYPE)
1309                                                                });
1310                                        }
1311                                        return this.delta;
1312                                }
1313                        } else if (Flags.isEnum(typeAccess)) {
1314                                if (!Flags.isEnum(typeAccess2)) {
1315                                        if (Flags.isAnnotation(typeAccess2)) {
1316                                                // report conversion from enum to annotation
1317                                                this.addDelta(
1318                                                                IDelta.ENUM_ELEMENT_TYPE,
1319                                                                IDelta.CHANGED,
1320                                                                IDelta.TYPE_CONVERSION,
1321                                                                this.currentDescriptorRestrictions,
1322                                                                typeAccess,
1323                                                                typeAccess2,
1324                                                                this.type1,
1325                                                                this.type1.getName(),
1326                                                                new String[] {
1327                                                                                Util.getDescriptorName(type1),
1328                                                                                Integer.toString(IDelta.ENUM_ELEMENT_TYPE),
1329                                                                                Integer.toString(IDelta.ANNOTATION_ELEMENT_TYPE)
1330                                                                });
1331                                        } else if (Flags.isInterface(typeAccess2)) {
1332                                                // report conversion from enum to interface
1333                                                this.addDelta(
1334                                                                IDelta.ENUM_ELEMENT_TYPE,
1335                                                                IDelta.CHANGED,
1336                                                                IDelta.TYPE_CONVERSION,
1337                                                                this.currentDescriptorRestrictions,
1338                                                                typeAccess,
1339                                                                typeAccess2,
1340                                                                this.type1,
1341                                                                this.type1.getName(),
1342                                                                new String[] {
1343                                                                                Util.getDescriptorName(type1),
1344                                                                                Integer.toString(IDelta.ENUM_ELEMENT_TYPE),
1345                                                                                Integer.toString(IDelta.INTERFACE_ELEMENT_TYPE)
1346                                                                });
1347                                        } else {
1348                                                // report conversion from enum to class
1349                                                this.addDelta(
1350                                                                IDelta.ENUM_ELEMENT_TYPE,
1351                                                                IDelta.CHANGED,
1352                                                                IDelta.TYPE_CONVERSION,
1353                                                                this.currentDescriptorRestrictions,
1354                                                                typeAccess,
1355                                                                typeAccess2,
1356                                                                this.type1,
1357                                                                this.type1.getName(),
1358                                                                new String[] {
1359                                                                                Util.getDescriptorName(type1),
1360                                                                                Integer.toString(IDelta.ENUM_ELEMENT_TYPE),
1361                                                                                Integer.toString(IDelta.CLASS_ELEMENT_TYPE)
1362                                                                });
1363                                        }
1364                                        return this.delta;
1365                                }
1366                        } else if (!Util.isClass(typeAccess2)) {
1367                                if (Flags.isAnnotation(typeAccess2)) {
1368                                        // report conversion from class to annotation
1369                                        this.addDelta(
1370                                                        IDelta.CLASS_ELEMENT_TYPE,
1371                                                        IDelta.CHANGED,
1372                                                        IDelta.TYPE_CONVERSION,
1373                                                        this.currentDescriptorRestrictions,
1374                                                        typeAccess,
1375                                                        typeAccess2,
1376                                                        this.type1,
1377                                                        this.type1.getName(),
1378                                                        new String[] {
1379                                                                        Util.getDescriptorName(type1),
1380                                                                        Integer.toString(IDelta.CLASS_ELEMENT_TYPE),
1381                                                                        Integer.toString(IDelta.ANNOTATION_ELEMENT_TYPE)
1382                                                        });
1383                                } else if (Flags.isInterface(typeAccess2)) {
1384                                        // report conversion from class to interface
1385                                        this.addDelta(
1386                                                        IDelta.CLASS_ELEMENT_TYPE,
1387                                                        IDelta.CHANGED,
1388                                                        IDelta.TYPE_CONVERSION,
1389                                                        this.currentDescriptorRestrictions,
1390                                                        typeAccess,
1391                                                        typeAccess2,
1392                                                        this.type1,
1393                                                        this.type1.getName(),
1394                                                        new String[] {
1395                                                                        Util.getDescriptorName(type1),
1396                                                                        Integer.toString(IDelta.CLASS_ELEMENT_TYPE),
1397                                                                        Integer.toString(IDelta.INTERFACE_ELEMENT_TYPE)
1398                                                        });
1399                                } else {
1400                                        // report conversion from class to enum
1401                                        this.addDelta(
1402                                                        IDelta.CLASS_ELEMENT_TYPE,
1403                                                        IDelta.CHANGED,
1404                                                        IDelta.TYPE_CONVERSION,
1405                                                        this.currentDescriptorRestrictions,
1406                                                        typeAccess,
1407                                                        typeAccess2,
1408                                                        this.type1,
1409                                                        this.type1.getName(),
1410                                                        new String[] {
1411                                                                        Util.getDescriptorName(type1),
1412                                                                        Integer.toString(IDelta.CLASS_ELEMENT_TYPE),
1413                                                                        Integer.toString(IDelta.ENUM_ELEMENT_TYPE)
1414                                                        });
1415                                }
1416                                return this.delta;
1417                        }
1418 
1419                        if (Flags.isStatic(typeAccess)) {
1420                                if (!Flags.isStatic(typeAccess2)) {
1421                                        this.addDelta(
1422                                                        getElementType(this.type1),
1423                                                        IDelta.CHANGED,
1424                                                        IDelta.STATIC_TO_NON_STATIC,
1425                                                        this.currentDescriptorRestrictions,
1426                                                        typeAccess,
1427                                                        typeAccess2,
1428                                                        this.type1,
1429                                                        this.type1.getName(),
1430                                                        Util.getDescriptorName(type1));
1431                                }
1432                        } else if (Flags.isStatic(typeAccess2)) {
1433                                this.addDelta(
1434                                                getElementType(this.type1),
1435                                                IDelta.CHANGED,
1436                                                IDelta.NON_STATIC_TO_STATIC,
1437                                                this.currentDescriptorRestrictions,
1438                                                typeAccess,
1439                                                typeAccess2,
1440                                                this.type1,
1441                                                this.type1.getName(),
1442                                                Util.getDescriptorName(type1));
1443                        }
1444                        // check super class set
1445                        checkSuperclass();
1446                        // check super interfaces set
1447                        checkSuperInterfaces();
1448                        
1449                        // checks fields
1450                        IApiField[] fields1 = this.type1.getFields();
1451                        IApiField[] fields2 = this.type2.getFields();
1452                        Set addedFields = new HashSet(fields2.length);
1453                        for (int i = 0; i < fields2.length; i++) {
1454                                addedFields.add(fields2[i].getName());
1455                        }
1456                        for (int i = 0; i < fields1.length; i++) {
1457                                addedFields.remove(fields1[i].getName());
1458                                getDeltaForField(fields1[i]);
1459                        }
1460                        // checks remaining fields (added fields)
1461                        for (Iterator iterator = addedFields.iterator(); iterator.hasNext();) {
1462                                IApiField field = this.type2.getField((String) iterator.next());
1463                                reportFieldAddition(field, this.type2);
1464                        }
1465                        
1466                        // checks methods
1467                        IApiMethod[] methods1 = this.type1.getMethods();
1468                        IApiMethod[] methods2 = this.type2.getMethods();
1469                        Set addedMethods = new HashSet(methods2.length);
1470                        for (int i = 0; i < methods2.length; i++) {
1471                                if(!methods2[i].isSynthetic()) {
1472                                        addedMethods.add(methods2[i].getHandle());
1473                                }
1474                        }
1475                        for (int i = 0; i < methods1.length; i++) {
1476                                addedMethods.remove(methods1[i].getHandle());
1477                                getDeltaForMethod(methods1[i]);
1478                        }
1479                        // checks remaining methods (added methods)
1480                        for (Iterator iterator = addedMethods.iterator(); iterator.hasNext();) {
1481                                IMethodDescriptor md = (IMethodDescriptor) iterator.next();
1482                                IApiMethod method = this.type2.getMethod(md.getName(), md.getSignature());
1483                                reportMethodAddition(method, this.type2);
1484                        }
1485                        if (Flags.isAbstract(typeAccess)) {
1486                                if (!Flags.isAbstract(typeAccess2)) {
1487                                        // report delta - changed from abstract to non-abstract
1488                                        this.addDelta(
1489                                                        getElementType(this.type1),
1490                                                        IDelta.CHANGED,
1491                                                        IDelta.ABSTRACT_TO_NON_ABSTRACT,
1492                                                        this.currentDescriptorRestrictions,
1493                                                        typeAccess,
1494                                                        typeAccess2,
1495                                                        this.type1,
1496                                                        this.type1.getName(),
1497                                                        Util.getDescriptorName(type1));
1498                                }
1499                        } else if (Flags.isAbstract(typeAccess2)){
1500                                // report delta - changed from non-abstract to abstract
1501                                if(!RestrictionModifiers.isInstantiateRestriction(initialDescriptorRestrictions)) {
1502                                        this.addDelta(
1503                                                        getElementType(this.type1),
1504                                                        IDelta.CHANGED,
1505                                                        IDelta.NON_ABSTRACT_TO_ABSTRACT,
1506                                                        this.currentDescriptorRestrictions,
1507                                                        typeAccess,
1508                                                        typeAccess2,
1509                                                        this.type1,
1510                                                        this.type1.getName(),
1511                                                        Util.getDescriptorName(type1));
1512                                }
1513                        }
1514 
1515                        if (Flags.isFinal(typeAccess)) {
1516                                if (!Flags.isFinal(typeAccess2)) {
1517                                        // report delta - changed from final to non-final
1518                                        this.addDelta(
1519                                                        getElementType(this.type1),
1520                                                        IDelta.CHANGED,
1521                                                        IDelta.FINAL_TO_NON_FINAL,
1522                                                        this.currentDescriptorRestrictions,
1523                                                        typeAccess,
1524                                                        typeAccess2,
1525                                                        this.type1,
1526                                                        this.type1.getName(),
1527                                                        Util.getDescriptorName(type1));
1528                                }
1529                        } else if (Flags.isFinal(typeAccess2)){
1530                                // report delta - changed from non-final to final
1531                                this.addDelta(
1532                                                getElementType(this.type1),
1533                                                IDelta.CHANGED,
1534                                                IDelta.NON_FINAL_TO_FINAL,
1535                                                this.initialDescriptorRestrictions,
1536                                                typeAccess,
1537                                                typeAccess2,
1538                                                this.type1,
1539                                                this.type1.getName(),
1540                                                Util.getDescriptorName(type1));
1541                        }
1542                        // check type parameters
1543                        String signature1 = this.type1.getGenericSignature();
1544                        String signature2 = this.type2.getGenericSignature();
1545                        checkGenericSignature(signature1, signature2, this.type1, this.type2);
1546                        
1547                        // check type members
1548                        checkTypeMembers();
1549                        return this.delta.isEmpty() ? ApiComparator.NO_DELTA : this.delta;
1550                } catch (CoreException e) {
1551                        reportStatus(e);
1552                        return null;
1553                }
1554                finally {
1555                        localmonitor.done();
1556                }
1557        }
1558 
1559        private void getDeltaForField(IApiField field) {
1560                int access = field.getModifiers();
1561                if (Flags.isSynthetic(access)) {
1562                        // we ignore synthetic fields
1563                        return;
1564                }
1565                String name = field.getName();
1566                IApiField field2 = this.type2.getField(name);
1567                if (field2 == null) {
1568                        if (Flags.isPrivate(access)
1569                                        || Util.isDefault(access)) {
1570                                this.addDelta(
1571                                                getElementType(this.type1),
1572                                                IDelta.REMOVED,
1573                                                IDelta.FIELD,
1574                                                this.currentDescriptorRestrictions,
1575                                                access,
1576                                                0,
1577                                                this.type1,
1578                                                name,
1579                                                new String[] {Util.getDescriptorName(this.type1), name});
1580                        } else {
1581                                boolean found = false;
1582                                if (this.component2 != null) {
1583                                        if (this.type1.isInterface()) {
1584                                                Set interfacesSet = getInterfacesSet(this.type2);
1585                                                if (interfacesSet != null) {
1586                                                        for (Iterator iterator = interfacesSet.iterator(); iterator.hasNext();) {
1587                                                                IApiType superTypeDescriptor = (IApiType) iterator.next();
1588                                                                IApiField field3 = superTypeDescriptor.getField(name);
1589                                                                if (field3 == null) {
1590                                                                        continue;
1591                                                                } else {
1592                                                                        // interface method can only be public
1593                                                                        // method has been move up in the hierarchy - report the delta and abort loop
1594                                                                        this.addDelta(
1595                                                                                        getElementType(this.type1),
1596                                                                                        IDelta.REMOVED,
1597                                                                                        IDelta.FIELD_MOVED_UP,
1598                                                                                        this.currentDescriptorRestrictions,
1599                                                                                        access,
1600                                                                                        field3.getModifiers(),
1601                                                                                        this.type1,
1602                                                                                        name,
1603                                                                                        new String[] {Util.getDescriptorName(this.type1), name});
1604                                                                        found = true;
1605                                                                        break;
1606                                                                }
1607                                                        }
1608                                                }
1609                                        } else {
1610                                                List superclassList = getSuperclassList(this.type2);
1611                                                if (superclassList != null && isStatusOk()) {
1612                                                        loop: for (Iterator iterator = superclassList.iterator(); iterator.hasNext();) {
1613                                                                IApiType superTypeDescriptor = (IApiType) iterator.next();
1614                                                                IApiField field3 = superTypeDescriptor.getField(name);
1615                                                                if (field3 == null) {
1616                                                                        continue;
1617                                                                } else {
1618                                                                        int access3 = field3.getModifiers();
1619                                                                        if (Flags.isPublic(access3)
1620                                                                                        || Flags.isProtected(access3)) {
1621                                                                                // method has been move up in the hierarchy - report the delta and abort loop
1622                                                                                this.addDelta(
1623                                                                                                getElementType(this.type1),
1624                                                                                                IDelta.REMOVED,
1625                                                                                                IDelta.FIELD_MOVED_UP,
1626                                                                                                this.currentDescriptorRestrictions,
1627                                                                                                access,
1628                                                                                                field3.getModifiers(),
1629                                                                                                this.type1,
1630                                                                                                name,
1631                                                                                                new String[] {Util.getDescriptorName(this.type1), name});
1632                                                                                found = true;
1633                                                                                break loop;
1634                                                                        }
1635                                                                }
1636                                                        }
1637                                                }
1638                                        }
1639                                }
1640                                if (!found) {
1641                                        if ((this.visibilityModifiers == VisibilityModifiers.API) && component.hasApiDescription()) {
1642                                                // check if this field should be removed because it is tagged as @noreference
1643                                                IApiDescription apiDescription = null;
1644                                                try {
1645                                                        apiDescription = this.component.getApiDescription();
1646                                                } catch (CoreException e) {
1647                                                        reportStatus(e);
1648                                                }
1649                                                if (apiDescription != null) {
1650                                                        IApiAnnotations apiAnnotations = apiDescription.resolveAnnotations(field.getHandle());
1651                                                        if (apiAnnotations != null) {
1652                                                                int restrictions = apiAnnotations.getRestrictions();
1653                                                                if (RestrictionModifiers.isReferenceRestriction(restrictions)) {
1654                                                                        // if not found, but tagged as @noreference in reference we don't need to report 
1655                                                                        // a removed field
1656                                                                        return;
1657                                                                }
1658                                                        }
1659                                                }
1660                                        }
1661                                        if (field.isEnumConstant()) {
1662                                                // report delta (removal of an enum constant - not compatible)
1663                                                this.addDelta(
1664                                                                getElementType(this.type1),
1665                                                                IDelta.REMOVED,
1666                                                                IDelta.ENUM_CONSTANT,
1667                                                                this.currentDescriptorRestrictions,
1668                                                                this.type1.getModifiers(),
1669                                                                this.type2.getModifiers(),
1670                                                                this.type1,
1671                                                                name,
1672                                                                new String[] {Util.getDescriptorName(this.type1), name});
1673                                                return;
1674                                        }
1675                                        // removing a public field is a breakage
1676                                        this.addDelta(
1677                                                        getElementType(this.type1),
1678                                                        IDelta.REMOVED,
1679                                                        IDelta.FIELD,
1680                                                        this.currentDescriptorRestrictions,
1681                                                        access,
1682                                                        0,
1683                                                        this.type1,
1684                                                        name,
1685                                                        new String[] {Util.getDescriptorName(this.type1), name});
1686                                }
1687                        }
1688                        return;
1689                }
1690                int restrictions = RestrictionModifiers.NO_RESTRICTIONS;
1691                int referenceRestrictions = RestrictionModifiers.NO_RESTRICTIONS;
1692                int access2 = field2.getModifiers();
1693                if (this.component2.hasApiDescription()) {
1694                        try {
1695                                IApiDescription apiDescription = this.component2.getApiDescription();
1696                                IApiAnnotations resolvedAPIDescription = apiDescription.resolveAnnotations(field2.getHandle());
1697                                if (resolvedAPIDescription != null) {
1698                                        restrictions = resolvedAPIDescription.getRestrictions();
1699                                }
1700                        } catch (CoreException e) {
1701                                // ignore
1702                        }
1703                }
1704                if ((this.visibilityModifiers == VisibilityModifiers.API) && component.hasApiDescription()) {
1705                        // check if this field should be removed because it is tagged as @noreference
1706                        IApiDescription apiDescription = null;
1707                        try {
1708                                apiDescription = this.component.getApiDescription();
1709                        } catch (CoreException e) {
1710                                reportStatus(e);
1711                        }
1712                        if (apiDescription != null) {
1713                                IApiAnnotations apiAnnotations = apiDescription.resolveAnnotations(field.getHandle());
1714                                if (apiAnnotations != null) {
1715                                        referenceRestrictions = apiAnnotations.getRestrictions();
1716                                }
1717                        }
1718                        if (RestrictionModifiers.isReferenceRestriction(referenceRestrictions)) {
1719                                // tagged as @noreference in the reference component
1720                                if (!RestrictionModifiers.isReferenceRestriction(restrictions)) {
1721                                        // no longer tagged as @noreference
1722                                        // report a field addition
1723                                        if (field2.isEnumConstant()) {
1724                                                // report delta (addition of an enum constant - compatible
1725                                                this.addDelta(
1726                                                                getElementType(this.type2),
1727                                                                IDelta.ADDED,
1728                                                                IDelta.ENUM_CONSTANT,
1729                                                                this.currentDescriptorRestrictions,
1730                                                                access,
1731                                                                access2,
1732                                                                this.type1,
1733                                                                name,
1734                                                                new String[] {Util.getDescriptorName(this.type2), name});
1735                                        } else {
1736                                                this.addDelta(
1737                                                                getElementType(this.type2),
1738                                                                IDelta.ADDED,
1739                                                                IDelta.FIELD,
1740                                                                this.currentDescriptorRestrictions,
1741                                                                access,
1742                                                                access2,
1743                                                                this.type1,
1744                                                                name,
1745                                                                new String[] {Util.getDescriptorName(this.type2), name});
1746                                        }
1747                                        return;
1748                                }
1749                        } else if (RestrictionModifiers.isReferenceRestriction(restrictions)) {
1750                                if (((Flags.isPublic(access2) || Flags.isProtected(access2)) && (Flags.isPublic(access) || Flags.isProtected(access)))
1751                                                && (this.visibilityModifiers == VisibilityModifiers.API)) {
1752                                        // report that it is no longer an API field
1753                                        this.addDelta(
1754                                                        getElementType(this.type2),
1755                                                        IDelta.REMOVED,
1756                                                        field2.isEnumConstant() ? IDelta.API_ENUM_CONSTANT : IDelta.API_FIELD,
1757                                                        restrictions,
1758                                                        access,
1759                                                        access2,
1760                                                        this.type1,
1761                                                        name,
1762                                                        new String[] {Util.getDescriptorName(this.type2), name});
1763                                }
1764                                return;
1765                        }
1766                }
1767 
1768                restrictions |= this.currentDescriptorRestrictions;
1769 
1770                if (!field.getSignature().equals(field2.getSignature())) {
1771                        // report delta
1772                        this.addDelta(
1773                                        IDelta.FIELD_ELEMENT_TYPE,
1774                                        IDelta.CHANGED,
1775                                        IDelta.TYPE,
1776                                        restrictions,
1777                                        access,
1778                                        access2,
1779                                        this.type1,
1780                                        name,
1781                                        new String[] {Util.getDescriptorName(this.type1), name});
1782                } else {
1783                        // check type parameters
1784                        String signature1 = field.getGenericSignature();
1785                        String signature2 = field2.getGenericSignature();
1786                        checkGenericSignature(signature1, signature2, field, field2);
1787                }
1788                boolean changeFinalToNonFinal = false;
1789                if (Flags.isProtected(access)) {
1790                        if (Flags.isPrivate(access2) || Util.isDefault(access2)) {
1791                                // report delta - decrease access: protected to default or private
1792                                this.addDelta(
1793                                                IDelta.FIELD_ELEMENT_TYPE,
1794                                                IDelta.CHANGED,
1795                                                IDelta.DECREASE_ACCESS,
1796                                                restrictions,
1797                                                access,
1798                                                access2,
1799                                                this.type1,
1800                                                name,
1801                                                new String[] {Util.getDescriptorName(this.type1), name});
1802                        } else if (Flags.isPublic(access2)) {
1803                                // report delta - increase access: protected to public
1804                                this.addDelta(
1805                                                IDelta.FIELD_ELEMENT_TYPE,
1806                                                IDelta.CHANGED,
1807                                                IDelta.INCREASE_ACCESS,
1808                                                restrictions,
1809                                                access,
1810                                                access2,
1811                                                this.type1,
1812                                                name,
1813                                                new String[] {Util.getDescriptorName(this.type1), name});
1814                        }
1815                } else if (Flags.isPublic(access)
1816                                && (Flags.isProtected(access2)
1817                                                || Flags.isPrivate(access2)
1818                                                || Util.isDefault(access2))) {
1819                        // report delta - decrease access: public to protected, default or private
1820                        this.addDelta(
1821                                        IDelta.FIELD_ELEMENT_TYPE,
1822                                        IDelta.CHANGED,
1823                                        IDelta.DECREASE_ACCESS,
1824                                        restrictions,
1825                                        access,
1826                                        access2,
1827                                        this.type1,
1828                                        name,
1829                                        new String[] {Util.getDescriptorName(this.type1), name});
1830                } else if (Flags.isPrivate(access)
1831                                && (Flags.isProtected(access2)
1832                                                || Util.isDefault(access2)
1833                                                || Flags.isPublic(access2))) {
1834                        this.addDelta(
1835                                        IDelta.FIELD_ELEMENT_TYPE,
1836                                        IDelta.CHANGED,
1837                                        IDelta.INCREASE_ACCESS,
1838                                        restrictions,
1839                                        access,
1840                                        access2,
1841                                        this.type1,
1842                                        name,
1843                                        new String[] {Util.getDescriptorName(this.type1), name});
1844                } else if (Util.isDefault(access)
1845                                && (Flags.isProtected(access2)
1846                                                || Flags.isPublic(access2))) {
1847                        this.addDelta(
1848                                        IDelta.FIELD_ELEMENT_TYPE,
1849                                        IDelta.CHANGED,
1850                                        IDelta.INCREASE_ACCESS,
1851                                        restrictions,
1852                                        access,
1853                                        access2,
1854                                        this.type1,
1855                                        name,
1856                                        new String[] {Util.getDescriptorName(this.type1), name});
1857                }
1858                if (Flags.isFinal(access)) {
1859                        if (!Flags.isFinal(access2)) {
1860                                if (!Flags.isStatic(access2)) {
1861                                        // report delta - final to non-final for a non static field
1862                                        this.addDelta(
1863                                                        IDelta.FIELD_ELEMENT_TYPE,
1864                                                        IDelta.CHANGED,
1865                                                        IDelta.FINAL_TO_NON_FINAL_NON_STATIC,
1866                                                        restrictions,
1867                                                        access,
1868                                                        access2,
1869                                                        this.type1,
1870                                                        name,
1871                                                        new String[] {Util.getDescriptorName(this.type1), name});
1872                                } else if (field.getConstantValue() != null) {
1873                                        // report delta - final to non-final for a static field with a compile time constant
1874                                        changeFinalToNonFinal = true;
1875                                        this.addDelta(
1876                                                        IDelta.FIELD_ELEMENT_TYPE,
1877                                                        IDelta.CHANGED,
1878                                                        IDelta.FINAL_TO_NON_FINAL_STATIC_CONSTANT,
1879                                                        restrictions,
1880                                                        access,
1881                                                        access2,
1882                                                        this.type1,
1883                                                        name,
1884                                                        new String[] {Util.getDescriptorName(this.type1), name});
1885                                } else {
1886                                        // report delta - final to non-final for a static field with no compile time constant
1887                                        this.addDelta(
1888                                                        IDelta.FIELD_ELEMENT_TYPE,
1889                                                        IDelta.CHANGED,
1890                                                        IDelta.FINAL_TO_NON_FINAL_STATIC_NON_CONSTANT,
1891                                                        restrictions,
1892                                                        access,
1893                                                        access2,
1894                                                        this.type1,
1895                                                        name,
1896                                                        new String[] {Util.getDescriptorName(this.type1), name});
1897                                }
1898                        }
1899                } else if (Flags.isFinal(access2)) {
1900                        // report delta - non-final to final
1901                        this.addDelta(
1902                                        IDelta.FIELD_ELEMENT_TYPE,
1903                                        IDelta.CHANGED,
1904                                        IDelta.NON_FINAL_TO_FINAL,
1905                                        restrictions,
1906                                        access,
1907                                        access2,
1908                                        this.type1,
1909                                        name,
1910                                        new String[] {Util.getDescriptorName(this.type1), name});
1911                }
1912                if (Flags.isStatic(access)) {
1913                        if (!Flags.isStatic(access2)) {
1914                                // report delta - static to non-static
1915                                this.addDelta(
1916                                                IDelta.FIELD_ELEMENT_TYPE,
1917                                                IDelta.CHANGED,
1918                                                IDelta.STATIC_TO_NON_STATIC,
1919                                                restrictions,
1920                                                access,
1921                                                access2,
1922                                                this.type1,
1923                                                name,
1924                                                new String[] {Util.getDescriptorName(this.type1), name});
1925                        }
1926                } else if (Flags.isStatic(access2)) {
1927                        // report delta - non-static to static
1928                        this.addDelta(
1929                                        IDelta.FIELD_ELEMENT_TYPE,
1930                                        IDelta.CHANGED,
1931                                        IDelta.NON_STATIC_TO_STATIC,
1932                                        restrictions,
1933                                        access,
1934                                        access2,
1935                                        this.type1,
1936                                        name,
1937                                        new String[] {Util.getDescriptorName(this.type1), name});
1938                }
1939                if (Flags.isTransient(access)) {
1940                        if (!Flags.isTransient(access2)) {
1941                                // report delta - transient to non-transient
1942                                this.addDelta(
1943                                                IDelta.FIELD_ELEMENT_TYPE,
1944                                                IDelta.CHANGED,
1945                                                IDelta.TRANSIENT_TO_NON_TRANSIENT,
1946                                                restrictions,
1947                                                access,
1948                                                access2,
1949                                                this.type1,
1950                                                name,
1951                                                new String[] {Util.getDescriptorName(this.type1), name});
1952                        }
1953                } else if (Flags.isTransient(access2)) {
1954                        // report delta - non-transient to transient
1955                        this.addDelta(
1956                                        IDelta.FIELD_ELEMENT_TYPE,
1957                                        IDelta.CHANGED,
1958                                        IDelta.NON_TRANSIENT_TO_TRANSIENT,
1959                                        restrictions,
1960                                        access,
1961                                        access2,
1962                                        this.type1,
1963                                        name,
1964                                        new String[] {Util.getDescriptorName(this.type1), name});
1965                }
1966                if (Flags.isVolatile(access)) {
1967                        if (!Flags.isVolatile(access2)) {
1968                                // report delta - volatile to non-volatile
1969                                this.addDelta(
1970                                                IDelta.FIELD_ELEMENT_TYPE,
1971                                                IDelta.CHANGED,
1972                                                IDelta.VOLATILE_TO_NON_VOLATILE,
1973                                                restrictions,
1974                                                access,
1975                                                access2,
1976                                                this.type1,
1977                                                name,
1978                                                new String[] {Util.getDescriptorName(this.type1), name});
1979                        }
1980                } else if (Flags.isVolatile(access2)) {
1981                        // report delta - non-volatile to volatile
1982                        this.addDelta(
1983                                        IDelta.FIELD_ELEMENT_TYPE,
1984                                        IDelta.CHANGED,
1985                                        IDelta.NON_VOLATILE_TO_VOLATILE,
1986                                        restrictions,
1987                                        access,
1988                                        access2,
1989                                        this.type1,
1990                                        name,
1991                                        new String[] {Util.getDescriptorName(this.type1), name});
1992                }
1993                if (Flags.isDeprecated(access)) {
1994                        if (!Flags.isDeprecated(access2)) {
1995                                this.addDelta(
1996                                                IDelta.FIELD_ELEMENT_TYPE,
1997                                                IDelta.REMOVED,
1998                                                IDelta.DEPRECATION,
1999                                                restrictions,
2000                                                access,
2001                                                access2,
2002                                                this.type1,
2003                                                name,
2004                                                new String[] {Util.getDescriptorName(this.type1), name});
2005                        }
2006                } else if (Flags.isDeprecated(access2)) {
2007                        // report delta - non-volatile to volatile
2008                        this.addDelta(
2009                                        IDelta.FIELD_ELEMENT_TYPE,
2010                                        IDelta.ADDED,
2011                                        IDelta.DEPRECATION,
2012                                        restrictions,
2013                                        access,
2014                                        access2,
2015                                        this.type1,
2016                                        name,
2017                                        new String[] {Util.getDescriptorName(this.type1), name});
2018                }
2019                if (field.getConstantValue() != null) {
2020                        if (field2.getConstantValue() == null) {
2021                                if (!changeFinalToNonFinal) {
2022                                        // report delta - removal of constant value
2023                                        this.addDelta(
2024                                                        IDelta.FIELD_ELEMENT_TYPE,
2025                                                        IDelta.REMOVED,
2026                                                        IDelta.VALUE,
2027                                                        restrictions,
2028                                                        access,
2029                                                        access2,
2030                                                        this.type1,
2031                                                        name,
2032                                                        new String[] {Util.getDescriptorName(this.type1), name, String.valueOf(field.getConstantValue())});
2033                                }
2034                        } else if (!field.getConstantValue().equals(field2.getConstantValue())) {
2035                                // report delta - modified constant value
2036                                this.addDelta(
2037                                                IDelta.FIELD_ELEMENT_TYPE,
2038                                                IDelta.CHANGED,
2039                                                IDelta.VALUE,
2040                                                restrictions,
2041                                                access,
2042                                                access2,
2043                                                this.type1,
2044                                                name,
2045                                                new String[] {Util.getDescriptorName(this.type1), name, String.valueOf(field.getConstantValue())});
2046                        }
2047                } else if (field2.getConstantValue() != null) {
2048                        // report delta
2049                        this.addDelta(
2050                                        IDelta.FIELD_ELEMENT_TYPE,
2051                                        IDelta.ADDED,
2052                                        IDelta.VALUE,
2053                                        restrictions,
2054                                        access,
2055                                        access2,
2056                                        this.type1,
2057                                        name,
2058                                        new String[] {Util.getDescriptorName(this.type1), name, String.valueOf(field2.getConstantValue())});
2059                }
2060        }
2061        private void getDeltaForMethod(IApiMethod method) {
2062                int access = method.getModifiers();
2063                if (Flags.isSynthetic(access)) {
2064                        // we ignore synthetic methods
2065                        return;
2066                }
2067                String name = method.getName();
2068                String descriptor = method.getSignature();
2069                String key = getKeyForMethod(method, this.type1);
2070                IApiMethod method2 = this.type2.getMethod(name, descriptor);
2071                String methodDisplayName = getMethodDisplayName(method, this.type1);
2072                if (method2 == null) {
2073                        if (method.isClassInitializer()) {
2074                                // report delta: removal of a clinit method
2075                                this.addDelta(
2076                                                getElementType(this.type1),
2077                                                IDelta.REMOVED,
2078                                                IDelta.CLINIT,
2079                                                this.currentDescriptorRestrictions,
2080                                                access,
2081                                                0,
2082                                                this.type1,
2083                                                this.type1.getName(),
2084                                                Util.getDescriptorName(type1));
2085                                return;
2086                        } else if (Flags.isPrivate(access)
2087                                        || Util.isDefault(access)) {
2088                                this.addDelta(
2089                                                getElementType(this.type1),
2090                                                IDelta.REMOVED,
2091                                                getTargetType(method),
2092                                                Flags.isAbstract(this.type2.getModifiers()) ? this.currentDescriptorRestrictions | RestrictionModifiers.NO_INSTANTIATE : this.currentDescriptorRestrictions,
2093                                                access,
2094                                                0,
2095                                                this.type1,
2096                                                getKeyForMethod(method, this.type1),
2097                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2098                                return;
2099                        }
2100                        // if null we need to walk the hierarchy of descriptor2
2101                        boolean found = false;
2102                        if (this.component2 != null && !method.isConstructor()) {
2103                                if (this.type1.isInterface()) {
2104                                        Set interfacesSet = getInterfacesSet(this.type2);
2105                                        if (interfacesSet != null && isStatusOk()) {
2106                                                for (Iterator iterator = interfacesSet.iterator(); iterator.hasNext();) {
2107                                                        IApiType superTypeDescriptor = (IApiType) iterator.next();
2108                                                        IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
2109                                                        if (method3 == null) {
2110                                                                continue;
2111                                                        } else {
2112                                                                // interface method can only be public
2113                                                                // method has been move up in the hierarchy - report the delta and abort loop
2114                                                                this.addDelta(
2115                                                                                getElementType(this.type1),
2116                                                                                IDelta.REMOVED,
2117                                                                                IDelta.METHOD_MOVED_UP,
2118                                                                                this.currentDescriptorRestrictions,
2119                                                                                access,
2120                                                                                method3.getModifiers(),
2121                                                                                this.type1,
2122                                                                                getKeyForMethod(method3, this.type1),
2123                                                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2124                                                                found = true;
2125                                                                break;
2126                                                        }
2127                                                }
2128                                        }
2129                                } else {
2130                                        List superclassList = getSuperclassList(this.type2, true);
2131                                        if (superclassList != null && isStatusOk()) {
2132                                                loop: for (Iterator iterator = superclassList.iterator(); iterator.hasNext();) {
2133                                                        IApiType superTypeDescriptor = (IApiType) iterator.next();
2134                                                        IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
2135                                                        if (method3 == null) {
2136                                                                continue;
2137                                                        } else {
2138                                                                int access3 = method3.getModifiers();
2139                                                                if (Flags.isPublic(access3)
2140                                                                                || Flags.isProtected(access3)) {
2141                                                                        // method has been move up in the hierarchy - report the delta and abort loop
2142                                                                        // TODO need to make the distinction between methods that need to be re-implemented and methods that don't
2143                                                                        this.addDelta(
2144                                                                                        getElementType(this.type1),
2145                                                                                        IDelta.REMOVED,
2146                                                                                        IDelta.METHOD_MOVED_UP,
2147                                                                                        this.currentDescriptorRestrictions,
2148                                                                                        access,
2149                                                                                        access3,
2150                                                                                        this.type1,
2151                                                                                        getKeyForMethod(method3, this.type1),
2152                                                                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2153                                                                        found = true;
2154                                                                        break loop;
2155                                                                }
2156                                                        }
2157                                                }
2158                                        }
2159                                }
2160                        }
2161                        if (!found) {
2162                                if ((this.visibilityModifiers == VisibilityModifiers.API) && component.hasApiDescription()) {
2163                                        // check if this method should be removed because it is tagged as @noreference
2164                                        IApiDescription apiDescription = null;
2165                                        try {
2166                                                apiDescription = this.component.getApiDescription();
2167                                        } catch (CoreException e) {
2168                                                reportStatus(e);
2169                                        }
2170                                        if (apiDescription != null) {
2171                                                IApiAnnotations apiAnnotations = apiDescription.resolveAnnotations(method.getHandle());
2172                                                if (apiAnnotations != null) {
2173                                                        int restrictions = apiAnnotations.getRestrictions();
2174                                                        if (RestrictionModifiers.isReferenceRestriction(restrictions)) {
2175                                                                // if not found, but tagged as @noreference in reference we don't need to report 
2176                                                                // a removed method
2177                                                                return;
2178                                                        }
2179                                                }
2180                                        }
2181                                }
2182                                if (this.type1.isAnnotation()) {
2183                                        this.addDelta(
2184                                                        getElementType(this.type1),
2185                                                        IDelta.REMOVED,
2186                                                        method.getDefaultValue() != null ? IDelta.METHOD_WITH_DEFAULT_VALUE : IDelta.METHOD_WITHOUT_DEFAULT_VALUE,
2187                                                        this.currentDescriptorRestrictions,
2188                                                        access,
2189                                                        0,
2190                                                        this.type1,
2191                                                        getKeyForMethod(method, this.type1),
2192                                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2193                                } else {
2194                                        int restrictions = this.currentDescriptorRestrictions;
2195                                        if (RestrictionModifiers.isExtendRestriction(this.initialDescriptorRestrictions)
2196                                                        && !RestrictionModifiers.isExtendRestriction(this.currentDescriptorRestrictions)) {
2197                                                restrictions = this.initialDescriptorRestrictions;
2198                                        }
2199                                        this.addDelta(
2200                                                        getElementType(this.type1),
2201                                                        IDelta.REMOVED,
2202                                                        getTargetType(method),
2203                                                        Flags.isAbstract(this.type2.getModifiers()) ? restrictions | RestrictionModifiers.NO_INSTANTIATE : restrictions,
2204                                                        access,
2205                                                        0,
2206                                                        this.type1,
2207                                                        getKeyForMethod(method, this.type1),
2208                                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2209                                }
2210                        }
2211                        return;
2212                }
2213                int restrictions = this.currentDescriptorRestrictions;
2214                if (component2.hasApiDescription()) {
2215                        try {
2216                                IApiDescription apiDescription = this.component2.getApiDescription();
2217                                IApiAnnotations resolvedAPIDescription = apiDescription.resolveAnnotations(method2.getHandle());
2218                                if (resolvedAPIDescription != null) {
2219                                        restrictions |= resolvedAPIDescription.getRestrictions();
2220                                }
2221                        } catch (CoreException e) {
2222                                // ignore
2223                        }
2224                }
2225                int referenceRestrictions = this.initialDescriptorRestrictions;
2226                int access2 = method2.getModifiers();
2227                if (this.component.hasApiDescription()) {
2228                        // check if this method should be removed because it is tagged as @noreference
2229                        IApiDescription apiDescription = null;
2230                        try {
2231                                apiDescription = this.component.getApiDescription();
2232                        } catch (CoreException e) {
2233                                reportStatus(e);
2234                        }
2235                        if (apiDescription != null) {
2236                                IApiAnnotations apiAnnotations = apiDescription.resolveAnnotations(method.getHandle());
2237                                if (apiAnnotations != null) {
2238                                        referenceRestrictions |= apiAnnotations.getRestrictions();
2239                                }
2240                        }
2241                }
2242                if ((this.visibilityModifiers == VisibilityModifiers.API) && this.component.hasApiDescription()) {
2243                        if (RestrictionModifiers.isReferenceRestriction(referenceRestrictions)) {
2244                                // tagged as @noreference in the reference component
2245                                if (!RestrictionModifiers.isReferenceRestriction(restrictions)) {
2246                                        // no longer tagged as @noreference
2247                                        // report a method addition
2248                                        if (method.isConstructor()) {
2249                                                this.addDelta(
2250                                                                getElementType(this.type2),
2251                                                                IDelta.ADDED,
2252                                                                IDelta.CONSTRUCTOR,
2253                                                                this.currentDescriptorRestrictions,
2254                                                                access,
2255                                                                access2,
2256                                                                this.type1,
2257                                                                getKeyForMethod(method, this.type2),
2258                                                                new String[] {Util.getDescriptorName(this.type2), methodDisplayName});
2259                                        } else if (this.type2.isAnnotation()) {
2260                                                if (method.getDefaultValue() != null) {
2261                                                        this.addDelta(
2262                                                                        getElementType(this.type2),
2263                                                                        IDelta.ADDED,
2264                                                                        IDelta.METHOD_WITH_DEFAULT_VALUE,
2265                                                                        this.currentDescriptorRestrictions,
2266                                                                        access,
2267                                                                        access2,
2268                                                                        this.type1,
2269                                                                        getKeyForMethod(method, this.type2),
2270                                                                        new String[] {Util.getDescriptorName(this.type2), methodDisplayName });
2271                                                } else {
2272                                                        this.addDelta(
2273                                                                        getElementType(this.type2),
2274                                                                        IDelta.ADDED,
2275                                                                        IDelta.METHOD_WITHOUT_DEFAULT_VALUE,
2276                                                                        this.currentDescriptorRestrictions,
2277                                                                        access,
2278                                                                        access2,
2279                                                                        this.type1,
2280                                                                        getKeyForMethod(method, this.type2),
2281                                                                        new String[] {Util.getDescriptorName(this.type2), methodDisplayName });
2282                                                }
2283                                        } else {
2284                                                // check superclass
2285                                                // if null we need to walk the hierarchy of descriptor2
2286                                                boolean found = false;
2287                                                if (this.component2 != null) {
2288                                                        if (this.type1.isInterface()) {
2289                                                                Set interfacesSet = getInterfacesSet(this.type2);
2290                                                                if (interfacesSet != null && isStatusOk()) {
2291                                                                        for (Iterator iterator = interfacesSet.iterator(); iterator.hasNext();) {
2292                                                                                IApiType superTypeDescriptor = (IApiType) iterator.next();
2293                                                                                IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
2294                                                                                if (method3 == null) {
2295                                                                                        continue;
2296                                                                                } else {
2297                                                                                        // interface method can only be public
2298                                                                                        // method has been move up in the hierarchy - report the delta and abort loop
2299                                                                                        found = true;
2300                                                                                        break;
2301                                                                                }
2302                                                                        }
2303                                                                }
2304                                                        } else {
2305                                                                List superclassList = getSuperclassList(this.type2, true);
2306                                                                if (superclassList != null) {
2307                                                                        loop: for (Iterator iterator = superclassList.iterator(); iterator.hasNext();) {
2308                                                                                IApiType superTypeDescriptor = (IApiType) iterator.next();
2309                                                                                IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
2310                                                                                if (method3 == null) {
2311                                                                                        continue;
2312                                                                                } else {
2313                                                                                        int access3 = method3.getModifiers();
2314                                                                                        if (Flags.isPublic(access3)
2315                                                                                                        || Flags.isProtected(access3)) {
2316                                                                                                // method has been move up in the hierarchy - report the delta and abort loop
2317                                                                                                // TODO need to make the distinction between methods that need to be re-implemented and methods that don't
2318                                                                                                found = true;
2319                                                                                                break loop;
2320                                                                                        }
2321                                                                                }
2322                                                                        }
2323                                                                }
2324                                                        }
2325                                                }
2326                                                this.addDelta(
2327                                                                getElementType(this.type2),
2328                                                                IDelta.ADDED,
2329                                                                found ? IDelta.OVERRIDEN_METHOD : IDelta.METHOD,
2330                                                                this.currentDescriptorRestrictions,
2331                                                                access,
2332                                                                access2,
2333                                                                this.type1,
2334                                                                getKeyForMethod(method, this.type2),
2335                                                                new String[] {Util.getDescriptorName(this.type2), methodDisplayName });
2336                                        }
2337                                        return;
2338                                }
2339                        } else if (RestrictionModifiers.isReferenceRestriction(restrictions)) {
2340                                if (Flags.isPublic(access2) || Flags.isProtected(access2)) {
2341                                        // report that it is no longer an API method
2342                                        if (this.type2.isAnnotation()) {
2343                                                this.addDelta(
2344                                                                getElementType(this.type2),
2345                                                                IDelta.REMOVED,
2346                                                                method.getDefaultValue() != null ? IDelta.API_METHOD_WITH_DEFAULT_VALUE : IDelta.API_METHOD_WITHOUT_DEFAULT_VALUE,
2347                                                                this.currentDescriptorRestrictions,
2348                                                                access,
2349                                                                access2,
2350                                                                this.type1,
2351                                                                getKeyForMethod(method2, this.type2),
2352                                                                new String[] {Util.getDescriptorName(this.type2), methodDisplayName});
2353                                        } else if (Flags.isPublic(access) || Flags.isProtected(access)) {
2354                                                this.addDelta(
2355                                                                getElementType(this.type2),
2356                                                                IDelta.REMOVED,
2357                                                                method.isConstructor() ? IDelta.API_CONSTRUCTOR : IDelta.API_METHOD,
2358                                                                Flags.isAbstract(this.type2.getModifiers()) ? this.currentDescriptorRestrictions | RestrictionModifiers.NO_INSTANTIATE : this.currentDescriptorRestrictions,
2359                                                                access,
2360                                                                access2,
2361                                                                this.type1,
2362                                                                getKeyForMethod(method2, this.type2),
2363                                                                new String[] {Util.getDescriptorName(this.type2), methodDisplayName});
2364                                        }
2365                                        return;
2366                                }
2367                        }
2368                }
2369                if (this.component.hasApiDescription() && !method.isConstructor() && !method.isClassInitializer()
2370                                && !(type1.isInterface() || type1.isAnnotation())) {
2371                        if (restrictions != referenceRestrictions) {
2372                                if (!Flags.isFinal(access2)) {
2373                                        if (RestrictionModifiers.isOverrideRestriction(restrictions)
2374                                                        && !RestrictionModifiers.isOverrideRestriction(referenceRestrictions)) {
2375                                                        this.addDelta(
2376                                                                        getElementType(method),
2377                                                                        IDelta.ADDED,
2378                                                                        IDelta.RESTRICTIONS,
2379                                                                        restrictions,
2380                                                                        access,
2381                                                                        access2,
2382                                                                        this.type1,
2383                                                                        getKeyForMethod(method2, this.type2),
2384                                                                        new String[] {Util.getDescriptorName(this.type2), methodDisplayName});
2385                                        }
2386                                }
2387                        }
2388                }
2389                String[] names1 = method.getExceptionNames();
2390                List list1 = null;
2391                if (names1 != null) {
2392                        list1 = new ArrayList(names1.length);
2393                        for (int i = 0; i < names1.length; i++) {
2394                                list1.add(names1[i]);
2395                        }
2396                }
2397                String[] names2 = method2.getExceptionNames();
2398                List list2 = null;
2399                if (names2 != null) {
2400                        list2 = new ArrayList(names2.length);
2401                        for (int i = 0; i < names2.length; i++) {
2402                                list2.add(names2[i]);
2403                        }
2404                }
2405                if (names1 != null) {
2406                        if (names2 == null) {
2407                                // check all exception in method descriptor to see if they are checked or unchecked exceptions
2408                                loop: for (Iterator iterator = list1.iterator(); iterator.hasNext(); ) {
2409                                        String exceptionName = ((String) iterator.next()).replace('/', '.');
2410                                        if (isCheckedException(this.apiBaseline1, this.component, exceptionName)) {
2411                                                // report delta - removal of checked exception
2412                                                // TODO should we continue the loop for all remaining exceptions
2413                                                this.addDelta(
2414                                                                getElementType(method),
2415                                                                IDelta.REMOVED,
2416                                                                IDelta.CHECKED_EXCEPTION,
2417                                                                restrictions,
2418                                                                access,
2419                                                                access2,
2420                                                                this.type1,
2421                                                                key,
2422                                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2423                                                break loop;
2424                                        } else {
2425                                                // report delta - removal of unchecked exception
2426                                                this.addDelta(
2427                                                                getElementType(method),
2428                                                                IDelta.REMOVED,
2429                                                                IDelta.UNCHECKED_EXCEPTION,
2430                                                                restrictions,
2431                                                                access,
2432                                                                access2,
2433                                                                this.type1,
2434                                                                key,
2435                                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2436                                        }
2437                                }
2438                        } else {
2439                                // check if the exceptions are consistent for both descriptors
2440                                List removedExceptions = new ArrayList();
2441                                for (Iterator iterator = list1.iterator(); iterator.hasNext(); ) {
2442                                        String exceptionName = ((String) iterator.next()).replace('/', '.');
2443                                        if (!list2.remove(exceptionName)) {
2444                                                // this means that the exceptionName was not found inside the new set of exceptions
2445                                                // so it has been removed
2446                                                removedExceptions.add(exceptionName);
2447                                        }
2448                                }
2449                                if (removedExceptions.size() != 0) {
2450                                        loop: for (Iterator iterator = removedExceptions.iterator(); iterator.hasNext(); ) {
2451                                                String exceptionName = ((String) iterator.next()).replace('/', '.');
2452                                                if (isCheckedException(this.apiBaseline1, this.component, exceptionName)) {
2453                                                        // report delta - removal of checked exception
2454                                                        // TODO should we continue the loop for all remaining exceptions
2455                                                        this.addDelta(
2456                                                                        getElementType(method),
2457                                                                        IDelta.REMOVED,
2458                                                                        IDelta.CHECKED_EXCEPTION,
2459                                                                        restrictions,
2460                                                                        access,
2461                                                                        access2,
2462                                                                        this.type1,
2463                                                                        key,
2464                                                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2465                                                        break loop;
2466                                                } else {
2467                                                        // report delta - removal of unchecked exception
2468                                                        this.addDelta(
2469                                                                        getElementType(method),
2470                                                                        IDelta.REMOVED,
2471                                                                        IDelta.UNCHECKED_EXCEPTION,
2472                                                                        restrictions,
2473                                                                        access,
2474                                                                        access2,
2475                                                                        this.type1,
2476                                                                        key,
2477                                                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2478                                                }
2479                                        }
2480                                }
2481                                loop: for (Iterator iterator = list2.iterator(); iterator.hasNext(); ) {
2482                                        String exceptionName = ((String) iterator.next()).replace('/', '.');
2483                                        if (isCheckedException(this.apiBaseline2, this.component2, exceptionName)) {
2484                                                // report delta - addition of checked exception
2485                                                // TODO should we continue the loop for all remaining exceptions
2486                                                this.addDelta(
2487                                                                getElementType(method),
2488                                                                IDelta.ADDED,
2489                                                                IDelta.CHECKED_EXCEPTION,
2490                                                                restrictions,
2491                                                                access,
2492                                                                access2,
2493                                                                this.type1,
2494                                                                key,
2495                                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2496                                                break loop;
2497                                        } else {
2498                                                // report delta - addition of unchecked exception
2499                                                this.addDelta(
2500                                                                getElementType(method),
2501                                                                IDelta.ADDED,
2502                                                                IDelta.UNCHECKED_EXCEPTION,
2503                                                                restrictions,
2504                                                                access,
2505                                                                access2,
2506                                                                this.type1,
2507                                                                key,
2508                                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2509                                        }
2510                                }
2511                        }
2512                } else if (names2 != null) {
2513                        // check all exception in method descriptor to see if they are checked or unchecked exceptions
2514                        loop: for (Iterator iterator = list2.iterator(); iterator.hasNext(); ) {
2515                                String exceptionName = ((String) iterator.next()).replace('/', '.');
2516                                if (isCheckedException(this.apiBaseline2, this.component2, exceptionName)) {
2517                                        // report delta - addition of checked exception
2518                                        this.addDelta(
2519                                                        getElementType(method),
2520                                                        IDelta.ADDED,
2521                                                        IDelta.CHECKED_EXCEPTION,
2522                                                        restrictions,
2523                                                        access,
2524                                                        access2,
2525                                                        this.type1,
2526                                                        key,
2527                                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2528                                        // TODO should we continue the loop for all remaining exceptions
2529                                        break loop;
2530                                } else {
2531                                        // report delta - addition of unchecked exception
2532                                        this.addDelta(
2533                                                        getElementType(method),
2534                                                        IDelta.ADDED,
2535                                                        IDelta.UNCHECKED_EXCEPTION,
2536                                                        restrictions,
2537                                                        access,
2538                                                        access2,
2539                                                        this.type1,
2540                                                        key,
2541                                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName, exceptionName});
2542                                }
2543                        }
2544                }
2545                if (Flags.isVarargs(access)) {
2546                        if (!Flags.isVarargs(access2)) {
2547                                // report delta: conversion from T... to T[] - break compatibility 
2548                                this.addDelta(
2549                                                getElementType(method),
2550                                                IDelta.CHANGED,
2551                                                IDelta.VARARGS_TO_ARRAY,
2552                                                restrictions,
2553                                                access,
2554                                                access2,
2555                                                this.type1,
2556                                                key,
2557                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2558                        }
2559                } else if (Flags.isVarargs(access2)) {
2560                        // report delta: conversion from T[] to T... compatible
2561                        this.addDelta(
2562                                        getElementType(method),
2563                                        IDelta.CHANGED,
2564                                        IDelta.ARRAY_TO_VARARGS,
2565                                        restrictions,
2566                                        access,
2567                                        access2,
2568                                        this.type1,
2569                                        key,
2570                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2571                }
2572                if (Flags.isProtected(access)) {
2573                        if (Flags.isPrivate(access2) || Util.isDefault(access2)) {
2574                                // report delta - decrease access: protected to default or private
2575                                this.addDelta(
2576                                                getElementType(method),
2577                                                IDelta.CHANGED,
2578                                                IDelta.DECREASE_ACCESS,
2579                                                restrictions,
2580                                                access,
2581                                                access2,
2582                                                this.type1,
2583                                                key,
2584                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2585                        } else if (Flags.isPublic(access2)) {
2586                                // report delta - increase access: protected to public
2587                                this.addDelta(
2588                                                getElementType(method),
2589                                                IDelta.CHANGED,
2590                                                IDelta.INCREASE_ACCESS,
2591                                                restrictions,
2592                                                access,
2593                                                access2,
2594                                                this.type1,
2595                                                key,
2596                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2597                        }
2598                } else if (Flags.isPublic(access)
2599                                && (Flags.isProtected(access2)
2600                                                || Flags.isPrivate(access2)
2601                                                || Util.isDefault(access2))) {
2602                        // report delta - decrease access: public to protected, default or private
2603                        this.addDelta(
2604                                        getElementType(method),
2605                                        IDelta.CHANGED,
2606                                        IDelta.DECREASE_ACCESS,
2607                                        restrictions,
2608                                        access,
2609                                        access2,
2610                                        this.type1,
2611                                        key,
2612                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2613                } else if (Util.isDefault(access)
2614                                && (Flags.isPublic(access2)
2615                                                || Flags.isProtected(access2))) {
2616                        this.addDelta(
2617                                        getElementType(method),
2618                                        IDelta.CHANGED,
2619                                        IDelta.INCREASE_ACCESS,
2620                                        restrictions,
2621                                        access,
2622                                        access2,
2623                                        this.type1,
2624                                        key,
2625                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2626                } else if (Flags.isPrivate(access)
2627                                && (Util.isDefault(access2)
2628                                                || Flags.isPublic(access2)
2629                                                || Flags.isProtected(access2))) {
2630                        this.addDelta(
2631                                        getElementType(method),
2632                                        IDelta.CHANGED,
2633                                        IDelta.INCREASE_ACCESS,
2634                                        restrictions,
2635                                        access,
2636                                        access2,
2637                                        this.type1,
2638                                        key,
2639                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2640                }
2641                if (Flags.isAbstract(access)) {
2642                        if (!Flags.isAbstract(access2)) {
2643                                // report delta - changed from abstract to non-abstract
2644                                this.addDelta(
2645                                                getElementType(method),
2646                                                IDelta.CHANGED,
2647                                                IDelta.ABSTRACT_TO_NON_ABSTRACT,
2648                                                restrictions,
2649                                                access,
2650                                                access2,
2651                                                this.type1,
2652                                                key,
2653                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2654                        }
2655                } else if (Flags.isAbstract(access2)){
2656                        // report delta - changed from non-abstract to abstract
2657                        this.addDelta(
2658                                        getElementType(method),
2659                                        IDelta.CHANGED,
2660                                        IDelta.NON_ABSTRACT_TO_ABSTRACT,
2661                                        restrictions,
2662                                        access,
2663                                        access2,
2664                                        this.type1,
2665                                        key,
2666                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2667                }
2668                if (Flags.isFinal(access)) {
2669                        if (!Flags.isFinal(access2)) {
2670                                // report delta - changed from final to non-final
2671                                this.addDelta(
2672                                                getElementType(method),
2673                                                IDelta.CHANGED,
2674                                                IDelta.FINAL_TO_NON_FINAL,
2675                                                restrictions,
2676                                                access,
2677                                                access2,
2678                                                this.type1,
2679                                                key,
2680                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2681                        }
2682                } else if (Flags.isFinal(access2)) {
2683                        int res = restrictions;
2684                        if (!RestrictionModifiers.isOverrideRestriction(res)) {
2685                                if (RestrictionModifiers.isExtendRestriction(this.currentDescriptorRestrictions)) {
2686                                        res = this.currentDescriptorRestrictions;
2687                                } else if (RestrictionModifiers.isExtendRestriction(this.initialDescriptorRestrictions)) {
2688                                        res = this.initialDescriptorRestrictions;
2689                                }
2690                                if (RestrictionModifiers.isOverrideRestriction(referenceRestrictions)) {
2691                                        // it is ok to remove @nooverride and add final at the same time
2692                                        res = referenceRestrictions;
2693                                }
2694                        }
2695                        // only report this delta is the method was visible
2696                        this.addDelta(
2697                                        getElementType(method2),
2698                                        IDelta.CHANGED,
2699                                        IDelta.NON_FINAL_TO_FINAL,
2700                                        res,
2701                                        access,
2702                                        access2,
2703                                        this.type1,
2704                                        key,
2705                                        new String[] {Util.getDescriptorName(this.type2), getMethodDisplayName(method2, this.type2)});
2706                }
2707                if (Flags.isStatic(access)) {
2708                        if (!Flags.isStatic(access2)) {
2709                                // report delta: change from static to non-static
2710                                this.addDelta(
2711                                                getElementType(method),
2712                                                IDelta.CHANGED,
2713                                                IDelta.STATIC_TO_NON_STATIC,
2714                                                restrictions,
2715                                                access,
2716                                                access2,
2717                                                this.type1,
2718                                                key,
2719                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2720                        }
2721                } else if (Flags.isStatic(access2)){
2722                        // report delta: change from non-static to static
2723                        this.addDelta(
2724                                        getElementType(method),
2725                                        IDelta.CHANGED,
2726                                        IDelta.NON_STATIC_TO_STATIC,
2727                                        restrictions,
2728                                        access,
2729                                        access2,
2730                                        this.type1,
2731                                        key,
2732                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2733                }
2734                if (Flags.isNative(access)) {
2735                        if (!Flags.isNative(access2)) {
2736                                // report delta: change from native to non-native
2737                                this.addDelta(
2738                                                getElementType(method),
2739                                                IDelta.CHANGED,
2740                                                IDelta.NATIVE_TO_NON_NATIVE,
2741                                                restrictions,
2742                                                access,
2743                                                access2,
2744                                                this.type1,
2745                                                key,
2746                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2747                        }
2748                } else if (Flags.isNative(access2)){
2749                        // report delta: change from non-native to native
2750                        this.addDelta(
2751                                        getElementType(method),
2752                                        IDelta.CHANGED,
2753                                        IDelta.NON_NATIVE_TO_NATIVE,
2754                                        restrictions,
2755                                        access,
2756                                        access2,
2757                                        this.type1,
2758                                        key,
2759                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2760                }
2761                if (Flags.isSynchronized(access)) {
2762                        if (!Flags.isSynchronized(access2)) {
2763                                // report delta: change from synchronized to non-synchronized
2764                                this.addDelta(
2765                                                getElementType(method),
2766                                                IDelta.CHANGED,
2767                                                IDelta.SYNCHRONIZED_TO_NON_SYNCHRONIZED,
2768                                                restrictions,
2769                                                access,
2770                                                access2,
2771                                                this.type1,
2772                                                key,
2773                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2774                        }
2775                } else if (Flags.isSynchronized(access2)){
2776                        // report delta: change from non-synchronized to synchronized
2777                        this.addDelta(
2778                                        getElementType(method),
2779                                        IDelta.CHANGED,
2780                                        IDelta.NON_SYNCHRONIZED_TO_SYNCHRONIZED,
2781                                        restrictions,
2782                                        access,
2783                                        access2,
2784                                        this.type1,
2785                                        key,
2786                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2787                }
2788                if (Flags.isDeprecated(access)) {
2789                        if (!Flags.isDeprecated(access2)) {
2790                                this.addDelta(
2791                                                getElementType(method),
2792                                                IDelta.REMOVED,
2793                                                IDelta.DEPRECATION,
2794                                                restrictions,
2795                                                access,
2796                                                access2,
2797                                                this.type1,
2798                                                key,
2799                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2800                        }
2801                } else if (Flags.isDeprecated(access2)) {
2802                        // report delta - non-volatile to volatile
2803                        this.addDelta(
2804                                        getElementType(method),
2805                                        IDelta.ADDED,
2806                                        IDelta.DEPRECATION,
2807                                        restrictions,
2808                                        access,
2809                                        access2,
2810                                        this.type1,
2811                                        key,
2812                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2813                }
2814                // check type parameters
2815                String signature1 = method.getGenericSignature();
2816                String signature2 = method2.getGenericSignature();
2817                checkGenericSignature(signature1, signature2, method, method2);
2818                
2819                if (method.getDefaultValue() == null) {
2820                        if (method2.getDefaultValue() != null) {
2821                                // report delta : default value has been added - compatible
2822                                this.addDelta(
2823                                                getElementType(method),
2824                                                IDelta.ADDED,
2825                                                IDelta.ANNOTATION_DEFAULT_VALUE,
2826                                                restrictions,
2827                                                access,
2828                                                access2,
2829                                                this.type1,
2830                                                key,
2831                                                new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2832                        }
2833                } else if (method2.getDefaultValue() == null) {
2834                        // report delta : default value has been removed - incompatible
2835                        this.addDelta(
2836                                        getElementType(method),
2837                                        IDelta.REMOVED,
2838                                        IDelta.ANNOTATION_DEFAULT_VALUE,
2839                                        restrictions,
2840                                        access,
2841                                        access2,
2842                                        this.type1,
2843                                        key,
2844                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2845                } else if (!method.getDefaultValue().equals(method2.getDefaultValue())) {
2846                        // report delta: default value has changed
2847                        this.addDelta(
2848                                        getElementType(method),
2849                                        IDelta.CHANGED,
2850                                        IDelta.ANNOTATION_DEFAULT_VALUE,
2851                                        restrictions,
2852                                        access,
2853                                        access2,
2854                                        this.type1,
2855                                        key,
2856                                        new String[] {Util.getDescriptorName(this.type1), methodDisplayName});
2857                }
2858        }
2859 
2860        /**
2861         * Returns the complete super-interface set for the given type descriptor or null, if it could not be
2862         * computed
2863         * @param type
2864         * @param apiComponent
2865         * @param profile
2866         * @return the complete super-interface set for the given descriptor, or <code>null</code>
2867         */
2868        private Set getInterfacesSet(IApiType type) {
2869                HashSet set = new HashSet();
2870                this.status = null;
2871                collectAllInterfaces(type, set);
2872                if (set.isEmpty()) {
2873                        return null;
2874                }
2875                return set;
2876        }
2877 
2878        private String getMethodDisplayName(IApiMethod method, IApiType type) {
2879                String methodName = null;
2880                if (method.isConstructor()) {
2881                        methodName = type.getSimpleName();
2882                } else {
2883                        methodName = method.getName();
2884                }
2885                String signature = null;
2886                String genericSignature = method.getGenericSignature();
2887                if (genericSignature != null) {
2888                        signature = genericSignature;
2889                } else {
2890                        signature = method.getSignature();
2891                }
2892                return Signature.toString(signature, methodName, null, false, false);
2893        }
2894 
2895        private SignatureDescriptor getSignatureDescriptor(String signature) {
2896                SignatureDescriptor signatureDescriptor = new SignatureDescriptor();
2897                SignatureReader signatureReader = new SignatureReader(signature);
2898                signatureReader.accept(new SignatureDecoder(signatureDescriptor));
2899                return signatureDescriptor;
2900        }
2901        private List getSuperclassList(IApiType type) {
2902                return getSuperclassList(type, false);
2903        }
2904        private List getSuperclassList(IApiType type, boolean includeObject) {
2905                return getSuperclassList(type, includeObject, false);
2906        }
2907        private List getSuperclassList(IApiType type, boolean includeObject, boolean includePrivate) {
2908                IApiType superClass = type;
2909                this.status = null;
2910                String superName = superClass.getSuperclassName();
2911                if (Util.isJavaLangObject(superName) && !includeObject) {
2912                        return null;
2913                }
2914                List list = new ArrayList();
2915                try {
2916                        while (superName != null && (!Util.isJavaLangObject(superName) || includeObject)) {
2917                                superClass = superClass.getSuperclass();
2918                                int visibility = VisibilityModifiers.PRIVATE;
2919                                IApiComponent superComponent = superClass.getApiComponent();
2920                                IApiDescription apiDescription = superComponent.getApiDescription();
2921                                IApiAnnotations elementDescription = apiDescription.resolveAnnotations(superClass.getHandle());
2922                                if (elementDescription != null) {
2923                                        visibility = elementDescription.getVisibility();
2924                                }
2925                                if (includePrivate || ((visibility & visibilityModifiers) != 0)) {
2926                                        list.add(superClass);
2927                                }
2928                                superName = superClass.getSuperclassName();
2929                        }
2930                } catch (CoreException e) {
2931                        reportStatus(e);
2932                }
2933                if (list.isEmpty()) return null;
2934                return list;
2935        }
2936        
2937        private void reportFieldAddition(IApiField field, IApiType type) {
2938                int access = field.getModifiers();
2939                String name = field.getName();
2940        
2941                if (Flags.isSynthetic(access)) {
2942                        // we ignore synthetic fields 
2943                        return;
2944                }
2945                if ((this.visibilityModifiers == VisibilityModifiers.API) && component2.hasApiDescription()) {
2946                        // check if this method should be removed because it is tagged as @noreference
2947                        IApiDescription apiDescription = null;
2948                        try {
2949                                apiDescription = this.component2.getApiDescription();
2950                        } catch (CoreException e) {
2951                                reportStatus(e);
2952                        }
2953                        if (apiDescription != null) {
2954                                IApiAnnotations apiAnnotations = apiDescription.resolveAnnotations(field.getHandle());
2955                                if (apiAnnotations != null) {
2956                                        int restrictions = apiAnnotations.getRestrictions();
2957                                        if (RestrictionModifiers.isReferenceRestriction(restrictions)) {
2958                                                // such a method is not seen as an API method
2959                                                return;
2960                                        }
2961                                }
2962                        }
2963                }
2964                if (field.isEnumConstant()) {
2965                        // report delta (addition of an enum constant - compatible
2966                        this.addDelta(
2967                                        getElementType(type),
2968                                        IDelta.ADDED,
2969                                        IDelta.ENUM_CONSTANT,
2970                                        this.currentDescriptorRestrictions,
2971                                        0,
2972                                        access,
2973                                        this.type1,
2974                                        name,
2975                                        new String[] {Util.getDescriptorName(type), name});
2976                } else {
2977                        this.addDelta(
2978                                        getElementType(type),
2979                                        IDelta.ADDED,
2980                                        IDelta.FIELD,
2981                                        this.currentDescriptorRestrictions,
2982                                        0,
2983                                        access,
2984                                        this.type1,
2985                                        name,
2986                                        new String[] {Util.getDescriptorName(type), name});
2987                }
2988        }
2989        private void reportMethodAddition(IApiMethod method, IApiType type) {
2990                int access = method.getModifiers();
2991                if (method.isClassInitializer()) {
2992                        // report delta: addition of clinit method
2993                        this.addDelta(
2994                                        getElementType(type),
2995                                        IDelta.ADDED,
2996                                        IDelta.CLINIT,
2997                                        this.currentDescriptorRestrictions,
2998                                        0,
2999                                        access,
3000                                        this.type1,
3001                                        type.getName(),
3002                                        Util.getDescriptorName(type1));
3003                        return;
3004                }
3005                if (Flags.isSynthetic(access)) {
3006                        // we ignore synthetic method
3007                        return;
3008                }
3009                if ((this.visibilityModifiers == VisibilityModifiers.API) && component2.hasApiDescription()) {
3010                        // check if this method should be removed because it is tagged as @noreference
3011                        IApiDescription apiDescription = null;
3012                        int restrictions = RestrictionModifiers.NO_RESTRICTIONS;
3013                        try {
3014                                apiDescription = this.component2.getApiDescription();
3015                        } catch (CoreException e) {
3016                                reportStatus(e);
3017                        }
3018                        if (apiDescription != null) {
3019                                IApiAnnotations apiAnnotations = apiDescription.resolveAnnotations(method.getHandle());
3020                                if (apiAnnotations != null) {
3021                                        restrictions = apiAnnotations.getRestrictions();
3022                                }
3023                        }
3024                        // check if this method should be removed because it is tagged as @noreference
3025                        if (RestrictionModifiers.isReferenceRestriction(restrictions)) {
3026                                // such a method is not seen as an API method
3027                                return;
3028                        }
3029                }
3030                String methodDisplayName = getMethodDisplayName(method, type);
3031                int restrictionsForMethodAddition = this.currentDescriptorRestrictions;
3032                if (Flags.isFinal(this.type2.getModifiers())) {
3033                        restrictionsForMethodAddition |= RestrictionModifiers.NO_EXTEND;
3034                }
3035                if (Flags.isPublic(access) || Flags.isProtected(access)) {
3036                        if (method.isConstructor()) {
3037                                this.addDelta(
3038                                                getElementType(type),
3039                                                IDelta.ADDED,
3040                                                IDelta.CONSTRUCTOR,
3041                                                restrictionsForMethodAddition,
3042                                                0,
3043                                                access,
3044                                                this.type1,
3045                                                getKeyForMethod(method, type),
3046                                                new String[] {Util.getDescriptorName(type), methodDisplayName});
3047                        } else if (type.isAnnotation()) {
3048                                if (method.getDefaultValue() != null) {
3049                                        this.addDelta(
3050                                                        getElementType(type),
3051                                                        IDelta.ADDED,
3052                                                        IDelta.METHOD_WITH_DEFAULT_VALUE,
3053                                                        restrictionsForMethodAddition,
3054                                                        0,
3055                                                        access,
3056                                                        this.type1,
3057                                                        getKeyForMethod(method, type),
3058                                                        new String[] {Util.getDescriptorName(type), methodDisplayName });
3059                                } else {
3060                                        this.addDelta(
3061                                                        getElementType(type),
3062                                                        IDelta.ADDED,
3063                                                        IDelta.METHOD_WITHOUT_DEFAULT_VALUE,
3064                                                        restrictionsForMethodAddition,
3065                                                        0,
3066                                                        access,
3067                                                        this.type1,
3068                                                        getKeyForMethod(method, type),
3069                                                        new String[] {Util.getDescriptorName(type), methodDisplayName });
3070                                }
3071                        } else {
3072                                // check superclass
3073                                // if null we need to walk the hierarchy of descriptor2
3074                                boolean found = false;
3075                                if (this.component2 != null) {
3076                                        String name = method.getName();
3077                                        String descriptor = method.getSignature();
3078                                        if (this.type1.isInterface()) {
3079                                                Set interfacesSet = getInterfacesSet(this.type2);
3080                                                if (interfacesSet != null && isStatusOk()) {
3081                                                        for (Iterator iterator = interfacesSet.iterator(); iterator.hasNext();) {
3082                                                                IApiType superTypeDescriptor = (IApiType) iterator.next();
3083                                                                IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
3084                                                                if (method3 == null) {
3085                                                                        continue;
3086                                                                } else {
3087                                                                        // interface method can only be public
3088                                                                        // method has been move up in the hierarchy - report the delta and abort loop
3089                                                                        found = true;
3090                                                                        break;
3091                                                                }
3092                                                        }
3093                                                }
3094                                        } else {
3095                                                List superclassList = getSuperclassList(this.type2, true);
3096                                                if (superclassList != null && isStatusOk()) {
3097                                                        loop: for (Iterator iterator = superclassList.iterator(); iterator.hasNext();) {
3098                                                                IApiType superTypeDescriptor = (IApiType) iterator.next();
3099                                                                IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
3100                                                                if (method3 == null) {
3101                                                                        continue;
3102                                                                } else {
3103                                                                        int access3 = method3.getModifiers();
3104                                                                        if (Flags.isPublic(access3)
3105                                                                                        || Flags.isProtected(access3)) {
3106                                                                                // method has been move up in the hierarchy - report the delta and abort loop
3107                                                                                // TODO need to make the distinction between methods that need to be re-implemented and methods that don't
3108                                                                                found = true;
3109                                                                                break loop;
3110                                                                        }
3111                                                                }
3112                                                        }
3113                                                }
3114                                        }
3115                                }
3116                                if (!found) {
3117                                        // check if the method has been pushed down
3118                                        // if null we need to walk the hierarchy of descriptor
3119                                        if (this.component != null) {
3120                                                String name = method.getName();
3121                                                String descriptor = method.getSignature();
3122                                                if (this.type1.isInterface()) {
3123                                                        Set interfacesSet = getInterfacesSet(this.type1);
3124                                                        if (interfacesSet != null && isStatusOk()) {
3125                                                                for (Iterator iterator = interfacesSet.iterator(); iterator.hasNext();) {
3126                                                                        IApiType superTypeDescriptor = (IApiType) iterator.next();
3127                                                                        IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
3128                                                                        if (method3 == null) {
3129                                                                                continue;
3130                                                                        } else {
3131                                                                                // interface method can only be public
3132                                                                                // method has been move up in the hierarchy - report the delta and abort loop
3133                                                                                found = true;
3134                                                                                break;
3135                                                                        }
3136                                                                }
3137                                                        }
3138                                                } else {
3139                                                        List superclassList = getSuperclassList(this.type1, true);
3140                                                        if (superclassList != null && isStatusOk()) {
3141                                                                loop: for (Iterator iterator = superclassList.iterator(); iterator.hasNext();) {
3142                                                                        IApiType superTypeDescriptor = (IApiType) iterator.next();
3143                                                                        IApiMethod method3 = superTypeDescriptor.getMethod(name, descriptor);
3144                                                                        if (method3 == null) {
3145                                                                                continue;
3146                                                                        } else {
3147                                                                                int access3 = method3.getModifiers();
3148                                                                                if (Flags.isPublic(access3)
3149                                                                                                || Flags.isProtected(access3)) {
3150                                                                                        // method has been pushed down in the hierarchy - report the delta and abort loop
3151                                                                                        // TODO need to make the distinction between methods that need to be re-implemented and methods that don't
3152                                                                                        found = true;
3153                                                                                        break loop;
3154                                                                                }
3155                                                                        }
3156                                                                }
3157                                                        }
3158                                                }
3159                                        }
3160                                        this.addDelta(
3161                                                        getElementType(type),
3162                                                        IDelta.ADDED,
3163                                                        found ? IDelta.METHOD_MOVED_DOWN : IDelta.METHOD,
3164                                                        restrictionsForMethodAddition,
3165                                                        0,
3166                                                        method.getModifiers(),
3167                                                        this.type1,
3168                                                        getKeyForMethod(method, type),
3169                                                        new String[] {Util.getDescriptorName(type), methodDisplayName });
3170                                } else {
3171                                        this.addDelta(
3172                                                        getElementType(type),
3173                                                        IDelta.ADDED,
3174                                                        found ? IDelta.OVERRIDEN_METHOD : IDelta.METHOD,
3175                                                        restrictionsForMethodAddition,
3176                                                        0,
3177                                                        method.getModifiers(),
3178                                                        this.type1,
3179                                                        getKeyForMethod(method, type),
3180                                                        new String[] {Util.getDescriptorName(type), methodDisplayName });
3181                                }
3182                        }
3183                } else {
3184                        this.addDelta(
3185                                        getElementType(type),
3186                                        IDelta.ADDED,
3187                                        method.isConstructor() ? IDelta.CONSTRUCTOR : IDelta.METHOD,
3188                                        restrictionsForMethodAddition,
3189                                        0,
3190                                        method.getModifiers(),
3191                                        this.type1,
3192                                        getKeyForMethod(method, type),
3193                                        new String[] {Util.getDescriptorName(type), methodDisplayName });
3194                }
3195        }
3196        
3197        private String getKeyForMethod(IApiMethod method, IApiType type) {
3198                StringBuffer buffer = new StringBuffer();
3199                if (method.isConstructor()) {
3200                        String name = type.getName();
3201                        int index = name.lastIndexOf('.');
3202                        int dollarIndex = name.lastIndexOf('$');
3203                        if (dollarIndex != -1 && type.isMemberType()) {
3204                                buffer.append(type.getName().substring(dollarIndex + 1));
3205                        } else {
3206                                buffer.append(type.getName().substring(index + 1));
3207                        }
3208                } else {
3209                        buffer.append(method.getName());
3210                }
3211                String genericSignature = method.getGenericSignature();
3212                if (genericSignature != null) {
3213                        buffer.append(genericSignature);
3214                } else {
3215                        buffer.append(method.getSignature());
3216                }
3217                return String.valueOf(buffer);
3218        }
3219 
3220        private static boolean isAPI(int visibility,
3221                        IApiType memberTypeDescriptor) {
3222                int access = memberTypeDescriptor.getModifiers();
3223                return VisibilityModifiers.isAPI(visibility)
3224                        && (Flags.isPublic(access) || Flags.isProtected(access));
3225        }
3226        
3227        private IApiTypeRoot getType(String typeName, IApiComponent component, IApiBaseline profile) throws CoreException {
3228                String packageName = Signatures.getPackageName(typeName);
3229                IApiComponent[] components = profile.resolvePackage(component, packageName);
3230                if (components == null) {
3231                        String msg = MessageFormat.format(ComparatorMessages.ClassFileComparator_1, new String[] {packageName, profile.getName(), component.getId()});
3232                        if (Debug) {
3233                                System.err.println("TYPE LOOKUP: "+msg); //$NON-NLS-1$
3234                        }
3235                        reportStatus(new Status(IStatus.ERROR, component.getId(), msg));
3236                        return null;
3237                }
3238                IApiTypeRoot result = Util.getClassFile(components, typeName); 
3239                if (result == null) {
3240                        String msg = MessageFormat.format(ComparatorMessages.ClassFileComparator_2, new String[] {typeName, profile.getName(), component.getId()});
3241                        if (Debug) {
3242                                System.err.println("TYPE LOOKUP: "+msg); //$NON-NLS-1$
3243                        }
3244                        reportStatus(new Status(IStatus.ERROR, component.getId(), msg));
3245                        return null;
3246                }
3247                return result;
3248        }
3249        
3250        /**
3251         * Returns the delta element type code for the given type.
3252         * Translates a type to interface, class, emum or annotation.
3253         * 
3254         * @param type
3255         * @return delta element type
3256         */
3257        private int getElementType(IApiType type) {
3258                if (type.isAnnotation()) {
3259                        return IDelta.ANNOTATION_ELEMENT_TYPE;
3260                } 
3261                if (type.isEnum()) {
3262                        return IDelta.ENUM_ELEMENT_TYPE;
3263                }
3264                if (type.isInterface()) {
3265                        return IDelta.INTERFACE_ELEMENT_TYPE;
3266                }
3267                return IDelta.CLASS_ELEMENT_TYPE;
3268        }
3269        
3270        /**
3271         * Returns the delta element type code for the given method.
3272         * Translates a method to constructor or method.
3273         * 
3274         * @param method
3275         * @return delta element type
3276         */
3277        private int getElementType(IApiMethod method) {
3278                if (method.isConstructor()) {
3279                        return IDelta.CONSTRUCTOR_ELEMENT_TYPE;
3280                }
3281                return IDelta.METHOD_ELEMENT_TYPE;
3282        }
3283        
3284        /**
3285         * Returns the delta type code for the given method when it is the target of a remove/add.
3286         * Translates a method to constructor or method.
3287         * 
3288         * @param method
3289         * @return delta type
3290         */
3291        private int getTargetType(IApiMethod method) {
3292                if (method.isConstructor()) {
3293                        return IDelta.CONSTRUCTOR;
3294                }
3295                return IDelta.METHOD;
3296        }        
3297        
3298        /**
3299         * Translates a member to its delta element type code.
3300         * 
3301         * @param member
3302         * @return delta element type code
3303         */
3304        private int getElementType(IApiMember member) {
3305                switch (member.getType()) {
3306                case IApiElement.TYPE:
3307                        return getElementType((IApiType)member);
3308                case IApiElement.METHOD:
3309                        return getElementType((IApiMethod)member);
3310                }
3311                return IDelta.FIELD_ELEMENT_TYPE;
3312        }
3313}

[all classes][org.eclipse.pde.api.tools.internal.comparator]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov