All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mustachejava.codes.ExtendCode Maven / Gradle / Ivy

There is a newer version: 0.9.13
Show newest version
package com.github.mustachejava.codes;

import com.github.mustachejava.Code;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheException;
import com.github.mustachejava.TemplateContext;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Extending a template through in-place replacement of the overridden codes.
 * 
 * User: sam
 * Date: 11/27/11
 * Time: 10:39 AM
 */
public class ExtendCode extends PartialCode {

  private final DefaultMustacheFactory mf;

  public ExtendCode(TemplateContext tc, DefaultMustacheFactory mf, Mustache codes, String name) throws MustacheException {
    super(tc, mf, codes, "<", name);
    this.mf = mf;
  }

  private Code[] replaceCodes(Code[] supercodes, Map replaceMap, Set seen) {
    Code[] newcodes = supercodes.clone();
    for (int i = 0; i < supercodes.length; i++) {
      Code code = supercodes[i];
      if (seen.add(code)) {
        if (code instanceof ExtendNameCode) {
          ExtendNameCode enc = (ExtendNameCode) code;
          ExtendNameCode extendReplaceCode = replaceMap.get(enc.getName());
          if (extendReplaceCode != null) {
            ExtendNameCode newcode = (ExtendNameCode) (newcodes[i] = (Code) extendReplaceCode.clone());
            // We need to set the appended text of the new code to that of the old code
            newcode.appended = enc.appended;
          } else {
            enc.setCodes(replaceCodes(enc.getCodes(), replaceMap, seen));
          }
        } else {
          if (code instanceof ExtendCheckNameCode) {
            ExtendCheckNameCode ecnc = (ExtendCheckNameCode) code;
            if (!replaceMap.containsKey(ecnc.getName())) {
              code.setCodes(new Code[0]);
            }
          }
          Code[] codes = code.getCodes();
          if (codes != null) {
            code.setCodes(replaceCodes(codes, replaceMap, seen));
          }
        }
        seen.remove(code);
      }
    }
    return newcodes;
  }

  @SuppressWarnings("StatementWithEmptyBody")
  @Override
  public synchronized void init() {
    filterText();
    Map replaceMap = new HashMap<>();
    for (Code code : mustache.getCodes()) {
      if (code instanceof ExtendNameCode) {
        // put name codes in the map
        ExtendNameCode erc = (ExtendNameCode) code;
        replaceMap.put(erc.getName(), erc);
        erc.init();
      } else if ((code instanceof WriteCode) || (code instanceof CommentCode)) {
        // ignore text and comments
      } else {
        // fail on everything else
        throw new IllegalArgumentException(
                "Illegal code in extend section: " + code.getClass().getName());
      }
    }
    Mustache original = mf.compilePartial(partialName());
    partial = (Mustache) original.clone();
    Code[] supercodes = partial.getCodes();
    // recursively replace named sections with replacements
    Set seen = new HashSet<>();
    seen.add(partial);
    partial.setCodes(replaceCodes(supercodes, replaceMap, seen));
  }

}