/******************************************************************************* * 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 java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; import org.apache.commons.lang.StringUtils; import org.eclipse.skalli.commons.FormatUtils; import org.eclipse.skalli.commons.XMLUtils; import org.eclipse.skalli.model.Member; import org.eclipse.skalli.model.Project; import org.eclipse.skalli.services.project.ProjectService; import org.eclipse.skalli.testutil.BundleManager; import org.eclipse.skalli.testutil.MarshallingContextMock; import org.eclipse.skalli.testutil.SchemaValidationUtils; import org.eclipse.skalli.testutil.StringBufferHierarchicalStreamWriter; import org.eclipse.skalli.testutil.XMLDiffUtil; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.w3c.dom.Document; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; @SuppressWarnings("nls") public class ProjectConverterTest { private static class ProjectConverterWrapper extends ProjectConverter { public ProjectConverterWrapper(String host, String[] extensions) { super(host, extensions); } @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { writer.startNode("project"); super.marshal(source, writer, context); writer.endNode(); } } private static class ProjectsConverterWrapper extends ProjectsConverter { public ProjectsConverterWrapper(String host, String[] extensions) { super(host, extensions); } @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { writer.startNode("projects"); super.marshal(source, writer, context); writer.endNode(); } } private List<Project> projects; private ProjectService projectService; @Before public void setup() throws Exception { projectService = BundleManager.getRequiredService(ProjectService.class); projects = projectService.getAll(); Assert.assertTrue("projects.size() > 0", projects.size() > 0); } @Test public void testMarshal() throws Exception { for (Project project : projects) { StringBufferHierarchicalStreamWriter writer = new StringBufferHierarchicalStreamWriter(); ProjectConverterWrapper converter = new ProjectConverterWrapper("https://localhost", new String[] { "members" }); MarshallingContext context = new MarshallingContextMock(writer); converter.marshal(project, writer, context); // marshal the expected result String expected = marshalExpected(writer, project); // compare marshaled and expected output Document expectedDoc = XMLUtils.documentFromString(expected.toString()); Document actualDoc = XMLUtils.documentFromString(writer.toString()); XMLDiffUtil.assertEquals(expectedDoc, actualDoc); } } private String marshalExpected(HierarchicalStreamWriter writer, Project project) throws Exception { // render the expected output of the writer StringBuilder expected = new StringBuilder(); expected.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); expected.append("<project xmlns=\"http://www.eclipse.org/skalli/2010/API\" "); expected.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "); expected.append("xsi:schemaLocation=\"http://www.eclipse.org/skalli/2010/API "); expected.append("https://localhost/schemas/project.xsd\" "); expected.append("apiVersion=\"").append(ProjectConverter.API_VERSION).append("\" "); expected.append("lastModified=\"").append(project.getLastModified()).append("\" "); expected.append("modifiedBy=\"").append(project.getLastModifiedBy()).append("\">"); expected.append(" <uuid>").append(project.getUuid().toString()).append("</uuid>"); expected.append(" <id>").append(enc(project.getProjectId())).append("</id>"); expected.append(" <nature>PROJECT</nature>"); expected.append(" <template>").append(enc(project.getProjectTemplateId())).append("</template>"); expected.append(" <name>").append(enc(project.getName())).append("</name>"); expected.append(" <shortName>").append(enc(project.getShortName())).append("</shortName>"); expected.append(" <link rel=\"project\" href=\"https://localhost/api/projects/"); expected.append(project.getUuid().toString()).append("\"/>"); expected.append(" <link rel=\"browse\" href=\"https://localhost/projects/"); expected.append(project.getProjectId()).append("\"/>"); expected.append(" <link rel=\"issues\" href=\"https://localhost/api/projects/"); expected.append(project.getUuid().toString()).append("/issues\"/>"); expected.append(" <phase>").append(enc(project.getPhase())).append("</phase>"); if (project.getRegistered() > 0) { expected.append(" <registered millis=\"").append(project.getRegistered()).append("\">"); expected.append(FormatUtils.formatUTC(project.getRegistered())).append("</registered>"); } if (StringUtils.isNotBlank(enc(project.getDescription()))) { expected.append(" <description>").append(enc(project.getDescription())).append("</description>"); } if (project.getParentEntityId() != null) { expected.append(" <link rel=\"parent\" href=\"https://localhost/api/projects/"); expected.append(enc(project.getParentEntityId().toString())).append("\"/>"); } SortedSet<Project> subprojects = project.getSubProjects(); if (subprojects.size() > 0) { expected.append(" <subprojects>"); for (Project subproject : subprojects) { expected.append(" <link rel=\"subproject\" href=\"https://localhost/api/projects/"); expected.append(enc(subproject.getUuid().toString())).append("\"/>"); } expected.append(" </subprojects>"); } Set<Member> allPeople = projectService.getMembers(project.getUuid()); if (allPeople.size() > 0) { expected.append(" <members>"); for (Member member : allPeople) { expected.append(" <member>"); expected.append(" <userId>").append(enc(member.getUserID())).append("</userId>"); expected.append(" <link rel=\"user\" href=\"https://localhost/api/user/"); expected.append(enc(member.getUserID())).append("\"/>"); for (Entry<String, SortedSet<Member>> entry : projectService.getMembersByRole(project.getUuid()).entrySet()) { if (entry.getValue().contains(member)) { expected.append(" <role>").append(enc(entry.getKey())).append("</role>"); } } expected.append(" </member>"); } expected.append(" </members>"); } else { expected.append(" <members/>"); } expected.append(" <extensions/>"); expected.append("</project>"); return expected.toString(); } @Test public void testValidate() throws Exception { SchemaValidationUtils.validate(projects, new ProjectConverterWrapper("https://localhost", new String[] { "members" }), "project.xsd"); Projects plist = new Projects(projects); SchemaValidationUtils.validate(plist, new ProjectsConverterWrapper("https://localhost", new String[] { "members" }), "projects.xsd"); } private String enc(String s) { if (s == null) { return null; } StringBuffer buffer = new StringBuffer(); for (int i = 0; i < s.length(); i++) { switch (s.charAt(i)) { case '&': buffer.append("&"); //$NON-NLS-1$ continue; case '<': buffer.append("<"); //$NON-NLS-1$ continue; case '>': buffer.append(">"); //$NON-NLS-1$ continue; case '\'': buffer.append("'"); //$NON-NLS-1$ continue; case '"': buffer.append("""); //$NON-NLS-1$ continue; case '\r': buffer.append(" "); //$NON-NLS-1$ continue; default: buffer.append(s.charAt(i)); } } return buffer.toString(); } }