docs: public PolicyFactory and(PolicyFactory f) {
      ImmutableMap.Builder<String, ElementAndAttributePolicies> b
          = ImmutableMap.builder();
      // Merge this and f into a map of element names to attribute policies.
      for (Map.Entry<String, ElementAndAttributePolicies> e
          : policies.entrySet()) {
        String elName = e.getKey();
        ElementAndAttributePolicies p = e.getValue();
        ElementAndAttributePolicies q = f.policies.get(elName);
        if (q != null) {
          p = p.and(q);
        } else {
          // Mix in any globals that are not already taken into account in this.
          p = p.andGlobals(f.globalAttrPolicies);
        }
        b.put(elName, p);
      }
      // Handle keys that are in f but not in this.
      for (Map.Entry<String, ElementAndAttributePolicies> e
          : f.policies.entrySet()) {
        String elName = e.getKey();
        if (!policies.containsKey(elName)) {
          ElementAndAttributePolicies p = e.getValue();
          // Mix in any globals that are not already taken into account in this.
          p = p.andGlobals(globalAttrPolicies);
          b.put(elName, p);
        }
      }
      ImmutableSet<String> allTextContainers;
      if (this.textContainers.containsAll(f.textContainers)) {
        allTextContainers = this.textContainers;
      } else if (f.textContainers.containsAll(this.textContainers)) {
        allTextContainers = f.textContainers;
      } else {
        allTextContainers = ImmutableSet.<String>builder()
          .addAll(this.textContainers)
          .addAll(f.textContainers)
          .build();
      }
      ImmutableMap<String, AttributePolicy> allGlobalAttrPolicies;
      if (f.globalAttrPolicies.isEmpty()) {
        allGlobalAttrPolicies = this.globalAttrPolicies;
      } else if (this.globalAttrPolicies.isEmpty()) {
        allGlobalAttrPolicies = f.globalAttrPolicies;
      } else {
        ImmutableMap.Builder<String, AttributePolicy> ab = ImmutableMap.builder();
        for (Map.Entry<String, AttributePolicy> e
            : this.globalAttrPolicies.entrySet()) {
          String attrName = e.getKey();
          ab.put(
              attrName,
              AttributePolicy.Util.join(
                  e.getValue(), f.globalAttrPolicies.get(attrName)));
        }
        for (Map.Entry<String, AttributePolicy> e
            : f.globalAttrPolicies.entrySet()) {
          String attrName = e.getKey();
          if (!this.globalAttrPolicies.containsKey(attrName)) {
            ab.put(attrName, e.getValue());
          }
        }
        allGlobalAttrPolicies = ab.build();
      }
      HtmlStreamEventProcessor compositionOfPreprocessors
          = HtmlStreamEventProcessor.Processors.compose(
              this.preprocessor, f.preprocessor);
      HtmlStreamEventProcessor compositionOfPostprocessors
          = HtmlStreamEventProcessor.Processors.compose(
              this.postprocessor, f.postprocessor);
      return new PolicyFactory(
          b.build(), allTextContainers, allGlobalAttrPolicies,
          compositionOfPreprocessors, compositionOfPostprocessors);
    }