UNPKG

@jaricardodev/ews-javascript-api

Version:
547 lines (477 loc) 22.9 kB
import { EnumHelper, StringHelper } from "../ExtensionMethods"; import { EwsLogging } from '../Core/EwsLogging'; import { EwsServiceXmlWriter } from "../Core/EwsServiceXmlWriter"; import { EwsUtilities } from "../Core/EwsUtilities"; import { ExchangeService } from "../Core/ExchangeService"; import { ExchangeVersion } from "../Enumerations/ExchangeVersion"; import { FolderId } from "../ComplexProperties/FolderId"; import { InvalidOperationException } from '../Exceptions/InvalidOperationException'; import { ItemId } from "../ComplexProperties/ItemId"; import { PropertyException } from '../Exceptions/PropertyException'; import { ServiceVersionException } from '../Exceptions/ServiceVersionException'; import { Strings } from '../Strings'; import { UserConfigurationDictionary } from "../ComplexProperties/UserConfigurationDictionary"; import { UserConfigurationProperties } from "../Enumerations/UserConfigurationProperties"; import { WellKnownFolderName } from "../Enumerations/WellKnownFolderName"; import { XmlAttributeNames } from "../Core/XmlAttributeNames"; import { XmlElementNames } from "../Core/XmlElementNames"; import { XmlNamespace } from "../Enumerations/XmlNamespace"; export type base64String = string; /** * Represents an object that can be used to store user-defined configuration settings. */ export class UserConfiguration {//IJsonSerializable private static ObjectVersion: ExchangeVersion = ExchangeVersion.Exchange2010; // For consistency with ServiceObject behavior, access to ItemId is permitted for a new object. private static PropertiesAvailableForNewObject: UserConfigurationProperties = UserConfigurationProperties.BinaryData | UserConfigurationProperties.Dictionary | UserConfigurationProperties.XmlData; private static NoProperties: UserConfigurationProperties = <UserConfigurationProperties>0; // TODO: Consider using SimplePropertyBag class to store XmlData & BinaryData property values. private service: ExchangeService; private name: string; private parentFolderId: FolderId = null; private itemId: ItemId = null; private dictionary: UserConfigurationDictionary = null; private xmlData: base64String = null;//System.Byte[]; //info: base64 encoded value private binaryData: base64String = null;//System.Byte[]; private propertiesAvailableForAccess: UserConfigurationProperties = UserConfigurationProperties.Id; private updatedProperties: UserConfigurationProperties = UserConfigurationProperties.Id; /** * Indicates whether changes trigger an update or create operation. */ private isNew: boolean = false; /** * Gets the name of the user configuration. * internal set */ get Name(): string { return this.name; } set Name(value: string) { this.name = value; } /** * Gets the Id of the folder containing the user configuration. * internal set */ get ParentFolderId(): FolderId { return this.parentFolderId; } set ParentFolderId(value: FolderId) { this.parentFolderId = value; } /** * Gets the Id of the user configuration. */ get ItemId(): ItemId { return this.itemId; } /** * Gets the dictionary of the user configuration. */ get Dictionary(): UserConfigurationDictionary { return this.dictionary; } /** * Gets or sets the xml data of the user configuration. * ### base64 encoded value, not the memory stream or byte[] */ get XmlData(): base64String {//System.Byte[]; this.ValidatePropertyAccess(UserConfigurationProperties.XmlData); return this.xmlData; } set XmlData(value: base64String) { this.xmlData = value; this.MarkPropertyForUpdate(UserConfigurationProperties.XmlData); } /** * Gets or sets the binary data of the user configuration. * ### base64 encoded value, not the memory stream or byte[] */ get BinaryData(): base64String {//System.Byte[]; this.ValidatePropertyAccess(UserConfigurationProperties.BinaryData); return this.binaryData; } set BinaryData(value: base64String) { this.binaryData = value; this.MarkPropertyForUpdate(UserConfigurationProperties.BinaryData); } /** * Gets a value indicating whether this user configuration has been modified. */ get IsDirty(): boolean { return (this.updatedProperties != UserConfiguration.NoProperties) || this.dictionary.IsDirty; } /** * Initializes a new instance of **UserConfiguration** class. * * @param {ExchangeService} service The service to which the user configuration is bound. */ constructor(service: ExchangeService); /** * @internal Initializes a new instance of **UserConfiguration** class. * * @param {ExchangeService} service The service to which the user configuration is bound. * @param {UserConfigurationProperties} requestedProperties The properties requested for this user configuration. */ constructor(service: ExchangeService, requestedProperties: UserConfigurationProperties); constructor(service: ExchangeService, requestedProperties: UserConfigurationProperties = UserConfiguration.PropertiesAvailableForNewObject) { EwsUtilities.ValidateParam(service, "service"); if (service.RequestedServerVersion < UserConfiguration.ObjectVersion) { throw new ServiceVersionException( StringHelper.Format( Strings.ObjectTypeIncompatibleWithRequestVersion, "UserConfiguration", ExchangeVersion[UserConfiguration.ObjectVersion])); } this.service = service; this.isNew = true; this.InitializeProperties(requestedProperties); } /** * Binds to an existing user configuration and loads the specified properties. * Calling this method results in a call to EWS. * * @param {ExchangeService} service The service to which the user configuration is bound. * @param {string} name The name of the user configuration. * @param {FolderId} parentFolderId The Id of the folder containing the user configuration. * @param {UserConfigurationProperties} properties The properties to load. * @return {Promise<UserConfiguration>} A user configuration Instance :Promise. */ public static Bind(service: ExchangeService, name: string, parentFolderId: FolderId, properties: UserConfigurationProperties): Promise<UserConfiguration>; /** * Binds to an existing user configuration and loads the specified properties. * Calling this method results in a call to EWS. * * @param {ExchangeService} service The service to which the user configuration is bound. * @param {string} name The name of the user configuration. * @param {parentFolderName} parentFolderName The name of the folder containing the user configuration. * @param {UserConfigurationProperties} properties The properties to load. * @return {Promise<UserConfiguration>} A user configuration Instance :Promise. */ public static Bind(service: ExchangeService, name: string, parentFolderName: WellKnownFolderName, properties: UserConfigurationProperties): Promise<UserConfiguration>; public static Bind(service: ExchangeService, name: string, parentFolderIdOrName: FolderId | WellKnownFolderName, properties: UserConfigurationProperties): Promise<UserConfiguration> { let parentFolderId: FolderId = parentFolderIdOrName as FolderId; if (typeof parentFolderIdOrName === 'number') { parentFolderId = new FolderId(parentFolderIdOrName); } return service.GetUserConfiguration( name, parentFolderId, properties).then((result: UserConfiguration) => { result.isNew = false; return result; }); } /** * Deletes the user configuration. * Calling this method results in a call to EWS. * @return {Promise<void>} :Promise. */ Delete(): Promise<void> { if (this.isNew) { Promise.reject(new InvalidOperationException(Strings.DeleteInvalidForUnsavedUserConfiguration)); } else { return this.service.DeleteUserConfiguration(this.name, this.parentFolderId); } } /** * Gets the base64 property value. * * @param {base64String} bytes The bytes. * @return {string} [description] */ private GetBase64PropertyValue(bytes: base64String/*System.Byte[]*/): string { throw new Error("UserConfiguration.ts - GetBase64PropertyValue : Not implemented."); } /** * Initializes properties. * * /remarks/ InitializeProperties is called in 3 cases: * . Create new object: From the UserConfiguration constructor. * . Bind to existing object: Again from the constructor. The constructor is called eventually by the GetUserConfiguration request. * . Refresh properties: From the Load method. * * @param {UserConfigurationProperties} requestedProperties The properties requested for this UserConfiguration. */ private InitializeProperties(requestedProperties: UserConfigurationProperties): void { this.itemId = null; this.dictionary = new UserConfigurationDictionary(); this.xmlData = null; this.binaryData = null; this.propertiesAvailableForAccess = requestedProperties; this.ResetIsDirty(); } /** * Determines whether the specified property was updated. * * @param {UserConfigurationProperties} property property to evaluate. * @return {boolean} Boolean indicating whether to send the property Xml. */ private IsPropertyUpdated(property: UserConfigurationProperties): boolean { let isPropertyDirty: boolean = false; let isPropertyEmpty: boolean = false; switch (property) { case UserConfigurationProperties.Dictionary: isPropertyDirty = this.Dictionary.IsDirty; isPropertyEmpty = this.Dictionary.Count == 0; break; case UserConfigurationProperties.XmlData: isPropertyDirty = (property & this.updatedProperties) == property; isPropertyEmpty = (this.xmlData == null) || (this.xmlData.length == 0); break; case UserConfigurationProperties.BinaryData: isPropertyDirty = (property & this.updatedProperties) == property; isPropertyEmpty = (this.binaryData == null) || (this.binaryData.length == 0); break; default: EwsLogging.Assert( false, "UserConfiguration.IsPropertyUpdated", "property not supported: " + EnumHelper.ToString(UserConfigurationProperties, property)); break; } // Consider the property updated, if it's been modified, and either // . there's a value or // . there's no value but the operation is update. return isPropertyDirty && ((!isPropertyEmpty) || (!this.isNew)); } /** * Loads the specified properties on the user configuration. * Calling this method results in a call to EWS. * @return {Promise<void>} :Promise. */ Load(properties: UserConfigurationProperties): Promise<void> { this.InitializeProperties(properties); return this.service.LoadPropertiesForUserConfiguration(this, properties); } /** * @internal Loads service object from XML. * * @param {any} jsObject Json Object converted from XML. * @param {ExchangeService} service The service. */ LoadFromXmlJsObject(jsObject: any, service: ExchangeService): void { for (let key in jsObject) { switch (key) { case XmlElementNames.UserConfigurationName: let userConfigName: string = jsObject[key]; let responseName: string = userConfigName[XmlAttributeNames.Name]; EwsLogging.Assert( StringHelper.Compare(this.name, responseName, /** StringComparison.Ordinal*/ false) == 0, "UserConfiguration.LoadFromXmlJsObject", "UserConfigurationName does not match: Expected: " + this.name + " Name in response: " + responseName); break; case XmlElementNames.ItemId: this.itemId = new ItemId(); this.itemId.LoadFromXmlJsObject(jsObject[key], service); break; case XmlElementNames.Dictionary: (this.dictionary).CreateFromXMLJsObjectCollection(jsObject[key], service); break; case XmlElementNames.XmlData: this.xmlData = jsObject[key]; //Convert.FromBase64String(jsObject.ReadAsString(key)); //info: no need to convert, using base64 as is break; case XmlElementNames.BinaryData: this.binaryData = jsObject[key]; //Convert.FromBase64String(jsObject.ReadAsString(key)); //info: no need to convert, using base64 as is break; default: break; } } } /** * Adds the passed property to updatedProperties. * * @param {UserConfigurationProperties} property Property to update. */ private MarkPropertyForUpdate(property: UserConfigurationProperties): void { this.updatedProperties |= property; this.propertiesAvailableForAccess |= property; } /** * Resets flags to indicate that properties haven't been modified. */ private ResetIsDirty(): void { this.updatedProperties = UserConfiguration.NoProperties; this.dictionary.IsDirty = false; } /** * Saves the user configuration. Calling this method results in a call to EWS. * * @param {string} name The name of the user configuration. * @param {WellKnownFolderName} parentFolderName The Id of the folder in which to save the user configuration. * @return {Promise<void>} :Promise. */ Save(name: string, parentFolderName: WellKnownFolderName): Promise<void>; /** * Saves the user configuration. Calling this method results in a call to EWS. * * @param {string} name The name of the user configuration. * @param {FolderId} parentFolderId The Id of the folder in which to save the user configuration. * @return {Promise<void>} :Promise. */ Save(name: string, parentFolderId: FolderId): Promise<void>; Save(name: string, parentFolderIdOrName: FolderId | WellKnownFolderName): Promise<void> { let parentFolderId: FolderId = parentFolderIdOrName as FolderId; if (typeof parentFolderIdOrName === 'number') { parentFolderId = new FolderId(parentFolderIdOrName); } EwsUtilities.ValidateParam(name, "name"); EwsUtilities.ValidateParam(parentFolderId, "parentFolderId"); parentFolderId.Validate(this.service.RequestedServerVersion); if (!this.isNew) { throw new InvalidOperationException(Strings.CannotSaveNotNewUserConfiguration); } this.parentFolderId = parentFolderId; this.name = name; return this.service.CreateUserConfiguration(this).then(() => { this.isNew = false; this.ResetIsDirty(); }); } /** * Updates the user configuration by applying local changes to the Exchange server. * Calling this method results in a call to EWS. * @return {Promise<void>} :Promise. */ Update(): Promise<void> { if (this.isNew) { Promise.reject(new InvalidOperationException(Strings.CannotUpdateNewUserConfiguration)); } if (this.IsPropertyUpdated(UserConfigurationProperties.BinaryData) || this.IsPropertyUpdated(UserConfigurationProperties.Dictionary) || this.IsPropertyUpdated(UserConfigurationProperties.XmlData)) { return this.service.UpdateUserConfiguration(this).then(() => { this.ResetIsDirty(); }); } else { this.ResetIsDirty(); return Promise.resolve(); } } /** * Determines whether the specified property may be accessed. * * @param {UserConfigurationProperties} property Property to access. */ ValidatePropertyAccess(property: UserConfigurationProperties): void { if ((property & this.propertiesAvailableForAccess) != property) { throw new PropertyException(Strings.MustLoadOrAssignPropertyBeforeAccess, EnumHelper.ToString(UserConfigurationProperties, property)); } } /** * Writes the BinaryData property to Xml. * * @param {EwsServiceXmlWriter} writer The writer. */ private WriteBinaryDataToXml(writer: EwsServiceXmlWriter): void { EwsLogging.Assert( writer != null, "UserConfiguration.WriteBinaryDataToXml", "writer is null"); UserConfiguration.WriteByteArrayToXml( writer, this.binaryData, XmlElementNames.BinaryData); } /** * Writes a byte array to Xml. * * @param {EwsServiceXmlWriter} writer The writer. * @param {base64String} byteArray Byte array to write #base64 string. * @param {string} xmlElementName Name of the Xml element. */ private static WriteByteArrayToXml(writer: EwsServiceXmlWriter, byteArray: base64String/*System.Byte[]*/, xmlElementName: string): void { EwsLogging.Assert( writer != null, "UserConfiguration.WriteByteArrayToXml", "writer is null"); EwsLogging.Assert( xmlElementName != null, "UserConfiguration.WriteByteArrayToXml", "xmlElementName is null"); writer.WriteStartElement(XmlNamespace.Types, xmlElementName); if (byteArray != null && byteArray.length > 0) { //writer.WriteValue(Convert.ToBase64String(byteArray), xmlElementName); //info: no need to convert to string, it is already base 64 encoded string writer.WriteValue(byteArray, xmlElementName); } writer.WriteEndElement(); } /** * @internal Writes to XML. * * @param {EwsServiceXmlWriter} writer The writer. * @param {XmlNamespace} xmlNamespace The XML namespace. * @param {string} xmlElementName Name of the XML element. */ WriteToXml(writer: EwsServiceXmlWriter, xmlNamespace: XmlNamespace, xmlElementName: string): void { EwsLogging.Assert( writer != null, "UserConfiguration.WriteToXml", "writer is null"); EwsLogging.Assert( xmlElementName != null, "UserConfiguration.WriteToXml", "xmlElementName is null"); writer.WriteStartElement(xmlNamespace, xmlElementName); // Write the UserConfigurationName element UserConfiguration.WriteUserConfigurationNameToXml( writer, XmlNamespace.Types, this.name, this.parentFolderId); // Write the Dictionary element if (this.IsPropertyUpdated(UserConfigurationProperties.Dictionary)) { this.dictionary.WriteToXml(writer, XmlElementNames.Dictionary); } // Write the XmlData element if (this.IsPropertyUpdated(UserConfigurationProperties.XmlData)) { this.WriteXmlDataToXml(writer); } // Write the BinaryData element if (this.IsPropertyUpdated(UserConfigurationProperties.BinaryData)) { this.WriteBinaryDataToXml(writer); } writer.WriteEndElement(); } /** * @internal Writes to Xml. * * @param {EwsServiceXmlWriter} writer The writer. * @param {XmlNamespace} xmlNamespace The XML namespace. * @param {string} name The user configuration name. * @param {FolderId} parentFolderId The Id of the folder containing the user configuration. */ static WriteUserConfigurationNameToXml(writer: EwsServiceXmlWriter, xmlNamespace: XmlNamespace, name: string, parentFolderId: FolderId): void { EwsLogging.Assert( writer != null, "UserConfiguration.WriteUserConfigurationNameToXml", "writer is null"); EwsLogging.Assert( name != null, "UserConfiguration.WriteUserConfigurationNameToXml", "name is null"); EwsLogging.Assert( parentFolderId != null, "UserConfiguration.WriteUserConfigurationNameToXml", "parentFolderId is null"); writer.WriteStartElement(xmlNamespace, XmlElementNames.UserConfigurationName); writer.WriteAttributeValue(XmlAttributeNames.Name, name); parentFolderId.WriteToXml(writer); writer.WriteEndElement(); } /** * Writes the XmlData property to Xml. * * @param {EwsServiceXmlWriter} writer The writer. */ private WriteXmlDataToXml(writer: EwsServiceXmlWriter): void { EwsLogging.Assert( writer != null, "UserConfiguration.WriteXmlDataToXml", "writer is null"); UserConfiguration.WriteByteArrayToXml( writer, this.xmlData, XmlElementNames.XmlData); } }