private void addVersion() {
   RythmEngine e = engine();
   if (!e.reloadByIncClassVersion()) return;
   TemplateClassManager tcc = engine().classes;
   tcc.clsNameIdx.remove(name());
   // List<TemplateClass> allEmbedded = tcc.getEmbeddedClasses(name0());
   version = nextVersion.getAndIncrement();
   tcc.clsNameIdx.put(name(), this);
 }
 public String name() {
   // return isInner() ? name : name + "v" + version;
   RythmEngine e = engine();
   String n = (!e.reloadByIncClassVersion() || isInner()) ? name : name + "v" + version;
   return n;
 }
  /**
   * @return true if this class has changes refreshed, otherwise this class has not been changed yet
   */
  public boolean refresh(boolean forceRefresh) {
    if (refreshing()) return false;
    if (inner) return false;
    try {
      RythmEngine e = engine();
      refreshing(true);
      if (!templateResource.isValid()) {
        // it is removed?
        isValid = false;
        engine().classes.remove(this);
        return false;
      }
      if (null == name) {
        // this is the root level template class
        root = this;
        name = templateResource.getSuggestedClassName() + CN_SUFFIX;
        // name = templateResource.getSuggestedClassName();
        if (e.reloadByIncClassVersion()) version = nextVersion.getAndIncrement();
        engine().classes.add(this);
      }

      if (null == javaSource) {
        engine().classCache.loadTemplateClass(this);
        if (null != javaSource) {
          // try refresh extended template class if there is
          Pattern p =
              Pattern.compile(
                  ".*extends\\s+([a-zA-Z0-9_]+)\\s*\\{\\s*\\/\\/<extended_resource_key\\>(.*)\\<\\/extended_resource_key\\>.*",
                  Pattern.DOTALL);
          Matcher m = p.matcher(javaSource);
          if (m.matches()) {
            String extended = m.group(1);
            TemplateClassManager tcm = engine().classes;
            extendedTemplateClass = tcm.getByClassName(extended);
            if (null == extendedTemplateClass) {
              String extendedResourceKey = m.group(2);
              extendedTemplateClass = tcm.getByTemplate(extendedResourceKey);
              if (null == extendedTemplateClass) {
                extendedTemplateClass = new TemplateClass(extendedResourceKey, engine());
                extendedTemplateClass.refresh();
              }
            }
            engine().addExtendRelationship(extendedTemplateClass, this);
          }
        }
      }

      boolean extendedTemplateChanged = false;
      if (extendedTemplateClass != null)
        extendedTemplateChanged = extendedTemplateClass.refresh(forceRefresh);
      boolean includedTemplateChanged = false;
      if (includedTemplateClasses.size() == 0
          && !S.isEmpty(includeTemplateClassNames)
          && !NO_INCLUDE_CLASS.equals(includeTemplateClassNames)) {
        // just loaded from persistent store
        for (String tcName : includeTemplateClassNames.split(",")) {
          if (S.isEmpty(tcName)) continue;
          tcName = tcName.trim();
          String fullName = engine().testTag(tcName, this);
          if (null == fullName) {
            logger.warn("Unable to load included template class from name: %s", tcName);
            continue;
          }
          TemplateClass tc = engine().getTemplateClassFromTagName(fullName);
          if (null == tc) {
            logger.warn("Unable to load included template class from name: %s", tcName);
            continue;
          }
          includedTemplateClasses.add(tc);
        }
      }
      for (TemplateClass tc : includedTemplateClasses) {
        if (tc.refresh(forceRefresh)) {
          includedTemplateChanged = true;
          break;
        }
      }

      if (extendedTemplateChanged && engine().reloadByRestart() && !forceRefresh) {
        reset();
        compiled = false;
        engine().restart(new ClassReloadException("extended class changed"));
        refreshing(false);
        refresh(forceRefresh);
        return true; // pass refresh state to sub template
      }
      // templateResource.refresh() must be put at first so we make sure resource get refreshed

      boolean resourceChanged = templateResource.refresh();
      boolean refresh =
          resourceChanged
              || forceRefresh
              || (null == javaSource)
              || includedTemplateChanged
              || extendedTemplateChanged;
      if (!refresh) return false;

      // now start generate source and compile source to byte code
      reset();
      buildSourceCode();
      engine().classCache.cacheTemplateClassSource(this); // cache source code for debugging purpose
      if (!codeBuilder.isRythmTemplate()) {
        isValid = false;
        engine().classes.remove(this);
        return false;
      }
      isValid = true;
      // if (!engine().isProd  Mode()) logger.info(javaSource);
      compiled = false;
      return true;
    } finally {
      refreshing(false);
    }
  }
 private TemplateClass(RythmEngine engine) {
   this.engine = null == engine ? null : engine.isSingleton() ? null : engine;
 }