LCOV - code coverage report
Current view: top level - rdf/base - nsRDFXMLSerializer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 580 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=4 sw=4 et tw=80:
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             : 
       8             : #include "nsRDFXMLSerializer.h"
       9             : 
      10             : #include "nsIAtom.h"
      11             : #include "nsIOutputStream.h"
      12             : #include "nsIRDFService.h"
      13             : #include "nsIRDFContainerUtils.h"
      14             : #include "nsIServiceManager.h"
      15             : #include "nsString.h"
      16             : #include "nsXPIDLString.h"
      17             : #include "nsTArray.h"
      18             : #include "rdf.h"
      19             : #include "rdfutil.h"
      20             : #include "mozilla/Attributes.h"
      21             : 
      22             : #include "rdfIDataSource.h"
      23             : 
      24             : int32_t nsRDFXMLSerializer::gRefCnt = 0;
      25             : nsIRDFContainerUtils* nsRDFXMLSerializer::gRDFC;
      26             : nsIRDFResource* nsRDFXMLSerializer::kRDF_instanceOf;
      27             : nsIRDFResource* nsRDFXMLSerializer::kRDF_type;
      28             : nsIRDFResource* nsRDFXMLSerializer::kRDF_nextVal;
      29             : nsIRDFResource* nsRDFXMLSerializer::kRDF_Bag;
      30             : nsIRDFResource* nsRDFXMLSerializer::kRDF_Seq;
      31             : nsIRDFResource* nsRDFXMLSerializer::kRDF_Alt;
      32             : 
      33             : static const char kRDFDescriptionOpen[]      = "  <RDF:Description";
      34             : static const char kIDAttr[]                  = " RDF:ID=\"";
      35             : static const char kAboutAttr[]               = " RDF:about=\"";
      36             : static const char kRDFDescriptionClose[]     = "  </RDF:Description>\n";
      37             : static const char kRDFResource1[] = " RDF:resource=\"";
      38             : static const char kRDFResource2[] = "\"/>\n";
      39             : static const char kRDFParseTypeInteger[] = " NC:parseType=\"Integer\">";
      40             : static const char kRDFParseTypeDate[] = " NC:parseType=\"Date\">";
      41             : static const char kRDFUnknown[] = "><!-- unknown node type -->";
      42             : 
      43             : nsresult
      44           0 : nsRDFXMLSerializer::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
      45             : {
      46           0 :     if (aOuter)
      47           0 :         return NS_ERROR_NO_AGGREGATION;
      48             : 
      49           0 :     nsCOMPtr<nsIRDFXMLSerializer> result = new nsRDFXMLSerializer();
      50           0 :     if (! result)
      51           0 :         return NS_ERROR_OUT_OF_MEMORY;
      52             :     // The serializer object is here, addref gRefCnt so that the
      53             :     // destructor can safely release it.
      54           0 :     gRefCnt++;
      55             : 
      56             :     nsresult rv;
      57           0 :     rv = result->QueryInterface(aIID, aResult);
      58             : 
      59           0 :     if (NS_FAILED(rv)) return rv;
      60             : 
      61           0 :     if (gRefCnt == 1) do {
      62           0 :         nsCOMPtr<nsIRDFService> rdf = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
      63           0 :         if (NS_FAILED(rv)) break;
      64             : 
      65           0 :         rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
      66           0 :                               &kRDF_instanceOf);
      67           0 :         if (NS_FAILED(rv)) break;
      68             : 
      69           0 :         rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
      70           0 :                               &kRDF_type);
      71           0 :         if (NS_FAILED(rv)) break;
      72             : 
      73           0 :         rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"),
      74           0 :                               &kRDF_nextVal);
      75           0 :         if (NS_FAILED(rv)) break;
      76             : 
      77           0 :         rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Bag"),
      78           0 :                               &kRDF_Bag);
      79           0 :         if (NS_FAILED(rv)) break;
      80             : 
      81           0 :         rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Seq"),
      82           0 :                               &kRDF_Seq);
      83           0 :         if (NS_FAILED(rv)) break;
      84             : 
      85           0 :         rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Alt"),
      86           0 :                               &kRDF_Alt);
      87           0 :         if (NS_FAILED(rv)) break;
      88             : 
      89           0 :         rv = CallGetService("@mozilla.org/rdf/container-utils;1", &gRDFC);
      90           0 :         if (NS_FAILED(rv)) break;
      91             :     } while (0);
      92             : 
      93           0 :     return rv;
      94             : }
      95             : 
      96           0 : nsRDFXMLSerializer::nsRDFXMLSerializer()
      97             : {
      98           0 : }
      99             : 
     100           0 : nsRDFXMLSerializer::~nsRDFXMLSerializer()
     101             : {
     102           0 :     if (--gRefCnt == 0) {
     103           0 :         NS_IF_RELEASE(kRDF_Bag);
     104           0 :         NS_IF_RELEASE(kRDF_Seq);
     105           0 :         NS_IF_RELEASE(kRDF_Alt);
     106           0 :         NS_IF_RELEASE(kRDF_instanceOf);
     107           0 :         NS_IF_RELEASE(kRDF_type);
     108           0 :         NS_IF_RELEASE(kRDF_nextVal);
     109           0 :         NS_IF_RELEASE(gRDFC);
     110             :     }
     111           0 : }
     112             : 
     113           0 : NS_IMPL_ISUPPORTS(nsRDFXMLSerializer, nsIRDFXMLSerializer, nsIRDFXMLSource)
     114             : 
     115             : NS_IMETHODIMP
     116           0 : nsRDFXMLSerializer::Init(nsIRDFDataSource* aDataSource)
     117             : {
     118           0 :     if (! aDataSource)
     119           0 :         return NS_ERROR_NULL_POINTER;
     120             : 
     121           0 :     mDataSource = aDataSource;
     122           0 :     mDataSource->GetURI(getter_Copies(mBaseURLSpec));
     123             : 
     124             :     // Add the ``RDF'' prefix, by default.
     125           0 :     nsCOMPtr<nsIAtom> prefix;
     126             : 
     127           0 :     prefix = NS_Atomize("RDF");
     128           0 :     AddNameSpace(prefix, NS_LITERAL_STRING("http://www.w3.org/1999/02/22-rdf-syntax-ns#"));
     129             : 
     130           0 :     prefix = NS_Atomize("NC");
     131           0 :     AddNameSpace(prefix, NS_LITERAL_STRING("http://home.netscape.com/NC-rdf#"));
     132             : 
     133           0 :     mPrefixID = 0;
     134             : 
     135           0 :     return NS_OK;
     136             : }
     137             : 
     138             : NS_IMETHODIMP
     139           0 : nsRDFXMLSerializer::AddNameSpace(nsIAtom* aPrefix, const nsAString& aURI)
     140             : {
     141           0 :     nsCOMPtr<nsIAtom> prefix = aPrefix;
     142           0 :     if (!prefix) {
     143             :         // Make up a prefix, we don't want default namespaces, so
     144             :         // that we can use QNames for elements and attributes alike.
     145           0 :         prefix = EnsureNewPrefix();
     146             :     }
     147           0 :     mNameSpaces.Put(aURI, prefix);
     148           0 :     return NS_OK;
     149             : }
     150             : 
     151             : static nsresult
     152           0 : rdf_BlockingWrite(nsIOutputStream* stream, const char* buf, uint32_t size)
     153             : {
     154           0 :     uint32_t written = 0;
     155           0 :     uint32_t remaining = size;
     156           0 :     while (remaining > 0) {
     157             :         nsresult rv;
     158             :         uint32_t cb;
     159             : 
     160           0 :         if (NS_FAILED(rv = stream->Write(buf + written, remaining, &cb)))
     161           0 :             return rv;
     162             : 
     163           0 :         written += cb;
     164           0 :         remaining -= cb;
     165             :     }
     166           0 :     return NS_OK;
     167             : }
     168             : 
     169             : static nsresult
     170           0 : rdf_BlockingWrite(nsIOutputStream* stream, const nsACString& s)
     171             : {
     172           0 :     return rdf_BlockingWrite(stream, s.BeginReading(), s.Length());
     173             : }
     174             : 
     175             : static nsresult
     176           0 : rdf_BlockingWrite(nsIOutputStream* stream, const nsAString& s)
     177             : {
     178           0 :     NS_ConvertUTF16toUTF8 utf8(s);
     179           0 :     return rdf_BlockingWrite(stream, utf8.get(), utf8.Length());
     180             : }
     181             : 
     182             : already_AddRefed<nsIAtom>
     183           0 : nsRDFXMLSerializer::EnsureNewPrefix()
     184             : {
     185           0 :     nsAutoString qname;
     186           0 :     nsCOMPtr<nsIAtom> prefix;
     187             :     bool isNewPrefix;
     188           0 :     do {
     189           0 :         isNewPrefix = true;
     190           0 :         qname.AssignLiteral("NS");
     191           0 :         qname.AppendInt(++mPrefixID, 10);
     192           0 :         prefix = NS_Atomize(qname);
     193           0 :         nsNameSpaceMap::const_iterator iter = mNameSpaces.first();
     194           0 :         while (iter != mNameSpaces.last() && isNewPrefix) {
     195           0 :             isNewPrefix = (iter->mPrefix != prefix);
     196           0 :             ++iter;
     197             :         }
     198           0 :     } while (!isNewPrefix);
     199           0 :     return prefix.forget();
     200             : }
     201             : 
     202             : // This converts a property resource (like
     203             : // "http://www.w3.org/TR/WD-rdf-syntax#Description") into a QName
     204             : // ("RDF:Description"), and registers the namespace, if it's made up.
     205             : 
     206             : nsresult
     207           0 : nsRDFXMLSerializer::RegisterQName(nsIRDFResource* aResource)
     208             : {
     209           0 :     nsAutoCString uri, qname;
     210           0 :     aResource->GetValueUTF8(uri);
     211             : 
     212           0 :     nsNameSpaceMap::const_iterator iter = mNameSpaces.GetNameSpaceOf(uri);
     213           0 :     if (iter != mNameSpaces.last()) {
     214           0 :         NS_ENSURE_TRUE(iter->mPrefix, NS_ERROR_UNEXPECTED);
     215           0 :         iter->mPrefix->ToUTF8String(qname);
     216           0 :         qname.Append(':');
     217           0 :         qname += StringTail(uri, uri.Length() - iter->mURI.Length());
     218           0 :         mQNames.Put(aResource, qname);
     219           0 :         return NS_OK;
     220             :     }
     221             : 
     222             :     // Okay, so we don't have it in our map. Try to make one up. This
     223             :     // is very bogus.
     224           0 :     int32_t i = uri.RFindChar('#'); // first try a '#'
     225           0 :     if (i == -1) {
     226           0 :         i = uri.RFindChar('/');
     227           0 :         if (i == -1) {
     228             :             // Okay, just punt and assume there is _no_ namespace on
     229             :             // this thing...
     230           0 :             mQNames.Put(aResource, uri);
     231           0 :             return NS_OK;
     232             :         }
     233             :     }
     234             : 
     235             :     // Take whatever is to the right of the '#' or '/' and call it the
     236             :     // local name, make up a prefix.
     237           0 :     nsCOMPtr<nsIAtom> prefix = EnsureNewPrefix();
     238           0 :     mNameSpaces.Put(StringHead(uri, i+1), prefix);
     239           0 :     prefix->ToUTF8String(qname);
     240           0 :     qname.Append(':');
     241           0 :     qname += StringTail(uri, uri.Length() - (i + 1));
     242             : 
     243           0 :     mQNames.Put(aResource, qname);
     244           0 :     return NS_OK;
     245             : }
     246             : 
     247             : nsresult
     248           0 : nsRDFXMLSerializer::GetQName(nsIRDFResource* aResource, nsCString& aQName)
     249             : {
     250           0 :     return mQNames.Get(aResource, &aQName) ? NS_OK : NS_ERROR_UNEXPECTED;
     251             : }
     252             : 
     253             : bool
     254           0 : nsRDFXMLSerializer::IsContainerProperty(nsIRDFResource* aProperty)
     255             : {
     256             :     // Return `true' if the property is an internal property related
     257             :     // to being a container.
     258           0 :     if (aProperty == kRDF_instanceOf)
     259           0 :         return true;
     260             : 
     261           0 :     if (aProperty == kRDF_nextVal)
     262           0 :         return true;
     263             : 
     264           0 :     bool isOrdinal = false;
     265           0 :     gRDFC->IsOrdinalProperty(aProperty, &isOrdinal);
     266           0 :     if (isOrdinal)
     267           0 :         return true;
     268             : 
     269           0 :     return false;
     270             : }
     271             : 
     272             : 
     273             : // convert '&', '<', and '>' into "&amp;", "&lt;", and "&gt", respectively.
     274             : static const char amp[] = "&amp;";
     275             : static const char lt[] = "&lt;";
     276             : static const char gt[] = "&gt;";
     277             : static const char quot[] = "&quot;";
     278             : 
     279             : static void
     280           0 : rdf_EscapeAmpersandsAndAngleBrackets(nsCString& s)
     281             : {
     282             :     uint32_t newLength, origLength;
     283           0 :     newLength = origLength = s.Length();
     284             : 
     285             :     // Compute the length of the result string.
     286           0 :     const char* start = s.BeginReading();
     287           0 :     const char* end = s.EndReading();
     288           0 :     const char* c = start;
     289           0 :     while (c != end) {
     290           0 :         switch (*c) {
     291             :         case '&' :
     292           0 :             newLength += sizeof(amp) - 2;
     293           0 :             break;
     294             :         case '<':
     295             :         case '>':
     296           0 :             newLength += sizeof(gt) - 2;
     297           0 :             break;
     298             :         default:
     299           0 :             break;
     300             :         }
     301           0 :         ++c;
     302             :     }
     303           0 :     if (newLength == origLength) {
     304             :         // nothing to escape
     305           0 :         return;
     306             :     }
     307             : 
     308             :     // escape the chars from the end back to the front.
     309           0 :     s.SetLength(newLength);
     310             : 
     311             :     // Buffer might have changed, get the pointers again
     312           0 :     start = s.BeginReading(); // begin of string
     313           0 :     c = start + origLength - 1; // last char in original string
     314           0 :     char* w = s.EndWriting() - 1; // last char in grown buffer
     315           0 :     while (c >= start) {
     316           0 :         switch (*c) {
     317             :         case '&' :
     318           0 :             w -= 4;
     319           0 :             nsCharTraits<char>::copy(w, amp, sizeof(amp) - 1);
     320           0 :             break;
     321             :         case '<':
     322           0 :             w -= 3;
     323           0 :             nsCharTraits<char>::copy(w, lt, sizeof(lt) - 1);
     324           0 :             break;
     325             :         case '>':
     326           0 :             w -= 3;
     327           0 :             nsCharTraits<char>::copy(w, gt, sizeof(gt) - 1);
     328           0 :             break;
     329             :         default:
     330           0 :             *w = *c;
     331             :         }
     332           0 :         --w;
     333           0 :         --c;
     334             :     }
     335             : }
     336             : 
     337             : // convert '"' to "&quot;"
     338             : static void
     339           0 : rdf_EscapeQuotes(nsCString& s)
     340             : {
     341           0 :     int32_t i = 0;
     342           0 :     while ((i = s.FindChar('"', i)) != -1) {
     343           0 :         s.Replace(i, 1, quot, sizeof(quot) - 1);
     344           0 :         i += sizeof(quot) - 2;
     345             :     }
     346           0 : }
     347             : 
     348             : static void
     349           0 : rdf_EscapeAttributeValue(nsCString& s)
     350             : {
     351           0 :     rdf_EscapeAmpersandsAndAngleBrackets(s);
     352           0 :     rdf_EscapeQuotes(s);
     353           0 : }
     354             : 
     355             : 
     356             : nsresult
     357           0 : nsRDFXMLSerializer::SerializeInlineAssertion(nsIOutputStream* aStream,
     358             :                                              nsIRDFResource* aResource,
     359             :                                              nsIRDFResource* aProperty,
     360             :                                              nsIRDFLiteral* aValue)
     361             : {
     362             :     nsresult rv;
     363           0 :     nsCString qname;
     364           0 :     rv = GetQName(aProperty, qname);
     365           0 :     NS_ENSURE_SUCCESS(rv, rv);
     366             : 
     367           0 :     rv = rdf_BlockingWrite(aStream,
     368           0 :                            NS_LITERAL_CSTRING("\n                   "));
     369           0 :     if (NS_FAILED(rv)) return rv;
     370             : 
     371             :     const char16_t* value;
     372           0 :     aValue->GetValueConst(&value);
     373           0 :     NS_ConvertUTF16toUTF8 s(value);
     374             : 
     375           0 :     rdf_EscapeAttributeValue(s);
     376             : 
     377           0 :     rv = rdf_BlockingWrite(aStream, qname);
     378           0 :     if (NS_FAILED(rv)) return rv;
     379           0 :     rv = rdf_BlockingWrite(aStream, "=\"", 2);
     380           0 :     if (NS_FAILED(rv)) return rv;
     381           0 :     s.Append('"');
     382           0 :     return rdf_BlockingWrite(aStream, s);
     383             : }
     384             : 
     385             : nsresult
     386           0 : nsRDFXMLSerializer::SerializeChildAssertion(nsIOutputStream* aStream,
     387             :                                             nsIRDFResource* aResource,
     388             :                                             nsIRDFResource* aProperty,
     389             :                                             nsIRDFNode* aValue)
     390             : {
     391           0 :     nsCString qname;
     392           0 :     nsresult rv = GetQName(aProperty, qname);
     393           0 :     NS_ENSURE_SUCCESS(rv, rv);
     394             : 
     395           0 :     rv = rdf_BlockingWrite(aStream, "    <", 5);
     396           0 :     if (NS_FAILED(rv)) return rv;
     397           0 :     rv = rdf_BlockingWrite(aStream, qname);
     398           0 :     if (NS_FAILED(rv)) return rv;
     399             : 
     400           0 :     nsCOMPtr<nsIRDFResource> resource;
     401           0 :     nsCOMPtr<nsIRDFLiteral> literal;
     402           0 :     nsCOMPtr<nsIRDFInt> number;
     403           0 :     nsCOMPtr<nsIRDFDate> date;
     404             : 
     405           0 :     if ((resource = do_QueryInterface(aValue)) != nullptr) {
     406           0 :         nsAutoCString uri;
     407           0 :         resource->GetValueUTF8(uri);
     408             : 
     409           0 :         rdf_MakeRelativeRef(mBaseURLSpec, uri);
     410           0 :         rdf_EscapeAttributeValue(uri);
     411             : 
     412             :         rv = rdf_BlockingWrite(aStream, kRDFResource1,
     413           0 :                                sizeof(kRDFResource1) - 1);
     414           0 :         if (NS_FAILED(rv)) return rv;
     415           0 :         rv = rdf_BlockingWrite(aStream, uri);
     416           0 :         if (NS_FAILED(rv)) return rv;
     417             :         rv = rdf_BlockingWrite(aStream, kRDFResource2,
     418           0 :                                sizeof(kRDFResource2) - 1);
     419           0 :         if (NS_FAILED(rv)) return rv;
     420             : 
     421           0 :         goto no_close_tag;
     422             :     }
     423           0 :     else if ((literal = do_QueryInterface(aValue)) != nullptr) {
     424             :         const char16_t *value;
     425           0 :         literal->GetValueConst(&value);
     426           0 :         NS_ConvertUTF16toUTF8 s(value);
     427             : 
     428           0 :         rdf_EscapeAmpersandsAndAngleBrackets(s);
     429             : 
     430           0 :         rv = rdf_BlockingWrite(aStream, ">", 1);
     431           0 :         if (NS_FAILED(rv)) return rv;
     432           0 :         rv = rdf_BlockingWrite(aStream, s);
     433           0 :         if (NS_FAILED(rv)) return rv;
     434             :     }
     435           0 :     else if ((number = do_QueryInterface(aValue)) != nullptr) {
     436             :         int32_t value;
     437           0 :         number->GetValue(&value);
     438             : 
     439           0 :         nsAutoCString n;
     440           0 :         n.AppendInt(value);
     441             : 
     442             :         rv = rdf_BlockingWrite(aStream, kRDFParseTypeInteger,
     443           0 :                                sizeof(kRDFParseTypeInteger) - 1);
     444           0 :         if (NS_FAILED(rv)) return rv;
     445           0 :         rv = rdf_BlockingWrite(aStream, n);
     446           0 :         if (NS_FAILED(rv)) return rv;
     447             :     }
     448           0 :     else if ((date = do_QueryInterface(aValue)) != nullptr) {
     449             :         PRTime value;
     450           0 :         date->GetValue(&value);
     451             : 
     452           0 :         nsAutoCString s;
     453           0 :         rdf_FormatDate(value, s);
     454             : 
     455             :         rv = rdf_BlockingWrite(aStream, kRDFParseTypeDate,
     456           0 :                                sizeof(kRDFParseTypeDate) - 1);
     457           0 :         if (NS_FAILED(rv)) return rv;
     458           0 :         rv = rdf_BlockingWrite(aStream, s);
     459           0 :         if (NS_FAILED(rv)) return rv;
     460             :     }
     461             :     else {
     462             :         // XXX it doesn't support nsIRDFResource _or_ nsIRDFLiteral???
     463             :         // We should serialize nsIRDFInt, nsIRDFDate, etc...
     464           0 :         NS_WARNING("unknown RDF node type");
     465             : 
     466           0 :         rv = rdf_BlockingWrite(aStream, kRDFUnknown, sizeof(kRDFUnknown) - 1);
     467           0 :         if (NS_FAILED(rv)) return rv;
     468             :     }
     469             : 
     470           0 :     rv = rdf_BlockingWrite(aStream, "</", 2);
     471           0 :     if (NS_FAILED(rv)) return rv;
     472           0 :     rv = rdf_BlockingWrite(aStream, qname);
     473           0 :     if (NS_FAILED(rv)) return rv;
     474           0 :     return rdf_BlockingWrite(aStream, ">\n", 2);
     475             : 
     476             :  no_close_tag:
     477           0 :     return NS_OK;
     478             : }
     479             : 
     480             : nsresult
     481           0 : nsRDFXMLSerializer::SerializeProperty(nsIOutputStream* aStream,
     482             :                                       nsIRDFResource* aResource,
     483             :                                       nsIRDFResource* aProperty,
     484             :                                       bool aInline,
     485             :                                       int32_t* aSkipped)
     486             : {
     487           0 :     nsresult rv = NS_OK;
     488             : 
     489           0 :     int32_t skipped = 0;
     490             : 
     491           0 :     nsCOMPtr<nsISimpleEnumerator> assertions;
     492           0 :     mDataSource->GetTargets(aResource, aProperty, true, getter_AddRefs(assertions));
     493           0 :     if (! assertions)
     494           0 :         return NS_ERROR_FAILURE;
     495             : 
     496             :     // Serializing the assertion inline is ok as long as the property has
     497             :     // only one target value, and it is a literal that doesn't include line
     498             :     // breaks.
     499           0 :     bool needsChild = false;
     500             : 
     501             :     while (1) {
     502           0 :         bool hasMore = false;
     503           0 :         assertions->HasMoreElements(&hasMore);
     504           0 :         if (! hasMore)
     505           0 :             break;
     506             : 
     507           0 :         nsCOMPtr<nsISupports> isupports;
     508           0 :         assertions->GetNext(getter_AddRefs(isupports));
     509           0 :         nsCOMPtr<nsIRDFLiteral> literal = do_QueryInterface(isupports);
     510           0 :         needsChild |= (!literal);
     511             : 
     512           0 :         if (!needsChild) {
     513           0 :             assertions->HasMoreElements(&needsChild);
     514           0 :             if (!needsChild) {
     515           0 :                 const char16_t* literalVal = nullptr;
     516           0 :                 literal->GetValueConst(&literalVal);
     517           0 :                 if (literalVal) {
     518           0 :                     for (; *literalVal; literalVal++) {
     519           0 :                         if (*literalVal == char16_t('\n') ||
     520           0 :                             *literalVal == char16_t('\r')) {
     521           0 :                             needsChild = true;
     522           0 :                             break;
     523             :                         }
     524             :                     }
     525             :                 }
     526             :             }
     527             :         }
     528             : 
     529           0 :         if (aInline && !needsChild) {
     530           0 :             rv = SerializeInlineAssertion(aStream, aResource, aProperty, literal);
     531             :         }
     532           0 :         else if (!aInline && needsChild) {
     533           0 :             nsCOMPtr<nsIRDFNode> value = do_QueryInterface(isupports);
     534           0 :             rv = SerializeChildAssertion(aStream, aResource, aProperty, value);
     535             :         }
     536             :         else {
     537           0 :             ++skipped;
     538           0 :             rv = NS_OK;
     539             :         }
     540             : 
     541           0 :         if (NS_FAILED(rv))
     542           0 :             break;
     543           0 :     }
     544             : 
     545           0 :     *aSkipped += skipped;
     546           0 :     return rv;
     547             : }
     548             : 
     549             : 
     550             : nsresult
     551           0 : nsRDFXMLSerializer::SerializeDescription(nsIOutputStream* aStream,
     552             :                                          nsIRDFResource* aResource)
     553             : {
     554             :     nsresult rv;
     555             : 
     556           0 :     bool isTypedNode = false;
     557           0 :     nsCString typeQName;
     558             : 
     559           0 :     nsCOMPtr<nsIRDFNode> typeNode;
     560           0 :     mDataSource->GetTarget(aResource, kRDF_type, true, getter_AddRefs(typeNode));
     561           0 :     if (typeNode) {
     562           0 :         nsCOMPtr<nsIRDFResource> type = do_QueryInterface(typeNode, &rv);
     563           0 :         if (type) {
     564             :             // Try to get a namespace prefix.  If none is available,
     565             :             // just treat the description as if it weren't a typed node
     566             :             // after all and emit rdf:type as a normal property.  This
     567             :             // seems preferable to using a bogus (invented) prefix.
     568           0 :             isTypedNode = NS_SUCCEEDED(GetQName(type, typeQName));
     569             :         }
     570             :     }
     571             : 
     572           0 :     nsAutoCString uri;
     573           0 :     rv = aResource->GetValueUTF8(uri);
     574           0 :     if (NS_FAILED(rv)) return rv;
     575             : 
     576           0 :     rdf_MakeRelativeRef(mBaseURLSpec, uri);
     577           0 :     rdf_EscapeAttributeValue(uri);
     578             : 
     579             :     // Emit an open tag and the subject
     580           0 :     if (isTypedNode) {
     581           0 :         rv = rdf_BlockingWrite(aStream, NS_LITERAL_STRING("  <"));
     582           0 :         if (NS_FAILED(rv)) return rv;
     583             :         // Watch out for the default namespace!
     584           0 :         rv = rdf_BlockingWrite(aStream, typeQName);
     585           0 :         if (NS_FAILED(rv)) return rv;
     586             :     }
     587             :     else {
     588           0 :         rv = rdf_BlockingWrite(aStream, kRDFDescriptionOpen,
     589             :                                sizeof(kRDFDescriptionOpen) - 1);
     590           0 :         if (NS_FAILED(rv)) return rv;
     591             :     }
     592           0 :     if (uri[0] == char16_t('#')) {
     593           0 :         uri.Cut(0, 1);
     594           0 :         rv = rdf_BlockingWrite(aStream, kIDAttr, sizeof(kIDAttr) - 1);
     595             :     }
     596             :     else {
     597           0 :         rv = rdf_BlockingWrite(aStream, kAboutAttr, sizeof(kAboutAttr) - 1);
     598             :     }
     599           0 :     if (NS_FAILED(rv)) return rv;
     600             : 
     601           0 :     uri.Append('"');
     602           0 :     rv = rdf_BlockingWrite(aStream, uri);
     603           0 :     if (NS_FAILED(rv)) return rv;
     604             : 
     605             :     // Any value that's a literal we can write out as an inline
     606             :     // attribute on the RDF:Description
     607           0 :     AutoTArray<nsIRDFResource*, 8> visited;
     608           0 :     int32_t skipped = 0;
     609             : 
     610           0 :     nsCOMPtr<nsISimpleEnumerator> arcs;
     611           0 :     mDataSource->ArcLabelsOut(aResource, getter_AddRefs(arcs));
     612             : 
     613           0 :     if (arcs) {
     614             :         // Don't re-serialize rdf:type later on
     615           0 :         if (isTypedNode)
     616           0 :             visited.AppendElement(kRDF_type);
     617             : 
     618             :         while (1) {
     619           0 :             bool hasMore = false;
     620           0 :             arcs->HasMoreElements(&hasMore);
     621           0 :             if (! hasMore)
     622           0 :                 break;
     623             : 
     624           0 :             nsCOMPtr<nsISupports> isupports;
     625           0 :             arcs->GetNext(getter_AddRefs(isupports));
     626             : 
     627           0 :             nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
     628           0 :             if (! property)
     629           0 :                 continue;
     630             : 
     631             :             // Ignore properties that pertain to containers; we may be
     632             :             // called from SerializeContainer() if the container resource
     633             :             // has been assigned non-container properties.
     634           0 :             if (IsContainerProperty(property))
     635           0 :                 continue;
     636             : 
     637             :             // Only serialize values for the property once.
     638           0 :             if (visited.Contains(property.get()))
     639           0 :                 continue;
     640             : 
     641           0 :             visited.AppendElement(property.get());
     642             : 
     643           0 :             SerializeProperty(aStream, aResource, property, true, &skipped);
     644           0 :         }
     645             :     }
     646             : 
     647           0 :     if (skipped) {
     648             :         // Close the RDF:Description tag.
     649           0 :         rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(">\n"));
     650           0 :         if (NS_FAILED(rv)) return rv;
     651             : 
     652             :         // Now write out resources (which might have their own
     653             :         // substructure) as children.
     654           0 :         mDataSource->ArcLabelsOut(aResource, getter_AddRefs(arcs));
     655             : 
     656           0 :         if (arcs) {
     657             :             // Forget that we've visited anything
     658           0 :             visited.Clear();
     659             :             // ... except for rdf:type
     660           0 :             if (isTypedNode)
     661           0 :                 visited.AppendElement(kRDF_type);
     662             : 
     663             :             while (1) {
     664           0 :                 bool hasMore = false;
     665           0 :                 arcs->HasMoreElements(&hasMore);
     666           0 :                 if (! hasMore)
     667           0 :                     break;
     668             : 
     669           0 :                 nsCOMPtr<nsISupports> isupports;
     670           0 :                 arcs->GetNext(getter_AddRefs(isupports));
     671             : 
     672           0 :                 nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
     673           0 :                 if (! property)
     674           0 :                     continue;
     675             : 
     676             :                 // Ignore properties that pertain to containers; we may be
     677             :                 // called from SerializeContainer() if the container
     678             :                 // resource has been assigned non-container properties.
     679           0 :                 if (IsContainerProperty(property))
     680           0 :                     continue;
     681             : 
     682             :                 // have we already seen this property?  If so, don't write it
     683             :                 // out again; serialize property will write each instance.
     684           0 :                 if (visited.Contains(property.get()))
     685           0 :                     continue;
     686             : 
     687           0 :                 visited.AppendElement(property.get());
     688             : 
     689           0 :                 SerializeProperty(aStream, aResource, property, false, &skipped);
     690           0 :             }
     691             :         }
     692             : 
     693             :         // Emit a proper close-tag.
     694           0 :         if (isTypedNode) {
     695           0 :             rv = rdf_BlockingWrite(aStream,  NS_LITERAL_CSTRING("  </"));
     696           0 :             if (NS_FAILED(rv)) return rv;
     697             :             // Watch out for the default namespace!
     698           0 :             rdf_BlockingWrite(aStream, typeQName);
     699           0 :             if (NS_FAILED(rv)) return rv;
     700           0 :             rdf_BlockingWrite(aStream, ">\n", 2);
     701           0 :             if (NS_FAILED(rv)) return rv;
     702             :         }
     703             :         else {
     704           0 :             rv = rdf_BlockingWrite(aStream, kRDFDescriptionClose,
     705             :                                    sizeof(kRDFDescriptionClose) - 1);
     706           0 :             if (NS_FAILED(rv)) return rv;
     707             :         }
     708             :     }
     709             :     else {
     710             :         // If we saw _no_ child properties, then we can don't need a
     711             :         // close-tag.
     712           0 :         rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(" />\n"));
     713           0 :         if (NS_FAILED(rv)) return rv;
     714             :     }
     715             : 
     716           0 :     return NS_OK;
     717             : }
     718             : 
     719             : nsresult
     720           0 : nsRDFXMLSerializer::SerializeMember(nsIOutputStream* aStream,
     721             :                                       nsIRDFResource* aContainer,
     722             :                                       nsIRDFNode* aMember)
     723             : {
     724             :     // If it's a resource, then output a "<RDF:li RDF:resource=... />"
     725             :     // tag, because we'll be dumping the resource separately. (We
     726             :     // iterate thru all the resources in the datasource,
     727             :     // remember?) Otherwise, output the literal value.
     728             : 
     729           0 :     nsCOMPtr<nsIRDFResource> resource;
     730           0 :     nsCOMPtr<nsIRDFLiteral> literal;
     731           0 :     nsCOMPtr<nsIRDFInt> number;
     732           0 :     nsCOMPtr<nsIRDFDate> date;
     733             : 
     734             : static const char kRDFLIOpen[] = "    <RDF:li";
     735             :     nsresult rv = rdf_BlockingWrite(aStream, kRDFLIOpen,
     736           0 :                                     sizeof(kRDFLIOpen) - 1);
     737           0 :     if (NS_FAILED(rv)) return rv;
     738             : 
     739           0 :     if ((resource = do_QueryInterface(aMember)) != nullptr) {
     740           0 :         nsAutoCString uri;
     741           0 :         resource->GetValueUTF8(uri);
     742             : 
     743           0 :         rdf_MakeRelativeRef(mBaseURLSpec, uri);
     744           0 :         rdf_EscapeAttributeValue(uri);
     745             : 
     746             :         rv = rdf_BlockingWrite(aStream, kRDFResource1,
     747           0 :                                sizeof(kRDFResource1) - 1);
     748           0 :         if (NS_FAILED(rv)) return rv;
     749           0 :         rv = rdf_BlockingWrite(aStream, uri);
     750           0 :         if (NS_FAILED(rv)) return rv;
     751             :         rv = rdf_BlockingWrite(aStream, kRDFResource2,
     752           0 :                                sizeof(kRDFResource2) - 1);
     753           0 :         if (NS_FAILED(rv)) return rv;
     754             : 
     755           0 :         goto no_close_tag;
     756             :     }
     757           0 :     else if ((literal = do_QueryInterface(aMember)) != nullptr) {
     758             :         const char16_t *value;
     759           0 :         literal->GetValueConst(&value);
     760             : static const char kRDFLIOpenGT[] = ">";
     761             :         // close the '<RDF:LI' before adding the literal
     762             :         rv = rdf_BlockingWrite(aStream, kRDFLIOpenGT,
     763           0 :                                sizeof(kRDFLIOpenGT) - 1);
     764           0 :         if (NS_FAILED(rv)) return rv;
     765             : 
     766           0 :         NS_ConvertUTF16toUTF8 s(value);
     767           0 :         rdf_EscapeAmpersandsAndAngleBrackets(s);
     768             : 
     769           0 :         rv = rdf_BlockingWrite(aStream, s);
     770           0 :         if (NS_FAILED(rv)) return rv;
     771             :     }
     772           0 :     else if ((number = do_QueryInterface(aMember)) != nullptr) {
     773             :         int32_t value;
     774           0 :         number->GetValue(&value);
     775             : 
     776           0 :         nsAutoCString n;
     777           0 :         n.AppendInt(value);
     778             : 
     779             :         rv = rdf_BlockingWrite(aStream, kRDFParseTypeInteger,
     780           0 :                                sizeof(kRDFParseTypeInteger) - 1);
     781           0 :         if (NS_FAILED(rv)) return rv;
     782           0 :         rv = rdf_BlockingWrite(aStream, n);
     783           0 :         if (NS_FAILED(rv)) return rv;
     784             :     }
     785           0 :     else if ((date = do_QueryInterface(aMember)) != nullptr) {
     786             :         PRTime value;
     787           0 :         date->GetValue(&value);
     788             : 
     789           0 :         nsAutoCString s;
     790           0 :         rdf_FormatDate(value, s);
     791             : 
     792             :         rv = rdf_BlockingWrite(aStream, kRDFParseTypeDate,
     793           0 :                                sizeof(kRDFParseTypeDate) - 1);
     794           0 :         if (NS_FAILED(rv)) return rv;
     795           0 :         rv = rdf_BlockingWrite(aStream, s);
     796           0 :         if (NS_FAILED(rv)) return rv;
     797             :     }
     798             :     else {
     799             :         // XXX it doesn't support nsIRDFResource _or_ nsIRDFLiteral???
     800             :         // We should serialize nsIRDFInt, nsIRDFDate, etc...
     801           0 :         NS_WARNING("unknown RDF node type");
     802             : 
     803           0 :         rv = rdf_BlockingWrite(aStream, kRDFUnknown, sizeof(kRDFUnknown) - 1);
     804           0 :         if (NS_FAILED(rv)) return rv;
     805             :     }
     806             : 
     807             :     {
     808             : static const char kRDFLIClose[] = "</RDF:li>\n";
     809           0 :         rv = rdf_BlockingWrite(aStream, kRDFLIClose, sizeof(kRDFLIClose) - 1);
     810           0 :         if (NS_FAILED(rv)) return rv;
     811             :     }
     812             : 
     813             :  no_close_tag:
     814           0 :     return NS_OK;
     815             : }
     816             : 
     817             : 
     818             : nsresult
     819           0 : nsRDFXMLSerializer::SerializeContainer(nsIOutputStream* aStream,
     820             :                                          nsIRDFResource* aContainer)
     821             : {
     822             :     nsresult rv;
     823           0 :     nsAutoCString tag;
     824             : 
     825             :     // Decide if it's a sequence, bag, or alternation, and print the
     826             :     // appropriate tag-open sequence
     827             : 
     828           0 :     if (IsA(mDataSource, aContainer, kRDF_Bag)) {
     829           0 :         tag.AssignLiteral("RDF:Bag");
     830             :     }
     831           0 :     else if (IsA(mDataSource, aContainer, kRDF_Seq)) {
     832           0 :         tag.AssignLiteral("RDF:Seq");
     833             :     }
     834           0 :     else if (IsA(mDataSource, aContainer, kRDF_Alt)) {
     835           0 :         tag.AssignLiteral("RDF:Alt");
     836             :     }
     837             :     else {
     838           0 :         NS_ASSERTION(false, "huh? this is _not_ a container.");
     839           0 :         return NS_ERROR_UNEXPECTED;
     840             :     }
     841             : 
     842           0 :     rv = rdf_BlockingWrite(aStream, "  <", 3);
     843           0 :     if (NS_FAILED(rv)) return rv;
     844           0 :     rv = rdf_BlockingWrite(aStream, tag);
     845           0 :     if (NS_FAILED(rv)) return rv;
     846             : 
     847             : 
     848             :     // Unfortunately, we always need to print out the identity of the
     849             :     // resource, even if was constructed "anonymously". We need to do
     850             :     // this because we never really know who else might be referring
     851             :     // to it...
     852             : 
     853           0 :     nsAutoCString uri;
     854           0 :     if (NS_SUCCEEDED(aContainer->GetValueUTF8(uri))) {
     855           0 :         rdf_MakeRelativeRef(mBaseURLSpec, uri);
     856             : 
     857           0 :         rdf_EscapeAttributeValue(uri);
     858             : 
     859           0 :         if (uri.First() == '#') {
     860             :             // Okay, it's actually identified as an element in the
     861             :             // current document, not trying to decorate some absolute
     862             :             // URI. We can use the 'ID=' attribute...
     863             : 
     864           0 :             uri.Cut(0, 1); // chop the '#'
     865           0 :             rv = rdf_BlockingWrite(aStream, kIDAttr, sizeof(kIDAttr) - 1);
     866           0 :             if (NS_FAILED(rv)) return rv;
     867             :         }
     868             :         else {
     869             :             // We need to cheat and spit out an illegal 'about=' on
     870             :             // the sequence.
     871             :             rv = rdf_BlockingWrite(aStream, kAboutAttr,
     872           0 :                                    sizeof(kAboutAttr) - 1);
     873           0 :             if (NS_FAILED(rv)) return rv;
     874             :         }
     875             : 
     876           0 :         rv = rdf_BlockingWrite(aStream, uri);
     877           0 :         if (NS_FAILED(rv)) return rv;
     878           0 :         rv = rdf_BlockingWrite(aStream, "\"", 1);
     879           0 :         if (NS_FAILED(rv)) return rv;
     880             :     }
     881             : 
     882           0 :     rv = rdf_BlockingWrite(aStream, ">\n", 2);
     883           0 :     if (NS_FAILED(rv)) return rv;
     884             : 
     885             :     // First iterate through each of the ordinal elements (the RDF/XML
     886             :     // syntax doesn't allow us to place properties on RDF container
     887             :     // elements).
     888           0 :     nsCOMPtr<nsISimpleEnumerator> elements;
     889           0 :     rv = NS_NewContainerEnumerator(mDataSource, aContainer, getter_AddRefs(elements));
     890             : 
     891           0 :     if (NS_SUCCEEDED(rv)) {
     892             :         while (1) {
     893             :             bool hasMore;
     894           0 :             rv = elements->HasMoreElements(&hasMore);
     895           0 :             if (NS_FAILED(rv)) break;
     896             : 
     897           0 :             if (! hasMore)
     898           0 :                 break;
     899             : 
     900           0 :             nsCOMPtr<nsISupports> isupports;
     901           0 :             elements->GetNext(getter_AddRefs(isupports));
     902             : 
     903           0 :             nsCOMPtr<nsIRDFNode> element = do_QueryInterface(isupports);
     904           0 :             NS_ASSERTION(element != nullptr, "not an nsIRDFNode");
     905           0 :             if (! element)
     906           0 :                 continue;
     907             : 
     908           0 :             SerializeMember(aStream, aContainer, element);
     909           0 :         }
     910             :     }
     911             : 
     912             :     // close the container tag
     913           0 :     rv = rdf_BlockingWrite(aStream, "  </", 4);
     914           0 :     if (NS_FAILED(rv)) return rv;
     915           0 :     tag.Append(">\n", 2);
     916           0 :     rv = rdf_BlockingWrite(aStream, tag);
     917           0 :     if (NS_FAILED(rv)) return rv;
     918             : 
     919             :     // Now, we iterate through _all_ of the arcs, in case someone has
     920             :     // applied properties to the bag itself. These'll be placed in a
     921             :     // separate RDF:Description element.
     922           0 :     nsCOMPtr<nsISimpleEnumerator> arcs;
     923           0 :     mDataSource->ArcLabelsOut(aContainer, getter_AddRefs(arcs));
     924             : 
     925           0 :     bool wroteDescription = false;
     926           0 :     while (! wroteDescription) {
     927           0 :         bool hasMore = false;
     928           0 :         rv = arcs->HasMoreElements(&hasMore);
     929           0 :         if (NS_FAILED(rv)) break;
     930             : 
     931           0 :         if (! hasMore)
     932           0 :             break;
     933             : 
     934             :         nsIRDFResource* property;
     935           0 :         rv = arcs->GetNext((nsISupports**) &property);
     936           0 :         if (NS_FAILED(rv)) break;
     937             : 
     938             :         // If it's a membership property, then output a "LI"
     939             :         // tag. Otherwise, output a property.
     940           0 :         if (! IsContainerProperty(property)) {
     941           0 :             rv = SerializeDescription(aStream, aContainer);
     942           0 :             wroteDescription = true;
     943             :         }
     944             : 
     945           0 :         NS_RELEASE(property);
     946           0 :         if (NS_FAILED(rv))
     947           0 :             break;
     948             :     }
     949             : 
     950           0 :     return NS_OK;
     951             : }
     952             : 
     953             : 
     954             : nsresult
     955           0 : nsRDFXMLSerializer::SerializePrologue(nsIOutputStream* aStream)
     956             : {
     957             : static const char kXMLVersion[] = "<?xml version=\"1.0\"?>\n";
     958             : 
     959             :     nsresult rv;
     960           0 :     rv = rdf_BlockingWrite(aStream, kXMLVersion, sizeof(kXMLVersion) - 1);
     961           0 :     if (NS_FAILED(rv)) return rv;
     962             : 
     963             :     // global name space declarations
     964           0 :     rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("<RDF:RDF "));
     965           0 :     if (NS_FAILED(rv)) return rv;
     966             : 
     967           0 :     nsNameSpaceMap::const_iterator first = mNameSpaces.first();
     968           0 :     nsNameSpaceMap::const_iterator last = mNameSpaces.last();
     969           0 :     for (nsNameSpaceMap::const_iterator entry = first; entry != last; ++entry) {
     970           0 :         if (entry != first) {
     971           0 :             rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("\n         "));
     972           0 :             if (NS_FAILED(rv)) return rv;
     973             :         }
     974           0 :         rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("xmlns"));
     975           0 :         if (NS_FAILED(rv)) return rv;
     976             : 
     977           0 :         if (entry->mPrefix) {
     978           0 :             rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(":"));
     979           0 :             if (NS_FAILED(rv)) return rv;
     980           0 :             nsAutoCString prefix;
     981           0 :             entry->mPrefix->ToUTF8String(prefix);
     982           0 :             rv = rdf_BlockingWrite(aStream, prefix);
     983           0 :             if (NS_FAILED(rv)) return rv;
     984             :         }
     985             : 
     986           0 :         rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("=\""));
     987           0 :         if (NS_FAILED(rv)) return rv;
     988           0 :         nsAutoCString uri(entry->mURI);
     989           0 :         rdf_EscapeAttributeValue(uri);
     990           0 :         rv = rdf_BlockingWrite(aStream, uri);
     991           0 :         if (NS_FAILED(rv)) return rv;
     992           0 :         rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("\""));
     993           0 :         if (NS_FAILED(rv)) return rv;
     994             :     }
     995             : 
     996           0 :     return rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(">\n"));
     997             : }
     998             : 
     999             : 
    1000             : nsresult
    1001           0 : nsRDFXMLSerializer::SerializeEpilogue(nsIOutputStream* aStream)
    1002             : {
    1003           0 :     return rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("</RDF:RDF>\n"));
    1004             : }
    1005             : 
    1006             : class QNameCollector final : public rdfITripleVisitor {
    1007             : public:
    1008             :     NS_DECL_ISUPPORTS
    1009             :     NS_DECL_RDFITRIPLEVISITOR
    1010           0 :     explicit QNameCollector(nsRDFXMLSerializer* aParent)
    1011           0 :         : mParent(aParent){}
    1012             : private:
    1013           0 :     ~QNameCollector() {}
    1014             :     nsRDFXMLSerializer* mParent;
    1015             : };
    1016             : 
    1017           0 : NS_IMPL_ISUPPORTS(QNameCollector, rdfITripleVisitor)
    1018             : nsresult
    1019           0 : QNameCollector::Visit(nsIRDFNode* aSubject, nsIRDFResource* aPredicate,
    1020             :                       nsIRDFNode* aObject, bool aTruthValue)
    1021             : {
    1022           0 :     if (aPredicate == mParent->kRDF_type) {
    1023             :         // try to get a type QName for aObject, should be a resource
    1024           0 :         nsCOMPtr<nsIRDFResource> resType = do_QueryInterface(aObject);
    1025           0 :         if (!resType) {
    1026             :             // ignore error
    1027           0 :             return NS_OK;
    1028             :         }
    1029           0 :         if (mParent->mQNames.Get(resType, nullptr)) {
    1030           0 :             return NS_OK;
    1031             :         }
    1032           0 :         mParent->RegisterQName(resType);
    1033           0 :         return NS_OK;
    1034             :     }
    1035             : 
    1036           0 :     if (mParent->mQNames.Get(aPredicate, nullptr)) {
    1037           0 :         return NS_OK;
    1038             :     }
    1039           0 :     if (aPredicate == mParent->kRDF_instanceOf ||
    1040           0 :         aPredicate == mParent->kRDF_nextVal)
    1041           0 :         return NS_OK;
    1042           0 :     bool isOrdinal = false;
    1043           0 :     mParent->gRDFC->IsOrdinalProperty(aPredicate, &isOrdinal);
    1044           0 :     if (isOrdinal)
    1045           0 :         return NS_OK;
    1046             : 
    1047           0 :     mParent->RegisterQName(aPredicate);
    1048             : 
    1049           0 :     return NS_OK;
    1050             : }
    1051             : 
    1052             : nsresult
    1053           0 : nsRDFXMLSerializer::CollectNamespaces()
    1054             : {
    1055             :     // Iterate over all Triples to get namespaces for subject resource types
    1056             :     // and Predicates and cache all the QNames we want to use.
    1057             :     nsCOMPtr<rdfITripleVisitor> collector =
    1058           0 :         new QNameCollector(this);
    1059           0 :     nsCOMPtr<rdfIDataSource> ds = do_QueryInterface(mDataSource); // XXX API
    1060           0 :     NS_ENSURE_TRUE(collector && ds, NS_ERROR_FAILURE);
    1061           0 :     return ds->VisitAllTriples(collector);
    1062             : }
    1063             : 
    1064             : //----------------------------------------------------------------------
    1065             : 
    1066             : NS_IMETHODIMP
    1067           0 : nsRDFXMLSerializer::Serialize(nsIOutputStream* aStream)
    1068             : {
    1069             :     nsresult rv;
    1070             : 
    1071           0 :     rv = CollectNamespaces();
    1072           0 :     if (NS_FAILED(rv)) return rv;
    1073             : 
    1074           0 :     nsCOMPtr<nsISimpleEnumerator> resources;
    1075           0 :     rv = mDataSource->GetAllResources(getter_AddRefs(resources));
    1076           0 :     if (NS_FAILED(rv)) return rv;
    1077             : 
    1078           0 :     rv = SerializePrologue(aStream);
    1079           0 :     if (NS_FAILED(rv))
    1080           0 :         return rv;
    1081             : 
    1082             :     while (1) {
    1083           0 :         bool hasMore = false;
    1084           0 :         resources->HasMoreElements(&hasMore);
    1085           0 :         if (! hasMore)
    1086           0 :             break;
    1087             : 
    1088           0 :         nsCOMPtr<nsISupports> isupports;
    1089           0 :         resources->GetNext(getter_AddRefs(isupports));
    1090             : 
    1091           0 :         nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(isupports);
    1092           0 :         if (! resource)
    1093           0 :             continue;
    1094             : 
    1095           0 :         if (IsA(mDataSource, resource, kRDF_Bag) ||
    1096           0 :             IsA(mDataSource, resource, kRDF_Seq) ||
    1097           0 :             IsA(mDataSource, resource, kRDF_Alt)) {
    1098           0 :             rv = SerializeContainer(aStream, resource);
    1099             :         }
    1100             :         else {
    1101           0 :             rv = SerializeDescription(aStream, resource);
    1102             :         }
    1103             : 
    1104           0 :         if (NS_FAILED(rv))
    1105           0 :             break;
    1106           0 :     }
    1107             : 
    1108           0 :     rv = SerializeEpilogue(aStream);
    1109             : 
    1110           0 :     return rv;
    1111             : }
    1112             : 
    1113             : 
    1114             : bool
    1115           0 : nsRDFXMLSerializer::IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType)
    1116             : {
    1117             :     nsresult rv;
    1118             : 
    1119             :     bool result;
    1120           0 :     rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, aType, true, &result);
    1121           0 :     if (NS_FAILED(rv)) return false;
    1122             : 
    1123           0 :     return result;
    1124             : }

Generated by: LCOV version 1.13