Esempio n. 1
0
        private void toolStripButtonViewInsert_Click(object sender, EventArgs e)
        {
            List<DocModelView> list = null;
            if (this.m_target is DocPublication)
            {
                list = ((DocPublication)this.m_target).Views;
            }
            else if (this.m_target is DocExample)
            {
                list = ((DocExample)this.m_target).Views;
            }

            using (FormSelectView form = new FormSelectView(this.m_project, "Select the view(s) to include."))
            {
                if (form.ShowDialog(this) == DialogResult.OK)
                {
                    foreach(DocModelView docView in form.Selection)
                    {
                        if(!list.Contains(docView))
                        {
                            list.Add(docView);
                        }
                    }

                    this.LoadReferencedViews();
                }
            }
        }
Esempio n. 2
0
        private void buttonViewBase_Click(object sender, EventArgs e)
        {
            using (FormSelectView form = new FormSelectView(this.m_project, null))
            {
                DialogResult res = form.ShowDialog();
                if (res == DialogResult.OK)
                {
                    DocModelView docView = (DocModelView)this.m_target;

                    if (form.Selection != null && form.Selection.Length == 1)
                    {
                        this.textBoxViewBase.Text = form.Selection[0].Name;
                        docView.BaseView = form.Selection[0].Uuid.ToString();
                    }
                    else
                    {
                        this.textBoxViewBase.Text = String.Empty;
                        docView.BaseView = null;
                    }
                }
            }
        }
Esempio n. 3
0
        private void toolStripMenuItemToolsValidate_Click(object sender, EventArgs e)
        {
            DocModelView docView = null;
            if (this.m_filterviews != null && this.m_filterviews.Length > 0)
            {
                docView = this.m_filterviews[0];
            }

            using (FormValidate form = new FormValidate(this.m_project, docView, this.m_filterexchange))
            {
                DialogResult res = form.ShowDialog();
                if (res != DialogResult.OK || String.IsNullOrEmpty(Properties.Settings.Default.ValidateFile))
                    return;

                this.m_filterviews = new DocModelView[] {form.SelectedView};
                this.m_filterexchange = form.SelectedExchange;

                using (this.m_formProgress = new FormProgress())
                {
                    this.m_formProgress.Text = "Validating File";
                    this.m_formProgress.Description = "Validating file...";

                    this.backgroundWorkerValidate.RunWorkerAsync();

                    res = this.m_formProgress.ShowDialog();
                    if (res != DialogResult.OK)
                    {
                        this.backgroundWorkerValidate.CancelAsync();
                    }
                }

                if (this.m_exception != null)
                {
                    MessageBox.Show(this, this.m_exception.Message, "Error");
                    this.m_exception = null;
                    return;
                }

                // show window
                this.splitContainerEdit.Panel2Collapsed = false;
                this.InitInstanceList();

            }

            #if false
            DialogResult res = this.openFileDialogValidate.ShowDialog();
            if (res != DialogResult.OK)
                return;

            using(FormSelectView form = new FormSelectView(this.m_project, "Select the model view for validating the file."))
            {
                if(form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK && form.Selection != null)
                {
                    this.m_filterviews = form.Selection;
                    using (FormSelectExchange formExchange = new FormSelectExchange(this.m_filterviews[0]))
                    {
                        if (formExchange.ShowDialog(this) == System.Windows.Forms.DialogResult.OK && formExchange.Selection != null)
                        {
                            this.m_filterexchange = formExchange.Selection;

                            using (this.m_formProgress = new FormProgress())
                            {
                                this.m_formProgress.Text = "Validating File";
                                this.m_formProgress.Description = "Validating file...";

                                this.backgroundWorkerValidate.RunWorkerAsync();

                                res = this.m_formProgress.ShowDialog();
                                if (res != DialogResult.OK)
                                {
                                    this.backgroundWorkerValidate.CancelAsync();
                                }
                            }
                        }
                    }

                    if (this.m_exception != null)
                    {
                        MessageBox.Show(this, this.m_exception.Message, "Error");
                        this.m_exception = null;
                        return;
                    }

                    // show window
                    this.splitContainerEdit.Panel2Collapsed = false;
                    this.InitInstanceList();
                }
            }
            #endif
        }
Esempio n. 4
0
        private void toolStripMenuItemToolsModule_Click(object sender, EventArgs e)
        {
            if(this.saveFileDialogModule.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                // prompt for model view
                using(FormSelectView form = new FormSelectView(this.m_project, "Select an optional Model View for generating validation rules and a schema subset, or none to support all definitions."))
                {
                    if(form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                    {
                        Compiler compiler = new Compiler(this.m_project, form.Selection, null);
                        System.Reflection.Emit.AssemblyBuilder ab = compiler.Assembly;
                        ab.Save("IFC4.dll");

                        if(System.IO.File.Exists(this.saveFileDialogModule.FileName))
                        {
                            System.IO.File.Delete(this.saveFileDialogModule.FileName);
                        }

                        System.IO.File.Move(compiler.Module.FullyQualifiedName, this.saveFileDialogModule.FileName);
                    }
                }
            }
        }
Esempio n. 5
0
        private void toolStripMenuItemInsertConceptRoot_Click(object sender, EventArgs e)
        {
            DocEntity docEntity = (DocEntity)this.treeView.SelectedNode.Tag;

            // pick the model view definition
            using (FormSelectView form = new FormSelectView(this.m_project, null))
            {
                if (form.ShowDialog(this) == DialogResult.OK && form.Selection != null && form.Selection.Length == 1)
                {
                    DocModelView docView = form.Selection[0];

                    DocConceptRoot docConceptRoot = new DocConceptRoot();
                    docConceptRoot.ApplicableEntity = docEntity;
                    docView.ConceptRoots.Add(docConceptRoot);

                    // update tree
                    this.treeView.SelectedNode = this.LoadNode(this.treeView.SelectedNode, docConceptRoot, docView.Name, false);
                }
            }
        }
Esempio n. 6
0
        private void toolStripMenuItemFileImport_Click(object sender, EventArgs e)
        {
            StringBuilder sbErrors = new StringBuilder();

            DialogResult res = this.openFileDialogImport.ShowDialog(this);
            if (res == DialogResult.OK)
            {
                List<DocSchema> importedschemas = new List<DocSchema>();

                bool updateDescriptions = false;
                if(this.openFileDialogImport.FileName.EndsWith(".vex"))
                {
                    DialogResult resUpdate = MessageBox.Show(this, "Do you want to update the documentation? Click Yes to update documentation and definitions, or No to update just definitions.", "Import VEX", MessageBoxButtons.YesNoCancel);
                    if (resUpdate == System.Windows.Forms.DialogResult.Cancel)
                        return;

                    if (resUpdate == System.Windows.Forms.DialogResult.Yes)
                        updateDescriptions = true;
                }

                foreach (string filename in this.openFileDialogImport.FileNames)
                {
                    string ext = System.IO.Path.GetExtension(filename).ToLower();
                    switch (ext)
                    {
                        case ".vex":
                            using (FormatSPF format = new FormatSPF(filename, SchemaVEX.Types, null))
                            {
                                format.Load();

                                // get the root schemata
                                SCHEMATA vexschema = null;
                                foreach (SEntity entity in format.Instances.Values)
                                {
                                    if (entity is SCHEMATA)
                                    {
                                        vexschema = (SCHEMATA)entity;
                                        break;
                                    }
                                }

                                if (vexschema != null)
                                {
                                    DocSchema schema = Program.ImportVex(vexschema, this.m_project, updateDescriptions);
                                    importedschemas.Add(schema); // add schemas from multiple files first, process later
                                }
                            }
                            break;

                        case ".xml":
                            if (filename.Contains("Pset_"))
                            {
                                using (FormatXML format = new FormatXML(filename, typeof(PropertySetDef), "http://buildingSMART-tech.org/xml/psd/PSD_IFC4.xsd"))
                                {
                                    format.Load();
                                    PropertySetDef psd = (PropertySetDef)format.Instance;

                                    string schema = null;
                                    if (psd.Versions != null && psd.Versions.Count > 0)
                                    {
                                        schema = psd.Versions[0].schema;
                                    }

                                    if (String.IsNullOrEmpty(schema))
                                    {
                                        // guess the schema according to applicable type value
                                        if (psd.ApplicableTypeValue != null)
                                        {
                                            string[] parts = psd.ApplicableTypeValue.Split(new char[] { '/', '[' });
                                            TreeNode tnEntity = null;
                                            if (this.m_mapTree.TryGetValue(parts[0].ToLowerInvariant(), out tnEntity))
                                            {
                                                DocSchema docschema = (DocSchema)tnEntity.Parent.Parent.Tag;
                                                schema = docschema.Name;
                                            }
                                        }
                                    }

                                    if(schema == null)
                                    {
                                        schema = "IfcProductExtension";//fallback
                                    }

                                    // find the schema
                                    TreeNode tn = null;
                                    if (schema != null && this.m_mapTree.TryGetValue(schema.ToLowerInvariant(), out tn))
                                    {
                                        DocSchema docschema = (DocSchema)tn.Tag;

                                        // find existing pset if applicable
                                        DocPropertySet pset = docschema.RegisterPset(psd.Name);

                                        // use hashed guid
                                        if (pset.Uuid == Guid.Empty)
                                        {
                                            System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
                                            byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(pset.Name));
                                            pset.Uuid = new Guid(hash);
                                        }

                                        pset.Name = psd.Name;
                                        if (psd.Definition != null)
                                        {
                                            pset.Documentation = psd.Definition.Trim();
                                        }
                                        if (psd.ApplicableTypeValue != null)
                                        {
                                            pset.ApplicableType = psd.ApplicableTypeValue.Replace("Type", "").Replace("[PerformanceHistory]", ""); // organize at occurrences; use pset type to determine type applicability
                                        }

                                        // for now, rely on naming convention (better to capture in pset schema eventually)
                                        if (psd.Name.Contains("PHistory")) // special naming convention
                                        {
                                            pset.PropertySetType = "PSET_PERFORMANCEDRIVEN";
                                        }
                                        else if (psd.Name.Contains("Occurrence"))
                                        {
                                            pset.PropertySetType = "PSET_OCCURRENCEDRIVEN";
                                        }
                                        else
                                        {
                                            pset.PropertySetType = "PSET_TYPEDRIVENOVERRIDE";
                                        }

                                        // import localized definitions
                                        if (psd.PsetDefinitionAliases != null)
                                        {
                                            foreach (PsetDefinitionAlias pl in psd.PsetDefinitionAliases)
                                            {
                                                pset.RegisterLocalization(pl.lang, null, pl.Value);
                                            }
                                        }

                                        foreach (PropertyDef subdef in psd.PropertyDefs)
                                        {
                                            DocProperty docprop = pset.RegisterProperty(subdef.Name);
                                            Program.ImportPsdPropertyTemplate(subdef, docprop);
                                        }

                                        // add to Use Definition at applicable entity
            #if false
                                        if (pset.ApplicableType != null)
                                        {
                                            string[] apptypes = pset.ApplicableType.Split('/');
                                            if (this.m_mapTree.TryGetValue(apptypes[0].ToLowerInvariant(), out tn))
                                            {
                                                DocEntity entity = (DocEntity)tn.Tag;

                                                if (this.m_project.ModelViews.Count == 0)
                                                {
                                                    // must have at least one model view for populating property set links
                                                    this.m_project.ModelViews.Add(new DocModelView());
                                                }

                                                foreach (DocModelView docView in this.m_project.ModelViews)
                                                {
                                                    DocConceptRoot docRoot = null;
                                                    foreach (DocConceptRoot eachRoot in docView.ConceptRoots)
                                                    {
                                                        if (eachRoot.ApplicableEntity == entity)
                                                        {
                                                            docRoot = eachRoot;
                                                            break;
                                                        }
                                                    }

                                                    if (docRoot == null)
                                                    {
                                                        docRoot = new DocConceptRoot();
                                                        docRoot.ApplicableEntity = entity;
                                                        docView.ConceptRoots.Add(docRoot);
                                                    }

                                                    // find the pset template
                                                    DocTemplateUsage templateuse = null;
                                                    foreach (DocTemplateUsage eachtemplateuse in docRoot.Concepts)
                                                    {
                                                        if (eachtemplateuse.Definition != null && eachtemplateuse.Definition.Name.StartsWith("Property"))
                                                        {
                                                            templateuse = eachtemplateuse;
                                                            break;
                                                        }
                                                    }

                                                    DocTemplateDefinition docdefpset = this.m_project.GetTemplate(new Guid("f74255a6-0c0e-4f31-84ad-24981db62461"));
                                                    if (docdefpset != null)
                                                    {
                                                        // if no template, add it
                                                        if (templateuse == null)
                                                        {
                                                            // get the pset template
                                                            templateuse = new DocTemplateUsage();
                                                            docRoot.Concepts.Add(templateuse);
                                                            templateuse.Definition = docdefpset;
                                                        }

                                                        DocTemplateItem templateitem = new DocTemplateItem();
                                                        templateuse.Items.Add(templateitem);
                                                        templateitem.RuleInstanceID = "IfcPropertySet";

                                                        if (apptypes.Length == 2)
                                                        {
                                                            templateitem.RuleParameters += "PredefinedType=" + apptypes[1] + ";";
                                                        }
                                                        templateitem.RuleParameters += "Name=" + pset.Name + ";";
                                                        templateitem.RuleParameters += "TemplateType=" + pset.PropertySetType + ";";
                                                        // don't include documentation -- too wordy templateitem.Documentation = pset.Documentation;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                sbErrors.Append(System.IO.Path.GetFileNameWithoutExtension(filename) + ": unrecognized ApplicableTypeValue; ");
                                            }
                                        }
            #endif
                                    }
                                    else
                                    {
                                        sbErrors.Append(System.IO.Path.GetFileNameWithoutExtension(filename) + ": unrecognized schema; ");
                                    }

                                }
                            }
                            else if (filename.Contains("Qto_"))
                            {
                                using (FormatXML format = new FormatXML(filename, typeof(QtoSetDef)))
                                {
                                    format.Load();
                                    QtoSetDef qto = (QtoSetDef)format.Instance;

                                    string schema = qto.Versions[0].schema;
                                    TreeNode tn = null;
                                    if (schema != null && this.m_mapTree.TryGetValue(schema.ToLowerInvariant(), out tn))
                                    {
                                        DocSchema docschema = (DocSchema)tn.Tag;

                                        // find existing pset if applicable
                                        DocQuantitySet qset = docschema.RegisterQset(qto.Name);

                                        // use hashed guid
                                        if (qset.Uuid == Guid.Empty)
                                        {
                                            System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
                                            byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(qset.Name));
                                            qset.Uuid = new Guid(hash);
                                        }

                                        // everything is currently named "Base Quantities"; get name from file instead; e.g. "Qto_Beam"
                                        qset.Name = System.IO.Path.GetFileNameWithoutExtension(filename);
                                        qset.Documentation = qto.Definition;
                                        qset.ApplicableType = qto.ApplicableClasses[0].Value;

                                        // fix: remove "Type"
                                        if (qset.ApplicableType.EndsWith("Type"))
                                        {
                                            qset.ApplicableType = qset.ApplicableType.Substring(0, qset.ApplicableType.Length - 4);
                                        }

                                        // import localized definitions
                                        if (qto.QtoDefinitionAliases != null)
                                        {
                                            foreach (QtoDefinitionAlias pl in qto.QtoDefinitionAliases)
                                            {
                                                qset.RegisterLocalization(pl.lang, null, pl.Value);
                                            }
                                        }

                                        foreach (QtoDef qtodef in qto.QtoDefs)
                                        {
                                            DocQuantity q = qset.RegisterQuantity(qtodef.Name);
                                            q.Documentation = qtodef.Definition;

                                            switch (qtodef.QtoType)
                                            {
                                                case "IfcQuantityCount":
                                                    q.QuantityType = DocQuantityTemplateTypeEnum.Q_COUNT;
                                                    break;

                                                case "IfcQuantityLength":
                                                    q.QuantityType = DocQuantityTemplateTypeEnum.Q_LENGTH;
                                                    break;

                                                case "IfcQuantityArea":
                                                    q.QuantityType = DocQuantityTemplateTypeEnum.Q_AREA;
                                                    break;

                                                case "IfcQuantityVolume":
                                                    q.QuantityType = DocQuantityTemplateTypeEnum.Q_VOLUME;
                                                    break;

                                                case "IfcQuantityWeight":
                                                    q.QuantityType = DocQuantityTemplateTypeEnum.Q_WEIGHT;
                                                    break;

                                                case "IfcQuantityTime":
                                                    q.QuantityType = DocQuantityTemplateTypeEnum.Q_TIME;
                                                    break;
                                            }

                                            foreach (NameAlias namealias in qtodef.NameAliases)
                                            {
                                                string desc = null;
                                                foreach (DefinitionAlias docalias in qtodef.DefinitionAliases)
                                                {
                                                    if (docalias.lang.Equals(namealias.lang))
                                                    {
                                                        desc = docalias.Value;
                                                        break;
                                                    }
                                                }

                                                q.RegisterLocalization(namealias.lang, namealias.Value, desc);
                                            }

                                        }

                                        // map to use definition
                                        if (this.m_mapTree.TryGetValue(qset.ApplicableType.ToLowerInvariant(), out tn))
                                        {
                                            DocEntity entity = (DocEntity)tn.Tag;

                                            if (this.m_project.ModelViews.Count == 0)
                                            {
                                                // must have at least one model view for populating property set links
                                                this.m_project.ModelViews.Add(new DocModelView());
                                            }

                                            foreach (DocModelView docView in this.m_project.ModelViews)
                                            {
                                                DocConceptRoot docRoot = null;
                                                foreach (DocConceptRoot eachRoot in docView.ConceptRoots)
                                                {
                                                    if (eachRoot.ApplicableEntity == entity)
                                                    {
                                                        docRoot = eachRoot;
                                                        break;
                                                    }
                                                }

                                                if (docRoot == null)
                                                {
                                                    docRoot = new DocConceptRoot();
                                                    docRoot.ApplicableEntity = entity;
                                                    docView.ConceptRoots.Add(docRoot);
                                                }

                                                // find the qset template
                                                DocTemplateUsage templateuse = null;
                                                foreach (DocTemplateUsage eachtemplateuse in docRoot.Concepts)
                                                {
                                                    if (eachtemplateuse.Definition.Name.StartsWith("Quantity"))
                                                    {
                                                        templateuse = eachtemplateuse;
                                                        break;
                                                    }
                                                }

                                                // if no template, add it
                                                if (templateuse == null)
                                                {
                                                    // get the pset template
                                                    templateuse = new DocTemplateUsage();
                                                    docRoot.Concepts.Add(templateuse);
                                                    templateuse.Definition = this.m_project.GetTemplate(new Guid("6652398e-6579-4460-8cb4-26295acfacc7"));
                                                }

                                                if (templateuse != null)
                                                {
                                                    DocTemplateItem templateitem = new DocTemplateItem();
                                                    templateuse.Items.Add(templateitem);
                                                    templateitem.RuleInstanceID = "IfcElementQuantity";
                                                    templateitem.RuleParameters = "Name=" + qset.Name + ";TemplateType=QTO_OCCURRENCEDRIVEN;";
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        sbErrors.Append(System.IO.Path.GetFileNameWithoutExtension(filename) + ": unrecognized schema; ");
                                    }
                                }
                            }
                            else if (filename.Contains("ifcXML"))
                            {
                                using (FormatXML format = new FormatXML(filename, typeof(configuration), null, SchemaCNF.Prefixes))
                                {
                                    try
                                    {
                                        this.m_loading = true; // prevent constructors from registering instances (xml serializer instantiates)
                                        format.Load();

                                        DocModelView docView = null;
                                        using(FormSelectView form = new FormSelectView(this.m_project, null))
                                        {
                                            if(form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK && form.Selection != null && form.Selection.Length == 1)
                                            {
                                                docView = form.Selection[0];
                                            }
                                        }

                                        configuration cnf = (configuration)format.Instance;
                                        Program.ImportCnf(cnf, this.m_project, docView);
                                    }
                                    catch (Exception xx)
                                    {
                                        MessageBox.Show(this, xx.Message, "Import CNFXML");
                                    }
                                    finally
                                    {
                                        this.m_loading = false;
                                    }
                                }
                            }
                            break;

                        case ".mvdxml":
                            this.ImportMVD(filename);
                            break;

                        case ".txt":
                            using (FormatCSV format = new FormatCSV(filename))
                            {
                                try
                                {
                                    format.Instance = this.m_project;
                                    format.Load();
                                }
                                catch (System.Exception xx)
                                {
                                    MessageBox.Show(this, xx.Message, "Import CSV");
                                }
                            }
                            break;

                        case ".ifd":
                            using (FormatIFD format = new FormatIFD(filename))
                            {
                                try
                                {
                                    format.Instance = this.m_project;
                                    format.Load();
                                }
                                catch (System.Exception xx)
                                {
                                    MessageBox.Show(this, xx.Message, "Import IFD");
                                }
                            }
                            break;

                        case ".xsd":
                            using (FormatXML format = new FormatXML(filename, typeof(IfcDoc.Schema.XSD.schema), IfcDoc.Schema.XSD.SchemaXsd.DefaultNamespace))
                            {
                                try
                                {
                                    format.Load();
                                    DocSchema docSchema = Program.ImportXsd((IfcDoc.Schema.XSD.schema)format.Instance, this.m_project);
                                    if(docSchema.Name == null)
                                    {
                                        docSchema.Name = System.IO.Path.GetFileNameWithoutExtension(filename);
                                    }
                                }
                                catch(System.Exception xx)
                                {
                                    MessageBox.Show(this, xx.Message, "Import XSD");
                                }
                            }
                            break;
                    }

                }

                // load tree before generating use definitions
                this.LoadTree();

                // load tree again to pick up definitions
                if (importedschemas.Count > 0)
                {
                    LoadTree();
                }
            }

            if (sbErrors.Length > 0)
            {
                MessageBox.Show(this, "Import succeeded, however one or more definitions have missing or incorrect information:\r\n" + sbErrors.ToString(), "Import Errors");
            }
        }
Esempio n. 7
0
        private void toolStripMenuItemFileExport_Click(object sender, EventArgs e)
        {
            DialogResult res = this.saveFileDialogExport.ShowDialog(this);
            if (res == DialogResult.OK)
            {
                DocModelView[] views = null;
                string[] locales = null;
                DocDefinitionScopeEnum scope = DocDefinitionScopeEnum.None;

                string ext = System.IO.Path.GetExtension(this.saveFileDialogExport.FileName).ToLower();
                switch (ext)
                {
                    case ".txt":
                        // prompt for locale
                        using (FormSelectLocale form = new FormSelectLocale())
                        {
                            if (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                            {
                                locales = new string[] { form.SelectedLocale.TwoLetterISOLanguageName };
                            }
                            else
                            {
                                return;
                            }
                        }
                        // prompt for definitions
                        using (FormFilterDefinitions formFilter = new FormFilterDefinitions())
                        {
                            if (formFilter.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                            {
                                scope = formFilter.DefinitionScope;
                            }
                            else
                            {
                                return;
                            }
                        }
                        break;

                    default:
                        // prompt for model view
                        using (FormSelectView form = new FormSelectView(this.m_project, "Select an optional model view for filtering the export, or no model view to export all definitions."))
                        {
                            if (form.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                            {
                                if (form.Selection != null)
                                {
                                    views = form.Selection;
                                }
                            }
                        }
                        break;
                }

                // swap out instances temporarily
                Dictionary<long, SEntity> old = this.m_instances;
                long lid = this.m_lastid;

                this.m_instances = new Dictionary<long, SEntity>();
                this.m_lastid = 0;

                try
                {
                    DocumentationISO.DoExport(this.m_project, this.saveFileDialogExport.FileName, views, locales, scope, this.m_instances);
                }
                catch (Exception x)
                {
                    MessageBox.Show(x.Message, "Error");
                }
                finally
                {
                    this.m_instances = old;
                    this.m_lastid = lid;
                }

            }
        }