/**
   * Populates the container from an XMLStreamReader
   *
   * @param xmlr the XMLStreamReader to read from
   * @throws XMLStreamException if there is an error parsing the stream
   * @throws ParseException if there is an error in parsing a date
   * @throws URISyntaxException if the uri is invalid
   * @throws StorageException
   */
  protected static CloudBlobContainer readContainer(
      final XMLStreamReader xmlr, final CloudBlobClient serviceClient)
      throws XMLStreamException, ParseException, URISyntaxException, StorageException {

    xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.CONTAINER_ELEMENT);

    final BlobContainerAttributes attributes =
        BlobDeserializationHelper.readBlobContainerAttributes(xmlr);

    final CloudBlobContainer retContainer =
        new CloudBlobContainer(attributes.getUri(), serviceClient);
    retContainer.setMetadata(attributes.getMetadata());
    retContainer.setName(attributes.getName());
    retContainer.setProperties(attributes.getProperties());
    retContainer.setUri(attributes.getUri());

    xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.CONTAINER_ELEMENT);
    return retContainer;
  }
  /**
   * Populates the CloudBlobDirectory from an XMLStreamReader, reader must be at Start element of
   * BlobPrefix
   *
   * @param xmlr the XMLStreamReader to read from
   * @param serviceClient the CloudBlobClient associated with the objects.
   * @param container the container associated with the objects.
   * @return a CloudBlobDirectory parsed from the stream.
   * @throws XMLStreamException if there is an error parsing the stream
   * @throws ParseException if there is an error in parsing a date
   * @throws URISyntaxException if the uri is invalid
   * @throws StorageException
   */
  protected static CloudBlobDirectory readDirectory(
      final XMLStreamReader xmlr,
      final CloudBlobClient serviceClient,
      final CloudBlobContainer container)
      throws XMLStreamException, ParseException, URISyntaxException, StorageException {
    xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.BLOB_PREFIX_ELEMENT);

    // Move to Name element
    xmlr.next();
    xmlr.require(XMLStreamConstants.START_ELEMENT, null, Constants.NAME_ELEMENT);

    final String prefixName = Utility.readElementFromXMLReader(xmlr, Constants.NAME_ELEMENT);

    // Move from End name element to end prefix element
    xmlr.next();
    xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.BLOB_PREFIX_ELEMENT);

    return container.getDirectoryReference(prefixName);
  }
  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException {
    String currentNode = this.elementStack.pop();

    // if the node popped from the stack and the localName don't match, the xml document is
    // improperly formatted
    if (!localName.equals(currentNode)) {
      throw new SAXException(SR.INVALID_RESPONSE_RECEIVED);
    }

    String parentNode = null;
    if (!this.elementStack.isEmpty()) {
      parentNode = this.elementStack.peek();
    }

    String value = this.bld.toString();
    if (value.isEmpty()) {
      value = null;
    }

    if (BlobConstants.CONTAINER_ELEMENT.equals(currentNode)) {
      try {
        CloudBlobContainer retContainer =
            this.serviceClient.getContainerReference(this.containerName);
        retContainer.setMetadata(this.attributes.getMetadata());
        retContainer.setProperties(this.attributes.getProperties());

        this.response.getResults().add(retContainer);
      } catch (URISyntaxException e) {
        throw new SAXException(e);
      } catch (StorageException e) {
        throw new SAXException(e);
      }

    } else if (ListResponse.ENUMERATION_RESULTS.equals(parentNode)) {
      if (Constants.PREFIX_ELEMENT.equals(currentNode)) {
        this.response.setPrefix(value);
      } else if (Constants.MARKER_ELEMENT.equals(currentNode)) {
        this.response.setMarker(value);
      } else if (Constants.NEXT_MARKER_ELEMENT.equals(currentNode)) {
        this.response.setNextMarker(value);
      } else if (Constants.MAX_RESULTS_ELEMENT.equals(currentNode)) {
        this.response.setMaxResults(Integer.parseInt(value));
      }
    } else if (BlobConstants.CONTAINER_ELEMENT.equals(parentNode)) {
      if (Constants.NAME_ELEMENT.equals(currentNode)) {
        this.containerName = value;
      }
    } else if (Constants.PROPERTIES.equals(parentNode)) {
      try {
        getProperties(currentNode, value);
      } catch (ParseException e) {
        throw new SAXException(e);
      }
    } else if (Constants.METADATA_ELEMENT.equals(parentNode)) {
      if (value == null) {
        value = "";
      }
      this.attributes.getMetadata().put(currentNode, value);
    }

    this.bld = new StringBuilder();
  }