1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.doclava; 18 19 import com.google.doclava.apicheck.ApiParseException; 20 import java.net.URL; 21 import java.util.ArrayList; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 26 /** 27 * Cross-references documentation among different libraries. A FederationTagger 28 * is populated with a list of {@link FederatedSite} objects which are linked 29 * against when overlapping content is discovered. 30 */ 31 public final class FederationTagger { 32 private final Map<String, URL> federatedUrls = new HashMap<String, URL>(); 33 private final Map<String, String> federatedXmls = new HashMap<String, String>(); 34 private final List<FederatedSite> federatedSites = new ArrayList<FederatedSite>(); 35 private boolean initialized = false; 36 /** 37 * Adds a Doclava documentation site for federation. Accepts the base URL of 38 * the remote API. 39 */ addSiteUrl(String name, URL site)40 public void addSiteUrl(String name, URL site) { 41 federatedUrls.put(name, site); 42 } 43 addSiteApi(String name, String file)44 public void addSiteApi(String name, String file) { 45 federatedXmls.put(name, file); 46 } 47 tag(ClassInfo classDoc)48 public void tag(ClassInfo classDoc) { 49 initialize(); 50 for (FederatedSite site : federatedSites) { 51 applyFederation(site, new ClassInfo[] { classDoc }); 52 } 53 } 54 tagAll(ClassInfo[] classDocs)55 public void tagAll(ClassInfo[] classDocs) { 56 initialize(); 57 for (FederatedSite site : federatedSites) { 58 applyFederation(site, classDocs); 59 } 60 } 61 initialize()62 private void initialize() { 63 if (initialized) { 64 return; 65 } 66 67 for (String name : federatedXmls.keySet()) { 68 if (!federatedUrls.containsKey(name)) { 69 Errors.error(Errors.NO_FEDERATION_DATA, null, "Unknown documentation site for " + name); 70 } 71 } 72 73 for (String name : federatedUrls.keySet()) { 74 try { 75 if (federatedXmls.containsKey(name)) { 76 federatedSites.add(new FederatedSite(name, federatedUrls.get(name), 77 federatedXmls.get(name))); 78 } else { 79 federatedSites.add(new FederatedSite(name, federatedUrls.get(name))); 80 } 81 } catch (ApiParseException e) { 82 String error = "Could not add site for federation: " + name; 83 if (e.getMessage() != null) { 84 error += ": " + e.getMessage(); 85 } 86 Errors.error(Errors.NO_FEDERATION_DATA, null, error); 87 } 88 } 89 90 initialized = true; 91 } 92 applyFederation(FederatedSite federationSource, ClassInfo[] classDocs)93 private void applyFederation(FederatedSite federationSource, ClassInfo[] classDocs) { 94 for (ClassInfo classDoc : classDocs) { 95 PackageInfo packageSpec 96 = federationSource.apiInfo().getPackages().get(classDoc.containingPackage().name()); 97 98 if (packageSpec == null) { 99 continue; 100 } 101 102 ClassInfo classSpec = packageSpec.allClasses().get(classDoc.name()); 103 104 if (classSpec == null) { 105 continue; 106 } 107 108 federateMethods(federationSource, classSpec, classDoc); 109 federateConstructors(federationSource, classSpec, classDoc); 110 federateFields(federationSource, classSpec, classDoc); 111 federateClass(federationSource, classDoc); 112 federatePackage(federationSource, classDoc.containingPackage()); 113 } 114 } 115 federateMethods(FederatedSite site, ClassInfo federatedClass, ClassInfo localClass)116 private void federateMethods(FederatedSite site, ClassInfo federatedClass, ClassInfo localClass) { 117 for (MethodInfo method : localClass.methods()) { 118 for (ClassInfo superclass : federatedClass.hierarchy()) { 119 if (superclass.allMethods().containsKey(method.getHashableName())) { 120 method.addFederatedReference(site); 121 break; 122 } 123 } 124 } 125 } 126 federateConstructors(FederatedSite site, ClassInfo federatedClass, ClassInfo localClass)127 private void federateConstructors(FederatedSite site, ClassInfo federatedClass, 128 ClassInfo localClass) { 129 for (MethodInfo constructor : localClass.constructors()) { 130 if (federatedClass.hasConstructor(constructor)) { 131 constructor.addFederatedReference(site); 132 } 133 } 134 } 135 federateFields(FederatedSite site, ClassInfo federatedClass, ClassInfo localClass)136 private void federateFields(FederatedSite site, ClassInfo federatedClass, ClassInfo localClass) { 137 for (FieldInfo field : localClass.fields()) { 138 if (federatedClass.allFields().containsKey(field.name())) { 139 field.addFederatedReference(site); 140 } 141 } 142 } 143 federateClass(FederatedSite source, ClassInfo doc)144 private void federateClass(FederatedSite source, ClassInfo doc) { 145 doc.addFederatedReference(source); 146 } 147 federatePackage(FederatedSite source, PackageInfo pkg)148 private void federatePackage(FederatedSite source, PackageInfo pkg) { 149 pkg.addFederatedReference(source); 150 } 151 }