ReportBuilder.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. using MediaBrowser.Controller.Entities;
  2. using MediaBrowser.Controller.Entities.Audio;
  3. using MediaBrowser.Controller.Entities.Movies;
  4. using MediaBrowser.Controller.Entities.TV;
  5. using MediaBrowser.Controller.Library;
  6. using MediaBrowser.Controller.Localization;
  7. using MediaBrowser.Model.Channels;
  8. using MediaBrowser.Model.Dto;
  9. using MediaBrowser.Model.Entities;
  10. using MediaBrowser.Model.Querying;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Linq.Expressions;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. namespace MediaBrowser.Api.Reports
  18. {
  19. /// <summary> A report builder. </summary>
  20. /// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
  21. public class ReportBuilder : ReportBuilderBase
  22. {
  23. /// <summary>
  24. /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportBuilder class. </summary>
  25. /// <param name="libraryManager"> Manager for library. </param>
  26. public ReportBuilder(ILibraryManager libraryManager)
  27. : base(libraryManager)
  28. {
  29. }
  30. private Func<bool, string> GetBoolString = s => s == true ? "x" : "";
  31. public ReportResult GetReportResult(BaseItem[] items, ReportViewType reportRowType, BaseReportRequest request)
  32. {
  33. List<HeaderMetadata> headersMetadata = this.GetFilteredReportHeaderMetadata(reportRowType, request);
  34. var headers = GetReportHeaders(reportRowType, headersMetadata);
  35. var rows = GetReportRows(items, headersMetadata);
  36. ReportResult result = new ReportResult { Headers = headers };
  37. HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy);
  38. int i = headers.FindIndex(x => x.FieldName == groupBy);
  39. if (groupBy != HeaderMetadata.None && i > 0)
  40. {
  41. var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Genre = g.Trim(), Rows = x })
  42. .GroupBy(x => x.Genre)
  43. .OrderBy(x => x.Key)
  44. .Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() });
  45. result.Groups = rowsGroup.ToList();
  46. result.IsGrouped = true;
  47. }
  48. else
  49. {
  50. result.Rows = rows;
  51. result.IsGrouped = false;
  52. }
  53. return result;
  54. }
  55. public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, BaseReportRequest request)
  56. {
  57. List<ReportHeader> headersMetadata = this.GetReportHeaders(reportRowType);
  58. if (request != null && !string.IsNullOrEmpty(request.ReportColumns))
  59. {
  60. List<HeaderMetadata> headersMetadataFiltered = this.GetFilteredReportHeaderMetadata(reportRowType, request);
  61. foreach (ReportHeader reportHeader in headersMetadata)
  62. {
  63. if (!headersMetadataFiltered.Contains(reportHeader.FieldName))
  64. {
  65. reportHeader.Visible = false;
  66. }
  67. }
  68. }
  69. return headersMetadata;
  70. }
  71. public List<ReportHeader> GetReportHeaders(ReportViewType reportRowType, List<HeaderMetadata> headersMetadata = null)
  72. {
  73. if (headersMetadata == null)
  74. headersMetadata = this.GetDefaultReportHeaderMetadata(reportRowType);
  75. List<ReportOptions<BaseItem>> options = new List<ReportOptions<BaseItem>>();
  76. foreach (HeaderMetadata header in headersMetadata)
  77. {
  78. options.Add(GetReportOption(header));
  79. }
  80. List<ReportHeader> headers = new List<ReportHeader>();
  81. foreach (ReportOptions<BaseItem> option in options)
  82. {
  83. headers.Add(option.Header);
  84. }
  85. return headers;
  86. }
  87. private List<ReportRow> GetReportRows(IEnumerable<BaseItem> items, List<HeaderMetadata> headersMetadata)
  88. {
  89. List<ReportOptions<BaseItem>> options = new List<ReportOptions<BaseItem>>();
  90. foreach (HeaderMetadata header in headersMetadata)
  91. {
  92. options.Add(GetReportOption(header));
  93. }
  94. var rows = new List<ReportRow>();
  95. foreach (BaseItem item in items)
  96. {
  97. ReportRow rRow = GetRow(item);
  98. foreach (ReportOptions<BaseItem> option in options)
  99. {
  100. object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
  101. object itemId = option.ItemID != null ? option.ItemID(item) : "";
  102. ReportItem rItem = new ReportItem
  103. {
  104. Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
  105. Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
  106. };
  107. rRow.Columns.Add(rItem);
  108. }
  109. rows.Add(rRow);
  110. }
  111. return rows;
  112. }
  113. /// <summary> Gets a row. </summary>
  114. /// <param name="item"> The item. </param>
  115. /// <returns> The row. </returns>
  116. private ReportRow GetRow(BaseItem item)
  117. {
  118. var hasTrailers = item as IHasTrailers;
  119. var hasSpecialFeatures = item as IHasSpecialFeatures;
  120. var video = item as Video;
  121. ReportRow rRow = new ReportRow
  122. {
  123. Id = item.Id.ToString("N"),
  124. HasLockData = item.IsLocked,
  125. IsUnidentified = item.IsUnidentified,
  126. HasLocalTrailer = hasTrailers != null ? hasTrailers.GetTrailerIds().Count() > 0 : false,
  127. HasImageTagsPrimary = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Primary) > 0),
  128. HasImageTagsBackdrop = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Backdrop) > 0),
  129. HasImageTagsLogo = (item.ImageInfos != null && item.ImageInfos.Count(n => n.Type == ImageType.Logo) > 0),
  130. HasSpecials = hasSpecialFeatures != null ? hasSpecialFeatures.SpecialFeatureIds.Count > 0 : false,
  131. HasSubtitles = video != null ? video.HasSubtitles : false,
  132. RowType = ReportHelper.GetRowType(item.GetClientTypeName())
  133. };
  134. return rRow;
  135. }
  136. public List<HeaderMetadata> GetFilteredReportHeaderMetadata(ReportViewType reportRowType, BaseReportRequest request)
  137. {
  138. if (request != null && !string.IsNullOrEmpty(request.ReportColumns))
  139. {
  140. var s = request.ReportColumns.Split('|').Select(x => ReportHelper.GetHeaderMetadataType(x)).Where(x => x != HeaderMetadata.None);
  141. return s.ToList();
  142. }
  143. else
  144. return this.GetDefaultReportHeaderMetadata(reportRowType);
  145. }
  146. public List<HeaderMetadata> GetDefaultReportHeaderMetadata(ReportViewType reportRowType)
  147. {
  148. switch (reportRowType)
  149. {
  150. case ReportViewType.Season:
  151. return new List<HeaderMetadata>
  152. {
  153. HeaderMetadata.StatusImage,
  154. HeaderMetadata.Series,
  155. HeaderMetadata.Season,
  156. HeaderMetadata.SeasonNumber,
  157. HeaderMetadata.DateAdded,
  158. HeaderMetadata.Year,
  159. HeaderMetadata.Genres
  160. };
  161. case ReportViewType.Series:
  162. return new List<HeaderMetadata>
  163. {
  164. HeaderMetadata.StatusImage,
  165. HeaderMetadata.Name,
  166. HeaderMetadata.Network,
  167. HeaderMetadata.DateAdded,
  168. HeaderMetadata.Year,
  169. HeaderMetadata.Genres,
  170. HeaderMetadata.ParentalRating,
  171. HeaderMetadata.CommunityRating,
  172. HeaderMetadata.Runtime,
  173. HeaderMetadata.Trailers,
  174. HeaderMetadata.Specials
  175. };
  176. case ReportViewType.MusicAlbum:
  177. return new List<HeaderMetadata>
  178. {
  179. HeaderMetadata.StatusImage,
  180. HeaderMetadata.Name,
  181. HeaderMetadata.AlbumArtist,
  182. HeaderMetadata.DateAdded,
  183. HeaderMetadata.ReleaseDate,
  184. HeaderMetadata.Tracks,
  185. HeaderMetadata.Year,
  186. HeaderMetadata.Genres
  187. };
  188. case ReportViewType.MusicArtist:
  189. return new List<HeaderMetadata>
  190. {
  191. HeaderMetadata.StatusImage,
  192. HeaderMetadata.MusicArtist,
  193. HeaderMetadata.Countries,
  194. HeaderMetadata.DateAdded,
  195. HeaderMetadata.Year,
  196. HeaderMetadata.Genres
  197. };
  198. case ReportViewType.Game:
  199. return new List<HeaderMetadata>
  200. {
  201. HeaderMetadata.StatusImage,
  202. HeaderMetadata.Name,
  203. HeaderMetadata.GameSystem,
  204. HeaderMetadata.DateAdded,
  205. HeaderMetadata.ReleaseDate,
  206. HeaderMetadata.ParentalRating,
  207. HeaderMetadata.CommunityRating,
  208. HeaderMetadata.Players,
  209. HeaderMetadata.Year,
  210. HeaderMetadata.Genres,
  211. HeaderMetadata.Trailers
  212. };
  213. case ReportViewType.Movie:
  214. return new List<HeaderMetadata>
  215. {
  216. HeaderMetadata.StatusImage,
  217. HeaderMetadata.Name,
  218. HeaderMetadata.DateAdded,
  219. HeaderMetadata.ReleaseDate,
  220. HeaderMetadata.Year,
  221. HeaderMetadata.Genres,
  222. HeaderMetadata.ParentalRating,
  223. HeaderMetadata.CommunityRating,
  224. HeaderMetadata.Runtime,
  225. HeaderMetadata.Video,
  226. HeaderMetadata.Resolution,
  227. HeaderMetadata.Audio,
  228. HeaderMetadata.Subtitles,
  229. HeaderMetadata.Trailers,
  230. HeaderMetadata.Specials
  231. };
  232. case ReportViewType.Book:
  233. return new List<HeaderMetadata>
  234. {
  235. HeaderMetadata.StatusImage,
  236. HeaderMetadata.Name,
  237. HeaderMetadata.DateAdded,
  238. HeaderMetadata.ReleaseDate,
  239. HeaderMetadata.Year,
  240. HeaderMetadata.Genres,
  241. HeaderMetadata.ParentalRating,
  242. HeaderMetadata.CommunityRating
  243. };
  244. case ReportViewType.BoxSet:
  245. return new List<HeaderMetadata>
  246. {
  247. HeaderMetadata.StatusImage,
  248. HeaderMetadata.Name,
  249. HeaderMetadata.DateAdded,
  250. HeaderMetadata.ReleaseDate,
  251. HeaderMetadata.Year,
  252. HeaderMetadata.Genres,
  253. HeaderMetadata.ParentalRating,
  254. HeaderMetadata.CommunityRating,
  255. HeaderMetadata.Trailers
  256. };
  257. case ReportViewType.Audio:
  258. return new List<HeaderMetadata>
  259. {
  260. HeaderMetadata.StatusImage,
  261. HeaderMetadata.Name,
  262. HeaderMetadata.AudioAlbumArtist,
  263. HeaderMetadata.AudioAlbum,
  264. HeaderMetadata.Disc,
  265. HeaderMetadata.Track,
  266. HeaderMetadata.DateAdded,
  267. HeaderMetadata.ReleaseDate,
  268. HeaderMetadata.Year,
  269. HeaderMetadata.Genres,
  270. HeaderMetadata.ParentalRating,
  271. HeaderMetadata.CommunityRating,
  272. HeaderMetadata.Runtime,
  273. HeaderMetadata.Audio
  274. };
  275. case ReportViewType.Episode:
  276. return new List<HeaderMetadata>
  277. {
  278. HeaderMetadata.StatusImage,
  279. HeaderMetadata.Name,
  280. HeaderMetadata.EpisodeSeries,
  281. HeaderMetadata.Season,
  282. HeaderMetadata.DateAdded,
  283. HeaderMetadata.ReleaseDate,
  284. HeaderMetadata.Year,
  285. HeaderMetadata.Genres,
  286. HeaderMetadata.ParentalRating,
  287. HeaderMetadata.CommunityRating,
  288. HeaderMetadata.Runtime,
  289. HeaderMetadata.Video,
  290. HeaderMetadata.Resolution,
  291. HeaderMetadata.Audio,
  292. HeaderMetadata.Subtitles,
  293. HeaderMetadata.Trailers,
  294. HeaderMetadata.Specials
  295. };
  296. case ReportViewType.Video:
  297. case ReportViewType.MusicVideo:
  298. case ReportViewType.Trailer:
  299. case ReportViewType.BaseItem:
  300. default:
  301. return new List<HeaderMetadata>
  302. {
  303. HeaderMetadata.StatusImage,
  304. HeaderMetadata.Name,
  305. HeaderMetadata.DateAdded,
  306. HeaderMetadata.ReleaseDate,
  307. HeaderMetadata.Year,
  308. HeaderMetadata.Genres,
  309. HeaderMetadata.ParentalRating,
  310. HeaderMetadata.CommunityRating,
  311. HeaderMetadata.Runtime,
  312. HeaderMetadata.Video,
  313. HeaderMetadata.Resolution,
  314. HeaderMetadata.Audio,
  315. HeaderMetadata.Subtitles,
  316. HeaderMetadata.Trailers,
  317. HeaderMetadata.Specials
  318. };
  319. }
  320. }
  321. /// <summary> Gets report option. </summary>
  322. /// <param name="header"> The header. </param>
  323. /// <param name="sortField"> The sort field. </param>
  324. /// <returns> The report option. </returns>
  325. private ReportOptions<BaseItem> GetReportOption(HeaderMetadata header, string sortField = "")
  326. {
  327. ReportHeader reportHeader = new ReportHeader
  328. {
  329. HeaderFieldType = ReportFieldType.String,
  330. SortField = sortField,
  331. Type = "",
  332. ItemViewType = ItemViewType.None
  333. };
  334. Func<BaseItem, ReportRow, object> column = null;
  335. Func<BaseItem, object> itemId = null;
  336. HeaderMetadata internalHeader = header;
  337. switch (header)
  338. {
  339. case HeaderMetadata.StatusImage:
  340. reportHeader.ItemViewType = ItemViewType.StatusImage;
  341. internalHeader = HeaderMetadata.Status;
  342. reportHeader.CanGroup = false;
  343. break;
  344. case HeaderMetadata.Name:
  345. column = (i, r) => i.Name;
  346. reportHeader.ItemViewType = ItemViewType.Detail;
  347. reportHeader.SortField = "SortName";
  348. break;
  349. case HeaderMetadata.DateAdded:
  350. column = (i, r) => i.DateCreated;
  351. reportHeader.SortField = "DateCreated,SortName";
  352. reportHeader.HeaderFieldType = ReportFieldType.DateTime;
  353. reportHeader.Type = "";
  354. break;
  355. case HeaderMetadata.PremiereDate:
  356. case HeaderMetadata.ReleaseDate:
  357. column = (i, r) => i.PremiereDate;
  358. reportHeader.HeaderFieldType = ReportFieldType.DateTime;
  359. reportHeader.SortField = "ProductionYear,PremiereDate,SortName";
  360. break;
  361. case HeaderMetadata.Runtime:
  362. column = (i, r) => this.GetRuntimeDateTime(i.RunTimeTicks);
  363. reportHeader.HeaderFieldType = ReportFieldType.Minutes;
  364. reportHeader.SortField = "Runtime,SortName";
  365. break;
  366. case HeaderMetadata.PlayCount:
  367. reportHeader.HeaderFieldType = ReportFieldType.Int;
  368. break;
  369. case HeaderMetadata.Season:
  370. column = (i, r) => this.GetEpisode(i);
  371. reportHeader.ItemViewType = ItemViewType.Detail;
  372. reportHeader.SortField = "SortName";
  373. break;
  374. case HeaderMetadata.SeasonNumber:
  375. column = (i, r) => this.GetObject<Season, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
  376. reportHeader.SortField = "IndexNumber";
  377. reportHeader.HeaderFieldType = ReportFieldType.Int;
  378. break;
  379. case HeaderMetadata.Series:
  380. column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
  381. reportHeader.ItemViewType = ItemViewType.Detail;
  382. reportHeader.SortField = "SeriesSortName,SortName";
  383. break;
  384. case HeaderMetadata.EpisodeSeries:
  385. column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
  386. reportHeader.ItemViewType = ItemViewType.Detail;
  387. itemId = (i) =>
  388. {
  389. Series series = this.GetObject<Episode, Series>(i, (x) => x.Series);
  390. if (series == null)
  391. return string.Empty;
  392. return series.Id;
  393. };
  394. reportHeader.SortField = "SeriesSortName,SortName";
  395. internalHeader = HeaderMetadata.Series;
  396. break;
  397. case HeaderMetadata.EpisodeSeason:
  398. column = (i, r) => this.GetObject<IHasSeries, string>(i, (x) => x.SeriesName);
  399. reportHeader.ItemViewType = ItemViewType.Detail;
  400. itemId = (i) =>
  401. {
  402. Season season = this.GetObject<Episode, Season>(i, (x) => x.Season);
  403. if (season == null)
  404. return string.Empty;
  405. return season.Id;
  406. };
  407. reportHeader.SortField = "SortName";
  408. internalHeader = HeaderMetadata.Season;
  409. break;
  410. case HeaderMetadata.Network:
  411. column = (i, r) => this.GetListAsString(i.Studios);
  412. itemId = (i) => this.GetStudioID(i.Studios.FirstOrDefault());
  413. reportHeader.ItemViewType = ItemViewType.ItemByNameDetails;
  414. reportHeader.SortField = "Studio,SortName";
  415. break;
  416. case HeaderMetadata.Year:
  417. column = (i, r) => this.GetSeriesProductionYear(i);
  418. reportHeader.SortField = "ProductionYear,PremiereDate,SortName";
  419. break;
  420. case HeaderMetadata.ParentalRating:
  421. column = (i, r) => i.OfficialRating;
  422. reportHeader.SortField = "OfficialRating,SortName";
  423. break;
  424. case HeaderMetadata.CommunityRating:
  425. column = (i, r) => i.CommunityRating;
  426. reportHeader.SortField = "CommunityRating,SortName";
  427. break;
  428. case HeaderMetadata.Trailers:
  429. column = (i, r) => this.GetBoolString(r.HasLocalTrailer);
  430. reportHeader.ItemViewType = ItemViewType.TrailersImage;
  431. break;
  432. case HeaderMetadata.Specials:
  433. column = (i, r) => this.GetBoolString(r.HasSpecials);
  434. reportHeader.ItemViewType = ItemViewType.SpecialsImage;
  435. break;
  436. case HeaderMetadata.GameSystem:
  437. column = (i, r) => this.GetObject<Game, string>(i, (x) => x.GameSystem);
  438. reportHeader.SortField = "GameSystem,SortName";
  439. break;
  440. case HeaderMetadata.Players:
  441. column = (i, r) => this.GetObject<Game, int?>(i, (x) => x.PlayersSupported);
  442. reportHeader.SortField = "Players,GameSystem,SortName";
  443. break;
  444. case HeaderMetadata.AlbumArtist:
  445. column = (i, r) => this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist);
  446. itemId = (i) => this.GetPersonID(this.GetObject<MusicAlbum, string>(i, (x) => x.AlbumArtist));
  447. reportHeader.ItemViewType = ItemViewType.Detail;
  448. reportHeader.SortField = "AlbumArtist,Album,SortName";
  449. break;
  450. case HeaderMetadata.MusicArtist:
  451. column = (i, r) => this.GetObject<MusicArtist, string>(i, (x) => x.GetLookupInfo().Name);
  452. reportHeader.ItemViewType = ItemViewType.Detail;
  453. reportHeader.SortField = "AlbumArtist,Album,SortName";
  454. internalHeader = HeaderMetadata.AlbumArtist;
  455. break;
  456. case HeaderMetadata.AudioAlbumArtist:
  457. column = (i, r) => this.GetListAsString(this.GetObject<Audio, List<string>>(i, (x) => x.AlbumArtists));
  458. reportHeader.SortField = "AlbumArtist,Album,SortName";
  459. internalHeader = HeaderMetadata.AlbumArtist;
  460. break;
  461. case HeaderMetadata.AudioAlbum:
  462. column = (i, r) => this.GetObject<Audio, string>(i, (x) => x.Album);
  463. reportHeader.SortField = "Album,SortName";
  464. internalHeader = HeaderMetadata.Album;
  465. break;
  466. case HeaderMetadata.Countries:
  467. column = (i, r) => this.GetListAsString(this.GetObject<IHasProductionLocations, List<string>>(i, (x) => x.ProductionLocations));
  468. break;
  469. case HeaderMetadata.Disc:
  470. column = (i, r) => i.ParentIndexNumber;
  471. break;
  472. case HeaderMetadata.Track:
  473. column = (i, r) => i.IndexNumber;
  474. break;
  475. case HeaderMetadata.Tracks:
  476. column = (i, r) => this.GetObject<MusicAlbum, List<Audio>>(i, (x) => x.Tracks.ToList(), new List<Audio>()).Count();
  477. break;
  478. case HeaderMetadata.Audio:
  479. column = (i, r) => this.GetAudioStream(i);
  480. break;
  481. case HeaderMetadata.EmbeddedImage:
  482. break;
  483. case HeaderMetadata.Video:
  484. column = (i, r) => this.GetVideoStream(i);
  485. break;
  486. case HeaderMetadata.Resolution:
  487. column = (i, r) => this.GetVideoResolution(i);
  488. break;
  489. case HeaderMetadata.Subtitles:
  490. column = (i, r) => this.GetBoolString(r.HasSubtitles);
  491. reportHeader.ItemViewType = ItemViewType.SubtitleImage;
  492. break;
  493. case HeaderMetadata.Genres:
  494. column = (i, r) => this.GetListAsString(i.Genres);
  495. break;
  496. }
  497. string headerName = "";
  498. if (internalHeader != HeaderMetadata.None)
  499. {
  500. string localHeader = "Header" + internalHeader.ToString();
  501. headerName = internalHeader != HeaderMetadata.None ? ReportHelper.GetJavaScriptLocalizedString(localHeader) : "";
  502. if (string.Compare(localHeader, headerName, StringComparison.CurrentCultureIgnoreCase) == 0)
  503. headerName = ReportHelper.GetServerLocalizedString(localHeader);
  504. }
  505. reportHeader.Name = headerName;
  506. reportHeader.FieldName = header;
  507. ReportOptions<BaseItem> option = new ReportOptions<BaseItem>()
  508. {
  509. Header = reportHeader,
  510. Column = column,
  511. ItemID = itemId
  512. };
  513. return option;
  514. }
  515. }
  516. }