/// <summary> /// Write out the data in a single item /// </summary> /// <param name="item"></param> /// <param name="output"></param> private void WriteItem(IClassItem item, StreamWriter output) { if (item == null) { throw new ArgumentNullException("item - can't have a null item in an ntuple!"); } // If there are any attributes associated with this guy, dump them out. if (item is IClassItemExtraAttributes) { var e = item as IClassItemExtraAttributes; foreach (var attr in e.GetAttributes()) { output.WriteLine(" [{0}]", attr); } } if (item.NotAPointer) { output.WriteLine(" [NotAPointer]"); } string t = item.ItemType; output.WriteLine(" public {0} {1};", t, item.Name.FixupLeafName()); }
/// <summary> /// Populate a class with the stuff we find in the branches we are looking at. /// </summary> /// <param name="container"></param> /// <param name="branches"></param> /// <returns></returns> private IEnumerable <ROOTClassShell> ExtractClassesFromBranchList(ROOTClassShell container, IEnumerable <ROOTNET.Interface.NTBranch> branches) { /// /// Now, loop through each branch and see if we can't convert everything! /// foreach (var branch in branches) { /// /// What kind of branch is this? Is it a leaf branch or is it a "class" branch. That is, does it have /// sub leaves on it? The key question to ask is how many sub-branches are there here? /// if (branch.ListOfBranches.Entries == 0) { foreach (var leaf in branch.GetListOfLeaves().Cast <ROOTNET.Interface.NTLeaf>()) { var cls = ROOTNET.NTClass.GetClass(leaf.TypeName); if (cls == null || !cls.IsShellTClass() || cls.IsSTLClass()) { // This is a class known to ROOT or // it is something very simple (int, vector<int>, etc.). try { IClassItem toAdd = ExtractUnsplitKnownClass(leaf); if (toAdd != null) { container.Add(toAdd); } } catch (Exception e) { SimpleLogging.Log("Info: Unable to transltae ntuple leaf '" + leaf.Name + "': " + e.Message); } } else { // This is a class we will have to bulid metadata for - from the streamer (the # of leaves // is zero if we are here, so it can only be streamer defiend). foreach (var item in ExtractUnsplitUnknownClass(container, leaf.Name, cls)) { yield return(item); } } } } else { var rc = ExtractClass(container, branch); ROOTClassShell lastOne = null; foreach (var rootClass in rc) { yield return(rootClass); lastOne = rootClass; } } } }
private IClassItem ExtractSimpleItem(SimpleLeafInfo leaf) { string className = TypeDefTranslator.ResolveTypedef(leaf.TypeName); // // Check if it is a c-style array. If it is, then the title will contain // the specification we need to look at for the c-style array bit. This will get // called recursively to parse the actual type after the c-style array bit is stripped off. // if (leaf.Title.Contains("[")) { return(ExtractCArrayInfo(leaf)); } // // Next, if the type is a template, special parse that. // var result = TemplateParser.ParseForTemplates(className); if (result is TemplateParser.TemplateInfo) { return(ExtractTemplateItem(leaf, result as TemplateParser.TemplateInfo)); } /// /// Ok - so it is a single "object" or similar. So we need to look at it and figure /// out how to deal with it. It could be a root object or just an "int" /// var ln = NormalizeLeafName(leaf.Name); IClassItem toAdd = null; if (IsROOTClass(className) && className != "string") { toAdd = new ItemROOTClass(ln, className); } else { toAdd = new ItemSimpleType(ln, className.SimpleCPPTypeToCSharpType()); } if (toAdd == null || toAdd.ItemType == null) { throw new InvalidOperationException("Unknown type - can't translate '" + className + "'."); } return(toAdd); }
public void GenerateClassFromClasses( ClassGenerator target, int outputChoice, int numExtraFiles, int numExtraFilesToCreate, int extraFileIndexNull, string nameSName, int NumObjectCollection) { if (numExtraFiles < 0 || numExtraFilesToCreate < 0 || extraFileIndexNull < 0 || outputChoice < 0 || NumObjectCollection < 0) { return; } /// /// Kill off the directory we might have left behind from a previous run, and create a new one. /// DirectoryInfo testDir = new DirectoryInfo(".\\GenerateClassFromClasses"); if (testDir.Exists) { testDir.Delete(true); } testDir.Create(); /// /// Setup the input stuff so Pex can play /// FileInfo outputCSFile; if (outputChoice == 1) { outputCSFile = new FileInfo(testDir.FullName + "\\output.cs"); } else { outputCSFile = null; } ROOTClassShell[] objCollect = null; if (NumObjectCollection > 0) { List <ROOTClassShell> objs = new List <ROOTClassShell>(); for (int i = 0; i < NumObjectCollection; i++) { ROOTClassShell rcs = new ROOTClassShell(); rcs.Name = "dude_" + i.ToString(); for (int j = 0; j < i; j++) { IClassItem item = null; switch (NumObjectCollection % 4) { case 0: item = null; break; case 1: var itm = new ItemSimpleType() { ItemType = "int" }; item = itm; break; case 2: var itmv = new ItemVector() { ItemType = "int[]" }; item = itmv; break; case 3: var itmr = new ItemROOTClass() { ItemType = "TLorentzVector" }; item = itmr; break; } if (item != null) { item.Name = "item_" + j.ToString(); } rcs.Items.Add(item); } objs.Add(rcs); } objCollect = objs.ToArray(); } /// /// Create the final object, and any extra files needed! /// NtupleTreeInfo info = new NtupleTreeInfo() { Classes = objCollect }; info.ClassImplimintationFiles = (from c in Enumerable.Range(0, numExtraFiles) let f = new FileInfo(testDir.FullName + "\\GenerateClassFromClasses_extra_" + c.ToString() + ".cpp") select f.FullName ).ToArray(); int maxFilesToCreate = numExtraFilesToCreate > numExtraFiles ? numExtraFiles : numExtraFilesToCreate; for (int i = 0; i < maxFilesToCreate; i++) { using (var w = File.CreateText(info.ClassImplimintationFiles[i])) { w.WriteLine(); w.Close(); } } if (extraFileIndexNull < numExtraFiles) { info.ClassImplimintationFiles[extraFileIndexNull] = null; } /// /// Ok, do the investigation /// target.GenerateClasss(info, outputCSFile, nameSName); Assert.IsFalse(info.ClassImplimintationFiles.Any(c => c == null), "no null implementation files allowed"); Assert.IsFalse(info.ClassImplimintationFiles.Any(c => !File.Exists(c)), "all implimntation files must exist"); /// Check that all the ntuple proxy guys and the temp file guys appear in the file foreach (var item in info.ClassImplimintationFiles) { Assert.IsTrue(FindInFile(outputCSFile, item), "coul dnot find impl file '" + item + "'"); } }
/// <summary> /// Called when user clicks on the add-in menu /// </summary> /// <param name="e">The context of the VS tools and metadata</param> public override void OnClick(AddinDesignerEventArgs e) { try { int displayOrder = 0; // we will create Extension class here var selectedElement = e.SelectedElement as Microsoft.Dynamics.Framework.Tools.MetaModel.Automation.IRootElement; if (selectedElement != null) { // Find current model var modelSaveInfo = Common.CommonUtil.GetCurrentModelSaveInfo(); var metaModelService = Common.CommonUtil.GetModelSaveService(); IClassItem classItem = selectedElement as IClassItem; // Get the selected class AxClass object AxClass selectedClass = Common.CommonUtil.GetModelSaveService().GetClass(classItem.Name); // TODO: check that the class is a RunBaseBatch class. Otherwise send message that this is not required. // Create Contract class Microsoft.Dynamics.AX.Metadata.MetaModel.AxClass contractClass = new AxClass() { Name = classItem.Name + "Contract", }; contractClass.Implements.Add("SysOperationValidatable"); contractClass.AddAttribute(new AxAttribute() { Name = "DataContract" }); contractClass.SourceCode.Declaration = $"[DataContract]\npublic final class {contractClass.Name} implements SysOperationValidatable\n{{\n\n}}"; // this is replaced again later with the variables List <string> contractParms = new List <string>(); // store the variables here List <string> contractParmMethods = new List <string>(); // store the parm methods here List <string> axParmVariables = new List <string>(); List <AxMethod> axMethods = new List <AxMethod>(); string currentGroup = string.Empty; string headerAttributes = "DataContract"; int headerAttributeOrder = 0; var dialogMethod = selectedClass.Methods.Where(m => m.Name.Equals("dialog", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (dialogMethod != null) { // from the dialog method we would know what the code fields should be var dialogSource = dialogMethod.Source; // var dialogLines = dialogSource.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList(); foreach (var dialogLine in dialogLines) { if (dialogLine.Trim().StartsWith("public")) { continue; } else if (dialogLine.Contains(".addGroup(")) { // set the group name here string dialogSourceLine = dialogLine.Substring(dialogLine.IndexOf("(") + 1); dialogSourceLine = dialogSourceLine.Replace(");", "").Replace("\"", "").Trim(); string currentGrouplabel = dialogSourceLine; currentGroup = dialogSourceLine; if (currentGroup.StartsWith("@")) { // we need to get a name for this group var label = Labels.LabelHelper.FindLabelGlobally(currentGrouplabel); if (label != null) { currentGroup = label.LabelText; } } currentGroup = currentGroup.Replace(" ", "").Trim(); headerAttributes += $", SysOperationGroupAttribute('{currentGroup}', \"{currentGrouplabel}\", '{headerAttributeOrder}')"; headerAttributeOrder++; } else if (dialogLine.Contains(".addField")) { string addFieldLine = dialogLine.Trim(); // so over here we will get the field to add as a member & parm method addFieldLine = addFieldLine.Substring(addFieldLine.IndexOf(".addField")); addFieldLine = addFieldLine.Substring(addFieldLine.IndexOf("(") + 1); addFieldLine = addFieldLine.Replace(");", "").Trim(); var parameters = addFieldLine.Split(new string[] { "," }, StringSplitOptions.None).ToList(); parameters.ForEach(p => p.Trim()); string fieldType = String.Empty; string fieldLabel = String.Empty; string fieldHelp = String.Empty; string fieldName = String.Empty; string attributes = String.Empty; attributes = $"[DataMember, SysOperationDisplayOrder('{displayOrder}')"; // we will always have a fieldType (or atleast we should) fieldType = parameters[0].Substring(parameters[0].IndexOf("(") + 1) .Replace("(", "").Replace(")", "").Trim(); if (parameters.Count >= 2) { fieldName = parameters[1].Replace("\"", "").Trim(); //if (String.IsNullOrEmpty(fieldLabel) == false) //{ // attributes += $", SysOperationLabel('{fieldName}')"; //} } if (parameters.Count >= 3) { fieldLabel = parameters[2].Replace("\"", "").Trim(); if (String.IsNullOrEmpty(fieldLabel) == false) { attributes += $", SysOperationLabel(\"{fieldLabel}\")"; } } if (parameters.Count >= 4) { fieldHelp = parameters[3].Replace("\"", "").Trim(); if (String.IsNullOrEmpty(fieldHelp) == false) { attributes += $", SysOperationHelpText(\"{fieldHelp}\")"; } } // add the group here if (!String.IsNullOrEmpty(currentGroup)) { attributes += $", SysOperationGroupMemberAttribute(\"{currentGroup}\")"; } attributes += "]"; /* Crude method * string fieldType = addFieldLine.Substring(0, addFieldLine.IndexOf(",")); * fieldType = fieldType.Substring(fieldType.IndexOf("(") + 1) * .Replace("(", "").Replace(")", "").Trim(); * * string fieldLabel = String.Empty; * string fieldHelp = String.Empty; * string fieldName = addFieldLine.Substring(addFieldLine.IndexOf(",") + 1) * .Replace(")", "").Replace(";", "").Trim(); * if (fieldName.Count(c => c == ',') > 0) * { * // that means there is a label / help label in here as well * // Break the fieldname further * // find the label here * string fieldNameLabel = fieldName; * fieldName = fieldNameLabel.Substring(0, fieldNameLabel.IndexOf(",")).Trim(); * * // find the help label here * } */ AxClassMemberVariable axVar = new AxClassMemberVariable { TypeName = fieldType, Name = fieldName }; axVar.Type = Microsoft.Dynamics.AX.Metadata.Core.MetaModel.CompilerBaseType.AnyType; axParmVariables.Add($"\t{fieldType} {fieldName};"); contractClass.AddMember(axVar); // need to add Attributes here // add parameters to the method //fieldName = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fieldName); AxMethod method = new AxMethod { Name = "parm" + System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fieldName), ReturnType = new AxMethodReturnType() { TypeName = fieldType } }; //,{SysOperationLabelAttribute(""{}"")} // add the group & label & help attribute method.Source = //$@" [DataMember,SysOperationDisplayOrder('{displayOrder}')] $@" {attributes} public {fieldType} {method.Name} ({fieldType} _{fieldName} = {fieldName}) {{ {fieldName} = _{fieldName}; return {fieldName}; }}" + Environment.NewLine; //contractClass.AddMethod(method); axMethods.Add(method); displayOrder++; } } } // Add all the axmethods here string parmVarSource = string.Empty; axParmVariables.ForEach(s => parmVarSource = parmVarSource + "\n" + s); //contractClass.SourceCode.Declaration = $"[DataContract]\npublic final class {contractClass.Name}\n{{\n{parmVarSource}\n\n}}"; contractClass.SourceCode.Declaration = $"[{headerAttributes}]\npublic final class {contractClass.Name} implements SysOperationValidatable\n{{\n{parmVarSource}\n\n}}"; axMethods.ForEach(method => contractClass.AddMethod(method)); // Create validate method this.applyValidateMethod(selectedClass, contractClass); metaModelService.CreateClass(contractClass, modelSaveInfo); Common.CommonUtil.AddElementToProject(contractClass); //extensionClass.SourceCode.Declaration = $"[ExtensionOf({intrinsicStr}({selectedElement.Name}))]\npublic final class {className}\n{{\n\n}}"; /* * * metaModelService.CreateClass(extensionClass, modelSaveInfo); * Common.CommonUtil.AddElementToProject(extensionClass); */ } } catch (Exception ex) { CoreUtility.HandleExceptionWithErrorMessage(ex); } }