Week 23 contribution of PDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License
"Eclipse Public License v1.0" which accompanies this distribution,
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
Nokia Corporation - initial contribution.
Contributors:
-->
<!DOCTYPE concept
PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept xml:lang="en" id="GUID-38A656D3-F830-5E26-8167-3638B6BC5DF6"><title>How to restore a compound object</title><prolog><metadata><keywords/></metadata></prolog><conbody><p>The protocol for restoring a compound object is the <codeph>RestoreL()</codeph> function. This is true whether the object has been stored in-line or out-of-line, and should be prototyped as:</p> <codeblock id="GUID-AA727C46-3D5E-53D2-8697-721ED1F0D05C" xml:space="preserve">void RestoreL(CStreamStore& aStore,TStreamId anId);</codeblock> <p>The function takes a reference to the store in which streams are stored and a stream ID. In some cases, the design of a class may be such that it maintains a pointer or reference to the store. In this event, the <codeph>CStreamStore</codeph> argument would be redundant.</p> <section><title>Restoring components stored in-line</title> <p>If an object's components have been stored in-line, then all of these components have been written to the same single stream.</p> <p>For the example class <codeph>CCompound</codeph>, defined as:</p> <codeblock id="GUID-1BB27256-2ADE-516E-8213-4B901A64BB30" xml:space="preserve">CCompound class : public CBase
{
...
TInt iDdata;
CComponentA* iCompA;
CComponentB* iCompB;
...
}</codeblock> <p>RestoreL() is implemented as: </p> <codeblock id="GUID-AD51C522-3734-5827-938A-0595DD012A79" xml:space="preserve">void CCompound::RestoreL(CStreamStore& aStore,TStreamId anId)
{
RStoreReadStream instream;
instream.OpenLC(aStore,anId);
InternalizeL(instream);
CleanupStack::PopAndDestroy();
}</codeblock> <p>where the stream ID passed to the function is the ID of the single stream containing the data.</p> </section> <section><title>Restoring components stored out-of-line</title> <p>If an object's components have been stored out-of-line, then all of these components have been written to separate streams.</p> <p>For the example class <codeph>CCompound</codeph>, defined as:</p> <codeblock id="GUID-345E2356-1AD3-5CF4-9847-7AE6C383448C" xml:space="preserve">CCompound class : public CBase
{
...
TInt iDdata;
TSwizzle<CComponentA> iCompA;
TSwizzle<CComponentB> iCompB;
...
}</codeblock> <p>RestoreL() is implemented as:</p> <codeblock id="GUID-81FEC5E3-EDDE-5596-BE12-420CC5D19F91" xml:space="preserve">void CCompound::RestoreL(CStreamStore& aStore,TStreamId anId)
{
RStoreReadStream stream; // Construct a read stream.
stream.OpenLC(aStore,anId); // Open the head stream.
InternalizeL(stream); // Internalise top level stream containing CCompound
// and the IDs of its components.
RestoreComponentsL(aStore); // Restore components.
CleanupStack::PopAndDestroy();
}
</codeblock> <p>where the stream ID passed to the function is the ID of the head stream.</p> <p>InternalizeL() internalises CCompound's data members and the stream IDs of its components:</p> <codeblock id="GUID-36C860E3-9552-52C4-AD54-53B614DE7B8A" xml:space="preserve">void CCompound::InternalizeL(RReadStream& aStream)
{
aStream >> iDataA;
aStream >> iCompA;
aStream >> iCompB;
}</codeblock> <p><codeph>RestoreComponentsL()</codeph> constructs each component object and restores them from their respective stream networks. </p> <codeblock id="GUID-FD539747-82E8-5EF1-ADF0-E5101AE8EDA3" xml:space="preserve">void CCompound::RestoreComponentsL(CStreamStore& aStore)
{
CComponentA* ptrA = new (ELeave) CComponentA;
CleanupStack::PushL(ptrA);
ptrA->RestoreL(aStore,iCompA.AsId());
iCompA = ptrA;
CleanupStack::Pop();
CComponentB* ptrB = new (ELeave) CComponentB;
CleanupStack::PushL(ptrB);
ptrB->RestoreL(aStore,iCompB.AsId());
iCompB = ptrB CleanupStack::Pop();
}</codeblock> <p>In general, an application might want to defer the loading of some components. This would mean either changing the implementation of <codeph>RestoreComponents()</codeph> or adding new functionality to the class. The use of Swizzles is important here as they simplify the handling of the dual representation of an object as a pointer to an in-memory object or as an ID of a stream.</p> <p>Typically, an application might use code such as:</p> <codeblock id="GUID-E2D26E4E-02C0-5E89-8D82-0F628101011C" xml:space="preserve">if (iCompA.IsId())
{
iCompA = CComponentA::NewL(iStore,iCompA.AsId());
}</codeblock> <p>to test whether the component is currently represented by a stream ID or by a pointer to an in-memory object. If a stream ID, then the component would be restored. In this small code fragment, an overloaded <codeph>NewL()</codeph> function is used both to construct and to restore the component object. Once this code has executed, the component is represented by a pointer.</p> <p><b>See also</b> </p> <p><xref href="GUID-C1AA34CB-D63D-57E3-87F6-28AD22537D21.dita">Store map</xref> </p> <p><xref href="GUID-53112730-5871-5920-8861-D2F6BF1595BC.dita">Swizzles and deferred loading</xref> </p> </section> </conbody></concept>