diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..af19312 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +text=auto \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..407ac72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +target +.idea +*.iml +filter-dev.properties diff --git a/pom.xml b/pom.xml index 4b79bc6..1aa04c4 100644 --- a/pom.xml +++ b/pom.xml @@ -2,40 +2,25 @@ 4.0.0 - pl.itcrowd youtrack-rest-api 1.1.0-SNAPSHOT - - - - junit - junit - 4.8.2 - test - - - org.apache.httpcomponents - httpclient - 4.2-beta1 - - - commons-io - commons-io - 2.3 - - - org.mockito - mockito-all - 1.9.0-rc1 - test - - - + + scm:git:https://itcrowd.pl/gitblit/git/OpenSource/youtrack-rest-api.git + org.apache.maven.plugins + maven-release-plugin + 2.4.1 + + true + false + + + + org.apache.maven.plugins maven-source-plugin 2.1.2 @@ -48,17 +33,8 @@ - - maven-release-plugin - - true - false - true - - - generate-jaxb-artifacts @@ -76,10 +52,10 @@ - pl.itcrowd.youtrack.api.rest - ${project.build.sourceDirectory} false false + ${project.build.sourceDirectory} + pl.itcrowd.youtrack.api.rest @@ -92,7 +68,30 @@ - + + + commons-io + commons-io + 2.3 + + + org.apache.httpcomponents + httpclient + 4.2-beta1 + + + junit + junit + 4.8.2 + test + + + org.mockito + mockito-all + 1.9.0-rc1 + test + + itcrowd.pl @@ -105,9 +104,4 @@ http://artifactory.itcrowd.pl/libs-snapshot-local - - - scm:git:https://itcrowd.pl/gitblit/git/OpenSource/youtrack-rest-api.git - - diff --git a/src/main/java/pl/itcrowd/youtrack/api/URIUtils.java b/src/main/java/pl/itcrowd/youtrack/api/URIUtils.java index 87a0b41..01ad56f 100644 --- a/src/main/java/pl/itcrowd/youtrack/api/URIUtils.java +++ b/src/main/java/pl/itcrowd/youtrack/api/URIUtils.java @@ -2,12 +2,13 @@ package pl.itcrowd.youtrack.api; import java.net.URI; import java.net.URISyntaxException; +import java.util.Map; public class URIUtils { public static URI buildURI(URI base, String path) { - return buildURI(base, path, null); + return buildURI(base, path, (String) null); } public static URI buildURI(URI base, String path, String query) @@ -19,4 +20,15 @@ public class URIUtils { throw new RuntimeException(e); } } + + public static URI buildURI(URI base, String path, Map params) + { + final StringBuilder query = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (null != entry.getValue()) { + query.append("&").append(entry.getKey()).append("=").append(entry.getValue()); + } + } + return buildURI(base, path, query.length() > 0 ? query.substring(1) : query.toString()); + } } diff --git a/src/main/java/pl/itcrowd/youtrack/api/YoutrackAPI.java b/src/main/java/pl/itcrowd/youtrack/api/YoutrackAPI.java index 26d7786..5b911cf 100644 --- a/src/main/java/pl/itcrowd/youtrack/api/YoutrackAPI.java +++ b/src/main/java/pl/itcrowd/youtrack/api/YoutrackAPI.java @@ -35,6 +35,7 @@ import pl.itcrowd.youtrack.api.exceptions.YoutrackErrorException; import pl.itcrowd.youtrack.api.rest.AssigneeList; import pl.itcrowd.youtrack.api.rest.Enumeration; import pl.itcrowd.youtrack.api.rest.Issue; +import pl.itcrowd.youtrack.api.rest.IssueCompacts; import pl.itcrowd.youtrack.api.rest.Issues; import pl.itcrowd.youtrack.api.rest.User; import pl.itcrowd.youtrack.api.rest.UserRefs; @@ -57,7 +58,9 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,6 +80,36 @@ public class YoutrackAPI { private URI serviceLocationURI; + public YoutrackAPI(String serviceLocation) + { + this(serviceLocation, null); + } + + public YoutrackAPI(String serviceLocation, HttpClient httpClient) + { + if (serviceLocation == null) { + throw new IllegalArgumentException("serviceLocation cannot be null"); + } + this.serviceLocation = serviceLocation; + try { + serviceLocationURI = new URI(this.serviceLocation); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + this.httpClient = httpClient == null ? getDefaultHttpClient() : httpClient; + } + + public YoutrackAPI(String serviceLocation, String username, String password) throws IOException, JAXBException + { + this(serviceLocation, null, username, password); + } + + public YoutrackAPI(String serviceLocation, HttpClient httpClient, String username, String password) throws IOException, JAXBException + { + this(serviceLocation, httpClient); + login(username, password); + } + private static HttpClient getDefaultHttpClient() { SSLContext sslContext; @@ -129,34 +162,71 @@ public class YoutrackAPI { return true; } - public YoutrackAPI(String serviceLocation) + public AssigneeList getAssignees(String project) throws IOException, JAXBException { - this(serviceLocation, null); + final String responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/project/" + project + "/assignee"))); + final Object result = YoutrackUnmarshaller.unmarshall(responseString); + if (result instanceof AssigneeList) { + return (AssigneeList) result; + } else { + throw new YoutrackAPIException("Unexpected type: " + result); + } } - public YoutrackAPI(String serviceLocation, HttpClient httpClient) + public Enumeration getBundle(String customField) throws IOException, JAXBException { - if (serviceLocation == null) { - throw new IllegalArgumentException("serviceLocation cannot be null"); - } - this.serviceLocation = serviceLocation; - try { - serviceLocationURI = new URI(this.serviceLocation); - } catch (URISyntaxException e) { - throw new RuntimeException(e); + final Object result = YoutrackUnmarshaller.unmarshall( + execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/customfield/bundle/" + customField)))); + if (result instanceof Enumeration) { + return (Enumeration) result; + } else if (result instanceof JAXBElement) { + final JAXBElement jaxbElement = (JAXBElement) result; + if (Enumeration_QNAME.equals(jaxbElement.getName())) { + return (Enumeration) ((JAXBElement) result).getValue(); + } else { + throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); + } + } else { + throw new YoutrackAPIException("Unexpected type: " + result); } - this.httpClient = httpClient == null ? getDefaultHttpClient() : httpClient; } - public YoutrackAPI(String serviceLocation, String username, String password) throws IOException, JAXBException + public List getIndividualAssignees(String project) throws IOException, JAXBException { - this(serviceLocation, null, username, password); + final String responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/project/" + project + "/assignee/individual"))); + final Object result = YoutrackUnmarshaller.unmarshall(responseString); + if (result instanceof UserRefs) { + return ((UserRefs) result).getUsers(); + } else { + throw new YoutrackAPIException("Unexpected type: " + result); + } } - public YoutrackAPI(String serviceLocation, HttpClient httpClient, String username, String password) throws IOException, JAXBException + public IssueWrapper getIssue(String issueId) throws IOException, JAXBException { - this(serviceLocation, httpClient); - login(username, password); + final String responseString; + try { + responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/issue/" + issueId))); + } catch (YoutrackErrorException e) { + if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { + throw new NoResultFoundException(e.getMessage(), e); + } else { + throw e; + } + } + final Object result = YoutrackUnmarshaller.unmarshall(responseString); + if (result instanceof pl.itcrowd.youtrack.api.rest.Issue) { + return new IssueWrapper((Issue) result); + } else if (result instanceof JAXBElement) { + final JAXBElement jaxbElement = (JAXBElement) result; + if (Issue_QNAME.equals(jaxbElement.getName())) { + return new IssueWrapper((Issue) jaxbElement.getValue()); + } else { + throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); + } + } else { + throw new YoutrackAPIException("Unexpected type " + result); + } } public String getServiceLocation() @@ -233,78 +303,29 @@ public class YoutrackAPI { execute(new HttpDelete(buildURI(serviceLocationURI, "/rest/issue/" + issueId))); } - public AssigneeList getAssignees(String project) throws IOException, JAXBException - { - final String responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/project/" + project + "/assignee"))); - final Object result = YoutrackUnmarshaller.unmarshall(responseString); - if (result instanceof AssigneeList) { - return (AssigneeList) result; - } else { - throw new YoutrackAPIException("Unexpected type: " + result); - } - } - - public Enumeration getBundle(String customField) throws IOException, JAXBException - { - final Object result = YoutrackUnmarshaller.unmarshall( - execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/customfield/bundle/" + customField)))); - if (result instanceof Enumeration) { - return (Enumeration) result; - } else if (result instanceof JAXBElement) { - final JAXBElement jaxbElement = (JAXBElement) result; - if (Enumeration_QNAME.equals(jaxbElement.getName())) { - return (Enumeration) ((JAXBElement) result).getValue(); - } else { - throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); - } - } else { - throw new YoutrackAPIException("Unexpected type: " + result); - } - } - - public List getIndividualAssignees(String project) throws IOException, JAXBException + public void login(String username, String password) throws IOException, JAXBException { - final String responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/admin/project/" + project + "/assignee/individual"))); - final Object result = YoutrackUnmarshaller.unmarshall(responseString); - if (result instanceof UserRefs) { - return ((UserRefs) result).getUsers(); - } else { - throw new YoutrackAPIException("Unexpected type: " + result); - } + final HttpPost request = new HttpPost(buildURI(serviceLocationURI, "/rest/user/login")); + request.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("login", username), new BasicNameValuePair("password", password)))); + execute(request); } - public IssueWrapper getIssue(String issueId) throws IOException, JAXBException + public List searchIssues(Object filter, Integer maxResults, Integer after) throws JAXBException, IOException { - final String responseString; - try { - responseString = execute(new HttpGet(buildURI(serviceLocationURI, "/rest/issue/" + issueId))); - } catch (YoutrackErrorException e) { - if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { - throw new NoResultFoundException(e.getMessage(), e); - } else { - throw e; - } + final Map params = new HashMap(); + params.put("filter", filter); + params.put("max", maxResults); + params.put("after", after); + final Object result = YoutrackUnmarshaller.unmarshall(execute(new HttpGet(buildURI(serviceLocationURI, "/rest/issue", params)))); + if (!(result instanceof IssueCompacts)) { + throw new YoutrackAPIException("Unmarshalling problem. Expected Issues, received: " + result.getClass() + " " + result); } - final Object result = YoutrackUnmarshaller.unmarshall(responseString); - if (result instanceof pl.itcrowd.youtrack.api.rest.Issue) { - return new IssueWrapper((Issue) result); - } else if (result instanceof JAXBElement) { - final JAXBElement jaxbElement = (JAXBElement) result; - if (Issue_QNAME.equals(jaxbElement.getName())) { - return new IssueWrapper((Issue) jaxbElement.getValue()); - } else { - throw new YoutrackAPIException("Unexpected type: " + jaxbElement.getValue()); - } - } else { - throw new YoutrackAPIException("Unexpected type " + result); + List issues = ((IssueCompacts) result).getIssues(); + List wrappedIssues = new ArrayList(); + for (Issue issue : issues) { + wrappedIssues.add(new IssueWrapper(issue)); } - } - - public void login(String username, String password) throws IOException, JAXBException - { - final HttpPost request = new HttpPost(buildURI(serviceLocationURI, "/rest/user/login")); - request.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("login", username), new BasicNameValuePair("password", password)))); - execute(request); + return wrappedIssues; } public List searchIssuesByProject(String project, Object filter) throws JAXBException, IOException @@ -345,7 +366,7 @@ public class YoutrackAPI { private String execute(HttpUriRequest request) throws IOException { - request.addHeader("Accept","application/xml"); + request.addHeader("Accept", "application/xml"); final HttpResponse response = httpClient.execute(request); final StatusLine statusLine = response.getStatusLine(); final HttpEntity entity = response.getEntity(); diff --git a/src/main/java/pl/itcrowd/youtrack/api/rest/IssueCompacts.java b/src/main/java/pl/itcrowd/youtrack/api/rest/IssueCompacts.java new file mode 100644 index 0000000..314c198 --- /dev/null +++ b/src/main/java/pl/itcrowd/youtrack/api/rest/IssueCompacts.java @@ -0,0 +1,68 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// +package pl.itcrowd.youtrack.api.rest; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.util.ArrayList; +import java.util.List; + +/** + *

Java class for anonymous complex type. + *

+ *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence maxOccurs="unbounded" minOccurs="0">
+ *         <element name="issue" type="{}issueType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = {"issues"}) +@XmlRootElement(name = "issueCompacts") +public class IssueCompacts { + + @XmlElement(name = "issue") + protected List issues; + + /** + * Gets the value of the issues property. + *

+ *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the issues property. + *

+ *

+ * For example, to add a new item, do as follows: + *

+     *    getIssues().add(newItem);
+     * 
+ *

+ *

+ *

+ * Objects of the following type(s) are allowed in the list + * {@link Issue } + */ + public List getIssues() + { + if (issues == null) { + issues = new ArrayList(); + } + return this.issues; + } +} diff --git a/src/main/java/pl/itcrowd/youtrack/api/rest/ObjectFactory.java b/src/main/java/pl/itcrowd/youtrack/api/rest/ObjectFactory.java index 75efb9e..2eae2b5 100644 --- a/src/main/java/pl/itcrowd/youtrack/api/rest/ObjectFactory.java +++ b/src/main/java/pl/itcrowd/youtrack/api/rest/ObjectFactory.java @@ -26,22 +26,22 @@ import javax.xml.namespace.QName; @XmlRegistry public class ObjectFactory { - private final static QName _Error_QNAME = new QName("", "error"); - - private final static QName _Int_QNAME = new QName("", "int"); - - private final static QName _Issue_QNAME = new QName("", "issue"); - - private final static QName _Enumeration_QNAME = new QName("", "enumeration"); - private final static QName _CommentReplies_QNAME = new QName("", "replies"); private final static QName _CommentValue_QNAME = new QName("", "value"); + private final static QName _Enumeration_QNAME = new QName("", "enumeration"); + private final static QName _ErrorTypeField_QNAME = new QName("", "field"); private final static QName _ErrorTypeMessage_QNAME = new QName("", "message"); + private final static QName _Error_QNAME = new QName("", "error"); + + private final static QName _Int_QNAME = new QName("", "int"); + + private final static QName _Issue_QNAME = new QName("", "issue"); + /** * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: pl.itcrowd.youtrack.api.rest */ @@ -50,83 +50,86 @@ public class ObjectFactory { } /** - * Create an instance of {@link Field } + * Create an instance of {@link AssignedByType } */ - public Field createField() + public AssignedByType createAssignedByType() { - return new Field(); + return new AssignedByType(); } /** - * Create an instance of {@link Enumeration } + * Create an instance of {@link AssigneeList } */ - public Enumeration createEnumeration() + public AssigneeList createAssigneeList() { - return new Enumeration(); + return new AssigneeList(); } /** - * Create an instance of {@link User } + * Create an instance of {@link AssigneeList.Assignees } */ - public User createUser() + public AssigneeList.Assignees createAssigneeListAssignees() { - return new User(); + return new AssigneeList.Assignees(); } /** - * Create an instance of {@link UserRefs } + * Create an instance of {@link AssigneeType } */ - public UserRefs createUserRefs() + public AssigneeType createAssigneeType() { - return new UserRefs(); + return new AssigneeType(); } /** - * Create an instance of {@link Issues } + * Create an instance of {@link Comment } */ - public Issues createIssues() + public Comment createComment() { - return new Issues(); + return new Comment(); } /** - * Create an instance of {@link AssigneeList } + * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} */ - public AssigneeList createAssigneeList() + @XmlElementDecl(namespace = "", name = "replies", scope = Comment.class) + public JAXBElement createCommentReplies(String value) { - return new AssigneeList(); + return new JAXBElement(_CommentReplies_QNAME, String.class, Comment.class, value); } /** - * Create an instance of {@link Field.Value } + * Create an instance of {@link Comment.Value } */ - public Field.Value createFieldValue() + public Comment.Value createCommentValue() { - return new Field.Value(); + return new Comment.Value(); } /** - * Create an instance of {@link AssigneeType } + * Create an instance of {@link JAXBElement }{@code <}{@link Comment.Value }{@code >}} */ - public AssigneeType createAssigneeType() + @XmlElementDecl(namespace = "", name = "value", scope = Comment.class) + public JAXBElement createCommentValue(Comment.Value value) { - return new AssigneeType(); + return new JAXBElement(_CommentValue_QNAME, Comment.Value.class, Comment.class, value); } /** - * Create an instance of {@link ErrorType } + * Create an instance of {@link Enumeration } */ - public ErrorType createErrorType() + public Enumeration createEnumeration() { - return new ErrorType(); + return new Enumeration(); } /** - * Create an instance of {@link AssignedByType } + * Create an instance of {@link JAXBElement }{@code <}{@link Enumeration }{@code >}} */ - public AssignedByType createAssignedByType() + @XmlElementDecl(namespace = "", name = "enumeration") + public JAXBElement createEnumeration(Enumeration value) { - return new AssignedByType(); + return new JAXBElement(_Enumeration_QNAME, Enumeration.class, null, value); } /** @@ -138,52 +141,54 @@ public class ObjectFactory { } /** - * Create an instance of {@link AssigneeList.Assignees } + * Create an instance of {@link JAXBElement }{@code <}{@link ErrorType }{@code >}} */ - public AssigneeList.Assignees createAssigneeListAssignees() + @XmlElementDecl(namespace = "", name = "error") + public JAXBElement createError(ErrorType value) { - return new AssigneeList.Assignees(); + return new JAXBElement(_Error_QNAME, ErrorType.class, null, value); } /** - * Create an instance of {@link UserGroupRefType } + * Create an instance of {@link ErrorType } */ - public UserGroupRefType createUserGroupRefType() + public ErrorType createErrorType() { - return new UserGroupRefType(); + return new ErrorType(); } /** - * Create an instance of {@link Comment } + * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} */ - public Comment createComment() + @XmlElementDecl(namespace = "", name = "field", scope = ErrorType.class) + public JAXBElement createErrorTypeField(String value) { - return new Comment(); + return new JAXBElement(_ErrorTypeField_QNAME, String.class, ErrorType.class, value); } /** - * Create an instance of {@link Comment.Value } + * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} */ - public Comment.Value createCommentValue() + @XmlElementDecl(namespace = "", name = "message", scope = ErrorType.class) + public JAXBElement createErrorTypeMessage(String value) { - return new Comment.Value(); + return new JAXBElement(_ErrorTypeMessage_QNAME, String.class, ErrorType.class, value); } /** - * Create an instance of {@link Issue } + * Create an instance of {@link Field } */ - public Issue createIssue() + public Field createField() { - return new Issue(); + return new Field(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link ErrorType }{@code >}} + * Create an instance of {@link Field.Value } */ - @XmlElementDecl(namespace = "", name = "error") - public JAXBElement createError(ErrorType value) + public Field.Value createFieldValue() { - return new JAXBElement(_Error_QNAME, ErrorType.class, null, value); + return new Field.Value(); } /** @@ -196,6 +201,14 @@ public class ObjectFactory { } /** + * Create an instance of {@link Issue } + */ + public Issue createIssue() + { + return new Issue(); + } + + /** * Create an instance of {@link JAXBElement }{@code <}{@link Issue }{@code >}} */ @XmlElementDecl(namespace = "", name = "issue") @@ -205,47 +218,42 @@ public class ObjectFactory { } /** - * Create an instance of {@link JAXBElement }{@code <}{@link Enumeration }{@code >}} + * Create an instance of {@link IssueCompacts } */ - @XmlElementDecl(namespace = "", name = "enumeration") - public JAXBElement createEnumeration(Enumeration value) + public IssueCompacts createIssueCompacts() { - return new JAXBElement(_Enumeration_QNAME, Enumeration.class, null, value); + return new IssueCompacts(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} + * Create an instance of {@link Issues } */ - @XmlElementDecl(namespace = "", name = "replies", scope = Comment.class) - public JAXBElement createCommentReplies(String value) + public Issues createIssues() { - return new JAXBElement(_CommentReplies_QNAME, String.class, Comment.class, value); + return new Issues(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link Comment.Value }{@code >}} + * Create an instance of {@link User } */ - @XmlElementDecl(namespace = "", name = "value", scope = Comment.class) - public JAXBElement createCommentValue(Comment.Value value) + public User createUser() { - return new JAXBElement(_CommentValue_QNAME, Comment.Value.class, Comment.class, value); + return new User(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} + * Create an instance of {@link UserGroupRefType } */ - @XmlElementDecl(namespace = "", name = "field", scope = ErrorType.class) - public JAXBElement createErrorTypeField(String value) + public UserGroupRefType createUserGroupRefType() { - return new JAXBElement(_ErrorTypeField_QNAME, String.class, ErrorType.class, value); + return new UserGroupRefType(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} + * Create an instance of {@link UserRefs } */ - @XmlElementDecl(namespace = "", name = "message", scope = ErrorType.class) - public JAXBElement createErrorTypeMessage(String value) + public UserRefs createUserRefs() { - return new JAXBElement(_ErrorTypeMessage_QNAME, String.class, ErrorType.class, value); + return new UserRefs(); } } diff --git a/src/main/xjb/bindings.xjb b/src/main/xjb/bindings.xjb index a617032..6497e79 100644 --- a/src/main/xjb/bindings.xjb +++ b/src/main/xjb/bindings.xjb @@ -9,6 +9,12 @@ + + + + + + diff --git a/src/main/xsd/issues.xml b/src/main/xsd/issues.xml new file mode 100644 index 0000000..fe51b86 --- /dev/null +++ b/src/main/xsd/issues.xml @@ -0,0 +1,78 @@ + + + + + SM + + + 1 + + + Draw screens + + + Draw screens in Balsamiq, the online tool for drawing screen sketches. http://balsamiq.com/ + As a result the screen image in PNG format and Balsamiq source in XML format are expected. + Artefacts must be delivered in form of directory structure (not in Enterprise Architect file). + Partially documented packages will not be accepted. + Sample directory structure: + + Package name (directory) + + Screen name (directory) + - Screen name.png + - Screen name.xml + + In screens include only elements specific to documented screen. Do not include stuff that will land in template. + + + + 1292829185847 + + + 1321871424473 + + + root + + + root + + + 1321607946298 + + + bernard + + + Bernard Łabno + + + 0 + + + 0 + + + SM-2 + SM-3 + SM-4 + SM-5 + SM-6 + SM-7 + SM-8 + SM-9 + SM-10 + + + Normal + + + Task + + + Verified + + + Beta + + + \ No newline at end of file diff --git a/src/main/xsd/issues.xsd b/src/main/xsd/issues.xsd new file mode 100644 index 0000000..8033dd5 --- /dev/null +++ b/src/main/xsd/issues.xsd @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file