/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.core.rest.resources;
import static org.eclipse.skalli.core.rest.resources.ConverterTestUtils.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.UUID;
import org.eclipse.skalli.commons.CollectionUtils;
import org.eclipse.skalli.core.extension.info.ExtensionServiceInfo;
import org.eclipse.skalli.core.extension.info.InfoConverter;
import org.eclipse.skalli.core.extension.tags.ExtensionServiceTags;
import org.eclipse.skalli.core.extension.tags.TagsConverter;
import org.eclipse.skalli.core.rest.JSONRestWriter;
import org.eclipse.skalli.core.rest.XMLRestWriter;
import org.eclipse.skalli.model.Member;
import org.eclipse.skalli.model.Project;
import org.eclipse.skalli.services.extension.ExtensionService;
import org.eclipse.skalli.services.rest.RestWriter;
import org.eclipse.skalli.testutil.RestWriterTestBase;
import org.eclipse.skalli.testutil.TestUUIDs;
import org.junit.Test;
@SuppressWarnings("nls")
public class CommonProjectConverterTest extends RestWriterTestBase {
public static final UUID[] SUBPROJECT_UUIDS = {
TestUUIDs.TEST_UUIDS[3], TestUUIDs.TEST_UUIDS[4], TestUUIDs.TEST_UUIDS[5]
};
public static final Member[] MEMBERS = new Member[]{new Member("homer"), new Member("marge"),
new Member("bart"), new Member("lisa")};
public static final SortedSet<Member> ALL_MEMBERS = CollectionUtils.asSortedSet(MEMBERS);
public static final Map<String,SortedSet<Member>> MEMBERS_BY_ROLE = new HashMap<String,SortedSet<Member>>();
static {
MEMBERS_BY_ROLE.put("leads", CollectionUtils.asSortedSet(MEMBERS[0], MEMBERS[1]));
MEMBERS_BY_ROLE.put("members", CollectionUtils.asSortedSet(MEMBERS));
}
public static final List<ExtensionService<?>> EXTENSION_SERVICES = new ArrayList<ExtensionService<?>>();
static {
EXTENSION_SERVICES.add(new ExtensionServiceInfo());
EXTENSION_SERVICES.add(new ExtensionServiceTags());
}
public static final String PROJECT_ATTRIBUTES_XML(boolean omitAttributes) {
return omitAttributes? "" :
MessageFormat.format(
" apiVersion=\"{0}\""
+ " lastModifiedMillis=\"{1}\""
+ " lastModified=\"{2}\""
+ " modifiedBy=\"{3}\"",
CommonProjectConverter.API_VERSION,
LAST_MODIFIED_MILLIS, LAST_MODIFIED, LAST_MODIFIER);
}
public static final String ROOT_XML(boolean omitAttributes) {
return MessageFormat.format(
"<project{0}>", PROJECT_ATTRIBUTES_XML(omitAttributes));
}
public static final String REGISTERED_XML = MessageFormat.format(
"<registered millis=\"{0}\">{1}</registered>",
REGISTERED_MILLIS, REGISTERED);
public static final String COMMON_SECTION_XML(UUID uuid, String id, String name, boolean omitAttributes) {
return MessageFormat.format(
"{0}"
+ "<uuid>{1}</uuid>"
+ "<id>{2}</id>"
+ "<nature>PROJECT</nature>"
+ "<template>default</template>"
+ "<name>{3}</name>",
ROOT_XML(omitAttributes), uuid, id, name);
}
public static final String LINKS_SECTION_XML(UUID uuid, String id) {
return MessageFormat.format(
"<link rel=\"project\" href=\"http://example.org/api/projects/{0}\"/>"
+ "<link rel=\"permalink\" href=\"http://example.org/projects/{0}\"/>"
+ "<link rel=\"browse\" href=\"http://example.org/projects/{1}\"/>"
+ "<link rel=\"issues\" href=\"http://example.org/api/projects/{0}/issues\"/>"
+ "<link rel=\"subprojects\" href=\"http://example.org/api/projects/{0}/subprojects\"/>",
uuid, id);
}
public static final String SUBPROJECTLINKS_SECTION_XML(UUID...uuids) {
return MessageFormat.format(
"<subprojects>"
+ "<link rel=\"subproject\" href=\"http://example.org/api/projects/{0}\"/>"
+ "<link rel=\"subproject\" href=\"http://example.org/api/projects/{1}\"/>"
+ "<link rel=\"subproject\" href=\"http://example.org/api/projects/{2}\"/>"
+ "</subprojects>",
(Object[])uuids);
}
public static final String MEMBERS_SECTION_XML() {
return "<members>"
+ "<member><userId>bart</userId><link rel=\"user\" href=\"http://example.org/api/users/bart\"/>"
+ "<role>members</role></member>"
+ "<member><userId>homer</userId><link rel=\"user\" href=\"http://example.org/api/users/homer\"/>"
+ "<role>leads</role><role>members</role></member>"
+ "<member><userId>lisa</userId><link rel=\"user\" href=\"http://example.org/api/users/lisa\"/>"
+ "<role>members</role></member>"
+ "<member><userId>marge</userId><link rel=\"user\" href=\"http://example.org/api/users/marge\"/>"
+ "<role>leads</role><role>members</role></member>"
+ "</members>";
}
public static final String ATTRIBUTES_INFO_EXTENSION =
MessageFormat.format(ATTRIBUTES_PATTERN + " lastModifiedMillis=\"{3}\" lastModified=\"{4}\" inherited=\"true\" derived=\"false\"",
InfoConverter.NAMESPACE, "extension-info", InfoConverter.API_VERSION, LAST_MODIFIED_MILLIS, LAST_MODIFIED);
public static final String ATTRIBUTES_TAGS_EXTENSION =
MessageFormat.format(ATTRIBUTES_PATTERN + " modifiedBy=\"{3}\" inherited=\"false\" derived=\"false\"",
TagsConverter.NAMESPACE, "extension-tags", TagsConverter.API_VERSION, LAST_MODIFIER);
public static final String EXTENSIONS_SECTION_XML() {
return MessageFormat.format("<extensions>"
+ "<info {0}><homepage>foobar</homepage><mailingLists/></info>"
+ "<tags {1}><tag>a</tag><tag>b</tag></tags>"
+ "</extensions>", ATTRIBUTES_INFO_EXTENSION, ATTRIBUTES_TAGS_EXTENSION);
}
public static final String MINIMAL_PROJECT_BEGIN_XML(UUID uuid, String id, String name, boolean omitAttributes) {
return COMMON_SECTION_XML(uuid, id, name, omitAttributes)
+ "<phase>initial</phase>"
+ "<descriptionFormat>text</descriptionFormat>"
+ LINKS_SECTION_XML(uuid, id);
}
public static final String MINIMAL_PROJECT_XML(UUID uuid, String id, String name, boolean omitAttributes) {
return MINIMAL_PROJECT_BEGIN_XML(uuid, id, name, omitAttributes)
+ "<subprojects/><members/><extensions/></project>";
}
public static final String BASE_PROJECT_BEGIN_XML(UUID uuid, UUID parent, boolean omitAttributes) {
return COMMON_SECTION_XML(uuid, "foo", "bar", omitAttributes)
+ "<shortName>sh1</shortName>"
+ "<phase>initial</phase>"
+ REGISTERED_XML
+ "<descriptionFormat>text</descriptionFormat>"
+ "<description>descr1</description>"
+ LINKS_SECTION_XML(uuid, "foo")
+ "<link rel=\"parent\" href=\"http://example.org/api/projects/" + parent + "\"/>";
}
public static final String BASE_PROJECT_XML(UUID uuid, UUID parent, boolean omitAttributes) {
return BASE_PROJECT_BEGIN_XML(uuid, parent, omitAttributes)
+ "<subprojects/><members/><extensions/></project>";
}
public static final String PROJECT_WITH_SUBPROJECTS_XML(UUID uuid, boolean omitAttributes, UUID...subprojects) {
return MINIMAL_PROJECT_BEGIN_XML(uuid, "foo", "bar", omitAttributes)
+ SUBPROJECTLINKS_SECTION_XML(subprojects)
+ "<members/><extensions/></project>";
}
public static final String REGISTERED_JSON = MessageFormat.format(
"\"registered\":'{'\"millis\":{0},\"value\":\"{1}\"}",
REGISTERED_MILLIS, REGISTERED);
public static final String PROJECT_ATTRIBUTES_JSON(boolean omitAttributes) {
return omitAttributes? "" :
MessageFormat.format(
"\"apiVersion\":\"{0}\","
+ "\"lastModifiedMillis\":{1},"
+ "\"lastModified\":\"{2}\","
+ "\"modifiedBy\":\"{3}\",",
CommonProjectConverter.API_VERSION,
LAST_MODIFIED_MILLIS, LAST_MODIFIED, LAST_MODIFIER);
}
public static final String ROOT_JSON(boolean omitAttributes) {
return MessageFormat.format(
"'{'{0}", PROJECT_ATTRIBUTES_JSON(omitAttributes));
}
public static final String COMMON_SECTION_JSON(UUID uuid, String id, String name, boolean omitAttributes) {
return MessageFormat.format(
"{0}"
+"\"uuid\":\"{1}\","
+ "\"id\":\"{2}\","
+ "\"nature\":\"PROJECT\","
+ "\"template\":\"default\","
+ "\"name\":\"{3}\"",
ROOT_JSON(omitAttributes), uuid, id, name);
}
public static final String LINKS_SECTION_JSON(UUID uuid, String id) {
return MessageFormat.format(
"'{'\"rel\":\"project\",\"href\":\"http://example.org/api/projects/{0}\"},"
+ "'{'\"rel\":\"permalink\",\"href\":\"http://example.org/projects/{0}\"},"
+ "'{'\"rel\":\"browse\",\"href\":\"http://example.org/projects/{1}\"},"
+ "'{'\"rel\":\"issues\",\"href\":\"http://example.org/api/projects/{0}/issues\"},"
+ "'{'\"rel\":\"subprojects\",\"href\":\"http://example.org/api/projects/{0}/subprojects\"}",
uuid, id);
}
public static final String SUBPROJECTLINKS_SECTION_JSON(UUID...uuids) {
return MessageFormat.format(
"\"subprojects\":["
+ "'{'\"rel\":\"subproject\",\"href\":\"http://example.org/api/projects/{0}\","
+ "\"uuid\":\"{0}\",\"id\":\"id1\",\"name\":\"name1\"},"
+ "'{'\"rel\":\"subproject\",\"href\":\"http://example.org/api/projects/{1}\","
+ "\"uuid\":\"{1}\",\"id\":\"id2\",\"name\":\"name2\"},"
+ "'{'\"rel\":\"subproject\",\"href\":\"http://example.org/api/projects/{2}\","
+ "\"uuid\":\"{2}\",\"id\":\"id3\",\"name\":\"name3\"}"
+ "]",
(Object[])uuids);
}
public static final String MEMBERS_SECTION_JSON() {
return "{\"members\":["
+ "{\"userId\":\"bart\",\"link\":{\"rel\":\"user\",\"href\":\"http://example.org/api/users/bart\"},"
+ "\"roles\":[\"members\"]},"
+ "{\"userId\":\"homer\",\"link\":{\"rel\":\"user\",\"href\":\"http://example.org/api/users/homer\"},"
+ "\"roles\":[\"leads\",\"members\"]},"
+ "{\"userId\":\"lisa\",\"link\":{\"rel\":\"user\",\"href\":\"http://example.org/api/users/lisa\"},"
+ "\"roles\":[\"members\"]},"
+ "{\"userId\":\"marge\",\"link\":{\"rel\":\"user\",\"href\":\"http://example.org/api/users/marge\"},"
+ "\"roles\":[\"leads\",\"members\"]}"
+ "]}";
}
public static final String EXTENSIONS_SECTION_JSON() {
return MessageFormat.format("'{'\"extensions\":'{'"
+ "\"info\":'{'\"namespace\":\"{0}\",\"apiVersion\":\"{1}\",\"lastModifiedMillis\":{2},\"lastModified\":\"{3}\","
+ "\"inherited\":true,\"derived\":false,"
+ "\"homepage\":\"foobar\",\"mailingLists\":[]},"
+ "\"tags\":'{'\"namespace\":\"{4}\",\"apiVersion\":\"{5}\",\"modifiedBy\":\"{6}\","
+ "\"inherited\":false,\"derived\":false,"
+ "\"items\":[\"a\",\"b\"]}"
+ "}}",
InfoConverter.NAMESPACE, InfoConverter.API_VERSION, LAST_MODIFIED_MILLIS, LAST_MODIFIED,
TagsConverter.NAMESPACE, TagsConverter.API_VERSION, LAST_MODIFIER);
}
public static final String MINIMAL_PROJECT_BEGIN_JSON(UUID uuid, String id, String name, boolean omitAttributes) {
return COMMON_SECTION_JSON(uuid, id, name, omitAttributes)
+ ",\"phase\":\"initial\""
+ ",\"descriptionFormat\":\"text\""
+ ",\"links\":[" + LINKS_SECTION_JSON(uuid, id) + "]";
}
public static final String MINIMAL_PROJECT_JSON(UUID uuid, String id, String name, boolean omitAttributes) {
return MINIMAL_PROJECT_BEGIN_JSON(uuid, id, name, omitAttributes)
+ ",\"subprojects\":[],\"members\":[],\"extensions\":{}}";
}
public static final String BASE_PROJECT_BEGIN_JSON(UUID uuid, UUID parent, boolean omitAttributes) {
return COMMON_SECTION_JSON(uuid, "foo", "bar", omitAttributes)
+ ",\"shortName\":\"sh1\","
+ "\"phase\":\"initial\","
+ REGISTERED_JSON
+ ",\"descriptionFormat\":\"text\""
+ ",\"description\":\"descr1\""
+ ",\"links\":[" + LINKS_SECTION_JSON(uuid, "foo")
+ ",{\"rel\":\"parent\",\"href\":\"http://example.org/api/projects/" + parent + "\""
+ ",\"uuid\":\"" + parent + "\",\"id\":\"parent\",\"name\":\"Parent\"}]";
}
public static final String BASE_PROJECT_JSON(UUID uuid, UUID parent, boolean omitAttributes) {
return BASE_PROJECT_BEGIN_JSON(uuid, parent, omitAttributes)
+ ",\"subprojects\":[],\"members\":[],\"extensions\":{}}";
}
public static final String PROJECT_WITH_SUBPROJECTS_JSON(UUID uuid, boolean omitAttributes, UUID...subprojects) {
return MINIMAL_PROJECT_BEGIN_JSON(uuid, "foo", "bar", omitAttributes)
+ "," + SUBPROJECTLINKS_SECTION_JSON(subprojects)
+",\"members\":[],\"extensions\":{}}";
}
public static final String PROJECT_WITH_MEMBERS_JSON(UUID uuid, boolean omitAttributes) {
return MINIMAL_PROJECT_BEGIN_JSON(uuid, "foo", "bar", omitAttributes)
+ ",\"subprojects\":[]"
+ "," + MEMBERS_SECTION_JSON()
+ ",\"extensions\":{}}";
}
@Test
public void testMarshalMinimalProjectXML() throws Exception {
Project project = newMinimalProject();
XMLRestWriter restWriter = new XMLRestWriter(writer, "http://example.org");
marshalProject(project, restWriter);
assertEqualsXML(MINIMAL_PROJECT_XML(TestUUIDs.TEST_UUIDS[0], "foo", "bar", true));
}
@Test
public void testMarshalMinimalProjectJSON() throws Exception {
Project project = newMinimalProject();
JSONRestWriter restWriter = new JSONRestWriter(writer, "http://example.org");
marshalProject(project, restWriter);
assertEqualsJSON(MINIMAL_PROJECT_JSON(TestUUIDs.TEST_UUIDS[0], "foo", "bar", true));
}
@Test
public void testMarshalProjectNoExtensionsXML() throws Exception {
Project project = newBaseProject();
XMLRestWriter restWriter = new XMLRestWriter(writer, "http://example.org");
marshalProject(project, restWriter);
assertEqualsXML(BASE_PROJECT_XML(TestUUIDs.TEST_UUIDS[0], TestUUIDs.TEST_UUIDS[1], true));
}
@Test
public void testMarshalProjectNoExtensionsJSON() throws Exception {
Project project = newBaseProject();
JSONRestWriter restWriter = new JSONRestWriter(writer, "http://example.org");
marshalProject(project, restWriter);
assertEqualsJSON(BASE_PROJECT_JSON(TestUUIDs.TEST_UUIDS[0], TestUUIDs.TEST_UUIDS[1], true));
}
@Test
public void testMarshalProjectWithSubprojectsXML() throws Exception {
Project project = newMinimalProjectWithSubProjects();
XMLRestWriter restWriter = new XMLRestWriter(writer, "http://example.org");
marshalProject(project, restWriter);
assertEqualsXML(PROJECT_WITH_SUBPROJECTS_XML(TestUUIDs.TEST_UUIDS[0], true, SUBPROJECT_UUIDS));
}
@Test
public void testMarshalProjectWithSubprojectsJSON() throws Exception {
Project project = newMinimalProjectWithSubProjects();
JSONRestWriter restWriter = new JSONRestWriter(writer, "http://example.org");
marshalProject(project, restWriter);
assertEqualsJSON(PROJECT_WITH_SUBPROJECTS_JSON(TestUUIDs.TEST_UUIDS[0], true, SUBPROJECT_UUIDS));
}
@Test
public void testMarshalMembersXML() throws Exception {
XMLRestWriter restWriter = new XMLRestWriter(writer, "http://example.org");
marshalMembers(ALL_MEMBERS, MEMBERS_BY_ROLE, restWriter);
assertEqualsXML(MEMBERS_SECTION_XML());
}
@Test
public void testMarshalMembersJSON() throws Exception {
JSONRestWriter restWriter = new JSONRestWriter(writer, "http://example.org");
restWriter.set(JSONRestWriter.NAMED_ROOT);
marshalMembers(ALL_MEMBERS, MEMBERS_BY_ROLE, restWriter);
assertEqualsJSON(MEMBERS_SECTION_JSON());
}
@Test
public void testMarshalProjectWithExtensionsXML() throws Exception {
Project project = newMinimalProjectWithExtensions();
XMLRestWriter restWriter = new XMLRestWriter(writer, "http://example.org");
marshalExtensions(project, EXTENSION_SERVICES, restWriter);
assertEqualsXML(EXTENSIONS_SECTION_XML());
}
@Test
public void testMarshalProjectWitExtensionsJSON() throws Exception {
Project project = newMinimalProjectWithExtensions();
JSONRestWriter restWriter = new JSONRestWriter(writer, "http://example.org");
marshalExtensions(project, EXTENSION_SERVICES, restWriter);
assertEqualsJSON(EXTENSIONS_SECTION_JSON());
}
private void marshalProject(Project project, RestWriter restWriter) throws Exception {
CommonProjectConverter converter = new CommonProjectConverter(CommonProjectConverter.ALL_EXTENSIONS);
restWriter.object("project");
converter.marshal(project, restWriter);
restWriter.end();
restWriter.flush();
}
private void marshalMembers(SortedSet<Member> members,
Map<String,SortedSet<Member>> membersByRole, RestWriter restWriter) throws Exception {
CommonProjectConverter converter = new CommonProjectConverter(CommonProjectConverter.ALL_EXTENSIONS);
restWriter.object();
converter.setRestWriter(restWriter);
converter.marshalMembers(TestUUIDs.TEST_UUIDS[0], members, membersByRole);
restWriter.end();
restWriter.flush();
}
private void marshalExtensions(Project project, Collection<ExtensionService<?>> extensionServices,
RestWriter restWriter) throws Exception {
CommonProjectConverter converter = new CommonProjectConverter(CommonProjectConverter.ALL_EXTENSIONS);
restWriter.object();
converter.setRestWriter(restWriter);
converter.marshalExtensions(project, extensionServices);
restWriter.end();
restWriter.flush();
}
}