Home | History | Annotate | Download | only in doclava
      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    */
     40   public void addSiteUrl(String name, URL site) {
     41     federatedUrls.put(name, site);
     42   }
     43 
     44   public void addSiteApi(String name, String file) {
     45     federatedXmls.put(name, file);
     46   }
     47 
     48   public void tag(ClassInfo classDoc) {
     49     initialize();
     50     for (FederatedSite site : federatedSites) {
     51       applyFederation(site, new ClassInfo[] { classDoc });
     52     }
     53   }
     54 
     55   public void tagAll(ClassInfo[] classDocs) {
     56     initialize();
     57     for (FederatedSite site : federatedSites) {
     58       applyFederation(site, classDocs);
     59     }
     60   }
     61 
     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 
     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 
    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 
    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 
    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 
    144   private void federateClass(FederatedSite source, ClassInfo doc) {
    145     doc.addFederatedReference(source);
    146   }
    147 
    148   private void federatePackage(FederatedSite source, PackageInfo pkg) {
    149     pkg.addFederatedReference(source);
    150   }
    151 }