/**
   * Updates a registration
   *
   * @param registration The registration to update
   * @return The updated registration
   * @throws Exception
   */
  private Registration upsertRegistrationInternal(Registration registration) throws Exception {
    Connection conn = new Connection(mConnectionString);

    String resource = registration.getURI();
    String content = registration.toXml();

    String response = conn.executeRequest(resource, content, XML_CONTENT_TYPE, "PUT");

    Registration result;
    if (PnsSpecificRegistrationFactory.getInstance().isTemplateRegistration(response)) {
      result =
          PnsSpecificRegistrationFactory.getInstance()
              .createTemplateRegistration(mNotificationHubPath);
    } else {
      result =
          PnsSpecificRegistrationFactory.getInstance()
              .createNativeRegistration(mNotificationHubPath);
    }

    result.loadXml(response, mNotificationHubPath);

    storeRegistrationId(result.getName(), result.getRegistrationId(), registration.getPNSHandle());

    return result;
  }
  /**
   * Registers the client for native notifications with the specified tags
   *
   * @param pnsHandle PNS specific identifier
   * @param tags Tags to use in the registration
   * @return The created registration
   * @throws Exception
   */
  public Registration register(String pnsHandle, String... tags) throws Exception {
    if (isNullOrWhiteSpace(pnsHandle)) {
      throw new IllegalArgumentException("pnsHandle");
    }

    Registration registration =
        PnsSpecificRegistrationFactory.getInstance().createNativeRegistration(mNotificationHubPath);
    registration.setPNSHandle(pnsHandle);
    registration.setName(Registration.DEFAULT_REGISTRATION_NAME);
    registration.addTags(tags);

    return registerInternal(registration);
  }
  /**
   * Registers the client for template notifications with the specified tags
   *
   * @param pnsHandle PNS specific identifier
   * @param templateName The template name
   * @param template The template body
   * @param tags The tags to use in the registration
   * @return The created registration
   * @throws Exception
   */
  public TemplateRegistration registerTemplate(
      String pnsHandle, String templateName, String template, String... tags) throws Exception {
    if (isNullOrWhiteSpace(pnsHandle)) {
      throw new IllegalArgumentException("pnsHandle");
    }

    if (isNullOrWhiteSpace(templateName)) {
      throw new IllegalArgumentException("templateName");
    }

    if (isNullOrWhiteSpace(template)) {
      throw new IllegalArgumentException("template");
    }

    TemplateRegistration registration =
        PnsSpecificRegistrationFactory.getInstance()
            .createTemplateRegistration(mNotificationHubPath);
    registration.setPNSHandle(pnsHandle);
    registration.setName(templateName);
    registration.setBodyTemplate(template);
    registration.addTags(tags);

    return (TemplateRegistration) registerInternal(registration);
  }
  private void refreshRegistrationInformation(String pnsHandle) throws Exception {
    if (isNullOrWhiteSpace(pnsHandle)) {
      throw new IllegalArgumentException("pnsHandle");
    }

    // delete old registration information
    Editor editor = mSharedPreferences.edit();
    Set<String> keys = mSharedPreferences.getAll().keySet();
    for (String key : keys) {
      if (key.startsWith(STORAGE_PREFIX + REGISTRATION_NAME_STORAGE_KEY)) {
        editor.remove(key);
      }
    }

    editor.commit();

    // get existing registrations
    Connection conn = new Connection(mConnectionString);

    String filter =
        PnsSpecificRegistrationFactory.getInstance().getPNSHandleFieldName()
            + " eq '"
            + pnsHandle
            + "'";

    String resource =
        mNotificationHubPath + "/Registrations/?$filter=" + URLEncoder.encode(filter, "UTF-8");
    String content = null;
    String response = conn.executeRequest(resource, content, XML_CONTENT_TYPE, "GET");

    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    builder.setEntityResolver(
        new EntityResolver() {
          @Override
          public InputSource resolveEntity(String publicId, String systemId)
              throws SAXException, IOException {
            return null;
          }
        });

    Document doc = builder.parse(new InputSource(new StringReader(response)));

    doc.getDocumentElement().normalize();
    Element root = doc.getDocumentElement();

    // for each registration, parse it
    NodeList entries = root.getElementsByTagName("entry");
    for (int i = 0; i < entries.getLength(); i++) {
      Registration registration;
      Element entry = (Element) entries.item(i);
      String xml = getXmlString(entry);
      if (PnsSpecificRegistrationFactory.getInstance().isTemplateRegistration(xml)) {
        registration =
            PnsSpecificRegistrationFactory.getInstance()
                .createTemplateRegistration(mNotificationHubPath);
      } else {
        registration =
            PnsSpecificRegistrationFactory.getInstance()
                .createNativeRegistration(mNotificationHubPath);
      }

      registration.loadXml(xml, mNotificationHubPath);

      storeRegistrationId(
          registration.getName(), registration.getRegistrationId(), registration.getPNSHandle());
    }

    mIsRefreshNeeded = false;
  }