@Test
  public void testPOSTObject() throws Exception {
    final String TAG_VALUE = "TAG";

    Property property = new Property();
    property.setName("tags");
    property.setValue(TAG_VALUE);
    Object object = objectFactory.createObject();
    object.setClassName("XWiki.TagClass");
    object.getProperties().add(property);

    PostMethod postMethod =
        executePostXml(
            getUriBuilder(ObjectsResource.class).build(getWiki(), "Main", "WebHome").toString(),
            object,
            "Admin",
            "admin");
    Assert.assertEquals(
        getHttpMethodInfo(postMethod), HttpStatus.SC_CREATED, postMethod.getStatusCode());

    object = (Object) unmarshaller.unmarshal(postMethod.getResponseBodyAsStream());

    Assert.assertEquals(TAG_VALUE, getProperty(object, "tags").getValue());

    GetMethod getMethod =
        executeGet(
            getUriBuilder(ObjectResource.class)
                .build(getWiki(), "Main", "WebHome", object.getClassName(), object.getNumber())
                .toString());
    Assert.assertEquals(getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

    object = (Object) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());

    Assert.assertEquals(TAG_VALUE, getProperty(object, "tags").getValue());
  }
  public Property getProperty(Object object, String propertyName) {
    for (Property property : object.getProperties()) {
      if (property.getName().equals(propertyName)) {
        return property;
      }
    }

    return null;
  }
  @Test
  public void testPOSTObjectNotAuthorized() throws Exception {
    final String TAG_VALUE = "TAG";

    Property property = new Property();
    property.setName("tags");
    property.setValue(TAG_VALUE);
    Object object = objectFactory.createObject();
    object.setClassName("XWiki.TagClass");
    object.getProperties().add(property);

    PostMethod postMethod =
        executePostXml(
            getUriBuilder(ObjectsResource.class).build(getWiki(), "Main", "WebHome").toString(),
            object);
    Assert.assertEquals(
        getHttpMethodInfo(postMethod), HttpStatus.SC_UNAUTHORIZED, postMethod.getStatusCode());
  }
  @GET
  public Property getClassProperty(
      @PathParam("wikiName") String wikiName,
      @PathParam("className") String className,
      @PathParam("propertyName") String propertyName)
      throws XWikiException {

    String database = Utils.getXWikiContext(componentManager).getDatabase();

    try {
      Utils.getXWikiContext(componentManager).setDatabase(wikiName);

      com.xpn.xwiki.api.Class xwikiClass = Utils.getXWikiApi(componentManager).getClass(className);
      if (xwikiClass == null) {
        throw new WebApplicationException(Status.NOT_FOUND);
      }

      Class clazz =
          DomainObjectFactory.createClass(
              objectFactory, uriInfo.getBaseUri(), wikiName, xwikiClass);

      for (Property property : clazz.getProperties()) {
        if (property.getName().equals(propertyName)) {
          String classUri =
              UriBuilder.fromUri(uriInfo.getBaseUri())
                  .path(ClassResource.class)
                  .build(wikiName, xwikiClass.getName())
                  .toString();
          Link classLink = objectFactory.createLink();
          classLink.setHref(classUri);
          classLink.setRel(Relations.CLASS);
          property.getLinks().add(classLink);

          return property;
        }
      }

      throw new WebApplicationException(Status.NOT_FOUND);

    } finally {
      Utils.getXWiki(componentManager).setDatabase(database);
    }
  }
  @Test
  public void testPOSTInvalidObject() throws Exception {
    final String TAG_VALUE = "TAG";

    Property property = new Property();
    property.setName("tags");
    property.setValue(TAG_VALUE);
    Object object = objectFactory.createObject();
    object.getProperties().add(property);

    PostMethod postMethod =
        executePostXml(
            getUriBuilder(ObjectsResource.class).build(getWiki(), "Main", "WebHome").toString(),
            object,
            "Admin",
            "admin");
    Assert.assertEquals(
        getHttpMethodInfo(postMethod), HttpStatus.SC_BAD_REQUEST, postMethod.getStatusCode());
  }
  public String getEmailAddress(String wikiName, String username) throws LpRestExceptionXWikiImpl {
    String emailAddress = null;

    HttpClient httpClient = restResource.getClient();

    // http://<server>/rest/wikis/xwiki/spaces/XWiki/pages/<username>/objects/XWiki.XWikiUsers/0/properties/email
    String uri =
        String.format(
            "%s/wikis/%s/spaces/XWiki/pages/%s/objects/XWiki.XWikiUsers/0/properties/email",
            DefaultRestResource.REST_URI, wikiName, username);
    GetMethod getMethod = new GetMethod(uri);

    try {
      httpClient.executeMethod(getMethod);

      InputStream response = getMethod.getResponseBodyAsStream();

      JAXBContext jaxbContext = JAXBContext.newInstance(Property.class);
      Property emailProperty = (Property) jaxbContext.createUnmarshaller().unmarshal(response);

      emailAddress = emailProperty.getValue();
    } catch (IOException e) {
      String message =
          String.format(
              "Unable to GET the email propery of '%s' on %s@%s'.",
              username, wikiName, DefaultRestResource.REST_URI);
      logger.error(message, e);
      throw new LpRestExceptionXWikiImpl(message, e.getCause());
    } catch (JAXBException e) {
      String message =
          String.format(
              "Unable to unmarshall the email propery of '%s' on %s@%s'.",
              username, wikiName, DefaultRestResource.REST_URI);
      logger.error(message, e);
      throw new LpRestExceptionXWikiImpl(message, e.getCause());
    }

    return emailAddress;
  }
  @Test
  public void testGETObjectAtPageVersion() throws Exception {
    Object objectToBePut = getObject("XWiki.TagClass");

    Map<String, String> versionToValueMap = new HashMap<String, String>();
    for (int i = 0; i < 5; i++) {
      String value = String.format("Value%d", i);

      Property property = getProperty(objectToBePut, "tags");
      property.setValue(value);

      PutMethod putMethod =
          executePutXml(
              getUriBuilder(ObjectResource.class)
                  .build(
                      getWiki(),
                      "Main",
                      "WebHome",
                      objectToBePut.getClassName(),
                      objectToBePut.getNumber())
                  .toString(),
              objectToBePut,
              "Admin",
              "admin");
      Assert.assertEquals(
          getHttpMethodInfo(putMethod), HttpStatus.SC_ACCEPTED, putMethod.getStatusCode());

      GetMethod getMethod =
          executeGet(
              getUriBuilder(PageResource.class).build(getWiki(), "Main", "WebHome").toString());
      Assert.assertEquals(
          getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

      Page page = (Page) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());

      versionToValueMap.put(page.getVersion(), value);
    }

    for (String version : versionToValueMap.keySet()) {
      GetMethod getMethod =
          executeGet(
              getUriBuilder(ObjectAtPageVersionResource.class)
                  .build(
                      getWiki(),
                      "Main",
                      "WebHome",
                      version,
                      objectToBePut.getClassName(),
                      objectToBePut.getNumber())
                  .toString());
      Assert.assertEquals(
          getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

      Object currentObject = (Object) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());

      Property property = getProperty(currentObject, "tags");

      Assert.assertEquals(versionToValueMap.get(version), property.getValue());

      checkLinks(currentObject);
      for (Property p : currentObject.getProperties()) {
        checkLinks(p);
      }
    }
  }
  @Test
  public void testPUTPropertyFormUrlEncoded() throws Exception {
    final String TAG_VALUE = UUID.randomUUID().toString();

    GetMethod getMethod =
        executeGet(
            getUriBuilder(PageResource.class).build(getWiki(), "Main", "WebHome").toString());
    Assert.assertEquals(getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

    Page page = (Page) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());
    Link link = getFirstLinkByRelation(page, Relations.OBJECTS);
    Assert.assertNotNull(link);

    getMethod = executeGet(link.getHref());
    Assert.assertEquals(getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

    Objects objects = (Objects) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());

    Assert.assertFalse(objects.getObjectSummaries().isEmpty());

    Object currentObject = null;

    for (ObjectSummary objectSummary : objects.getObjectSummaries()) {
      if (objectSummary.getClassName().equals("XWiki.TagClass")) {
        link = getFirstLinkByRelation(objectSummary, Relations.OBJECT);
        Assert.assertNotNull(link);
        getMethod = executeGet(link.getHref());
        Assert.assertEquals(
            getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

        currentObject = (Object) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());
        break;
      }
    }

    Assert.assertNotNull(currentObject);

    Property tagsProperty = getProperty(currentObject, "tags");

    Assert.assertNotNull(tagsProperty);

    Link tagsPropertyLink = getFirstLinkByRelation(tagsProperty, Relations.SELF);

    Assert.assertNotNull(tagsPropertyLink);

    NameValuePair[] nameValuePairs = new NameValuePair[1];
    nameValuePairs[0] = new NameValuePair("property#tags", TAG_VALUE);

    PostMethod postMethod =
        executePostForm(
            String.format("%s?method=PUT", tagsPropertyLink.getHref()),
            nameValuePairs,
            "Admin",
            "admin");
    Assert.assertEquals(
        getHttpMethodInfo(postMethod), HttpStatus.SC_ACCEPTED, postMethod.getStatusCode());

    getMethod =
        executeGet(
            getUriBuilder(ObjectResource.class)
                .build(
                    getWiki(),
                    "Main",
                    "WebHome",
                    currentObject.getClassName(),
                    currentObject.getNumber())
                .toString());
    Assert.assertEquals(HttpStatus.SC_OK, getMethod.getStatusCode());

    currentObject = (Object) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());

    tagsProperty = getProperty(currentObject, "tags");

    Assert.assertEquals(TAG_VALUE, tagsProperty.getValue());
  }
  @Test
  public void testPUTPropertyWithTextPlain() throws Exception {
    final String TAG_VALUE = UUID.randomUUID().toString();

    /* Make sure that an Object with the TagClass exists. */
    Object objectToBeUpdated = getObject("XWiki.TagClass");

    GetMethod getMethod =
        executeGet(
            getUriBuilder(PageResource.class).build(getWiki(), "Main", "WebHome").toString());
    Assert.assertEquals(getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

    Page page = (Page) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());
    Link link = getFirstLinkByRelation(page, Relations.OBJECTS);
    Assert.assertNotNull(link);

    getMethod = executeGet(link.getHref());
    Assert.assertEquals(getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

    Objects objects = (Objects) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());

    Assert.assertFalse(objects.getObjectSummaries().isEmpty());

    Object currentObject = null;

    for (ObjectSummary objectSummary : objects.getObjectSummaries()) {
      if (objectSummary.getClassName().equals("XWiki.TagClass")) {
        link = getFirstLinkByRelation(objectSummary, Relations.OBJECT);
        Assert.assertNotNull(link);
        getMethod = executeGet(link.getHref());
        Assert.assertEquals(
            getHttpMethodInfo(getMethod), HttpStatus.SC_OK, getMethod.getStatusCode());

        currentObject = (Object) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());
        break;
      }
    }

    Assert.assertNotNull(currentObject);

    Property tagsProperty = getProperty(currentObject, "tags");

    Assert.assertNotNull(tagsProperty);

    Link tagsPropertyLink = getFirstLinkByRelation(tagsProperty, Relations.SELF);

    Assert.assertNotNull(tagsPropertyLink);

    PutMethod putMethod =
        executePut(tagsPropertyLink.getHref(), TAG_VALUE, MediaType.TEXT_PLAIN, "Admin", "admin");
    Assert.assertEquals(
        getHttpMethodInfo(putMethod), HttpStatus.SC_ACCEPTED, putMethod.getStatusCode());

    getMethod =
        executeGet(
            getUriBuilder(ObjectResource.class)
                .build(
                    getWiki(),
                    "Main",
                    "WebHome",
                    currentObject.getClassName(),
                    currentObject.getNumber())
                .toString());
    Assert.assertEquals(HttpStatus.SC_OK, getMethod.getStatusCode());

    currentObject = (Object) unmarshaller.unmarshal(getMethod.getResponseBodyAsStream());

    tagsProperty = getProperty(currentObject, "tags");

    Assert.assertEquals(TAG_VALUE, tagsProperty.getValue());
  }
  public static Class createClass(
      ObjectFactory objectFactory,
      URI baseUri,
      String wikiName,
      com.xpn.xwiki.api.Class xwikiClass) {
    Class clazz = objectFactory.createClass();
    clazz.setId(xwikiClass.getName());
    clazz.setName(xwikiClass.getName());

    for (java.lang.Object xwikiPropertyClassObject : xwikiClass.getProperties()) {
      PropertyClass xwikiPropertyClass = (PropertyClass) xwikiPropertyClassObject;

      Property property = objectFactory.createProperty();
      property.setName(xwikiPropertyClass.getName());
      property.setType(xwikiPropertyClass.getxWikiClass().getName());

      for (java.lang.Object xwikiPropertyObject : xwikiPropertyClass.getProperties()) {
        com.xpn.xwiki.api.Property xwikiProperty = (com.xpn.xwiki.api.Property) xwikiPropertyObject;
        java.lang.Object value = xwikiProperty.getValue();

        Attribute attribute = objectFactory.createAttribute();
        attribute.setName(xwikiProperty.getName());

        if (value != null) {
          attribute.setValue(value.toString());
        } else {
          attribute.setValue("");
        }

        property.getAttributes().add(attribute);
      }

      String propertyUri =
          uri(
              baseUri,
              ClassPropertyResource.class,
              wikiName,
              xwikiClass.getName(),
              xwikiPropertyClass.getName());
      Link propertyLink = objectFactory.createLink();
      propertyLink.setHref(propertyUri);
      propertyLink.setRel(Relations.SELF);
      property.getLinks().add(propertyLink);

      clazz.getProperties().add(property);
    }

    String classUri = uri(baseUri, ClassResource.class, wikiName, xwikiClass.getName());
    Link classLink = objectFactory.createLink();
    classLink.setHref(classUri);
    classLink.setRel(Relations.SELF);
    clazz.getLinks().add(classLink);

    String propertiesUri =
        uri(baseUri, ClassPropertiesResource.class, wikiName, xwikiClass.getName());
    Link propertyLink = objectFactory.createLink();
    propertyLink.setHref(propertiesUri);
    propertyLink.setRel(Relations.PROPERTIES);
    clazz.getLinks().add(propertyLink);

    String objectsUri =
        uri(baseUri, AllObjectsForClassNameResource.class, wikiName, xwikiClass.getName());
    Link objectsLink = objectFactory.createLink();
    objectsLink.setHref(objectsUri);
    objectsLink.setRel(Relations.OBJECTS);
    clazz.getLinks().add(objectsLink);

    return clazz;
  }
  public static Object createObject(
      ObjectFactory objectFactory,
      URI baseUri,
      XWikiContext xwikiContext,
      Document doc,
      BaseObject xwikiObject,
      boolean useVersion,
      XWiki xwikiApi,
      Boolean withPrettyNames)
      throws XWikiException {
    Object object = objectFactory.createObject();
    fillObjectSummary(object, objectFactory, baseUri, doc, xwikiObject, xwikiApi, withPrettyNames);

    BaseClass xwikiClass = xwikiObject.getXClass(xwikiContext);

    for (java.lang.Object propertyClassObject : xwikiClass.getProperties()) {
      com.xpn.xwiki.objects.classes.PropertyClass propertyClass =
          (com.xpn.xwiki.objects.classes.PropertyClass) propertyClassObject;

      Property property = objectFactory.createProperty();

      for (java.lang.Object o : propertyClass.getProperties()) {
        BaseProperty baseProperty = (BaseProperty) o;
        Attribute attribute = objectFactory.createAttribute();
        attribute.setName(baseProperty.getName());

        /* Check for null values in order to prevent NPEs */
        if (baseProperty.getValue() != null) {
          attribute.setValue(baseProperty.getValue().toString());
        } else {
          attribute.setValue("");
        }

        property.getAttributes().add(attribute);
      }

      if (propertyClass instanceof ListClass) {
        ListClass listClass = (ListClass) propertyClass;

        List allowedValueList = listClass.getList(xwikiContext);

        if (!allowedValueList.isEmpty()) {
          Formatter f = new Formatter();
          for (int i = 0; i < allowedValueList.size(); i++) {
            if (i != allowedValueList.size() - 1) {
              f.format("%s,", allowedValueList.get(i).toString());
            } else {
              f.format("%s", allowedValueList.get(i).toString());
            }
          }

          Attribute attribute = objectFactory.createAttribute();
          attribute.setName(Constants.ALLOWED_VALUES_ATTRIBUTE_NAME);
          attribute.setValue(f.toString());
          property.getAttributes().add(attribute);
        }
      }

      property.setName(propertyClass.getName());
      property.setType(propertyClass.getClassType());
      if (xwikiObject.get(propertyClass.getName()) != null) {
        property.setValue(xwikiObject.get(propertyClass.getName()).toFormString());
      } else {
        property.setValue("");
      }

      String propertyUri;

      if (useVersion) {
        propertyUri =
            uri(
                baseUri,
                ObjectPropertyAtPageVersionResource.class,
                doc.getWiki(),
                doc.getSpace(),
                doc.getName(),
                doc.getVersion(),
                xwikiObject.getClassName(),
                xwikiObject.getNumber(),
                propertyClass.getName());
      } else {
        propertyUri =
            uri(
                baseUri,
                ObjectPropertyResource.class,
                doc.getWiki(),
                doc.getSpace(),
                doc.getName(),
                xwikiObject.getClassName(),
                xwikiObject.getNumber(),
                propertyClass.getName());
      }
      Link propertyLink = objectFactory.createLink();
      propertyLink.setHref(propertyUri);
      propertyLink.setRel(Relations.SELF);
      property.getLinks().add(propertyLink);

      object.getProperties().add(property);
    }

    Link objectLink =
        getObjectLink(objectFactory, baseUri, doc, xwikiObject, useVersion, Relations.SELF);
    object.getLinks().add(objectLink);

    return object;
  }
  @Override
  public Property getObjectProperty(
      String wikiName,
      String spaceName,
      String pageName,
      String version,
      String className,
      Integer objectNumber,
      String propertyName,
      Boolean withPrettyNames)
      throws XWikiRestException {
    try {
      DocumentInfo documentInfo =
          getDocumentInfo(wikiName, spaceName, pageName, null, version, true, false);

      Document doc = documentInfo.getDocument();

      XWikiDocument xwikiDocument =
          Utils.getXWiki(componentManager)
              .getDocument(doc.getPrefixedFullName(), Utils.getXWikiContext(componentManager));

      xwikiDocument =
          Utils.getXWiki(componentManager)
              .getDocument(
                  xwikiDocument, doc.getVersion(), Utils.getXWikiContext(componentManager));

      com.xpn.xwiki.objects.BaseObject baseObject =
          xwikiDocument.getObject(className, objectNumber);
      if (baseObject == null) {
        throw new WebApplicationException(Status.NOT_FOUND);
      }

      Object object =
          DomainObjectFactory.createObject(
              objectFactory,
              uriInfo.getBaseUri(),
              Utils.getXWikiContext(componentManager),
              doc,
              baseObject,
              true,
              Utils.getXWikiApi(componentManager),
              withPrettyNames);

      for (Property property : object.getProperties()) {
        if (property.getName().equals(propertyName)) {
          String objectUri =
              Utils.createURI(
                      uriInfo.getBaseUri(),
                      ObjectAtPageVersionResource.class,
                      doc.getWiki(),
                      doc.getSpace(),
                      doc.getName(),
                      version,
                      object.getClassName(),
                      object.getNumber())
                  .toString();
          Link objectLink = objectFactory.createLink();
          objectLink.setHref(objectUri);
          objectLink.setRel(Relations.OBJECT);
          property.getLinks().add(objectLink);

          return property;
        }
      }

      throw new WebApplicationException(Status.NOT_FOUND);
    } catch (XWikiException e) {
      throw new XWikiRestException(e);
    }
  }