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

COVERAGE SUMMARY FOR SOURCE FILE [UseReportConverter.java]

nameclass, %method, %block, %line, %
UseReportConverter.java0%   (0/10)0%   (0/71)0%   (0/4564)0%   (0/914)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class UseReportConverter0%   (0/1)0%   (0/43)0%   (0/3332)0%   (0/670)
<static initializer> 0%   (0/1)0%   (0/65)0%   (0/18)
UseReportConverter (String, String, String []): void 0%   (0/1)0%   (0/85)0%   (0/23)
applyXSLT (File, File, File): void 0%   (0/1)0%   (0/51)0%   (0/10)
applyXSLT (Source, File, File): void 0%   (0/1)0%   (0/21)0%   (0/6)
composeName (String, String): String 0%   (0/1)0%   (0/24)0%   (0/3)
convert (String, IProgressMonitor): void 0%   (0/1)0%   (0/239)0%   (0/56)
extractLinkFrom (File, String): String 0%   (0/1)0%   (0/33)0%   (0/7)
getAdditionalIndexInfo (boolean): String 0%   (0/1)0%   (0/2)0%   (0/1)
getAdditionalReferencedTypeInformation (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getDisplayName (IElementDescriptor, boolean): String 0%   (0/1)0%   (0/43)0%   (0/15)
getHTMLFileLocation (File, File): String 0%   (0/1)0%   (0/36)0%   (0/9)
getIndexHeader (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getIndexTitle (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getMetadata (): UseMetadata 0%   (0/1)0%   (0/167)0%   (0/47)
getMissingBundles (File): String [] 0%   (0/1)0%   (0/18)0%   (0/3)
getMissingBundlesHeader (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getNameFromXMLFilename (File): String 0%   (0/1)0%   (0/34)0%   (0/6)
getNoReportsInformation (): String 0%   (0/1)0%   (0/17)0%   (0/3)
getNotSearchedXSLPath (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getParser (): SAXParser 0%   (0/1)0%   (0/35)0%   (0/10)
getReferenceTableEntry (UseReportConverter$CountGroup, String, String): String 0%   (0/1)0%   (0/83)0%   (0/10)
getReferencedTypeHeader (String): String 0%   (0/1)0%   (0/4)0%   (0/1)
getReferencedTypeTitle (String): String 0%   (0/1)0%   (0/4)0%   (0/1)
getReferencesTable (UseReportConverter$Member): String 0%   (0/1)0%   (0/170)0%   (0/31)
getReferencesTableHeader (String): String 0%   (0/1)0%   (0/139)0%   (0/22)
getReportIndex (): File 0%   (0/1)0%   (0/3)0%   (0/1)
getTypeCountSummary (String, UseReportConverter$CountGroup, int): String 0%   (0/1)0%   (0/41)0%   (0/4)
getTypeDetails (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getTypeDetailsHeader (): String 0%   (0/1)0%   (0/2)0%   (0/1)
getTypeHeader (String): String 0%   (0/1)0%   (0/5)0%   (0/1)
getTypeTitle (String): String 0%   (0/1)0%   (0/5)0%   (0/1)
readPatterns (Element): String [] 0%   (0/1)0%   (0/33)0%   (0/8)
setDebug (boolean): void 0%   (0/1)0%   (0/9)0%   (0/2)
tranformXml (File [], File): void 0%   (0/1)0%   (0/52)0%   (0/11)
writeIndexPage (List, File): void 0%   (0/1)0%   (0/270)0%   (0/52)
writeMetaPage (File): void 0%   (0/1)0%   (0/128)0%   (0/29)
writeMetaTag (StringBuffer, String, String): void 0%   (0/1)0%   (0/13)0%   (0/2)
writeMetadataHeaders (StringBuffer): void 0%   (0/1)0%   (0/6)0%   (0/2)
writeMetadataSummary (StringBuffer): void 0%   (0/1)0%   (0/484)0%   (0/80)
writeMissingBundlesPage (File): void 0%   (0/1)0%   (0/229)0%   (0/43)
writeNotSearchedPage (File): void 0%   (0/1)0%   (0/110)0%   (0/21)
writeReferencedMemberPage (UseReportConverter$Report, List): void 0%   (0/1)0%   (0/412)0%   (0/75)
writeTypePage (TreeMap, UseReportConverter$Type, File, String): void 0%   (0/1)0%   (0/248)0%   (0/49)
     
class UseReportConverter$10%   (0/1)0%   (0/2)0%   (0/94)0%   (0/19)
UseReportConverter$1 (): void 0%   (0/1)0%   (0/3)0%   (0/2)
compare (Object, Object): int 0%   (0/1)0%   (0/91)0%   (0/17)
     
class UseReportConverter$20%   (0/1)0%   (0/2)0%   (0/14)0%   (0/3)
UseReportConverter$2 (UseReportConverter): void 0%   (0/1)0%   (0/6)0%   (0/2)
compare (Object, Object): int 0%   (0/1)0%   (0/8)0%   (0/1)
     
class UseReportConverter$CountGroup0%   (0/1)0%   (0/7)0%   (0/138)0%   (0/36)
UseReportConverter$CountGroup (): void 0%   (0/1)0%   (0/48)0%   (0/16)
getTotalApiRefCount (): int 0%   (0/1)0%   (0/9)0%   (0/1)
getTotalFragmentPermissibleRefCount (): int 0%   (0/1)0%   (0/9)0%   (0/1)
getTotalInternalRefCount (): int 0%   (0/1)0%   (0/9)0%   (0/1)
getTotalOtherRefCount (): int 0%   (0/1)0%   (0/9)0%   (0/1)
getTotalPermissableRefCount (): int 0%   (0/1)0%   (0/9)0%   (0/1)
getTotalRefCount (): int 0%   (0/1)0%   (0/45)0%   (0/15)
     
class UseReportConverter$Member0%   (0/1)0%   (0/1)0%   (0/20)0%   (0/6)
UseReportConverter$Member (IElementDescriptor): void 0%   (0/1)0%   (0/20)0%   (0/6)
     
class UseReportConverter$MissingHandler0%   (0/1)0%   (0/3)0%   (0/50)0%   (0/13)
<static initializer> 0%   (0/1)0%   (0/3)0%   (0/2)
UseReportConverter$MissingHandler (): void 0%   (0/1)0%   (0/8)0%   (0/2)
startElement (String, String, String, Attributes): void 0%   (0/1)0%   (0/39)0%   (0/10)
     
class UseReportConverter$Reference0%   (0/1)0%   (0/1)0%   (0/21)0%   (0/7)
UseReportConverter$Reference (IElementDescriptor, int, int): void 0%   (0/1)0%   (0/21)0%   (0/7)
     
class UseReportConverter$Report0%   (0/1)0%   (0/1)0%   (0/17)0%   (0/4)
UseReportConverter$Report (): void 0%   (0/1)0%   (0/17)0%   (0/4)
     
class UseReportConverter$Type0%   (0/1)0%   (0/1)0%   (0/14)0%   (0/5)
UseReportConverter$Type (IElementDescriptor): void 0%   (0/1)0%   (0/14)0%   (0/5)
     
class UseReportConverter$Visitor0%   (0/1)0%   (0/10)0%   (0/864)0%   (0/154)
UseReportConverter$Visitor (UseReportConverter): void 0%   (0/1)0%   (0/33)0%   (0/7)
acceptReference (IMemberDescriptor): boolean 0%   (0/1)0%   (0/29)0%   (0/5)
endVisit (IComponentDescriptor): void 0%   (0/1)0%   (0/89)0%   (0/17)
endVisitMember (IMemberDescriptor): void 0%   (0/1)0%   (0/41)0%   (0/9)
endVisitReferencingComponent (IComponentDescriptor): void 0%   (0/1)0%   (0/12)0%   (0/3)
getEnclosingDescriptor (IMemberDescriptor): IReferenceTypeDescriptor 0%   (0/1)0%   (0/11)0%   (0/4)
visitComponent (IComponentDescriptor): boolean 0%   (0/1)0%   (0/23)0%   (0/4)
visitMember (IMemberDescriptor): boolean 0%   (0/1)0%   (0/77)0%   (0/16)
visitReference (int, IMemberDescriptor, int, int): void 0%   (0/1)0%   (0/541)0%   (0/87)
visitReferencingComponent (IComponentDescriptor): boolean 0%   (0/1)0%   (0/8)0%   (0/2)

1/*******************************************************************************
2 * Copyright (c) 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.search;
12 
13import java.io.BufferedInputStream;
14import java.io.BufferedWriter;
15import java.io.File;
16import java.io.FileWriter;
17import java.io.IOException;
18import java.io.InputStream;
19import java.io.PrintWriter;
20import java.util.ArrayList;
21import java.util.Collections;
22import java.util.Comparator;
23import java.util.HashMap;
24import java.util.Iterator;
25import java.util.List;
26import java.util.StringTokenizer;
27import java.util.TreeMap;
28import java.util.TreeSet;
29import java.util.Map.Entry;
30import java.util.regex.Pattern;
31import java.util.regex.PatternSyntaxException;
32 
33import javax.xml.parsers.ParserConfigurationException;
34import javax.xml.parsers.SAXParser;
35import javax.xml.parsers.SAXParserFactory;
36import javax.xml.transform.Result;
37import javax.xml.transform.Source;
38import javax.xml.transform.Transformer;
39import javax.xml.transform.TransformerException;
40import javax.xml.transform.TransformerFactory;
41import javax.xml.transform.stream.StreamResult;
42import javax.xml.transform.stream.StreamSource;
43 
44import org.eclipse.core.runtime.CoreException;
45import org.eclipse.core.runtime.IPath;
46import org.eclipse.core.runtime.IProgressMonitor;
47import org.eclipse.core.runtime.Path;
48import org.eclipse.core.runtime.SubMonitor;
49import org.eclipse.jdt.core.Signature;
50import org.eclipse.osgi.util.NLS;
51import org.eclipse.pde.api.tools.internal.IApiXmlConstants;
52import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
53import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
54import org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor;
55import org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor;
56import org.eclipse.pde.api.tools.internal.provisional.descriptors.IFieldDescriptor;
57import org.eclipse.pde.api.tools.internal.provisional.descriptors.IMemberDescriptor;
58import org.eclipse.pde.api.tools.internal.provisional.descriptors.IMethodDescriptor;
59import org.eclipse.pde.api.tools.internal.provisional.descriptors.IReferenceTypeDescriptor;
60import org.eclipse.pde.api.tools.internal.util.Signatures;
61import org.eclipse.pde.api.tools.internal.util.Util;
62import org.w3c.dom.Element;
63import org.w3c.dom.NodeList;
64import org.xml.sax.Attributes;
65import org.xml.sax.SAXException;
66import org.xml.sax.helpers.DefaultHandler;
67 
68/**
69 * This class converts a collection of API use report XML files
70 * from a given location to a corresponding collection of
71 * HTML in a given location
72 * 
73 * @since 1.0.1
74 */
75public class UseReportConverter extends HTMLConvertor {
76 
77        /**
78         * Use visitor to write the reports
79         */
80        class Visitor extends UseScanVisitor {
81                
82                ArrayList reports = new ArrayList();
83                Report currentreport = null;
84                Type currenttype = null, currentreferee = null;
85                Member currentmember = null;
86                HashMap keys = new HashMap();
87                ArrayList referees = new ArrayList();
88                
89                /**
90                 * Returns if the reference should be reported or not
91                 * @param desc
92                 * @return true if the reference should be reported false otherwise
93                 */
94                private boolean acceptReference(IMemberDescriptor desc) {
95                        if(filterPatterns != null) {
96                                for (int i = 0; i < filterPatterns.length; i++) {
97                                        if(filterPatterns[i].matcher(desc.getPackage().getName()).find()) {
98                                                //TODO should we record filtered results?
99                                                return false;
100                                        }
101                                }
102                        }
103                        return true;
104                }
105                
106                /**
107                 * Returns the enclosing {@link IReferenceTypeDescriptor} for the given member
108                 * descriptor
109                 * @param member
110                 * @return the enclosing {@link IReferenceTypeDescriptor} or <code>null</code>
111                 */
112                IReferenceTypeDescriptor getEnclosingDescriptor(IMemberDescriptor member) {
113                        switch(member.getElementType()) {
114                        case IElementDescriptor.TYPE: {
115                                return (IReferenceTypeDescriptor) member;
116                        }
117                        case IElementDescriptor.METHOD:
118                        case IElementDescriptor.FIELD: {
119                                return member.getEnclosingType();
120                        }
121                }
122                return null;
123        }
124                
125                /* (non-Javadoc)
126                 * @see org.eclipse.pde.api.tools.internal.search.UseScanVisitor#visitComponent(org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor)
127                 */
128                public boolean visitComponent(IComponentDescriptor target) {
129                        this.currentreport = new Report();
130                        this.currentreport.name = composeName(target.getId(), target.getVersion());
131                        this.reports.add(this.currentreport);
132                        return true;
133                }
134                
135                /* (non-Javadoc)
136                 * @see org.eclipse.pde.api.tools.internal.search.UseScanVisitor#endVisit(org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor)
137                 */
138                public void endVisit(IComponentDescriptor target) {
139                        try {
140                                long start = 0;
141                                if(DEBUG) {
142                                        System.out.println("Writing report for bundle: "+target.getId()); //$NON-NLS-1$
143                                        start = System.currentTimeMillis();
144                                }
145                                if(this.currentreport.counts.getTotalRefCount() > 0) {
146                                        writeReferencedMemberPage(this.currentreport, this.referees);
147                                }
148                                else {
149                                        this.reports.remove(this.currentreport);
150                                }
151                                if(DEBUG) {
152                                        System.out.println("done in: "+(System.currentTimeMillis()-start)+ " ms"); //$NON-NLS-1$ //$NON-NLS-2$
153                                }
154                        }
155                        catch(Exception e) {
156                                ApiPlugin.log(e);
157                        }
158                        finally {
159                                //clear any children as we have written them out - keep the report object to write a sorted index page
160                                this.currentreport.children.clear();
161                                this.keys.clear();
162                                this.referees.clear();
163                        }
164                }
165 
166                /* (non-Javadoc)
167                 * @see org.eclipse.pde.api.tools.internal.search.UseScanVisitor#visitReferencingComponent(org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor)
168                 */
169                public boolean visitReferencingComponent(IComponentDescriptor component) {
170                        this.currentreferee = new Type(component);
171                        return true;
172                }
173                /* (non-Javadoc)
174                 * @see org.eclipse.pde.api.tools.internal.search.UseScanVisitor#endVisitReferencingComponent(org.eclipse.pde.api.tools.internal.provisional.descriptors.IComponentDescriptor)
175                 */
176                public void endVisitReferencingComponent(IComponentDescriptor component) {
177                        if(this.currentreferee.counts.getTotalRefCount() > 0) {
178                                this.referees.add(this.currentreferee);
179                        }
180                }
181                /* (non-Javadoc)
182                 * @see org.eclipse.pde.api.tools.internal.search.UseScanVisitor#visitMember(org.eclipse.pde.api.tools.internal.provisional.descriptors.IMemberDescriptor)
183                 */
184                public boolean visitMember(IMemberDescriptor referencedMember) {
185                        IReferenceTypeDescriptor desc = getEnclosingDescriptor(referencedMember);
186                        if(desc == null) {
187                                return false;
188                        }
189                        this.currenttype = (Type) this.keys.get(desc);
190                        if(this.currenttype == null) {
191                                this.currenttype = new Type(desc);
192                                this.keys.put(desc, this.currenttype);
193                        }
194                        TreeMap map = (TreeMap) this.currentreport.children.get(this.currenttype);
195                        if(map == null) {
196                                map = new TreeMap(compare);
197                                this.currentreport.children.put(this.currenttype, map);
198                        }
199                        this.currentmember = (Member) map.get(referencedMember);
200                        if(this.currentmember == null) {
201                                this.currentmember = new Member(referencedMember);
202                                map.put(referencedMember, this.currentmember);
203                        }
204                        return true;
205                }
206                
207                /* (non-Javadoc)
208                 * @see org.eclipse.pde.api.tools.internal.search.UseScanVisitor#endVisitMember(org.eclipse.pde.api.tools.internal.provisional.descriptors.IMemberDescriptor)
209                 */
210                public void endVisitMember(IMemberDescriptor referencedMember) {
211                        if(this.currentmember.children.size() == 0) {
212                                TreeMap map = (TreeMap) this.currentreport.children.get(this.currenttype);
213                                map.remove(referencedMember);
214                        }
215                        if(this.currenttype.counts.getTotalRefCount() == 0) {
216                                IReferenceTypeDescriptor desc = getEnclosingDescriptor(referencedMember);
217                                if(desc != null) {
218                                        this.keys.remove(desc);
219                                        this.currentreport.children.remove(this.currenttype);
220                                }
221                        }
222                }
223                
224                /* (non-Javadoc)
225                 * @see org.eclipse.pde.api.tools.internal.search.UseScanVisitor#visitReference(int, org.eclipse.pde.api.tools.internal.provisional.descriptors.IMemberDescriptor, int, int)
226                 */
227                public void visitReference(int refKind, IMemberDescriptor fromMember, int lineNumber, int visibility) {
228                        if(!acceptReference(fromMember)) {
229                                return;
230                        }
231                        String refname = org.eclipse.pde.api.tools.internal.builder.Reference.getReferenceText(refKind);
232                        ArrayList refs = (ArrayList) this.currentmember.children.get(refname);
233                        if(refs == null) {
234                                refs = new ArrayList();
235                                this.currentmember.children.put(refname, refs);
236                        }
237                        refs.add(new Reference(fromMember, lineNumber, visibility));
238                        switch(fromMember.getElementType()) {
239                                case IElementDescriptor.TYPE: {
240                                        switch(visibility) {
241                                                case VisibilityModifiers.API: {
242                                                        this.currentmember.counts.total_api_type_count++;
243                                                        this.currenttype.counts.total_api_type_count++;
244                                                        this.currentreferee.counts.total_api_type_count++;
245                                                        this.currentreport.counts.total_api_type_count++;
246                                                        break;
247                                                }
248                                                case VisibilityModifiers.PRIVATE: {
249                                                        this.currentmember.counts.total_private_type_count++;
250                                                        this.currenttype.counts.total_private_type_count++;
251                                                        this.currentreferee.counts.total_private_type_count++;
252                                                        this.currentreport.counts.total_private_type_count++;
253                                                        break;
254                                                }
255                                                case VisibilityModifiers.PRIVATE_PERMISSIBLE: {
256                                                        this.currentmember.counts.total_permissable_type_count++;
257                                                        this.currenttype.counts.total_permissable_type_count++;
258                                                        this.currentreferee.counts.total_permissable_type_count++;
259                                                        this.currentreport.counts.total_permissable_type_count++;
260                                                        break;
261                                                }
262                                                case FRAGMENT_PERMISSIBLE: {
263                                                        this.currentmember.counts.total_fragment_permissible_type_count++;
264                                                        this.currenttype.counts.total_fragment_permissible_type_count++;
265                                                        this.currentreferee.counts.total_fragment_permissible_type_count++;
266                                                        this.currentreport.counts.total_fragment_permissible_type_count++;
267                                                        break;
268                                                }
269                                                default: {
270                                                        this.currentmember.counts.total_other_type_count++;
271                                                        this.currenttype.counts.total_other_type_count++;
272                                                        this.currentreferee.counts.total_other_type_count++;
273                                                        this.currentreport.counts.total_other_type_count++;
274                                                        break;
275                                                }
276                                        }
277                                        break;
278                                }
279                                case IElementDescriptor.METHOD: {
280                                        switch(visibility) {
281                                                case VisibilityModifiers.API: {
282                                                        this.currentmember.counts.total_api_method_count++;
283                                                        this.currenttype.counts.total_api_method_count++;
284                                                        this.currentreferee.counts.total_api_method_count++;
285                                                        this.currentreport.counts.total_api_method_count++;
286                                                        break;
287                                                }
288                                                case VisibilityModifiers.PRIVATE: {
289                                                        this.currentmember.counts.total_private_method_count++;
290                                                        this.currenttype.counts.total_private_method_count++;
291                                                        this.currentreferee.counts.total_private_method_count++;
292                                                        this.currentreport.counts.total_private_method_count++;
293                                                        break;
294                                                }
295                                                case VisibilityModifiers.PRIVATE_PERMISSIBLE: {
296                                                        this.currentmember.counts.total_permissable_method_count++;
297                                                        this.currenttype.counts.total_permissable_method_count++;
298                                                        this.currentreferee.counts.total_permissable_method_count++;
299                                                        this.currentreport.counts.total_permissable_method_count++;
300                                                        break;
301                                                }
302                                                case FRAGMENT_PERMISSIBLE: {
303                                                        this.currentmember.counts.total_fragment_permissible_method_count++;
304                                                        this.currenttype.counts.total_fragment_permissible_method_count++;
305                                                        this.currentreferee.counts.total_fragment_permissible_method_count++;
306                                                        this.currentreport.counts.total_fragment_permissible_method_count++;
307                                                        break;
308                                                }
309                                                default: {
310                                                        this.currentmember.counts.total_other_method_count++;
311                                                        this.currenttype.counts.total_other_method_count++;
312                                                        this.currentreferee.counts.total_other_method_count++;
313                                                        this.currentreport.counts.total_other_method_count++;
314                                                        break;
315                                                }
316                                        }
317                                        break;
318                                }
319                                case IElementDescriptor.FIELD: {
320                                        switch(visibility) {
321                                                case VisibilityModifiers.API: {
322                                                        this.currentmember.counts.total_api_field_count++;
323                                                        this.currenttype.counts.total_api_field_count++;
324                                                        this.currentreferee.counts.total_api_field_count++;
325                                                        this.currentreport.counts.total_api_field_count++;
326                                                        break;
327                                                }
328                                                case VisibilityModifiers.PRIVATE: {
329                                                        this.currentmember.counts.total_private_field_count++;
330                                                        this.currenttype.counts.total_private_field_count++;
331                                                        this.currentreferee.counts.total_private_field_count++;
332                                                        this.currentreport.counts.total_private_field_count++;
333                                                        break;
334                                                }
335                                                case VisibilityModifiers.PRIVATE_PERMISSIBLE: {
336                                                        this.currentmember.counts.total_permissable_field_count++;
337                                                        this.currenttype.counts.total_permissable_field_count++;
338                                                        this.currentreferee.counts.total_permissable_field_count++;
339                                                        this.currentreport.counts.total_permissable_field_count++;
340                                                        break;
341                                                }
342                                                case FRAGMENT_PERMISSIBLE: {
343                                                        this.currentmember.counts.total_fragment_permissible_field_count++;
344                                                        this.currenttype.counts.total_fragment_permissible_field_count++;
345                                                        this.currentreferee.counts.total_fragment_permissible_field_count++;
346                                                        this.currentreport.counts.total_fragment_permissible_field_count++;
347                                                        break;
348                                                }
349                                                default: {
350                                                        this.currentmember.counts.total_other_field_count++;
351                                                        this.currenttype.counts.total_other_field_count++;
352                                                        this.currentreferee.counts.total_other_field_count++;
353                                                        this.currentreport.counts.total_other_field_count++;
354                                                        break;
355                                                }
356                                        }
357                                        break;
358                                }
359                        }
360                }
361        }
362        
363        /**
364         * Comparator for use report items
365         */
366        static Comparator compare = new Comparator() {
367                public int compare(Object o1, Object o2) {
368                        if(o1 instanceof String && o2 instanceof String) {
369                                return ((String)o1).compareTo((String)o2);
370                        }
371                        if(o1 instanceof Type && o2 instanceof Type) {
372                                return compare(((Type)o1).desc, ((Type)o2).desc);
373                        }
374                        if(o1 instanceof IReferenceTypeDescriptor && o2 instanceof IReferenceTypeDescriptor) {
375                                return ((IReferenceTypeDescriptor)o1).getQualifiedName().compareTo(((IReferenceTypeDescriptor)o2).getQualifiedName());
376                        }
377                        if(o1 instanceof IMethodDescriptor && o2 instanceof IMethodDescriptor) {
378                                try {
379                                        return Signatures.getQualifiedMethodSignature((IMethodDescriptor)o1).compareTo(Signatures.getQualifiedMethodSignature((IMethodDescriptor)o2));
380                                }
381                                catch(CoreException ce) {
382                                        return  -1;
383                                }
384                        }
385                        if(o1 instanceof IFieldDescriptor && o2 instanceof IFieldDescriptor) {
386                                try {
387                                        return Signatures.getQualifiedFieldSignature((IFieldDescriptor)o1).compareTo(Signatures.getQualifiedFieldSignature((IFieldDescriptor)o2));
388                                }
389                                catch(CoreException ce) {
390                                        return -1;
391                                }
392                        }
393                        if(o1 instanceof IComponentDescriptor && o2 instanceof IComponentDescriptor) {
394                                return ((IComponentDescriptor)o1).getId().compareTo(((IComponentDescriptor)o2).getId());
395                        }
396                        return -1;
397                };
398        };
399        
400        /**
401         * Root item describing the use of one component
402         */
403        static class Report {
404                String name = null;
405                TreeMap children = new TreeMap(compare);
406                CountGroup counts = new CountGroup();
407        }
408        
409        /**
410         * Describes a type, used to key a collection of {@link Member}s
411         */
412        static class Type {
413                IElementDescriptor desc = null;
414                CountGroup counts = new CountGroup();
415                public Type(IElementDescriptor desc) {
416                        this.desc = desc;
417                }
418        }
419        
420        /**
421         * Describes a member that is being used
422         */
423        static class Member {
424                IElementDescriptor descriptor = null;
425                TreeMap children = new TreeMap(compare);
426                CountGroup counts = new CountGroup();
427                public Member(IElementDescriptor desc) {
428                        this.descriptor = desc;
429                }
430        }
431        
432        /**
433         * Describes a reference from a given descriptor
434         */
435        static class Reference {
436                IElementDescriptor desc = null;
437                int line = -1, vis = -1;
438                public Reference(IElementDescriptor desc, int line, int vis) {
439                        this.desc = desc;
440                        this.line = line;
441                        this.vis = vis;
442                }
443        }
444        
445        /**
446         * A group of counters to origin meta-data
447         */
448        static final class CountGroup {
449                int total_api_field_count = 0;
450                int total_private_field_count = 0;
451                int total_permissable_field_count = 0;
452                int total_fragment_permissible_field_count = 0;
453                int total_other_field_count = 0;
454                int total_api_method_count = 0;
455                int total_private_method_count = 0;
456                int total_permissable_method_count = 0;
457                int total_fragment_permissible_method_count = 0;
458                int total_other_method_count = 0;
459                int total_api_type_count = 0;
460                int total_private_type_count = 0;
461                int total_permissable_type_count = 0;
462                int total_fragment_permissible_type_count = 0;
463                int total_other_type_count = 0;
464                
465                public int getTotalRefCount() {
466                        return total_api_field_count +
467                                        total_api_method_count +
468                                        total_api_type_count +
469                                        total_other_field_count +
470                                        total_other_method_count +
471                                        total_other_type_count +
472                                        total_private_field_count +
473                                        total_private_method_count +
474                                        total_private_type_count +
475                                        total_permissable_field_count +
476                                        total_permissable_method_count + 
477                                        total_permissable_type_count +
478                                        total_fragment_permissible_field_count +
479                                        total_fragment_permissible_method_count +
480                                        total_fragment_permissible_type_count;
481                }
482                
483                public int getTotalApiRefCount() {
484                        return total_api_field_count + total_api_method_count + total_api_type_count;
485                }
486                
487                public int getTotalInternalRefCount() {
488                        return total_private_field_count + total_private_method_count + total_private_type_count;
489                }
490                
491                public int getTotalOtherRefCount() {
492                        return total_other_field_count + total_other_method_count + total_other_type_count;
493                }
494                
495                public int getTotalPermissableRefCount() {
496                        return total_permissable_field_count + total_permissable_method_count + total_permissable_type_count;
497                }
498                
499                public int getTotalFragmentPermissibleRefCount() {
500                        return total_fragment_permissible_field_count + total_fragment_permissible_method_count + total_fragment_permissible_type_count;
501                }
502        }
503        
504        /**
505         * Handler for parsing the not_searched.xml file to output a summary or 
506         * missing required bundles
507         */
508        static final class MissingHandler extends DefaultHandler {
509                List missing = new ArrayList();
510                static String pattern = "Require-Bundle:"; //$NON-NLS-1$
511                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
512                        if(IApiXmlConstants.ELEMENT_COMPONENT.equals(qName)) {
513                                String value = attributes.getValue("details"); //$NON-NLS-1$
514                                StringTokenizer tokenizer = new StringTokenizer(value, "<>"); //$NON-NLS-1$
515                                int index = -1;
516                                while(tokenizer.hasMoreTokens()) {
517                                        value = tokenizer.nextToken();
518                                        index = value.indexOf(pattern);
519                                        if(index > -1) {
520                                                missing.add(value.replaceAll(pattern, Util.EMPTY_STRING));
521                                        }
522                                }
523                        }
524                }
525        }
526        
527        /**
528         * Visibility constant indicating an element has host-fragment level of visibility.
529         *  i.e. fragments have {@link #PRIVATE_PERMISSIBLE}-like access to the internals of their host.
530         *  
531         *  @since 1.0.1
532         */
533        public static final int FRAGMENT_PERMISSIBLE = 0x0000005;
534        /**
535         * Default XSLT file name
536         */
537        private static final String DEFAULT_XSLT = "/references.xsl"; //$NON-NLS-1$
538        /**
539         * Colour white for normal / permissible references
540         */
541        static final String NORMAL_REFS_COLOUR = "#FFFFFF"; //$NON-NLS-1$
542        /**
543         * Colour red for internal references
544         */
545         static final String INTERNAL_REFS_COLOUR = "#F6CECE"; //$NON-NLS-1$
546        /**
547         * Style HTML bits for a page that shows references
548         */
549        static final String REF_STYLE;
550        /**
551         * The script block used to show an expanding table of references
552         */
553        static final String REF_SCRIPT;
554        
555        static {
556                StringBuffer buffer = new StringBuffer();
557                buffer.append("<style type=\"text/css\">\n"); //$NON-NLS-1$
558                buffer.append("\t.main {\t\tfont-family:Arial, Helvetica, sans-serif;\n\t}\n"); //$NON-NLS-1$
559                buffer.append("\t.main h3 {\n\t\tfont-family:Arial, Helvetica, sans-serif;\n\t\t\background-color:#FFFFFF;\n\t\tfont-size:14px;\n\t\tmargin:0.1em;\n\t}\n"); //$NON-NLS-1$
560                buffer.append("\t.main h4 {\n\t\tbackground-color:#CCCCCC;\n\t\tmargin:0.15em;\n\t}\n"); //$NON-NLS-1$
561                buffer.append("\ta.typeslnk {\n\t\tfont-family:Arial, Helvetica, sans-serif;\n\t\ttext-decoration:none;\n\t\tmargin-left:0.25em;\n\t}\n"); //$NON-NLS-1$
562                buffer.append("\ta.typeslnk:hover {\n\t\ttext-decoration:underline;\n\t}\n"); //$NON-NLS-1$
563                buffer.append("\ta.kindslnk {\n\t\tfont-family:Arial, Helvetica, sans-serif;\n\t\ttext-decoration:none;\n\t\tmargin-left:0.25em;\n\t}\n"); //$NON-NLS-1$
564                buffer.append("\t.types {\n\t\tdisplay:none;\n\t\tmargin-bottom:0.25em;\n\t\tmargin-top:0.25em;\n\t\tmargin-right:0.25em;\n\t\tmargin-left:0.75em;\n\t}\n"); //$NON-NLS-1$
565                buffer.append("</style>\n"); //$NON-NLS-1$
566                REF_STYLE = buffer.toString();
567                
568                buffer = new StringBuffer();
569                buffer.append("<script type=\"text/javascript\">\n\tfunction expand(location) {\n\t\tif(document.getElementById) {\n\t\t\tvar childhtml = location.firstChild;\n\t\t\tif(!childhtml.innerHTML) {\n\t\t\t\tchildhtml = childhtml.nextSibling;\n\t\t\t}\n\t\t\tchildhtml.innerHTML = childhtml.innerHTML == '[+] ' ? '[-] ' : '[+] ';\n\t\t\tvar parent = location.parentNode;\n\t\t\tchildhtml = parent.nextSibling.style ? parent.nextSibling : parent.nextSibling.nextSibling;\n\t\t\tchildhtml.style.display = childhtml.style.display == 'block' ? 'none' : 'block';\n\t\t}\n\t}\n</script>\n"); //$NON-NLS-1$
570                buffer.append("<noscript>\n\t<style type=\"text/css\">\n\t\t.types {display:block;}\n\t\t.kinds{display:block;}\n\t</style>\n</noscript>\n"); //$NON-NLS-1$
571                REF_SCRIPT = buffer.toString();
572        }
573        
574        /**
575         * Method used for initializing tracing in the report converter
576         */
577        public static void setDebug(boolean debugValue) {
578                DEBUG = debugValue || Util.DEBUG;
579        }
580        
581        /**
582         * Constant used for controlling tracing in the report converter
583         */
584        protected static boolean DEBUG = Util.DEBUG;
585        
586        private File htmlRoot = null;
587        private File reportsRoot = null;
588        private String xmlLocation = null;
589        private String htmlLocation = null;
590        private File htmlIndex = null;
591        SAXParser parser = null;
592        private boolean hasmissing = false;
593        private UseMetadata metadata = null;
594        Pattern[] filterPatterns = null;
595        
596        /**
597         * Constructor
598         * @param htmlroot the folder root where the HTML reports should be written
599         * @param xmlroot the folder root where the current API use scan output is located
600         * @param patterns array of regular expressions to prune HTML output with
601         */
602        public UseReportConverter(String htmlroot, String xmlroot, String[] patterns) {
603                this.xmlLocation = xmlroot;
604                this.htmlLocation = htmlroot;
605                if(patterns != null) {
606                        ArrayList pats = new ArrayList(patterns.length);
607                        for (int i = 0; i < patterns.length; i++) {
608                                try {
609                                        pats.add(Pattern.compile(patterns[i]));
610                                }
611                                catch(PatternSyntaxException pse) {
612                                        if(DEBUG) {
613                                                System.out.println(NLS.bind(SearchMessages.UseReportConverter_filter_pattern_not_valid, patterns[i]));
614                                                System.out.println(pse.getMessage());
615                                        }
616                                }
617                        }
618                        if(!pats.isEmpty()) {
619                                this.filterPatterns = (Pattern[]) pats.toArray(new Pattern[pats.size()]);
620                        }
621                }
622        }
623        
624        /**
625         * Runs the converter on the given locations
626         */
627        public void convert(String xslt, IProgressMonitor monitor) throws Exception {
628                if (this.htmlLocation == null) {
629                        return;
630                }
631                SubMonitor localmonitor = SubMonitor.convert(monitor, SearchMessages.UseReportConverter_preparing_report_metadata, 8);
632                try {
633                        localmonitor.setTaskName(SearchMessages.UseReportConverter_preparing_html_root);
634                        Util.updateMonitor(localmonitor, 1);
635                        this.htmlRoot = new File(this.htmlLocation);
636                        if (!this.htmlRoot.exists()) {
637                                if (!this.htmlRoot.mkdirs()) {
638                                        throw new Exception(NLS.bind(SearchMessages.could_not_create_file, this.htmlLocation));
639                                }
640                        }
641                        else {
642                                this.htmlRoot.mkdirs();
643                        }
644                        localmonitor.setTaskName(SearchMessages.UseReportConverter_preparing_xml_root);
645                        Util.updateMonitor(localmonitor, 1);
646                        if (this.xmlLocation == null) {
647                                throw new Exception(SearchMessages.missing_xml_files_location);
648                        }
649                        this.reportsRoot = new File(this.xmlLocation);
650                        if (!this.reportsRoot.exists() || !this.reportsRoot.isDirectory()) {
651                                throw new Exception(NLS.bind(SearchMessages.invalid_directory_name, this.xmlLocation));
652                        }
653                        
654                        localmonitor.setTaskName(SearchMessages.UseReportConverter_preparing_xslt_file);
655                        Util.updateMonitor(localmonitor, 1);
656                        File xsltFile = null;
657                        if(xslt != null) {
658                                // we will use the default XSLT transform from the ant jar when this is null
659                                xsltFile = new File(xslt);
660                                if(!xsltFile.exists() || !xsltFile.isFile()) {
661                                        throw new Exception(SearchMessages.UseReportConverter_xslt_file_not_valid);
662                                }
663                        }
664                        long start = 0;
665                        if(DEBUG) {
666                                start = System.currentTimeMillis();
667                        }
668                        localmonitor.setTaskName(SearchMessages.UseReportConverter_writing_not_searched);
669                        writeMissingBundlesPage(this.htmlRoot);
670                        writeNotSearchedPage(this.htmlRoot);
671                        Util.updateMonitor(localmonitor, 1);
672                        if(DEBUG) {
673                                System.out.println("done in: "+(System.currentTimeMillis()-start)+ " ms"); //$NON-NLS-1$ //$NON-NLS-2$
674                                System.out.println("Parsing use scan..."); //$NON-NLS-1$
675                                start = System.currentTimeMillis();
676                        }
677                        localmonitor.setTaskName(SearchMessages.UseReportConverter_parsing_use_scan);
678                        UseScanParser parser = new UseScanParser();
679                        Visitor convertor = new Visitor();
680                        parser.parse(xmlLocation, localmonitor.newChild(5), convertor);
681                        Util.updateMonitor(localmonitor, 1);
682                        if(DEBUG) {
683                                System.out.println("done in: "+(System.currentTimeMillis()-start)+ " ms"); //$NON-NLS-1$ //$NON-NLS-2$
684                                System.out.println("Sorting reports and writing index..."); //$NON-NLS-1$
685                                start = System.currentTimeMillis();
686                        }
687                        localmonitor.setTaskName(SearchMessages.UseReportConverter_writing_root_index);
688                        Collections.sort(convertor.reports, new Comparator() {
689                                public int compare(Object o1, Object o2) {
690                                        return ((Report)o1).name.compareTo(((Report)o2).name);
691                                }
692                        });
693                        writeIndexPage(convertor.reports, this.htmlRoot);
694                        Util.updateMonitor(localmonitor, 1);
695                        if(DEBUG) {
696                                System.out.println("done in: "+(System.currentTimeMillis()-start)+ " ms"); //$NON-NLS-1$ //$NON-NLS-2$
697                        }
698                        writeMetaPage(this.htmlRoot);
699                }
700                finally {
701                        if(localmonitor != null) {
702                                localmonitor.done();
703                        }
704                }
705        }
706        
707        /**
708         * Returns the handle to the default parser, caches the handle once it has been created
709         * @return the handle to the default parser
710         * @throws Exception forwarded general exception that can be trapped in Ant builds
711         */
712        SAXParser getParser() throws Exception {
713                if(this.parser == null) {
714                        SAXParserFactory factory = SAXParserFactory.newInstance();
715                        try {
716                                this.parser = factory.newSAXParser();
717                        } catch (ParserConfigurationException pce) {
718                                throw new Exception(SearchMessages.UseReportConverter_pce_error_getting_parser, pce);
719                        } catch (SAXException se) {
720                                throw new Exception(SearchMessages.UseReportConverter_se_error_parser_handle, se);
721                        }
722                        if (this.parser == null) {
723                                throw new Exception(SearchMessages.could_not_create_sax_parser);
724                        }
725                }
726                return this.parser;
727        }
728        
729        /**
730         * Builds the name for the component
731         * @param id
732         * @param version
733         * @return
734         */
735        protected String composeName(String id, String version) {
736                StringBuffer buffer = new StringBuffer(3+id.length()+version.length());
737                buffer.append(id).append(" (").append(version).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
738                return buffer.toString();
739        }
740        
741        /**
742         * @return the index.html file created from the report conversion or <code>null</code>
743         * if the conversion failed
744         */
745        public File getReportIndex() {
746                return htmlIndex;
747        }
748        
749        /**
750         * Applies the given XSLT to the given XML to produce HTML in the given file
751         * @param xsltfile
752         * @param xmlfile
753         * @param htmloutput
754         * @throws TransformerException
755         */
756        protected void applyXSLT(File xsltFile, File xmlfile, File htmloutput) throws TransformerException, Exception {
757                Source xslt = null;
758                if (xsltFile != null) {
759                        xslt = new StreamSource(xsltFile);
760                } else {
761                        InputStream defaultXsltInputStream = UseReportConverter.class.getResourceAsStream(DEFAULT_XSLT);
762                        if (defaultXsltInputStream != null) {
763                                xslt = new StreamSource(new BufferedInputStream(defaultXsltInputStream));
764                        }
765                }
766                if(xslt == null) {
767                        throw new Exception(SearchMessages.UseReportConverter_no_xstl_specified);
768                }
769                applyXSLT(xslt, xmlfile, htmloutput);
770        }
771        
772        /**
773         * Applies the given XSLT source to the given XML file outputting to the given HTML file
774         * @param xslt
775         * @param xmlfile
776         * @param htmlfile
777         * @throws TransformerException
778         */
779        protected void applyXSLT(Source xslt, File xmlfile, File htmlfile) throws TransformerException {
780                Source xml = new StreamSource(xmlfile);
781                Result html = new StreamResult(htmlfile);
782                TransformerFactory factory = TransformerFactory.newInstance();
783                Transformer former = factory.newTransformer(xslt);
784                former.transform(xml, html);
785        }
786        
787        /**
788         * Transforms the given set of xml files with the given XSLT and places the result into a
789         * corresponding HTML file
790         * @param xmlfiles
791         * @param xsltFile
792         * @param html
793         */
794        protected void tranformXml(File[] xmlfiles, File xsltFile) {
795                File html = null;
796                for (int i = 0; i < xmlfiles.length; i++) {
797                        try {
798                                File htmlroot = new File(this.htmlLocation, getHTMLFileLocation(this.reportsRoot, xmlfiles[i]));
799                                if(!htmlroot.exists()) {
800                                        htmlroot.mkdirs();
801                                }
802                                html = new File(getNameFromXMLFilename(xmlfiles[i]));
803                                applyXSLT(xsltFile, xmlfiles[i], html);
804                        }
805                        catch(TransformerException te) {}
806                        catch (Exception e) {
807                                ApiPlugin.log(e);
808                        }
809                }
810        }
811        
812        /**
813         * Gets the HTML path to write out the transformed XML file to
814         * @param reportroot
815         * @param xmlfile
816         * @return
817         */
818        protected String getHTMLFileLocation(File reportroot, File xmlfile) {
819                IPath xml = new Path(xmlfile.getPath());
820                IPath report = new Path(reportroot.getPath());
821                int segments = xml.matchingFirstSegments(report);
822                if(segments > 0) {
823                        if(xml.getDevice() != null) {
824                                xml = xml.setDevice(null);
825                        }
826                        IPath html = xml.removeFirstSegments(segments);
827                        return html.removeLastSegments(1).toOSString();
828                }
829                return null;
830        }
831        
832        /**
833         * Returns the name to use for the corresponding HTML file
834         * from the given XML file
835         * @param xmlFile
836         * @return the HTML name to use
837         */
838        protected String getNameFromXMLFilename(File xmlFile) {
839                String fileName = xmlFile.getAbsolutePath();
840                int index = fileName.lastIndexOf('.');
841                StringBuffer buffer = new StringBuffer();
842                buffer.append(fileName.substring(this.reportsRoot.getAbsolutePath().length(), index)).append(HTML_EXTENSION); 
843                File htmlFile = new File(this.htmlLocation, String.valueOf(buffer));
844                return htmlFile.getAbsolutePath();
845        }
846        
847        /**
848         * Returns the collection of missing bundle names
849         * @param missingfile
850         * @return the collection of missing bundle names
851         * @throws Exception
852         */
853        protected String[] getMissingBundles(File missingfile) throws Exception {
854                MissingHandler handler = new MissingHandler();
855                getParser().parse(missingfile, handler);
856                return (String[]) handler.missing.toArray(new String[handler.missing.size()]); 
857        }
858        
859        /**
860         * Returns the sentence describing the purpose / reason of the missing bundles
861         * @return a blurb describing the table of missing bundles
862         */
863        protected String getMissingBundlesHeader() {
864                return SearchMessages.UseReportConverter_reported_missing_bundles;
865        }
866        
867        /**
868         * Writes any existing metadata out to a meta.html file in the root of the 
869         * HTML report location
870         * @param htmlroot
871         * @throws Exception
872         */
873        void writeMetaPage(File htmlroot) throws Exception {
874                File meta = null;
875                PrintWriter writer = null;
876                try {
877                        File file = new File(this.reportsRoot, "meta.xml"); //$NON-NLS-1$
878                        if(!file.exists()) {
879                                //do nothing if no meta.xml file
880                                return;
881                        }
882                        String filename = "meta"; //$NON-NLS-1$
883                        meta = new File(htmlroot, filename+HTML_EXTENSION); 
884                        if(!meta.exists()) {
885                                meta.createNewFile();
886                        }
887                        StringBuffer buffer = new StringBuffer();
888                        buffer.append(HTML_HEADER);
889                        buffer.append(OPEN_HTML).append(OPEN_HEAD).append(CONTENT_TYPE_META);
890                        buffer.append(OPEN_TITLE).append(SearchMessages.UseReportConverter_use_scan_info).append(CLOSE_TITLE); 
891                        buffer.append(CLOSE_HEAD); 
892                        buffer.append(OPEN_BODY); 
893                        buffer.append(OPEN_H3).append(SearchMessages.UseReportConverter_use_scan_info).append(CLOSE_H3);
894                        writeMetadataSummary(buffer); 
895                        buffer.append(W3C_FOOTER);
896                        
897                        //write file
898                        FileWriter fileWriter = new FileWriter(meta);
899                        writer = new PrintWriter(new BufferedWriter(fileWriter));
900                        writer.println(buffer.toString());
901                        writer.flush();
902                }
903                catch(IOException ioe) {
904                        throw new Exception(NLS.bind(SearchMessages.ioexception_writing_html_file, meta.getAbsolutePath()));
905                }
906                finally {
907                        if(writer != null) {
908                                writer.close();
909                        }
910                }
911        }
912        
913        /**
914         * Writes out a summary of the missing required bundles
915         * @param htmlroot
916         */
917        protected void writeMissingBundlesPage(final File htmlroot) throws Exception {
918                File missing = null;
919                PrintWriter writer = null;
920                try {
921                        String filename = "missing"; //$NON-NLS-1$
922                        missing = new File(htmlroot, filename+HTML_EXTENSION); 
923                        if(!missing.exists()) {
924                                missing.createNewFile();
925                        }
926                        
927                        File file = new File(this.reportsRoot, "not_searched.xml"); //$NON-NLS-1$
928                        TreeSet sorted = new TreeSet(Util.componentsorter);
929                        if (file.exists()) {
930                                String[] missingBundles = getMissingBundles(file); 
931                                this.hasmissing = missingBundles.length > 0;
932                                for (int i = 0; i < missingBundles.length; i++) {
933                                        sorted.add(missingBundles[i]);
934                                }
935                        }
936                        StringBuffer buffer = new StringBuffer();
937                        buffer.append(HTML_HEADER);
938                        buffer.append(OPEN_HTML).append(OPEN_HEAD).append(CONTENT_TYPE_META);
939                        buffer.append(OPEN_TITLE).append(SearchMessages.UseReportConverter_missing_required).append(CLOSE_TITLE); 
940                        buffer.append(CLOSE_HEAD); 
941                        buffer.append(OPEN_BODY); 
942                        buffer.append(OPEN_H3).append(SearchMessages.UseReportConverter_missing_required).append(CLOSE_H3);
943                        
944                        if(sorted.isEmpty()) {
945                                buffer.append(SearchMessages.UseReportConverter_no_required_missing).append(BR);
946                        }
947                        else {
948                                buffer.append(OPEN_P).append(getMissingBundlesHeader()).append(CLOSE_P); 
949                                buffer.append("<table border=\"1\" width=\"50%\">\n"); //$NON-NLS-1$
950                                buffer.append(OPEN_TR).append("<td bgcolor=\"#CC9933\" width=\"36%\">").append(OPEN_B).append(SearchMessages.UseReportConverter_required_bundles).append(CLOSE_B).append(CLOSE_TD).append(CLOSE_TR); //$NON-NLS-1$ 
951                        }
952                        String value = null;
953                        for (Iterator iter = sorted.iterator(); iter.hasNext();) {
954                                value = (String) iter.next();
955                                buffer.append(OPEN_TR).append(OPEN_TD).append(value).append(CLOSE_TD).append(CLOSE_TR);  
956                        }
957                        buffer.append(CLOSE_TABLE); 
958                        buffer.append(BR).append("<a href=\"not_searched.html\">").append(SearchMessages.UseReportConverter_back_to_not_searched).append(CLOSE_A); //$NON-NLS-1$ 
959                        buffer.append(W3C_FOOTER);
960                        
961                        //write file
962                        FileWriter fileWriter = new FileWriter(missing);
963                        writer = new PrintWriter(new BufferedWriter(fileWriter));
964                        writer.println(buffer.toString());
965                        writer.flush();
966                }
967                catch(IOException ioe) {
968                        throw new Exception(NLS.bind(SearchMessages.ioexception_writing_html_file, missing.getAbsolutePath()));
969                }
970                finally {
971                        if(writer != null) {
972                                writer.close();
973                        }
974                }
975        }
976        
977        /**
978         * Writes out the file of components that were not searched: either because they appeared in an exclude list
979         * or they have no .api_description file
980         * 
981         * @param htmlroot
982         */
983        void writeNotSearchedPage(final File htmlroot) throws Exception {
984                File originhtml = null;
985                try {
986                        String filename = "not_searched"; //$NON-NLS-1$
987                        originhtml = new File(htmlroot, filename+HTML_EXTENSION); 
988                        if(!originhtml.exists()) {
989                                originhtml.createNewFile();
990                        }
991                        File xml = new File(this.reportsRoot, filename+XML_EXTENSION); 
992                        InputStream defaultXsltInputStream = UseReportConverter.class.getResourceAsStream(getNotSearchedXSLPath()); 
993                        Source xslt = null;
994                        if (defaultXsltInputStream != null) {
995                                xslt = new StreamSource(new BufferedInputStream(defaultXsltInputStream));
996                        }
997                        if(xslt == null) {
998                                throw new Exception(SearchMessages.UseReportConverter_no_xstl_specified);
999                        }
1000                        if (xml.exists()) {
1001                                applyXSLT(xslt, xml, originhtml);
1002                        }
1003                }
1004                catch(IOException ioe) {
1005                        throw new Exception(NLS.bind(SearchMessages.ioexception_writing_html_file, originhtml.getAbsolutePath()));
1006                }
1007                catch (TransformerException te) {
1008                        throw new Exception(SearchMessages.UseReportConverter_te_applying_xslt_skipped, te);
1009                }
1010                catch (CoreException e) {
1011                        throw new Exception(NLS.bind(SearchMessages.UseReportConverter_coreexception_writing_html_file, originhtml.getAbsolutePath()));
1012                }
1013        }
1014        
1015        /**
1016         * Returns path of XSL file to use when generating "not searched" information.
1017         * 
1018         * @return path to the XSL file
1019         */
1020        String getNotSearchedXSLPath() {
1021                return "/notsearched.xsl"; //$NON-NLS-1$
1022        }
1023        
1024        /**
1025         * Writes the referenced member index page
1026         * @param report
1027         * @param referees the listing of referencing bundles
1028         */
1029        void writeReferencedMemberPage(final Report report, final List referees) throws Exception {
1030                PrintWriter writer = null;
1031                File originhtml = null;
1032                try {
1033                        File htmlroot = new File(this.htmlLocation, report.name);
1034                        if(!htmlroot.exists()) {
1035                                htmlroot.mkdirs();
1036                        }
1037                        originhtml = new File(htmlroot, "index.html"); //$NON-NLS-1$
1038                        if(!originhtml.exists()) {
1039                                originhtml.createNewFile();
1040                        }
1041                        StringBuffer buffer = new StringBuffer();
1042                        buffer.append(HTML_HEADER);
1043                        buffer.append(OPEN_HTML).append(OPEN_HEAD).append(CONTENT_TYPE_META);
1044                        buffer.append(REF_STYLE);
1045                        buffer.append(REF_SCRIPT);
1046                        buffer.append(OPEN_TITLE).append(getReferencedTypeTitle(report.name)).append(CLOSE_TITLE); 
1047                        buffer.append(CLOSE_HEAD); 
1048                        buffer.append(OPEN_BODY); 
1049                        buffer.append(OPEN_H3).append(getReferencedTypeHeader(report.name)).append(CLOSE_H3);
1050                        buffer.append(OPEN_P).append(NLS.bind(SearchMessages.UseReportConverter_list_of_all_refing_bundles, new String[] {"<a href=\"#bundles\">", "</a>"})).append(CLOSE_P); //$NON-NLS-1$ //$NON-NLS-2$
1051                        String additional = getAdditionalReferencedTypeInformation();
1052                        if(additional != null) {
1053                                buffer.append(additional);
1054                        }
1055                        buffer.append(getReferencesTableHeader(SearchMessages.UseReportConverter_referenced_type));
1056                        CountGroup counts = null;
1057                        String link = null;
1058                        Entry entry = null;
1059                        File typefile = null;
1060                        TreeMap map = null;
1061                        Type type = null;
1062                        for (Iterator iter = report.children.entrySet().iterator(); iter.hasNext();) {
1063                                entry = (Entry) iter.next();
1064                                map = (TreeMap) entry.getValue();
1065                                type = (Type) entry.getKey();
1066                                counts = type.counts;
1067                                
1068                                String fqname = Signatures.getQualifiedTypeSignature((IReferenceTypeDescriptor) type.desc);
1069                                typefile = new File(htmlroot, fqname+HTML_EXTENSION); 
1070                                if(!typefile.exists()) {
1071                                        typefile.createNewFile();
1072                                }
1073                                link = extractLinkFrom(htmlroot, typefile.getAbsolutePath());
1074                                buffer.append(getReferenceTableEntry(counts, link, fqname));
1075                                writeTypePage(map, type, typefile, fqname);
1076                        }
1077                        buffer.append(CLOSE_TABLE); 
1078                        buffer.append(BR);
1079                        buffer.append(OPEN_H4).append(SearchMessages.UseReportConverter_referencing_bundles).append(CLOSE_H4);
1080                        buffer.append(OPEN_P).append(NLS.bind(SearchMessages.UseReportConverter_following_bundles_have_refs, report.name)).append(CLOSE_P);
1081                        buffer.append("<a name=\"bundles\">").append(CLOSE_A); //$NON-NLS-1$
1082                        buffer.append("<table border=\"1\" width=\"70%\">\n"); //$NON-NLS-1$
1083                        buffer.append(OPEN_TR); 
1084                        buffer.append("\t<td bgcolor=\"#CC9933\" width=\"70%\">").append(OPEN_B).append(SearchMessages.UseReportConverter_bundle).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$
1085                        buffer.append("\t<td bgcolor=\"#CC9933\" width=\"14%\" align=\"center\">").append(OPEN_B).append(SearchMessages.UseReportConverter_version).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$
1086                        buffer.append("\t<td bgcolor=\"#CC9933\" width=\"36%\" align=\"center\">").append(OPEN_B).append(SearchMessages.UseReportConverter_reference_count).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$
1087                        buffer.append(CLOSE_TR);
1088                        Collections.sort(referees, compare);
1089                        IComponentDescriptor comp = null;
1090                        for (int i = 0; i < referees.size(); i++) {
1091                                type = (Type) referees.get(i);
1092                                comp = (IComponentDescriptor) type.desc;
1093                                buffer.append("<tr bgcolor=\"").append((type.counts.getTotalInternalRefCount() > 0 ? INTERNAL_REFS_COLOUR : NORMAL_REFS_COLOUR)).append("\">\n");  //$NON-NLS-1$//$NON-NLS-2$
1094                                buffer.append("\t").append(OPEN_TD).append(comp.getId()).append(CLOSE_TD); //$NON-NLS-1$
1095                                buffer.append("\t").append(OPEN_TD).append(comp.getVersion()).append(CLOSE_TD); //$NON-NLS-1$
1096                                buffer.append("\t<td align=\"center\">").append(type.counts.getTotalRefCount()).append(CLOSE_TD); //$NON-NLS-1$
1097                                buffer.append(CLOSE_TR);
1098                        }
1099                        buffer.append(CLOSE_TABLE);
1100                        buffer.append(OPEN_P).append("<a href=\"../index.html\">").append(SearchMessages.UseReportConverter_back_to_bundle_index).append(CLOSE_A).append(CLOSE_P); //$NON-NLS-1$ 
1101                        buffer.append(W3C_FOOTER);
1102                        
1103                        FileWriter fileWriter = new FileWriter(originhtml);
1104                        writer = new PrintWriter(new BufferedWriter(fileWriter));
1105                        writer.println(buffer.toString());
1106                        writer.flush();
1107                }
1108                catch(IOException ioe) {
1109                        throw new Exception(NLS.bind(SearchMessages.ioexception_writing_html_file, originhtml.getAbsolutePath()));
1110                }
1111                finally {
1112                        if (writer != null) {
1113                                writer.close();
1114                        }
1115                }
1116        }
1117 
1118        /**
1119         * Returns a string of additional information to print out at the top of the referenced types page.
1120         * @return additional referenced type information.
1121         */
1122        protected String getAdditionalReferencedTypeInformation() {
1123                return null;
1124        }
1125        
1126        /**
1127         * Returns the page title to use for the referenced types page
1128         * @param bundle
1129         * @return the page title for the referenced types page
1130         */
1131        protected String getReferencedTypeTitle(String bundle) {
1132                return NLS.bind(SearchMessages.UseReportConverter_types_used_in, bundle);
1133        }
1134        
1135        /**
1136         * Returns the header title to use for the reference types page. This header
1137         * is the first header on the top of the page.
1138         * @param bundle
1139         * @return the header title for the referenced types page
1140         */
1141        protected String getReferencedTypeHeader(String bundle) {
1142                return NLS.bind(SearchMessages.UseReportConverter_types_used_in, bundle);
1143        }
1144        
1145        /**
1146         * Writes the page that displays all of the members used in a type
1147         * @param map
1148         * @param type
1149         * @param typefile
1150         * @param typename
1151         * @throws Exception
1152         */
1153        void writeTypePage(TreeMap map, Type type, File typefile, String typename) throws Exception {
1154                PrintWriter writer = null;
1155                try {
1156                        StringBuffer buffer = new StringBuffer();
1157                        buffer.append(HTML_HEADER);
1158                        buffer.append(OPEN_HTML).append(OPEN_HEAD).append(CONTENT_TYPE_META);
1159                        buffer.append(REF_STYLE);
1160                        buffer.append(REF_SCRIPT);
1161                        buffer.append(OPEN_TITLE).append(getTypeTitle(typename)).append(CLOSE_TITLE); 
1162                        buffer.append(CLOSE_HEAD); 
1163                        buffer.append(OPEN_BODY); 
1164                        buffer.append(OPEN_H3).append(getTypeHeader(typename)).append(CLOSE_H3); 
1165                        buffer.append(getTypeCountSummary(typename, type.counts, map.size()));
1166                        buffer.append(OPEN_H4).append(getTypeDetailsHeader()).append(CLOSE_H4); 
1167                        buffer.append("<table width=\"50%\" border=\"1\">\n"); //$NON-NLS-1$
1168                        buffer.append(OPEN_P).append(getTypeDetails()).append(CLOSE_P); 
1169                        buffer.append("<div align=\"left\" class=\"main\">"); //$NON-NLS-1$
1170                        buffer.append("<table border=\"1\" width=\"70%\">\n"); //$NON-NLS-1$
1171                        buffer.append(OPEN_TR); 
1172                        buffer.append("<td bgcolor=\"#CC9933\">").append(OPEN_B).append(SearchMessages.UseReportConverter_member).append("</b></td>\n"); //$NON-NLS-1$ //$NON-NLS-2$ 
1173                        buffer.append(CLOSE_TR); 
1174                        Entry entry = null;
1175                        IElementDescriptor desc = null;
1176                        Member mem = null;
1177                        for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
1178                                entry = (Entry) iter.next();
1179                                desc = (IElementDescriptor)entry.getKey();
1180                                mem = (Member) entry.getValue();
1181                                buffer.append(OPEN_TR); 
1182                                buffer.append("<td align=\"left\">\n"); //$NON-NLS-1$
1183                                buffer.append(OPEN_B); 
1184                                buffer.append("<a href=\"javascript:void(0)\" class=\"typeslnk\" onclick=\"expand(this)\">\n"); //$NON-NLS-1$
1185                                buffer.append("<span>[+] </span>").append(getDisplayName(desc, false)).append("\n");  //$NON-NLS-1$//$NON-NLS-2$
1186                                buffer.append(CLOSE_A).append(CLOSE_B);
1187                                buffer.append(getReferencesTable(mem)).append("\n"); //$NON-NLS-1$
1188                                buffer.append(CLOSE_TR); 
1189                        }
1190                        buffer.append(CLOSE_TABLE);
1191                        buffer.append(CLOSE_DIV); 
1192                        buffer.append(OPEN_P).append("<a href=\"index.html\">").append(SearchMessages.UseReportConverter_back_to_bundle_index).append(CLOSE_A).append(CLOSE_P); //$NON-NLS-1$ 
1193                        buffer.append(W3C_FOOTER);
1194                        
1195                        //write the file
1196                        FileWriter fileWriter = new FileWriter(typefile);
1197                        writer = new PrintWriter(new BufferedWriter(fileWriter));
1198                        writer.print(buffer.toString());
1199                        writer.flush();
1200                }
1201                catch(IOException ioe) {
1202                        throw new Exception(NLS.bind(SearchMessages.ioexception_writing_html_file, typefile.getAbsolutePath()));
1203                }
1204                finally {
1205                        if(writer != null) {
1206                                writer.close();
1207                        }
1208                }
1209        }
1210        
1211        /**
1212         * Returns the header to use for the section that describes the type details table
1213         * @return the details header
1214         */
1215        protected String getTypeDetailsHeader() {
1216                return SearchMessages.UseReportConverter_reference_details;
1217        }
1218        
1219        /**
1220         * Returns the blurb that follows the type details header
1221         * @return the details information
1222         * @see #getTypeDetailsHeader()
1223         */
1224        protected String getTypeDetails() {
1225                return SearchMessages.UseReportConverter_click_an_entry_to_see_details;
1226        }
1227        
1228        /**
1229         * Returns the title to use for the type references page
1230         * @param typename
1231         * @return the type references page title
1232         */
1233        protected String getTypeTitle(String typename) {
1234                return NLS.bind(SearchMessages.UseReportConverter_usage_details, Signature.getSimpleName(typename));
1235        }
1236        
1237        /**
1238         * Returns the header to use for the types page. This is the first header on the page
1239         * @param typename
1240         * @return the type page header
1241         */
1242        protected String getTypeHeader(String typename) {
1243                return NLS.bind(SearchMessages.UseReportConverter_usage_details, Signature.getSimpleName(typename));
1244        }
1245        
1246        /**
1247         * Returns the nested table of references
1248         * @return the nested table of references as a string
1249         */
1250        String getReferencesTable(Member member) {
1251                StringBuffer buffer = new StringBuffer();
1252                Entry entry = null;
1253                buffer.append("<div colspan=\"6\" class=\"types\">\n"); //$NON-NLS-1$
1254                buffer.append("<table width=\"100%\" border=\"0\">\n"); //$NON-NLS-1$
1255                ArrayList refs = null;
1256                Reference ref = null;
1257                for (Iterator iter = member.children.entrySet().iterator(); iter.hasNext();) {
1258                        entry = (Entry) iter.next();
1259                        buffer.append("<tr align=\"left\"> \n"); //$NON-NLS-1$
1260                        buffer.append("<td colspan=\"3\" bgcolor=\"#CCCCCC\">").append(OPEN_B).append(entry.getKey()).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$
1261                        buffer.append(CLOSE_TR);
1262                        buffer.append("<tr bgcolor=\"#CC9933\">"); //$NON-NLS-1$
1263                        buffer.append("<td align=\"left\" width=\"92%\">").append(OPEN_B).append(SearchMessages.UseReportConverter_reference_location).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$ 
1264                        buffer.append("<td align=\"center\" width=\"8%\">").append(OPEN_B).append(SearchMessages.UseReportConverter_line_number).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$ 
1265                        buffer.append("<td align=\"center\" width=\"8%\">").append(OPEN_B).append(SearchMessages.UseReportConverter_reference_kind).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$ 
1266                        buffer.append(CLOSE_TR); 
1267                        refs = (ArrayList) entry.getValue();
1268                        Collections.sort(refs, compare);
1269                        for (Iterator iter2 = refs.iterator(); iter2.hasNext();) {
1270                                ref = (Reference) iter2.next();
1271                                try {
1272                                        String name = getDisplayName(ref.desc, true);
1273                                        buffer.append(OPEN_TR);
1274                                        buffer.append(OPEN_TD).append(name).append(CLOSE_TD); 
1275                                        buffer.append("<td align=\"center\">").append(ref.line).append(CLOSE_TD); //$NON-NLS-1$ 
1276                                        buffer.append("<td align=\"center\">").append(VisibilityModifiers.getVisibilityName(ref.vis)).append(CLOSE_TD); //$NON-NLS-1$ 
1277                                        buffer.append(CLOSE_TR); 
1278                                }
1279                                catch(CoreException ce) {
1280                                        ApiPlugin.log(ce);
1281                                }
1282                        }
1283                }
1284                buffer.append(CLOSE_TABLE); 
1285                buffer.append(CLOSE_DIV); 
1286                return buffer.toString();
1287        }
1288        
1289        /**
1290         * Returns the name to display for the given {@link IElementDescriptor} which can be qualified or not
1291         * @param desc
1292         * @param qualified
1293         * @return the (un)-qualified name to display for the given {@link IElementDescriptor}
1294         * @throws CoreException
1295         */
1296        String getDisplayName(IElementDescriptor desc, boolean qualified) throws CoreException {
1297                String displayname = null;
1298                switch(desc.getElementType()) {
1299                        case IElementDescriptor.TYPE: {
1300                                IReferenceTypeDescriptor rtype = (IReferenceTypeDescriptor) desc;
1301                                displayname = Signatures.getTypeSignature(rtype.getSignature(), rtype.getGenericSignature(), qualified);
1302                                break;
1303                        }
1304                        case IElementDescriptor.METHOD: {
1305                                IMethodDescriptor method = (IMethodDescriptor)desc;
1306                                if(qualified) {
1307                                        displayname = Signatures.getQualifiedMethodSignature(method);
1308                                }
1309                                else {
1310                                        displayname = Signatures.getMethodSignature(method);
1311                                }
1312                                break;
1313                        }
1314                        case IElementDescriptor.FIELD: {
1315                                IFieldDescriptor field = (IFieldDescriptor) desc;
1316                                if(qualified) {
1317                                        displayname = Signatures.getQualifiedFieldSignature(field);
1318                                }
1319                                else {
1320                                        displayname = field.getName();
1321                                }
1322                                break;
1323                        }
1324                }
1325                return displayname;
1326        }
1327        
1328        /**
1329         * Extracts underlying link text from the given absolute filename based off the root file
1330         * @param root
1331         * @param fileName
1332         * @return link text pruned via the given root file
1333         */
1334        String extractLinkFrom(File root, String fileName) {
1335                StringBuffer buffer = new StringBuffer();
1336                String substring = fileName.substring(root.getAbsolutePath().length()).replace('\\', '/');
1337                buffer.append('.');
1338                if(substring.charAt(0) != '/') {
1339                        buffer.append('/');
1340                }
1341                buffer.append(substring);
1342                return String.valueOf(buffer);
1343        }
1344        
1345        /**
1346         * Returns the page title for the index page
1347         * @return the index page title
1348         */
1349        protected String getIndexTitle() {
1350                return SearchMessages.UseReportConverter_bundle_usage_information;
1351        }
1352        
1353        /**
1354         * Returns the main header for the index page, this header appears as the first header for the page
1355         * @return the index page header
1356         */
1357        protected String getIndexHeader() {
1358                return SearchMessages.UseReportConverter_bundle_usage_information;
1359        }
1360        
1361        /**
1362         * Writes the main index file for the reports
1363         * @param reportsRoot
1364         */
1365        void writeIndexPage(List sortedreports, File reportsRoot) throws Exception {
1366                PrintWriter writer = null;
1367                try {
1368                        htmlIndex = new File(this.htmlLocation, "index.html"); //$NON-NLS-1$
1369                        if(!htmlIndex.exists()) {
1370                                htmlIndex.createNewFile();
1371                        }
1372                        StringBuffer buffer = new StringBuffer();
1373                        buffer.append(HTML_HEADER);
1374                        buffer.append(OPEN_HTML).append(OPEN_HEAD).append(CONTENT_TYPE_META);
1375                        writeMetadataHeaders(buffer);
1376                        buffer.append(OPEN_TITLE).append(getIndexTitle()).append(CLOSE_TITLE); 
1377                        buffer.append(CLOSE_HEAD); 
1378                        buffer.append(OPEN_BODY); 
1379                        buffer.append(OPEN_H3).append(getIndexHeader()).append(CLOSE_H3);
1380                        writeMetadataSummary(buffer);
1381                        buffer.append(OPEN_H4).append(SearchMessages.UseReportConvertor_additional_infos_section).append(CLOSE_H4); 
1382                        if(this.hasmissing) {
1383                                buffer.append(OPEN_P); 
1384                                buffer.append(NLS.bind(SearchMessages.UseReportConverter_missing_bundles_prevented_scan, 
1385                                                new String[] {" <a href=\"./missing.html\">", "</a>"})); //$NON-NLS-1$ //$NON-NLS-2$
1386                                buffer.append(CLOSE_P); 
1387                        }
1388                        buffer.append(OPEN_P); 
1389                        buffer.append(NLS.bind(SearchMessages.UseReportConverter_bundles_that_were_not_searched, new String[] {"<a href=\"./not_searched.html\">", "</a></p>\n"}));  //$NON-NLS-1$//$NON-NLS-2$
1390                        String additional = getAdditionalIndexInfo(sortedreports.size() > 0);
1391                        if(additional != null) {
1392                                buffer.append(additional);
1393                        }
1394                        if(sortedreports.size() > 0) {
1395                                buffer.append(OPEN_P).append(SearchMessages.UseReportConverter_inlined_description).append(CLOSE_P);
1396                                buffer.append(getReferencesTableHeader(SearchMessages.UseReportConverter_bundle));
1397                                if(sortedreports.size() > 0) {
1398                                        Report report = null;
1399                                        File refereehtml = null;
1400                                        String link = null;
1401                                        for(Iterator iter = sortedreports.iterator(); iter.hasNext();) {
1402                                                report = (Report) iter.next();
1403                                                if(report != null) {
1404                                                        refereehtml = new File(this.reportsRoot, report.name+File.separator+"index.html"); //$NON-NLS-1$
1405                                                        link = extractLinkFrom(this.reportsRoot, refereehtml.getAbsolutePath());
1406                                                        buffer.append(getReferenceTableEntry(report.counts, link, report.name));
1407                                                }
1408                                        }
1409                                        buffer.append(CLOSE_TABLE); 
1410                                }
1411                        }
1412                        else {
1413                                buffer.append(getNoReportsInformation()); 
1414                        }
1415                        buffer.append(W3C_FOOTER);
1416                        buffer.append(CLOSE_BODY).append(CLOSE_HTML);  
1417                        
1418                        //write the file
1419                        FileWriter fileWriter = new FileWriter(htmlIndex);
1420                        writer = new PrintWriter(new BufferedWriter(fileWriter));
1421                        writer.print(buffer.toString());
1422                        writer.flush();
1423                } catch (IOException e) {
1424                        throw new Exception(NLS.bind(SearchMessages.ioexception_writing_html_file, htmlIndex.getAbsolutePath()));
1425                } finally {
1426                        if (writer != null) {
1427                                writer.close();
1428                        }
1429                }
1430        }
1431        
1432        /**
1433         * @return the string to write if there are no reported bundles
1434         */
1435        protected String getNoReportsInformation() {
1436                StringBuffer buffer = new StringBuffer();
1437                buffer.append(OPEN_P).append(BR).append(SearchMessages.UseReportConverter_no_reported_usage).append(CLOSE_P); 
1438                return buffer.toString();
1439        }
1440        
1441        /**
1442         * This method is called during the HTML header creation phase to allow
1443         * META header elements to be written for metadata objects
1444         * @param buffer
1445         * @throws Exception
1446         */
1447        void writeMetadataHeaders(StringBuffer buffer) throws Exception {
1448                writeMetaTag(buffer, "description", SearchMessages.UseReportConverter_root_index_description); //$NON-NLS-1$
1449                //TODO could write metadata information here
1450        }
1451        
1452        /**
1453         * This method is called during the initial index page creation to allow
1454         * and executive summary of the use scan to be written out from metadata
1455         * @param buffer
1456         * @throws Exception
1457         */
1458        void writeMetadataSummary(StringBuffer buffer) throws Exception {
1459                buffer.append(OPEN_H4).append(SearchMessages.UseReportConverter_scan_details).append(CLOSE_H4);
1460                getMetadata();
1461                if(this.metadata != null) {
1462                        buffer.append("<table border=\"0px\" title=\"").append(SearchMessages.UseReportConverter_scan_details).append("\"width=\"50%\">"); //$NON-NLS-1$ //$NON-NLS-2$ 
1463                        buffer.append(OPEN_TR);
1464                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_scan_date).append(CLOSE_TD); 
1465                        buffer.append(openTD(36)).append(this.metadata.getRunAtDate()).append(CLOSE_TD); 
1466                        buffer.append(CLOSE_TR);
1467                        buffer.append(OPEN_TR);
1468                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_description).append(CLOSE_TD); 
1469                        String desc = this.metadata.getDescription();
1470                        buffer.append(openTD(36)).append((desc != null ? desc : SearchMessages.UseReportConverter_none)).append(CLOSE_TD); 
1471                        buffer.append(CLOSE_TR);
1472                        buffer.append(OPEN_TR);
1473                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_includes_API_refs).append(CLOSE_TD); 
1474                        buffer.append(openTD(36)).append(this.metadata.includesAPI()).append(CLOSE_TD); 
1475                        buffer.append(CLOSE_TR);
1476                        buffer.append(OPEN_TR);
1477                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_includes_internal_refs).append(CLOSE_TD); 
1478                        buffer.append(openTD(36)).append(this.metadata.includesInternal()).append(CLOSE_TD); 
1479                        buffer.append(CLOSE_TR);
1480                        buffer.append(OPEN_TR);
1481                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_baseline_loc).append(CLOSE_TD); 
1482                        buffer.append(openTD(36)).append(this.metadata.getBaselineLocation()).append(CLOSE_TD); 
1483                        buffer.append(CLOSE_TR);
1484                        buffer.append(OPEN_TR);
1485                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_scope_pattern).append(CLOSE_TD); 
1486                        buffer.append(openTD(36)).append(this.metadata.getScopePattern()).append(CLOSE_TD); 
1487                        buffer.append(CLOSE_TR);
1488                        buffer.append(OPEN_TR);
1489                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_reference_pattern).append(CLOSE_TD); 
1490                        buffer.append(openTD(36)).append(this.metadata.getReferencePattern()).append(CLOSE_TD); 
1491                        buffer.append(CLOSE_TR);
1492                        buffer.append(OPEN_TR);
1493                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_report_location).append(CLOSE_TD); 
1494                        buffer.append(openTD(36)).append(this.metadata.getReportLocation()).append(CLOSE_TD); 
1495                        buffer.append(CLOSE_TR);
1496                        buffer.append(OPEN_TR);
1497                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_api_pattern).append(CLOSE_TD); 
1498                        buffer.append(openTD(36)); 
1499                        String[] patterns = this.metadata.getApiPatterns();
1500                        if(patterns != null) {
1501                                buffer.append(this.metadata.getApiPatterns());
1502                                for (int i = 0; i < patterns.length; i++) {
1503                                        buffer.append(patterns[i]).append(BR);
1504                                }
1505                        }
1506                        else {
1507                                buffer.append(SearchMessages.UseReportConverter_none);
1508                        }
1509                        buffer.append(CLOSE_TD);
1510                        buffer.append(CLOSE_TR);
1511                        buffer.append(OPEN_TR);
1512                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_internal_patterns).append(CLOSE_TD); 
1513                        buffer.append(openTD(36)); 
1514                        patterns = this.metadata.getInternalPatterns();
1515                        if(patterns != null) {
1516                                for (int i = 0; i < patterns.length; i++) {
1517                                        buffer.append(patterns[i]).append(BR);
1518                                }
1519                        }
1520                        else {
1521                                buffer.append(SearchMessages.UseReportConverter_none); 
1522                        }
1523                        buffer.append(CLOSE_TD);
1524                        buffer.append(CLOSE_TR);
1525                        buffer.append(OPEN_TR);
1526                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_archive_patterns).append(CLOSE_TD); 
1527                        buffer.append(openTD(36)); 
1528                        patterns = this.metadata.getArchivePatterns();
1529                        if(patterns != null) {
1530                                for (int i = 0; i < patterns.length; i++) {
1531                                        buffer.append(patterns[i]).append(BR);
1532                                }
1533                        }
1534                        else {
1535                                buffer.append(SearchMessages.UseReportConverter_none); 
1536                        }
1537                        buffer.append(CLOSE_TD);
1538                        buffer.append(CLOSE_TR);
1539                        buffer.append(OPEN_TR);
1540                        buffer.append(openTD(14)).append(SearchMessages.UseReportConverter_filter_pattern).append(CLOSE_TD); 
1541                        buffer.append(openTD(36)); 
1542                        if(this.filterPatterns != null) {
1543                                for (int i = 0; i < this.filterPatterns.length; i++) {
1544                                        buffer.append(this.filterPatterns[i].pattern()).append(BR);
1545                                }
1546                        }
1547                        else {
1548                                buffer.append(SearchMessages.UseReportConverter_none); 
1549                        }
1550                        buffer.append(CLOSE_TD);
1551                        buffer.append(CLOSE_TR);
1552                        buffer.append(CLOSE_TABLE);
1553                }
1554                else {
1555                        buffer.append(OPEN_P).append(SearchMessages.UseReportConverter_no_additional_scan_info).append(CLOSE_P);
1556                }
1557        }
1558        
1559        /**
1560         * Returns the use metadata from this scan
1561         * @return
1562         * @throws Exception
1563         */
1564        UseMetadata getMetadata() throws Exception {
1565                if(this.metadata == null) {
1566                        File xml = null;
1567                        try {
1568                                xml = new File(this.reportsRoot, "meta"+XML_EXTENSION);  //$NON-NLS-1$
1569                                if(xml.exists()) {
1570                                        String xmlstr = Util.getFileContentAsString(xml);
1571                                        Element doc = Util.parseDocument(xmlstr);
1572                                        this.metadata = new UseMetadata();
1573                                        Element element = null;
1574                                        String value = null, name = null;
1575                                        NodeList nodes = doc.getElementsByTagName("*"); //$NON-NLS-1$
1576                                        for(int i = 0; i < nodes.getLength(); i++) {
1577                                                element = (Element) nodes.item(i);
1578                                                value = element.getAttribute(UseMetadata.VALUE);
1579                                                name = element.getNodeName();
1580                                                if(UseMetadata.FLAGS.equals(name)) {
1581                                                        try {
1582                                                                this.metadata.setSearchflags(Integer.parseInt(value));
1583                                                        }
1584                                                        catch(NumberFormatException nfe) {
1585                                                                //do nothing
1586                                                        }
1587                                                        continue;
1588                                                }
1589                                                if(UseMetadata.RUNATDATE.equals(name)) {
1590                                                        this.metadata.setRunAtDate(value);
1591                                                        continue;
1592                                                }
1593                                                if(UseMetadata.DESCRIPTION.equals(name)) {
1594                                                        this.metadata.setDescription(value);
1595                                                        continue;
1596                                                }
1597                                                if(UseMetadata.BASELINELOCATION.equals(name)) {
1598                                                        this.metadata.setBaselineLocation(value);
1599                                                        continue;
1600                                                }
1601                                                if(UseMetadata.REPORTLOCATION.equals(name)) {
1602                                                        this.metadata.setReportLocation(value);
1603                                                        continue;
1604                                                }
1605                                                if(UseMetadata.SCOPEPATTERN.equals(name)) {
1606                                                        this.metadata.setScopePattern(value);
1607                                                        continue;
1608                                                }
1609                                                if(UseMetadata.REFERENCEPATTERN.equals(name)) {
1610                                                        this.metadata.setReferencePattern(value);
1611                                                        continue;
1612                                                }
1613                                                if(UseMetadata.APIPATTERNS.equals(name)) {
1614                                                        this.metadata.setApiPatterns(readPatterns(element));
1615                                                        continue;
1616                                                }
1617                                                if(UseMetadata.INTERNALPATTERNS.equals(name)) {
1618                                                        this.metadata.setInternalPatterns(readPatterns(element));
1619                                                        continue;
1620                                                }
1621                                                if(UseMetadata.ARCHIVEPATTERNS.equals(name)) {
1622                                                        this.metadata.setArchivePatterns(readPatterns(element));
1623                                                        continue;
1624                                                }
1625                                        }
1626                                }
1627                        }
1628                        catch (CoreException e) {
1629                                throw new Exception(NLS.bind(SearchMessages.UseReportConverter_core_exep_reading_metadata, xml.getAbsolutePath()));
1630                        }
1631                }
1632                return this.metadata;
1633        }
1634        
1635        /**
1636         * Reads saved patterns from the meta.xml file
1637         * @param element
1638         * @return the array of patterns or <code>null</code>
1639         */
1640        private String[] readPatterns(Element element) {
1641                String[] pats = null;
1642                NodeList patterns = element.getElementsByTagName(UseMetadata.PATTERN);
1643                int length = patterns.getLength();
1644                if(length > 0) {
1645                        pats = new String[length];
1646                        for (int j = 0; j < length; j++) {
1647                                pats[j] = ((Element)patterns.item(j)).getAttribute(UseMetadata.VALUE);
1648                        }
1649                }
1650                return pats;
1651        }
1652        
1653        /**
1654         * Writes out a META tag of the kind <code>description</code>
1655         * @param buffer
1656         * @param description
1657         */
1658        void writeMetaTag(StringBuffer buffer, String name, String content) {
1659                buffer.append("<meta name=\"").append(name).append("\" content=\"").append(content).append("\">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1660        }
1661        
1662        /**
1663         * Returns the HTML markup for the default references table header.
1664         * Where the first column contains the linked item and the following five columns are 
1665         * API, Internal, Permissible, Fragment-Permissible and Other reference counts respectively
1666         * @param columnname
1667         * @return the default references table header
1668         */
1669        String getReferencesTableHeader(String columnname) {
1670                StringBuffer buffer = new StringBuffer();
1671                buffer.append(OPEN_H4).append(SearchMessages.UseReportConverter_references).append(CLOSE_H4);
1672                buffer.append("<table border=\"1\" width=\"70%\">\n"); //$NON-NLS-1$
1673                buffer.append(OPEN_TR); 
1674                buffer.append("\t<td bgcolor=\"#CC9933\" width=\"30%\">").append(OPEN_B).append(columnname).append(CLOSE_B).append(CLOSE_TD); //$NON-NLS-1$ 
1675                buffer.append("\t<td bgcolor=\"#CC9933\" align=\"center\" width=\"8%\" title=\""); //$NON-NLS-1$
1676                buffer.append(SearchMessages.UseReportConverter_api_ref_description).append("\"\">"); //$NON-NLS-1$
1677                buffer.append(OPEN_B).append(SearchMessages.UseReportConverter_api_references).append(CLOSE_B).append(CLOSE_TD); 
1678                buffer.append("\t<td bgcolor=\"#CC9933\" align=\"center\" width=\"8%\" title=\""); //$NON-NLS-1$
1679                buffer.append(SearchMessages.UseReportConverter_internal_ref_description).append("\">"); //$NON-NLS-1$
1680                buffer.append(OPEN_B).append(SearchMessages.UseReportConverter_internal_references).append(CLOSE_B).append(CLOSE_TD); 
1681                buffer.append("\t<td bgcolor=\"#CC9933\" align=\"center\" width=\"8%\" title=\""); //$NON-NLS-1$
1682                buffer.append(SearchMessages.UseReportConverter_permissible_ref_description).append("\">"); //$NON-NLS-1$
1683                buffer.append(OPEN_B).append(SearchMessages.UseReportConverter_internal_permissible_references).append(CLOSE_B).append(CLOSE_TD); 
1684                buffer.append("\t<td bgcolor=\"#CC9933\" align=\"center\" width=\"8%\" title=\""); //$NON-NLS-1$
1685                buffer.append(SearchMessages.UseReportConverter_fragment_ref_description).append("\">"); //$NON-NLS-1$
1686                buffer.append(OPEN_B).append(SearchMessages.UseReportConverter_fragment_permissible_references).append(CLOSE_B).append(CLOSE_TD);  
1687                buffer.append("\t<td bgcolor=\"#CC9933\" align=\"center\" width=\"8%\" title=\""); //$NON-NLS-1$
1688                buffer.append(SearchMessages.UseReportConverter_other_ref_description).append("\">"); //$NON-NLS-1$
1689                buffer.append(OPEN_B).append(SearchMessages.UseReportConverter_other_references).append(CLOSE_B).append(CLOSE_TD);  
1690                buffer.append(CLOSE_TR); 
1691                return buffer.toString();
1692        }
1693        
1694        /**
1695         * Returns the HTML markup for one entry in the default references table.
1696         * Where the first column contains the linked item and the following five columns are 
1697         * API, Internal, Permissible, Fragment-Permissible and Other reference counts respectively
1698         * @param counts
1699         * @param link
1700         * @param linktext
1701         * @return a single reference table entry
1702         */
1703        String getReferenceTableEntry(CountGroup counts, String link, String linktext) {
1704                StringBuffer buffer = new StringBuffer();
1705                buffer.append("<tr bgcolor=\"").append((counts.getTotalInternalRefCount() > 0 ? INTERNAL_REFS_COLOUR : NORMAL_REFS_COLOUR)).append("\">\n");  //$NON-NLS-1$//$NON-NLS-2$
1706                buffer.append("\t<td><a href=\"").append(link).append("\">").append(linktext).append("</a>").append(CLOSE_TD); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1707                buffer.append("\t<td align=\"center\">").append(counts.getTotalApiRefCount()).append(CLOSE_TD); //$NON-NLS-1$ 
1708                buffer.append("\t<td align=\"center\">").append(counts.getTotalInternalRefCount()).append(CLOSE_TD); //$NON-NLS-1$ 
1709                buffer.append("\t<td align=\"center\">").append(counts.getTotalPermissableRefCount()).append(CLOSE_TD); //$NON-NLS-1$ 
1710                buffer.append("\t<td align=\"center\">").append(counts.getTotalFragmentPermissibleRefCount()).append(CLOSE_TD); //$NON-NLS-1$ 
1711                buffer.append("\t<td align=\"center\">").append(counts.getTotalOtherRefCount()).append(CLOSE_TD); //$NON-NLS-1$ 
1712                buffer.append(CLOSE_TR); 
1713                return buffer.toString();
1714        }
1715        
1716        /**
1717         * Allows additional infos to be added to the HTML at the top of the report page
1718         * @param hasreports
1719         * 
1720         * @return additional information string to add
1721         */
1722        protected String getAdditionalIndexInfo(boolean hasreports) {
1723                return null;
1724        }
1725        
1726        /**
1727         * Returns HTML summary for references from a specific component.
1728         * 
1729         * @param typename
1730         * @param counts
1731         * @return HTML as a string
1732         */
1733        protected String getTypeCountSummary(String typename, CountGroup counts, int membercount) {
1734                StringBuffer buffer = new StringBuffer();
1735                buffer.append(OPEN_H4).append(SearchMessages.UseReportConverter_summary).append(CLOSE_H4); 
1736                buffer.append(OPEN_P).append(NLS.bind(SearchMessages.UseReportConverter___has_total_refs, new String[] {typename, Integer.toString(counts.getTotalRefCount()), Integer.toString(membercount)})).append(CLOSE_P);  
1737                return buffer.toString();
1738        }
1739}

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