// // (C) Copyright 2003-2007 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections.Generic; using System.Text; using Autodesk.Revit; using System.Data; using Autodesk.Revit.Parameters; using Autodesk.Revit.Enums; namespace Revit.SDK.Samples.RDBLink.CS { /// /// Provides export and import functions for Revit elements. /// public abstract class ElementList : APIObjectList { #region Fields /// /// Element set which is related with a specific table in database. /// private ElementSet m_elements = new ElementSet(); #endregion #region Properties /// /// Gets the element list. /// protected ElementSet Elements { get { return m_elements; } } #endregion #region Methods /// /// Get the category id of an element /// /// element to get category id /// public static BuiltInCategory GetCategoryId(Element element) { if (element != null) { Parameter catParameter = element.get_Parameter(BuiltInParameter.ELEM_CATEGORY_PARAM); if (catParameter != null) { return (BuiltInCategory)catParameter.AsElementId().Value; } } return BuiltInCategory.INVALID; } /// /// Get id of an element /// /// element to get id /// -1 if the element is null, otherwise its id public static int GetElementId(Element element) { if (element != null) { Parameter idParameter = element.get_Parameter(BuiltInParameter.ID_PARAM); if (idParameter != null) { return idParameter.AsElementId().Value; } } return -1; } /// /// If the element belongs to the related table, then add it to the element set. /// /// element to try to append. /// True if append successfully, otherwise false. public bool TryAppend(Element element) { if (CanAppend(element)) { Append(element); return true; } return false; } /// /// Add an element to element set. /// /// element to append public void Append(Element element) { m_elements.Insert(element); } /// /// Clear the element list. /// public void Clear() { m_elements.Clear(); } /// /// Export all data in element set into a DataTable /// /// DataTable which revit data will be exported into public override void Export(DataTable dataTable) { DataTable = dataTable; foreach (Element element in m_elements) { InsertDbRow(element, false); } } /// /// Import data from DataTable /// /// DataTable to import public override void Import(DataTable dataTable) { if (dataTable == null) return; DataTable = dataTable; //represents elements that appears in Revit but not in database ElementSet elementsNotInDb = new ElementSet(); foreach (Element elem in m_elements) { elementsNotInDb.Insert(elem); } ElementId eId; DataRow row = null; //the following code is to iterate all rows to find existing records to modify elements //and new records to create elements. for (int rowIndex = 0; rowIndex < DataTable.Rows.Count; rowIndex++) { row = DataTable.Rows[rowIndex]; //get id of an element int idInDb = (int)row["Id"]; eId.Value = idInDb; //get element using its id Element element = ActiveDocument.get_Element(ref eId); //verify whether the element exists if (element != null && CanAppend(element)) { // if this element exists, remove it from elementsNotInDb. elementsNotInDb.Erase(element); // And update it. If update element failed, update database. UpdateElement(element, rowIndex); } else { // if this element does not exist, create one try { // just symbol can be duplicated. element = CreateElement(row); } catch { element = null; } // if create successfully if (element != null) { // update the row and add it to the pending row list which will be updated // at the end of importing. AddToUpdateList(element, rowIndex); // add it to the element set m_elements.Insert(element); } else { // if create failed, remove the record to garbage row list which will be // deleted at the end of importing. DeleteDbRow(rowIndex); } } if (element != null) { if (elementsNotInDb.Contains(element)) { elementsNotInDb.Erase(element); } } } //if there are some elements don't exist in database, insert them to database if (elementsNotInDb.Size > 0) { foreach (Element elem in elementsNotInDb) { InsertDbRow(elem, false); } } elementsNotInDb.Dispose(); } /// /// Verify whether an element belongs to the specific table. /// /// element to verify. /// true if the element belongs to the table, otherwise false. abstract protected bool CanAppend(Element element); /// /// Update element. if update element failed, update database. /// /// element to update /// index of DataRow in DataTable related with the element abstract protected void UpdateElement(Element element, int rowIndex); /// /// Populate data of an element into a DataRow. /// /// element to retrieve data from. /// DataRow to populate. abstract protected void PopulateDbRow(Element element, DataRow row); /// /// Create an element. /// /// DataRow which contains the information to create element. /// the created element. virtual protected Element CreateElement(DataRow row) { return null; } /// /// Delete database row. /// /// row index protected void DeleteDbRow(int rowIndex) { GarbageRows.Add(DataTable.Rows[rowIndex]); } /// /// Update the row and add it to the pending row list which will be updated /// at the end of importing. /// /// element used to update DataRow /// index of DataRow in DataTable private void AddToUpdateList(Element element, int rowIndex) { DataRow row = InsertDbRow(element, true); PendingRows.Add(row, DataTable.Rows[rowIndex]); } /// /// Create a new DataRow preserves the element data, if the element is an existing one, /// add the DataRow to DataTable. /// /// element used to populate DataRow. /// true if the element is a new created element by API. /// Created DataRow private DataRow InsertDbRow(Element element, bool isElementCreated) { DataRow row = DataTable.NewRow(); if (!isElementCreated) DataTable.Rows.Add(row); PopulateDbRow(element, row); return row; } /// /// Get the value of the parameter which can be inserted into database. /// /// parameter to retrieve data. /// value of the parameter protected object GetParameterDdValue(Parameter parameter) { if (parameter == null) return DBNull.Value; object retval = null; switch (parameter.StorageType) { case StorageType.Double: double tmpval = parameter.AsDouble(); try { DisplayUnitType dut = parameter.DisplayUnitType; retval = Unit.CovertFromAPI(dut, tmpval); } catch { retval = tmpval; } break; case StorageType.ElementId: int id = parameter.AsElementId().Value; retval = (id == -1) ? retval = DBNull.Value : id; break; case StorageType.Integer: retval = parameter.AsInteger(); break; case StorageType.None: retval = parameter.AsValueString(); break; case StorageType.String: retval = parameter.AsString(); // currently we can't get all "Assembly Codes" in document using RevitAPI // so we just ignore it. if (parameter.Definition.Name.Equals("Assembly Code")) { retval = DBNull.Value; } break; default: break; } return retval == null ? DBNull.Value : retval; } /// /// Get the value of an element id. /// /// element to get id. /// DBNull.Value if element id equals -1 or the element is null, /// otherwise its id. protected static object GetIdDbValue(Element element) { int id = GetElementId(element); return id != -1 ? (object)id : DBNull.Value; } /// /// Get the value of an element name. /// /// element to get name. /// DBNull.Value if the element or its name is null, otherwise its name. protected static object GetNameDbValue(Element element) { if (element != null) return DBNull.Value; try { if (element.Name != null) { return element.Name; } } catch { // element.Name may cause exception // when exception throws, it means this element does not have name. } return DBNull.Value; } /// /// Get a parameter of an element by definition name. /// /// /// definition name of the parameter. /// Parameter if found, otherwise null. protected static Parameter GetParameterByDefinitionName(Element element, string name) { if (element == null) return null; foreach (Parameter param in element.Parameters) { if (param.Definition.Name.Equals(name)) { return param; } } return null; } #endregion }; }