browserutilities/feedsengine/FeedsServer/FeedHandler/src/AtomFeedParser.cpp
changeset 0 dd21522fd290
child 36 0ed94ceaa377
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  RSS parser
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "FeedAttributes.h"
       
    20 #include "FeedParserObserver.h"
       
    21 #include "LeakTracker.h"
       
    22 #include "AtomFeedParser.h"
       
    23 #include "XmlUtils.h"
       
    24 
       
    25 
       
    26 // Element and attribute names used by this parser.
       
    27 _LIT8(KHead, "feed");
       
    28 
       
    29 _LIT8(KTagline, "tagline");
       
    30 _LIT8(KSubtitle, "subtitle");
       
    31 _LIT8(KTitle, "title");
       
    32 _LIT8(KLink, "link");
       
    33 _LIT8(KId, "id");
       
    34 _LIT8(KSummary, "summary");
       
    35 _LIT8(KContent, "content");
       
    36 _LIT8(KEntry, "entry");
       
    37 //_LIT8(KXmlns, "xmlns");
       
    38 _LIT8(KRel, "rel");
       
    39 _LIT8(KHref, "href");
       
    40 _LIT8(KType, "type");
       
    41 _LIT8(KLength, "length");
       
    42 _LIT8(KPublished, "published");
       
    43 _LIT8(KUpdated, "updated");
       
    44 _LIT8(KModified, "modified");
       
    45 _LIT8(KIssued, "issued");
       
    46 
       
    47 _LIT(KAlternate, "alternate");
       
    48 _LIT(KEnclosure, "enclosure");
       
    49 
       
    50 //_LIT8(KAtom1_0Namespace, "http://www.w3.org/2005/Atom");
       
    51 
       
    52 // -----------------------------------------------------------------------------
       
    53 // AtomFeedParser::NewL
       
    54 //
       
    55 // Two-phased constructor.
       
    56 // -----------------------------------------------------------------------------
       
    57 //
       
    58 CAtomFeedParser* CAtomFeedParser::NewL(CXmlUtils& aXmlUtils)
       
    59     {
       
    60     CAtomFeedParser* self = new (ELeave) CAtomFeedParser(aXmlUtils);
       
    61     
       
    62     CleanupStack::PushL(self);
       
    63     self->ConstructL();
       
    64     CleanupStack::Pop();
       
    65 
       
    66     return self;
       
    67     }
       
    68 
       
    69         
       
    70 // -----------------------------------------------------------------------------
       
    71 // CAtomFeedParser::CAtomFeedParser
       
    72 // C++ default constructor can NOT contain any code, that
       
    73 // might leave.
       
    74 // -----------------------------------------------------------------------------
       
    75 //
       
    76 CAtomFeedParser::CAtomFeedParser(CXmlUtils& aXmlUtils):
       
    77         CFeedParser(aXmlUtils), iLeakTracker(CLeakTracker::EAtomFeedParser)
       
    78     {
       
    79     }
       
    80         
       
    81 
       
    82 // -----------------------------------------------------------------------------
       
    83 // CAtomFeedParser::ConstructL
       
    84 // Symbian 2nd phase constructor can leave.
       
    85 // -----------------------------------------------------------------------------
       
    86 //
       
    87 void CAtomFeedParser::ConstructL()
       
    88     {
       
    89     // The mappings are used to map elements to handler methods.  For example when
       
    90     // a <title> element is found its contents are extracted as CDATA and passed
       
    91     // on to the observer as a EFeedAttributeTitle.
       
    92     
       
    93     //
       
    94     // Add mappings to process the children of a channel.
       
    95     //
       
    96     AddFeedMappingL(KNullDesC8(), KEntry(), EFeedAttributeUnused, ElementHandlerItemL);
       
    97 
       
    98     AddFeedMappingL(KNullDesC8(), KTitle(), EFeedAttributeTitle, ElementHandlerTextL);
       
    99     AddFeedMappingL(KNullDesC8(), KLink(), EFeedAttributeLink, ElementHandlerLinkL);
       
   100     AddFeedMappingL(KNullDesC8(), KTagline(), EFeedAttributeDescription, ElementHandlerCDataL);
       
   101     AddFeedMappingL(KNullDesC8(), KSubtitle(), EFeedAttributeDescription, ElementHandlerCDataL);
       
   102 
       
   103     AddFeedMappingL(KNullDesC8(), KPublished(), EFeedAttributeTimestamp, ElementHandlerTimestampL); 
       
   104     AddFeedMappingL(KNullDesC8(), KUpdated(), EFeedAttributeTimestamp, ElementHandlerTimestampL); 
       
   105     AddFeedMappingL(KNullDesC8(), KModified(), EFeedAttributeTimestamp, ElementHandlerTimestampL); 
       
   106     AddFeedMappingL(KNullDesC8(), KIssued(), EFeedAttributeTimestamp, ElementHandlerTimestampL);        
       
   107 
       
   108     //
       
   109     // Add mappings to process the children of an item.
       
   110     //
       
   111     AddItemMappingL(KNullDesC8(), KTitle(), EItemAttributeTitle, ElementHandlerTextL);
       
   112     AddItemMappingL(KNullDesC8(), KLink(), EItemAttributeLink, ElementHandlerLinkL);
       
   113     AddItemMappingL(KNullDesC8(), KContent(), EItemAttributeDescription, ElementHandlerCDataL);    
       
   114     AddItemMappingL(KNullDesC8(), KSummary(), EItemAttributeDescription, ElementHandlerCDataL); 
       
   115     
       
   116     AddItemMappingL(KNullDesC8(), KPublished(), EItemAttributeTimestamp, ElementHandlerTimestampL); 
       
   117     AddItemMappingL(KNullDesC8(), KUpdated(), EItemAttributeTimestamp, ElementHandlerTimestampL); 
       
   118     AddItemMappingL(KNullDesC8(), KModified(), EItemAttributeTimestamp, ElementHandlerTimestampL); 
       
   119     AddItemMappingL(KNullDesC8(), KIssued(), EItemAttributeTimestamp, ElementHandlerTimestampL);        
       
   120     }
       
   121 
       
   122 
       
   123 // -----------------------------------------------------------------------------
       
   124 // CAtomFeedParser::~CAtomFeedParser
       
   125 // Deconstructor.
       
   126 // -----------------------------------------------------------------------------
       
   127 //
       
   128 CAtomFeedParser::~CAtomFeedParser()
       
   129     {
       
   130     }
       
   131 
       
   132         
       
   133 // -----------------------------------------------------------------------------
       
   134 // CAtomFeedParser::IsFeedSupported
       
   135 //
       
   136 // Returns true if this feed parser can process the given document. 
       
   137 // -----------------------------------------------------------------------------
       
   138 //
       
   139 TBool CAtomFeedParser::IsFeedSupported(CXmlUtils& aXmlUtils, 
       
   140         RXmlEngDocument aDocument, const TDesC& /*aContentType*/)
       
   141     {
       
   142     TXmlEngElement  node;
       
   143     
       
   144     // Get the root element.
       
   145     node = aXmlUtils.GetDocumentFirstElement(aDocument);
       
   146 
       
   147     // If the root node is missing the feed isn't supported.    
       
   148     if (node.IsNull())
       
   149         {
       
   150         return EFalse;
       
   151         }
       
   152 
       
   153     // If the root node is not HEAD_STR the feed isn't supported.
       
   154     if (!aXmlUtils.IsNamed(node, KHead))
       
   155         {
       
   156         return EFalse;
       
   157         }
       
   158 
       
   159     return ETrue;
       
   160     }
       
   161 
       
   162 
       
   163 // -----------------------------------------------------------------------------
       
   164 // CAtomFeedParser::ParseFeedL
       
   165 //
       
   166 // Creates a Feed instance from the given document. 
       
   167 // -----------------------------------------------------------------------------
       
   168 //
       
   169 void CAtomFeedParser::ParseFeedL(RXmlEngDocument aDocument, 
       
   170         MFeedParserObserver& aObserver)
       
   171     {
       
   172 	TXmlEngElement             rootNode;
       
   173     RXmlEngNodeList<TXmlEngElement>  children;
       
   174 
       
   175     // Get the feed node.
       
   176     rootNode = iXmlUtils.GetDocumentFirstElement(aDocument);
       
   177 
       
   178     iFeedTimestampNode = NULL;
       
   179     
       
   180     // Process the channel's children.
       
   181     aObserver.FeedBeginsL();
       
   182     
       
   183     rootNode.GetChildElements(children);
       
   184     
       
   185     while (children.HasNext())
       
   186         {
       
   187         TXmlEngElement    node = children.Next();
       
   188         
       
   189         // Process the element.
       
   190         HandleFeedChildL(node, aObserver);
       
   191         }
       
   192 
       
   193     // Set the timestamp attribute.
       
   194     if (iFeedTimestampNode.NotNull())
       
   195         {
       
   196         ElementHandlerDateL(*this, iXmlUtils, iFeedTimestampNode, 
       
   197                 EFeedAttributeTimestamp, aObserver);
       
   198         }
       
   199         
       
   200     aObserver.FeedEndsL();
       
   201     }
       
   202 
       
   203 
       
   204 // -----------------------------------------------------------------------------
       
   205 // CAtomFeedParser::ElementHandlerItemL
       
   206 //
       
   207 // A ElementHandler function that populates the Item instance with the 
       
   208 // values from the given item node.
       
   209 // -----------------------------------------------------------------------------
       
   210 //
       
   211 void CAtomFeedParser::ElementHandlerItemL(const CFeedParser& aParser, CXmlUtils& aXmlUtils, 
       
   212         TXmlEngElement aNode, TInt /*aValueId*/, MFeedParserObserver& aObserver)
       
   213     {
       
   214     CAtomFeedParser&  parser(const_cast<CAtomFeedParser&>(static_cast<const CAtomFeedParser&>(aParser)));
       
   215     TXmlEngElement          node = NULL;
       
   216     
       
   217     // Create an empty Item.
       
   218     aObserver.ItemBeginsL();
       
   219     
       
   220     // Process the item's children.
       
   221     node = aXmlUtils.GetFirstElementChild(aNode);
       
   222     
       
   223     parser.iItemTimestampNode = NULL;
       
   224     
       
   225     while (node.NotNull())
       
   226         {
       
   227         // Process the element.
       
   228         parser.HandleItemChildL(node, aObserver);
       
   229 
       
   230         // Get the next element.
       
   231         node = aXmlUtils.GetNextSiblingElement(node);
       
   232         }
       
   233     
       
   234     // Postprocess the EItemAttributeIdStr attribute.
       
   235     parser.SetItemIdStrAttributeL(aNode, aObserver);
       
   236 
       
   237     // Postprocess the EItemAttributeTimestamp attribute.
       
   238     if (parser.iItemTimestampNode.NotNull())
       
   239         {
       
   240         ElementHandlerDateL(aParser, aXmlUtils, parser.iItemTimestampNode, 
       
   241                 EItemAttributeTimestamp, aObserver);
       
   242         }
       
   243         
       
   244     // Add the Item to the Feed.
       
   245     aObserver.ItemEndsL();
       
   246     }
       
   247 
       
   248 
       
   249 // -----------------------------------------------------------------------------
       
   250 // CAtomFeedParser::ElementHandlerLinkL
       
   251 //
       
   252 // A ElementHandler function that handles the link element.
       
   253 // -----------------------------------------------------------------------------
       
   254 //
       
   255 void CAtomFeedParser::ElementHandlerLinkL(const CFeedParser& /*aParser*/, CXmlUtils& aXmlUtils, 
       
   256         TXmlEngElement aNode, TInt aValueId, MFeedParserObserver& aObserver)
       
   257     {
       
   258     HBufC*  rel = NULL;
       
   259     HBufC*  href = NULL;
       
   260     
       
   261     // Get the link's relationship.
       
   262     rel = aXmlUtils.AttributeL(aNode, KRel);
       
   263     CleanupStack::PushL(rel);
       
   264         
       
   265     // Get the link's url.
       
   266     // TODO: Resolve the href using the base element or feed url.
       
   267     href = aXmlUtils.AttributeL(aNode, KHref);
       
   268     CleanupStack::PushL(href);
       
   269 
       
   270     if ((href == NULL) || (href->Length() == 0))
       
   271         {
       
   272         CleanupStack::PopAndDestroy(href);
       
   273         CleanupStack::PopAndDestroy(rel);
       
   274         
       
   275         return;
       
   276         }
       
   277 
       
   278     // The link points to an item's full story or feed's main web page.
       
   279     if ((rel == NULL) || (rel->CompareF(KAlternate) == 0))
       
   280         {
       
   281         aObserver.AddAttributeL(aValueId, *href);
       
   282         }
       
   283                 
       
   284     // The link points to an enclsoure.
       
   285     else if (rel->CompareF(KEnclosure) == 0)
       
   286         {
       
   287         HBufC*  type = NULL;
       
   288         HBufC*  title = NULL;
       
   289         HBufC*  length = NULL;
       
   290             
       
   291         type = aXmlUtils.AttributeL(aNode, KType);
       
   292         CleanupStack::PushL(type);
       
   293         title = aXmlUtils.AttributeL(aNode, KTitle);
       
   294         CleanupStack::PushL(title);
       
   295         length = aXmlUtils.AttributeL(aNode, KLength);
       
   296         CleanupStack::PushL(length);
       
   297 
       
   298         aObserver.EnclosureBeginsL();
       
   299 
       
   300         if (type != NULL)
       
   301             {                    
       
   302             aObserver.AddAttributeL(EEnclosureAttributeContentType, *type);
       
   303             }
       
   304         if (length != NULL)
       
   305             {                    
       
   306             aObserver.AddAttributeL(EEnclosureAttributeSize, *length);
       
   307             }
       
   308         if (href != NULL)
       
   309             {                    
       
   310             aObserver.AddAttributeL(EEnclosureAttributeLink, *href);
       
   311             }
       
   312         if (title != NULL)
       
   313             {                    
       
   314             aObserver.AddAttributeL(EEnclosureAttributeTitle, *title);
       
   315             }
       
   316 
       
   317         aObserver.EnclosureEndsL();
       
   318 
       
   319         CleanupStack::PopAndDestroy(length);
       
   320         CleanupStack::PopAndDestroy(title);
       
   321         CleanupStack::PopAndDestroy(type);
       
   322         }
       
   323     
       
   324     CleanupStack::PopAndDestroy(href);
       
   325     CleanupStack::PopAndDestroy(rel);
       
   326     }
       
   327 
       
   328 
       
   329 // -----------------------------------------------------------------------------
       
   330 // CAtomFeedParser::ElementHandlerTimestampL
       
   331 //
       
   332 // A ElementHandler function that determines the timestamp to use.  The
       
   333 // point is to track the most relevant timestamp (updated and modified take 
       
   334 // precedence over published and issued).
       
   335 // -----------------------------------------------------------------------------
       
   336 //
       
   337 void CAtomFeedParser::ElementHandlerTimestampL(const CFeedParser& aParser, CXmlUtils& aXmlUtils, 
       
   338         TXmlEngElement aNode, TInt aValueId, MFeedParserObserver& /*aObserver*/) 
       
   339     {
       
   340     CAtomFeedParser&  parser(const_cast<CAtomFeedParser&>(static_cast<const CAtomFeedParser&>(aParser)));
       
   341     TXmlEngElement*         timestampNode;
       
   342     
       
   343     if (aValueId == EFeedAttributeTimestamp)
       
   344         {
       
   345         timestampNode = &parser.iFeedTimestampNode;
       
   346         }
       
   347     else
       
   348         {
       
   349         timestampNode = &parser.iItemTimestampNode;
       
   350         }
       
   351         
       
   352     // As updated and modified mean the same thing (Atom 1.0 vs 0.3) just blindly
       
   353     // update iTimestamp.
       
   354     if (aXmlUtils.IsNamed(aNode, KUpdated))
       
   355         {
       
   356         *timestampNode = aNode;
       
   357         }
       
   358     else if (aXmlUtils.IsNamed(aNode, KModified))
       
   359         {
       
   360         *timestampNode = aNode;
       
   361         }
       
   362         
       
   363         
       
   364     // Only update iTimestamp if it wasn't already set.
       
   365     else if (timestampNode->IsNull())
       
   366         {
       
   367         if (aXmlUtils.IsNamed(aNode, KPublished))
       
   368             {
       
   369             *timestampNode = aNode;
       
   370             }
       
   371         else if (aXmlUtils.IsNamed(aNode, KIssued))
       
   372             {
       
   373             *timestampNode = aNode;
       
   374             }
       
   375         }
       
   376     }
       
   377 
       
   378 
       
   379 // -----------------------------------------------------------------------------
       
   380 // CAtomFeedParser::SetItemIdStrAttributeL
       
   381 //
       
   382 // Determine and set the unique IdStr attribute (unique to the feed that is).
       
   383 // -----------------------------------------------------------------------------
       
   384 //
       
   385 void CAtomFeedParser::SetItemIdStrAttributeL(TXmlEngElement aItemNode, 
       
   386         MFeedParserObserver& aObserver)
       
   387     {    
       
   388     const TInt  KStrChunk = 30;
       
   389     
       
   390     TDesC*    content = NULL;
       
   391     TDesC*    summary = NULL;
       
   392     TDesC*    description = NULL;
       
   393     TDesC*    title = NULL;
       
   394     HBufC*    url = NULL;
       
   395     HBufC*    idStr = NULL;
       
   396     TXmlEngElement  node;
       
   397 
       
   398     // If the id node is present use it.
       
   399     node = iXmlUtils.GetFirstNamedChild(aItemNode, KId);
       
   400     if (node.NotNull())
       
   401         {
       
   402         ElementHandlerCDataL(*this, iXmlUtils, node, EItemAttributeIdStr, aObserver);        
       
   403         return;
       
   404         }
       
   405 
       
   406     // Otherwise create a idStr from the first 30 chars of the description and title
       
   407     // and the last 30 chars of the url.  This doesn't guarantee a unique id, but 
       
   408     // it very likely.
       
   409     node = iXmlUtils.GetFirstNamedChild(aItemNode, KSummary);
       
   410     summary = iXmlUtils.ExtractSimpleTextL(node, KStrChunk);
       
   411     CleanupStack::PushL(summary);
       
   412         
       
   413     node = iXmlUtils.GetFirstNamedChild(aItemNode, KContent);
       
   414     content = iXmlUtils.ExtractSimpleTextL(node, KStrChunk);
       
   415     CleanupStack::PushL(content);
       
   416 
       
   417     node = iXmlUtils.GetFirstNamedChild(aItemNode, KTitle);
       
   418     title = iXmlUtils.ExtractSimpleTextL(node, KStrChunk);
       
   419     CleanupStack::PushL(title);
       
   420     
       
   421     node = iXmlUtils.GetFirstNamedChild(aItemNode, KLink);
       
   422     url = iXmlUtils.ExtractSimpleTextL(node, KStrChunk, ETrue);
       
   423     CleanupStack::PushL(url);
       
   424 
       
   425     // Determine whether content or summary will be used for the description.
       
   426     description = summary;
       
   427     
       
   428     if (content != NULL)
       
   429         {
       
   430         if (summary == NULL)
       
   431             {
       
   432             description = content;
       
   433             }
       
   434         else if (content->Length() > summary->Length())
       
   435             {
       
   436             description = content;
       
   437             }
       
   438         }
       
   439 
       
   440     // Construct the idStr from the parts.
       
   441     TInt  len = 0;
       
   442     
       
   443     if (description != NULL)
       
   444         {
       
   445         len += description->Length();
       
   446         }
       
   447     if (title != NULL)
       
   448         {
       
   449         len += title->Length();
       
   450         }
       
   451     if (url != NULL)
       
   452         {
       
   453         len += url->Length();
       
   454         }
       
   455     
       
   456     idStr = HBufC::NewL(len);
       
   457     CleanupStack::PushL(idStr);
       
   458 
       
   459     TPtr  ptr(idStr->Des());
       
   460     
       
   461     if (description != NULL)
       
   462         {
       
   463         ptr.Append(*description);
       
   464         }
       
   465     if (title != NULL)
       
   466         {
       
   467         ptr.Append(*title);
       
   468         }
       
   469     if (url != NULL)
       
   470         {
       
   471         ptr.Append(*url);
       
   472         }
       
   473         
       
   474     // Replace any chars that may interfere with the database.
       
   475     _LIT(KSpace, " ");
       
   476     
       
   477     for (TInt i = 0; i < ptr.Length(); i++)
       
   478         {
       
   479         if (ptr[i] == '\'')
       
   480             {
       
   481             ptr.Replace(i, 1, KSpace());
       
   482             }
       
   483         }
       
   484     
       
   485     // Set the idStr attribute.
       
   486     aObserver.AddAttributeL(EItemAttributeIdStr, *idStr);
       
   487     
       
   488     CleanupStack::PopAndDestroy(idStr);    
       
   489     CleanupStack::PopAndDestroy(url);    
       
   490     CleanupStack::PopAndDestroy(title);    
       
   491     CleanupStack::PopAndDestroy(content);    
       
   492     CleanupStack::PopAndDestroy(summary);    
       
   493     }