/** {@inheritDoc} */
  @Override
  public void toLDAPAttributes(
      final SCIMObject scimObject,
      final Collection<Attribute> attributes,
      final LDAPRequestInterface ldapInterface,
      final LDAPSearchResolver searchResolver)
      throws SCIMException {
    final SCIMAttribute scimAttribute =
        scimObject.getAttribute(
            getAttributeDescriptor().getSchema(), getAttributeDescriptor().getName());
    if (scimAttribute != null) {
      final SCIMAttribute managerId = scimAttribute.getValue().getAttribute("managerId");
      if (managerId == null) {
        throw new InvalidResourceException("The manager attribute does not have a managerId.");
      }

      final String resourceID = managerId.getValue().getStringValue();
      try {
        final String dn = searchResolver.getDnFromId(ldapInterface, resourceID);
        attributes.add(new Attribute(ATTR_MANAGER, dn));
      } catch (ResourceNotFoundException e) {
        // If the manager id is non-existent, we want to return a 400 to the
        // client, not a 404.
        throw new InvalidResourceException("The managerId '" + resourceID + "' does not exist.");
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public SCIMAttribute toSCIMAttribute(
      final Entry entry,
      final LDAPRequestInterface ldapInterface,
      final LDAPSearchResolver searchResolver)
      throws SCIMException {
    if (entry.hasAttribute(ATTR_MANAGER)) {
      final String dn = entry.getAttributeValue(ATTR_MANAGER);
      final String resourceID = searchResolver.getIdFromDn(ldapInterface, dn);

      final List<SCIMAttribute> attributes = new ArrayList<SCIMAttribute>(1);
      attributes.add(
          SCIMAttribute.create(
              descriptor.getSubAttribute("managerId"),
              SCIMAttributeValue.createStringValue(resourceID)));

      return SCIMAttribute.create(descriptor, SCIMAttributeValue.createComplexValue(attributes));
    }

    return null;
  }
  /**
   * Verify that a known valid user can be read from JSON.
   *
   * @throws Exception If the test fails.
   */
  @Test
  public void testUnmarshal() throws Exception {
    final ResourceDescriptor userResourceDescriptor = CoreSchema.USER_DESCRIPTOR;
    InputStream testJson = getResource("/com/unboundid/scim/marshal/spec/core-user.json");
    final Unmarshaller unmarshaller = new JsonUnmarshaller();
    final SCIMObject o =
        unmarshaller
            .unmarshal(testJson, userResourceDescriptor, BaseResource.BASE_RESOURCE_FACTORY)
            .getScimObject();
    assertNotNull(o);
    SCIMAttribute roles = o.getAttribute(SCIMConstants.SCHEMA_URI_CORE, "roles");
    assertNotNull(roles);
    assertEquals(roles.getValues().length, 3);
    assertEquals(
        roles.getValues()[0].getAttribute("value").getValue().getStringValue(), "Employee");
    assertEquals(
        roles.getValues()[1].getAttribute("value").getValue().getStringValue(), "Accounting");
    assertEquals(roles.getValues()[2].getAttribute("value").getValue().getStringValue(), "Web");
    SCIMAttribute groups = o.getAttribute(SCIMConstants.SCHEMA_URI_CORE, "groups");
    assertNotNull(groups);
    assertEquals(groups.getValues().length, 3);
    assertEquals(
        groups.getValues()[0].getAttribute("value").getValue().getStringValue(),
        "00300000005N2Y6AA");
    assertEquals(
        groups.getValues()[0].getAttribute("primary").getValue().getBooleanValue(), Boolean.TRUE);
    assertEquals(
        groups.getValues()[0].getAttribute("type").getValue().getStringValue(), "Tour Guides");
    assertEquals(
        groups.getValues()[1].getAttribute("value").getValue().getStringValue(),
        "00300000005N34H78");
    assertEquals(
        groups.getValues()[1].getAttribute("type").getValue().getStringValue(), "Employees");
    assertEquals(
        groups.getValues()[2].getAttribute("value").getValue().getStringValue(),
        "00300000005N98YT1");
    assertEquals(
        groups.getValues()[2].getAttribute("type").getValue().getStringValue(), "US Employees");

    SCIMAttribute x509Certificates =
        o.getAttribute(SCIMConstants.SCHEMA_URI_CORE, "x509Certificates");
    assertNotNull(x509Certificates);
    assertEquals(x509Certificates.getValues().length, 1);
    final SCIMAttributeValue binaryAttributeValue =
        x509Certificates.getValues()[0].getAttribute("value").getValue();
    assertEquals(
        binaryAttributeValue.getStringValue(),
        "MIIDQzCCAqygAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwTjELMAkGA1UEBhMCVVMx"
            + "EzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAoMC2V4YW1wbGUuY29tMRQwEgYD"
            + "VQQDDAtleGFtcGxlLmNvbTAeFw0xMTEwMjIwNjI0MzFaFw0xMjEwMDQwNjI0MzFa"
            + "MH8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQKDAtl"
            + "eGFtcGxlLmNvbTEhMB8GA1UEAwwYTXMuIEJhcmJhcmEgSiBKZW5zZW4gSUlJMSIw"
            + "IAYJKoZIhvcNAQkBFhNiamVuc2VuQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B"
            + "AQEFAAOCAQ8AMIIBCgKCAQEA7Kr+Dcds/JQ5GwejJFcBIP682X3xpjis56AK02bc"
            + "1FLgzdLI8auoR+cC9/Vrh5t66HkQIOdA4unHh0AaZ4xL5PhVbXIPMB5vAPKpzz5i"
            + "PSi8xO8SL7I7SDhcBVJhqVqr3HgllEG6UClDdHO7nkLuwXq8HcISKkbT5WFTVfFZ"
            + "zidPl8HZ7DhXkZIRtJwBweq4bvm3hM1Os7UQH05ZS6cVDgweKNwdLLrT51ikSQG3"
            + "DYrl+ft781UQRIqxgwqCfXEuDiinPh0kkvIi5jivVu1Z9QiwlYEdRbLJ4zJQBmDr"
            + "SGTMYn4lRc2HgHO4DqB/bnMVorHB0CC6AV1QoFK4GPe1LwIDAQABo3sweTAJBgNV"
            + "HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZp"
            + "Y2F0ZTAdBgNVHQ4EFgQU8pD0U0vsZIsaA16lL8En8bx0F/gwHwYDVR0jBBgwFoAU"
            + "dGeKitcaF7gnzsNwDx708kqaVt0wDQYJKoZIhvcNAQEFBQADgYEAA81SsFnOdYJt"
            + "Ng5Tcq+/ByEDrBgnusx0jloUhByPMEVkoMZ3J7j1ZgI8rAbOkNngX8+pKfTiDz1R"
            + "C4+dx8oU6Za+4NJXUjlL5CvV6BEYb1+QAEJwitTVvxB/A67g42/vzgAtoRUeDov1"
            + "+GFiBZ+GNF/cAYKcMtGcrs2i97ZkJMo=");
    binaryAttributeValue.getBinaryValue(); // Should not throw.
  }
  /**
   * Verify that JSON with missing or malformed schema is handled appropriately.
   *
   * @throws Exception If the test fails.
   */
  @Test
  public void testUnmarshalBadSchema() throws Exception {
    final ResourceDescriptor userResourceDescriptor = CoreSchema.USER_DESCRIPTOR;
    final Unmarshaller unmarshaller = new JsonUnmarshaller();
    InputStream testJson;
    // Test unmarshalling a JSON user entry
    testJson = getResource("/com/unboundid/scim/marshal/spec/mixed-user.json");
    try {
      unmarshaller.unmarshal(testJson, userResourceDescriptor, BaseResource.BASE_RESOURCE_FACTORY);
      fail("Expected JSONUnmarshaller to detect an ambiguous " + "resource representation.");
    } catch (InvalidResourceException e) {
      // expected
      System.err.println(e.getMessage());
    }
    testJson = getResource("/com/unboundid/scim/marshal/spec/mixed-user-malformed.json");
    try {
      unmarshaller.unmarshal(testJson, userResourceDescriptor, BaseResource.BASE_RESOURCE_FACTORY);
      fail("Expected JSONUnmarshaller to detect an ambiguous " + "resource representation.");
    } catch (InvalidResourceException e) {
      // expected
      System.err.println(e.getMessage());
    }

    // Try with implicit schema checking enabled
    testJson = getResource("/com/unboundid/scim/marshal/spec/mixed-user.json");
    try {
      System.setProperty(SCIMConstants.IMPLICIT_SCHEMA_CHECKING_PROPERTY, "true");
      final SCIMObject o =
          unmarshaller
              .unmarshal(testJson, userResourceDescriptor, BaseResource.BASE_RESOURCE_FACTORY)
              .getScimObject();
      assertNotNull(o);
      SCIMAttribute username = o.getAttribute(SCIMConstants.SCHEMA_URI_CORE, "userName");
      assertEquals(username.getValue().getStringValue(), "babs");
      SCIMAttribute employeeNumber =
          o.getAttribute(SCIMConstants.SCHEMA_URI_ENTERPRISE_EXTENSION, "employeeNumber");
      assertEquals(employeeNumber.getValue().getStringValue(), "1");
    } finally {
      System.setProperty(SCIMConstants.IMPLICIT_SCHEMA_CHECKING_PROPERTY, "");
    }
    testJson = getResource("/com/unboundid/scim/marshal/spec/mixed-user-malformed.json");
    try {
      System.setProperty(SCIMConstants.IMPLICIT_SCHEMA_CHECKING_PROPERTY, "true");
      unmarshaller.unmarshal(testJson, userResourceDescriptor, BaseResource.BASE_RESOURCE_FACTORY);
      fail("Expected JSONUnmarshaller to fail because no schema can be found " + "for attribute.");
    } catch (InvalidResourceException e) {
      // expected
      System.err.println(e.getMessage());
    } finally {
      System.setProperty(SCIMConstants.IMPLICIT_SCHEMA_CHECKING_PROPERTY, "");
    }

    // Test unmarshalling a JSON user patch with meta data
    testJson = getResource("/com/unboundid/scim/marshal/spec/meta-user-patch.json");
    try {
      unmarshaller.unmarshal(testJson, userResourceDescriptor, BaseResource.BASE_RESOURCE_FACTORY);
      fail("Expected JSONUnmarshaller to detect an ambiguous " + "resource representation.");
    } catch (InvalidResourceException e) {
      // expected
      System.err.println(e.getMessage());
    }
    // Try with implicit schema checking enabled
    testJson = getResource("/com/unboundid/scim/marshal/spec/meta-user-patch.json");
    try {
      System.setProperty(SCIMConstants.IMPLICIT_SCHEMA_CHECKING_PROPERTY, "true");
      final SCIMObject o =
          unmarshaller
              .unmarshal(testJson, userResourceDescriptor, BaseResource.BASE_RESOURCE_FACTORY)
              .getScimObject();
      assertNotNull(o);
      SCIMAttribute metaAttr = o.getAttribute(SCIMConstants.SCHEMA_URI_CORE, "meta");
      String metaString = metaAttr.toString();
      assertTrue(metaString.contains("department"));
      assertTrue(
          metaString.contains(SCIMConstants.SEPARATOR_CHAR_QUALIFIED_ATTRIBUTE + "department"));
    } finally {
      System.setProperty(SCIMConstants.IMPLICIT_SCHEMA_CHECKING_PROPERTY, "");
    }
  }