Esempio n. 1
0
        /// <summary>
        /// Loads the instance data from the given <see cref="Uri"/>.
        /// </summary>
        /// <param name="resourceUri"></param>
        internal void Load(Uri resourceUri)
        {
            Contract.Requires <ArgumentNullException>(resourceUri != null);

            try
            {
                // normalize uri with base
                if (Element.GetBaseUri() != null && !resourceUri.IsAbsoluteUri)
                {
                    resourceUri = new Uri(Element.GetBaseUri(), resourceUri);
                }
            }
            catch (UriFormatException e)
            {
                throw new DOMTargetEventException(Element, Events.LinkException, e);
            }

            // return resource as a stream
            var response = requestService.Submit(new ModelRequest(resourceUri, ModelMethod.Get));

            if (response == null ||
                response.Status == ModelResponseStatus.Error)
            {
                throw new DOMTargetEventException(Element, Events.LinkException,
                                                  string.Format("Error retrieving resource '{0}'.", resourceUri));
            }

            // load instance
            Load(response.Body);
        }
Esempio n. 2
0
        void OnSubmitImpl()
        {
            // The data model is updated based on some of the flags defined for deferred updates. Specifically, if the
            // deferred update rebuild flag is set for the model containing this submission, then the rebuild operation
            // is performed without dispatching an event to invoke the operation. Then, if the deferred update
            // recalculate flag is set for the model containing this submission, then the recalculate operation is
            // performed without dispatching an event to invoke the operation. This sequence of operations affects the
            // deferred update behavior by clearing the deferred update flags associated with the operations performed.
            var model = Element.Ancestors(Constants.XForms_1_0 + "model").First().Interface <Model>();

            if (model.State.Rebuild)
            {
                model.OnRebuild();
            }
            if (model.State.Recalculate)
            {
                model.OnRecalculate();
            }

            // If the binding attributes of submission indicate an empty sequence or an item other than an element or
            // an instance document root node, then submission fails with no-data. Otherwise, the binding attributes of
            // submission indicate a node of instance data.
            var modelItems = new Binding(Element, context.Value.Context, properties.Ref).ModelItems;

            if (modelItems == null ||
                modelItems.Length != 1 ||
                modelItems.Any(i => i.Xml.NodeType != XmlNodeType.Document && i.Xml.NodeType != XmlNodeType.Element))
            {
                throw new DOMTargetEventException(Element, Events.SubmitError, new SubmitErrorContextInfo(
                                                      SubmitErrorErrorType.NoData
                                                      ));
            }

            // The indicated node and all nodes for which it is an ancestor are selected. If the attribute relevant is
            // true, whether by default or declaration, then any selected node which is not relevant as defined in The
            // relevant Property is deselected (pruned). If all instance nodes are deselected, then submission fails
            // with no-data.
            var node = (XNode) new SubmitTransformer(properties.Relevant)
                       .Visit(modelItems[0].Xml);

            if (node == null)
            {
                throw new DOMTargetEventException(Element, Events.SubmitError, new SubmitErrorContextInfo(
                                                      SubmitErrorErrorType.NoData
                                                      ));
            }

            // If the attribute validate is true, whether by default or declaration, then all selected instance data
            // nodes are checked for validity according to the definition in The xforms-revalidate Event (no
            // notification events are marked for dispatching due to this operation). If any selected instance data
            // node is found to be invalid, submission fails with validation-error.
            if (properties.Validate &&
                new ValidationVisitor().Validate(node) == false)
            {
                throw new DOMTargetEventException(Element, Events.SubmitError, new SubmitErrorContextInfo(
                                                      SubmitErrorErrorType.ValidationError
                                                      ));
            }

            // The submission method is determined.
            // The submission method may be specified by the method attribute. The submission element can have a child
            // element named method, which overrides the submission method setting obtained from the method attribute
            // if both are specified. If more than one method element is given, the first occurrence in document order
            // must be selected for use. Individually, the method element and the method attribute are not required.
            // However, one of the two is mandatory as there is no default submission method.
            var method = GetMethod();

            if (method == null)
            {
                throw new DOMTargetEventException(Element, Events.SubmitError, "Unknown ModelMethod.");
            }

            // The resource element provides the submission URI, overriding the resource attribute and the action
            // attribute. If a submission has more than one resource child element, the first resource element child
            // must be selected for use. Individually, the resource element, the resource attribute and the action
            // attribute are not required. However, one of the three is mandatory as there is no default submission
            // resource.
            var resource = GetResource();

            if (resource == null)
            {
                throw new DOMTargetEventException(Element, Events.SubmitError, new SubmitErrorContextInfo(
                                                      SubmitErrorErrorType.ResourceError));
            }

            // If the serialization attribute value is "none", then the submission data serialization is the empty
            // string. Otherwise, the event xforms-submit-serialize is dispatched; if the submission-body property
            // of the event is changed from the initial value of empty string, then the content of the submission-body
            // property string is used as the submission data serialization. Otherwise, the submission data
            // serialization consists of a serialization of the selected instance data according to the rules stated
            // in Serialization.
            if (properties.Serialization.None)
            {
                node = null;
            }
            else
            {
                var evt = Element.Interface <EventTarget>().Dispatch(Events.SubmitSerialize, new SubmitSerializeContextInfo());
                var ctx = evt.Context as SubmitSerializeContextInfo;
                if (ctx != null &&
                    ctx.SubmissionBody != "")
                {
                    // wrap in XText
                    node = new XText(ctx.SubmissionBody);
                }
            }

            // The submission is performed based on the submission headers, submission method, submission resource, and
            // submission data serialization. The exact rules of submission are based on the URI scheme and the
            // submission method, as defined in Submission Options.
            var request = new ModelRequest(resource, (ModelMethod)method);

            request.MediaType = properties.MediaType;
            request.Body      = node;
            request.Encoding  = properties.Encoding;
            request.Headers.Add(GetHeaders());

            // submit and check for response
            var response = requestService.Submit(request);

            if (response == null)
            {
                throw new DOMTargetEventException(Element, Events.SubmitError, new SubmitErrorContextInfo(
                                                      SubmitErrorErrorType.ResourceError));
            }

            // For error responses, processing depends on the value of the replace attribute on element submission:
            // all: either the document is replaced with an implementation-specific indication of an error or submission fails with resource-error.
            // any other value: nothing in the document is replaced, and submission fails with resource-error.
            if (response.Status == ModelResponseStatus.Error)
            {
                throw new DOMTargetEventException(Element, Events.SubmitError, new SubmitErrorContextInfo(
                                                      SubmitErrorErrorType.ResourceError));
            }

            // For success responses, if the response does not include a body, submission succeeds.
            if (response.Body == null)
            {
                Element.DispatchEvent(Events.SubmitDone);
                return;
            }

            // handle result based on 'replace' property
            switch (properties.Replace)
            {
            // none: submission succeeds.
            case SubmissionReplace.None:
                Element.DispatchEvent(Events.SubmitDone);
                break;

            // all: the event xforms-submit-done may be dispatched with appropriate context information, and submit
            // processing concludes with the entire containing document being replaced with the returned body.
            case SubmissionReplace.All:
                throw new NotImplementedException();

            // instance: If the body is not of type accepted by the processor, as specified in Creating instance data
            // from external resources, nothing in the document is replaced and submission fails with resource-error.
            // Otherwise the body is parsed to give an XPath Data Model according to Creating instance data from
            // external resources. If the parse fails, then submission fails with parse-error. If the parse succeeds,
            // then instance data replacement is performed according to Replacing Data with the Submission Response.
            // If this operation fails, submission fails with target-error. Otherwise, submission succeeds.
            case SubmissionReplace.Instance:
                FinishWithReplaceInstance(response, modelItems[0]);
                break;

            // text: If the body is neither an XML media type (i.e. with a content type not matching any of the
            // specifiers in [RFC 3023]) nor a text type (i.e. with a content type not matching text/*), nothing in the
            // document is replaced and submission fails with resource-error. Otherwise the content replacement is
            // performed according to Replacing Data with the Submission Response. If this operation fails, then the
            // submission fails with target-error. Otherwise, submission succeeds.
            case SubmissionReplace.Text:
                throw new NotImplementedException();
            }
        }