/// <summary>
 ///     Central place to set a transform definition, centralizing the
 /// call to the name manager.
 /// </summary>
 private void SetTransformDefinition( string transformLabel, TransformInstance definition )
 {
     _transformDefinitions[ transformLabel ] = definition;
 }
    /// <summary>
    /// Define a data transform object with the given object identification and
    /// labeled with the given name.
    /// </summary>
    /// <param name="transformClassName">Transform identification string</param>
    /// <param name="newTransformLabel">Label to use for new transform</param>
    internal void DefineTransform(string transformClassName, string newTransformLabel )
    {
        CheckDisposedStatus();

        // Check to see if transform name is obviously invalid
        CU.CheckStringAgainstNullAndEmpty( transformClassName, "Transform identifier name" );

        // Check to see if transform name is valid
        CU.CheckStringAgainstNullAndEmpty( newTransformLabel, "Transform label" );

        // Given transform name must not be a reserved string
        CU.CheckStringAgainstReservedName( newTransformLabel, "Transform label" );
        
        // Can't re-use an existing transform name
        if( TransformLabelIsDefined( newTransformLabel ) )
            throw new ArgumentException(
                SR.Get(SRID.TransformLabelInUse));

        // Create class the transform object will use to communicate to us
        TransformEnvironment transformEnvironment = new TransformEnvironment( this, newTransformLabel );

        // Create a TransformInstance object to represent this transform instance.
        TransformInstance newTransform = new TransformInstance(
            TransformIdentifierTypes_PredefinedTransformName,
            transformClassName,
            null,
            transformEnvironment );

        SetTransformDefinition( newTransformLabel, newTransform );

        // Create the transform object
        IDataTransform transformObject = InstantiateDataTransformObject(
                                                    TransformIdentifierTypes_PredefinedTransformName,
                                                    transformClassName,
                                                    transformEnvironment );
        newTransform.transformReference = transformObject;

        // If transform is not ready out-of-the-box, do an initialization run.
        //  Note: Transform is not required to be "ready" after this.  This is
        //  done for those transforms that need initialization work up-front.
        if( ! transformObject.IsReady )
        {
            CallTransformInitializers( 
                new TransformInitializationEventArgs(
                    transformObject,
                    null,
                    null,
                    newTransformLabel) 
                );
        }

        _dirtyFlag = true;

        return;
    }
    /// <summary>
    /// Read all transform definitions in one chunk
    /// </summary>
    // 

    void ReadTransformDefinitions()
    {
        ThrowIfIncorrectReaderVersion();

        StorageInfo dataSpaceStorage = 
            new StorageInfo( _associatedStorage, DataSpaceStorageName );
        StorageInfo transformDefinitionsStorage =
            new StorageInfo( dataSpaceStorage, TransformDefinitions );

        if( transformDefinitionsStorage.Exists )
        {
            // Read transform definitions from file
            foreach( StorageInfo transformStorage in transformDefinitionsStorage.GetSubStorages() )
            {
                // Read from primary stream
                StreamInfo transformPrimary = new StreamInfo(
                    transformStorage, TransformPrimaryInfo );

                using(Stream transformDefinition = transformPrimary.GetStream(FileMode.Open))
                {
                    using(BinaryReader definitionReader = new BinaryReader( transformDefinition, System.Text.Encoding.Unicode ))
                    {
                        int headerLength = definitionReader.ReadInt32(); // We don't actually do anything with HeaderLen at the moment
                        int transformType = definitionReader.ReadInt32();

                        if (headerLength < 0)
                            throw new FileFormatException(SR.Get(SRID.CorruptedData));

                        // Create a TransformInstance class using name from file
                        TransformInstance transformInstance =
                            new TransformInstance(transformType, CU.ReadByteLengthPrefixedDWordPaddedUnicodeString( definitionReader ) );

                        
                        int extraDataSize = checked ((int) (headerLength - transformDefinition.Position));

                        if (extraDataSize < 0)
                            throw new FileFormatException(SR.Get(SRID.CorruptedData));

                        if (extraDataSize > 0)
                        {
                            if (extraDataSize > AllowedExtraDataMaximumSize)
                                throw new FileFormatException(SR.Get(SRID.CorruptedData));

                            // Preserve the fields we don't know about.
                            byte[] extraData = definitionReader.ReadBytes(extraDataSize);

                            if (extraData.Length != extraDataSize)
                                throw new FileFormatException(SR.Get(SRID.CorruptedData));

                            transformInstance.ExtraData = extraData;
                        }

                        if( transformDefinition.Length > transformDefinition.Position )
                        {
                            // We have additional data in the primary instance data stream
                            int instanceDataSize = checked ((int)(transformDefinition.Length - transformDefinition.Position));
                            byte[] instanceData = new byte[instanceDataSize];
                            PackagingUtilities.ReliableRead(transformDefinition, instanceData, 0, instanceDataSize);

                            //build memory stream on the byte[] , and allow writes only if 
                            // FileAccess is Write or ReadWrite
                            MemoryStream instanceDataStream;
                            if (_associatedStorage.OpenAccess == FileAccess.Read)
                            {
                                //  NOTE: Building MemoryStream directly on top of
                                //  instanceData byte array because we want it to be
                                //  NOT resizable and NOT writable.                    
                                instanceDataStream = new MemoryStream(instanceData, false /* Not writable */);
                            }
                            else
                            {
                                // Copy additional data into a memory stream
                                //  NOTE: Not building MemoryStream directly on top of
                                //  instanceData byte array because we want it to be
                                //  resizable.                    
                                instanceDataStream = new MemoryStream();
                                instanceDataStream.Write( instanceData, 0, instanceDataSize );
                            }
                            instanceDataStream.Seek( 0, SeekOrigin.Begin );

                            // Dirty state should be tracked after the original data is read in from the disk into the memory stream
                            transformInstance.transformPrimaryStream = new DirtyStateTrackingStream(instanceDataStream);
                        }

                        transformInstance.transformStorage = transformStorage;

                        SetTransformDefinition( transformStorage.Name, transformInstance );
                    }
                }
            }
        }
    }