gt:         TreeMap<Ident,MClass> lConts = new TreeMap<Ident, MClass>();
context: package org.opendaylight.opflex.genie.content.format.agent.meta.cpp;
  
  import java.util.Collection;
  import java.util.Map;
  import java.util.TreeMap;
  
  import org.opendaylight.opflex.genie.content.model.mclass.MClass;
  import org.opendaylight.opflex.genie.content.model.mconst.ConstAction;
  import org.opendaylight.opflex.genie.content.model.mconst.MConst;
  import org.opendaylight.opflex.genie.content.model.mnaming.MNameComponent;
  import org.opendaylight.opflex.genie.content.model.mnaming.MNameRule;
  import org.opendaylight.opflex.genie.content.model.mownership.MOwner;
  import org.opendaylight.opflex.genie.content.model.mprop.MProp;
  import org.opendaylight.opflex.genie.content.model.mtype.MType;
  import org.opendaylight.opflex.genie.content.model.mtype.MTypeHint;
  import org.opendaylight.opflex.genie.content.model.mtype.TypeInfo;
  import org.opendaylight.opflex.genie.engine.file.WriteStats;
  import org.opendaylight.opflex.genie.engine.format.*;
  import org.opendaylight.opflex.genie.engine.model.Ident;
  import org.opendaylight.opflex.genie.engine.model.Item;
  import org.opendaylight.opflex.genie.engine.proc.Config;
  
  /**
   * Created by midvorki on 9/24/14.
   */
  public class FMetaDef
          extends GenericFormatterTask
  {
      public FMetaDef(
              FormatterCtx aInFormatterCtx,
              FileNameRule aInFileNameRule,
              Indenter aInIndenter,
              BlockFormatDirective aInHeaderFormatDirective,
              BlockFormatDirective aInCommentFormatDirective,
              boolean aInIsUserFile,
              WriteStats aInStats)
      {
          super(aInFormatterCtx,
                aInFileNameRule,
                aInIndenter,
                aInHeaderFormatDirective,
                aInCommentFormatDirective,
                aInIsUserFile,
                aInStats);
      }
  
      /**
       * Optional API required by the framework for transformation of file naming rule for the corresponding
       * generated file. This method can customize the location for the generated file.
       * @param aInFnr file name rule template
       * @return transformed file name rule
       */
      public static FileNameRule transformFileNameRule(FileNameRule aInFnr)
      {
          String lOldRelativePath = aInFnr.getRelativePath();
          String lNewRelativePath = lOldRelativePath + "/src/";
  
          FileNameRule lFnr = new FileNameRule(
                  lNewRelativePath,
                  null,
                  aInFnr.getFilePrefix(),
                  aInFnr.getFileSuffix(),
                  aInFnr.getFileExtension(),
                  "metadata");
  
          return lFnr;
      }
  
      public void generate()
      {
          out.println(0, "#include <boost/assign/list_of.hpp>");
          out.println(0, "#include <" + Config.getProjName() + "/metadata/metadata.hpp>");
          out.println(0, "#include <" + Config.getProjName() + "/dmtree/Root.hpp>");
  
          out.println(0, "namespace " + Config.getProjName());
          out.println(0, "{");
  
          generateMetaAccessor(0);
  
          out.println(0, "} // namespace " + Config.getProjName());
      }
  
      private void generateMetaAccessor(int aInIndent)
      {
          out.println(aInIndent, "const opflex::modb::ModelMetadata& getMetadata()");
          out.println(aInIndent, "{");
          out.println(aInIndent + 1, "using namespace opflex::modb;");
          out.println(aInIndent + 1, "using namespace boost::assign;");
              out.println(aInIndent + 1, "static const opflex::modb::ModelMetadata metadata(\"" + 
                      Config.getProjName() + "\", ");
              generateClassDefs(aInIndent + 2);
              out.println(aInIndent + 2, ");");
              out.println(aInIndent + 1, "return metadata;");
          out.println(aInIndent, "}");
      }
  
      private void generateClassDefs(int aInIndent)
      {
          out.println(aInIndent, "list_of");
          for (Item lIt : MClass.getConcreteClasses())
          {
              MClass lClass = (MClass) lIt;
              if (lClass.isConcrete())
              {
                  genMo(aInIndent + 2, lClass);
              }
          }
      }
  
      public static String getClassType(MClass aIn)
      {
          if (isPolicy(aIn))
          {
              return "ClassInfo::POLICY";
          }
          else if (isObservable(aIn))
          {
              return "ClassInfo::OBSERVABLE";
          }
          else if (isRelationshipSource(aIn))
          {
              return "ClassInfo::RELATIONSHIP";
          }
          else if (isRelationshipTarget(aIn))
          {
              return "ClassInfo::REVERSE_RELATIONSHIP";
          }
          else  if (isRelationshipResolver(aIn))
          {
              return "ClassInfo::RESOLVER";
          }
          else if (!aIn.isConcrete())
          {
              return "ClassInfo::ABSTRACT";
          }
          else if (isGlobalEp(aIn))
          {
              return "ClassInfo::LOCAL_ENDPOINT";
          }
          else if (isLocalEp(aIn))
          {
              return "ClassInfo::LOCAL_ONLY";
          }
          else
          {
              return "ClassInfo::LOCAL_ONLY";
          }
      }
      
      public static String getTypeName(MType aIn)
      {
          String lType = aIn.getLID().getName().toUpperCase();
          switch (lType)
          {
              case "URI":
              case "IP":
              case "UUID":
                  return "STRING";
              case "UINT64":
              case "UINT32":
              case "UINT16":
              case "UINT8":
              case "BITMASK8":
              case "BITMASK16":
              case "BITMASK32":
              case "BITMASK64":
                  return "U64";
              default:
                  return lType;
          }
      }
  
      public static boolean isLocalEp(MClass aIn)
      {
          return aIn.isSubclassOf("epr/LocalEp");
  
      }
  
      public static boolean isGlobalEp(MClass aIn)
      {
          return aIn.isSubclassOf("epr/ReportedEp");
      }
  
      public static boolean isPolicy(MClass aIn)
      {
          return aIn.isSubclassOf("policy/Component") || aIn.isSubclassOf("policy/Definition");
      }
  
      public static boolean isObservable(MClass aIn)
      {
          return aIn.isSubclassOf("observer/Observable");
      }
  
      public static boolean isRelationshipSource(MClass aIn)
      {
          return aIn.isConcreteSuperclassOf("relator/Source");
      }
  
      public static boolean isRelationshipTarget(MClass aIn)
      {
          return aIn.isConcreteSuperclassOf("relator/Target");
      }
  
      public static boolean isRelationshipResolver(MClass aIn)
      {
          return aIn.isConcreteSuperclassOf("relator/Resolver");
      }
  
      public static  MNameRule getNamingRule(MClass aInClass)
      {
          Collection<MNameRule> lNrs = aInClass.findNamingRules();
          return lNrs.isEmpty() ? null : lNrs.iterator().next();
      }
  
      public static String getOwner(MClass aIn)
      {
          Collection<MOwner> lOwners = aIn.findOwners();
          return lOwners.isEmpty() ? (aIn.isConcrete() ? "default" : "abstract") : lOwners.iterator().next().getLID().getName();
      }
  
      private void genMo(int aInIndent, MClass aInClass)
      {
          out.println(aInIndent, '(');
              /**
              out.println(aInIndent, "// NAME: " + aInClass.getGID().getName());
              out.println(aInIndent, "// CONT PATHS: " + aInClass.getContainmentPaths());
              out.println(aInIndent, "// NAMING PATHS: " + aInClass.getNamingPaths());
              if (aInClass instanceof MRelationshipClass)
              {
                  out.printIncodeComment(aInIndent + 1, new String[]
                          {
                                  "RELATIONSHIPS: " + ((MRelationshipClass) aInClass).getRelationships(),
                                  "NAME: " + aInClass.getGID().getName(),
                                  "CONTAINED BY: " + aInClass.getContainedByClasses(true, true),
                                  "SOURCE: " + ((MRelationshipClass) aInClass).getSourceClass().getGID().getName(),
                                  "TARGETS: " + ((MRelationshipClass) aInClass).getTargetClasses(),
                          });
              }
               */
              out.print(aInIndent + 1, "ClassInfo(" + aInClass.getGID().getId() + ", ");
  
              // if (aInClass.hasSuperclass())
              // {
              //    MClass lSuper = aInClass.getSuperclass();
              //    out.print(lSuper.getGID().getId() + "/* super: " + lSuper.getGID().getName() + " */, ");
              // }
              // else
              // {
              //    out.print("0 /* no superclass */, ");
              // }
              out.println(getClassType(aInClass) + ", \"" + aInClass.getFullConcatenatedName() + "\", \"" + getOwner(aInClass) + "\",");
                  genProps(aInIndent + 2, aInClass);
                  genNamingProps(aInIndent + 2, aInClass);
                  out.println(aInIndent + 2, ")");
          out.println(aInIndent, ')');
      }
  
      private String toUnsignedStr(int aInInt) {
      	return Long.toString(aInInt & 0xFFFFFFFFL) + "ul";
      }
      
      private void genProps(int aInIndent, MClass aInClass)
      {
          //boolean hasDesc = aInClass.hasProps() || aInClass.hasContained();
          TreeMap<String,MProp> lProps = new TreeMap<String, MProp>();
          aInClass.findProp(lProps,true);
  
  