Dictionary.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Data;
  5. using System.IO;
  6. using FastReport.Utils;
  7. using System.CodeDom;
  8. using System.ComponentModel;
  9. using System.Collections;
  10. using FastReport.CrossView;
  11. using System.Windows.Forms;
  12. namespace FastReport.Data
  13. {
  14. /// <summary>
  15. /// This class stores all report data items such as datasources, connections, relations, parameters,
  16. /// system variables.
  17. /// </summary>
  18. /// <remarks>
  19. /// You can access the report dictionary via <b>Report.Dictionary</b> property.
  20. /// </remarks>
  21. public class Dictionary : Base, IParent
  22. {
  23. #region Fields
  24. private ConnectionCollection connections;
  25. private DataSourceCollection dataSources;
  26. private RelationCollection relations;
  27. private ParameterCollection parameters;
  28. private SystemVariables systemVariables;
  29. private TotalCollection totals;
  30. private CubeSourceCollection cubeSources;
  31. private List<RegDataItem> registeredItems;
  32. private ObjectCollection cachedAllObjects;
  33. private bool cacheAllObjects;
  34. #endregion
  35. #region Properties
  36. /// <summary>
  37. /// Gets a collection of connection objects available in a report.
  38. /// </summary>
  39. public ConnectionCollection Connections
  40. {
  41. get { return connections; }
  42. }
  43. /// <summary>
  44. /// Gets a collection of datasources available in a report.
  45. /// </summary>
  46. /// <remarks>
  47. /// Usually you don't need to use this property. It contains only datasources
  48. /// registered using the <b>RegisterData</b> method. All other datasources are contained
  49. /// in connection objects and may be accessed via <see cref="Connections"/> property.
  50. /// </remarks>
  51. public DataSourceCollection DataSources
  52. {
  53. get { return dataSources; }
  54. }
  55. /// <summary>
  56. /// Gets a collection of relations.
  57. /// </summary>
  58. public RelationCollection Relations
  59. {
  60. get { return relations; }
  61. }
  62. /// <summary>
  63. /// Gets a collection of parameters.
  64. /// </summary>
  65. /// <remarks>
  66. /// Another way to access parameters is to use the <b>Report.Parameters</b> property
  67. /// which is actually a shortcut to this property. You also may use the <b>Report.GetParameter</b>
  68. /// and <b>Report.GetParameterValue</b> methods.
  69. /// </remarks>
  70. public ParameterCollection Parameters
  71. {
  72. get { return parameters; }
  73. }
  74. /// <summary>
  75. /// Gets a collection of system variables like Date, PageNofM etc.
  76. /// </summary>
  77. /// <remarks>
  78. /// Another way to access a system variable is to use the <b>Report.GetVariableValue</b> method.
  79. /// </remarks>
  80. public SystemVariables SystemVariables
  81. {
  82. get { return systemVariables; }
  83. }
  84. /// <summary>
  85. /// Gets a collection of totals.
  86. /// </summary>
  87. /// <remarks>
  88. /// Another way to get a total value is to use the <b>Report.GetTotalValue</b> method.
  89. /// </remarks>
  90. public TotalCollection Totals
  91. {
  92. get { return totals; }
  93. }
  94. /// <summary>
  95. /// Gets a collection of cubesources available in a report.
  96. /// </summary>
  97. /// <remarks>
  98. /// Usually you don't need to use this property. It contains only cubesources
  99. /// registered using the <b>RegisterData</b> method.
  100. /// </remarks>
  101. public CubeSourceCollection CubeSources
  102. {
  103. get { return cubeSources; }
  104. }
  105. /// <summary>
  106. /// Gets a list of registered items.
  107. /// </summary>
  108. /// <remarks>
  109. /// This property is for internal use only.
  110. /// </remarks>
  111. public List<RegDataItem> RegisteredItems
  112. {
  113. get { return registeredItems; }
  114. }
  115. internal bool CacheAllObjects
  116. {
  117. get { return cacheAllObjects; }
  118. set
  119. {
  120. cacheAllObjects = value;
  121. if (cacheAllObjects)
  122. {
  123. cachedAllObjects = base.AllObjects;
  124. }
  125. else
  126. {
  127. cachedAllObjects = null;
  128. }
  129. }
  130. }
  131. ///<inheritdoc/>
  132. public new ObjectCollection AllObjects
  133. {
  134. get
  135. {
  136. if (cachedAllObjects != null)
  137. return cachedAllObjects;
  138. return base.AllObjects;
  139. }
  140. }
  141. #endregion
  142. #region Private Methods
  143. private RegDataItem FindRegisteredItem(object data)
  144. {
  145. foreach (RegDataItem item in registeredItems)
  146. {
  147. if (item.data == data)
  148. return item;
  149. }
  150. return null;
  151. }
  152. private RegDataItem FindRegisteredItem(string name)
  153. {
  154. foreach (RegDataItem item in registeredItems)
  155. {
  156. if (item.name == name)
  157. return item;
  158. }
  159. return null;
  160. }
  161. internal void AddRegisteredItem(object data, string name)
  162. {
  163. if (FindRegisteredItem(data) == null)
  164. registeredItems.Add(new RegDataItem(data, name));
  165. }
  166. #endregion
  167. #region Public Methods
  168. /// <inheritdoc/>
  169. public override void Assign(Base source)
  170. {
  171. BaseAssign(source);
  172. }
  173. internal void RegisterDataSet(DataSet data, string referenceName, bool enabled)
  174. {
  175. DictionaryHelper helper = new DictionaryHelper(this, AllObjects, Report.AllNamedObjects);
  176. helper.RegisterDataSet(data, referenceName, enabled);
  177. }
  178. internal void RegisterDataTable(DataTable table, string referenceName, bool enabled)
  179. {
  180. AddRegisteredItem(table, referenceName);
  181. TableDataSource source = FindDataComponent(referenceName) as TableDataSource;
  182. if (source != null)
  183. {
  184. source.Reference = table;
  185. source.InitSchema();
  186. source.RefreshColumns(true);
  187. }
  188. else
  189. {
  190. // check tables inside connections. Are we trying to replace the connection table
  191. // with table provided by an application?
  192. source = FindByAlias(referenceName) as TableDataSource;
  193. // check "Data.TableName" case
  194. if (source == null && referenceName.StartsWith("Data."))
  195. source = FindByAlias(referenceName.Remove(0, 5)) as TableDataSource;
  196. if (source != null && (source.Connection != null || source.IgnoreConnection))
  197. {
  198. source.IgnoreConnection = true;
  199. source.Reference = table;
  200. source.InitSchema();
  201. source.RefreshColumns(true);
  202. }
  203. else
  204. {
  205. source = new TableDataSource();
  206. source.ReferenceName = referenceName;
  207. source.Reference = table;
  208. source.Name = CreateUniqueName(referenceName.Contains(".") ? table.TableName : referenceName);
  209. source.Alias = CreateUniqueAlias(source.Alias);
  210. source.Enabled = enabled;
  211. source.InitSchema();
  212. DataSources.Add(source);
  213. }
  214. }
  215. }
  216. /// <summary>
  217. /// Registers a DataView.
  218. /// </summary>
  219. /// <param name="view">The DataView to register.</param>
  220. /// <param name="referenceName">The name of the data object.</param>
  221. /// <param name="enabled">Determines wheter to enable the object or not.</param>
  222. /// <remarks>
  223. /// This method is for internal use only.
  224. /// </remarks>
  225. public void RegisterDataView(DataView view, string referenceName, bool enabled)
  226. {
  227. AddRegisteredItem(view, referenceName);
  228. ViewDataSource source = FindDataComponent(referenceName) as ViewDataSource;
  229. if (source != null)
  230. {
  231. source.Reference = view;
  232. source.InitSchema();
  233. source.RefreshColumns();
  234. }
  235. else
  236. {
  237. source = new ViewDataSource();
  238. source.ReferenceName = referenceName;
  239. source.Reference = view;
  240. source.Name = CreateUniqueName(referenceName);
  241. source.Alias = CreateUniqueAlias(source.Alias);
  242. source.Enabled = enabled;
  243. source.InitSchema();
  244. DataSources.Add(source);
  245. }
  246. }
  247. internal void RegisterDataRelation(DataRelation relation, string referenceName, bool enabled)
  248. {
  249. AddRegisteredItem(relation, referenceName);
  250. if (FindDataComponent(referenceName) != null)
  251. return;
  252. Relation rel = new Relation();
  253. rel.ReferenceName = referenceName;
  254. rel.Reference = relation;
  255. rel.Name = relation.RelationName;
  256. rel.Enabled = enabled;
  257. rel.ParentDataSource = FindDataTableSource(relation.ParentTable);
  258. rel.ChildDataSource = FindDataTableSource(relation.ChildTable);
  259. string[] parentColumns = new string[relation.ParentColumns.Length];
  260. string[] childColumns = new string[relation.ChildColumns.Length];
  261. for (int i = 0; i < relation.ParentColumns.Length; i++)
  262. {
  263. parentColumns[i] = relation.ParentColumns[i].Caption;
  264. }
  265. for (int i = 0; i < relation.ChildColumns.Length; i++)
  266. {
  267. childColumns[i] = relation.ChildColumns[i].Caption;
  268. }
  269. rel.ParentColumns = parentColumns;
  270. rel.ChildColumns = childColumns;
  271. Relations.Add(rel);
  272. }
  273. /// <summary>
  274. /// Registers a business object.
  275. /// </summary>
  276. /// <param name="data">The business object.</param>
  277. /// <param name="referenceName">The name of the object.</param>
  278. /// <param name="maxNestingLevel">Maximum level of data nesting.</param>
  279. /// <param name="enabled">Determines wheter to enable the object or not.</param>
  280. /// <remarks>
  281. /// This method is for internal use only.
  282. /// </remarks>
  283. public void RegisterBusinessObject(IEnumerable data, string referenceName, int maxNestingLevel, bool enabled)
  284. {
  285. AddRegisteredItem(data, referenceName);
  286. Type dataType = data.GetType();
  287. if (data is BindingSource)
  288. {
  289. if ((data as BindingSource).DataSource is Type)
  290. dataType = ((data as BindingSource).DataSource as Type);
  291. else
  292. dataType = (data as BindingSource).DataSource.GetType();
  293. }
  294. BusinessObjectConverter converter = new BusinessObjectConverter(this);
  295. BusinessObjectDataSource source = FindDataComponent(referenceName) as BusinessObjectDataSource;
  296. if (source != null)
  297. {
  298. source.Reference = data;
  299. source.DataType = dataType;
  300. converter.UpdateExistingObjects(source, maxNestingLevel);
  301. }
  302. else
  303. {
  304. source = new BusinessObjectDataSource();
  305. source.ReferenceName = referenceName;
  306. source.Reference = data;
  307. source.DataType = dataType;
  308. source.Name = CreateUniqueName(referenceName);
  309. source.Alias = CreateUniqueAlias(source.Alias);
  310. source.Enabled = enabled;
  311. DataSources.Add(source);
  312. converter.CreateInitialObjects(source, maxNestingLevel);
  313. }
  314. }
  315. /// <summary>
  316. /// Registers a CubeLink.
  317. /// </summary>
  318. /// <param name="cubeLink">The CubeLink to register.</param>
  319. /// <param name="referenceName">The name of the data object.</param>
  320. /// <param name="enabled">Determines wheter to enable the object or not.</param>
  321. /// <remarks>
  322. /// This method is for internal use only.
  323. /// </remarks>
  324. public void RegisterCubeLink(IBaseCubeLink cubeLink, string referenceName, bool enabled)
  325. {
  326. AddRegisteredItem(cubeLink, referenceName);
  327. CubeSourceBase source = FindDataComponent(referenceName) as CubeSourceBase;
  328. if (source != null)
  329. {
  330. source.Reference = cubeLink;
  331. }
  332. else
  333. {
  334. source = new SliceCubeSource();
  335. source.ReferenceName = referenceName;
  336. source.Reference = cubeLink;
  337. source.Name = CreateUniqueName(referenceName);
  338. source.Alias = CreateUniqueAlias(source.Alias);
  339. source.Enabled = enabled;
  340. CubeSources.Add(source);
  341. }
  342. }
  343. /// <summary>
  344. /// Registers a data object.
  345. /// </summary>
  346. /// <param name="data">The object to register.</param>
  347. /// <param name="name">The name of the object.</param>
  348. /// <param name="enabled">Determines wheter to enable the object or not.</param>
  349. /// <remarks>
  350. /// This method is for internal use only.
  351. /// </remarks>
  352. public void RegisterData(object data, string name, bool enabled)
  353. {
  354. if (data is DataSet)
  355. {
  356. RegisterDataSet(data as DataSet, name, enabled);
  357. }
  358. else if (data is DataTable)
  359. {
  360. RegisterDataTable(data as DataTable, name, enabled);
  361. }
  362. else if (data is DataView)
  363. {
  364. RegisterDataView(data as DataView, name, enabled);
  365. }
  366. else if (data is DataRelation)
  367. {
  368. RegisterDataRelation(data as DataRelation, name, enabled);
  369. }
  370. else if (data is IEnumerable)
  371. {
  372. RegisterBusinessObject(data as IEnumerable, name, 1, enabled);
  373. }
  374. else if (data is IBaseCubeLink)
  375. {
  376. RegisterCubeLink(data as IBaseCubeLink, name, enabled);
  377. }
  378. }
  379. /// <summary>
  380. /// Unregisters the previously registered data.
  381. /// </summary>
  382. /// <param name="data">The application data.</param>
  383. public void UnregisterData(object data)
  384. {
  385. UnregisterData(data, "Data");
  386. }
  387. /// <summary>
  388. /// Unregisters the previously registered data.
  389. /// </summary>
  390. /// <param name="data">The application data.</param>
  391. /// <param name="name">The name of the data.</param>
  392. /// <remarks>
  393. /// You must specify the same <b>data</b> and <b>name</b> as when you call <b>RegisterData</b>.
  394. /// </remarks>
  395. public void UnregisterData(object data, string name)
  396. {
  397. for (int i = 0; i < registeredItems.Count; i++)
  398. {
  399. RegDataItem item = registeredItems[i];
  400. if (item.name == name)
  401. {
  402. registeredItems.RemoveAt(i);
  403. break;
  404. }
  405. }
  406. DataComponentBase comp = FindDataComponent(name);
  407. if (comp != null)
  408. comp.Dispose();
  409. if (data is DataSet)
  410. {
  411. foreach (DataTable table in (data as DataSet).Tables)
  412. {
  413. UnregisterData(table, name + "." + table.TableName);
  414. }
  415. foreach (DataRelation relation in (data as DataSet).Relations)
  416. {
  417. UnregisterData(relation, name + "." + relation.RelationName);
  418. }
  419. }
  420. }
  421. /// <summary>
  422. /// Re-registers the data registered before.
  423. /// </summary>
  424. /// <remarks>
  425. /// This method is for internal use only.
  426. /// </remarks>
  427. public void ReRegisterData()
  428. {
  429. ReRegisterData(this);
  430. }
  431. /// <summary>
  432. /// Re-registers the data registered before.
  433. /// </summary>
  434. /// <param name="dictionary"></param>
  435. public void ReRegisterData(Dictionary dictionary)
  436. {
  437. // re-register all data items. It is needed after load or "new report" operations
  438. if (registeredItems.Count > 0)
  439. {
  440. DictionaryHelper helper = new DictionaryHelper(dictionary, dictionary.AllObjects, dictionary.Report.AllNamedObjects);
  441. helper.ReRegisterData(registeredItems, false);
  442. }
  443. }
  444. /// <summary>
  445. /// Clears all registered data.
  446. /// </summary>
  447. public void ClearRegisteredData()
  448. {
  449. registeredItems.Clear();
  450. }
  451. /// <summary>
  452. /// Enables or disables relations between data tables.
  453. /// </summary>
  454. /// <remarks>
  455. /// Call this method if you create master-detail report from code. This method enables
  456. /// relation between two data tables which <b>Enabled</b> flag is set to <b>true</b>. Relations
  457. /// whose parent and child tables are disabled, gets disabled too.
  458. /// </remarks>
  459. public void UpdateRelations()
  460. {
  461. foreach (Relation relation in Relations)
  462. {
  463. relation.Enabled = relation.ParentDataSource != null && relation.ParentDataSource.Enabled &&
  464. relation.ChildDataSource != null && relation.ChildDataSource.Enabled;
  465. }
  466. }
  467. /// <summary>
  468. /// Creates unique name for data item such as connection, datasource, relation, parameter or total.
  469. /// </summary>
  470. /// <param name="name">The base name.</param>
  471. /// <returns>The new unique name.</returns>
  472. /// <remarks>
  473. /// Use this method to create unique name of the data item. It is necessary when you create new
  474. /// items in code to avoid conflicts with existing report items.
  475. /// <example>This example show how to add a new parameter:
  476. /// <code>
  477. /// Report report1;
  478. /// Parameter par = new Parameter();
  479. /// par.Name = report1.Dictionary.CreateUniqueName("Parameter");
  480. /// report1.Parameters.Add(par);
  481. /// </code>
  482. /// </example>
  483. /// </remarks>
  484. public string CreateUniqueName(string name)
  485. {
  486. string baseName = name;
  487. int i = 1;
  488. while (FindByName(name) != null || Report.FindObject(name) != null)
  489. {
  490. name = baseName + i.ToString();
  491. i++;
  492. }
  493. return name;
  494. }
  495. /// <summary>
  496. /// Creates unique alias for data item such as connection, datasource or relation.
  497. /// </summary>
  498. /// <param name="alias">The base alias.</param>
  499. /// <returns>The new unique alias.</returns>
  500. /// <remarks>
  501. /// Use this method to create unique alias of the data item. It is necessary when you create new
  502. /// items in code to avoid conflicts with existing report items.
  503. /// <example>This example show how to add a new table:
  504. /// <code>
  505. /// Report report1;
  506. /// DataConnectionBase conn = report1.Dictionary.Connections.FindByName("Connection1");
  507. /// TableDataSource table = new TableDataSource();
  508. /// table.TableName = "Employees";
  509. /// table.Name = report1.Dictionary.CreateUniqueName("EmployeesTable");
  510. /// table.Alias = report1.Dictionary.CreateUniqueAlias("Employees");
  511. /// conn.Tables.Add(table);
  512. /// </code>
  513. /// </example>
  514. /// </remarks>
  515. public string CreateUniqueAlias(string alias)
  516. {
  517. string baseAlias = alias;
  518. int i = 1;
  519. while (FindByAlias(alias) != null)
  520. {
  521. alias = baseAlias + i.ToString();
  522. i++;
  523. }
  524. return alias;
  525. }
  526. /// <summary>
  527. /// Finds a data item such as connection, datasource, relation, parameter or total by its name.
  528. /// </summary>
  529. /// <param name="name">The item's name.</param>
  530. /// <returns>The data item if found; otherwise, <b>null</b>.</returns>
  531. public Base FindByName(string name)
  532. {
  533. foreach (Base c in AllObjects)
  534. {
  535. if (c is DataConnectionBase || c is DataSourceBase || c is Relation ||
  536. (c is Parameter && c.Parent == this) || c is Total || c is CubeSourceBase)
  537. {
  538. // check complete match or match without case sensitivity
  539. if (name == c.Name || name.ToLower() == c.Name.ToLower())
  540. return c;
  541. }
  542. }
  543. return null;
  544. }
  545. /// <summary>
  546. /// Finds a data item such as connection, datasource or relation by its alias.
  547. /// </summary>
  548. /// <param name="alias">The item's alias.</param>
  549. /// <returns>The data item if found; otherwise, <b>null</b>.</returns>
  550. public DataComponentBase FindByAlias(string alias)
  551. {
  552. foreach (Base c in AllObjects)
  553. {
  554. if (c is DataConnectionBase || c is Relation)
  555. {
  556. // check complete match or match without case sensitivity
  557. if (alias == (c as DataComponentBase).Alias || alias.ToLower() == (c as DataComponentBase).Alias.ToLower())
  558. return c as DataComponentBase;
  559. }
  560. else if (c is DataSourceBase)
  561. {
  562. // check complete match or match without case sensitivity
  563. if (alias == (c as DataSourceBase).FullName || alias.ToLower() == (c as DataSourceBase).FullName.ToLower())
  564. return c as DataSourceBase;
  565. }
  566. }
  567. return null;
  568. }
  569. /// <summary>
  570. /// Finds a datasource that matches the specified DataTable.
  571. /// </summary>
  572. /// <param name="table">The <b>DataTable</b> object to check.</param>
  573. /// <returns>The <b>DataSourceBase</b> object if found.</returns>
  574. /// <remarks>
  575. /// This method is for internal use only.
  576. /// </remarks>
  577. public DataSourceBase FindDataTableSource(DataTable table)
  578. {
  579. foreach (DataSourceBase c in DataSources)
  580. {
  581. if (c is TableDataSource && c.Reference == table)
  582. return c;
  583. }
  584. return null;
  585. }
  586. /// <summary>
  587. /// Finds a data component that matches the specified reference name.
  588. /// </summary>
  589. /// <param name="referenceName">The name to check.</param>
  590. /// <returns>The <b>DataComponentBase</b> object if found.</returns>
  591. /// <remarks>
  592. /// This method is for internal use only.
  593. /// </remarks>
  594. public DataComponentBase FindDataComponent(string referenceName)
  595. {
  596. foreach (Base c in AllObjects)
  597. {
  598. DataComponentBase data = c as DataComponentBase;
  599. if (data != null && data.ReferenceName == referenceName)
  600. return data;
  601. }
  602. return null;
  603. }
  604. /// <inheritdoc/>
  605. public override void Serialize(FRWriter writer)
  606. {
  607. writer.ItemName = ClassName;
  608. ObjectCollection childObjects = ChildObjects;
  609. foreach (Base c in childObjects)
  610. {
  611. if (c is Parameter || c is Total || c is CubeSourceBase || (c is DataComponentBase && (c as DataComponentBase).Enabled))
  612. writer.Write(c);
  613. }
  614. }
  615. /// <inheritdoc/>
  616. public override void Deserialize(FRReader reader)
  617. {
  618. base.Deserialize(reader);
  619. ReRegisterData();
  620. }
  621. /// <summary>
  622. /// Saves the dictionary to a stream.
  623. /// </summary>
  624. /// <param name="stream">Stream to save to.</param>
  625. public void Save(Stream stream)
  626. {
  627. using (FRWriter writer = new FRWriter())
  628. {
  629. writer.Write(this);
  630. writer.Save(stream);
  631. }
  632. }
  633. /// <summary>
  634. /// Saves the dictionary to a file.
  635. /// </summary>
  636. /// <param name="fileName">The name of a file to save to.</param>
  637. public void Save(string fileName)
  638. {
  639. using (FileStream f = new FileStream(fileName, FileMode.Create))
  640. {
  641. Save(f);
  642. }
  643. }
  644. /// <summary>
  645. /// Loads the dictionary from a stream.
  646. /// </summary>
  647. /// <param name="stream">The stream to load from.</param>
  648. public void Load(Stream stream)
  649. {
  650. Clear();
  651. using (FRReader reader = new FRReader(Report))
  652. {
  653. reader.Load(stream);
  654. reader.Read(this);
  655. }
  656. }
  657. /// <summary>
  658. /// Loads the dictionary from a file.
  659. /// </summary>
  660. /// <param name="fileName">The name of a file to load from.</param>
  661. public void Load(string fileName)
  662. {
  663. using (FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
  664. {
  665. Load(f);
  666. }
  667. }
  668. /// <summary>
  669. /// Merges this dictionary with another <b>Dictionary</b>.
  670. /// </summary>
  671. /// <param name="source">Another dictionary to merge the data from.</param>
  672. public void Merge(Dictionary source)
  673. {
  674. // Report object is needed to handle save/load of dictionary correctly.
  675. // Some dictionary objects (such as relations) may contain references to other objects.
  676. // In order to clone them correctly, we need a parent Report object, because
  677. // reader uses it to fixup references.
  678. using (Report cloneReport = new Report())
  679. {
  680. Dictionary clone = cloneReport.Dictionary;
  681. clone.AssignAll(source, true);
  682. foreach (Base c in clone.ChildObjects)
  683. {
  684. Base my = FindByName(c.Name);
  685. if (my != null)
  686. my.Dispose();
  687. c.Parent = this;
  688. }
  689. source.ReRegisterData(this);
  690. ReRegisterData();
  691. }
  692. }
  693. #endregion
  694. #region IParent Members
  695. /// <inheritdoc/>
  696. public bool CanContain(Base child)
  697. {
  698. return child is DataConnectionBase || child is DataSourceBase || child is Relation || child is Parameter ||
  699. child is Total || child is CubeSourceBase;
  700. }
  701. /// <inheritdoc/>
  702. public void GetChildObjects(ObjectCollection list)
  703. {
  704. foreach (DataConnectionBase c in Connections)
  705. {
  706. list.Add(c);
  707. }
  708. foreach (DataSourceBase c in DataSources)
  709. {
  710. list.Add(c);
  711. }
  712. foreach (Relation c in Relations)
  713. {
  714. list.Add(c);
  715. }
  716. foreach (Parameter c in Parameters)
  717. {
  718. list.Add(c);
  719. }
  720. foreach (Total c in Totals)
  721. {
  722. list.Add(c);
  723. }
  724. foreach (CubeSourceBase c in CubeSources)
  725. {
  726. list.Add(c);
  727. }
  728. }
  729. /// <inheritdoc/>
  730. public void AddChild(Base child)
  731. {
  732. if (child is DataConnectionBase)
  733. Connections.Add(child as DataConnectionBase);
  734. else if (child is DataSourceBase)
  735. DataSources.Add(child as DataSourceBase);
  736. else if (child is Relation)
  737. Relations.Add(child as Relation);
  738. else if (child is Parameter)
  739. Parameters.Add(child as Parameter);
  740. else if (child is Total)
  741. Totals.Add(child as Total);
  742. else if (child is CubeSourceBase)
  743. CubeSources.Add(child as CubeSourceBase);
  744. }
  745. /// <inheritdoc/>
  746. public void RemoveChild(Base child)
  747. {
  748. if (child is DataConnectionBase)
  749. Connections.Remove(child as DataConnectionBase);
  750. else if (child is DataSourceBase)
  751. DataSources.Remove(child as DataSourceBase);
  752. else if (child is Relation)
  753. Relations.Remove(child as Relation);
  754. else if (child is Parameter)
  755. Parameters.Remove(child as Parameter);
  756. else if (child is Total)
  757. Totals.Remove(child as Total);
  758. else if (child is CubeSourceBase)
  759. CubeSources.Remove(child as CubeSourceBase);
  760. }
  761. /// <inheritdoc/>
  762. public int GetChildOrder(Base child)
  763. {
  764. return 0;
  765. }
  766. /// <inheritdoc/>
  767. public void SetChildOrder(Base child, int order)
  768. {
  769. // do nothing
  770. }
  771. /// <inheritdoc/>
  772. public void UpdateLayout(float dx, float dy)
  773. {
  774. // do nothing
  775. }
  776. #endregion
  777. /// <summary>
  778. /// Initializes a new instance of the <see cref="Dictionary"/> class with default settings.
  779. /// </summary>
  780. public Dictionary()
  781. {
  782. connections = new ConnectionCollection(this);
  783. dataSources = new DataSourceCollection(this);
  784. relations = new RelationCollection(this);
  785. parameters = new ParameterCollection(this);
  786. systemVariables = new SystemVariables(this);
  787. totals = new TotalCollection(this);
  788. cubeSources = new CubeSourceCollection(this);
  789. registeredItems = new List<RegDataItem>();
  790. }
  791. /// <summary>
  792. /// Represents the item registered in a dictionary.
  793. /// </summary>
  794. public class RegDataItem
  795. {
  796. /// <summary>
  797. /// Gets the item data.
  798. /// </summary>
  799. public object data;
  800. /// <summary>
  801. /// Gets the item name.
  802. /// </summary>
  803. public string name;
  804. internal RegDataItem(object data, string name)
  805. {
  806. this.data = data;
  807. this.name = name;
  808. }
  809. }
  810. }
  811. }