calendarengines/versit2/src/ICalBase.cpp
changeset 0 f979ecb2b13e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarengines/versit2/src/ICalBase.cpp	Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,685 @@
+/*
+* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+* Description:   Class implementing the definition of CICalBase. This class is base class from which ICal class has been derived.
+*
+*/
+
+
+
+// Class include.
+#include "ICalBase.h"	// CICalBase
+
+//debug
+#include "calendarengines_debug.h"
+
+// User includes.
+#include "ICalComponent.h"			// CICalComponent
+#include "ICalContentLineReader.h"	// CICalContentLineReader
+#include "ICalContentLineWriter.h"	// CICalContentLineWriter
+#include "ICalErrors.h"				// Error codes
+#include "ICalKeyWords.h"			// Literals
+#include "ICalProperty.h"			// CICalProperty
+#include "ICalUtil.h"				// NICalUtil
+#include "ICalValue.h"				// CICalValue
+
+using namespace NICalUtil;
+
+/**
+Destructor.
+@internalTechnology
+*/
+CICalBase::~CICalBase()
+	{
+	TRACE_ENTRY_POINT;
+	
+	iComponents.ResetAndDestroy();
+	iProperties.ResetAndDestroy();
+	
+	TRACE_EXIT_POINT;
+	}
+	
+/**
+Creates a new property with a value from the given parameters, adds it to 
+this object and returns a modifiable reference to it.
+@param aName Name of the property to add.
+@param aValue Value of the property to add.
+@return A reference to a new property owned by this object.
+@leave Leaves with KErrUnsupportedProperty if the given property is not valid.
+for this component.
+@publishedPartner
+*/
+EXPORT_C CICalProperty& CICalBase::AddPropertyL(const TDesC& aName, const TDesC& aValue)
+	{
+	TRACE_ENTRY_POINT;
+	
+	CICalProperty* property = CreatePropertyL(aName);	// Not taking ownership.
+	
+	if (!property)
+		{
+		User::Leave(KErrUnsupportedProperty);	
+		}
+	
+	property->AddValueL(aValue);
+	
+	TRACE_EXIT_POINT;
+	return *property;
+	}
+
+/**
+Creates a new property with a value and adds it to this object, returning a
+reference to it. Ownership of aValue is transferred and it will be deleted if
+this function leaves.
+@leave Leaves with KErrPropertyHasNoValue if aValue is Null.
+@leave Leaves with KErrUnsupportedProperty if the given property is not valid.
+@return A new property
+@publishedPartner
+*/
+EXPORT_C CICalProperty& CICalBase::AddPropertyL(const TDesC& aName, CICalValue* aValue)
+	{
+	TRACE_ENTRY_POINT;
+	
+	if (!aValue)
+		{
+		User::Leave(KErrPropertyHasNoValue);
+		}
+		
+	CleanupStack::PushL(aValue);
+	CICalProperty* property = CreatePropertyL(aName);	// Not taking ownership.
+	
+	if (!property)
+		{
+		User::Leave(KErrUnsupportedProperty);	
+		}
+	
+	CleanupStack::Pop(aValue);
+	property->AddValueL(aValue);
+	
+	TRACE_EXIT_POINT;
+	return *property;
+	}
+
+/**
+Creates a new component, adds it to this object, and returns a modifiable
+reference to it.
+@param aType The type of component to be created.
+@return A new component
+@leave Leaves with KErrUnsupportedComponent if the given component is not a
+valid subcomponent for this object.
+@publishedPartner
+*/
+EXPORT_C CICalComponent& CICalBase::AddComponentL(TICalComponentType aType)
+	{
+	TRACE_ENTRY_POINT;
+	
+	CICalComponent* component = CreateComponentL(aType);	// Not taking ownership.
+	
+	if (!component)
+		{
+		User::Leave(KErrUnsupportedComponent);
+		}
+	TRACE_EXIT_POINT;	
+	return *component;
+	}
+	
+/**
+Access function for the component array.
+@return The array of components as a constant reference.
+@publishedPartner
+*/
+EXPORT_C const RPointerArray<CICalComponent>& CICalBase::Components() const
+	{
+	TRACE_ENTRY_POINT;
+	TRACE_EXIT_POINT;
+	return iComponents; 
+	}
+
+/**
+Access function for the property array.
+@return The array of properties as a constant reference.
+@publishedPartner
+*/
+EXPORT_C const RPointerArray<CICalProperty>& CICalBase::Properties() const
+	{
+	TRACE_ENTRY_POINT;
+	TRACE_EXIT_POINT;
+	return iProperties;
+	}
+
+/**
+Returns the descriptor form of this component type.
+@return The descriptor form of this component type.
+@publishedPartner
+*/
+EXPORT_C const TDesC& CICalBase::TypeStringL() const
+	{
+	TRACE_ENTRY_POINT;
+	TRACE_EXIT_POINT;
+	return TypeStringL(iComponentType);
+	}
+	
+/**
+Access method returning the concrete type as an enumeration.
+@return The type of the concrete derived class.
+@publishedPartner
+*/
+EXPORT_C CICalBase::TICalComponentType CICalBase::Type() const
+	{
+	TRACE_ENTRY_POINT;
+	TRACE_EXIT_POINT;
+	return iComponentType;
+	}
+	
+/**
+Checks for a component already existing in current object's sub-components
+@param aType The type of the component to check.
+@return ETrue if the property does exist, EFalse otherwise
+@publishedPartner
+*/
+EXPORT_C TBool CICalBase::ComponentExists(TICalComponentType aType) const
+	{
+	const TInt count = iComponents.Count();
+	
+	for (TInt i = 0; i < count; i++)
+		{
+		if (iComponents[i]->Type() == aType)
+			{
+			TRACE_EXIT_POINT;
+			return ETrue;
+			}
+		}
+	
+	TRACE_EXIT_POINT;	
+	return EFalse;
+	}
+
+/**
+Finds the first property with a particular name and returns a pointer to it.
+Ownership is not passed out.
+@param aName The name of the property to search for.
+@return A pointer to the property, or NULL.
+@publishedPartner
+*/
+EXPORT_C const CICalProperty* CICalBase::FindProperty(const TDesC& aName) const
+	{
+	TRACE_ENTRY_POINT;
+	
+	const TInt count = iProperties.Count();
+	
+	for (TInt p = 0; p < count; ++p)
+		{
+		if (iProperties[p]->Type().CompareF(aName) == 0)
+			{
+			TRACE_EXIT_POINT;
+			return iProperties[p];
+			}
+		}
+	
+	TRACE_EXIT_POINT;
+	return NULL;
+	}
+
+/**
+Takes a line reader and reads lines from it until the end of the component is
+located. Any other END:, or an end of file, are treated as errors.
+@param aReader The line reader to read from.
+@leave Leaves with KErrCorrupt if the component is corrupt.
+@internalTechnology
+*/
+void CICalBase::InternalizeL(CICalContentLineReader& aReader)
+	{
+	TRACE_ENTRY_POINT;
+	
+	TPtrC line;
+	TPtrC name;
+	TPtrC parameters;
+	TPtrC values;
+	
+	TInt error(aReader.GetNextContentLine(line));
+
+	while (error == KErrNone)
+		{
+		if (ExtractSectionsL(line, name, parameters, values) == KErrNone)
+			{	
+			if (name.CompareF(KICalBegin) == 0)
+				{
+				// This is the start of a component:
+				
+				TICalComponentType type(TypeFromNameL(values));
+				
+				if (type == EICalInvalid)
+					{
+					aReader.SkipComponentL(values);
+					}
+				else
+					{
+					CICalComponent* component = CreateComponentL(type);	// Not taking ownership.
+					
+					if (component)
+						{
+						component->InternalizeL(aReader);	
+						}
+					else
+						{
+						// This component cannot be nested - ignore it
+						aReader.SkipComponentL(values);
+						}
+					}
+				}
+			else if (name.CompareF(KICalEnd) == 0)
+				{
+				// This is the end of a component.
+				if (values.CompareF(TypeStringL(iComponentType)) != 0)
+					{
+					User::Leave(KErrCorrupt);	// This is the end of a different component!
+					}
+				break;
+				}
+			else
+				{
+				// This is a property
+				
+				// Only allow properties with at least one value - if there is no value then
+				// ignore the property and continue.
+				if (values.Length() > 0)
+					{	
+					CICalProperty* property = CreatePropertyL(name); // Not taking ownership
+					if (property)
+						{
+						if (name.CompareF(KICalRRule) == 0)
+							{
+							// This is a special case - commas have a different meaning.
+							ExtractParametersL(parameters, *property);
+							property->AddValueL(values);
+							}
+						else if (name.CompareF(KICalCategories) == 0)
+							{
+							// Outlook escapes the comma separators between categories.
+							// This is not part of the iCal specification.
+							ExtractParametersL(parameters, *property);
+							ExtractPropertyValuesL(values, *property, EEscapeValueSeparators);
+							}
+						else if (name.CompareF(KICalTzid) == 0)
+							{
+							// Outlook doesn't escape commas in TZID fields.
+							// This is not part of the iCal specification.
+							ExtractParametersL(parameters, *property);
+							property->AddValueL(values);
+							}
+						else
+							{
+							ExtractPropertyL(parameters, values, *property);
+							}
+						
+						// Remove property if it doesn't have a value.
+						if (property->Values().Count() == 0)
+							{
+							TInt index(iProperties.Find(property));
+							
+							if (index >= 0)
+								{
+								iProperties.Remove(index);
+								}
+								
+							delete property;
+							}
+						else
+							{
+							// If the property is a method, remember it.
+							if (name.CompareF(KICalMethod) == 0)
+								{
+								TPtrC val;
+								val.Set(property->Values()[0]->TextL());
+								if (val.CompareF(KICalPublish) == 0)
+									{
+									iMethod = CICalBase::EMethodPublish;
+									}
+								else if (val.CompareF(KICalRequest) == 0)
+									{
+									iMethod = CICalBase::EMethodRequest;
+									}
+								else if (val.CompareF(KICalReply) == 0)
+									{
+									iMethod = CICalBase::EMethodReply;
+									}
+								else if (val.CompareF(KICalAdd) == 0)
+									{
+									iMethod = CICalBase::EMethodAdd;
+									}
+								else if (val.CompareF(KICalCancel) == 0)
+									{
+									iMethod = CICalBase::EMethodCancel;
+									}
+								else if (val.CompareF(KICalRefresh) == 0)
+									{
+									iMethod = CICalBase::EMethodRefresh;
+									}
+								else if (val.CompareF(KICalCounter) == 0)
+									{
+									iMethod = CICalBase::EMethodCounter;
+									}
+								else if (val.CompareF(KICalDeclineCounter) == 0)
+									{
+									iMethod = CICalBase::EMethodDeclineCounter;
+									}
+								else
+									{
+									User::Leave(KErrCorrupt);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			
+		error = aReader.GetNextContentLine(line);
+		}
+		
+	if ((error != KErrNone) && (error != KErrEof))
+		{
+		User::Leave(error);
+		}
+		
+    TRACE_EXIT_POINT;
+	}
+
+/**
+Takes a line writer and exports this component, including all owned properties
+and sub components, to it.
+@param aWriter the writer to export to.
+@internalTechnology
+*/
+void CICalBase::ExternalizeL(CICalContentLineWriter& aWriter) const
+	{
+	TRACE_ENTRY_POINT;
+	
+	aWriter.AppendL(KICalBegin());
+	aWriter.AppendL(KICalColon());
+	aWriter.AppendL(TypeStringL(iComponentType));
+	
+	aWriter.WriteContentLineL();
+	
+	// Externalize any component properties:
+	TInt count(iProperties.Count());
+	
+	for (TInt prop = 0; prop < count; ++prop)
+		{
+		// Only externalise properties with a value.
+		if (iProperties[prop]->Values().Count() > 0)
+			{
+			iProperties[prop]->ExternalizeL(aWriter);
+			}
+		}
+
+	// Externalize any child components:	
+	count = iComponents.Count();
+	for (TInt comp = 0; comp < count; ++comp)
+		{
+		iComponents[comp]->ExternalizeL(aWriter);
+		}
+
+	aWriter.AppendL(KICalEnd());
+	aWriter.AppendL(KICalColon());
+	aWriter.AppendL(TypeStringL(iComponentType));
+	aWriter.WriteContentLineL();
+	
+	TRACE_EXIT_POINT;
+	}
+
+/**
+Converts between a TICalComponentType and the type as a descriptor. 
+@param aName The type as a descriptor.
+@return The type as an enumeration.
+@leave KErrCorrupt if this is not a valid type.
+@internalTechnology
+*/
+CICalBase::TICalComponentType CICalBase::TypeFromNameL(const TDesC& aName)
+	{
+	TRACE_ENTRY_POINT;
+	
+	TICalComponentType type(EICalInvalid);
+
+	if (aName.CompareF(KICalVCalendar) == 0)
+		{
+		type = EICalCalendar;
+		}
+	else if (aName.CompareF(KICalEvent) == 0)
+		{
+		type = EICalEvent;
+		}
+	else if (aName.CompareF(KICalTodo) == 0)
+		{
+		type = EICalTodo;
+		}
+	else if (aName.CompareF(KICalJournal) == 0)
+		{
+		type = EICalJournal;
+		}
+	else if (aName.CompareF(KICalAlarm) == 0)
+		{
+		type = EICalAlarm;
+		}
+	else if (aName.CompareF(KICalTimeZone) == 0)
+		{
+		type = EICalTimeZone;
+		}
+	else if (aName.CompareF(KICalFreeBusy) == 0)
+		{
+		type = EICalFreeBusy;
+		}
+	else if (aName.CompareF(KICalStandard) == 0)
+		{
+		type = EICalStandard;
+		}
+	else if (aName.CompareF(KICalDaylight) == 0)
+		{
+		type = EICalDaylight;
+		}
+	else
+		{
+		type = EICalInvalid;
+		}
+	
+	TRACE_EXIT_POINT;
+	return type;
+	}
+	
+/**
+Constructor
+@internalTechnology
+*/
+CICalBase::CICalBase()
+	{
+	TRACE_ENTRY_POINT;
+	TRACE_EXIT_POINT;
+	}
+	
+/**
+Converts between a TICalComponentType and the type as a descriptor.
+@param aType The type as an enumeration.
+@return The type as a descriptor.
+@leave KErrCorrupt if this is not a valid type.
+@internalTechnology
+*/
+const TDesC& CICalBase::TypeStringL(TICalComponentType aType) const
+	{
+	TRACE_ENTRY_POINT;
+	
+	switch (aType)
+		{
+		case EICalCalendar:
+		    TRACE_EXIT_POINT;
+			return KICalVCalendar();
+		case EICalEvent:
+		    TRACE_EXIT_POINT;
+			return KICalEvent();
+		case EICalJournal:
+		    TRACE_EXIT_POINT;
+			return KICalJournal();
+		case EICalAlarm:
+		    TRACE_EXIT_POINT;
+			return KICalAlarm();
+		case EICalFreeBusy:
+		    TRACE_EXIT_POINT;
+			return KICalFreeBusy();
+		case EICalTodo:
+		    TRACE_EXIT_POINT;
+			return KICalTodo();
+		case EICalTimeZone:
+		    TRACE_EXIT_POINT;
+			return KICalTimeZone();
+		case EICalStandard:
+		    TRACE_EXIT_POINT;
+			return KICalStandard();
+		case EICalDaylight:
+		    TRACE_EXIT_POINT;
+			return KICalDaylight();
+		case EICalInvalid:
+			// Fall through...
+		default:
+			User::Leave(KErrCorrupt);
+			break;	
+		};
+
+    TRACE_EXIT_POINT;		
+	return KNullDesC;	// Never reached.
+	}
+
+/**
+Private implementation of AddComponentL(), used directly during InternalizeL().
+Checks that the given component can be nested within this component. The returned
+pointer will be NULL if it is not supported - the calling function does NOT take
+ownership of the returned pointer.
+@param aType The type of component to be created.
+@return pointer to newly added component. This will be NULL if the property is
+not supported.
+@leave Leaves if there is an error adding a new component.
+@internalTechnology
+*/
+CICalComponent* CICalBase::CreateComponentL(TICalComponentType aType)
+	{
+	TRACE_ENTRY_POINT;
+	
+	CICalComponent* component = NULL;
+	
+	if (ValidateComponent(aType))
+		{
+		component = CICalComponent::CreateICalComponentLC(aType, iMethod);
+		User::LeaveIfError(iComponents.Append(component));
+		CleanupStack::Pop(component);
+		}
+	
+	TRACE_EXIT_POINT;	
+	return component;	
+	}
+	
+/**
+Private implementation of AddPropertyL(), used directly during InternalizeL().
+Checks that the given property is supported by this component. The returned
+pointer will be NULL if it is not supported - the calling function does NOT
+take ownership of the returned pointer.
+@param aName Name of the property to add.
+@return pointer to newly added property. This will be NULL if the property is
+not supported.
+@leave Leaves if there is an error adding a new property.
+@internalTechnology
+*/
+CICalProperty* CICalBase::CreatePropertyL(const TDesC& aName)
+	{
+	TRACE_ENTRY_POINT;
+	
+	CICalProperty* property = NULL;
+	
+	if (ValidateProperty(aName))
+		{
+		property = CICalProperty::NewLC(aName);
+		User::LeaveIfError(iProperties.Append(property));
+		CleanupStack::Pop(property);
+		}
+	
+	TRACE_EXIT_POINT;	
+	return property;
+	}
+
+TBool CICalBase::ValidateProperty(const TDesC& aName) const
+	{
+	TRACE_ENTRY_POINT;
+	
+	if (
+	//Not checking properties in these components here...
+	(iComponentType == EICalCalendar) || (iComponentType == EICalAlarm) || 
+	(iComponentType == EICalTimeZone) || (iComponentType == EICalDaylight) || 
+	(iComponentType == EICalStandard) || (iComponentType == EICalJournal) ||
+	(iComponentType == EICalEvent) || (iComponentType == EICalTodo) ||
+	
+	//If no METHOD property exists, then RFC2446 does not apply...
+	(iComponentMethodBitMask & EMaskEventNone)    ||
+	(iComponentMethodBitMask & EMaskTodoNone)     ||
+	(iComponentMethodBitMask & EMaskJournalNone)  ||
+	(iComponentMethodBitMask & EMaskFreeBusyNone) ||
+	
+	//Validate the property against RFC2446	
+	((iComponentMethodBitMask & EICalAttendeeFlags) && (aName.CompareF(KICalAttendee) == 0)) ||
+	((iComponentMethodBitMask & EICalDtStampFlags) && (aName.CompareF(KICalDtstamp) == 0)) ||
+	((iComponentMethodBitMask & EICalDtStartFlags) && (aName.CompareF(KICalDtstart) == 0)) ||
+	((iComponentMethodBitMask & EICalOrganizerFlags) && (aName.CompareF(KICalOrganizer) == 0)) ||
+	((iComponentMethodBitMask & EICalSummaryFlags) && (aName.CompareF(KICalSummary) == 0)) ||
+	((iComponentMethodBitMask & EICalUIDFlags) && (aName.CompareF(KICalUid) == 0)) ||
+	((iComponentMethodBitMask & EICalRecurrenceIdFlags) && (aName.CompareF(KICalRecurrenceId) == 0)) ||
+	((iComponentMethodBitMask & EICalSequenceFlags) && (aName.CompareF(KICalSequence) == 0)) ||
+	((iComponentMethodBitMask & EICalAttachFlags) && (aName.CompareF(KICalAttach) == 0)) ||
+	((iComponentMethodBitMask & EICalCategoriesFlags) && (aName.CompareF(KICalCategories) == 0)) ||
+	((iComponentMethodBitMask & EICalClassFlags) && (aName.CompareF(KICalClass) == 0)) ||
+	((iComponentMethodBitMask & EICalCommentFlags) && (aName.CompareF(KICalComment) == 0)) ||
+	((iComponentMethodBitMask & EICalContactFlags) && (aName.CompareF(KICalContact) == 0)) ||
+	((iComponentMethodBitMask & EICalCreatedFlags) && (aName.CompareF(KICalCreated) == 0)) ||
+	((iComponentMethodBitMask & EICalDescriptionFlags) && (aName.CompareF(KICalDescription) == 0)) ||
+	((iComponentMethodBitMask & EICalDtEndFlags) && (aName.CompareF(KICalDtend) == 0)) ||
+	((iComponentMethodBitMask & EICalDurationFlags) && (aName.CompareF(KICalDuration) == 0)) ||
+	((iComponentMethodBitMask & EICalExDateFlags) && (aName.CompareF(KICalExdate) == 0)) ||
+	((iComponentMethodBitMask & EICalExRuleFlags) && (aName.CompareF(KICalExrule) == 0)) ||
+	((iComponentMethodBitMask & EICalGeoFlags) && (aName.CompareF(KICalGeo) == 0)) ||
+	((iComponentMethodBitMask & EICalLastModifiedFlags) && (aName.CompareF(KICalLastmodified) == 0)) ||
+	((iComponentMethodBitMask & EICalLocationFlags) && (aName.CompareF(KICalLocation) == 0)) ||
+	((iComponentMethodBitMask & EICalPriorityFlags) && (aName.CompareF(KICalPriority) == 0)) ||
+	((iComponentMethodBitMask & EICalRDateFlags) && (aName.CompareF(KICalRdate) == 0)) ||
+	((iComponentMethodBitMask & EICalRelatedToFlags) && (aName.CompareF(KICalRelatedto) == 0)) ||
+	((iComponentMethodBitMask & EICalRequestStatusFlags) && (aName.CompareF(KICalRequeststatus) == 0)) ||
+	((iComponentMethodBitMask & EICalResourcesFlags) && (aName.CompareF(KICalResources) == 0)) ||
+	((iComponentMethodBitMask & EICalRRuleFlags) && (aName.CompareF(KICalRRule) == 0)) ||
+	((iComponentMethodBitMask & EICalStatusFlags) && (aName.CompareF(KICalStatus) == 0)) ||
+	((iComponentMethodBitMask & EICalTranspFlags) && (aName.CompareF(KICalTransp) == 0)) ||
+	((iComponentMethodBitMask & EICalUrlFlags) && (aName.CompareF(KICalUrl) == 0)) ||
+	((iComponentMethodBitMask & EICalDueFlags) && (aName.CompareF(KICalDue) == 0)) ||
+	((iComponentMethodBitMask & EICalPercentCompleteFlags) && (aName.CompareF(KICalPercentcomplete) == 0)) ||
+	((iComponentMethodBitMask & EICalFreeBusyFlags) && (aName.CompareF(KICalFreebusy) == 0))
+	)
+		{
+		TRACE_EXIT_POINT;
+		return ValidatePropertyImpl(aName);
+		}
+	
+	//Allow all X-Properties
+	else if ((aName.Length() >= 2) && (aName.Left(2).CompareF(KICalXProperty) == 0))
+		{
+		TRACE_EXIT_POINT;
+		return ETrue;
+		}
+		
+	TRACE_EXIT_POINT;
+	return EFalse;
+	}
+
+// End of File
+