2
* Copyright 2005-2012 Restlet S.A.S.
4
* The contents of this file are subject to the terms of one of the following
5
* open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
6
* 1.0 (the "Licenses"). You can select the license that you prefer but you may
7
* not use this file except in compliance with one of these Licenses.
9
* You can obtain a copy of the Apache 2.0 license at
10
* http://www.opensource.org/licenses/apache-2.0
12
* You can obtain a copy of the LGPL 3.0 license at
13
* http://www.opensource.org/licenses/lgpl-3.0
15
* You can obtain a copy of the LGPL 2.1 license at
16
* http://www.opensource.org/licenses/lgpl-2.1
18
* You can obtain a copy of the CDDL 1.0 license at
19
* http://www.opensource.org/licenses/cddl1
21
* You can obtain a copy of the EPL 1.0 license at
22
* http://www.opensource.org/licenses/eclipse-1.0
24
* See the Licenses for the specific language governing permissions and
25
* limitations under the Licenses.
27
* Alternatively, you can obtain a royalty free commercial license with less
28
* limitations, transferable or non-transferable, directly at
29
* http://www.restlet.com/products/restlet-framework
31
* Restlet is a registered trademark of Restlet S.A.S.
34
package org.restlet.ext.wadl;
36
import static org.restlet.ext.wadl.WadlRepresentation.APP_NAMESPACE;
38
import java.util.ArrayList;
39
import java.util.Iterator;
40
import java.util.List;
43
import org.restlet.data.MediaType;
44
import org.restlet.data.Method;
45
import org.restlet.data.Reference;
46
import org.restlet.ext.xml.XmlWriter;
47
import org.restlet.representation.Variant;
48
import org.restlet.resource.Directory;
49
import org.restlet.resource.ServerResource;
50
import org.xml.sax.SAXException;
51
import org.xml.sax.helpers.AttributesImpl;
54
* Describes a class of closely related resources.
56
* @author Jerome Louvel
58
public class ResourceInfo extends DocumentedInfo {
61
* Returns a WADL description of the current resource.
63
* @param applicationInfo
64
* The parent application.
66
* The resource to describe.
68
* Path of the current resource.
70
* WADL description of the current resource to update.
72
@SuppressWarnings("deprecation")
73
public static void describe(ApplicationInfo applicationInfo,
74
ResourceInfo info, Object resource, String path) {
75
if ((path != null) && path.startsWith("/")) {
76
path = path.substring(1);
81
// Introspect the current resource to detect the allowed methods
82
List<Method> methodsList = new ArrayList<Method>();
84
if (resource instanceof ServerResource) {
85
((ServerResource) resource).updateAllowedMethods();
86
methodsList.addAll(((ServerResource) resource).getAllowedMethods());
88
if (resource instanceof WadlServerResource) {
89
info.setParameters(((WadlServerResource) resource)
90
.describeParameters());
92
if (applicationInfo != null) {
93
((WadlServerResource) resource).describe(applicationInfo);
96
} else if (resource instanceof org.restlet.resource.Resource) {
97
methodsList.addAll(((org.restlet.resource.Resource) resource)
98
.getAllowedMethods());
100
if (resource instanceof WadlResource) {
101
info.setParameters(((WadlResource) resource)
102
.getParametersInfo());
104
} else if (resource instanceof Directory) {
105
Directory directory = (Directory) resource;
106
methodsList.add(Method.GET);
108
if (directory.isModifiable()) {
109
methodsList.add(Method.DELETE);
110
methodsList.add(Method.PUT);
114
Method.sort(methodsList);
116
// Update the resource info with the description of the allowed methods
117
List<MethodInfo> methods = info.getMethods();
118
MethodInfo methodInfo;
120
for (Method method : methodsList) {
121
methodInfo = new MethodInfo();
122
methods.add(methodInfo);
123
methodInfo.setName(method);
125
if (resource instanceof ServerResource) {
126
if (resource instanceof WadlServerResource) {
127
WadlServerResource wsResource = (WadlServerResource) resource;
129
if (wsResource.canDescribe(method)) {
130
wsResource.describeMethod(method, methodInfo);
133
MethodInfo.describeAnnotations(methodInfo,
134
(ServerResource) resource);
136
} else if (resource instanceof org.restlet.resource.Resource) {
137
if (resource instanceof WadlResource) {
138
WadlResource wsResource = (WadlResource) resource;
140
if (wsResource.isDescribable(method)) {
141
wsResource.describeMethod(method, methodInfo);
144
// Can document the list of supported variants.
145
if (Method.GET.equals(method)) {
146
ResponseInfo responseInfo = null;
148
for (Variant variant : ((org.restlet.resource.Resource) resource)
150
RepresentationInfo representationInfo = new RepresentationInfo();
151
representationInfo.setMediaType(variant
154
if (responseInfo == null) {
155
responseInfo = new ResponseInfo();
156
methodInfo.getResponses().add(responseInfo);
159
responseInfo.getRepresentations().add(
167
// Document the resource
169
String textContent = null;
171
if (resource instanceof WadlServerResource) {
172
title = ((WadlServerResource) resource).getName();
173
textContent = ((WadlServerResource) resource).getDescription();
174
} else if (resource instanceof WadlResource) {
175
title = ((WadlResource) resource).getTitle();
178
if ((title != null) && !"".equals(title)) {
179
DocumentationInfo doc = null;
181
if (info.getDocumentations().isEmpty()) {
182
doc = new DocumentationInfo();
183
info.getDocumentations().add(doc);
185
info.getDocumentations().get(0);
189
doc.setTextContent(textContent);
193
/** List of child resources. */
194
private List<ResourceInfo> childResources;
196
/** Identifier for that element. */
197
private String identifier;
199
/** List of supported methods. */
200
private List<MethodInfo> methods;
202
/** List of parameters. */
203
private List<ParameterInfo> parameters;
205
/** URI template for the identifier of the resource. */
208
/** Media type for the query component of the resource URI. */
209
private MediaType queryType;
211
/** List of references to resource type elements. */
212
private List<Reference> type;
217
public ResourceInfo() {
222
* Constructor with a single documentation element.
224
* @param documentation
225
* A single documentation element.
227
public ResourceInfo(DocumentationInfo documentation) {
228
super(documentation);
232
* Constructor with a list of documentation elements.
234
* @param documentations
235
* The list of documentation elements.
237
public ResourceInfo(List<DocumentationInfo> documentations) {
238
super(documentations);
242
* Constructor with a single documentation element.
244
* @param documentation
245
* A single documentation element.
247
public ResourceInfo(String documentation) {
248
super(documentation);
252
* Creates an application descriptor that wraps this resource descriptor.
253
* The title of the resource, that is to say the title of its first
254
* documentation tag is transfered to the title of the first documentation
255
* tag of the main application tag.
257
* @return The new application descriptor.
259
public ApplicationInfo createApplication() {
260
ApplicationInfo result = new ApplicationInfo();
262
if (!getDocumentations().isEmpty()) {
263
String titleResource = getDocumentations().get(0).getTitle();
264
if (titleResource != null && !"".equals(titleResource)) {
265
DocumentationInfo doc = null;
267
if (result.getDocumentations().isEmpty()) {
268
doc = new DocumentationInfo();
269
result.getDocumentations().add(doc);
271
doc = result.getDocumentations().get(0);
274
doc.setTitle(titleResource);
278
ResourcesInfo resources = new ResourcesInfo();
279
result.setResources(resources);
280
resources.getResources().add(this);
285
* Returns the list of child resources.
287
* @return The list of child resources.
289
public List<ResourceInfo> getChildResources() {
290
// Lazy initialization with double-check.
291
List<ResourceInfo> r = this.childResources;
293
synchronized (this) {
294
r = this.childResources;
296
this.childResources = r = new ArrayList<ResourceInfo>();
304
* Returns the identifier for that element.
306
* @return The identifier for that element.
308
public String getIdentifier() {
309
return this.identifier;
313
* Returns the list of supported methods.
315
* @return The list of supported methods.
317
public List<MethodInfo> getMethods() {
318
// Lazy initialization with double-check.
319
List<MethodInfo> m = this.methods;
321
synchronized (this) {
325
this.methods = m = new ArrayList<MethodInfo>();
333
* Returns the list of parameters.
335
* @return The list of parameters.
337
public List<ParameterInfo> getParameters() {
338
// Lazy initialization with double-check.
339
List<ParameterInfo> p = this.parameters;
341
synchronized (this) {
344
this.parameters = p = new ArrayList<ParameterInfo>();
352
* Returns the URI template for the identifier of the resource.
354
* @return The URI template for the identifier of the resource.
356
public String getPath() {
361
* Returns the media type for the query component of the resource URI.
363
* @return The media type for the query component of the resource URI.
365
public MediaType getQueryType() {
366
return this.queryType;
370
* Returns the list of references to resource type elements.
372
* @return The list of references to resource type elements.
374
public List<Reference> getType() {
375
// Lazy initialization with double-check.
376
List<Reference> t = this.type;
378
synchronized (this) {
381
this.type = t = new ArrayList<Reference>();
389
* Sets the list of child resources.
392
* The list of child resources.
394
public void setChildResources(List<ResourceInfo> resources) {
395
this.childResources = resources;
399
* Sets the identifier for that element.
402
* The identifier for that element.
404
public void setIdentifier(String identifier) {
405
this.identifier = identifier;
409
* Sets the list of supported methods.
412
* The list of supported methods.
414
public void setMethods(List<MethodInfo> methods) {
415
this.methods = methods;
419
* Sets the list of parameters.
422
* The list of parameters.
424
public void setParameters(List<ParameterInfo> parameters) {
425
this.parameters = parameters;
429
* Sets the URI template for the identifier of the resource.
432
* The URI template for the identifier of the resource.
434
public void setPath(String path) {
439
* Sets the media type for the query component of the resource URI.
442
* The media type for the query component of the resource URI.
444
public void setQueryType(MediaType queryType) {
445
this.queryType = queryType;
449
* Sets the list of references to resource type elements.
452
* The list of references to resource type elements.
454
public void setType(List<Reference> type) {
459
public void updateNamespaces(Map<String, String> namespaces) {
460
namespaces.putAll(resolveNamespaces());
462
for (final ParameterInfo parameterInfo : getParameters()) {
463
parameterInfo.updateNamespaces(namespaces);
465
for (final ResourceInfo resourceInfo : getChildResources()) {
466
resourceInfo.updateNamespaces(namespaces);
468
for (final MethodInfo methodInfo : getMethods()) {
469
methodInfo.updateNamespaces(namespaces);
474
* Writes the current object as an XML element using the given SAX writer.
478
* @throws SAXException
480
public void writeElement(XmlWriter writer) throws SAXException {
481
final AttributesImpl attributes = new AttributesImpl();
482
if ((getIdentifier() != null) && !getIdentifier().equals("")) {
483
attributes.addAttribute("", "id", null, "xs:ID", getIdentifier());
486
if ((getPath() != null) && !getPath().equals("")) {
487
attributes.addAttribute("", "path", null, "xs:string", getPath());
490
if (getQueryType() != null) {
491
attributes.addAttribute("", "queryType", null, "xs:string",
492
getQueryType().getMainType());
494
if ((getType() != null) && !getType().isEmpty()) {
495
final StringBuilder builder = new StringBuilder();
496
for (final Iterator<Reference> iterator = getType().iterator(); iterator
498
final Reference reference = iterator.next();
499
builder.append(reference.toString());
500
if (iterator.hasNext()) {
504
attributes.addAttribute("", "type", null, "xs:string", builder
508
if (getChildResources().isEmpty() && getDocumentations().isEmpty()
509
&& getMethods().isEmpty() && getParameters().isEmpty()) {
510
writer.emptyElement(APP_NAMESPACE, "resource", null, attributes);
512
writer.startElement(APP_NAMESPACE, "resource", null, attributes);
514
for (final ResourceInfo resourceInfo : getChildResources()) {
515
resourceInfo.writeElement(writer);
518
for (final DocumentationInfo documentationInfo : getDocumentations()) {
519
documentationInfo.writeElement(writer);
522
for (final ParameterInfo parameterInfo : getParameters()) {
523
parameterInfo.writeElement(writer);
526
for (final MethodInfo methodInfo : getMethods()) {
527
methodInfo.writeElement(writer);
530
writer.endElement(APP_NAMESPACE, "resource");