PageRenderTime 68ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/Server/IServV2/IPhone/Plugins/Content/AFP.IPhone.Content.Plugins.JournalInternet/Plugin.cs

https://bitbucket.org/fboltz/afpmobile
C# | 3180 lines | 2278 code | 446 blank | 456 comment | 372 complexity | 89b288cb6c243a771e0dbf16bfc6be8c MD5 | raw file
Possible License(s): Apache-2.0, MPL-2.0, LGPL-2.1, MIT, BSD-3-Clause, 0BSD, AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. using AFP.IPhone.Application;
  2. using AFP.IPhone.Extensions;
  3. using AFP.IPhone.Storage;
  4. using AFP.IPhone.Processor.Plugins.JournalInternet.Documents;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Data;
  8. using System.Data.SqlClient;
  9. using System.Drawing;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Text.RegularExpressions;
  14. using System.Threading;
  15. using System.Xml;
  16. using System.Xml.Xsl;
  17. using System.Web.Services;
  18. using System.Globalization;
  19. #if SERVICE
  20. using AFP.IPhone.Plugins.GetCourseId;
  21. #endif
  22. namespace AFP.IPhone.Processor.Plugins.JournalInternet
  23. {
  24. class ExXmlTextWriter : XmlTextWriter
  25. {
  26. private StringWriter mvar_Writer;
  27. private ExXmlTextWriter(StringWriter w)
  28. : base(w)
  29. {
  30. mvar_Writer = w;
  31. // Indentation
  32. this.Formatting = Formatting.Indented;
  33. this.Indentation = 2;
  34. }
  35. public ExXmlTextWriter()
  36. : this(new StringWriter())
  37. {
  38. }
  39. public override string ToString()
  40. {
  41. return mvar_Writer.ToString();
  42. }
  43. }
  44. /// <summary>
  45. /// Class to handle JI AFP iPhone Content
  46. /// </summary>
  47. ///
  48. public class Plugin : ProcessorPluginBase
  49. {
  50. private const string _storagePhotosFormatName = "Photos";
  51. private const string _storageVideosFormatName = "Videos";
  52. private const string _storageDocumentFormatName = "Documents";
  53. private readonly List<SqlProcessor> _sqlProcessorList;
  54. private readonly List<SqlProcessor> _sqlProcessorList2;
  55. private readonly List<string> _dynamicTopicList;
  56. private XmlDocument _sites;
  57. private ProcessorServer.TTrace _levelTrace;
  58. private int _Version =1;
  59. private string _ImageActive ="true";
  60. private string _PreviewRole ="HighDef";
  61. private Boolean _UseUri = false;
  62. private System.Collections.Hashtable _Xslt;
  63. private static XmlWriter createXmlWriter()
  64. {
  65. return new ExXmlTextWriter();
  66. }
  67. public struct RatingEntry
  68. {
  69. public readonly string Lang;
  70. public readonly string NewsId;
  71. public readonly string TopicId;
  72. public RatingEntry(string topicId, string newsId, string lang)
  73. {
  74. Lang = lang;
  75. NewsId = newsId;
  76. TopicId = topicId;
  77. }
  78. }
  79. public struct HitEntry
  80. {
  81. public readonly string Lang;
  82. public readonly string NewsId;
  83. public readonly string TopicId;
  84. public readonly int Hits;
  85. public HitEntry(string topicId, string newsId, string lang, int hits)
  86. {
  87. Lang = lang;
  88. NewsId = newsId;
  89. TopicId = topicId;
  90. Hits = hits;
  91. }
  92. }
  93. public struct RatingEntryKey : IComparable<RatingEntryKey>
  94. {
  95. private readonly string _value;
  96. public RatingEntryKey(DateTime newsDate, DataRow row)
  97. {
  98. _value = string.Format("{0}{1}", (((double)row["averageRating"] * 1000) / (1 + (Math.Truncate(DateTime.Now.Subtract(newsDate).TotalDays) * 10))).ToString("0000"), ((int)row["votes"]).ToString("0000000000"));
  99. }
  100. public int CompareTo(RatingEntryKey other)
  101. {
  102. var cmp = other._value.CompareTo(_value);
  103. return (cmp == 0) ? -1 : cmp;
  104. }
  105. }
  106. private enum ComponentType
  107. {
  108. photo,
  109. video,
  110. text,
  111. unsupported
  112. }
  113. private enum MessageSection
  114. {
  115. Alimentation,
  116. Database,
  117. Processing
  118. }
  119. private enum NewsMediaFilter
  120. {
  121. all,
  122. photoOnly,
  123. videoOnly
  124. }
  125. private static Object GBLock = new Object();
  126. /// <summary>
  127. /// Creates a new instance of Plugin
  128. /// </summary>
  129. ///
  130. public Plugin()
  131. {
  132. // Initialisations
  133. _dynamicTopicList = new List<string>();
  134. _sqlProcessorList = new List<SqlProcessor>();
  135. _sites = new XmlDocument();
  136. _Xslt = new System.Collections.Hashtable();
  137. // Chargement sites
  138. _sites.LoadXml("<sites/>");
  139. // Initialisation des bases rating
  140. try
  141. {
  142. foreach (var connection in Configuration.GetAttribute("ratingConnection").Split('|'))
  143. {
  144. if (string.IsNullOrEmpty(connection) == false)
  145. _sqlProcessorList.Add(new SqlProcessor(connection));
  146. }
  147. foreach (var connection in Configuration.GetAttribute("alertConnection").Split('|'))
  148. {
  149. if (string.IsNullOrEmpty(connection) == false)
  150. _sqlProcessorList2.Add(new SqlProcessor(connection));
  151. }
  152. }
  153. catch (Exception e)
  154. {
  155. Process.Trace(e, System.Diagnostics.EventLogEntryType.Error);
  156. throw;
  157. }
  158. }
  159. /// <summary>
  160. /// Gets the plugin key name.
  161. /// </summary>
  162. ///
  163. public override string Key
  164. {
  165. get { return "JI"; }
  166. }
  167. /// <summary>
  168. /// Get or Set Leveltrace
  169. /// </summary>
  170. public override ProcessorServer.TTrace levelTrace
  171. {
  172. get
  173. {
  174. return _levelTrace;
  175. }
  176. set
  177. {
  178. _levelTrace = value;
  179. }
  180. }
  181. public override int Version
  182. {
  183. get
  184. {
  185. return _Version;
  186. }
  187. set
  188. {
  189. _Version = value;
  190. }
  191. }
  192. public override string ImageActive
  193. {
  194. get
  195. {
  196. return _ImageActive;
  197. }
  198. set
  199. {
  200. _ImageActive = value;
  201. }
  202. }
  203. public override bool UseUri
  204. {
  205. get
  206. {
  207. return _UseUri;
  208. }
  209. set
  210. {
  211. _UseUri = value;
  212. }
  213. }
  214. public override string PreviewRole
  215. {
  216. get
  217. {
  218. return _PreviewRole;
  219. }
  220. set
  221. {
  222. _PreviewRole = value;
  223. }
  224. }
  225. public override void MakeTopic(string topicId)
  226. {
  227. TopicImplementation topic;
  228. topic = TopicImplementation.Load(topicId);
  229. MakeTopic(topic, false, null);
  230. }
  231. /// <summary>
  232. /// Process the defined topics.
  233. /// </summary>
  234. /// <param name="content">The content configuration.</param>
  235. /// <param name="refresh">Flag for refreshing content.</param>
  236. ///
  237. public override void MakeTopics(XmlElement content, bool refresh, Boolean multiThread, int maxThreads)
  238. {
  239. var doneTopics = new List<ManualResetEvent>();
  240. //note : Traitement de tous les topics et subtopics du site
  241. try
  242. {
  243. foreach (XmlNode item in content.ChildNodes)
  244. {
  245. if (item is XmlElement)
  246. {
  247. if (item.HasChildNodes)
  248. MakeTopics((XmlElement)item, refresh, Boolean.Parse(item.GetAttributeValue("multiThread", multiThread.ToString())), maxThreads);
  249. // Traitement d'un topic
  250. if (item.Name.Equals("topic") || item.Name.Equals("subtopic"))
  251. {
  252. // dans le cadre du Touch il faut passer l'id et non l'item...
  253. var topic = new TopicImplementation((XmlElement)item);
  254. // note: Tout ce passe ici pour la synchro
  255. if (multiThread == false)
  256. {
  257. MakeTopic(topic, refresh, null);
  258. }
  259. else
  260. {
  261. if (topic.DynamicDelay.Equals(TimeSpan.Zero))
  262. {
  263. doneTopics.Add(new ManualResetEvent(false));
  264. ThreadPool.QueueUserWorkItem
  265. (
  266. MakeTopic, new object[]
  267. {
  268. topic,
  269. refresh,
  270. doneTopics[doneTopics.Count - 1]
  271. });
  272. // Limitation WaitAll à 64
  273. if (doneTopics.Count == maxThreads)
  274. {
  275. WaitHandle.WaitAll(doneTopics.ToArray());
  276. doneTopics.Clear();
  277. }
  278. }
  279. else if (_dynamicTopicList.Contains(topic.Id) == false)
  280. {
  281. var dynamicMakeTopicThread = new Thread(MakeTopicFromThread);
  282. dynamicMakeTopicThread.IsBackground = true;
  283. dynamicMakeTopicThread.Name = String.Format("MakeTopics:{0}", topic.Id);
  284. dynamicMakeTopicThread.Start(topic);
  285. _dynamicTopicList.Add(topic.Id);
  286. }
  287. }
  288. }
  289. }
  290. }
  291. }
  292. finally
  293. {
  294. // Attente fin de traitement de tous les topics d'un même niveau
  295. if (doneTopics.Count > 0)
  296. WaitHandle.WaitAll(doneTopics.ToArray());
  297. }
  298. }
  299. /// <summary>
  300. /// Rate a media.
  301. /// </summary>
  302. /// <param name="topicImplementation">Topic implementation.</param>
  303. /// <param name="newsId">Id of the owner news.</param>
  304. /// <param name="mediaId">Id of the media.</param>
  305. /// <param name="rate">Rate value.</param>
  306. ///
  307. public override string Rate(TopicImplementation topicImplementation, string productId, string newsId, string mediaId, float rate, string device)
  308. {
  309. //en cours
  310. double realRate = rate;
  311. int votes;
  312. // Vérification site
  313. if (_sites == null)
  314. new Rating(rate, "Invalid site value.", 1).ToString();
  315. lock (_sites)
  316. {
  317. // Récupération des votes
  318. GetRating(string.Format("SELECT SUM(votes) AS votes, SUM(rating) AS rating FROM Ratings2 WHERE mediaId='{0}' and productId='{1}' GROUP BY mediaId", mediaId, productId), ref realRate, out votes);
  319. // Vote
  320. foreach (var sqlProcessor in _sqlProcessorList)
  321. sqlProcessor.Add(new SqlMediaRateRequest(productId, topicImplementation.Id, newsId, mediaId, topicImplementation.Lang, rate, device));
  322. }
  323. return new Rating(rate, realRate, votes).ToString();
  324. }
  325. /// <summary>
  326. /// Rate a media.
  327. /// </summary>
  328. /// <param name="topicImplementation">Topic implementation</param>
  329. /// <param name="topicId">Id of the owner topic.</param>
  330. /// <param name="newsId">Id of the owner news.</param>
  331. /// <param name="rate">Rate value.</param>
  332. ///
  333. public override string Rate(TopicImplementation topicImplementation, string productId, string newsId, float rate, string device)
  334. {
  335. double realRate = rate;
  336. int votes;
  337. // Vérification site
  338. if (_sites == null)
  339. new Rating(rate, "Invalid site value.", 1).ToString();
  340. lock (_sites)
  341. {
  342. // Récupération des votes
  343. GetRating(string.Format("SELECT SUM(votes) AS votes, SUM(rating) AS rating FROM Ratings2 WHERE newsId='{0}' AND mediaId IS NULL AND producId='{1}' GROUP BY newsId", newsId, productId), ref realRate, out votes);
  344. // Vote
  345. foreach (var sqlProcessor in _sqlProcessorList)
  346. {
  347. sqlProcessor.Add(new SqlNewsRateRequest(productId, topicImplementation.Id, newsId, topicImplementation.Lang, rate, device));
  348. #if DEBUG && TRACE_REQUEST
  349. Process.Trace(string.Format(" productId {0} topicId {1} newsId {2} lang {3} rating {4} device {5} ", productId, topicImplementation.Id, newsId, topicImplementation.Lang, rate, device), System.Diagnostics.EventLogEntryType.Information);
  350. #endif
  351. }
  352. }
  353. return new Rating(rate, realRate, votes).ToString();
  354. }
  355. /// <summary>
  356. /// Appel via WCF pour connaitre le vote sur un article ou une photo
  357. /// </summary>
  358. /// <param name="productId"></param>
  359. /// <param name="topicId"></param>
  360. /// <param name="newsId"></param>
  361. /// <param name="mediaId"></param>
  362. /// <param name="lang"></param>
  363. /// <param name="rate"></param>
  364. /// <param name="vote"></param>
  365. public override void getRated(string productId, string topicId, string newsId, string mediaId, string lang, out double rate, out int vote)
  366. {
  367. if (_sites == null)
  368. throw new Exception("Invalid Site value");
  369. double realRate = 0;
  370. //int votes;
  371. if (string.IsNullOrEmpty(mediaId) == false)
  372. GetRating(string.Format("SELECT SUM(votes) AS votes, SUM(rating) AS rating FROM Ratings2 WHERE mediaId='{0}' and productId='{1}' GROUP BY mediaId", newsId, productId), ref realRate, out vote);
  373. else
  374. GetRating(string.Format("SELECT SUM(votes) AS votes, SUM(rating) AS rating FROM Ratings2 WHERE newsId='{0}' AND mediaId IS NULL AND productId='{1}' GROUP BY newsId", newsId, productId), ref realRate, out vote);
  375. rate = realRate;
  376. //return realRate;
  377. }
  378. //Encours GetMostViewed
  379. /// <summary>
  380. /// donne la liste des plus vus pour ce serveur...
  381. /// </summary>
  382. /// <param name="lstId"></param>
  383. /// <param name="productId"></param>
  384. /// <returns></returns>
  385. public override string GetMostViewed(string lstId, string productId, string topicId, TimeSpan MaxAge, int MaxEntries)
  386. {
  387. throw new NotImplementedException();
  388. }
  389. /// <summary>
  390. /// Donne la listes des medias les plus votés
  391. /// </summary>
  392. /// <param name="lstId"></param>
  393. /// <param name="productId"></param>
  394. /// <returns></returns>
  395. public override string GetHeartRatedList(string lstId, string productId, string topicId, TimeSpan MaxAge, int MaxEntries, string lang )
  396. {
  397. string sqlLang;
  398. if (string.IsNullOrEmpty(lang))
  399. {
  400. sqlLang = "";
  401. }
  402. else
  403. {
  404. sqlLang = string.Format(" AND [lang] = '{0}' ", lang);
  405. }
  406. string query = string.Format(
  407. "SELECT lang, topicId, newsId, MAX([rating]/[votes]) AS averageRating, SUM([votes]) AS votes " +
  408. "FROM [Ratings2] WHERE NOT [mediaId] IS NULL AND [dateUpdated] > CONVERT(datetime, '{0}', 120) " +
  409. "AND [productId]='{1}' {2} GROUP BY lang, topicId, newsId ORDER BY [averageRating] DESC, [votes] DESC",
  410. DateTime.UtcNow.Subtract(MaxAge).ToString("yyyy-MM-dd"), productId, sqlLang );
  411. //en cours
  412. #if DEBUG && TRACE_REQUEST
  413. Process.Trace(query, "GetHeartRatedList", System.Diagnostics.EventLogEntryType.Information);
  414. #endif
  415. return TopicBuildRated(query, topicId, MaxEntries, new StorageServer(), false);
  416. }
  417. /// <summary>
  418. /// Donne la liste les Articles les mieux votés
  419. /// </summary>
  420. /// <param name="lstId"></param>
  421. /// <param name="productId"></param>
  422. /// <returns></returns>
  423. public override string GetArticleRatedList(string lstId, string productId, string topicId, TimeSpan MaxAge, int MaxEntries, string lang )
  424. {
  425. #if DEBUG && DEBUGRATEDLIST
  426. System.Diagnostics.Debugger.Break();
  427. #endif
  428. string sqlLang ;
  429. if (string.IsNullOrEmpty(lang))
  430. {
  431. sqlLang = "";
  432. }
  433. else
  434. {
  435. sqlLang = string.Format(" AND [lang] = '{0}' ", lang);
  436. }
  437. string query = string.Format(
  438. "SELECT lang, topicId, newsId, MAX([rating]/[votes]) AS averageRating, SUM([votes]) AS votes " +
  439. "FROM [Ratings2] WHERE [mediaId] IS NULL AND [dateUpdated] > CONVERT(datetime, '{0}', 120) " +
  440. "AND [productId]='{1}' {2} GROUP BY lang, topicId, newsId ORDER BY [averageRating] DESC, [votes] DESC"
  441. , DateTime.UtcNow.Subtract(MaxAge).ToString("yyyy-MM-dd"), productId ,sqlLang );
  442. //en cours
  443. #if DEBUG && TRACE_REQUEST
  444. Process.Trace(query, "GetArticleRatedList", System.Diagnostics.EventLogEntryType.Information);
  445. #endif
  446. return TopicBuildRated(query, topicId, MaxEntries, new StorageServer(), false);
  447. }
  448. private void getDegMinSec(string value, ref int deg ,ref int min , ref int sec)
  449. {
  450. float Valeur = value.toFloat(0f) ;
  451. deg = (int) Math.Truncate(Valeur);
  452. Valeur = (Valeur - (float) deg ) * 60f;
  453. min = (int)Math.Truncate(Valeur);
  454. Valeur = (Valeur - (float)min) * 60f;
  455. sec = (int)Math.Truncate(Valeur);
  456. }
  457. public override string GetAroundMe(string latitude, string longitude, string range ,int MaxEntries, string lang )
  458. {
  459. //ttot
  460. // Determination de la plage
  461. /* int degLat = 0;
  462. int minLat = 0;
  463. int secLat = 0;
  464. int degLong = 0;
  465. int minLong = 0;
  466. int secLong = 0;
  467. */
  468. string sWhere = " where ";
  469. string sWhereLatitudeSup ="" ;
  470. string sWhereLatitudeInf ="" ;
  471. string sWhereLongitudeSup ="" ;
  472. string sWhereLongitudeInf ="" ;
  473. Decimal oLat = latitude.toDecimal(0m);
  474. Decimal oLong = longitude.toDecimal(0m);
  475. Sexagesimal sRange = new Sexagesimal (range, true);
  476. Decimal Valeur = range.toDecimal(0m) / 111.195m;
  477. Decimal latitudeBornesup ;
  478. Decimal latitudeBorneInf ;
  479. latitudeBornesup = oLat + Valeur ;
  480. if( latitudeBornesup > 90m)
  481. {
  482. // il faut découper
  483. sWhereLatitudeSup = string.Format(" latitude < 90 or ( latitude > {0:0.########} and latitude <90 and longitude >-180 and longitude <180) ", 90m - (latitudeBornesup - 90m));
  484. }
  485. else
  486. {
  487. sWhereLatitudeSup = string.Format(" latitude < {0:0.########} ", latitudeBornesup.ToString("G",CultureInfo.InvariantCulture) );
  488. }
  489. latitudeBorneInf = oLat - Valeur ;
  490. if ( latitudeBorneInf <-90m)
  491. {
  492. // il faut découper
  493. sWhereLatitudeInf = string.Format (" latitude > -90 or ( latitude < {1} and latitude >-90 and longitude >-180 and longitude <180) ", -90m +(latitudeBornesup -90m) );
  494. }
  495. else
  496. {
  497. sWhereLatitudeInf = string.Format(" latitude > {0:0.########}", latitudeBorneInf.ToString("G", CultureInfo.InvariantCulture));
  498. }
  499. Decimal longitudeBordSup ;
  500. Decimal longitudeBordInf;
  501. longitudeBordSup = oLong + Valeur ;
  502. longitudeBordInf = oLong - Valeur ;
  503. if( longitudeBordSup > 180m )
  504. {
  505. // on a dépasser le bord de la terre on tombe... ha non c'est rond.
  506. sWhereLongitudeSup = string.Format(" (longitude < {0:0.########} or (longitude > -180 and longitude < {1:0.########} ) ", longitudeBordSup.ToString("G", CultureInfo.InvariantCulture), -180m + (longitudeBordSup - 180m));
  507. }
  508. else
  509. {
  510. sWhereLongitudeSup = string.Format(" longitude < {0:0.########} ", longitudeBordSup.ToString("G", CultureInfo.InvariantCulture));
  511. }
  512. if(longitudeBordInf <-180m )
  513. {
  514. sWhereLongitudeSup = string.Format(" (longitude > {0:0.########} or (longitude > {1:0.########} and longitude < 180 ) ", longitudeBordSup.ToString("G", CultureInfo.InvariantCulture), 180m - (longitudeBordInf - 180m));
  515. }
  516. else
  517. {
  518. sWhereLongitudeInf = string.Format(" longitude > {0:0.########}", longitudeBordInf.ToString("G", CultureInfo.InvariantCulture));
  519. }
  520. sWhere = string.Format ("{4} {0} and {1} and {2} and {3}" , sWhereLatitudeInf , sWhereLatitudeSup , sWhereLongitudeInf ,sWhereLongitudeSup , sWhere );
  521. string query = string.Format(
  522. "SELECT * from Localization {0} ", sWhere );
  523. if (!string.IsNullOrEmpty(lang))
  524. {
  525. query = string.Format("{0} and lang='{1}'", query, lang);
  526. }
  527. #if DEBUG && TRACEAROUND
  528. Process.Trace(query, System.Diagnostics.EventLogEntryType.Information);
  529. #endif
  530. return TopicBuildAround(query,new StorageServer() , MaxEntries );
  531. }
  532. /// <summary>
  533. /// Trace viewed.
  534. /// </summary>
  535. /// <param name="topicImplementation"></param>
  536. /// <param name="productId"></param>
  537. /// <param name="newsId"></param>
  538. /// <param name="mediaId"></param>
  539. /// <param name="device"></param>
  540. public override void InsertViewed(TopicImplementation topicImplementation, string productId, string newsId, string mediaId, string device)
  541. {
  542. #if DEBUG && DEBUGINSERT
  543. System.Diagnostics.Debugger.Break();
  544. #endif
  545. // Insert viewed
  546. foreach (var sqlProcessor in _sqlProcessorList)
  547. sqlProcessor.Add(new SqlNewsViewed(productId, topicImplementation.Id, newsId, mediaId, topicImplementation.Lang, device));
  548. }
  549. private XslCompiledTransform GetXsltCT(string path)
  550. {
  551. lock (_Xslt)
  552. {
  553. if (!_Xslt.ContainsKey(path))
  554. {
  555. XslCompiledTransform newX = new XslCompiledTransform(System.Diagnostics.Debugger.IsAttached);
  556. newX.Load(path);
  557. _Xslt.Add(path, newX);
  558. }
  559. }
  560. return (XslCompiledTransform)_Xslt[path];
  561. }
  562. private string GetMediaName(string href, TopicImplementation topic)
  563. {
  564. var pattern = topic["mediaNamePattern"];
  565. var regEx = new Regex((string.IsNullOrEmpty(pattern)) ? "(.)*" : pattern);
  566. return regEx.Match(Path.GetFileNameWithoutExtension(href)).ToString();
  567. }
  568. public void GetRating(string query, ref double rate, out int votes)
  569. {
  570. // Valeur par défaut
  571. votes = 0;
  572. // Ajout du rating
  573. foreach (var processor in _sqlProcessorList)
  574. using (var sqlRatingReader = new SqlDataAdapter(query, processor.ConnectionString))
  575. {
  576. using (var sqlRatingTable = new DataTable())
  577. {
  578. try
  579. {
  580. sqlRatingReader.Fill(sqlRatingTable);
  581. }
  582. catch
  583. {
  584. continue;
  585. }
  586. if (sqlRatingTable.Rows.Count == 0)
  587. votes = 0;
  588. else
  589. {
  590. votes = ((int)sqlRatingTable.Rows[0]["votes"] + 1);
  591. rate = ((double)sqlRatingTable.Rows[0]["rating"] + rate) / votes;
  592. }
  593. break;
  594. }
  595. }
  596. }
  597. private void MakeTopic(object stateInfo)
  598. {
  599. MakeTopic((TopicImplementation)((object[])stateInfo)[0], (bool)((object[])stateInfo)[1], (ManualResetEvent)((object[])stateInfo)[2]);
  600. }
  601. private void MakeTopic(TopicImplementation topic, bool refresh, ManualResetEvent doneEvent)
  602. {
  603. var storage = new StorageServer();
  604. #if DBG_PERFORMANCE_TRACE
  605. var timer = new System.Diagnostics.Stopwatch();
  606. // Démarage compteur
  607. timer.Start();
  608. if (_levelTrace.TraceTimeMakeTopic == true )
  609. {
  610. Process.Trace(string.Format(" Start Processing {0} at {1}", topic.Id, DateTime.Now), System.Diagnostics.EventLogEntryType.Information);
  611. }
  612. #endif
  613. try
  614. {
  615. // Traitement des différents type de topic
  616. switch (topic.Type)
  617. {
  618. case TopicImplementation.TopicType.heart:
  619. case TopicImplementation.TopicType.rated:
  620. // Construction du topic et stockage
  621. // TO DO a reprendre et a tester...
  622. XmlDocument topicRated = new XmlDocument();
  623. topicRated.LoadXml(TopicBuildRated(topic, storage, refresh));
  624. using (var storageTopicFile = storage.Store(Constants._storageTopicFormatName, Key, string.Format("{0}.xml", topic.Id)))
  625. topicRated.Save(storageTopicFile);
  626. break;
  627. case TopicImplementation.TopicType.videorama:
  628. case TopicImplementation.TopicType.standard:
  629. // Récupération du fichier index NewsML
  630. NewsML index = TopicLoadDocument(topic, storage);
  631. #if DBG_PERFORMANCE_TRACE
  632. if (_levelTrace.TraceTimeMakeTopic == true)
  633. {
  634. Process.Trace(string.Format("TopicLoadDocument for topicId '{0}' processed after {1} seconds.", topic.Id, timer.ElapsedMilliseconds / 1000), System.Diagnostics.EventLogEntryType.SuccessAudit);
  635. }
  636. #endif
  637. // Transformation du document et stockage
  638. if (index != null)
  639. {
  640. String topicContent = TopicBuildStandard(index, topic, storage, topic.MaxEntries, refresh);
  641. #if DBG_PERFORMANCE_TRACE
  642. if (_levelTrace.TraceTimeMakeTopic == true)
  643. {
  644. Process.Trace(string.Format("TopicBuildStandard for topicId '{0}' processed after {1} seconds.", topic.Id, timer.ElapsedMilliseconds / 1000), System.Diagnostics.EventLogEntryType.SuccessAudit);
  645. }
  646. #endif
  647. if (String.IsNullOrEmpty(topicContent) == false)
  648. {
  649. Stream output = storage.Store(Constants._storageTopicFormatName, Key, string.Format("{0}.xml", topic.Id));
  650. if (output != null)
  651. {
  652. TextWriter wr = new StreamWriter(output, Encoding.UTF8);
  653. wr.Write(topicContent);
  654. wr.Flush();
  655. output.Close();
  656. }
  657. }
  658. }
  659. break;
  660. case TopicImplementation.TopicType.buildedvideorama:
  661. // Construction du topic et stockage
  662. var topicVideorama = TopicBuildVideorama(topic, storage, refresh);
  663. using (var storageTopicFile = storage.Store(Constants._storageTopicFormatName, Key, string.Format("{0}.xml", topic.Id)))
  664. topicVideorama.Save(storageTopicFile);
  665. break;
  666. /* case TopicImplementation.TopicType.magazin:
  667. case TopicImplementation.TopicType.diaporama:
  668. var indexd = TopicLoadDocument(topic, storage);
  669. if (indexd != null)
  670. {
  671. String topicContent = TopicBuildMagazin(indexd, topic, storage, topic.MaxEntries, refresh,"");
  672. #if DBG_PERFORMANCE_TRACE
  673. if (_levelTrace.TraceTimeMakeTopic == true)
  674. {
  675. Process.Trace(string.Format("TopicBuildStandard for topicId '{0}' processed after {1} seconds.", topic.Id, timer.ElapsedMilliseconds / 1000), System.Diagnostics.EventLogEntryType.SuccessAudit);
  676. }
  677. #endif
  678. if (String.IsNullOrEmpty(topicContent) == false)
  679. {
  680. Stream output = storage.Store(Constants._storageTopicFormatName, Key, string.Format("{0}.xml", topic.Id));
  681. if (output != null)
  682. {
  683. TextWriter wr = new StreamWriter(output, Encoding.UTF8);
  684. wr.Write(topicContent);
  685. wr.Flush();
  686. output.Close();
  687. }
  688. }
  689. }
  690. break;*/
  691. case TopicImplementation.TopicType.alert:
  692. //TODO implementer fonction alert
  693. break;
  694. case TopicImplementation.TopicType.diaporama:
  695. case TopicImplementation.TopicType.magazin:
  696. if (topic.IsSubTopic() == false)
  697. TopicLoadTableAndDoneTopics(topic, storage);
  698. else
  699. {
  700. // cas de l'update d'un topic spé Ipad de merde...
  701. NewsML index1 = TopicLoadDocument(topic, storage);
  702. // Transformation du document et stockage
  703. if (index1 != null)
  704. {
  705. String topicContent = TopicBuildStandard(index1, topic, storage, topic.MaxEntries, refresh);
  706. if (String.IsNullOrEmpty(topicContent) == false)
  707. {
  708. Stream output = storage.Store(Constants._storageTopicFormatName, Key, string.Format("{0}.xml", topic.Id));
  709. if (output != null)
  710. {
  711. TextWriter wr = new StreamWriter(output, Encoding.UTF8);
  712. wr.Write(topicContent);
  713. wr.Flush();
  714. output.Close();
  715. }
  716. }
  717. }
  718. }
  719. break;
  720. }
  721. }
  722. catch (ThreadAbortException)
  723. {
  724. }
  725. catch (Exception e)
  726. {
  727. Process.Trace(string.Format("Can't process topic {0}", topic.Id), e.ToString(), System.Diagnostics.EventLogEntryType.Error);
  728. this.Set("Topic process error", MessageSection.Processing.ToString(), System.Diagnostics.EventLogEntryType.Warning);
  729. }
  730. finally
  731. {
  732. #if DBG_PERFORMANCE_TRACE
  733. timer.Stop();
  734. if (_levelTrace.TraceTimeMakeTopic == true)
  735. {
  736. Process.Trace(string.Format("Topic '{0}' processed in {1} seconds.", topic.Id, timer.ElapsedMilliseconds / 1000), System.Diagnostics.EventLogEntryType.SuccessAudit);
  737. }
  738. #endif
  739. }
  740. // Attente fin des traitements
  741. if (doneEvent != null)
  742. doneEvent.Set();
  743. }
  744. private void MakeTopicFromThread(object state)
  745. {
  746. while (true)
  747. try
  748. {
  749. // Traitement
  750. MakeTopic((TopicImplementation)state, false, null);
  751. // Pause dynamique
  752. Thread.Sleep(((TopicImplementation)state).DynamicDelay);
  753. }
  754. catch (ThreadAbortException)
  755. {
  756. }
  757. }
  758. private void NewsBuildHtml(XmlElement extensions, XmlDocument news, TopicImplementation topic, string uno, StorageServer storage)
  759. {
  760. // Stockage et transformation de la news au format html
  761. if (String.IsNullOrEmpty((string)topic["htmlModel"]) == false)
  762. {
  763. using (var storageHtmlNews = storage.Store(Constants._storageNewsFormatName, Key, string.Format("{0}.htm", uno)))
  764. {
  765. XslCompiledTransform transform = GetXsltCT((string)topic["htmlModel"]);
  766. XsltArgumentList arguments = new XsltArgumentList();
  767. arguments.AddParam("NewsExtension", String.Empty, extensions);
  768. arguments.AddParam("Version", string.Empty, Version);
  769. arguments.AddParam("ImageActive", string.Empty, Convert.ToBoolean ( ImageActive )) ;
  770. transform.Transform(news, arguments, storageHtmlNews);
  771. }
  772. }
  773. }
  774. /// <summary>
  775. ///
  776. /// </summary>
  777. /// <param name="doc">Noeud ou on rajoute l'attribut</param>
  778. /// <param name="name">Nom de l'attribut</param>
  779. /// <param name="value">Valeur </param>
  780. /// <returns></returns>
  781. public XmlAttribute createAttribute(XmlDocument doc, String name, String value)
  782. {
  783. XmlAttribute attr = doc.CreateAttribute(name);
  784. attr.Value = value;
  785. return attr;
  786. }
  787. void appendXmlDateAttribute(XmlElement element, XmlDocument doc, String name, DateTime? dt)
  788. {
  789. if (dt != null && dt.HasValue)
  790. {
  791. String dtStr = XmlConvert.ToString(dt.Value, XmlDateTimeSerializationMode.RoundtripKind);
  792. element.Attributes.Append(createAttribute(doc, name, dtStr));
  793. }
  794. }
  795. private XmlElement NewsExtendDocument(XmlDocument news, List<Media> photoList, List<Media> documentsList, TopicImplementation topic, string uno, StorageServer storage, int XsltVersion)
  796. {
  797. XmlElement NewsExtension;
  798. Int16 pos = 0;
  799. Int16 previewB = 0;
  800. NewsExtension = news.CreateElement("NewsExtension");
  801. //NewsExtension.Attributes.Append(createAttribute(news, "id", topic.Id));
  802. if (topic.Id.Contains("__"))
  803. NewsExtension.Attributes.Append(createAttribute(news, "id", string.Format("{0:X}", topic.Id.Substring(topic.Id.IndexOf("__") + 2).MyGetHashCode())));
  804. else
  805. NewsExtension.Attributes.Append(createAttribute(news, "id", string.Format("{0:X}",topic.Id.MyGetHashCode())));
  806. //BUG le bon id commence par topic.Id.Substring(topic.Id.IndexOf("__")+2).MyGetHashCode()
  807. NewsExtension.Attributes.Append(createAttribute(news, "uno", uno));
  808. if (topic.UseBase64 == false)
  809. {
  810. NewsExtension.Attributes.Append(createAttribute(news, "DontUseDataUrl", "1"));
  811. }
  812. //NewsExtension.Attributes.Append(createAttribute(news, "Version", XsltVersion.ToString() ));
  813. // Traitement des dates
  814. if (XsltVersion == 1)
  815. {
  816. // on reste avec l'ancien traitement on ne sait jamais
  817. appendXmlDateAttribute(NewsExtension, news, "dateAndTime", news.DocumentElement.FindDate("/NewsML/NewsEnvelope/DateAndTime"));
  818. appendXmlDateAttribute(NewsExtension, news, "firstCreated", news.DocumentElement.FindDate("/NewsML/NewsItem/NewsManagement/FirstCreated"));
  819. appendXmlDateAttribute(NewsExtension, news, "thisRevisionCreated", news.DocumentElement.FindDate("/NewsML/NewsItem/NewsManagement/ThisRevisionCreated"));
  820. }
  821. else
  822. {
  823. NewsExtension.Attributes.Append(createAttribute(news, "dateAndTime", news.DocumentElement.FindDateToXmlUtcString("/NewsML/NewsEnvelope/DateAndTime")));
  824. NewsExtension.Attributes.Append(createAttribute(news, "firstCreated", news.DocumentElement.FindDateToXmlUtcString("/NewsML/NewsItem/NewsManagement/FirstCreated")));
  825. NewsExtension.Attributes.Append(createAttribute(news, "thisRevisionCreated", news.DocumentElement.FindDateToXmlUtcString("/NewsML/NewsItem/NewsManagement/ThisRevisionCreated")));
  826. }
  827. // Traitement des photos
  828. XmlElement ContainerNewsComponent = null ;
  829. string mediaCurrentId ="";
  830. Boolean newMediaId = false;
  831. foreach (Media media in photoList)
  832. {
  833. //XmlElement NewsComponent1 = news.CreateElement("NewsComponent");
  834. if (mediaCurrentId != media.Duid)
  835. {
  836. newMediaId = true;
  837. mediaCurrentId = media.Duid;
  838. }
  839. if (XsltVersion > 1 && newMediaId == true )
  840. {
  841. ContainerNewsComponent = news.CreateElement("NewsComponent");
  842. NewsExtension.AppendChild(ContainerNewsComponent);
  843. pos = 0; previewB = 0;
  844. newMediaId = false;
  845. }
  846. XmlElement NewsComponent;
  847. NewsComponent = news.CreateElement("NewsComponent");
  848. if (XsltVersion > 1)
  849. {
  850. ContainerNewsComponent.AppendChild(NewsComponent);
  851. }
  852. else
  853. {
  854. NewsExtension.AppendChild(NewsComponent);
  855. }
  856. //favori : Ici sont passées les Parametres...
  857. //NewsExtension.Attributes.Append(createAttribute(news, "uno", uno));
  858. if (XsltVersion == 1)
  859. {
  860. NewsComponent.Attributes.Append(createAttribute(news, "duid", media.Duid));
  861. NewsComponent.Attributes.Append(createAttribute(news, "hduid", string.Format("#{0}", media.Duid)));
  862. }
  863. else
  864. {
  865. if (pos == 0)
  866. {
  867. ContainerNewsComponent.Attributes.Append(createAttribute(news, "duid", media.Duid));
  868. ContainerNewsComponent.Attributes.Append(createAttribute(news, "huid", string.Format("#{0}", media.AbsoluteWebPath)));
  869. }
  870. pos += 1;
  871. }
  872. // insertion de la preview
  873. if (media.Role.Equals( _PreviewRole, StringComparison.InvariantCultureIgnoreCase ))
  874. {
  875. ContainerNewsComponent.Attributes.Append(createAttribute(news, "preview", string.Format("{0}", media.AbsoluteWebPath)));
  876. previewB += 1;
  877. }
  878. NewsComponent.Attributes.Append(createAttribute(news, "role", media.Role));
  879. // est-ce une video
  880. Boolean video= false;
  881. if (media.Role.ToLower() == "iformat" || media.Role.ToLower() == "video" || media.AbsoluteWebPath.EndsWith("mp4"))
  882. {
  883. NewsComponent.Attributes.Append(createAttribute(news, "video", "1"));
  884. video = true;
  885. }
  886. else
  887. {
  888. NewsComponent.Attributes.Append(createAttribute(news, "video", "0"));
  889. video = false;
  890. }
  891. if (topic.UseBase64 == true )
  892. {
  893. NewsComponent.Attributes.Append(createAttribute(news, "href", string.Format("{0}/{1}/{2}/{3}/{4}",
  894. topic.ProductServiceName,
  895. _storagePhotosFormatName,
  896. Key,
  897. Storage.StorageServer.GetHashFolder(media.Name),
  898. media.Name.UrlEncode()
  899. )
  900. ));
  901. }
  902. else
  903. {
  904. NewsComponent.Attributes.Append(createAttribute(news, "href", media.AbsoluteWebPath));
  905. }
  906. NewsComponent.Attributes.Append(createAttribute(news, "width", media.Width));
  907. NewsComponent.Attributes.Append(createAttribute(news, "height", media.Height));
  908. // Ecriture fichier encodé
  909. if (topic.UseBase64 && video == false)
  910. {
  911. if (storage.Exists(_storagePhotosFormatName, Key, media.Name))
  912. {
  913. using (var file = storage.Restore("Photos", Key, media.Name, true))
  914. {
  915. NewsComponent.InnerText = StorageServer.FileToBase64(file);
  916. }
  917. }
  918. }
  919. else
  920. {
  921. // NewsComponent.InnerText = media.AbsoluteWebPath;
  922. }
  923. }
  924. // on va maintenant prendre la liste des documents
  925. if (XsltVersion > 1)
  926. {
  927. XmlElement NewsComponent1 = news.CreateElement("NewsComponent");
  928. ((XmlElement)NewsComponent1).SetAttribute("role", "document");
  929. foreach (Media media in documentsList)
  930. {
  931. XmlElement docNewsComponent = news.CreateElement("NewsComponent");
  932. // NewsExtension.AppendChild(docNewsComponent);
  933. docNewsComponent.Attributes.Append(createAttribute(news, "duid", media.Duid));
  934. docNewsComponent.Attributes.Append(createAttribute(news, "role", "document"));
  935. docNewsComponent.Attributes.Append(createAttribute(news, "href", media.AbsoluteWebPath));
  936. NewsComponent1.AppendChild(docNewsComponent);
  937. }
  938. NewsExtension.AppendChild(NewsComponent1);
  939. }
  940. /* Process.Trace(" News Extension ",
  941. string.Format("version {0} ", XsltVersion),
  942. System.Diagnostics.EventLogEntryType.Information);
  943. */
  944. return NewsExtension;
  945. }
  946. private News NewsLoadDocument(NewsComponent newsComponent, TopicImplementation topic, StorageServer storage, DateTime dateReference)
  947. {
  948. return NewsLoadDocument(((NewsItemRef)newsComponent.Items[0]).NewsItem, topic, storage, dateReference);
  949. }
  950. private News NewsLoadDocument(String newsItemRef, TopicImplementation topic, StorageServer storage, DateTime dateReference)
  951. {
  952. String fileName = Path.GetFileName(newsItemRef);
  953. StorageFileInfo storedNewsInfo = storage.Info(Constants._storageNewsFormatName, Key, fileName);
  954. News news = new News(Path.GetFileNameWithoutExtension(fileName));
  955. Boolean srcNewsExists = false;
  956. String livraisonNewsPath = string.Empty;
  957. DateTime? ThisRevisionCreated;
  958. news.State = News.NewsState.New;
  959. try
  960. {
  961. // Recherche de la news
  962. foreach (var directoryName in topic.Folders)
  963. {
  964. livraisonNewsPath = Path.Combine(directoryName, newsItemRef);
  965. srcNewsExists = StorageServer.FileExists(livraisonNewsPath);
  966. if (srcNewsExists)
  967. {
  968. news.LastModificationDate = File.GetLastWriteTime(livraisonNewsPath);
  969. break;
  970. }
  971. }
  972. // Détermination de l'état de la news
  973. // News locale présente
  974. if (srcNewsExists)
  975. {
  976. // Ancienne news stockée existe ?
  977. using (var localNewsFile = StorageServer.FileOpen(livraisonNewsPath))
  978. {
  979. if (storedNewsInfo == null)
  980. {
  981. // Nouvelle news
  982. news.Document.Load(localNewsFile);
  983. news.Path = livraisonNewsPath;
  984. news.State = News.NewsState.New;
  985. #if SERVICE
  986. lock (GBLock)
  987. {
  988. AFP.IPhone.Plugins.GetCourseId.GetRefIdSoapClient Client = new AFP.IPhone.Plugins.GetCourseId.GetRefIdSoapClient();
  989. Client.ClientCredentials.Windows.AllowNtlm = true;
  990. news.Uid = Client.GetCourseId(topic.Id, news.Uno);
  991. };
  992. #endif
  993. }
  994. else
  995. {
  996. // La news a-t-elle été modifiée ? et la feuille de style a elle été modifiée?
  997. if (storedNewsInfo.LastModified >= news.LastModificationDate && topic.XsltDate <= storedNewsInfo.LastModified)
  998. {
  999. // La news est ancienne
  1000. news.Document.Load(storedNewsInfo.Path);
  1001. news.State = News.NewsState.Stored;
  1002. try
  1003. {
  1004. news.Uid = Convert.ToInt64(news.Document.SelectSingleNode("NewsML").Attributes["absoluteindex"].Value);
  1005. }
  1006. finally
  1007. {
  1008. }
  1009. }
  1010. else
  1011. {
  1012. // Nouvelle version de la news
  1013. news.Document.Load(localNewsFile);
  1014. news.Path = livraisonNewsPath;
  1015. #if SERVICE
  1016. lock (GBLock)
  1017. {
  1018. /*TO DO appel au service WEB !!! */
  1019. // TO DO a voir à factoriser le client
  1020. AFP.IPhone.Plugins.GetCourseId.GetRefIdSoapClient Client = new AFP.IPhone.Plugins.GetCourseId.GetRefIdSoapClient();
  1021. Client.ClientCredentials.Windows.AllowNtlm = true;
  1022. news.Uid = Client.GetCourseId(topic.Id, news.Uno);
  1023. };
  1024. #endif
  1025. news.State = News.NewsState.New;
  1026. }
  1027. }
  1028. }
  1029. // La news est ancienne
  1030. }
  1031. else
  1032. {
  1033. if (storedNewsInfo == null)
  1034. {
  1035. String Folders = "";
  1036. foreach (string cFolder in topic.Folders)
  1037. {
  1038. Folders = string.Format("{0} ; {1}", cFolder, Folders);
  1039. }
  1040. Process.Trace("Bug Store", string.Format("NO DOCUMENT FOUND {0}-{1}. Folder : {2}", topic.Id, newsItemRef, Folders), System.Diagnostics.EventLogEntryType.Information);
  1041. // La news n'est pas archivée
  1042. news.State = News.NewsState.Invalid;
  1043. }
  1044. else
  1045. {
  1046. //Process.Trace("Bug Store", string.Format("REUSE STORED DOCUMENT {0}-{1}", topic.Id, newsItemRef), System.Diagnostics.EventLogEntryType.Information);
  1047. // La news est archivée
  1048. if (topic.XsltDate <= storedNewsInfo.LastModified)
  1049. {
  1050. news.Document.Load(storedNewsInfo.Path);
  1051. try
  1052. {
  1053. news.Uid = Convert.ToInt64(news.Document.SelectSingleNode("NewsML").Attributes["absoluteindex"].Value);
  1054. }
  1055. finally
  1056. {
  1057. }
  1058. news.State = News.NewsState.Stored;
  1059. }
  1060. else
  1061. {
  1062. // la feuille de style a été modifiée on force le recalcul
  1063. news.Document.Load(storedNewsInfo.Path);
  1064. news.State = News.NewsState.New;
  1065. }
  1066. }
  1067. }
  1068. // Vérification date de validité et transformation éventuelle
  1069. if (news.State != News.NewsState.Invalid)
  1070. {
  1071. if (string.IsNullOrEmpty(topic.NewsXslt) == false)
  1072. {
  1073. using (var newsStream = new MemoryStream())
  1074. {
  1075. // Transformation de la news
  1076. GetXsltCT(topic.NewsXslt).Transform(news.Document, null, newsStream);
  1077. // Récupération
  1078. newsStream.Position = 0;
  1079. news.Document.Load(newsStream);
  1080. }
  1081. }
  1082. //ENCOURS si message alert on la prépare
  1083. if (topic.CanBeAlert)

Large files files are truncated, but you can click here to view the full file