PageRenderTime 83ms CodeModel.GetById 55ms app.highlight 24ms RepoModel.GetById 0ms app.codeStats 1ms

/src/yolk-syndication.ads

http://github.com/ThomasLocke/yolk
Ada | 554 lines | 328 code | 59 blank | 167 comment | 0 complexity | 971f044abf7ee74ed08d97050bad8002 MD5 | raw file
  1-------------------------------------------------------------------------------
  2--                                                                           --
  3--                   Copyright (C) 2010-, Thomas Løcke                   --
  4--                                                                           --
  5--  This library is free software;  you can redistribute it and/or modify    --
  6--  it under terms of the  GNU General Public License  as published by the   --
  7--  Free Software  Foundation;  either version 3,  or (at your  option) any  --
  8--  later version. This library is distributed in the hope that it will be   --
  9--  useful, but WITHOUT ANY WARRANTY;  without even the implied warranty of  --
 10--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     --
 11--                                                                           --
 12--  As a special exception under Section 7 of GPL version 3, you are         --
 13--  granted additional permissions described in the GCC Runtime Library      --
 14--  Exception, version 3.1, as published by the Free Software Foundation.    --
 15--                                                                           --
 16--  You should have received a copy of the GNU General Public License and    --
 17--  a copy of the GCC Runtime Library Exception along with this program;     --
 18--  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
 19--  <http://www.gnu.org/licenses/>.                                          --
 20--                                                                           --
 21-------------------------------------------------------------------------------
 22
 23with Ada.Calendar;
 24with Ada.Characters.Latin_1;
 25private with Ada.Containers.Doubly_Linked_Lists;
 26private with Ada.Strings.Unbounded;
 27with DOM.Core;
 28
 29package Yolk.Syndication is
 30
 31   Not_Valid_XML : exception;
 32   --  Is raised when some Xhtml content is not valid XML. This exception
 33   --  can be raised by all procedures that can take Xhtml as content.
 34
 35   type Content_Kinds is (Text, Html, Xhtml, InlineOther, OutOfLineOther);
 36   --  This type is common for a lot of Atom feed XML elements. It identifies
 37   --  the kind of data found in the element.
 38   --  Text:
 39   --    The content of the Text construct MUST NOT contain child elements.
 40   --    Such text is intended to be presented to humans in a readable fashion.
 41   --    Thus, Atom Processors MAY collapse white space (including line breaks)
 42   --    and display the text using typographic techniques such as
 43   --    justification and proportional fonts.
 44   --  Html:
 45   --    The content of the Text construct MUST NOT contain child elements and
 46   --    SHOULD be suitable for handling as HTML [HTML]. Any markup within is
 47   --    escaped; for example, "<br>" as "&lt;br>". Atom Processors that
 48   --    display such content MAY use that markup to aid in its display.
 49   --  Xhtml:
 50   --    The content SHOULD be suitable for handling as XHTML. The content is
 51   --    wrapped in a <div> element. The XHTML <div> element itself MUST NOT be
 52   --    considered part of the content. Atom Processors that display the
 53   --    content MAY use the markup to aid in displaying it. The escaped
 54   --    versions of characters such as "&" and ">" represent those characters,
 55   --    not markup.
 56   --  InlineOther:
 57   --    For inline content that is not Text, Html or Xhtml.
 58   --  OutOfLineOther:
 59   --    For content that is fetched from a given IRI reference.
 60
 61   subtype Text_Kinds is Content_Kinds range Text .. Xhtml;
 62   --  Text:
 63   --    The content of the Text construct MUST NOT contain child elements.
 64   --    Such text is intended to be presented to humans in a readable fashion.
 65   --    Thus, Atom Processors MAY collapse white space (including line breaks)
 66   --    and display the text using typographic techniques such as
 67   --    justification and proportional fonts.
 68   --  Html:
 69   --    The content of the Text construct MUST NOT contain child elements and
 70   --    SHOULD be suitable for handling as HTML [HTML]. Any markup within is
 71   --    escaped; for example, "<br>" as "&lt;br>". Atom Processors that
 72   --    display such content MAY use that markup to aid in its display.
 73   --  Xhtml:
 74   --    The content SHOULD be suitable for handling as XHTML. The content is
 75   --    wrapped in a <div> element. The XHTML <div> element itself MUST NOT be
 76   --    considered part of the content. Atom Processors that display the
 77   --    content MAY use the markup to aid in displaying it. The escaped
 78   --    versions of characters such as "&" and ">" represent those characters,
 79   --    not markup.
 80
 81   type Relation_Kinds is (Alternate, Related, Self, Enclosure, Via);
 82   --  There are five values for the Registry of Link Relations:
 83   --
 84   --    Alternate:
 85   --       Signifies that the IRI in the value of the href attribute
 86   --       identifies an alternate version of the resource described by the
 87   --       containing element.
 88   --    Related:
 89   --       Signifies that the IRI in the value of the href attribute
 90   --       identifies a resource related to the resource described by the
 91   --       containing element. For example, the feed for a site that
 92   --       discusses the performance of the search engine at
 93   --       "http://search.example.com" might contain, as a child of atom :
 94   --       feed : <link rel="related" href="http://search.example.com/"/>
 95   --       An identical link might appear as a child of any atom:entry whose
 96   --       content contains a discussion of that same search engine.
 97   --    Self:
 98   --       Signifies that the IRI in the value of the href attribute
 99   --       identifies a resource equivalent to the containing element.
100   --    Enclosure:
101   --       Signifies that the IRI in the value of the href attribute
102   --       identifies a related resource that is potentially large in size and
103   --       might require special handling. For atom : link elements with
104   --       rel = "enclosure", the length attribute SHOULD be provided.
105   --    Via:
106   --       Signifies that the IRI in the value of the href attribute
107   --       identifies a resource that is the source of the information
108   --       provided in the containing element.
109
110   type Atom_Entry is private;
111   --  The atom:entry object. This type is _not_ thread safe.
112
113   type Atom_Entry_Source is private;
114   --  The atom:source object. This type is _not_ thread safe.
115
116   type Atom_Feed is limited private;
117   --  The atom:feed object. This type is thread safe.
118
119   Q : Character renames Ada.Characters.Latin_1.Quotation;
120
121   None    : constant String := "";
122   PI      : constant String := "<?xml version="
123     & Q & "1.0" & Q & " encoding=" & Q & "utf-8" & Q & "?>"
124     & Ada.Characters.Latin_1.LF;
125   XHTMLNS : constant String := "http://www.w3.org/1999/xhtml";
126   XMLNS   : constant String := "http://www.w3.org/2005/Atom";
127   DIVNS   : constant String := "xmlns=" & Q & XHTMLNS & Q;
128
129   function New_Atom_Entry
130     (Base_URI : in String := None;
131      Language : in String := None)
132      return Atom_Entry;
133   --  Initialize an Atom entry object, as per the Atom specification RFC4287:
134   --    http://tools.ietf.org/html/rfc4287
135   --
136   --  NOTE: All data is expected to be UTF-8 encoded. Yolk.Syndication does
137   --  not do any kind of encoding.
138   --
139   --  Base_URI:
140   --    Establishes a base URI for resolving relative references in the entry.
141   --    Is overruled by Base_URI parameters for individual entry elements.
142   --  Language:
143   --    Indicates the natural language for the atom:entry element and its
144   --    descendents.
145
146   function New_Atom_Entry_Source
147     (Base_URI : in String := None;
148      Language : in String := None)
149      return Atom_Entry_Source;
150   --  Initialize an Atom source object. This is for those occassions where
151   --  the entry is copied from one feed into another. The atom:source
152   --  may contain all the metadata from the originating feed.
153   --
154   --  NOTE: All data is expected to be UTF-8 encoded. Yolk.Syndication does
155   --  not do any kind of encoding.
156   --
157   --  Base_URI:
158   --    Establishes a base URI for resolving relative references in the entry.
159   --    Is overruled by Base_URI parameters for individual entry elements.
160   --  Language:
161   --    Indicates the natural language for the atom:entry element and its
162   --    descendents.
163
164   function New_Atom_Feed
165     (Base_URI    : in String := None;
166      Language    : in String := None;
167      Max_Age     : in Duration := 5_616_000.0;
168      Max_Entries : in Positive := 100;
169      Min_Entries : in Positive := 10)
170      return Atom_Feed;
171   --  Initialize an Atom object, as per the Atom specification RFC4287:
172   --    http://tools.ietf.org/html/rfc4287
173   --
174   --  NOTE: All data is expected to be UTF-8 encoded. Yolk.Syndication does
175   --  not do any kind of encoding.
176   --
177   --  Base_URI:
178   --    Establishes a base URI for resolving relative references in the feed.
179   --    Is overruled by Base_URI parameters for individual feed child
180   --    elements.
181   --  Language:
182   --    Indicates the natural language for the atom:feed element and its
183   --    descendents.
184   --  Max_Age:
185   --    If an entries Updated value is older than Max_Age, and there are more
186   --    than Min_Entries in the list, then the entry is deleted. This is done
187   --    in the Add_Entry procedure. Max_Age is given in seconds.
188   --  Max_Entries:
189   --    This is the max amount of entries we keep in the list. If there are
190   --    more than Max_Entries entries in the list, then the oldest entries are
191   --    deleted until the list is Max_Entries long.
192   --  Min_Entries:
193   --    The is the minimum amount of entries that must be in the list before
194   --    we bother with deleting old entries. If there are less than
195   --    Min_Entries in the list, then even a 100 year old entry is kept.
196
197private
198
199   use Ada.Containers;
200   use Ada.Strings.Unbounded;
201
202   function U
203     (S : in String)
204      return Unbounded_String
205      renames To_Unbounded_String;
206
207   type Atom_Common is
208      record
209         Base_URI : Unbounded_String;
210         Language : Unbounded_String;
211      end record;
212
213   type Atom_Category is
214      record
215         Common : Atom_Common;
216         Label  : Unbounded_String;
217         Scheme : Unbounded_String;
218         Term   : Unbounded_String;
219      end record;
220
221   type Atom_Date is
222      record
223         Common     : Atom_Common;
224         Is_Set     : Boolean;
225         Time_Stamp : Ada.Calendar.Time;
226      end record;
227
228   type Atom_Entry_Content is
229      record
230         Common       : Atom_Common;
231         Content      : Unbounded_String;
232         Content_Kind : Content_Kinds;
233         Mime_Type    : Unbounded_String;
234         Source       : Unbounded_String;
235      end record;
236
237   type Atom_Generator is
238      record
239         Agent   : Unbounded_String;
240         Common  : Atom_Common;
241         URI     : Unbounded_String;
242         Version : Unbounded_String;
243      end record;
244
245   type Atom_Icon is
246      record
247         Common : Atom_Common;
248         URI    : Unbounded_String;
249      end record;
250
251   type Atom_Id is
252      record
253         Common : Atom_Common;
254         URI    : Unbounded_String;
255      end record;
256
257   type Atom_Link is
258      record
259         Common    : Atom_Common;
260         Href      : Unbounded_String;
261         Hreflang  : Unbounded_String;
262         Length    : Natural;
263         Mime_Type : Unbounded_String;
264         Rel       : Relation_Kinds;
265         Title     : Unbounded_String;
266      end record;
267
268   type Atom_Logo is
269      record
270         Common : Atom_Common;
271         URI    : Unbounded_String;
272      end record;
273
274   type Atom_Person is
275      record
276         Common : Atom_Common;
277         Email  : Unbounded_String;
278         Name   : Unbounded_String;
279         URI    : Unbounded_String;
280      end record;
281
282   type Atom_Text is
283      record
284         Common       : Atom_Common;
285         Text_Content : Unbounded_String;
286         Text_Kind    : Text_Kinds;
287      end record;
288
289   package Category_List is new Doubly_Linked_Lists (Atom_Category);
290   package Link_List is new Doubly_Linked_Lists (Atom_Link);
291   package Person_List is new Doubly_Linked_Lists (Atom_Person);
292
293   type Atom_Entry_Source is
294      record
295         Authors      : Person_List.List;
296         Categories   : Category_List.List;
297         Common       : Atom_Common;
298         Contributors : Person_List.List;
299         Generator    : Atom_Generator;
300         Icon         : Atom_Icon;
301         Id           : Atom_Id;
302         Links        : Link_List.List;
303         Logo         : Atom_Logo;
304         Rights       : Atom_Text;
305         Subtitle     : Atom_Text;
306         Title        : Atom_Text;
307         Updated      : Atom_Date;
308      end record;
309
310   Null_Atom_Entry_Source : constant Atom_Entry_Source
311     := (Authors      => Person_List.Empty_List,
312         Categories   => Category_List.Empty_List,
313         Common       => Atom_Common'(Base_URI => Null_Unbounded_String,
314                                      Language => Null_Unbounded_String),
315         Contributors => Person_List.Empty_List,
316         Generator    =>
317           Atom_Generator'(Agent   => Null_Unbounded_String,
318                           Common  =>
319                             Atom_Common'(Base_URI => Null_Unbounded_String,
320                                          Language => Null_Unbounded_String),
321                           URI     => Null_Unbounded_String,
322                           Version => Null_Unbounded_String),
323         Icon         =>
324           Atom_Icon'(Common =>
325                        Atom_Common'(Base_URI => Null_Unbounded_String,
326                                     Language => Null_Unbounded_String),
327                      URI    => Null_Unbounded_String),
328         Id           => Atom_Id'(Common =>
329                                    Atom_Common'(Base_URI =>
330                                                   Null_Unbounded_String,
331                                                 Language =>
332                                                   Null_Unbounded_String),
333                                  URI    => Null_Unbounded_String),
334         Links        => Link_List.Empty_List,
335         Logo         =>  Atom_Logo'(Common => Atom_Common'
336                                       (Base_URI => Null_Unbounded_String,
337                                        Language => Null_Unbounded_String),
338                                     URI    => Null_Unbounded_String),
339         Rights       => Atom_Text'(Common       => Atom_Common'
340                                      (Base_URI => Null_Unbounded_String,
341                                       Language => Null_Unbounded_String),
342                                    Text_Content => Null_Unbounded_String,
343                                    Text_Kind    => Text),
344         Subtitle     => Atom_Text'(Common       => Atom_Common'
345                                      (Base_URI => Null_Unbounded_String,
346                                       Language => Null_Unbounded_String),
347                                    Text_Content => Null_Unbounded_String,
348                                    Text_Kind    => Text),
349         Title        => Atom_Text'(Common       => Atom_Common'
350                                      (Base_URI => Null_Unbounded_String,
351                                       Language => Null_Unbounded_String),
352                                    Text_Content => Null_Unbounded_String,
353                                    Text_Kind    => Text),
354         Updated      => Atom_Date'(Common     => Atom_Common'
355                                      (Base_URI => Null_Unbounded_String,
356                                       Language => Null_Unbounded_String),
357                                    Is_Set     => False,
358                                    Time_Stamp => Ada.Calendar.Clock));
359
360   type Atom_Entry is
361      record
362         Authors      : Person_List.List;
363         Categories   : Category_List.List;
364         Common       : Atom_Common;
365         Content      : Atom_Entry_Content;
366         Contributors : Person_List.List;
367         Id           : Atom_Id;
368         Links        : Link_List.List;
369         Published    : Atom_Date;
370         Rights       : Atom_Text;
371         Source       : Atom_Entry_Source;
372         Summary      : Atom_Text;
373         Title        : Atom_Text;
374         Updated      : Atom_Date;
375      end record;
376
377   Null_Atom_Entry : constant Atom_Entry
378     := (Authors      => Person_List.Empty_List,
379         Categories   => Category_List.Empty_List,
380         Common       => Atom_Common'(Base_URI => Null_Unbounded_String,
381                                      Language => Null_Unbounded_String),
382         Content      =>
383           Atom_Entry_Content'(Common       =>
384                                 Atom_Common'(Base_URI =>
385                                                Null_Unbounded_String,
386                                              Language =>
387                                                Null_Unbounded_String),
388                               Content      => Null_Unbounded_String,
389                               Content_Kind => Text,
390                               Mime_Type    => Null_Unbounded_String,
391                               Source       => Null_Unbounded_String),
392         Contributors => Person_List.Empty_List,
393         Id           => Atom_Id'(Common =>
394                                    Atom_Common'(Base_URI =>
395                                                   Null_Unbounded_String,
396                                                 Language =>
397                                                   Null_Unbounded_String),
398                                  URI    => Null_Unbounded_String),
399         Links        => Link_List.Empty_List,
400         Published    => Atom_Date'(Common     =>
401                                      Atom_Common'(Base_URI =>
402                                                     Null_Unbounded_String,
403                                                   Language =>
404                                                     Null_Unbounded_String),
405                                    Is_Set     => False,
406                                    Time_Stamp => Ada.Calendar.Clock),
407         Rights       => Atom_Text'(Common       =>
408                                      Atom_Common'(Base_URI =>
409                                                     Null_Unbounded_String,
410                                                   Language =>
411                                                     Null_Unbounded_String),
412                                    Text_Content => Null_Unbounded_String,
413                                    Text_Kind    => Text),
414         Source       => Null_Atom_Entry_Source,
415         Summary      => Atom_Text'(Common       =>
416                                      Atom_Common'(Base_URI =>
417                                                     Null_Unbounded_String,
418                                                   Language =>
419                                                     Null_Unbounded_String),
420                                    Text_Content => Null_Unbounded_String,
421                                    Text_Kind    => Text),
422         Title        => Atom_Text'(Common       =>
423                                      Atom_Common'(Base_URI =>
424                                                     Null_Unbounded_String,
425                                                   Language =>
426                                                     Null_Unbounded_String),
427                                    Text_Content => Null_Unbounded_String,
428                                    Text_Kind    => Text),
429         Updated      => Atom_Date'(Common     =>
430                                      Atom_Common'(Base_URI =>
431                                                     Null_Unbounded_String,
432                                                   Language =>
433                                                     Null_Unbounded_String),
434                                    Is_Set     => False,
435                                    Time_Stamp => Ada.Calendar.Clock));
436
437   function Equal_Entry
438     (Left, Right : in Atom_Entry)
439      return Boolean;
440
441   package Entry_List is new Doubly_Linked_Lists (Atom_Entry, Equal_Entry);
442
443   protected type Protected_Atom_Feed is
444      procedure Add_Author
445        (Value : in Atom_Person);
446      --  ????
447
448      procedure Add_Category
449        (Value : in Atom_Category);
450      --  ????
451
452      procedure Add_Contributor
453        (Value : in Atom_Person);
454      --  ????
455
456      procedure Add_Entry
457        (Value : in Yolk.Syndication.Atom_Entry);
458      --  ????
459
460      procedure Add_Link
461        (Value : in Atom_Link);
462      --  ????
463
464      function Amount_Of_Entries return Natural;
465      --  ????
466
467      procedure Clear_Entry_List;
468      --  ????
469
470      procedure Delete_Entry
471        (Id : in String);
472      --  ????
473
474      function Get_DOM return DOM.Core.Document;
475      --  ????
476
477      function Get_String
478        (Pretty_Print : in Boolean := False)
479         return String;
480      --  ????
481
482      procedure Set_Common
483        (Value : in Atom_Common);
484      --  ????
485
486      procedure Set_Generator
487        (Value : in Atom_Generator);
488      --  ????
489
490      procedure Set_Icon
491        (Value : in Atom_Icon);
492      --  ????
493
494      procedure Set_Id
495        (Value : in Atom_Id);
496      --  ????
497
498      procedure Set_Logo
499        (Value : in Atom_Logo);
500      --  ????
501
502      procedure Set_Max_Age
503        (Value : in Duration);
504      --  ????
505
506      procedure Set_Max_Entries
507        (Value : in Positive);
508      --  ????
509
510      procedure Set_Min_Entries
511        (Value : in Positive);
512      --  ????
513
514      procedure Set_Rights
515        (Value : in Atom_Text);
516      --  ????
517
518      procedure Set_Subtitle
519        (Value : in Atom_Text);
520      --  ????
521
522      procedure Set_Title
523        (Value : in Atom_Text);
524      --  ????
525
526      procedure Set_Updated_Time
527        (Value : in Atom_Date);
528      --  ????
529   private
530      Authors       : Person_List.List;
531      Categories    : Category_List.List;
532      Common        : Atom_Common;
533      Contributors  : Person_List.List;
534      Entries       : Entry_List.List;
535      Generator     : Atom_Generator;
536      Icon          : Atom_Icon;
537      Id            : Atom_Id;
538      Links         : Link_List.List;
539      Logo          : Atom_Logo;
540      Max_Entry_Age : Duration;
541      Max_Entries   : Positive;
542      Min_Entries   : Positive;
543      Rights        : Atom_Text;
544      Subtitle      : Atom_Text;
545      Title         : Atom_Text;
546      Updated       : Atom_Date;
547   end Protected_Atom_Feed;
548
549   type Atom_Feed is
550      record
551         PAF : Protected_Atom_Feed;
552      end record;
553
554end Yolk.Syndication;