/// <summary>Recursively reads the children of an element as they appear in the message payload and returns
 /// the state of this element.</summary>
 /// <remarks>
 /// <para>Nodes for which an empty children collection is received are marked with
 /// <see cref="Model.RetrievalState.Complete"/>. The same happens if the collection only contains children we're
 /// not interested in. In all other cases, the state of the node is lowered to the lowest state of the
 /// interesting children appearing in the payload.</para>
 /// <para>This approach ensures that any node for which incomplete interesting children have been received will
 /// be visited by <see cref="UpdateRetrievalState"/>. This is necessary because some providers send messages
 /// with payloads where the same node appears multiple times. For example, the first time the state of the node
 /// may be set to <see cref="Model.RetrievalState.None"/>, due to the fact that there are indirect children for
 /// which a <code>getDirectory</code> request needs to be sent. The second time the node appears only with
 /// direct and indirect children that have the state <see cref="Model.RetrievalState.Complete"/>. Now the state
 /// of the node cannot be set to <see cref="Model.RetrievalState.Complete"/> because then no
 /// <code>getDirectory</code> requests would be issued for the children that appeared the first time.</para>
 /// <para>It follows that the state of a node cannot be set to its definitive value while its children are read.
 /// Instead there needs to be a second step that visits all affected nodes and updates their state, which is
 /// implemented by <see cref="UpdateRetrievalState"/>.</para></remarks>
 internal virtual RetrievalState ReadChildren(EmberReader reader)
 {
     reader.Skip();
     return(RetrievalState.Complete);
 }
        private void ReadConnections(EmberReader reader)
        {
            reader.AssertInnerNumber(GlowConnectionCollection.InnerNumber);

            while (reader.Read() && (reader.InnerNumber != InnerNumber.EndContainer))
            {
                switch (reader.GetContextSpecificOuterNumber())
                {
                case GlowConnectionCollection.Connection.OuterNumber:
                    reader.AssertInnerNumber(GlowConnection.InnerNumber);
                    int?  target                      = null;
                    int[] connectedSources            = new int[0];
                    ConnectionOperation   operation   = ConnectionOperation.Absolute;
                    ConnectionDisposition disposition = ConnectionDisposition.Tally;

                    while (reader.Read() && (reader.InnerNumber != InnerNumber.EndContainer))
                    {
                        switch (reader.GetContextSpecificOuterNumber())
                        {
                        case GlowConnection.Target.OuterNumber:
                            target = this.ReadInt(reader, GlowConnection.Target.Name);
                            break;

                        case GlowConnection.Sources.OuterNumber:
                            connectedSources = reader.AssertAndReadContentsAsInt32Array();
                            break;

                        case GlowConnection.Operation.OuterNumber:
                            operation =
                                this.ReadEnum <ConnectionOperation>(reader, GlowConnection.Operation.Name);
                            break;

                        case GlowConnection.Disposition.OuterNumber:
                            disposition =
                                this.ReadEnum <ConnectionDisposition>(reader, GlowConnection.Disposition.Name);
                            break;

                        default:
                            reader.Skip();
                            break;
                        }
                    }

                    if (target.HasValue && (disposition != ConnectionDisposition.Pending) && !this.HasChanges)
                    {
                        var existingConnectedSources = this.Connections[target.Value];

                        switch (operation)
                        {
                        case ConnectionOperation.Absolute:
                            Insert(existingConnectedSources, connectedSources, true);
                            break;

                        case ConnectionOperation.Connect:
                            Insert(existingConnectedSources, connectedSources, false);
                            break;

                        case ConnectionOperation.Disconnect:
                            foreach (var source in connectedSources)
                            {
                                existingConnectedSources.Remove(source);
                            }

                            break;
                        }
                    }

                    break;

                default:
                    reader.Skip();
                    break;
                }
            }
        }
 internal override RetrievalState ReadAdditionalField(EmberReader reader, int contextSpecificOuterNumber)
 {
     reader.Skip();
     return(this.RetrievalState);
 }
        internal sealed override RetrievalState ReadContents(EmberReader reader, ElementType actualType)
        {
            this.AssertElementType(ElementType.Matrix, actualType);
            var addressingMode = MatrixAddressingMode.Linear;

            while (reader.Read() && (reader.InnerNumber != InnerNumber.EndContainer))
            {
                switch (reader.GetContextSpecificOuterNumber())
                {
                case GlowMatrixContents.Description.OuterNumber:
                    this.Description = reader.AssertAndReadContentsAsString();
                    break;

                case GlowMatrixContents.Type.OuterNumber:
                    this.type = this.ReadEnum <MatrixType>(reader, GlowMatrixContents.Type.Name);
                    break;

                case GlowMatrixContents.AddressingMode.OuterNumber:
                    addressingMode =
                        this.ReadEnum <MatrixAddressingMode>(reader, GlowMatrixContents.AddressingMode.Name);
                    break;

                case GlowMatrixContents.TargetCount.OuterNumber:
                    this.Targets =
                        Enumerable.Range(0, this.ReadInt(reader, GlowMatrixContents.TargetCount.Name)).ToList();
                    break;

                case GlowMatrixContents.SourceCount.OuterNumber:
                    this.Sources =
                        Enumerable.Range(0, this.ReadInt(reader, GlowMatrixContents.SourceCount.Name)).ToList();
                    break;

                case GlowMatrixContents.MaximumTotalConnects.OuterNumber:
                    this.MaximumTotalConnects = this.ReadInt(reader, GlowMatrixContents.MaximumTotalConnects.Name);
                    break;

                case GlowMatrixContents.MaximumConnectsPerTarget.OuterNumber:
                    this.MaximumConnectsPerTarget =
                        this.ReadInt(reader, GlowMatrixContents.MaximumConnectsPerTarget.Name);
                    break;

                case GlowMatrixContents.ParametersLocation.OuterNumber:
                    this.ParametersLocation = this.ReadParametersLocation(reader);
                    break;

                case GlowMatrixContents.GainParameterNumber.OuterNumber:
                    this.GainParameterNumber = this.ReadInt(reader, GlowMatrixContents.GainParameterNumber.Name);
                    break;

                case GlowMatrixContents.Labels.OuterNumber:
                    this.Labels = ReadLabels(reader);
                    break;

                case GlowMatrixContents.SchemaIdentifiers.OuterNumber:
                    this.ReadSchemaIdentifiers(reader);
                    break;

                default:
                    reader.Skip();
                    break;
                }
            }

            return(this.RetrievalState);
        }
        internal override RetrievalState ReadContents(EmberReader reader, ElementType actualType)
        {
            this.AssertElementType(ElementType.Parameter, actualType);

            ParameterType?valueType = null;
            ParameterType?enumType  = null;
            ParameterType?typeType  = null;

            while (reader.Read() && (reader.InnerNumber != InnerNumber.EndContainer))
            {
                ParameterType?dummyType;

                switch (reader.GetContextSpecificOuterNumber())
                {
                case GlowParameterContents.Description.OuterNumber:
                    this.Description = reader.AssertAndReadContentsAsString();
                    break;

                case GlowParameterContents.Value.OuterNumber:
                    this.SetProviderValue(this.ReadValue(reader, out valueType));
                    break;

                case GlowParameterContents.Minimum.OuterNumber:
                    this.SetMinimum(this.ReadValue(reader, out dummyType));
                    break;

                case GlowParameterContents.Maximum.OuterNumber:
                    this.SetMaximum(this.ReadValue(reader, out dummyType));
                    break;

                case GlowParameterContents.Access.OuterNumber:
                    this.Access = this.ReadEnum <ParameterAccess>(reader, GlowParameterContents.Access.Name);
                    break;

                case GlowParameterContents.Format.OuterNumber:
                    this.Format = reader.AssertAndReadContentsAsString();
                    break;

                case GlowParameterContents.Enumeration.OuterNumber:
                    this.EnumMapCore = ReadEnumeration(reader);
                    enumType         = ParameterType.Enum;
                    break;

                case GlowParameterContents.Factor.OuterNumber:
                    this.FactorCore = this.ReadInt(reader, GlowParameterContents.Factor.Name);
                    break;

                case GlowParameterContents.IsOnline.OuterNumber:
                    this.IsOnline = reader.AssertAndReadContentsAsBoolean();
                    var send = (this.RetrieveDetailsChangeStatus == RetrieveDetailsChangeStatus.Changed) &&
                               this.RetrieveDetails && this.StreamIdentifier.HasValue;
                    this.RetrievalState &= send ? RetrievalState.None : RetrievalState.Complete;
                    break;

                case GlowParameterContents.Formula.OuterNumber:
                    this.FormulaCore = reader.AssertAndReadContentsAsString();
                    break;

                case GlowParameterContents.Step.OuterNumber:
                    this.ReadInt(reader, GlowParameterContents.Step.Name);
                    break;

                case GlowParameterContents.Default.OuterNumber:
                    this.DefaultValue = this.ReadValue(reader, out dummyType);
                    break;

                case GlowParameterContents.Type.OuterNumber:
                    typeType = this.ReadEnum <ParameterType>(reader, GlowParameterContents.Type.Name);
                    break;

                case GlowParameterContents.StreamIdentifier.OuterNumber:
                    this.StreamIdentifier = this.ReadInt(reader, GlowParameterContents.StreamIdentifier.Name);
                    break;

                case GlowParameterContents.EnumMap.OuterNumber:
                    this.EnumMapCore = this.ReadEnumMap(reader);
                    enumType         = ParameterType.Enum;
                    break;

                case GlowParameterContents.StreamDescriptor.OuterNumber:
                    this.StreamDescriptor = this.ReadStreamDescriptor(reader);
                    break;

                case GlowParameterContents.SchemaIdentifiers.OuterNumber:
                    this.ReadSchemaIdentifiers(reader);
                    break;

                default:
                    reader.Skip();
                    break;
                }
            }

            this.SetFinalTytpe(valueType, enumType, typeType);
            return(this.RetrievalState);
        }