diff --git a/build/tmpl/editions/build.xml b/build/tmpl/editions/build.xml
index b1ccd0fa82..3414055fcf 100644
--- a/build/tmpl/editions/build.xml
+++ b/build/tmpl/editions/build.xml
@@ -832,9 +832,17 @@
+
-
+
+
+
+
+
+
+
+
diff --git a/libraries/org.core4j_0.5/library.xml b/libraries/org.core4j_0.5/library.xml
new file mode 100644
index 0000000000..b39897c058
--- /dev/null
+++ b/libraries/org.core4j_0.5/library.xml
@@ -0,0 +1,19 @@
+
+ Core 4J
+ Core 4j Library used by odata4j
+ 0.5
+ 1
+ http://code.google.com/p/core4j/source/browse/
+ http://mvnrepository.com/artifact/org.core4j/core4j/0.5
+ Google Inc.
+
+
+
+ org.core4j
+ core4j
+
+
+
+
+
+
diff --git a/libraries/org.core4j_0.5/license.txt b/libraries/org.core4j_0.5/license.txt
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/libraries/org.core4j_0.5/license.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/libraries/org.core4j_0.5/org.core4j-0.5.jar b/libraries/org.core4j_0.5/org.core4j-0.5.jar
new file mode 100644
index 0000000000..be8a11d638
Binary files /dev/null and b/libraries/org.core4j_0.5/org.core4j-0.5.jar differ
diff --git a/libraries/org.jvnet.mimepull_1.9.3/library.xml b/libraries/org.jvnet.mimepull_1.9.3/library.xml
new file mode 100644
index 0000000000..7645fbec61
--- /dev/null
+++ b/libraries/org.jvnet.mimepull_1.9.3/library.xml
@@ -0,0 +1,19 @@
+
+ MimePull Library
+ Mimepull Library used by restlet for batch operations
+ 1.9.3
+ 1
+ http://mimepull.java.net/
+ http://mvnrepository.com/artifact/org.jvnet.mimepull/mimepull/1.9.3
+ Oracle Inc.
+
+
+
+ org.jvnet.mimepull
+ mimepull
+
+
+
+
+
+
diff --git a/libraries/org.jvnet.mimepull_1.9.3/license.txt b/libraries/org.jvnet.mimepull_1.9.3/license.txt
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/libraries/org.jvnet.mimepull_1.9.3/license.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/libraries/org.jvnet.mimepull_1.9.3/mimepull-1.9.3.jar b/libraries/org.jvnet.mimepull_1.9.3/mimepull-1.9.3.jar
new file mode 100644
index 0000000000..c3234556e0
Binary files /dev/null and b/libraries/org.jvnet.mimepull_1.9.3/mimepull-1.9.3.jar differ
diff --git a/modules/org.restlet.ext.crypto/src/META-INF/services/org.restlet.engine.security.AuthenticatorHelper b/modules/org.restlet.ext.crypto/src/META-INF/services/org.restlet.engine.security.AuthenticatorHelper
index c3ab215c04..e144058a66 100644
--- a/modules/org.restlet.ext.crypto/src/META-INF/services/org.restlet.engine.security.AuthenticatorHelper
+++ b/modules/org.restlet.ext.crypto/src/META-INF/services/org.restlet.engine.security.AuthenticatorHelper
@@ -3,3 +3,4 @@ org.restlet.ext.crypto.internal.HttpAwsQueryHelper
org.restlet.ext.crypto.internal.HttpDigestHelper
org.restlet.ext.crypto.internal.HttpAzureSharedKeyHelper
org.restlet.ext.crypto.internal.HttpAzureSharedKeyLiteHelper
+org.restlet.ext.crypto.internal.HttpNegotiateHelper
\ No newline at end of file
diff --git a/modules/org.restlet.ext.crypto/src/org/restlet/ext/crypto/internal/HttpNegotiateHelper.java b/modules/org.restlet.ext.crypto/src/org/restlet/ext/crypto/internal/HttpNegotiateHelper.java
new file mode 100644
index 0000000000..2845488432
--- /dev/null
+++ b/modules/org.restlet.ext.crypto/src/org/restlet/ext/crypto/internal/HttpNegotiateHelper.java
@@ -0,0 +1,184 @@
+/**
+ * Copyright 2005-2013 Restlet S.A.S.
+ *
+ * The contents of this file are subject to the terms of one of the following
+ * open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
+ * 1.0 (the "Licenses"). You can select the license that you prefer but you may
+ * not use this file except in compliance with one of these Licenses.
+ *
+ * You can obtain a copy of the Apache 2.0 license at
+ * http://www.opensource.org/licenses/apache-2.0
+ *
+ * You can obtain a copy of the LGPL 3.0 license at
+ * http://www.opensource.org/licenses/lgpl-3.0
+ *
+ * You can obtain a copy of the LGPL 2.1 license at
+ * http://www.opensource.org/licenses/lgpl-2.1
+ *
+ * You can obtain a copy of the CDDL 1.0 license at
+ * http://www.opensource.org/licenses/cddl1
+ *
+ * You can obtain a copy of the EPL 1.0 license at
+ * http://www.opensource.org/licenses/eclipse-1.0
+ *
+ * See the Licenses for the specific language governing permissions and
+ * limitations under the Licenses.
+ *
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly at
+ * http://www.restlet.com/products/restlet-framework
+ *
+ * Restlet is a registered trademark of Restlet S.A.S.
+ */
+
+package org.restlet.ext.crypto.internal;
+
+import java.io.UnsupportedEncodingException;
+import java.util.logging.Level;
+
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.ChallengeResponse;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.CookieSetting;
+import org.restlet.data.Form;
+import org.restlet.data.Header;
+import org.restlet.data.Reference;
+import org.restlet.data.Status;
+import org.restlet.engine.header.ChallengeWriter;
+import org.restlet.engine.header.CookieWriter;
+import org.restlet.engine.header.HeaderConstants;
+import org.restlet.engine.header.HeaderUtils;
+import org.restlet.engine.security.AuthenticatorHelper;
+import org.restlet.engine.util.Base64;
+import org.restlet.resource.ClientResource;
+import org.restlet.util.Series;
+
+/**
+ * Implements the HTTP Negotiate helper for form based authentication. It will
+ * submit the username/password passed as credentials from consumer to default
+ * action url. Once user is authenticated then we add the cookies sent by server
+ * to request object.
+ *
+ * @author Onkar Dhuri
+ */
+public class HttpNegotiateHelper extends AuthenticatorHelper {
+
+ /** The action url where form needs to submitted. */
+ public static String ACTION_URL = "/j_security_check";
+
+ /** The field name of username input box. */
+ public static String USERNAME = "j_username";
+
+ /** The field name of password input box. */
+ public static String PASSWORD = "j_password";
+
+ /**
+ * Constructor.
+ */
+ public HttpNegotiateHelper() {
+ super(ChallengeScheme.HTTP_NEGOTIATE, true, true);
+ }
+
+ /**
+ * This method submits the form to {ACTION_URL} as defined to authenticate
+ * the request.
+ * Once credentials are validated, the server will send out the 302 Response
+ * with "JSESSIONID" & "JSESSIONIDSSO" cookies.
+ * We set these cookies into request header for subsequent operations.
+ *
+ * @see org.restlet.engine.security.AuthenticatorHelper#formatResponse(org.restlet.engine.header.ChallengeWriter,
+ * org.restlet.data.ChallengeResponse, org.restlet.Request,
+ * org.restlet.util.Series)
+ *
+ */
+ @Override
+ public void formatResponse(ChallengeWriter cw, ChallengeResponse challenge,
+ Request request, Series httpHeaders) {
+ if (challenge == null) {
+ throw new RuntimeException(
+ "No challenge provided, unable to encode credentials");
+ } else {
+ /*
+ * Submit the form only if we dont have any cookies set in the request.
+ * For first /$metadata request, it wont have cookies, so it will submit the form and cookies are cached.
+ * Double check if cached cookies really has JSESSIONID/JSESSIONIDSSO, if not then submit the form again.
+ */
+ if(request.getCookies().size() == 0 ||
+ (request.getCookies().getFirst("JSESSIONID") == null || request.getCookies().getFirst("JSESSIONIDSSO") == null)){
+ Reference resourceRef = request.getResourceRef();
+ String relativeURL = resourceRef.toString().substring(0,
+ resourceRef.toString().lastIndexOf("/"));
+ ClientResource loginCr = new ClientResource(relativeURL
+ + ACTION_URL);
+ Form loginForm = new Form();
+ loginForm.add(USERNAME, challenge.getIdentifier());
+ loginForm.add(PASSWORD, new String(challenge.getSecret()));
+ loginCr.post(loginForm);
+ Response response = loginCr.getResponse();
+ // check if we get 302 response status; then only add the cookies
+ // else throw exception
+ if (response.getStatus().equals(Status.REDIRECTION_FOUND)
+ || response.getStatus()
+ .equals(Status.REDIRECTION_PERMANENT)) {
+ Series cookieSetting = loginCr
+ .getCookieSettings();
+ for (CookieSetting cs : cookieSetting) {
+ request.getCookies().add(cs.getName(), cs.getValue());
+ }
+ // finally add all the cookies in header
+ HeaderUtils.addHeader(HeaderConstants.HEADER_COOKIE,
+ CookieWriter.write(request.getCookies()), httpHeaders);
+ } else {
+ throw new RuntimeException(
+ "Can't authorize the request with passed credentials. "
+ + "Please check if you are passing correct credentials");
+ }
+ }
+ }
+ }
+
+ /**
+ * For "Negotiate" we are not currently using this API but we might use it
+ * in future if we need to set the credentials to ChallengeResponse
+ *
+ * @see org.restlet.engine.security.AuthenticatorHelper#parseResponse(org.restlet.data.ChallengeResponse,
+ * org.restlet.Request, org.restlet.util.Series)
+ *
+ */
+ @Override
+ public void parseResponse(ChallengeResponse challenge, Request request,
+ Series httpHeaders) {
+ try {
+ // Check if Negotiate auth header uses Base64 encoding
+ byte[] credentialsEncoded = Base64.decode(challenge.getRawValue());
+
+ if (credentialsEncoded == null) {
+ getLogger()
+ .info("Cannot decode credentials: "
+ + challenge.getRawValue());
+ }
+
+ String credentials = new String(credentialsEncoded, "ISO-8859-1");
+ int separator = credentials.indexOf(':');
+
+ if (separator == -1) {
+ // Log the blocking
+ getLogger().info(
+ "Invalid credentials given by client with IP: "
+ + ((request != null) ? request.getClientInfo()
+ .getAddress() : "?"));
+ } else {
+ challenge.setIdentifier(credentials.substring(0, separator));
+ challenge.setSecret(credentials.substring(separator + 1));
+ }
+ } catch (UnsupportedEncodingException e) {
+ getLogger().log(Level.INFO,
+ "Unsupported HTTP negotiate encoding error", e);
+ } catch (IllegalArgumentException e) {
+ getLogger().log(Level.INFO,
+ "Unable to decode the HTTP Negotiate credential", e);
+ }
+ }
+
+}
diff --git a/modules/org.restlet.ext.odata/module.xml b/modules/org.restlet.ext.odata/module.xml
index 0ba213f58a..bd33c7ceaa 100644
--- a/modules/org.restlet.ext.odata/module.xml
+++ b/modules/org.restlet.ext.odata/module.xml
@@ -13,6 +13,10 @@
+
+
+
+
diff --git a/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Generator.java b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Generator.java
index 23091fa3ec..2590b2630f 100644
--- a/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Generator.java
+++ b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Generator.java
@@ -36,10 +36,20 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
-
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.restlet.data.ChallengeResponse;
+import org.restlet.data.ChallengeScheme;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
@@ -66,311 +76,467 @@
*/
public class Generator {
- /**
- * Takes two (or three) parameters:
- *
- *
The URI of the OData service
- *
The output directory (optional, used the current directory by
- * default)
- *
The name of the generated service class name (optional)
- *
- *
- * @param args
- * The list of arguments.
- */
- public static void main(String[] args) {
- System.out.println("---------------------------");
- System.out.println("OData client code generator");
- System.out.println("---------------------------");
- System.out.println("step 1 - check parameters");
-
- String errorMessage = null;
-
- if (args == null || args.length == 0) {
- errorMessage = "Missing mandatory argument: URI of the OData service.";
- }
-
- File outputDir = null;
-
- if (errorMessage == null) {
- if (args.length > 1) {
- outputDir = new File(args[1]);
- } else {
- try {
- outputDir = new File(".").getCanonicalFile();
- } catch (IOException e) {
- errorMessage = "Unable to get the target directory. "
- + e.getMessage();
- }
- }
-
- if (outputDir.exists()) {
- System.out.println("step 2 - check the ouput directory");
- if (!outputDir.isDirectory()) {
- errorMessage = outputDir.getPath()
- + " is not a valid directory.";
- }
-
- } else {
- try {
- System.out.println("step 2 - create the ouput directory");
- outputDir.mkdirs();
- } catch (Throwable e) {
- errorMessage = "Cannot create " + outputDir.getPath()
- + " due to: " + e.getMessage();
- }
- }
- }
- if (errorMessage == null) {
- System.out.println("step 3 - get the metadata descriptor");
- String dataServiceUri = null;
-
- if (args[0].endsWith("$metadata")) {
- dataServiceUri = args[0].substring(0, args[0].length() - 10);
- } else if (args[0].endsWith("/")) {
- dataServiceUri = args[0].substring(0, args[0].length() - 1);
- } else {
- dataServiceUri = args[0];
- }
-
- Service service = new Service(dataServiceUri);
- if (service.getMetadata() == null) {
- errorMessage = "Cannot retrieve the metadata.";
- } else {
- System.out.println("step 4 - generate source code");
- Generator svcUtil = null;
- if (args.length == 3) {
- svcUtil = new Generator(service.getServiceRef(), args[2]);
- } else {
- svcUtil = new Generator(service.getServiceRef());
- }
-
- try {
- svcUtil.generate(outputDir);
- System.out
- .print("The source code has been generated in directory: ");
- System.out.println(outputDir.getPath());
- } catch (Exception e) {
- errorMessage = "Cannot generate the source code in directory: "
- + outputDir.getPath();
- }
- }
- }
-
- if (errorMessage != null) {
- System.out.println("An error occurred: ");
- System.out.println(errorMessage);
- System.out.println();
- System.out
- .println("Please check that you provide the following parameters:");
- System.out.println(" - Valid URI for the remote service");
- System.out
- .println(" - Valid directory path where to generate the files");
- System.out
- .println(" - Valid name for the generated service class (optional)");
- }
- }
-
- /** The name of the service class (in case there is only one in the schema). */
- private String serviceClassName;
-
- /** The URI of the target data service. */
- private Reference serviceRef;
-
- /**
- * Constructor.
- *
- * @param serviceRef
- * The URI of the OData service.
- */
- public Generator(Reference serviceRef) {
- this(serviceRef, null);
- }
-
- /**
- * Constructor. The name of the service class can be provided if there is
- * only one service defined in the metadata.
- *
- * @param serviceRef
- * The URI of the OData service.
- * @param serviceClassName
- * The name of the service class (in case there is only one in
- * the metadata).
- */
- public Generator(Reference serviceRef, String serviceClassName) {
- super();
- this.serviceRef = serviceRef;
- if (serviceClassName != null) {
- this.serviceClassName = ReflectUtils.normalize(serviceClassName);
- this.serviceClassName = this.serviceClassName.substring(0, 1)
- .toUpperCase() + this.serviceClassName.substring(1);
- }
-
- }
-
- /**
- * Constructor.
- *
- * @param serviceUri
- * The URI of the OData service.
- */
- public Generator(String serviceUri) {
- this(serviceUri, null);
- }
-
- /**
- * Constructor. The name of the service class can be provided if there is
- * only one service defined in the metadata.
- *
- * @param serviceUri
- * The URI of the OData service.
- * @param serviceClassName
- * The name of the service class (in case there is only one in
- * the metadata).
- */
- public Generator(String serviceUri, String serviceClassName) {
- this(new Reference(serviceUri), serviceClassName);
- }
-
- /**
- * Generates the client code to the given output directory.
- *
- * @param outputDir
- * The output directory.
- * @throws Exception
- */
- public void generate(File outputDir) throws Exception {
- Service service = new Service(serviceRef);
- Metadata metadata = (Metadata) service.getMetadata();
- if (metadata == null) {
- throw new Exception("Can't get the metadata for this service: "
- + serviceRef);
- }
-
- Configuration fmc = new Configuration();
- fmc.setDefaultEncoding(CharacterSet.UTF_8.getName());
-
- // Generate classes
- String rootTemplates = "clap://class/org/restlet/ext/odata/internal/templates";
- Representation complexTmpl = new StringRepresentation(
- new ClientResource(rootTemplates + "/complexType.ftl").get()
- .getText());
- Representation entityTmpl = new StringRepresentation(
- new ClientResource(rootTemplates + "/entityType.ftl").get()
- .getText());
- Representation serviceTmpl = new StringRepresentation(
- new ClientResource(rootTemplates + "/service.ftl").get()
- .getText());
-
- for (Schema schema : metadata.getSchemas()) {
- if ((schema.getEntityTypes() != null && !schema.getEntityTypes()
- .isEmpty())
- || (schema.getComplexTypes() != null && !schema
- .getComplexTypes().isEmpty())) {
- String packageName = TypeUtils.getPackageName(schema);
- File packageDir = new File(outputDir, packageName.replace(".",
- System.getProperty("file.separator")));
- packageDir.mkdirs();
-
- // For each entity type
- for (EntityType type : schema.getEntityTypes()) {
- String className = type.getClassName();
- Map dataModel = new HashMap();
- dataModel.put("type", type);
- dataModel.put("schema", schema);
- dataModel.put("metadata", metadata);
- dataModel.put("className", className);
- dataModel.put("packageName", packageName);
-
- TemplateRepresentation templateRepresentation = new TemplateRepresentation(
- entityTmpl, fmc, dataModel, MediaType.TEXT_PLAIN);
- templateRepresentation.setCharacterSet(CharacterSet.UTF_8);
-
- // Write the template representation as a Java class
- OutputStream fos = new FileOutputStream(new File(
- packageDir, type.getClassName() + ".java"));
- templateRepresentation.write(fos);
- fos.flush();
- }
-
- for (ComplexType type : schema.getComplexTypes()) {
- String className = type.getClassName();
- Map dataModel = new HashMap();
- dataModel.put("type", type);
- dataModel.put("schema", schema);
- dataModel.put("metadata", metadata);
- dataModel.put("className", className);
- dataModel.put("packageName", packageName);
-
- TemplateRepresentation templateRepresentation = new TemplateRepresentation(
- complexTmpl, fmc, dataModel, MediaType.TEXT_PLAIN);
- templateRepresentation.setCharacterSet(CharacterSet.UTF_8);
-
- // Write the template representation as a Java class
- OutputStream fos = new FileOutputStream(new File(
- packageDir, type.getClassName() + ".java"));
- templateRepresentation.write(fos);
- fos.flush();
- }
- }
- }
- if (metadata.getContainers() != null
- && !metadata.getContainers().isEmpty()) {
- for (EntityContainer entityContainer : metadata.getContainers()) {
- Schema schema = entityContainer.getSchema();
- // Generate Service subclass
- StringBuffer className = new StringBuffer();
-
- if (serviceClassName != null) {
- // Try to use the Client preference
- if (entityContainer.isDefaultEntityContainer()) {
- className.append(serviceClassName);
- } else if (metadata.getContainers().size() == 1) {
- className.append(serviceClassName);
- } else {
- className.append(schema.getNamespace()
- .getNormalizedName().substring(0, 1)
- .toUpperCase());
- className.append(schema.getNamespace()
- .getNormalizedName().substring(1));
- className.append("Service");
- }
- } else {
- className.append(schema.getNamespace().getNormalizedName()
- .substring(0, 1).toUpperCase());
- className.append(schema.getNamespace().getNormalizedName()
- .substring(1));
- className.append("Service");
- }
-
- Map dataModel = new HashMap();
- dataModel.put("schema", schema);
- dataModel.put("metadata", metadata);
- dataModel.put("className", className);
- dataModel.put("dataServiceUri", this.serviceRef.getTargetRef());
- dataModel.put("entityContainer", entityContainer);
-
- TemplateRepresentation templateRepresentation = new TemplateRepresentation(
- serviceTmpl, fmc, dataModel, MediaType.TEXT_PLAIN);
- templateRepresentation.setCharacterSet(CharacterSet.UTF_8);
-
- // Write the template representation as a Java class
- OutputStream fos = new FileOutputStream(new File(outputDir,
- className + ".java"));
- templateRepresentation.write(fos);
- fos.flush();
- }
- }
- }
-
- /**
- * Generates the client code to the given output directory.
- *
- * @param outputDir
- * The output directory.
- * @throws Exception
- */
- public void generate(String outputDir) throws Exception {
- generate(new File(outputDir));
- }
+ /** The Constant SERVICE_URL. */
+ private final static String SERVICE_URL = "serviceUrl";
+
+ /** The Constant USERNAME. */
+ private final static String USERNAME = "userName";
+
+ /** The Constant PASSWORD. */
+ private final static String PASSWORD = "password";
+
+ /** The Constant CHALLENGE_SCHEME. */
+ private final static String CHALLENGE_SCHEME = "challengeScheme";
+
+ /** The Constant SERVICE_CLASSNAME. */
+ private final static String SERVICE_CLASSNAME = "serviceClassName";
+
+ /** The Constant SERVICE_CLASS_DIR. */
+ private final static String SERVICE_CLASS_DIR = "serviceClassDir";
+
+ /** The Constant ENTITY_CLASS_DIR. */
+ private final static String ENTITY_CLASS_DIR = "entityClassDir";
+
+ /** The URI of the target data service. */
+ private Reference serviceUrl;
+
+ /** The user name. */
+ private static String userName;
+
+ /** The password. */
+ private static String password;
+
+ /** The challenge scheme. */
+ private static ChallengeScheme challengeScheme;
+
+ /** The name of the service class (in case there is only one in the schema). */
+ private static String serviceClassName;
+
+ /** The entity pkg. */
+ private static String entityPkg;
+
+ /** The service pkg. */
+ private static String servicePkg;
+
+ /** The package dir where entity classes are generated. */
+ private static File packageDir;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger
+ .getLogger(Generator.class.getName());
+
+
+ /**
+ * Default Constructor.
+ *
+ * @param serviceRef
+ * The URI of the OData service.
+ */
+ public Generator(Reference serviceRef) {
+ this(serviceRef, null);
+ }
+
+ /**
+ * Constructor. The name of the service class can be provided if there is
+ * only one service defined in the metadata.
+ *
+ * @param serviceRef
+ * The URI of the OData service.
+ * @param serviceClassName
+ * The name of the service class (in case there is only one in
+ * the metadata).
+ */
+ public Generator(Reference serviceRef, String serviceClassName) {
+ super();
+ this.serviceUrl = serviceRef;
+ if (serviceClassName != null) {
+ Generator.serviceClassName = ReflectUtils.normalize(serviceClassName);
+ Generator.serviceClassName = Generator.serviceClassName.substring(0, 1)
+ .toUpperCase() + Generator.serviceClassName.substring(1);
+ }
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param serviceUri
+ * The URI of the OData service.
+ */
+ public Generator(String serviceUri) {
+ this(serviceUri, null);
+ }
+
+ /**
+ * Constructor. The name of the service class can be provided if there is
+ * only one service defined in the metadata.
+ *
+ * @param serviceUri
+ * The URI of the OData service.
+ * @param serviceClassName
+ * The name of the service class (in case there is only one in
+ * the metadata).
+ */
+ public Generator(String serviceUri, String serviceClassName) {
+ this(new Reference(serviceUri), serviceClassName);
+ }
+
+
+ /**
+ * Takes seven parameters:
+ *
+ *
The URI of the OData service
+ *
Username to access OData service
+ *
Password to access OData service
+ *
ChallangeScheme - Possible values HTTP_BASIC, HTTP_NEGOTIATE, if not provided then HTTP_BASIC will be used as default.
+ *
Service class name
+ *
The output directory for Service class generation (For example : src/com/ow/service),
+ * if no directory is provided class will be generated in the default package.
+ *
The output directory for Entity class generation (For example : src/com/ow/entities),
+ * if no directory is provided schema name will be used as default package.
+ *
+ *
+ * @param args
+ * The list of arguments.
+ */
+ public static void main(String[] args) {
+
+ System.out.println("---------------------------");
+ System.out.println("OData client code generator");
+ System.out.println("---------------------------");
+ System.out.println("step 1 - check parameters");
+
+ String errorMessage = null;
+ File entityClassDir = null;
+ File serviceDir = null;
+
+ final CommandLineParser parser = new BasicParser();
+ final Options options = new Options();
+ setCommandLineOptions(options);
+
+ CommandLine commandLine = null;
+ // try to parse and validate the passed arguments using apache commons cli.
+ try {
+ commandLine = parser.parse(options, args);
+ } catch (ParseException e) {
+ System.out.println(e.getMessage());
+ printUsage(options);
+ }
+
+ userName = getOption(USERNAME, commandLine);
+ password = getOption(PASSWORD, commandLine);
+ challengeScheme = (getOption(CHALLENGE_SCHEME, commandLine) == null ? null
+ : ChallengeScheme.valueOf(getOption(CHALLENGE_SCHEME, commandLine)));
+
+ serviceClassName = getOption(SERVICE_CLASSNAME, commandLine);
+
+ if (getOption(SERVICE_CLASS_DIR, commandLine) != null) {
+ serviceDir = new File(getOption(SERVICE_CLASS_DIR, commandLine));
+ servicePkg = getOption(SERVICE_CLASS_DIR, commandLine).substring(4, getOption(SERVICE_CLASS_DIR, commandLine).length());
+ } else {
+ try {
+ serviceDir = new File(".").getCanonicalFile();
+ // set package name to blank if user did not pass this option
+ servicePkg = "";
+ } catch (IOException e) {
+ errorMessage = "Unable to get the target directory for service generation. "
+ + e.getMessage();
+ }
+ }
+
+ if (serviceDir.exists()) {
+ System.out.println("step 2 - check the service directory");
+ if (!serviceDir.isDirectory()) {
+ errorMessage = serviceDir.getPath()
+ + " is not a valid directory.";
+ }
+
+ } else {
+ try {
+ System.out.println("step 2 - create the service directory");
+ serviceDir.mkdirs();
+ } catch (Throwable e) {
+ errorMessage = "Cannot create " + serviceDir.getPath()
+ + " due to: " + e.getMessage();
+ }
+ }
+
+ if (getOption(ENTITY_CLASS_DIR, commandLine) != null) {
+ entityClassDir = new File(getOption(ENTITY_CLASS_DIR, commandLine));
+ entityPkg = getOption(ENTITY_CLASS_DIR, commandLine).substring(4, getOption(ENTITY_CLASS_DIR, commandLine).length());
+ }
+
+ if (errorMessage == null) {
+ System.out.println("step 3 - get the metadata descriptor");
+ String dataServiceUri = getOption(SERVICE_URL, commandLine);
+
+ if (dataServiceUri.endsWith("$metadata")) {
+ dataServiceUri = dataServiceUri.substring(0, dataServiceUri.length() - 10);
+ } else if (dataServiceUri.endsWith("/")) {
+ dataServiceUri = dataServiceUri.substring(0, dataServiceUri.length() - 1);
+ }
+
+ Service service = new Service(dataServiceUri);
+ if(challengeScheme != null && userName != null && password != null){
+ service.setCredentials(new ChallengeResponse(challengeScheme, userName,
+ password));
+ }
+ if (service.getMetadata() == null) {
+ errorMessage = "Cannot retrieve the metadata.";
+ } else {
+ System.out.println("step 4 - generate source code");
+ Generator svcUtil = new Generator(service.getServiceRef());
+
+ try {
+ svcUtil.generate(entityClassDir, serviceDir);
+ System.out.print("The source code has been generated in directory: ");
+ System.out.println(packageDir.getPath());
+ } catch (Exception e) {
+ errorMessage = "Cannot generate the source code in directory: "
+ + packageDir.getPath();
+ }
+ }
+ } else{
+ LOGGER.log(Level.SEVERE,errorMessage);
+ }
+ }
+
+ /**
+ * Sets the command line options.
+ *
+ * @param options the new command line options
+ */
+ private static void setCommandLineOptions(Options options) {
+
+ /** Creates an Option for serviceUrl using the specified parameters */
+ Option serviceUrlOption = new Option("su", SERVICE_URL, true, "The URI of the OData service");
+ serviceUrlOption.setRequired(true);
+ options.addOption(serviceUrlOption);
+
+ /** Creates an Option for userName */
+ Option userNameOption = new Option("ur", USERNAME, true, "Username to access OData service");
+ options.addOption(userNameOption);
+
+ /** Creates an Option for password */
+ Option passwordOption = new Option("pw", PASSWORD, true, "Password to access OData service");
+ options.addOption(passwordOption);
+
+ /** Creates an Option for challangeScheme */
+ Option challangeSchemeOption = new Option("cs", CHALLENGE_SCHEME, true, "ChallengeScheme - Possible values HTTP_BASIC, HTTP_NEGOTIATE, if not provided then no authentication will be used");
+ options.addOption(challangeSchemeOption);
+
+ /** Creates an Option for sreviceClassName */
+ Option sreviceClassNameOption = new Option("sc", SERVICE_CLASSNAME, true, "Service class name");
+ options.addOption(sreviceClassNameOption);
+
+ /** Creates an Option for serviceClassDir */
+ Option serviceClassDirOption = new Option("sd", SERVICE_CLASS_DIR, true, "The output directory for Service class generation (For example : src/com/edm/entities)");
+ options.addOption(serviceClassDirOption);
+
+ /** Creates an Option for entityClassDir */
+ Option entityClassDirOption = new Option("ed", ENTITY_CLASS_DIR, true, "The output directory for Entity class generation (For example : src/com/edm/entities");
+ options.addOption(entityClassDirOption);
+
+ }
+
+ /**
+ * Prints the usage.
+ *
+ * @param options the options
+ */
+ public static void printUsage(Options options)
+ {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("available options as follow : ", options );
+ System.exit(1);
+ }
+
+ /**
+ * To retrieve argument for the Option.
+ *
+ * @param option the option
+ * @param commandLine the command line
+ * @return the option
+ */
+ public static String getOption(final String option, final CommandLine commandLine) {
+
+ if (commandLine.hasOption(option)) {
+ return commandLine.getOptionValue(option);
+ }
+
+ return null;
+ }
+
+ /**
+ * Generates the client code to the given output directory.
+ *
+ * @param outputDir The output directory.
+ * @param serviceDir the service dir
+ * @throws Exception the exception
+ */
+ public void generate(File outputDir, File serviceDir) throws Exception {
+ Service service = new Service(serviceUrl);
+ if(challengeScheme != null && userName != null && password != null){
+ service.setCredentials(new ChallengeResponse(challengeScheme, userName,
+ password));
+ }
+ Configuration fmc = new Configuration();
+ fmc.setDefaultEncoding(CharacterSet.UTF_8.getName());
+
+ // Generate classes
+ String rootTemplates = "clap://class/org/restlet/ext/odata/internal/templates";
+ Representation complexTmpl = new StringRepresentation(
+ new ClientResource(rootTemplates + "/complexType.ftl").get()
+ .getText());
+ Representation entityTmpl = new StringRepresentation(
+ new ClientResource(rootTemplates + "/entityType.ftl").get()
+ .getText());
+ Representation serviceTmpl = new StringRepresentation(
+ new ClientResource(rootTemplates + "/service.ftl").get()
+ .getText());
+
+ Metadata metadata = (Metadata) service.getMetadata();
+ for (Schema schema : metadata.getSchemas()) {
+ if ((schema.getEntityTypes() != null && !schema.getEntityTypes()
+ .isEmpty())
+ || (schema.getComplexTypes() != null && !schema
+ .getComplexTypes().isEmpty())) {
+
+ packageDir = outputDir != null ? outputDir : new File(
+ TypeUtils.getPackageName(schema));
+ packageDir.mkdirs();
+
+ String packageName = outputDir != null ? (entityPkg.replace(
+ "/", ".")) : TypeUtils.getPackageName(schema);
+ // For each entity type
+ for (EntityType type : schema.getEntityTypes()) {
+ String className = type.getClassName();
+ Map dataModel = new HashMap();
+ dataModel.put("type", type);
+ dataModel.put("schema", schema);
+ dataModel.put("metadata", metadata);
+ dataModel.put("className", className);
+ dataModel.put("packageName", packageName);
+
+ try {
+ TemplateRepresentation templateRepresentation = new TemplateRepresentation(
+ entityTmpl, fmc, dataModel,
+ MediaType.TEXT_PLAIN);
+ templateRepresentation
+ .setCharacterSet(CharacterSet.UTF_8);
+
+ // Write the template representation as a Java class
+ templateRepresentation.write(new FileOutputStream(
+ new File(packageDir, type.getClassName()
+ + ".java")));
+ } catch (Exception e) {
+ String errormsg = "Exception Occurred in generating entity type for - "
+ + type.getClassName();
+ LOGGER.log(Level.SEVERE,errormsg);
+ }
+
+ }
+
+ for (ComplexType type : schema.getComplexTypes()) {
+ String className = type.getClassName();
+ Map dataModel = new HashMap();
+ dataModel.put("type", type);
+ dataModel.put("schema", schema);
+ dataModel.put("metadata", metadata);
+ dataModel.put("className", className);
+ dataModel.put("packageName", packageName);
+
+ try {
+ TemplateRepresentation templateRepresentation = new TemplateRepresentation(
+ complexTmpl, fmc, dataModel,
+ MediaType.TEXT_PLAIN);
+
+ templateRepresentation
+ .setCharacterSet(CharacterSet.UTF_8);
+
+ // Write the template representation as a Java class
+ templateRepresentation.write(new FileOutputStream(
+ new File(packageDir, type.getClassName()
+ + ".java")));
+ } catch (Exception e) {
+ String errormsg = "Exception Occurred in generating complex type for - "
+ + type.getClassName();
+ LOGGER.log(Level.SEVERE,errormsg);
+ }
+ }
+ }
+ }
+
+ if (metadata.getContainers() != null
+ && !metadata.getContainers().isEmpty()) {
+ for (EntityContainer entityContainer : metadata.getContainers()) {
+ Schema schema = entityContainer.getSchema();
+ // Generate Service subclass
+ StringBuffer className = new StringBuffer();
+ if (serviceClassName != null) {
+ // Try to use the Client preference
+ if (entityContainer.isDefaultEntityContainer()) {
+ className.append(serviceClassName);
+ } else if (metadata.getContainers().size() == 1) {
+ className.append(serviceClassName);
+ } else {
+ className.append(schema.getNamespace()
+ .getNormalizedName().substring(0, 1)
+ .toUpperCase());
+ className.append(schema.getNamespace()
+ .getNormalizedName().substring(1));
+ className.append("Service");
+ }
+ } else {
+ className.append(schema.getNamespace().getNormalizedName()
+ .substring(0, 1).toUpperCase());
+ className.append(schema.getNamespace().getNormalizedName()
+ .substring(1));
+ className.append("Service");
+ }
+
+ String packageName = outputDir != null ? (servicePkg.replace(
+ "/", ".")) : TypeUtils.getPackageName(schema);
+ String entityClassPkg = outputDir != null ? (entityPkg.replace("/", ".")) : TypeUtils
+ .getPackageName(schema);
+ Map dataModel = new HashMap();
+ dataModel.put("schema", schema);
+ dataModel.put("metadata", metadata);
+ dataModel.put("className", className);
+ dataModel.put(CHALLENGE_SCHEME, challengeScheme != null ? "ChallengeScheme."+challengeScheme.getName() : null);
+ dataModel.put(USERNAME, userName);
+ dataModel.put(PASSWORD, password);
+ dataModel.put("dataServiceUri", service.getServiceRef()
+ .getTargetRef());
+ dataModel.put("entityContainer", entityContainer);
+ dataModel.put("servicePkg", servicePkg.replace("/", "."));
+ dataModel.put("entityClassPkg", entityClassPkg);
+ dataModel.put("packageName", packageName);
+
+ try {
+ TemplateRepresentation templateRepresentation = new TemplateRepresentation(
+ serviceTmpl, fmc, dataModel, MediaType.TEXT_PLAIN);
+ templateRepresentation.setCharacterSet(CharacterSet.UTF_8);
+
+ // Write the template representation as a Java class
+ templateRepresentation.write(new FileOutputStream(new File(
+ serviceDir, className + ".java")));
+ } catch (Exception e) {
+ String errormsg = "Exception Occurred in generating Service class for - "
+ + className;
+ LOGGER.log(Level.SEVERE,errormsg);
+ }
+ }
+ }
+ }
+
+ /**
+ * Generates the client code to the given output directory.
+ *
+ * @param outputDir The output directory.
+ * @throws Exception the exception
+ */
+ public void generate(String outputDir) throws Exception {
+ generate(new File(outputDir), new File(outputDir));
+ }
}
diff --git a/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Query.java b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Query.java
index ada2eed62e..89b3dc5ecc 100644
--- a/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Query.java
+++ b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Query.java
@@ -51,6 +51,7 @@
import org.restlet.ext.odata.internal.FeedContentHandler;
import org.restlet.ext.odata.internal.edm.EntityType;
import org.restlet.ext.odata.internal.edm.Metadata;
+import org.restlet.ext.odata.xml.AtomFeedHandler;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ClientResource;
@@ -368,23 +369,15 @@ public void execute() throws Exception {
// Guess the type of query based on the URI structure
switch (guessType(targetUri)) {
case TYPE_ENTITY_SET:
- FeedContentHandler feedContentHandler = new FeedContentHandler(
- entityClass, entityType, metadata, getLogger());
- setFeed(new Feed(result, feedContentHandler));
- this.count = feedContentHandler.getCount();
- this.entities = feedContentHandler.getEntities();
- break;
case TYPE_ENTITY:
- EntryContentHandler entryContentHandler = new EntryContentHandler(
- entityClass, entityType, metadata, getLogger());
Feed feed = new Feed();
- feed.getEntries().add(
- new Entry(result, entryContentHandler));
- setFeed(feed);
- entities = new ArrayList();
- if (entryContentHandler.getEntity() != null) {
- entities.add(entryContentHandler.getEntity());
- }
+ AtomFeedHandler feedHandler = new AtomFeedHandler(entityType.getName(), entityType, entityClass, metadata);
+ ///AtomFeedCursorHandler feedHandler = new AtomFeedCursorHandler(entityType.getName(), entityType, entityClass);
+ feedHandler.setFeed(feed);
+ feedHandler.parse(result.getReader());
+ this.setFeed(feed);
+ this.count = -1;// no need to set as we send $count request later
+ this.entities = feedHandler.getEntities();
break;
case TYPE_UNKNOWN:
// Guess the type of query based on the returned
@@ -394,13 +387,13 @@ public void execute() throws Exception {
String string = rep.getText().substring(0,
Math.min(100, rep.getText().length()));
if (string.contains("(
+ FeedContentHandler feedContentHandler = new FeedContentHandler(
entityClass, entityType, metadata, getLogger());
setFeed(new Feed(rep, feedContentHandler));
this.count = feedContentHandler.getCount();
this.entities = feedContentHandler.getEntities();
} else if (string.contains("(
+ EntryContentHandler entryContentHandler = new EntryContentHandler(
entityClass, entityType, metadata, getLogger());
feed = new Feed();
feed.getEntries().add(
@@ -430,6 +423,19 @@ public void execute() throws Exception {
}
}
+
+ /**
+ * Gets the query client resource,used in the GetEntityRequest for Batch execution.
+ *
+ * @return the query client resource
+ */
+ public ClientResource getQueryClientResource() {
+ String targetUri = createTargetUri();
+ ClientResource resource = service.createResource(new Reference(
+ targetUri));
+ return resource;
+ }
+
/**
* Creates a new Query with the $expand option set in the URI generated
* by the returned query.
@@ -777,4 +783,11 @@ public Query skipToken(String token) {
public Query top(int rowsCount) {
return addParameter("$top", Integer.toString(rowsCount));
}
+
+ /**
+ * @return
+ */
+ public Class> getEntityClass() {
+ return entityClass;
+ }
}
diff --git a/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Service.java b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Service.java
index 3012ae3390..7db4a0ff01 100644
--- a/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Service.java
+++ b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/Service.java
@@ -35,11 +35,15 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -49,6 +53,7 @@
import org.restlet.Response;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.CharacterSet;
+import org.restlet.data.Cookie;
import org.restlet.data.Header;
import org.restlet.data.MediaType;
import org.restlet.data.Parameter;
@@ -58,12 +63,10 @@
import org.restlet.data.Tag;
import org.restlet.engine.header.HeaderConstants;
import org.restlet.engine.header.HeaderReader;
+import org.restlet.engine.header.HeaderUtils;
import org.restlet.ext.atom.Content;
import org.restlet.ext.atom.Entry;
-import org.restlet.ext.atom.Feed;
-import org.restlet.ext.atom.Link;
-import org.restlet.ext.atom.Relation;
-import org.restlet.ext.odata.internal.EntryContentHandler;
+import org.restlet.ext.odata.batch.util.RestletBatchRequestHelper;
import org.restlet.ext.odata.internal.edm.AssociationEnd;
import org.restlet.ext.odata.internal.edm.ComplexProperty;
import org.restlet.ext.odata.internal.edm.EntityContainer;
@@ -73,9 +76,13 @@
import org.restlet.ext.odata.internal.edm.Property;
import org.restlet.ext.odata.internal.edm.TypeUtils;
import org.restlet.ext.odata.internal.reflect.ReflectUtils;
+import org.restlet.ext.odata.streaming.StreamReference;
+import org.restlet.ext.odata.validation.annotation.SystemGenerated;
+import org.restlet.ext.odata.xml.AtomFeedHandler;
import org.restlet.ext.xml.DomRepresentation;
import org.restlet.ext.xml.SaxRepresentation;
import org.restlet.ext.xml.XmlWriter;
+import org.restlet.ext.xml.format.XmlFormatParser;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ClientResource;
@@ -129,7 +136,13 @@ public class Service {
/** The internal logger. */
private Logger logger;
-
+
+ private String slug = "";
+
+ /**
+ * add Query parameter in request header for each call.
+ */
+ private Map parameters;
/**
* The maximum version of the OData protocol extensions the client can
* accept in a response.
@@ -148,6 +161,18 @@ public class Service {
/** The reference of the WCF service. */
private Reference serviceRef;
+ /** The content type. */
+ private String contentType;
+
+ /** The isUpdateStreamData used to decide update operation on stream. */
+ private boolean isUpdateStreamData;
+
+ /** List of cookies used to cache the cookies sent from server. */
+ List cookies;
+
+ /** The isPostRequest used to differentiate POST request. */
+ private boolean isPostRequest;
+
/**
* Constructor.
*
@@ -199,6 +224,8 @@ public Service(String serviceUri) {
/**
* Adds an entity to an entity set.
+ * @param
+ * @param
*
* @param entitySetName
* The path of the entity set relatively to the service URI.
@@ -206,41 +233,103 @@ public Service(String serviceUri) {
* The entity to put.
* @throws Exception
*/
- public void addEntity(String entitySetName, Object entity) throws Exception {
- if (entity != null) {
- Entry entry = toEntry(entity);
-
- ClientResource resource = createResource(entitySetName);
- if (getMetadata() == null) {
- throw new Exception("Can't add entity to this entity set "
- + resource.getReference()
- + " due to the lack of the service's metadata.");
- }
-
- try {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- entry.write(baos);
- baos.flush();
- StringRepresentation r = new StringRepresentation(
- baos.toString(), MediaType.APPLICATION_ATOM);
- Representation rep = resource.post(r);
- EntryContentHandler> entryContentHandler = new EntryContentHandler
+ String nsPrefix = element.getName().getPrefix();
+ for (Iterator iterator1 = element.getAttributes(); iterator1.hasNext();) {
+ Attribute attribute = (Attribute)iterator1.next();
+ String attributeValue = getAttributeValueIfExists(element, attribute.getName());
+ String attibuteTag = parentTag+"/@"+attribute.getName().getLocalPart();
+ for (Iterator iterator = mappings.iterator(); iterator.hasNext();) {
+ Mapping mapping = (Mapping) iterator.next();
+ if(null != mapping.getNsPrefix() && mapping.getNsPrefix().equalsIgnoreCase(nsPrefix)){
+ if(attributeValue!= null & mapping.getValuePath().equalsIgnoreCase(attibuteTag)){
+ String propertyName = ReflectUtils.normalize(mapping.getPropertyPath());
+ ReflectUtils.invokeSetter(entity, propertyName, attributeValue);
+ break;
+ }
+ }
+ }
+ }
+
+
+ StartElement valueElement = null;
+ String propertyName = null;
+ while(reader.hasNext()){
+
+ XMLEvent event2;
+
+ try {
+ // iterate all the sub-elements under parent tag with
+ event2 = reader.nextEvent();
+ if (event2.isEndElement()
+ && event2.asEndElement().getName()
+ .equals(element.getName())) {
+ break;
+ }
+ if (valueElement == null && event2.isStartElement()) {
+ valueElement = event2.asStartElement();
+ // Iterate through sub-paths and set respective property for the entity.
+ // Eg:Cafe corp.
+ String innerTag = parentTag+"/"+valueElement.getName().getLocalPart();
+ for (Iterator iterator = mappings.iterator(); iterator.hasNext();) {
+ Mapping mapping = (Mapping) iterator.next();
+ if(mapping.getValuePath().equalsIgnoreCase(innerTag)){
+
+ //TODO: Abhijeet : Extract this into method and refer it in parseProperties
+ propertyName = ReflectUtils.normalize(mapping.getPropertyPath());
+ parsePropertiesByType(reader, entity, propertyName, event2);
+ break; // exit for loop if mapping is present and addressed
+
+ }
+ }
+ }
+ }catch (XMLStreamException e1) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the entry due to: " + e1.getMessage());
+ } catch (Exception e1) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the entry due to: " + e1.getMessage());
+ }
+ }
+ rt = e;
+ }
+ }
+ } catch (XMLStreamException e1) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the entry due to: " + e1.getMessage());
+ } catch (Exception e1) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the entry due to: " + e1.getMessage());
+ }
+
+ }
+ throw new RuntimeException();
+ }
+
+ /**
+ * @param reader
+ * @param p
+ * @param event
+ */
+ private void parseAuthor(XMLEventReader reader, Person p, XMLEvent event) {
+ StartElement contentElement = event.asStartElement();
+ StartElement valueElement = null;
+ while (reader.hasNext()) {
+ // handle content in separate handlers
+ XMLEvent event2;
+ try {
+ event2 = reader.nextEvent();
+ if (valueElement == null && event2.isStartElement()) {
+ valueElement = event2.asStartElement();
+ if (isStartElement(event2, ATOM_NAME)) {
+ String name = reader.getElementText();
+ if(!name.isEmpty()){
+ p.setName(name);
+ }
+ }else if (isStartElement(event2, ATOM_EMAIL)) {
+ String email = reader.getElementText();
+ if(!email.isEmpty()){
+ p.setEmail(email);
+ }
+ }
+ }
+ if (event2.isEndElement()
+ && event2.asEndElement().getName()
+ .equals(contentElement.getName())) {
+ break;
+ }
+ }catch (XMLStreamException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the author due to: " + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Method to set atom mappings to corresponding entity.
+ * @param entity
+ * @param author
+ * @param contributor
+ */
+ private void setDetailsOfPerson(T entity, Person author, Person contributor) {
+ // Handle Atom mapped values.
+ for (Mapping m : metadata.getMappings()) {
+ if (entityType != null && entityType.equals(m.getType())
+ && m.getNsUri() == null && m.getNsPrefix() == null) {
+
+ Object value = null;
+ if ("SyndicationAuthorEmail".equals(m.getValuePath())) {
+ value = (author != null) ? author.getEmail() : null;
+ } else if ("SyndicationAuthorName".equals(m.getValuePath())) {
+ value = (author != null) ? author.getName() : null;
+ } else if ("SyndicationAuthorUri".equals(m.getValuePath())) {
+ value = (author != null) ? author.getUri().toString()
+ : null;
+ } else if ("SyndicationContributorEmail".equals(m
+ .getValuePath())) {
+ value = (contributor != null) ? contributor.getEmail()
+ : null;
+ } else if ("SyndicationContributorName"
+ .equals(m.getValuePath())) {
+ value = (contributor != null) ? contributor.getName()
+ : null;
+ } else if ("SyndicationContributorUri".equals(m.getValuePath())) {
+ value = (contributor != null) ? contributor.getUri()
+ .toString() : null;
+ } /*else if ("SyndicationPublished".equals(m.getValuePath())) {
+ value = entry.getPublished();
+ } else if ("SyndicationRights".equals(m.getValuePath())) {
+ value = (entry.getRights() != null) ? entry.getRights()
+ .getContent() : null;
+ } else if ("SyndicationSummary".equals(m.getValuePath())) {
+ value = entry.getSummary();
+ } else if ("SyndicationTitle".equals(m.getValuePath())) {
+ value = (entry.getTitle() != null) ? entry.getTitle()
+ .getContent() : null;
+ } else if ("SyndicationUpdated".equals(m.getValuePath())) {
+ value = entry.getUpdated();
+ }*/
+
+ try {
+ if (value != null) {
+ ReflectUtils.invokeSetter(entity, m.getPropertyPath(),
+ value);
+ }
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the content due to: " + e.getMessage());
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Parses the atom link.
+ *
+ * @param reader the reader
+ * @param linkElement the link element
+ * @param entitySet the entity set
+ * @param entity the entity
+ * @return the link
+ */
+ private Link parseAtomLink(XMLEventReader reader, StartElement linkElement,
+ EntitySet entitySet, T entity) {
+
+ try {
+ Link rt = new Link();
+ rt.setRel(Relation.valueOf(getAttributeValueIfExists(linkElement,
+ "rel")));
+ rt.setType(MediaType.valueOf(getAttributeValueIfExists(linkElement,
+ "type")));
+ rt.setTitle(getAttributeValueIfExists(linkElement, "title"));
+ rt.setHref(new Reference(getAttributeValueIfExists(linkElement,
+ "href")));
+ //boolean inlineContent = false;
+
+ // expected cases:
+ // 1. - no inlined content, i.e. deferred
+ // 2. - inlined content but null entity or empty feed
+ // 3. ... - inlined content with 1 or more items
+ // 4. .. - inlined content 1 an item
+
+ while (reader.hasNext()) {
+ XMLEvent event;
+ event = reader.nextEvent();
+
+ if (event.isEndElement()
+ && event.asEndElement().getName()
+ .equals(linkElement.getName())) {
+ break;
+ } else if (isStartElement(event, XmlFormatParser.M_INLINE)) {
+ //inlineContent = true; // may be null content.
+ } else if (isStartElement(event, ATOM_FEED)) {
+ //skip all tags until we encounter first entry element to exclude link and other tags.
+ // Fix for edit link tag to prevent pre-matured exit of parent link iteration.
+ while( reader.hasNext()){
+ event = reader.nextEvent();
+ if(isStartElement(event,ATOM_ENTRY)){
+ String propertyName = rt.getHref().getLastSegment();
+ // create a property object
+ Object o = ReflectUtils.getPropertyObject(entity, propertyName);
+ parseInlineEntities(reader, entitySet, entity, event, propertyName, o);
+ // This break is added to not handle additional inline entities here. Those entries shall be handled in next else-if block.
+ break;
+ } else if(event.isEndElement() && event.asEndElement().getName().equals(ATOM_FEED.getLocalPart())){
+ break;
+ }
+ }
+ } else if (isStartElement(event, ATOM_ENTRY)) { //handle the inline entity
+ String propertyName = rt.getHref().getLastSegment();
+ // create a property object
+ Object o = ReflectUtils.getPropertyObject(entity, propertyName);
+ parseInlineEntities(reader, entitySet, entity, event, propertyName, o);
+ }
+ }
+ return rt;
+ } catch (XMLStreamException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the atom link due to: " + e.getMessage());
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the atom link due to: " + e.getMessage());
+ }
+ return null;
+ }
+
+ /**
+ * Method to parse Inline entities.
+ * @param reader
+ * @param entitySet
+ * @param entity
+ * @param event
+ * @param propertyName
+ * @param o
+ * @throws NoSuchFieldException
+ * @throws InstantiationException
+ * @throws IllegalAccessException
+ * @throws Exception
+ */
+ @SuppressWarnings(value = {"unchecked", "rawtypes" })
+ private void parseInlineEntities(XMLEventReader reader, EntitySet entitySet, T entity, XMLEvent event,
+ String propertyName, Object o) {
+ try {
+ if (o instanceof List) { // Collection of complex i.e. one to many association
+ Field field = entity.getClass().getDeclaredField(ReflectUtils.normalize(propertyName));
+ // String currentMType = startElement.getAttributeByName(M_TYPE).getValue();
+ // get the parameterize type using reflection
+ if (field.getGenericType() instanceof ParameterizedType) {
+ // determine what type of collection it is
+ ParameterizedType listType = (ParameterizedType) field.getGenericType();
+ Class> listClass = (Class>) listType.getActualTypeArguments()[0];
+ // Create new Item Instance
+ Object obj;
+ obj = listClass.newInstance();
+
+ // create a new instance and populate the properties
+ this.parseEntry(reader, event.asStartElement(), entitySet, (T) obj);
+ ((List) o).add(obj);
+ }
+
+ } else { // complex object i.e. embedded object in parent entity
+ // populate the object
+ this.parseEntry(reader, event.asStartElement(), entitySet, (T) o);
+ // set it back to parent entity
+ ReflectUtils.invokeSetter(entity, ReflectUtils.normalize(propertyName), o);
+ }
+ } catch (InstantiationException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the inline entities due to: " + e.getMessage());
+ } catch (IllegalAccessException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the inline entities due to: " + e.getMessage());
+ } catch (SecurityException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the inline entities due to: " + e.getMessage());
+ } catch (NoSuchFieldException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the inline entities due to: " + e.getMessage());
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the inline entities due to: " + e.getMessage());
+ }
+ }
+
+}
diff --git a/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/xml/CollectionPropertyHandler.java b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/xml/CollectionPropertyHandler.java
new file mode 100644
index 0000000000..a19c3df813
--- /dev/null
+++ b/modules/org.restlet.ext.odata/src/org/restlet/ext/odata/xml/CollectionPropertyHandler.java
@@ -0,0 +1,105 @@
+package org.restlet.ext.odata.xml;
+
+import static org.restlet.ext.xml.format.XmlFormatParser.DATASERVICES_ELEMENT;
+import static org.restlet.ext.xml.format.XmlFormatParser.M_TYPE;
+import static org.restlet.ext.xml.format.XmlFormatParser.NS_DATASERVICES;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.List;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.restlet.Context;
+import org.restlet.ext.odata.internal.edm.TypeUtils;
+
+/**
+ * The Class CollectionPropertyHandler which handles all type of collections.
+ *
+ * @author Onkar Dhuri
+ */
+public class CollectionPropertyHandler {
+
+ /**
+ * Parses the collection of either simple type or complex type
+ *
+ * @param the generic type
+ * @param reader the reader
+ * @param entity the entity
+ * @param startElement the start element
+ * @param parentEntity the parent entity
+ * @return the t
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static T parse(XMLEventReader reader, T entity,
+ StartElement startElement, T parentEntity) {
+
+ try {
+ Object obj = null;
+ String collectionType;
+ while (reader.hasNext()) {
+ XMLEvent event = reader.nextEvent();
+
+ if (event.isEndElement()
+ && event.asEndElement().getName()
+ .equals(startElement.getName())) {
+ return entity;
+ }
+
+ if (event.isStartElement()
+ && event.asStartElement().getName().getNamespaceURI()
+ .equals(NS_DATASERVICES)
+ && event.asStartElement().getName()
+ .equals(DATASERVICES_ELEMENT)) {
+ if (entity instanceof List) { // check first if it is type of List
+ Field field = parentEntity.getClass().getDeclaredField(
+ startElement.getName().getLocalPart());
+ String currentMType = startElement.getAttributeByName(
+ M_TYPE).getValue();
+ if (field.getGenericType() instanceof ParameterizedType) {
+ // determine what type of collection it is
+ ParameterizedType listType = (ParameterizedType) field
+ .getGenericType();
+ collectionType = TypeUtils
+ .getCollectionType(currentMType);
+ Class> listClass = (Class>) listType
+ .getActualTypeArguments()[0];
+ if (collectionType.toLowerCase().startsWith("edm")) { // simple type
+ // just add value to list
+ Object value = TypeUtils.convert(listClass,
+ reader.getElementText());
+ ((List) entity).add(value);
+ } else { // complex type
+ obj = listClass.newInstance();
+ // create a new instance and populate the properties
+ AtomFeedHandler.parseProperties(reader,
+ event.asStartElement(), obj);
+ ((List) entity).add(obj);
+ }
+ }
+ }
+ }
+ }
+ } catch (XMLStreamException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the collection due to: " + e.getMessage());
+ } catch (SecurityException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the collection due to: " + e.getMessage());
+ } catch (NoSuchFieldException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the collection due to: " + e.getMessage());
+ } catch (InstantiationException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the collection due to: " + e.getMessage());
+ } catch (IllegalAccessException e) {
+ Context.getCurrentLogger().warning(
+ "Cannot parse the collection due to: " + e.getMessage());
+ }
+ return entity;
+ }
+
+}
diff --git a/modules/org.restlet.ext.xml/module.xml b/modules/org.restlet.ext.xml/module.xml
index 42fe1a3041..b5ecbc2a79 100644
--- a/modules/org.restlet.ext.xml/module.xml
+++ b/modules/org.restlet.ext.xml/module.xml
@@ -9,6 +9,7 @@
+
diff --git a/modules/org.restlet.ext.xml/src/org/restlet/ext/xml/format/FormatParser.java b/modules/org.restlet.ext.xml/src/org/restlet/ext/xml/format/FormatParser.java
new file mode 100644
index 0000000000..586b30cf4a
--- /dev/null
+++ b/modules/org.restlet.ext.xml/src/org/restlet/ext/xml/format/FormatParser.java
@@ -0,0 +1,28 @@
+package org.restlet.ext.xml.format;
+
+import java.io.Reader;
+
+/**
+ * Deals with parsing the resulting stream into a Entry or
+ * Feed and converting it to a OEntity. The
+ * implementation depends on the format Atom or Json.
+ *
+ * @param Atom or json
+ *
+ * @author Onkar Dhuri
+ *
+ * @see Entry
+ * @see Feed
+ * @see OEntity
+ */
+public interface FormatParser {
+
+ /**
+ * Parses the feed from reader
+ *
+ * @param reader the reader
+ * @return the t
+ */
+ T parse(Reader reader);
+
+}
diff --git a/modules/org.restlet.ext.xml/src/org/restlet/ext/xml/format/XmlFormatParser.java b/modules/org.restlet.ext.xml/src/org/restlet/ext/xml/format/XmlFormatParser.java
new file mode 100644
index 0000000000..61ca232479
--- /dev/null
+++ b/modules/org.restlet.ext.xml/src/org/restlet/ext/xml/format/XmlFormatParser.java
@@ -0,0 +1,252 @@
+package org.restlet.ext.xml.format;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.core4j.Enumerable;
+
+/**
+ * The Class XmlFormatParser.
+ *
+ * @author Onkar Dhuri
+ */
+public class XmlFormatParser {
+
+ public static final String NS_APP = "http://www.w3.org/2007/app";
+ public static final String NS_XML = "http://www.w3.org/XML/1998/namespace";
+ public static final String NS_ATOM = "http://www.w3.org/2005/Atom";
+
+ public static final String NS_METADATA = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
+ public static final String NS_DATASERVICES = "http://schemas.microsoft.com/ado/2007/08/dataservices";
+ public static final String NS_SCHEME = "http://schemas.microsoft.com/ado/2007/08/dataservices/scheme";
+ public static final String NS_RELATED = "http://schemas.microsoft.com/ado/2007/08/dataservices/related/";
+ public static final String NS_EDM2006 = "http://schemas.microsoft.com/ado/2006/04/edm"; // edm 1.0
+ public static final String NS_EDM2007 = "http://schemas.microsoft.com/ado/2007/05/edm"; // edm 1.1
+ public static final String NS_EDM2008_1 = "http://schemas.microsoft.com/ado/2008/01/edm"; // edm 1.2
+ public static final String NS_EDM2008_9 = "http://schemas.microsoft.com/ado/2008/09/edm"; // edm 2.0
+ public static final String NS_EDM2009_8 = "http://schemas.microsoft.com/ado/2009/08/edm"; // edm ???
+ public static final String NS_EDM2009_11 = "http://schemas.microsoft.com/ado/2009/11/edm"; // edm 3.0
+ public static final String NS_EDMX = "http://schemas.microsoft.com/ado/2007/06/edmx";
+ public static final String NS_EDMANNOTATION = "http://schemas.microsoft.com/ado/2009/02/edm/annotation";
+ public static final String NS_CUSTOM_EDMANNOTATION = "http://www.lgc.com/dsdataserver/annotation";
+
+ public static final QName EDMX_EDMX = new QName(NS_EDMX, "Edmx");
+ public static final QName EDMX_DATASERVICES = new QName(NS_EDMX, "DataServices");
+
+ public static final QName EDM2006_SCHEMA = new QName(NS_EDM2006, "Schema");
+ public static final QName EDM2006_ENTITYTYPE = new QName(NS_EDM2006, "EntityType");
+ public static final QName EDM2006_ASSOCIATION = new QName(NS_EDM2006, "Association");
+ public static final QName EDM2006_COMPLEXTYPE = new QName(NS_EDM2006, "ComplexType");
+ public static final QName EDM2006_ENTITYCONTAINER = new QName(NS_EDM2006, "EntityContainer");
+ public static final QName EDM2006_ENTITYSET = new QName(NS_EDM2006, "EntitySet");
+ public static final QName EDM2006_ASSOCIATIONSET = new QName(NS_EDM2006, "AssociationSet");
+ public static final QName EDM2006_FUNCTIONIMPORT = new QName(NS_EDM2006, "FunctionImport");
+ public static final QName EDM2006_PARAMETER = new QName(NS_EDM2006, "Parameter");
+ public static final QName EDM2006_END = new QName(NS_EDM2006, "End");
+ public static final QName EDM2006_ONDELETE = new QName(NS_EDM2006, "OnDelete");
+ public static final QName EDM2006_REFCONSTRAINT = new QName(NS_EDM2006, "ReferentialConstraint");
+ public static final QName EDM2006_PRINCIPAL = new QName(NS_EDM2006, "Principal");
+ public static final QName EDM2006_DEPENDENT = new QName(NS_EDM2006, "Dependent");
+ public static final QName EDM2006_PROPERTYREF = new QName(NS_EDM2006, "PropertyRef");
+ public static final QName EDM2006_PROPERTY = new QName(NS_EDM2006, "Property");
+ public static final QName EDM2006_NAVIGATIONPROPERTY = new QName(NS_EDM2006, "NavigationProperty");
+
+ public static final QName EDM2007_SCHEMA = new QName(NS_EDM2007, "Schema");
+ public static final QName EDM2007_ENTITYTYPE = new QName(NS_EDM2007, "EntityType");
+ public static final QName EDM2007_ASSOCIATION = new QName(NS_EDM2007, "Association");
+ public static final QName EDM2007_COMPLEXTYPE = new QName(NS_EDM2007, "ComplexType");
+ public static final QName EDM2007_ENTITYCONTAINER = new QName(NS_EDM2007, "EntityContainer");
+ public static final QName EDM2007_ENTITYSET = new QName(NS_EDM2007, "EntitySet");
+ public static final QName EDM2007_ASSOCIATIONSET = new QName(NS_EDM2007, "AssociationSet");
+ public static final QName EDM2007_FUNCTIONIMPORT = new QName(NS_EDM2007, "FunctionImport");
+ public static final QName EDM2007_PARAMETER = new QName(NS_EDM2007, "Parameter");
+ public static final QName EDM2007_END = new QName(NS_EDM2007, "End");
+ public static final QName EDM2007_ONDELETE = new QName(NS_EDM2007, "OnDelete");
+ public static final QName EDM2007_REFCONSTRAINT = new QName(NS_EDM2007, "ReferentialConstraint");
+ public static final QName EDM2007_PRINCIPAL = new QName(NS_EDM2007, "Principal");
+ public static final QName EDM2007_DEPENDENT = new QName(NS_EDM2007, "Dependent");
+ public static final QName EDM2007_PROPERTYREF = new QName(NS_EDM2007, "PropertyRef");
+ public static final QName EDM2007_PROPERTY = new QName(NS_EDM2007, "Property");
+ public static final QName EDM2007_NAVIGATIONPROPERTY = new QName(NS_EDM2007, "NavigationProperty");
+
+ public static final QName EDM2008_1_SCHEMA = new QName(NS_EDM2008_1, "Schema");
+ public static final QName EDM2008_1_ENTITYTYPE = new QName(NS_EDM2008_1, "EntityType");
+ public static final QName EDM2008_1_ASSOCIATION = new QName(NS_EDM2008_1, "Association");
+ public static final QName EDM2008_1_COMPLEXTYPE = new QName(NS_EDM2008_1, "ComplexType");
+ public static final QName EDM2008_1_ENTITYCONTAINER = new QName(NS_EDM2008_1, "EntityContainer");
+ public static final QName EDM2008_1_ENTITYSET = new QName(NS_EDM2008_1, "EntitySet");
+ public static final QName EDM2008_1_ASSOCIATIONSET = new QName(NS_EDM2008_1, "AssociationSet");
+ public static final QName EDM2008_1_FUNCTIONIMPORT = new QName(NS_EDM2008_1, "FunctionImport");
+ public static final QName EDM2008_1_PARAMETER = new QName(NS_EDM2008_1, "Parameter");
+ public static final QName EDM2008_1_END = new QName(NS_EDM2008_1, "End");
+ public static final QName EDM2008_1_ONDELETE = new QName(NS_EDM2008_1, "OnDelete");
+ public static final QName EDM2008_1_REFCONSTRAINT = new QName(NS_EDM2008_1, "ReferentialConstraint");
+ public static final QName EDM2008_1_PRINCIPAL = new QName(NS_EDM2008_1, "Principal");
+ public static final QName EDM2008_1_DEPENDENT = new QName(NS_EDM2008_1, "Dependent");
+ public static final QName EDM2008_1_PROPERTYREF = new QName(NS_EDM2008_1, "PropertyRef");
+ public static final QName EDM2008_1_PROPERTY = new QName(NS_EDM2008_1, "Property");
+ public static final QName EDM2008_1_NAVIGATIONPROPERTY = new QName(NS_EDM2008_1, "NavigationProperty");
+
+ public static final QName EDM2008_9_SCHEMA = new QName(NS_EDM2008_9, "Schema");
+ public static final QName EDM2008_9_ENTITYTYPE = new QName(NS_EDM2008_9, "EntityType");
+ public static final QName EDM2008_9_ASSOCIATION = new QName(NS_EDM2008_9, "Association");
+ public static final QName EDM2008_9_COMPLEXTYPE = new QName(NS_EDM2008_9, "ComplexType");
+ public static final QName EDM2008_9_ENTITYCONTAINER = new QName(NS_EDM2008_9, "EntityContainer");
+ public static final QName EDM2008_9_ENTITYSET = new QName(NS_EDM2008_9, "EntitySet");
+ public static final QName EDM2008_9_ASSOCIATIONSET = new QName(NS_EDM2008_9, "AssociationSet");
+ public static final QName EDM2008_9_FUNCTIONIMPORT = new QName(NS_EDM2008_9, "FunctionImport");
+ public static final QName EDM2008_9_PARAMETER = new QName(NS_EDM2008_9, "Parameter");
+ public static final QName EDM2008_9_END = new QName(NS_EDM2008_9, "End");
+ public static final QName EDM2008_9_ONDELETE = new QName(NS_EDM2008_9, "OnDelete");
+ public static final QName EDM2008_9_REFCONSTRAINT = new QName(NS_EDM2008_9, "ReferentialConstraint");
+ public static final QName EDM2008_9_PRINCIPAL = new QName(NS_EDM2008_9, "Principal");
+ public static final QName EDM2008_9_DEPENDENT = new QName(NS_EDM2008_9, "Dependent");
+ public static final QName EDM2008_9_PROPERTYREF = new QName(NS_EDM2008_9, "PropertyRef");
+ public static final QName EDM2008_9_PROPERTY = new QName(NS_EDM2008_9, "Property");
+ public static final QName EDM2008_9_NAVIGATIONPROPERTY = new QName(NS_EDM2008_9, "NavigationProperty");
+
+ public static final QName EDM2009_8_SCHEMA = new QName(NS_EDM2009_8, "Schema");
+ public static final QName EDM2009_8_ENTITYTYPE = new QName(NS_EDM2009_8, "EntityType");
+ public static final QName EDM2009_8_ASSOCIATION = new QName(NS_EDM2009_8, "Association");
+ public static final QName EDM2009_8_COMPLEXTYPE = new QName(NS_EDM2009_8, "ComplexType");
+ public static final QName EDM2009_8_ENTITYCONTAINER = new QName(NS_EDM2009_8, "EntityContainer");
+ public static final QName EDM2009_8_ENTITYSET = new QName(NS_EDM2009_8, "EntitySet");
+ public static final QName EDM2009_8_ASSOCIATIONSET = new QName(NS_EDM2009_8, "AssociationSet");
+ public static final QName EDM2009_8_FUNCTIONIMPORT = new QName(NS_EDM2009_8, "FunctionImport");
+ public static final QName EDM2009_8_PARAMETER = new QName(NS_EDM2009_8, "Parameter");
+ public static final QName EDM2009_8_END = new QName(NS_EDM2009_8, "End");
+ public static final QName EDM2009_8_ONDELETE = new QName(NS_EDM2009_8, "OnDelete");
+ public static final QName EDM2009_8_REFCONSTRAINT = new QName(NS_EDM2009_8, "ReferentialConstraint");
+ public static final QName EDM2009_8_PRINCIPAL = new QName(NS_EDM2009_8, "Principal");
+ public static final QName EDM2009_8_DEPENDENT = new QName(NS_EDM2009_8, "Dependent");
+ public static final QName EDM2009_8_PROPERTYREF = new QName(NS_EDM2009_8, "PropertyRef");
+ public static final QName EDM2009_8_PROPERTY = new QName(NS_EDM2009_8, "Property");
+ public static final QName EDM2009_8_NAVIGATIONPROPERTY = new QName(NS_EDM2009_8, "NavigationProperty");
+
+ public static final QName EDM2009_11_SCHEMA = new QName(NS_EDM2009_11, "Schema");
+ public static final QName EDM2009_11_ENTITYTYPE = new QName(NS_EDM2009_11, "EntityType");
+ public static final QName EDM2009_11_ASSOCIATION = new QName(NS_EDM2009_11, "Association");
+ public static final QName EDM2009_11_COMPLEXTYPE = new QName(NS_EDM2009_11, "ComplexType");
+ public static final QName EDM2009_11_ENTITYCONTAINER = new QName(NS_EDM2009_11, "EntityContainer");
+ public static final QName EDM2009_11_ENTITYSET = new QName(NS_EDM2009_11, "EntitySet");
+ public static final QName EDM2009_11_ASSOCIATIONSET = new QName(NS_EDM2009_11, "AssociationSet");
+ public static final QName EDM2009_11_FUNCTIONIMPORT = new QName(NS_EDM2009_11, "FunctionImport");
+ public static final QName EDM2009_11_PARAMETER = new QName(NS_EDM2009_11, "Parameter");
+ public static final QName EDM2009_11_END = new QName(NS_EDM2009_11, "End");
+ public static final QName EDM2009_11_ONDELETE = new QName(NS_EDM2009_11, "OnDelete");
+ public static final QName EDM2009_11_REFCONSTRAINT = new QName(NS_EDM2009_11, "ReferentialConstraint");
+ public static final QName EDM2009_11_PRINCIPAL = new QName(NS_EDM2009_11, "Principal");
+ public static final QName EDM2009_11_DEPENDENT = new QName(NS_EDM2009_11, "Dependent");
+ public static final QName EDM2009_11_PROPERTYREF = new QName(NS_EDM2009_11, "PropertyRef");
+ public static final QName EDM2009_11_PROPERTY = new QName(NS_EDM2009_11, "Property");
+ public static final QName EDM2009_11_NAVIGATIONPROPERTY = new QName(NS_EDM2009_11, "NavigationProperty");
+
+ public static final QName ATOM_FEED = new QName(NS_ATOM, "feed");
+ public static final QName ATOM_ENTRY = new QName(NS_ATOM, "entry");
+ public static final QName ATOM_ID = new QName(NS_ATOM, "id");
+ public static final QName ATOM_TITLE = new QName(NS_ATOM, "title");
+ public static final QName ATOM_SUMMARY = new QName(NS_ATOM, "summary");
+ public static final QName ATOM_UPDATED = new QName(NS_ATOM, "updated");
+ public static final QName ATOM_CATEGORY = new QName(NS_ATOM, "category");
+ public static final QName ATOM_CONTENT = new QName(NS_ATOM, "content");
+ public static final QName ATOM_LINK = new QName(NS_ATOM, "link");
+ public static final QName ATOM_AUTHOR = new QName(NS_ATOM, "author");
+ public static final QName ATOM_NAME = new QName(NS_ATOM, "name");
+ public static final QName ATOM_EMAIL = new QName(NS_ATOM, "email");
+
+ public static final QName APP_WORKSPACE = new QName(NS_APP, "workspace");
+ public static final QName APP_SERVICE = new QName(NS_APP, "service");
+ public static final QName APP_COLLECTION = new QName(NS_APP, "collection");
+ public static final QName APP_ACCEPT = new QName(NS_APP, "accept");
+
+ public static final QName M_ETAG = new QName(NS_METADATA, "etag");
+ public static final QName M_PROPERTIES = new QName(NS_METADATA, "properties");
+ public static final QName M_ACTION = new QName(NS_METADATA, "action");
+ public static final QName M_FUNCTION = new QName(NS_METADATA, "function");
+ public static final QName M_TYPE = new QName(NS_METADATA, "type");
+ public static final QName M_NULL = new QName(NS_METADATA, "null");
+ public static final QName M_INLINE = new QName(NS_METADATA, "inline");
+ public static final QName M_MIMETYPE = new QName(NS_METADATA, "MimeType");
+ public static final QName M_FC_TARGETPATH = new QName(NS_METADATA, "FC_TargetPath");
+ public static final QName M_FC_CONTENTKIND = new QName(NS_METADATA, "FC_ContentKind");
+ public static final QName M_FC_KEEPINCONTENT = new QName(NS_METADATA, "FC_KeepInContent");
+ public static final QName M_FC_EPMCONTENTKIND = new QName(NS_METADATA, "FC_EpmContentKind");
+ public static final QName M_FC_EPMKEEPINCONTENT = new QName(NS_METADATA, "FC_EpmKeepInContent");
+ public static final QName M_FC_NSPREFIX = new QName(NS_METADATA, "FC_NsPrefix");
+ public static final QName M_FC_NSURI = new QName(NS_METADATA, "FC_NsUri");
+
+ public static final QName DATASERVICES_ELEMENT = new QName(NS_DATASERVICES, "element"); // a collection element
+
+ public static final QName XML_BASE = new QName(NS_XML, "base");
+
+ protected static boolean isStartElement(XMLEvent event, QName... names) {
+ if (!event.isStartElement()) {
+ return false;
+ }
+ QName name = new QName(event.asStartElement().getName().getNamespaceURI(), event.asStartElement().getName().getLocalPart());
+ return Enumerable.create(names).contains(name);
+
+ }
+
+ protected static boolean isElement(XMLEvent event, QName... names) {
+ QName name = new QName(event.asStartElement().getName().getNamespaceURI(), event.asStartElement().getName().getLocalPart());
+ return Enumerable.create(names).contains(name);
+
+ }
+
+ protected static boolean isEndElement(XMLEvent event, QName qname) {
+ if (!event.isEndElement()) {
+ return false;
+ }
+ QName name = event.asEndElement().getName();
+ return name.getNamespaceURI().equals(qname.getNamespaceURI())
+ && name.getLocalPart().equals(qname.getLocalPart());
+ }
+
+ protected static String urlCombine(String base, String rel) {
+ if (!base.endsWith("/") && !rel.startsWith("/"))
+ base = base + "/";
+ return base + rel;
+ }
+
+ protected static String getAttributeValueIfExists(StartElement element, String localName) {
+ return getAttributeValueIfExists(element, new QName(null, localName));
+ }
+
+ protected static String getAttributeValueIfExists(StartElement element, QName attName) {
+ Attribute rt = element.getAttributeByName(attName);
+ return rt == null ? null : rt.getValue();
+ }
+
+ protected static boolean isStartElement(XMLStreamReader reader, QName... names) {
+ if (!reader.isStartElement()) {
+ return false;
+ }
+ QName name = new QName(reader.getNamespaceURI(), reader.getLocalName());
+ return Enumerable.create(names).contains(name);
+
+ }
+
+ protected static boolean isElement(XMLStreamReader reader, QName... names) {
+ QName name = new QName(reader.getNamespaceURI(), reader.getLocalName());
+ return Enumerable.create(names).contains(name);
+
+ }
+
+ protected static boolean isEndElement(XMLStreamReader reader, QName qname) {
+ if (!reader.isEndElement()) {
+ return false;
+ }
+ QName name = new QName(reader.getNamespaceURI(), reader.getLocalName());
+ return name.getNamespaceURI().equals(qname.getNamespaceURI())
+ && name.getLocalPart().equals(qname.getLocalPart());
+ }
+
+ protected static String getAttributeValueIfExists(XMLStreamReader reader, String attName) {
+ return reader.getAttributeValue(null, attName);
+ }
+
+}
diff --git a/modules/org.restlet.test/module.xml b/modules/org.restlet.test/module.xml
index c5c4001d89..22078f2f5d 100644
--- a/modules/org.restlet.test/module.xml
+++ b/modules/org.restlet.test/module.xml
@@ -12,6 +12,7 @@
+
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/Cafe.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/Cafe.java
new file mode 100644
index 0000000000..4b746a8097
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/Cafe.java
@@ -0,0 +1,119 @@
+package org.restlet.test.batch.crud;
+
+/**
+ * Generated by the generator tool for the RestletBatch service extension for
+ * the Restlet framework.
+ *
+ * @see Metadata of the
+ * target Restlet Data Services
+ *
+ */
+public class Cafe {
+
+ /** The city. */
+ private String city;
+
+ /** The id. */
+ private String id;
+
+ /** The name. */
+ private String name;
+
+ /** The zip code. */
+ private int zipCode;
+
+ /**
+ * Constructor without parameter.
+ *
+ */
+ public Cafe() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param id
+ * The identifiant value of the entity.
+ */
+ public Cafe(String id) {
+ this();
+ this.id = id;
+ }
+
+ /**
+ * Returns the value of the city attribute.
+ *
+ * @return The value of the city attribute.
+ */
+ public String getCity() {
+ return city;
+ }
+
+ /**
+ * Returns the value of the id attribute.
+ *
+ * @return The value of the id attribute.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the value of the name attribute.
+ *
+ * @return The value of the name attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the zipCode attribute.
+ *
+ * @return The value of the zipCode attribute.
+ */
+ public int getZipCode() {
+ return zipCode;
+ }
+
+ /**
+ * Sets the value of the city attribute.
+ *
+ * @param city
+ * the new city
+ */
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ /**
+ * Sets the value of the id attribute.
+ *
+ * @param id
+ * the new id
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the value of the name attribute.
+ *
+ * @param name
+ * the new name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the zipCode attribute.
+ *
+ * @param zipCode
+ * the new zip code
+ */
+ public void setZipCode(int zipCode) {
+ this.zipCode = zipCode;
+ }
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/CafeCrudApplication.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CafeCrudApplication.java
new file mode 100644
index 0000000000..c882210dac
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CafeCrudApplication.java
@@ -0,0 +1,346 @@
+package org.restlet.test.batch.crud;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.jvnet.mimepull.Header;
+import org.jvnet.mimepull.MIMEMessage;
+import org.jvnet.mimepull.MIMEPart;
+import org.restlet.Application;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.LocalReference;
+import org.restlet.data.MediaType;
+import org.restlet.data.Method;
+import org.restlet.data.Parameter;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.batch.util.BatchConstants;
+import org.restlet.ext.odata.batch.util.BodyPart;
+import org.restlet.ext.odata.batch.util.Multipart;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.routing.Router;
+import org.restlet.util.Series;
+
+/**
+ * Sample application that simulates the CUD operation on entities.
+ */
+
+public class CafeCrudApplication extends Application {
+
+ /**
+ * The Class dataLogger.
+ */
+ private static class BatchTestRestlet extends Restlet {
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER1 = Logger
+ .getLogger(CreateCafeTestCase.class.getName());
+
+ /** The batch id added to response. */
+ private static boolean batchIdAddedToResponse = false;
+
+ /** The builder. */
+ private static StringBuilder builder = new StringBuilder();
+
+ /** The batch id. */
+ private static String batchId = null;
+
+ /** The batch xmlFilePath. */
+ private static final String xmlFilePath = "/org/restlet/test/batch/xml/";
+
+ /** The file. */
+ String fileName;
+
+ /**
+ * Instantiates a new data logger.
+ *
+ * @param context
+ * the context
+ * @param file
+ * the file
+ * @param updatable
+ * the updatable
+ */
+ public BatchTestRestlet(Context context, String xmlFileName,
+ boolean updatable) {
+ super(context);
+ this.fileName = xmlFileName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.Restlet#handle(org.restlet.Request,
+ * org.restlet.Response)
+ */
+ @Override
+ public void handle(Request request, Response response) {
+
+ if (Method.GET.equals(request.getMethod())) {
+ String filePath = xmlFilePath;
+ Response r = getContext().getClientDispatcher().handle(
+ new Request(Method.GET, LocalReference
+ .createClapReference(LocalReference.CLAP_CLASS,
+ filePath + fileName + ".xml")));
+ response.setEntity(r.getEntity());
+ response.setStatus(r.getStatus());
+
+ } else if (Method.POST.equals(request.getMethod())) {
+ String rep = null;
+ try {
+ rep = request.getEntity().getText();
+ String[] split = rep.split("\r\n");
+ for (int i = 0; i < split.length; i++) {
+ createResponse(split[i], builder);
+ }
+ response.setEntity(new StringRepresentation(builder
+ .toString()));
+ setResponse(response, Status.SUCCESS_OK);
+ } catch (IOException e) {
+ response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
+ }
+ if (null != rep && !rep.isEmpty()) {
+ response.setStatus(Status.SUCCESS_OK);
+ }
+
+ }
+ }
+
+ /**
+ * Creates the response as per the method type.
+ *
+ * @param rep
+ * the rep
+ * @param sb
+ * the sb
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private void createResponse(String rep, StringBuilder sb)
+ throws IOException {
+ String filePath = null;
+ if (rep.contains(Method.GET.toString())) {
+ LOGGER1.info("This is Get method");
+ filePath = getFilePath("getCafeResponse.xml");
+ readResponseAndFillBuffer(sb, filePath);
+
+ } else if (rep.contains(Method.DELETE.toString())) {
+ LOGGER1.info("This is delete method");
+ filePath = getFilePath("deleteCafeResponse.xml");
+ readResponseAndFillBuffer(sb, filePath);
+
+ } else if (rep.contains(Method.PUT.toString())) {
+ LOGGER1.info("This is put method");
+ filePath = getFilePath("updateCafeResponse.xml");
+ readResponseAndFillBuffer(sb, filePath);
+
+ } else if (rep.contains(Method.POST.toString())) {
+ LOGGER1.info("This is post method");
+ filePath = getFilePath("createCafeResponse.xml");
+ readResponseAndFillBuffer(sb, filePath);
+ } else if (rep.contains("--changeset")) {
+
+ sb.append("\n\n").append(
+ rep.replace("changeset", "changesetresponse"));
+
+ } else if (rep.contains("--batch")) {
+ if (!batchIdAddedToResponse) {
+ filePath = getFilePath("parentBatchResponse.xml");
+ String replace = rep.replace("batch", "batchresponse");
+ if (replace.contains("batch")) {
+ String[] split = replace.split("_");
+ batchId = split[1];
+ }
+ readResponseAndFillBuffer(sb, filePath);
+ String str = sb.toString();
+ str = str
+ .replace(
+ "batchresponse_1f82a90b-43f1-4276-b20a-59da3437dfa8",
+ "batchresponse_" + batchId);
+ String timeStamp = new SimpleDateFormat(
+ "yyyy:MM:dd_HH:mm:ss").format(Calendar
+ .getInstance().getTime());
+ str = str.replace("Date: Mon, 23 June 2014 09:44:08 GMT",
+ "Date:" + timeStamp);
+ builder = new StringBuilder(str);
+ batchIdAddedToResponse = true;
+ }
+ builder.append("\n\n").append(
+ rep.replace("batch", "batchresponse"));
+
+ } else if (rep
+ .contains("Content-Type: application/atom+xml;charset=utf-8")) {
+
+ sb.append("\n\n")
+ .append(rep
+ .replace(
+ "Content-Type: application/atom+xml;charset=utf-8",
+ ""));
+
+ } else if (rep.contains("Content-Type")) {
+ if (rep.contains("changeset")) {
+ sb.append("\n").append(
+ rep.replace("changeset", "changesetresponse"));
+ } else {
+ sb.append("\n").append(
+ rep.replace("Content-Type", "Content-Type"));
+ }
+ } else if (rep.contains("changeset_")) {
+ sb.append("\n").append(
+ rep.replace("changeset_", "changesetresponse_"));
+ } else if (rep.contains("Content-Transfer-Encoding:")) {
+ sb.append("\n").append(
+ rep.replace("Content-Transfer-Encoding",
+ "Content-Transfer-Encoding"));
+ }
+
+ }
+
+ /**
+ * Gets the complete xml filePath
+ *
+ * @param fileName
+ * the file name
+ * @return the file path
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private String getFilePath(String fileName) throws IOException {
+ return new File(".").getCanonicalPath() + "/src" + xmlFilePath
+ + fileName;
+ }
+
+ /**
+ * Read response and fill buffer.
+ *
+ * @param sb
+ * the sb
+ * @param filePath
+ * the file path
+ * @throws FileNotFoundException
+ * the file not found exception
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private void readResponseAndFillBuffer(StringBuilder sb, String filePath)
+ throws FileNotFoundException, IOException {
+ InputStream is = new FileInputStream(new File(filePath));
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ while (br.ready()) {
+ sb.append(br.readLine()).append("\n");
+
+ }
+ br.close();
+ }
+
+ /**
+ * Sets the response.
+ *
+ * @param response
+ * the response
+ * @param status
+ * the status
+ */
+ private void setResponse(Response response, Status status) {
+ Series parameters = new Series(
+ Parameter.class);
+ parameters.add("boundary", "batchresponse_" + batchId);
+ MediaType mediaType = new MediaType(
+ MediaType.MULTIPART_MIXED.toString(), parameters);
+ response.getEntity().setMediaType(mediaType);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.Application#createInboundRoot()
+ */
+ @Override
+ public Restlet createInboundRoot() {
+ getMetadataService().setDefaultCharacterSet(CharacterSet.ISO_8859_1);
+ getConnectorService().getClientProtocols().add(Protocol.CLAP);
+ Router router = new Router(getContext());
+
+ router.attach("/$metadata", new BatchTestRestlet(getContext(),
+ "metadata", true));
+ router.attach("/Cafes", new BatchTestRestlet(getContext(), "cafes",
+ true));
+ router.attach("/Cafes('40')", new BatchTestRestlet(getContext(),
+ "cafesUpdatedRequest", true));
+ router.attach("/$batch", new BatchTestRestlet(getContext(), "cafes",
+ true));
+
+ return router;
+ }
+
+ /**
+ * Creates the multipart.
+ *
+ * A Multipart is a logical representation of a batch request or Chnagset.
+ * It is a set of multiple http requests/response.
+ *
+ * @param is
+ * the is
+ * @param mediaType
+ * the media type
+ * @return the multipart
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ public static Multipart createMultipart(InputStream is, MediaType mediaType)
+ throws IOException {
+ // create a multipart
+ Multipart multipart = new Multipart();
+ // set its mediatype
+ multipart.setMediaType(mediaType);
+
+ MIMEMessage mimeMessage = new MIMEMessage(is, mediaType.getParameters()
+ .getFirstValue(BatchConstants.BATCH_BOUNDARY));
+ List attachments = mimeMessage.getAttachments();
+ for (MIMEPart mimePart : attachments) {
+ BodyPart bodyPart = new BodyPart(mimePart);
+ // copy headers into bodyparts
+ copyHeaders(bodyPart, mimePart);
+ bodyPart.setMediaType(new MediaType(bodyPart.getHeaders().getFirst(
+ BatchConstants.HTTP_HEADER_CONTENT_TYPE)));
+ multipart.addBodyParts(bodyPart);
+
+ }
+ return multipart;
+ }
+
+ /**
+ * Copy headers.
+ *
+ * @param bodyPart
+ * the body part
+ * @param mimePart
+ * the mime part
+ */
+ private static void copyHeaders(BodyPart bodyPart, MIMEPart mimePart) {
+ MultivaluedMap bpHeaders = bodyPart.getHeaders();
+ List extends Header> mHeaders = mimePart.getAllHeaders();
+ for (Header header : mHeaders) {
+ bpHeaders.add(header.getName(), header.getValue());
+ }
+
+ }
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/CafeService.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CafeService.java
new file mode 100644
index 0000000000..9133e0af10
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CafeService.java
@@ -0,0 +1,98 @@
+package org.restlet.test.batch.crud;
+
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.Service;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.BatchRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.CreateEntityRequest;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Generated by the generator tool for the RestletBatch service extension for
+ * the Restlet framework.
+ *
+ * @see Metadata of the
+ * target RestletBatch service
+ *
+ *
+ */
+public class CafeService extends Service {
+
+ /**
+ * Constructor.
+ *
+ */
+ public CafeService() {
+ super("http://localhost:8111/Cafe.svc/");
+ }
+
+ /**
+ * Adds a new entity to the service.
+ *
+ * @param entity
+ * The entity to add to the service.
+ * @return the creates the entity request
+ * @throws Exception
+ * the exception
+ */
+ public CreateEntityRequest addEntity(Cafe entity) throws Exception {
+ return addEntity("/Cafes", entity);
+ }
+
+ /**
+ * Creates a query for cafe entities hosted by this service.
+ *
+ * @param subpath
+ * The path to this entity relatively to the service URI.
+ * @return A query object.
+ */
+ public Query createCafeQuery(String subpath) {
+ return createQuery(subpath, Cafe.class);
+ }
+
+ /**
+ * Updates a query for cafe entities hosted by this service.
+ *
+ * @param subpath
+ * The path to this entity relatively to the service URI.
+ * @return A query object.
+ */
+
+ public Query updateCafeQuery(String subpath) {
+ return createQuery(subpath, Cafe.class);
+ }
+
+ /**
+ * Deletes a query for cafe entities hosted by this service.
+ *
+ * @param subpath
+ * The path to this entity relatively to the service URI.
+ * @return A query object.
+ */
+
+ public Query deleteCafeQuery(String subpath) {
+ return createQuery(subpath, Cafe.class);
+ }
+
+ /**
+ * Gets a query for cafe entities hosted by this service.
+ *
+ * @param subpath
+ * The path to this entity relatively to the service URI.
+ * @return A query object.
+ */
+
+ public Query getCafeQuery(String subpath) {
+ return createQuery(subpath, Cafe.class);
+ }
+
+ /**
+ * Method to perform batch operations. It maintains the list of
+ * clientBatchRequests within a batch.
+ *
+ * @return list of request in batch.
+ */
+ public BatchRequest createBatchRequest() {
+ return new BatchRequestImpl(this);
+ }
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateCafeTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateCafeTestCase.java
new file mode 100644
index 0000000000..a5f342f0ed
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateCafeTestCase.java
@@ -0,0 +1,154 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.CreateEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Test case for RestletBatch service for CREATE operation on entities.
+ *
+ */
+public class CreateCafeTestCase extends RestletTestCase {
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger
+ .getLogger(CreateCafeTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for CREATE operation on simple entities.
+ */
+ public void testCreate() {
+ CafeService service = new CafeService();
+
+ // create.
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+ try {
+
+ BatchRequest br = service.createBatchRequest();
+ ChangeSetRequestImpl changeSetRequest = new ChangeSetRequestImpl();
+ // Create request
+ CreateEntityRequest createEntityRequest = new CreateEntityRequest(
+ service, cafe);
+ changeSetRequest.addRequest(createEntityRequest);
+ List responses = br.addRequest(changeSetRequest)
+ .execute();
+ dumpResponse(responses);
+ // Assert for response.
+ Query createquery = service.createCafeQuery("/Cafes");
+ Cafe cafe1 = createquery.iterator().next();
+ assertEquals(cafeName, cafe1.getName());
+ assertEquals(cafeId, cafe1.getId());
+ assertEquals(cafeZipCode, cafe1.getZipCode());
+ Response latestResponse = createquery.getService()
+ .getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses
+ * the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if (batchResponse instanceof ChangeSetResponse) {
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List) entity);
+ LOGGER.info("Done with changeset");
+ } else {
+ LOGGER.info("Status =" + batchResponse.getStatus());
+ LOGGER.info("Entity = " + entity);
+ MultivaluedMap headers = batchResponse
+ .getHeaders();
+ if (headers != null) {
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key =" + key + "/t" + "value = " + value);
+ }
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateDeleteChangeSetTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateDeleteChangeSetTestCase.java
new file mode 100644
index 0000000000..e16e2e44a6
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateDeleteChangeSetTestCase.java
@@ -0,0 +1,166 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.CreateEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.DeleteEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Test case for RestletBatch service for CREATE & DELETE operation on entities.
+ *
+ */
+public class CreateDeleteChangeSetTestCase extends RestletTestCase {
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger
+ .getLogger(CreateDeleteChangeSetTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for CREATE & DELETE operation on simple entities.
+ */
+ public void testCreateDelete() {
+ CafeService service = new CafeService();
+
+ // create & delete
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+
+ try {
+
+ BatchRequest br = service.createBatchRequest();
+ ChangeSetRequestImpl changeSetRequest = new ChangeSetRequestImpl();
+ // Create request
+ CreateEntityRequest createEntityRequest = new CreateEntityRequest(
+ service, cafe);
+ DeleteEntityRequest deleteEntityRequest = new DeleteEntityRequest(
+ service, cafe);
+ changeSetRequest.addRequest(createEntityRequest);
+ changeSetRequest.addRequest(deleteEntityRequest);
+ List responses = br.addRequest(changeSetRequest)
+ .execute();
+ for (BatchResponse batchResponse : responses) {
+ batchResponse.getEntity();
+ dumpResponse(responses);
+ }
+
+ // Assert for response.
+ Query createquery = service.createCafeQuery("/Cafes");
+ Cafe cafe1 = createquery.iterator().next();
+ assertEquals(cafeName, cafe1.getName());
+ assertEquals(cafeId, cafe1.getId());
+ assertEquals(cafeZipCode, cafe1.getZipCode());
+ Response latestResponse = createquery.getService()
+ .getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ Query deletequery = service.deleteCafeQuery(("/Cafes('40')"));
+ latestResponse = deletequery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses
+ * the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if (batchResponse instanceof ChangeSetResponse) {
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List) entity);
+ LOGGER.info("Done with changeset");
+ } else {
+ LOGGER.info("Status =" + batchResponse.getStatus());
+ LOGGER.info("Entity = " + entity);
+ MultivaluedMap headers = batchResponse
+ .getHeaders();
+ if (headers != null) {
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key =" + key + "/t" + "value = " + value);
+ }
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateUpdateChangeSetTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateUpdateChangeSetTestCase.java
new file mode 100644
index 0000000000..5b47eaa34c
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/CreateUpdateChangeSetTestCase.java
@@ -0,0 +1,172 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.CreateEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.UpdateEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Test case for RestletBatch service for CREATE & UPDATE operation on entities.
+ *
+ */
+public class CreateUpdateChangeSetTestCase extends RestletTestCase {
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger
+ .getLogger(CreateUpdateChangeSetTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** The Constant cafeNameUpdated. */
+ private static final String cafeNameUpdated = "TestName-updated";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for CREATE & UPDATE operation on simple entities.
+ */
+ public void testCreateUpdate() {
+ CafeService service = new CafeService();
+
+ // create.
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+
+ // update
+ Cafe cafeU = new Cafe();
+ cafe.setName(cafeNameUpdated);
+ try {
+
+ BatchRequest br = service.createBatchRequest();
+ ChangeSetRequestImpl changeSetRequest = new ChangeSetRequestImpl();
+ // Create request
+ CreateEntityRequest createEntityRequest = new CreateEntityRequest(
+ service, cafe);
+ UpdateEntityRequest updateEntityRequest = new UpdateEntityRequest(
+ service, cafeU);
+ changeSetRequest.addRequest(createEntityRequest);
+ changeSetRequest.addRequest(updateEntityRequest);
+ List responses = br.addRequest(changeSetRequest)
+ .execute();
+ for (BatchResponse batchResponse : responses) {
+ batchResponse.getEntity();
+ dumpResponse(responses);
+ }
+
+ // Assert for response.
+ Query createquery = service.createCafeQuery("/Cafes");
+ Cafe cafe1 = createquery.iterator().next();
+ assertEquals(cafeName, cafe1.getName());
+ assertEquals(cafeId, cafe1.getId());
+ assertEquals(cafeZipCode, cafe1.getZipCode());
+ Response latestResponse = createquery.getService()
+ .getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ Query updatequery = service.updateCafeQuery("/Cafes('40')");
+ latestResponse = updatequery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses
+ * the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if (batchResponse instanceof ChangeSetResponse) {
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List) entity);
+ LOGGER.info("Done with changeset");
+ } else {
+ LOGGER.info("Status =" + batchResponse.getStatus());
+ LOGGER.info("Entity = " + entity);
+ MultivaluedMap headers = batchResponse
+ .getHeaders();
+ if (headers != null) {
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key =" + key + "/t" + "value = " + value);
+ }
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/DeleteCafeTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/DeleteCafeTestCase.java
new file mode 100644
index 0000000000..1418192eb3
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/DeleteCafeTestCase.java
@@ -0,0 +1,152 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.DeleteEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Test case for RestletBatch service for DELETE operation on entities.
+ */
+public class DeleteCafeTestCase extends RestletTestCase {
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger
+ .getLogger(DeleteCafeTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for DELETE operation on simple entities.
+ */
+ public void testDelete() {
+ CafeService service = new CafeService();
+
+ // create.
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+
+ // delete
+ Cafe cafeD = new Cafe();
+ cafeD.setId(cafeId);
+ cafeD.setName(cafeName);
+ cafeD.setCity("TestCity");
+ cafeD.setZipCode(cafeZipCode);
+ try {
+ BatchRequest br = service.createBatchRequest();
+ ChangeSetRequestImpl changeSetRequest = new ChangeSetRequestImpl();
+ // Create request
+ DeleteEntityRequest deleteEntityRequest = new DeleteEntityRequest(
+ service, cafe);
+ changeSetRequest.addRequest(deleteEntityRequest);
+ List responses = br.addRequest(changeSetRequest)
+ .execute();
+ dumpResponse(responses);
+ Query deleteQuery = service.deleteCafeQuery("/Cafes('40')");
+ Response latestResponse = deleteQuery.getService()
+ .getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses
+ * the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if (batchResponse instanceof ChangeSetResponse) {
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List) entity);
+ LOGGER.info("Done with changeset");
+ } else {
+ LOGGER.info("Status =" + batchResponse.getStatus());
+ LOGGER.info("Entity = " + entity);
+ MultivaluedMap headers = batchResponse
+ .getHeaders();
+ if (headers != null) {
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key =" + key + "/t" + "value = " + value);
+ }
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/GetCafeTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/GetCafeTestCase.java
new file mode 100644
index 0000000000..3c635715f9
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/GetCafeTestCase.java
@@ -0,0 +1,149 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.GetEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Test case for RestletBatch service for GET operation on entities.
+ */
+public class GetCafeTestCase extends RestletTestCase {
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger.getLogger(GetCafeTestCase.class
+ .getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for GET operation on simple entities.
+ */
+ public void testGet() {
+
+ // Get
+ CafeService service = new CafeService();
+ Cafe cafeG = new Cafe();
+ cafeG.setId(cafeId);
+ cafeG.setName(cafeName);
+ cafeG.setCity(cafeCity);
+ cafeG.setZipCode(cafeZipCode);
+ try {
+ BatchRequest br = service.createBatchRequest();
+ // get request
+ Query getQuery = service.createQuery("/Cafes('40')",
+ Cafe.class);
+ GetEntityRequest getEntityRequest = new GetEntityRequest(getQuery);
+ List responses = br.addRequest(getEntityRequest)
+ .execute();
+ dumpResponse(responses);
+ Assert.assertTrue(true);
+ // Assert for response.
+ Query getquery = service.getCafeQuery("/Cafes");
+ Cafe cafe2 = getquery.iterator().next();
+ assertEquals(cafeName, cafe2.getName());
+ assertEquals(cafeId, cafe2.getId());
+ assertEquals(cafeZipCode, cafe2.getZipCode());
+ Response latestResponse = getQuery.getService().getLatestResponse();
+ latestResponse = getquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses
+ * the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if (batchResponse instanceof ChangeSetResponse) {
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List) entity);
+ LOGGER.info("Done with changeset");
+ } else {
+ LOGGER.info("Status =" + batchResponse.getStatus());
+ LOGGER.info("Entity = " + entity);
+ MultivaluedMap headers = batchResponse
+ .getHeaders();
+ if (headers != null) {
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key =" + key + "/t" + "value = " + value);
+ }
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/MultipleChangeSetTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/MultipleChangeSetTestCase.java
new file mode 100644
index 0000000000..761927ae55
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/MultipleChangeSetTestCase.java
@@ -0,0 +1,190 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.CreateEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.DeleteEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.UpdateEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * The Class MultipleChangeSetTestCase.
+ *
+ * Batch
+ * ---changeset1 :Create
+ * ---changeset2 :Update
+ * ---changeset3 :Delete
+ * Batch ends
+ */
+
+public class MultipleChangeSetTestCase extends RestletTestCase {
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger
+ .getLogger(MultipleChangeSetTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** The Constant cafeNameUpdated. */
+ private static final String cafeNameUpdated = "TestName-updated";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test multiple change set.
+ */
+ public void testMultipleChangeSet() {
+ CafeService service = new CafeService();
+
+ // create & delete
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+
+ // create & update
+ Cafe cafeU = new Cafe();
+ cafe.setName(cafeNameUpdated);
+
+ try {
+
+ BatchRequest br = service.createBatchRequest();
+ ChangeSetRequestImpl changeSetRequest1 = new ChangeSetRequestImpl();
+ CreateEntityRequest createEntityRequest = new CreateEntityRequest(
+ service, cafe);
+ changeSetRequest1.addRequest(createEntityRequest);
+ ChangeSetRequestImpl changeSetRequest2 = new ChangeSetRequestImpl();
+ UpdateEntityRequest updateEntityRequest = new UpdateEntityRequest(
+ service, cafeU);
+ changeSetRequest2.addRequest(updateEntityRequest);
+ ChangeSetRequestImpl changeSetRequest3 = new ChangeSetRequestImpl();
+ DeleteEntityRequest deleteEntityRequest = new DeleteEntityRequest(
+ service, cafe);
+ changeSetRequest3.addRequest(deleteEntityRequest);
+ List responses = br.addRequest(changeSetRequest1)
+ .addRequest(changeSetRequest2)
+ .addRequest(changeSetRequest3).execute();
+ dumpResponse(responses);
+
+ // Assert for response-create & delete
+ Query createquery = service.createCafeQuery("/Cafes");
+ Cafe cafe1 = createquery.iterator().next();
+ assertEquals(cafeName, cafe1.getName());
+ assertEquals(cafeId, cafe1.getId());
+ assertEquals(cafeZipCode, cafe1.getZipCode());
+ Response latestResponse = createquery.getService()
+ .getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ Query deletequery = service.deleteCafeQuery(("/Cafes('40')"));
+ latestResponse = deletequery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+
+ // Assert for response-create & update
+ Query createquery2 = service.createCafeQuery("/Cafes");
+ Cafe cafe2 = createquery2.iterator().next();
+ assertEquals(cafeName, cafe2.getName());
+ assertEquals(cafeId, cafe2.getId());
+ assertEquals(cafeZipCode, cafe2.getZipCode());
+ latestResponse = createquery.getService().getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ Query updatequery = service.updateCafeQuery("/Cafes('40')");
+ latestResponse = updatequery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses
+ * the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if (batchResponse instanceof ChangeSetResponse) {
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List) entity);
+ LOGGER.info("Done with changeset");
+ } else {
+ LOGGER.info("Status =" + batchResponse.getStatus());
+ LOGGER.info("Entity = " + entity);
+ MultivaluedMap headers = batchResponse
+ .getHeaders();
+ if (headers != null) {
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key =" + key + "/t" + "value = " + value);
+ }
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/MultipleChangeSetWithGetTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/MultipleChangeSetWithGetTestCase.java
new file mode 100644
index 0000000000..144f0a5c05
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/MultipleChangeSetWithGetTestCase.java
@@ -0,0 +1,186 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.CreateEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.DeleteEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.GetEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.UpdateEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * The Class MultipleChangeSetWithGetTestCase.
+ * Batch---
+ * ---Get entity
+ * ---changeset1 :Create
+ * ---changeset2 :Update
+ * ---changeset3 :Delete
+ * Batch ends
+ *
+ */
+public class MultipleChangeSetWithGetTestCase extends RestletTestCase {
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger.getLogger(MultipleChangeSetTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** The Constant cafeNameUpdated. */
+ private static final String cafeNameUpdated = "TestName-updated";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /* (non-Javadoc)
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test multiple operations with get.
+ */
+ public void testMultipleOperationsWithGet() {
+ CafeService service = new CafeService();
+
+ // create & delete
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+
+ //create & update
+ Cafe cafeU = new Cafe();
+ cafe.setName(cafeNameUpdated);
+
+ try {
+
+ BatchRequest br = service.createBatchRequest();
+ Query getQuery = service.createQuery("/Cafes('40')",Cafe.class);
+ GetEntityRequest getEntityRequest = new GetEntityRequest(getQuery);
+ ChangeSetRequestImpl changeSetRequest1 = new ChangeSetRequestImpl();
+ CreateEntityRequest createEntityRequest = new CreateEntityRequest(service,cafe);
+ changeSetRequest1.addRequest(createEntityRequest);
+ ChangeSetRequestImpl changeSetRequest2 = new ChangeSetRequestImpl();
+ UpdateEntityRequest updateEntityRequest = new UpdateEntityRequest(service, cafeU);
+ changeSetRequest2.addRequest(updateEntityRequest);
+ ChangeSetRequestImpl changeSetRequest3 = new ChangeSetRequestImpl();
+ DeleteEntityRequest deleteEntityRequest = new DeleteEntityRequest(service, cafe);
+ changeSetRequest3.addRequest(deleteEntityRequest);
+ List responses = br.addRequest(getEntityRequest).addRequest(changeSetRequest1).addRequest(changeSetRequest2).addRequest(changeSetRequest3).execute();
+ dumpResponse(responses);
+
+
+ //Assert for response-create & delete
+ Query createquery = service.createCafeQuery("/Cafes");
+ Cafe cafe1=createquery.iterator().next();
+ assertEquals(cafeName, cafe1.getName());
+ assertEquals(cafeId, cafe1.getId());
+ assertEquals(cafeZipCode, cafe1.getZipCode());
+ Response latestResponse = createquery.getService().getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ Query deletequery = service.deleteCafeQuery(("/Cafes('40')"));
+ latestResponse = deletequery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK,latestResponse.getStatus());
+
+ //Assert for response-create & update
+ Query createquery2 = service.createCafeQuery("/Cafes");
+ Cafe cafe2=createquery2.iterator().next();
+ assertEquals(cafeName, cafe2.getName());
+ assertEquals(cafeId, cafe2.getId());
+ assertEquals(cafeZipCode, cafe2.getZipCode());
+ latestResponse = createquery.getService().getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ Query updatequery = service.updateCafeQuery("/Cafes('40')");
+ latestResponse = updatequery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK,latestResponse.getStatus());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if(batchResponse instanceof ChangeSetResponse){
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List)entity);
+ LOGGER.info("Done with changeset");
+ }else{
+ LOGGER.info("Status ="+ batchResponse.getStatus());
+ LOGGER.info("Entity = "+ entity);
+ MultivaluedMap headers = batchResponse.getHeaders();
+ if(headers!=null){
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key ="+ key + "/t"+"value = "+ value);
+ }
+ }
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/UpdateCafeTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/UpdateCafeTestCase.java
new file mode 100644
index 0000000000..9be293814e
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/UpdateCafeTestCase.java
@@ -0,0 +1,149 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.UpdateEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Test case for RestletBatch service for UPDATE operation on entities.
+ *
+ */
+public class UpdateCafeTestCase extends RestletTestCase {
+
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeNameUpdated. */
+ private static final String cafeNameUpdated = "TestName-updated";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger.getLogger(UpdateCafeTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /* (non-Javadoc)
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /* (non-Javadoc)
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for UPDATE operation on simple entities.
+ */
+ public void testUpdate() {
+ CafeService service = new CafeService();
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+
+
+ //update
+ Cafe cafeU = new Cafe();
+ cafeU.setId(cafeId);
+ cafeU.setName(cafeName);
+ cafeU.setCity(cafeCity);
+ cafeU.setZipCode(cafeZipCode);
+ cafeU.setName(cafeNameUpdated);
+ try {
+ BatchRequest br = service.createBatchRequest();
+ ChangeSetRequestImpl changeSetRequest = new ChangeSetRequestImpl();
+ UpdateEntityRequest updateEntityRequest = new UpdateEntityRequest(service,cafe);
+ changeSetRequest.addRequest(updateEntityRequest);
+ List responses = br.addRequest(changeSetRequest).execute();
+ dumpResponse(responses);
+
+ Query updatequery = service.updateCafeQuery("/Cafes('40')");
+ Response latestResponse = updatequery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if(batchResponse instanceof ChangeSetResponse){
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List)entity);
+ LOGGER.info("Done with changeset");
+ }else{
+ LOGGER.info("Status ="+ batchResponse.getStatus());
+ LOGGER.info("Entity = "+ entity);
+ MultivaluedMap headers = batchResponse.getHeaders();
+ if(headers!=null){
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key ="+ key + "/t"+"value = "+ value);
+ }
+ }
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/crud/UpdateDeleteChangeSetTestCase.java b/modules/org.restlet.test/src/org/restlet/test/batch/crud/UpdateDeleteChangeSetTestCase.java
new file mode 100644
index 0000000000..b8a98e479e
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/crud/UpdateDeleteChangeSetTestCase.java
@@ -0,0 +1,160 @@
+package org.restlet.test.batch.crud;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.batch.request.BatchRequest;
+import org.restlet.ext.odata.batch.request.impl.ChangeSetRequestImpl;
+import org.restlet.ext.odata.batch.request.impl.DeleteEntityRequest;
+import org.restlet.ext.odata.batch.request.impl.UpdateEntityRequest;
+import org.restlet.ext.odata.batch.response.BatchResponse;
+import org.restlet.ext.odata.batch.response.ChangeSetResponse;
+import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.crud.Cafe;
+
+/**
+ * Test case for RestletBatch service for UPDATE & DELETE operation on entities.
+ *
+ */
+public class UpdateDeleteChangeSetTestCase extends RestletTestCase {
+
+
+ /** The Constant cafeName. */
+ private static final String cafeName = "TestName";
+
+ /** The Constant cafeId. */
+ private static final String cafeId = "40";
+
+ /** The Constant cafeZipCode. */
+ private static final int cafeZipCode = 111111;
+
+ /** The Constant LOGGER. */
+ private static final Logger LOGGER = Logger.getLogger(UpdateDeleteChangeSetTestCase.class.getName());
+
+ /** The Constant cafeCity. */
+ private static final String cafeCity = "TestCity";
+
+ /** The Constant cafeNameUpdated. */
+ private static final String cafeNameUpdated = "TestName-updated";
+
+ /** Inner component. */
+ private Component component = new Component();
+
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ /* (non-Javadoc)
+ * @see org.restlet.test.RestletTestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ /* (non-Javadoc)
+ * @see org.restlet.test.RestletTestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for UPDATE & DELETE operation on simple entities.
+ */
+ public void testUpdateDelete() {
+ CafeService service = new CafeService();
+
+ // Update & Delete
+ Cafe cafe = new Cafe();
+ cafe.setId(cafeId);
+ cafe.setName(cafeName);
+ cafe.setCity(cafeCity);
+ cafe.setZipCode(cafeZipCode);
+
+
+ //update
+ Cafe cafeU = new Cafe();
+ cafe.setName(cafeNameUpdated);
+ try {
+
+ BatchRequest br = service.createBatchRequest();
+ ChangeSetRequestImpl changeSetRequest = new ChangeSetRequestImpl();
+ UpdateEntityRequest updateEntityRequest = new UpdateEntityRequest(service, cafeU);
+ DeleteEntityRequest deleteEntityRequest = new DeleteEntityRequest(service, cafe);
+ changeSetRequest.addRequest(updateEntityRequest);
+ changeSetRequest.addRequest(deleteEntityRequest);
+ List responses = br.addRequest(changeSetRequest).execute();
+ for (BatchResponse batchResponse : responses) {
+ batchResponse.getEntity();
+ dumpResponse(responses);
+ }
+
+ //Assert for response.
+ Query createquery = service.createCafeQuery("/Cafes('40')");
+ Response latestResponse = createquery.getService().getLatestResponse();
+ latestResponse = createquery.getService().getLatestResponse();
+ assertTrue(latestResponse.getStatus().isSuccess());
+ Query updatequery = service.updateCafeQuery("/Cafes('40')");
+ latestResponse = updatequery.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK,latestResponse.getStatus());
+ } catch (Exception ex) {
+ LOGGER.log(Level.SEVERE, ex.getMessage());
+ Assert.fail();
+ }
+ }
+
+ /**
+ * Dump response.
+ *
+ * @param responses the responses
+ */
+ @SuppressWarnings("unchecked")
+ public static void dumpResponse(List responses) {
+ for (BatchResponse batchResponse : responses) {
+ Object entity = batchResponse.getEntity();
+ if(batchResponse instanceof ChangeSetResponse){
+ LOGGER.info("Dumping changeset");
+ dumpResponse((List)entity);
+ LOGGER.info("Done with changeset");
+ }else{
+ LOGGER.info("Status ="+ batchResponse.getStatus());
+ LOGGER.info("Entity = "+ entity);
+ MultivaluedMap headers = batchResponse.getHeaders();
+ if(headers!=null){
+ Set keySet = headers.keySet();
+ LOGGER.info("Headers : ");
+ for (String key : keySet) {
+ List value = headers.get(key);
+ LOGGER.info("Key ="+ key + "/t"+"value = "+ value);
+ }
+ }
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/cafes.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/cafes.xml
new file mode 100644
index 0000000000..b7e7f07c33
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/cafes.xml
@@ -0,0 +1,29 @@
+
+
+ Cafes
+ http://localhost:8111/Cafe.svc/Cafes
+ 2010-02-17T11:28:13Z
+
+
+ http://localhost:8111/Cafe.svc/Cafes('40')
+
+ 2010-02-17T11:28:13Z
+
+
+
+
+
+
+
+ 40
+ TestName
+ 111111
+ TestCity
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/cafesUpdatedRequest.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/cafesUpdatedRequest.xml
new file mode 100644
index 0000000000..009ccffbbb
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/cafesUpdatedRequest.xml
@@ -0,0 +1,29 @@
+
+
+ Cafes
+ http://localhost:8111/Cafe.svc/Cafes
+ 2010-02-17T11:28:13Z
+
+
+ http://localhost:8111/Cafe.svc/Cafes('40')
+
+ 2010-02-17T11:28:13Z
+
+
+
+
+
+
+
+ 40
+ TestName-updated
+ 111111
+ TestCity
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/createCafeResponse.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/createCafeResponse.xml
new file mode 100644
index 0000000000..fb68d6f0ed
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/createCafeResponse.xml
@@ -0,0 +1,24 @@
+
+
+HTTP/1.1 201 Created
+Content-Type: application/atom+xml;charset=utf-8
+Location: http://localhost:8111/Cafe.svc/Cafes('40')
+DataServiceVersion: 3.0
+
+
+http://localhost:8111/Cafe.svc/Cafes('40')
+2014-05-27T09:17:16Z
+
+
+40
+UNKNOWN
+2014-06-23T09:44:08
+
+OWAT
+TestCity
+40
+TestName
+111111
+221
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/deleteCafeResponse.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/deleteCafeResponse.xml
new file mode 100644
index 0000000000..507d35844b
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/deleteCafeResponse.xml
@@ -0,0 +1,24 @@
+
+
+HTTP/1.1 200 OK
+Content-Type: application/atom+xml;charset=utf-8
+Location: http://localhost:8111/Cafe.svc/Cafes('40')
+DataServiceVersion: 3.0
+
+
+http://localhost:8111/Cafe.svc/Cafes('40')
+2014-05-27T09:17:16Z
+
+
+40
+UNKNOWN
+2014-06-23T09:44:08
+
+OWAT
+TestCity
+40
+TestName
+111111
+221
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/getCafeResponse.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/getCafeResponse.xml
new file mode 100644
index 0000000000..90d32c3d40
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/getCafeResponse.xml
@@ -0,0 +1,24 @@
+
+
+HTTP/1.1 200 OK
+Content-Type: application/xml;charset=utf-8
+Location: http://localhost:8111/Cafe.svc/Cafes('40')
+DataServiceVersion: 3.0
+
+
+http://localhost:8111/Cafe.svc/Cafes('40')
+2014-05-27T09:17:16Z
+
+
+40
+UNKNOWN
+2014-06-23T09:44:08
+
+OWAT
+TestCity
+40
+TestName
+111111
+221
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/metadata.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/metadata.xml
new file mode 100644
index 0000000000..4726582e39
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/metadata.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/parentBatchResponse.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/parentBatchResponse.xml
new file mode 100644
index 0000000000..a5ab7e7473
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/parentBatchResponse.xml
@@ -0,0 +1,9 @@
+HTTP/1.1 202 Accepted
+Server: Apache-Coyote/1.1
+DataServiceVersion: 3.0
+Content-Type: multipart/mixed;boundary=batchresponse_1f82a90b-43f1-4276-b20a-59da3437dfa8
+Transfer-Encoding: chunked
+Date: Mon, 23 June 2014 09:44:08 GMT
+Proxy-Connection: Keep-Alive
+Connection: Keep-Alive
+
diff --git a/modules/org.restlet.test/src/org/restlet/test/batch/xml/updateCafeResponse.xml b/modules/org.restlet.test/src/org/restlet/test/batch/xml/updateCafeResponse.xml
new file mode 100644
index 0000000000..c6d23e6f34
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/batch/xml/updateCafeResponse.xml
@@ -0,0 +1,27 @@
+
+
+HTTP/1.1 200 OK
+Content-Type: application/atom+xml;charset=utf-8
+Location: http://localhost:8111/Cafe.svc/Cafes('40')
+DataServiceVersion: 3.0
+
+
+http://localhost:8111/Cafe.svc/Cafes('40')
+2014-05-27T09:17:16Z
+
+
+
+40
+UNKNOWN
+2014-06-23T09:44:08
+
+TestName-updated
+OWAT
+TestCity
+40
+TestName
+111111
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeCustoFeedsTestCase.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeCustoFeedsTestCase.java
index 4c40a9a6dd..861aece9a2 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeCustoFeedsTestCase.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeCustoFeedsTestCase.java
@@ -34,11 +34,14 @@
package org.restlet.test.ext.odata;
import java.util.Iterator;
+import java.util.List;
import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.ext.odata.Query;
import org.restlet.test.RestletTestCase;
+import org.restlet.test.ext.odata.cafe.Point;
+import org.restlet.test.ext.odata.cafe.StructAny;
import org.restlet.test.ext.odata.cafecustofeeds.Cafe;
import org.restlet.test.ext.odata.cafecustofeeds.CafeCustoFeedsService;
import org.restlet.test.ext.odata.cafecustofeeds.Contact;
@@ -96,6 +99,9 @@ public void testQueryCafes() {
assertEquals("Levallois-Perret", cafe.getCity());
assertEquals(92300, cafe.getZipCode());
+ assertNotNull(cafe.getSpatial());
+ assertComplextTypeParsing(cafe.getSpatial());
+
assertTrue(iterator.hasNext());
cafe = iterator.next();
assertEquals("2", cafe.getId());
@@ -104,6 +110,55 @@ public void testQueryCafes() {
assertEquals("Marly Le Roi", cafe.getCity());
assertEquals(78310, cafe.getZipCode());
}
+
+ /**
+ * This checks that if an entity has a property of complex type.
+ * Also it checks for the collection properties of primitives as well as complex type.
+ *
+ * @param point
+ * complex entity to test.
+ */
+ private void assertComplextTypeParsing(Point point) {
+
+ assertEquals("LINESTRING", point.getGeo_type());
+ assertEquals("GEONAME", point.getGeo_name());
+
+ assertNotNull(point.getX());
+ assertTrue(point.getX().size()>0);
+
+ List listX = point.getX();
+
+ for (Iterator iterator = listX.iterator(); iterator.hasNext();) {
+ Double element = (Double) iterator.next();
+ assertTrue(element instanceof Double);
+ assertNotNull(element);
+ }
+
+ assertNotNull(point.getY());
+ assertTrue(point.getY().size()>0);
+
+ List listY = point.getY();
+
+ for (Iterator iterator = listY.iterator(); iterator.hasNext();) {
+ Double element = (Double) iterator.next();
+ assertTrue(element instanceof Double);
+ assertNotNull(element);
+ }
+
+ assertNotNull(point.getProperties());
+ assertTrue(point.getProperties().size()>0);
+
+ List listComplexObject = point.getProperties();
+
+ for (Iterator iterator = listComplexObject.iterator(); iterator.hasNext();) {
+ StructAny structAny = (StructAny) iterator.next();
+ assertEquals("md", structAny.getName());
+ assertEquals("FLOAT", structAny.getType());
+ assertEquals("meters", structAny.getUnit());
+ assertEquals("depth measure", structAny.getUnitType());
+ assertEquals("[0.0,2670.9678]", structAny.getValues());
+ }
+ }
/**
* Tests the parsing of Feed element with expansion of the one to one
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeTestCase.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeTestCase.java
index 43af095205..535fc5eeb0 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeTestCase.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataCafeTestCase.java
@@ -34,7 +34,9 @@
package org.restlet.test.ext.odata;
import java.util.Iterator;
+import java.util.List;
+import org.hamcrest.core.IsInstanceOf;
import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.ext.odata.Query;
@@ -43,6 +45,10 @@
import org.restlet.test.ext.odata.cafe.CafeService;
import org.restlet.test.ext.odata.cafe.Contact;
import org.restlet.test.ext.odata.cafe.Item;
+import org.restlet.test.ext.odata.cafe.Point;
+import org.restlet.test.ext.odata.cafe.StructAny;
+
+import sun.security.jca.GetInstance.Instance;
/**
* Test case for OData service.
@@ -92,6 +98,10 @@ public void testQueryCafes() {
assertEquals("Cafe corp.", cafe.getCompanyName());
assertEquals("Levallois-Perret", cafe.getCity());
assertEquals(92300, cafe.getZipCode());
+
+ //test complex type and collection type (Including collection of simple type as well as complex type).
+ assertNotNull(cafe.getSpatial());
+ assertComplextTypeParsing(cafe.getSpatial());
assertTrue(iterator.hasNext());
cafe = iterator.next();
@@ -103,6 +113,55 @@ public void testQueryCafes() {
}
/**
+ * This checks that if an entity has a property of complex type.
+ * Also it checks for the collection properties of primitives as well as complex type.
+ *
+ * @param point
+ * complex entity to test.
+ */
+ private void assertComplextTypeParsing(Point point) {
+
+ assertEquals("LINESTRING", point.getGeo_type());
+ assertEquals("GEONAME", point.getGeo_name());
+
+ assertNotNull(point.getX());
+ assertTrue(point.getX().size()>0);
+
+ List listX = point.getX();
+
+ for (Iterator iterator = listX.iterator(); iterator.hasNext();) {
+ Double element = (Double) iterator.next();
+ assertTrue(element instanceof Double);
+ assertNotNull(element);
+ }
+
+ assertNotNull(point.getY());
+ assertTrue(point.getY().size()>0);
+
+ List listY = point.getY();
+
+ for (Iterator iterator = listY.iterator(); iterator.hasNext();) {
+ Double element = (Double) iterator.next();
+ assertTrue(element instanceof Double);
+ assertNotNull(element);
+ }
+
+ assertNotNull(point.getProperties());
+ assertTrue(point.getProperties().size()>0);
+
+ List listComplexObject = point.getProperties();
+
+ for (Iterator iterator = listComplexObject.iterator(); iterator.hasNext();) {
+ StructAny structAny = (StructAny) iterator.next();
+ assertEquals("md", structAny.getName());
+ assertEquals("FLOAT", structAny.getType());
+ assertEquals("meters", structAny.getUnit());
+ assertEquals("depth measure", structAny.getUnitType());
+ assertEquals("[0.0,2670.9678]", structAny.getValues());
+ }
+ }
+
+ /**
* Tests the parsing of Feed element with expansion of the one to one
* association "Contact".
*/
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataTestSuite.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataTestSuite.java
index 6238f86d51..31523ca268 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataTestSuite.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/ODataTestSuite.java
@@ -33,7 +33,11 @@
package org.restlet.test.ext.odata;
+import org.restlet.test.ext.odata.complexcrud.ODataCafeCrudTestCase;
import org.restlet.test.ext.odata.deepexpand.ODataDeepExpandTestCase;
+import org.restlet.test.ext.odata.function.ActionTestCase;
+import org.restlet.test.ext.odata.function.FunctionTestCase;
+import org.restlet.test.ext.odata.streamcrud.ODataCafeCrudStreamTestCase;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -56,6 +60,11 @@ public static Test suite() {
result.addTestSuite(ODataCafeTestCase.class);
result.addTestSuite(ODataCafeCustoFeedsTestCase.class);
result.addTestSuite(ODataDeepExpandTestCase.class);
+ result.addTestSuite(ODataCafeCrudTestCase.class);
+ result.addTestSuite(org.restlet.test.ext.odata.crud.ODataCafeCrudTestCase.class);
+ result.addTestSuite(ODataCafeCrudStreamTestCase.class);
+ result.addTestSuite(ActionTestCase.class);
+ result.addTestSuite(FunctionTestCase.class);
return result;
}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/Cafe.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/Cafe.java
index 0d349080d5..45a50dd33a 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/Cafe.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/Cafe.java
@@ -33,35 +33,28 @@
package org.restlet.test.ext.odata.cafe;
+
+import java.util.ArrayList;
import java.util.List;
import org.restlet.test.ext.odata.cafe.Contact;
import org.restlet.test.ext.odata.cafe.Item;
/**
- * Generated by the generator tool for the WCF Data Services extension for the
- * Restlet framework.
- *
- * @see Metadata of the
- * target WCF Data Services
- *
- */
+* Generated by the generator tool for the WCF Data Services extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
public class Cafe {
- private String city;
-
- private String companyName;
-
- private String id;
-
- private String name;
-
- private int zipCode;
-
- private Contact contact;
-
- private List items;
-
- /**
+private Point spatial;
+private String city;
+private String companyName;
+private String id;
+private String name;
+private int zipCode;
+private Contact contact;
+private List items = new ArrayList(); /**
* Constructor without parameter.
*
*/
@@ -79,138 +72,154 @@ public Cafe(String id) {
this();
this.id = id;
}
+
+ /**
+ * Returns the value of the city attribute.
+ *
+ * @return The value of the city attribute.
+ */
+ public String getCity() {
+ return city;
+ }
+
+ /**
+ * Returns the value of the companyName attribute.
+ *
+ * @return The value of the companyName attribute.
+ */
+ public String getCompanyName() {
+ return companyName;
+ }
+
+ /**
+ * Returns the value of the id attribute.
+ *
+ * @return The value of the id attribute.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the value of the name attribute.
+ *
+ * @return The value of the name attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the zipCode attribute.
+ *
+ * @return The value of the zipCode attribute.
+ */
+ public int getZipCode() {
+ return zipCode;
+ }
+
+ /**
+ * Returns the value of the contact attribute.
+ *
+ * @return The value of the contact attribute.
+ */
+ public Contact getContact() {
+ return contact;
+ }
+
+ /**
+ * Returns the value of the items attribute.
+ *
+ * @return The value of the items attribute.
+ */
+ public List getItems() {
+ return items;
+ }
+
+
+ /**
+ * Sets the value of the city attribute.
+ *
+ * @param City
+ * The value of the city attribute.
+ */
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ /**
+ * Sets the value of the companyName attribute.
+ *
+ * @param CompanyName
+ * The value of the companyName attribute.
+ */
+ public void setCompanyName(String companyName) {
+ this.companyName = companyName;
+ }
+
+ /**
+ * Sets the value of the id attribute.
+ *
+ * @param ID
+ * The value of the id attribute.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the value of the name attribute.
+ *
+ * @param Name
+ * The value of the name attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the zipCode attribute.
+ *
+ * @param ZipCode
+ * The value of the zipCode attribute.
+ */
+ public void setZipCode(int zipCode) {
+ this.zipCode = zipCode;
+ }
+
+ /**
+ * Sets the value of the contact attribute.
+ *
+ * @param contact
+ * The value of the contact attribute.
+ */
+ public void setContact(Contact contact) {
+ this.contact = contact;
+ }
+
+ /**
+ * Sets the value of the items attribute.
+ *
+ * @param items
+ * The value of the items attribute.
+ */
+ public void setItems(List items) {
+ this.items = items;
+ }
- /**
- * Returns the value of the city attribute.
- *
- * @return The value of the city attribute.
- */
- public String getCity() {
- return city;
- }
-
- /**
- * Returns the value of the companyName attribute.
- *
- * @return The value of the companyName attribute.
- */
- public String getCompanyName() {
- return companyName;
- }
-
- /**
- * Returns the value of the id attribute.
- *
- * @return The value of the id attribute.
- */
- public String getId() {
- return id;
- }
-
- /**
- * Returns the value of the name attribute.
- *
- * @return The value of the name attribute.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the value of the zipCode attribute.
- *
- * @return The value of the zipCode attribute.
- */
- public int getZipCode() {
- return zipCode;
- }
-
- /**
- * Returns the value of the contact attribute.
- *
- * @return The value of the contact attribute.
- */
- public Contact getContact() {
- return contact;
- }
-
- /**
- * Returns the value of the items attribute.
- *
- * @return The value of the items attribute.
- */
- public List getItems() {
- return items;
- }
-
- /**
- * Sets the value of the city attribute.
- *
- * @param City
- * The value of the city attribute.
- */
- public void setCity(String city) {
- this.city = city;
- }
-
- /**
- * Sets the value of the companyName attribute.
- *
- * @param CompanyName
- * The value of the companyName attribute.
- */
- public void setCompanyName(String companyName) {
- this.companyName = companyName;
- }
-
- /**
- * Sets the value of the id attribute.
- *
- * @param ID
- * The value of the id attribute.
- */
- public void setId(String id) {
- this.id = id;
- }
-
- /**
- * Sets the value of the name attribute.
- *
- * @param Name
- * The value of the name attribute.
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * Sets the value of the zipCode attribute.
- *
- * @param ZipCode
- * The value of the zipCode attribute.
- */
- public void setZipCode(int zipCode) {
- this.zipCode = zipCode;
- }
+/**
+ * @return the spatial
+ */
+public Point getSpatial() {
+ return spatial;
+}
- /**
- * Sets the value of the contact attribute.
- *
- * @param contact
- * The value of the contact attribute.
- */
- public void setContact(Contact contact) {
- this.contact = contact;
- }
+/**
+ * @param spatial the spatial to set
+ */
+public void setSpatial(Point spatial) {
+ this.spatial = spatial;
+}
- /**
- * Sets the value of the items attribute.
- *
- * @param items
- * The value of the items attribute.
- */
- public void setItems(List items) {
- this.items = items;
- }
}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/Point.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/Point.java
new file mode 100644
index 0000000000..c29c4682dd
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/Point.java
@@ -0,0 +1,153 @@
+/**
+ * Copyright 2005-2013 Restlet S.A.S.
+ *
+ * The contents of this file are subject to the terms of one of the following
+ * open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
+ * 1.0 (the "Licenses"). You can select the license that you prefer but you may
+ * not use this file except in compliance with one of these Licenses.
+ *
+ * You can obtain a copy of the Apache 2.0 license at
+ * http://www.opensource.org/licenses/apache-2.0
+ *
+ * You can obtain a copy of the LGPL 3.0 license at
+ * http://www.opensource.org/licenses/lgpl-3.0
+ *
+ * You can obtain a copy of the LGPL 2.1 license at
+ * http://www.opensource.org/licenses/lgpl-2.1
+ *
+ * You can obtain a copy of the CDDL 1.0 license at
+ * http://www.opensource.org/licenses/cddl1
+ *
+ * You can obtain a copy of the EPL 1.0 license at
+ * http://www.opensource.org/licenses/eclipse-1.0
+ *
+ * See the Licenses for the specific language governing permissions and
+ * limitations under the Licenses.
+ *
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly at
+ * http://www.restlet.com/products/restlet-framework
+ *
+ * Restlet is a registered trademark of Restlet S.A.S.
+ */
+
+package org.restlet.test.ext.odata.cafe;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Generated for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class Point {
+
+ private String geo_type;
+ private String geo_name;
+ private List properties = new ArrayList();
+ private List x = new ArrayList();
+ private List y = new ArrayList();
+
+ /**
+ * Constructor without parameter.
+ *
+ */
+ public Point() {
+ super();
+ }
+
+ /**
+ * Returns the value of the "geo_type" attribute.
+ *
+ * @return The value of the "geo_type" attribute.
+ */
+ public String getGeo_type() {
+ return geo_type;
+ }
+
+
+
+ /**
+ * Returns the value of the "x" attribute.
+ *
+ * @return The value of the "x" attribute.
+ */
+ public List getX() {
+ return x;
+ }
+
+ /**
+ * Returns the value of the "y" attribute.
+ *
+ * @return The value of the "y" attribute.
+ */
+ public List getY() {
+ return y;
+ }
+
+
+
+ /**
+ * Sets the value of the "geo_type" attribute.
+ *
+ * @param geo_type
+ * The value of the "geo_type" attribute.
+ */
+ public void setGeo_type(String geo_type) {
+ this.geo_type = geo_type;
+ }
+
+
+
+ /**
+ * Sets the value of the "x" attribute.
+ *
+ * @param x
+ * The value of the "x" attribute.
+ */
+ public void setX(List x) {
+ this.x = x;
+ }
+
+ /**
+ * Sets the value of the "y" attribute.
+ *
+ * @param y
+ * The value of the "y" attribute.
+ */
+ public void setY(List y) {
+ this.y = y;
+ }
+
+
+/**
+ * @return the geo_name
+ */
+public String getGeo_name() {
+ return geo_name;
+}
+
+/**
+ * @param geo_name the geo_name to set
+ */
+public void setGeo_name(String geo_name) {
+ this.geo_name = geo_name;
+}
+
+/**
+ * @return the properties
+ */
+public List getProperties() {
+ return properties;
+}
+
+/**
+ * @param properties the properties to set
+ */
+public void setProperties(List properties) {
+ this.properties = properties;
+}
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/StructAny.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/StructAny.java
new file mode 100644
index 0000000000..894b4f1f38
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/StructAny.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright 2005-2013 Restlet S.A.S.
+ *
+ * The contents of this file are subject to the terms of one of the following
+ * open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
+ * 1.0 (the "Licenses"). You can select the license that you prefer but you may
+ * not use this file except in compliance with one of these Licenses.
+ *
+ * You can obtain a copy of the Apache 2.0 license at
+ * http://www.opensource.org/licenses/apache-2.0
+ *
+ * You can obtain a copy of the LGPL 3.0 license at
+ * http://www.opensource.org/licenses/lgpl-3.0
+ *
+ * You can obtain a copy of the LGPL 2.1 license at
+ * http://www.opensource.org/licenses/lgpl-2.1
+ *
+ * You can obtain a copy of the CDDL 1.0 license at
+ * http://www.opensource.org/licenses/cddl1
+ *
+ * You can obtain a copy of the EPL 1.0 license at
+ * http://www.opensource.org/licenses/eclipse-1.0
+ *
+ * See the Licenses for the specific language governing permissions and
+ * limitations under the Licenses.
+ *
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly at
+ * http://www.restlet.com/products/restlet-framework
+ *
+ * Restlet is a registered trademark of Restlet S.A.S.
+ */
+
+package org.restlet.test.ext.odata.cafe;
+
+
+
+/**
+* Generated for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class StructAny {
+
+ private String name;
+ private String type;
+ private String unit;
+ private String unitType;
+ private String values;
+
+ /**
+ * Constructor without parameter.
+ *
+ */
+ public StructAny() {
+ super();
+ }
+
+ /**
+ * Returns the value of the "name" attribute.
+ *
+ * @return The value of the "name" attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the "type" attribute.
+ *
+ * @return The value of the "type" attribute.
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the value of the "unit" attribute.
+ *
+ * @return The value of the "unit" attribute.
+ */
+ public String getUnit() {
+ return unit;
+ }
+
+ /**
+ * Returns the value of the "unitType" attribute.
+ *
+ * @return The value of the "unitType" attribute.
+ */
+ public String getUnitType() {
+ return unitType;
+ }
+
+ /**
+ * Returns the value of the "values" attribute.
+ *
+ * @return The value of the "values" attribute.
+ */
+ public String getValues() {
+ return values;
+ }
+
+
+ /**
+ * Sets the value of the "name" attribute.
+ *
+ * @param name
+ * The value of the "name" attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the "type" attribute.
+ *
+ * @param type
+ * The value of the "type" attribute.
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Sets the value of the "unit" attribute.
+ *
+ * @param unit
+ * The value of the "unit" attribute.
+ */
+ public void setUnit(String unit) {
+ this.unit = unit;
+ }
+
+ /**
+ * Sets the value of the "unitType" attribute.
+ *
+ * @param unitType
+ * The value of the "unitType" attribute.
+ */
+ public void setUnitType(String unitType) {
+ this.unitType = unitType;
+ }
+
+ /**
+ * Sets the value of the "values" attribute.
+ *
+ * @param values
+ * The value of the "values" attribute.
+ */
+ public void setValues(String values) {
+ this.values = values;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/cafes.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/cafes.xml
index d9b633cd59..8760e32983 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/cafes.xml
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/cafes.xml
@@ -27,6 +27,27 @@
92300Levallois-PerretCafe corp.
+
+ LINESTRING
+ GEONAME
+
+ 7.29
+ 7.29
+
+
+ 65.32000000000001
+ 65.32000000000001
+
+
+
+ md
+ FLOAT
+ meters
+ depth measure
+ [0.0,2670.9678]
+
+
+
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/metadata.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/metadata.xml
index fd3ddcb1d4..102f4e8e88 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/metadata.xml
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafe/metadata.xml
@@ -60,6 +60,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/Cafe.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/Cafe.java
index 765bc876be..5c774b5121 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/Cafe.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/Cafe.java
@@ -33,35 +33,30 @@
package org.restlet.test.ext.odata.cafecustofeeds;
+
+import java.util.ArrayList;
import java.util.List;
+
+import org.restlet.test.ext.odata.cafe.Point;
import org.restlet.test.ext.odata.cafecustofeeds.Contact;
import org.restlet.test.ext.odata.cafecustofeeds.Item;
/**
- * Generated by the generator tool for the WCF Data Services extension for the
- * Restlet framework.
- *
- * @see Metadata of
- * the target WCF Data Services
- *
- */
+* Generated by the generator tool for the WCF Data Services extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
public class Cafe {
- private String city;
-
- private String companyName;
-
- private String id;
-
- private String name;
-
- private int zipCode;
-
- private Contact contact;
-
- private List items;
-
- /**
+private Point spatial;
+private String city;
+private String companyName;
+private String id;
+private String name;
+private int zipCode;
+private Contact contact;
+private List items = new ArrayList(); /**
* Constructor without parameter.
*
*/
@@ -79,138 +74,154 @@ public Cafe(String id) {
this();
this.id = id;
}
+
+ /**
+ * Returns the value of the city attribute.
+ *
+ * @return The value of the city attribute.
+ */
+ public String getCity() {
+ return city;
+ }
+
+ /**
+ * Returns the value of the companyName attribute.
+ *
+ * @return The value of the companyName attribute.
+ */
+ public String getCompanyName() {
+ return companyName;
+ }
+
+ /**
+ * Returns the value of the id attribute.
+ *
+ * @return The value of the id attribute.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the value of the name attribute.
+ *
+ * @return The value of the name attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the zipCode attribute.
+ *
+ * @return The value of the zipCode attribute.
+ */
+ public int getZipCode() {
+ return zipCode;
+ }
+
+ /**
+ * Returns the value of the contact attribute.
+ *
+ * @return The value of the contact attribute.
+ */
+ public Contact getContact() {
+ return contact;
+ }
+
+ /**
+ * Returns the value of the items attribute.
+ *
+ * @return The value of the items attribute.
+ */
+ public List getItems() {
+ return items;
+ }
+
+
+ /**
+ * Sets the value of the city attribute.
+ *
+ * @param City
+ * The value of the city attribute.
+ */
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ /**
+ * Sets the value of the companyName attribute.
+ *
+ * @param CompanyName
+ * The value of the companyName attribute.
+ */
+ public void setCompanyName(String companyName) {
+ this.companyName = companyName;
+ }
+
+ /**
+ * Sets the value of the id attribute.
+ *
+ * @param ID
+ * The value of the id attribute.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the value of the name attribute.
+ *
+ * @param Name
+ * The value of the name attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the zipCode attribute.
+ *
+ * @param ZipCode
+ * The value of the zipCode attribute.
+ */
+ public void setZipCode(int zipCode) {
+ this.zipCode = zipCode;
+ }
+
+ /**
+ * Sets the value of the contact attribute.
+ *
+ * @param contact
+ * The value of the contact attribute.
+ */
+ public void setContact(Contact contact) {
+ this.contact = contact;
+ }
+
+ /**
+ * Sets the value of the items attribute.
+ *
+ * @param items
+ * The value of the items attribute.
+ */
+ public void setItems(List items) {
+ this.items = items;
+ }
- /**
- * Returns the value of the city attribute.
- *
- * @return The value of the city attribute.
- */
- public String getCity() {
- return city;
- }
-
- /**
- * Returns the value of the companyName attribute.
- *
- * @return The value of the companyName attribute.
- */
- public String getCompanyName() {
- return companyName;
- }
-
- /**
- * Returns the value of the id attribute.
- *
- * @return The value of the id attribute.
- */
- public String getId() {
- return id;
- }
-
- /**
- * Returns the value of the name attribute.
- *
- * @return The value of the name attribute.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the value of the zipCode attribute.
- *
- * @return The value of the zipCode attribute.
- */
- public int getZipCode() {
- return zipCode;
- }
-
- /**
- * Returns the value of the contact attribute.
- *
- * @return The value of the contact attribute.
- */
- public Contact getContact() {
- return contact;
- }
-
- /**
- * Returns the value of the items attribute.
- *
- * @return The value of the items attribute.
- */
- public List getItems() {
- return items;
- }
-
- /**
- * Sets the value of the city attribute.
- *
- * @param City
- * The value of the city attribute.
- */
- public void setCity(String city) {
- this.city = city;
- }
-
- /**
- * Sets the value of the companyName attribute.
- *
- * @param CompanyName
- * The value of the companyName attribute.
- */
- public void setCompanyName(String companyName) {
- this.companyName = companyName;
- }
-
- /**
- * Sets the value of the id attribute.
- *
- * @param ID
- * The value of the id attribute.
- */
- public void setId(String id) {
- this.id = id;
- }
-
- /**
- * Sets the value of the name attribute.
- *
- * @param Name
- * The value of the name attribute.
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * Sets the value of the zipCode attribute.
- *
- * @param ZipCode
- * The value of the zipCode attribute.
- */
- public void setZipCode(int zipCode) {
- this.zipCode = zipCode;
- }
+/**
+ * @return the spatial
+ */
+public Point getSpatial() {
+ return spatial;
+}
- /**
- * Sets the value of the contact attribute.
- *
- * @param contact
- * The value of the contact attribute.
- */
- public void setContact(Contact contact) {
- this.contact = contact;
- }
+/**
+ * @param spatial the spatial to set
+ */
+public void setSpatial(Point spatial) {
+ this.spatial = spatial;
+}
- /**
- * Sets the value of the items attribute.
- *
- * @param items
- * The value of the items attribute.
- */
- public void setItems(List items) {
- this.items = items;
- }
}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/Point.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/Point.java
new file mode 100644
index 0000000000..7d5c316c1e
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/Point.java
@@ -0,0 +1,153 @@
+/**
+ * Copyright 2005-2013 Restlet S.A.S.
+ *
+ * The contents of this file are subject to the terms of one of the following
+ * open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
+ * 1.0 (the "Licenses"). You can select the license that you prefer but you may
+ * not use this file except in compliance with one of these Licenses.
+ *
+ * You can obtain a copy of the Apache 2.0 license at
+ * http://www.opensource.org/licenses/apache-2.0
+ *
+ * You can obtain a copy of the LGPL 3.0 license at
+ * http://www.opensource.org/licenses/lgpl-3.0
+ *
+ * You can obtain a copy of the LGPL 2.1 license at
+ * http://www.opensource.org/licenses/lgpl-2.1
+ *
+ * You can obtain a copy of the CDDL 1.0 license at
+ * http://www.opensource.org/licenses/cddl1
+ *
+ * You can obtain a copy of the EPL 1.0 license at
+ * http://www.opensource.org/licenses/eclipse-1.0
+ *
+ * See the Licenses for the specific language governing permissions and
+ * limitations under the Licenses.
+ *
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly at
+ * http://www.restlet.com/products/restlet-framework
+ *
+ * Restlet is a registered trademark of Restlet S.A.S.
+ */
+
+package org.restlet.test.ext.odata.cafecustofeeds;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Generated for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class Point {
+
+ private String geo_type;
+ private String geo_name;
+ private List properties = new ArrayList();
+ private List x = new ArrayList();
+ private List y = new ArrayList();
+
+ /**
+ * Constructor without parameter.
+ *
+ */
+ public Point() {
+ super();
+ }
+
+ /**
+ * Returns the value of the "geo_type" attribute.
+ *
+ * @return The value of the "geo_type" attribute.
+ */
+ public String getGeo_type() {
+ return geo_type;
+ }
+
+
+
+ /**
+ * Returns the value of the "x" attribute.
+ *
+ * @return The value of the "x" attribute.
+ */
+ public List getX() {
+ return x;
+ }
+
+ /**
+ * Returns the value of the "y" attribute.
+ *
+ * @return The value of the "y" attribute.
+ */
+ public List getY() {
+ return y;
+ }
+
+
+
+ /**
+ * Sets the value of the "geo_type" attribute.
+ *
+ * @param geo_type
+ * The value of the "geo_type" attribute.
+ */
+ public void setGeo_type(String geo_type) {
+ this.geo_type = geo_type;
+ }
+
+
+
+ /**
+ * Sets the value of the "x" attribute.
+ *
+ * @param x
+ * The value of the "x" attribute.
+ */
+ public void setX(List x) {
+ this.x = x;
+ }
+
+ /**
+ * Sets the value of the "y" attribute.
+ *
+ * @param y
+ * The value of the "y" attribute.
+ */
+ public void setY(List y) {
+ this.y = y;
+ }
+
+
+/**
+ * @return the geo_name
+ */
+public String getGeo_name() {
+ return geo_name;
+}
+
+/**
+ * @param geo_name the geo_name to set
+ */
+public void setGeo_name(String geo_name) {
+ this.geo_name = geo_name;
+}
+
+/**
+ * @return the properties
+ */
+public List getProperties() {
+ return properties;
+}
+
+/**
+ * @param properties the properties to set
+ */
+public void setProperties(List properties) {
+ this.properties = properties;
+}
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/StructAny.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/StructAny.java
new file mode 100644
index 0000000000..9923968026
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/StructAny.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright 2005-2013 Restlet S.A.S.
+ *
+ * The contents of this file are subject to the terms of one of the following
+ * open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
+ * 1.0 (the "Licenses"). You can select the license that you prefer but you may
+ * not use this file except in compliance with one of these Licenses.
+ *
+ * You can obtain a copy of the Apache 2.0 license at
+ * http://www.opensource.org/licenses/apache-2.0
+ *
+ * You can obtain a copy of the LGPL 3.0 license at
+ * http://www.opensource.org/licenses/lgpl-3.0
+ *
+ * You can obtain a copy of the LGPL 2.1 license at
+ * http://www.opensource.org/licenses/lgpl-2.1
+ *
+ * You can obtain a copy of the CDDL 1.0 license at
+ * http://www.opensource.org/licenses/cddl1
+ *
+ * You can obtain a copy of the EPL 1.0 license at
+ * http://www.opensource.org/licenses/eclipse-1.0
+ *
+ * See the Licenses for the specific language governing permissions and
+ * limitations under the Licenses.
+ *
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly at
+ * http://www.restlet.com/products/restlet-framework
+ *
+ * Restlet is a registered trademark of Restlet S.A.S.
+ */
+
+package org.restlet.test.ext.odata.cafecustofeeds;
+
+
+
+/**
+* Generated for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class StructAny {
+
+ private String name;
+ private String type;
+ private String unit;
+ private String unitType;
+ private String values;
+
+ /**
+ * Constructor without parameter.
+ *
+ */
+ public StructAny() {
+ super();
+ }
+
+ /**
+ * Returns the value of the "name" attribute.
+ *
+ * @return The value of the "name" attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the "type" attribute.
+ *
+ * @return The value of the "type" attribute.
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the value of the "unit" attribute.
+ *
+ * @return The value of the "unit" attribute.
+ */
+ public String getUnit() {
+ return unit;
+ }
+
+ /**
+ * Returns the value of the "unitType" attribute.
+ *
+ * @return The value of the "unitType" attribute.
+ */
+ public String getUnitType() {
+ return unitType;
+ }
+
+ /**
+ * Returns the value of the "values" attribute.
+ *
+ * @return The value of the "values" attribute.
+ */
+ public String getValues() {
+ return values;
+ }
+
+
+ /**
+ * Sets the value of the "name" attribute.
+ *
+ * @param name
+ * The value of the "name" attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the "type" attribute.
+ *
+ * @param type
+ * The value of the "type" attribute.
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Sets the value of the "unit" attribute.
+ *
+ * @param unit
+ * The value of the "unit" attribute.
+ */
+ public void setUnit(String unit) {
+ this.unit = unit;
+ }
+
+ /**
+ * Sets the value of the "unitType" attribute.
+ *
+ * @param unitType
+ * The value of the "unitType" attribute.
+ */
+ public void setUnitType(String unitType) {
+ this.unitType = unitType;
+ }
+
+ /**
+ * Sets the value of the "values" attribute.
+ *
+ * @param values
+ * The value of the "values" attribute.
+ */
+ public void setValues(String values) {
+ this.values = values;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/cafes.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/cafes.xml
index 147cb3d95d..b5b9b91ffa 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/cafes.xml
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/cafes.xml
@@ -26,6 +26,27 @@
Le Cafe Louis92300Levallois-Perret
+
+ LINESTRING
+ GEONAME
+
+ 7.29
+ 7.29
+
+
+ 65.32000000000001
+ 65.32000000000001
+
+
+
+ md
+ FLOAT
+ meters
+ depth measure
+ [0.0,2670.9678]
+
+
+
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/metadata.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/metadata.xml
index a2415d1278..f9fb5ca635 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/metadata.xml
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/cafecustofeeds/metadata.xml
@@ -70,6 +70,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/Cafe.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/Cafe.java
new file mode 100644
index 0000000000..f49496db75
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/Cafe.java
@@ -0,0 +1,158 @@
+package org.restlet.test.ext.odata.complexcrud;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.restlet.test.ext.odata.cafe.Item;
+
+/**
+* Generated by the generator tool for the WCF Data Services extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class Cafe {
+
+private Point spatial;
+private String city;
+
+private String id;
+private String name;
+private int zipCode;
+
+private List items = new ArrayList(); /**
+ * Constructor without parameter.
+ *
+ */
+ public Cafe() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param id
+ * The identifiant value of the entity.
+ */
+ public Cafe(String id) {
+ this();
+ this.id = id;
+ }
+
+ /**
+ * Returns the value of the city attribute.
+ *
+ * @return The value of the city attribute.
+ */
+ public String getCity() {
+ return city;
+ }
+
+
+ /**
+ * Returns the value of the id attribute.
+ *
+ * @return The value of the id attribute.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the value of the name attribute.
+ *
+ * @return The value of the name attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the zipCode attribute.
+ *
+ * @return The value of the zipCode attribute.
+ */
+ public int getZipCode() {
+ return zipCode;
+ }
+
+
+ /**
+ * Returns the value of the items attribute.
+ *
+ * @return The value of the items attribute.
+ */
+ public List getItems() {
+ return items;
+ }
+
+
+ /**
+ * Sets the value of the city attribute.
+ *
+ * @param City
+ * The value of the city attribute.
+ */
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+
+ /**
+ * Sets the value of the id attribute.
+ *
+ * @param ID
+ * The value of the id attribute.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the value of the name attribute.
+ *
+ * @param Name
+ * The value of the name attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the zipCode attribute.
+ *
+ * @param ZipCode
+ * The value of the zipCode attribute.
+ */
+ public void setZipCode(int zipCode) {
+ this.zipCode = zipCode;
+ }
+
+
+ /**
+ * Sets the value of the items attribute.
+ *
+ * @param items
+ * The value of the items attribute.
+ */
+ public void setItems(List items) {
+ this.items = items;
+ }
+
+/**
+ * @return the spatial
+ */
+public Point getSpatial() {
+ return spatial;
+}
+
+/**
+ * @param spatial the spatial to set
+ */
+public void setSpatial(Point spatial) {
+ this.spatial = spatial;
+}
+
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/CafeCrudApplication.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/CafeCrudApplication.java
new file mode 100644
index 0000000000..af7c45bc0f
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/CafeCrudApplication.java
@@ -0,0 +1,87 @@
+package org.restlet.test.ext.odata.complexcrud;
+
+import java.io.IOException;
+
+import org.restlet.Application;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.Form;
+import org.restlet.data.LocalReference;
+import org.restlet.data.Method;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.routing.Router;
+
+/**
+ * Sample application that simulates cud operation for complex entities and
+ * collection.
+ */
+public class CafeCrudApplication extends Application {
+ private static class MyClapRestlet extends Restlet {
+ String file;
+
+ @SuppressWarnings("unused")
+ boolean updatable;
+
+ public MyClapRestlet(Context context, String file, boolean updatable) {
+ super(context);
+ this.file = file;
+ this.updatable = updatable;
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ public void handle(Request request, Response response) {
+
+ if (Method.GET.equals(request.getMethod())) {
+ Form form = request.getResourceRef().getQueryAsForm();
+ String uri = "/"
+ + this.getClass().getPackage().getName()
+ .replace(".", "/") + "/" + file;
+
+ Response r = getContext().getClientDispatcher().handle(
+ new Request(Method.GET, LocalReference
+ .createClapReference(LocalReference.CLAP_CLASS,
+ uri + ".xml")));
+ response.setEntity(r.getEntity());
+ response.setStatus(r.getStatus());
+
+ } else if (Method.POST.equals(request.getMethod()) || Method.PUT.equals(request.getMethod())) {
+ String rep=null;
+ try {
+ rep = request.getEntity().getText();
+ } catch (IOException e) {
+ response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
+ }
+ if(null != rep && !rep.isEmpty()){
+ response.setStatus(Status.SUCCESS_OK);
+ }
+
+ } else if (Method.DELETE.equals(request.getMethod())) {
+ response.setStatus(Status.SUCCESS_NO_CONTENT);
+
+ }
+
+ }
+ }
+
+
+ @Override
+ public Restlet createInboundRoot() {
+ getMetadataService().setDefaultCharacterSet(CharacterSet.ISO_8859_1);
+ getConnectorService().getClientProtocols().add(Protocol.CLAP);
+ Router router = new Router(getContext());
+
+ router.attach("/$metadata", new MyClapRestlet(getContext(), "metadata",
+ true));
+ router.attach("/Cafes", new MyClapRestlet(getContext(), "cafes", true));
+ router.attach("/Cafes('30')", new MyClapRestlet(getContext(),
+ "cafesUpdated", true));
+
+ return router;
+ }
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/CafeService.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/CafeService.java
new file mode 100644
index 0000000000..705b72739b
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/CafeService.java
@@ -0,0 +1,44 @@
+package org.restlet.test.ext.odata.complexcrud;
+
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.Service;
+
+/**
+* Generated by the generator tool for the WCF Data Services extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class CafeService extends Service {
+
+ /**
+ * Constructor.
+ *
+ */
+ public CafeService() {
+ super("http://localhost:8111/Cafe.svc");
+ }
+
+ /**
+ * Adds a new entity to the service.
+ *
+ * @param entity
+ * The entity to add to the service.
+ * @throws Exception
+ */
+ public void addEntity(Cafe entity) throws Exception {
+ addEntity("/Cafes", entity);
+ }
+
+ /**
+ * Creates a query for cafe entities hosted by this service.
+ *
+ * @param subpath
+ * The path to this entity relatively to the service URI.
+ * @return A query object.
+ */
+ public Query createCafeQuery(String subpath) {
+ return createQuery(subpath, Cafe.class);
+ }
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/ODataCafeCrudTestCase.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/ODataCafeCrudTestCase.java
new file mode 100644
index 0000000000..e13c133ea0
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/ODataCafeCrudTestCase.java
@@ -0,0 +1,142 @@
+package org.restlet.test.ext.odata.complexcrud;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Context;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.test.RestletTestCase;
+
+/**
+ * Test case for OData service for CUD operation on complex entities and
+ * collection.
+ *
+ */
+public class ODataCafeCrudTestCase extends RestletTestCase {
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for crud operation on complex entities and collection.
+ */
+ public void testCrudComplexEntity() {
+ CafeService service = new CafeService();
+
+ // create.
+ Cafe cafe = buildCafeEntity();
+
+ try {
+ service.addEntity(cafe);
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot add entity due to: " + e.getMessage());
+ Assert.fail();
+ }
+
+ Query query = service.createCafeQuery("/Cafes");
+ Cafe cafe1 = query.iterator().next();
+ assertEquals("TestName", cafe1.getName());
+ assertEquals("30", cafe1.getId());
+ assertEquals(111111, cafe1.getZipCode());
+ assertNotNull(cafe1.getSpatial());
+ Response latestResponse = query.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+
+ // // Update.
+ cafe1.setName("TestName-update");
+
+ try {
+ service.updateEntity(cafe1);
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot update entity due to: " + e.getMessage());
+ Assert.fail();
+ }
+
+ Query query3 = service.createCafeQuery("/Cafes('30')");
+
+ Cafe cafe2 = query3.iterator().next();
+ assertEquals("TestName-updated", cafe2.getName());
+ assertNotNull(cafe1.getSpatial());
+ latestResponse = query3.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+
+ // Delete
+ try {
+ service.deleteEntity(cafe2);
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot delete entity due to: " + e.getMessage());
+ Assert.fail();
+ }
+ latestResponse = query3.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_NO_CONTENT, latestResponse.getStatus());
+ }
+
+ private Cafe buildCafeEntity() {
+ Cafe cafe = new Cafe();
+ cafe.setId("30");
+ cafe.setName("TestName");
+ cafe.setCity("TestCity");
+ cafe.setZipCode(111111);
+
+ Point point = new Point();
+ point.setGeo_name("GEONAME");
+ point.setGeo_type("LINESTRING");
+
+ StructAny structAny = new StructAny();
+ structAny.setName("md");
+ structAny.setType("FLOAT");
+ structAny.setUnit("meters");
+ structAny.setUnitType("depth measure");
+ structAny.setValues("[0.0,2670.9678]");
+
+ List properties = new ArrayList();
+ properties.add(structAny);
+
+ List x = new ArrayList();
+ x.add(7.29d);
+ x.add(7.29d);
+ List y = new ArrayList();
+ y.add(65.32000000000001d);
+ y.add(65.32000000000001d);
+
+ point.setProperties(properties);
+ point.setX(x);
+ point.setY(y);
+ cafe.setSpatial(point);
+ return cafe;
+ }
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/Point.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/Point.java
new file mode 100644
index 0000000000..ab85b873b5
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/Point.java
@@ -0,0 +1,120 @@
+package org.restlet.test.ext.odata.complexcrud;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Generated for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class Point {
+
+ private String geo_type;
+ private String geo_name;
+ private List properties = new ArrayList();
+ private List x = new ArrayList();
+ private List y = new ArrayList();
+
+ /**
+ * Constructor without parameter.
+ *
+ */
+ public Point() {
+ super();
+ }
+
+ /**
+ * Returns the value of the "geo_type" attribute.
+ *
+ * @return The value of the "geo_type" attribute.
+ */
+ public String getGeo_type() {
+ return geo_type;
+ }
+
+
+
+ /**
+ * Returns the value of the "x" attribute.
+ *
+ * @return The value of the "x" attribute.
+ */
+ public List getX() {
+ return x;
+ }
+
+ /**
+ * Returns the value of the "y" attribute.
+ *
+ * @return The value of the "y" attribute.
+ */
+ public List getY() {
+ return y;
+ }
+
+
+
+ /**
+ * Sets the value of the "geo_type" attribute.
+ *
+ * @param geo_type
+ * The value of the "geo_type" attribute.
+ */
+ public void setGeo_type(String geo_type) {
+ this.geo_type = geo_type;
+ }
+
+
+
+ /**
+ * Sets the value of the "x" attribute.
+ *
+ * @param x
+ * The value of the "x" attribute.
+ */
+ public void setX(List x) {
+ this.x = x;
+ }
+
+ /**
+ * Sets the value of the "y" attribute.
+ *
+ * @param y
+ * The value of the "y" attribute.
+ */
+ public void setY(List y) {
+ this.y = y;
+ }
+
+
+/**
+ * @return the geo_name
+ */
+public String getGeo_name() {
+ return geo_name;
+}
+
+/**
+ * @param geo_name the geo_name to set
+ */
+public void setGeo_name(String geo_name) {
+ this.geo_name = geo_name;
+}
+
+/**
+ * @return the properties
+ */
+public List getProperties() {
+ return properties;
+}
+
+/**
+ * @param properties the properties to set
+ */
+public void setProperties(List properties) {
+ this.properties = properties;
+}
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/StructAny.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/StructAny.java
new file mode 100644
index 0000000000..495e5c22c4
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/StructAny.java
@@ -0,0 +1,124 @@
+
+package org.restlet.test.ext.odata.complexcrud;
+
+
+
+/**
+* Generated for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class StructAny {
+
+ private String name;
+ private String type;
+ private String unit;
+ private String unitType;
+ private String values;
+
+ /**
+ * Constructor without parameter.
+ *
+ */
+ public StructAny() {
+ super();
+ }
+
+ /**
+ * Returns the value of the "name" attribute.
+ *
+ * @return The value of the "name" attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the "type" attribute.
+ *
+ * @return The value of the "type" attribute.
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the value of the "unit" attribute.
+ *
+ * @return The value of the "unit" attribute.
+ */
+ public String getUnit() {
+ return unit;
+ }
+
+ /**
+ * Returns the value of the "unitType" attribute.
+ *
+ * @return The value of the "unitType" attribute.
+ */
+ public String getUnitType() {
+ return unitType;
+ }
+
+ /**
+ * Returns the value of the "values" attribute.
+ *
+ * @return The value of the "values" attribute.
+ */
+ public String getValues() {
+ return values;
+ }
+
+
+ /**
+ * Sets the value of the "name" attribute.
+ *
+ * @param name
+ * The value of the "name" attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the "type" attribute.
+ *
+ * @param type
+ * The value of the "type" attribute.
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Sets the value of the "unit" attribute.
+ *
+ * @param unit
+ * The value of the "unit" attribute.
+ */
+ public void setUnit(String unit) {
+ this.unit = unit;
+ }
+
+ /**
+ * Sets the value of the "unitType" attribute.
+ *
+ * @param unitType
+ * The value of the "unitType" attribute.
+ */
+ public void setUnitType(String unitType) {
+ this.unitType = unitType;
+ }
+
+ /**
+ * Sets the value of the "values" attribute.
+ *
+ * @param values
+ * The value of the "values" attribute.
+ */
+ public void setValues(String values) {
+ this.values = values;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/cafes.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/cafes.xml
new file mode 100644
index 0000000000..4724c0e3d2
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/cafes.xml
@@ -0,0 +1,51 @@
+
+
+ Cafes
+ http://localhost:8111/Cafe.svc/Cafes
+ 2010-02-17T11:28:13Z
+
+
+ http://localhost:8111/Cafe.svc/Cafes('30')
+
+ 2010-02-17T11:28:13Z
+
+
+
+
+
+
+
+ 30
+ TestName
+ 111111
+ TestCity
+
+
+ LINESTRING
+ GEONAME
+
+
+ md
+ FLOAT
+ meters
+ depth measure
+ [0.0,2670.9678]
+
+
+
+ 7.29
+ 7.29
+
+
+ 65.32000000000001
+ 65.32000000000001
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/cafesUpdated.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/cafesUpdated.xml
new file mode 100644
index 0000000000..89aecc6c8d
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/cafesUpdated.xml
@@ -0,0 +1,51 @@
+
+
+ Cafes
+ http://localhost:8111/Cafe.svc/Cafes
+ 2010-02-17T11:28:13Z
+
+
+ http://localhost:8111/Cafe.svc/Cafes('30')
+
+ 2010-02-17T11:28:13Z
+
+
+
+
+
+
+
+ 30
+ TestName-updated
+ 111111
+ TestCity
+
+
+ LINESTRING
+ GEONAME
+
+
+ md
+ FLOAT
+ meters
+ depth measure
+ [0.0,2670.9678]
+
+
+
+ 7.29
+ 7.29
+
+
+ 65.32000000000001
+ 65.32000000000001
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/metadata.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/metadata.xml
new file mode 100644
index 0000000000..b66f86e1f6
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/complexcrud/metadata.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/Cafe.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/Cafe.java
new file mode 100644
index 0000000000..28bb59e32e
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/Cafe.java
@@ -0,0 +1,120 @@
+package org.restlet.test.ext.odata.crud;
+
+
+
+/**
+* Generated by the generator tool for the WCF Data Services extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class Cafe {
+
+
+private String city;
+
+private String id;
+private String name;
+private int zipCode;
+
+/**
+ * Constructor without parameter.
+ *
+ */
+ public Cafe() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param id
+ * The identifiant value of the entity.
+ */
+ public Cafe(String id) {
+ this();
+ this.id = id;
+ }
+
+ /**
+ * Returns the value of the city attribute.
+ *
+ * @return The value of the city attribute.
+ */
+ public String getCity() {
+ return city;
+ }
+
+
+ /**
+ * Returns the value of the id attribute.
+ *
+ * @return The value of the id attribute.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the value of the name attribute.
+ *
+ * @return The value of the name attribute.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the zipCode attribute.
+ *
+ * @return The value of the zipCode attribute.
+ */
+ public int getZipCode() {
+ return zipCode;
+ }
+
+
+
+
+ /**
+ * Sets the value of the city attribute.
+ *
+ * @param City
+ * The value of the city attribute.
+ */
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+
+
+ /**
+ * Sets the value of the id attribute.
+ *
+ * @param ID
+ * The value of the id attribute.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the value of the name attribute.
+ *
+ * @param Name
+ * The value of the name attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the zipCode attribute.
+ *
+ * @param ZipCode
+ * The value of the zipCode attribute.
+ */
+ public void setZipCode(int zipCode) {
+ this.zipCode = zipCode;
+ }
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/CafeCrudApplication.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/CafeCrudApplication.java
new file mode 100644
index 0000000000..2d85bfeedc
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/CafeCrudApplication.java
@@ -0,0 +1,84 @@
+
+package org.restlet.test.ext.odata.crud;
+
+import java.io.IOException;
+
+import org.restlet.Application;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.LocalReference;
+import org.restlet.data.Method;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.routing.Router;
+
+/**
+ * Sample application that simulates the CUD operation on entities.
+ *
+ */
+@SuppressWarnings("unused")
+public class CafeCrudApplication extends Application {
+
+ private static class MyClapRestlet extends Restlet {
+ String file;
+
+ boolean updatable;
+
+ public MyClapRestlet(Context context, String file, boolean updatable) {
+ super(context);
+ this.file = file;
+ this.updatable = updatable;
+ }
+
+ @Override
+ public void handle(Request request, Response response) {
+ if (Method.GET.equals(request.getMethod())) {
+ String uri = "/"
+ + this.getClass().getPackage().getName()
+ .replace(".", "/") + "/" + file;
+
+ Response r = getContext().getClientDispatcher().handle(
+ new Request(Method.GET, LocalReference
+ .createClapReference(LocalReference.CLAP_CLASS,
+ uri + ".xml")));
+ response.setEntity(r.getEntity());
+ response.setStatus(r.getStatus());
+
+ } else if (Method.POST.equals(request.getMethod()) || Method.PUT.equals(request.getMethod())) {
+ String rep=null;
+ try {
+ rep = request.getEntity().getText();
+ } catch (IOException e) {
+ response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
+ }
+ if(null != rep && !rep.isEmpty()){
+ response.setStatus(Status.SUCCESS_OK);
+ }
+
+ } else if (Method.DELETE.equals(request.getMethod())) {
+ response.setStatus(Status.SUCCESS_NO_CONTENT);
+
+ }
+
+ }
+ }
+
+ @Override
+ public Restlet createInboundRoot() {
+ getMetadataService().setDefaultCharacterSet(CharacterSet.ISO_8859_1);
+ getConnectorService().getClientProtocols().add(Protocol.CLAP);
+ Router router = new Router(getContext());
+
+ router.attach("/$metadata", new MyClapRestlet(getContext(), "metadata",
+ true));
+ router.attach("/Cafes", new MyClapRestlet(getContext(), "cafes", true));
+ router.attach("/Cafes('30')", new MyClapRestlet(getContext(),
+ "cafesUpdated", true));
+
+ return router;
+ }
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/CafeService.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/CafeService.java
new file mode 100644
index 0000000000..27228381d0
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/CafeService.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright 2005-2013 Restlet S.A.S.
+ *
+ * The contents of this file are subject to the terms of one of the following
+ * open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
+ * 1.0 (the "Licenses"). You can select the license that you prefer but you may
+ * not use this file except in compliance with one of these Licenses.
+ *
+ * You can obtain a copy of the Apache 2.0 license at
+ * http://www.opensource.org/licenses/apache-2.0
+ *
+ * You can obtain a copy of the LGPL 3.0 license at
+ * http://www.opensource.org/licenses/lgpl-3.0
+ *
+ * You can obtain a copy of the LGPL 2.1 license at
+ * http://www.opensource.org/licenses/lgpl-2.1
+ *
+ * You can obtain a copy of the CDDL 1.0 license at
+ * http://www.opensource.org/licenses/cddl1
+ *
+ * You can obtain a copy of the EPL 1.0 license at
+ * http://www.opensource.org/licenses/eclipse-1.0
+ *
+ * See the Licenses for the specific language governing permissions and
+ * limitations under the Licenses.
+ *
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly at
+ * http://www.restlet.com/products/restlet-framework
+ *
+ * Restlet is a registered trademark of Restlet S.A.S.
+ */
+
+package org.restlet.test.ext.odata.crud;
+
+import org.restlet.ext.odata.Query;
+import org.restlet.ext.odata.Service;
+
+/**
+* Generated by the generator tool for the WCF Data Services extension for the Restlet framework.
+*
+* @see Metadata of the target WCF Data Services
+*
+*/
+public class CafeService extends Service {
+
+ /**
+ * Constructor.
+ *
+ */
+ public CafeService() {
+ super("http://localhost:8111/Cafe.svc");
+ }
+
+ /**
+ * Adds a new entity to the service.
+ *
+ * @param entity
+ * The entity to add to the service.
+ * @throws Exception
+ */
+ public void addEntity(Cafe entity) throws Exception {
+ addEntity("/Cafes", entity);
+ }
+
+ /**
+ * Creates a query for cafe entities hosted by this service.
+ *
+ * @param subpath
+ * The path to this entity relatively to the service URI.
+ * @return A query object.
+ */
+ public Query createCafeQuery(String subpath) {
+ return createQuery(subpath, Cafe.class);
+ }
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/ODataCafeCrudTestCase.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/ODataCafeCrudTestCase.java
new file mode 100644
index 0000000000..aa4dbd0ddb
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/ODataCafeCrudTestCase.java
@@ -0,0 +1,102 @@
+package org.restlet.test.ext.odata.crud;
+
+import junit.framework.Assert;
+
+import org.restlet.Component;
+import org.restlet.Context;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Status;
+import org.restlet.ext.odata.Query;
+import org.restlet.test.RestletTestCase;
+
+/**
+ * Test case for OData service for CUD operation on entities.
+ *
+ */
+public class ODataCafeCrudTestCase extends RestletTestCase {
+
+ /** Inner component. */
+ private Component component = new Component();
+
+ /** OData service used for all tests. */
+ @SuppressWarnings("unused")
+ private CafeService service;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ component.getServers().add(Protocol.HTTP, 8111);
+ component.getClients().add(Protocol.CLAP);
+ component.getDefaultHost().attach("/Cafe.svc",
+ new CafeCrudApplication());
+ component.start();
+
+ service = new CafeService();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ component.stop();
+ component = null;
+ super.tearDown();
+ }
+
+ /**
+ * Test method for crud operation on simple entities.
+ */
+ public void testCrudSimpleEntity() {
+ CafeService service = new CafeService();
+
+ // create.
+ Cafe cafe = new Cafe();
+ cafe.setId("30");
+ cafe.setName("TestName");
+ cafe.setCity("TestCity");
+ cafe.setZipCode(111111);
+ try {
+ service.addEntity(cafe);
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot add entity due to: " + e.getMessage());
+ Assert.fail();
+ }
+
+ Query query = service.createCafeQuery("/Cafes");
+ Cafe cafe1 = query.iterator().next();
+ assertEquals("TestName", cafe1.getName());
+ assertEquals("30", cafe1.getId());
+ assertEquals(111111, cafe1.getZipCode());
+ Response latestResponse = query.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+ // // Update.
+ cafe1.setName("TestName-update");
+
+ try {
+ service.updateEntity(cafe1);
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot update entity due to: " + e.getMessage());
+ Assert.fail();
+ }
+
+ Query query3 = service.createCafeQuery("/Cafes('30')");
+
+ Cafe cafe2 = query3.iterator().next();
+ assertEquals("TestName-updated", cafe2.getName());
+ latestResponse = query3.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_OK, latestResponse.getStatus());
+ // Delete
+ try {
+ service.deleteEntity(cafe2);
+ } catch (Exception e) {
+ Context.getCurrentLogger().warning(
+ "Cannot delete entity due to: " + e.getMessage());
+ Assert.fail();
+ }
+ latestResponse = query3.getService().getLatestResponse();
+ assertEquals(Status.SUCCESS_NO_CONTENT, latestResponse.getStatus());
+ }
+
+}
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/cafes.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/cafes.xml
new file mode 100644
index 0000000000..1098176fde
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/cafes.xml
@@ -0,0 +1,29 @@
+
+
+ Cafes
+ http://localhost:8111/Cafe.svc/Cafes
+ 2010-02-17T11:28:13Z
+
+
+ http://localhost:8111/Cafe.svc/Cafes('30')
+
+ 2010-02-17T11:28:13Z
+
+
+
+
+
+
+
+ 30
+ TestName
+ 111111
+ TestCity
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/cafesUpdated.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/cafesUpdated.xml
new file mode 100644
index 0000000000..95493e94db
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/cafesUpdated.xml
@@ -0,0 +1,29 @@
+
+
+ Cafes
+ http://localhost:8111/Cafe.svc/Cafes
+ 2010-02-17T11:28:13Z
+
+
+ http://localhost:8111/Cafe.svc/Cafes('30')
+
+ 2010-02-17T11:28:13Z
+
+
+
+
+
+
+
+ 30
+ TestName-updated
+ 111111
+ TestCity
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/metadata.xml b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/metadata.xml
new file mode 100644
index 0000000000..8ec48f6592
--- /dev/null
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/crud/metadata.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/ActivitySector.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/ActivitySector.java
index 8ad98c3082..7900119bae 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/ActivitySector.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/ActivitySector.java
@@ -33,6 +33,8 @@
package org.restlet.test.ext.odata.deepexpand.model;
+
+import java.util.ArrayList;
import java.util.List;
import org.restlet.test.ext.odata.deepexpand.model.ActivitySector;
@@ -54,11 +56,8 @@ public class ActivitySector {
private String description;
private int id;
-
- private List childActivitySectors;
-
- private List companies;
-
+ private List childActivitySectors = new ArrayList();
+ private List companies = new ArrayList();
private ActivitySector parentActivitySector;
/**
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/AuthenticatedUser.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/AuthenticatedUser.java
index ecc0eb50c0..70989b52a2 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/AuthenticatedUser.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/AuthenticatedUser.java
@@ -33,6 +33,8 @@
package org.restlet.test.ext.odata.deepexpand.model;
+
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -45,51 +47,31 @@
import org.restlet.test.ext.odata.deepexpand.model.Telephone;
/**
- * Generated by the generator tool for the OData extension for the Restlet
- * framework.
- *
- * @see Metadata
- * of the target OData service
- *
- */
+* Generated by the generator tool for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target OData service
+*
+*/
public class AuthenticatedUser {
private Date dateOfBirth;
-
private String email;
-
private String fatherName;
-
private String gender;
-
private int id;
-
private String motherName;
-
private String name;
-
private String notes;
-
private String surname;
-
private String userName;
-
private Tracking tracking;
-
- private List addresses;
-
+ private List addresses = new ArrayList();
private CoOp defaultCoOp;
-
private Department department;
-
private Language preferredLanguage;
-
- private List reports;
-
- private List roles;
-
- private List telephones;
+ private List reports = new ArrayList();
+ private List roles = new ArrayList();
+ private List telephones = new ArrayList();
/**
* Constructor without parameter.
@@ -110,346 +92,325 @@ public AuthenticatedUser(int id) {
this.id = id;
}
- /**
- * Returns the value of the "dateOfBirth" attribute.
- *
- * @return The value of the "dateOfBirth" attribute.
- */
- public Date getDateOfBirth() {
- return dateOfBirth;
- }
-
- /**
- * Returns the value of the "email" attribute.
- *
- * @return The value of the "email" attribute.
- */
- public String getEmail() {
- return email;
- }
-
- /**
- * Returns the value of the "fatherName" attribute.
- *
- * @return The value of the "fatherName" attribute.
- */
- public String getFatherName() {
- return fatherName;
- }
-
- /**
- * Returns the value of the "gender" attribute.
- *
- * @return The value of the "gender" attribute.
- */
- public String getGender() {
- return gender;
- }
-
- /**
- * Returns the value of the "id" attribute.
- *
- * @return The value of the "id" attribute.
- */
- public int getId() {
- return id;
- }
-
- /**
- * Returns the value of the "motherName" attribute.
- *
- * @return The value of the "motherName" attribute.
- */
- public String getMotherName() {
- return motherName;
- }
-
- /**
- * Returns the value of the "name" attribute.
- *
- * @return The value of the "name" attribute.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the value of the "notes" attribute.
- *
- * @return The value of the "notes" attribute.
- */
- public String getNotes() {
- return notes;
- }
-
- /**
- * Returns the value of the "surname" attribute.
- *
- * @return The value of the "surname" attribute.
- */
- public String getSurname() {
- return surname;
- }
-
- /**
- * Returns the value of the "userName" attribute.
- *
- * @return The value of the "userName" attribute.
- */
- public String getUserName() {
- return userName;
- }
-
- /**
- * Returns the value of the "tracking" attribute.
- *
- * @return The value of the "tracking" attribute.
- */
- public Tracking getTracking() {
- return tracking;
- }
-
- /**
- * Returns the value of the "addresses" attribute.
- *
- * @return The value of the "addresses" attribute.
- */
- public List getAddresses() {
- return addresses;
- }
-
- /**
- * Returns the value of the "defaultCoOp" attribute.
- *
- * @return The value of the "defaultCoOp" attribute.
- */
- public CoOp getDefaultCoOp() {
- return defaultCoOp;
- }
-
- /**
- * Returns the value of the "department" attribute.
- *
- * @return The value of the "department" attribute.
- */
- public Department getDepartment() {
- return department;
- }
-
- /**
- * Returns the value of the "preferredLanguage" attribute.
- *
- * @return The value of the "preferredLanguage" attribute.
- */
- public Language getPreferredLanguage() {
- return preferredLanguage;
- }
-
- /**
- * Returns the value of the "reports" attribute.
- *
- * @return The value of the "reports" attribute.
- */
- public List getReports() {
- return reports;
- }
-
- /**
- * Returns the value of the "roles" attribute.
- *
- * @return The value of the "roles" attribute.
- */
- public List getRoles() {
- return roles;
- }
-
- /**
- * Returns the value of the "telephones" attribute.
- *
- * @return The value of the "telephones" attribute.
- */
- public List getTelephones() {
- return telephones;
- }
-
- /**
- * Sets the value of the "dateOfBirth" attribute.
- *
- * @param dateOfBirth
- * The value of the "dateOfBirth" attribute.
- */
- public void setDateOfBirth(Date dateOfBirth) {
- this.dateOfBirth = dateOfBirth;
- }
-
- /**
- * Sets the value of the "email" attribute.
- *
- * @param email
- * The value of the "email" attribute.
- */
- public void setEmail(String email) {
- this.email = email;
- }
-
- /**
- * Sets the value of the "fatherName" attribute.
- *
- * @param fatherName
- * The value of the "fatherName" attribute.
- */
- public void setFatherName(String fatherName) {
- this.fatherName = fatherName;
- }
-
- /**
- * Sets the value of the "gender" attribute.
- *
- * @param gender
- * The value of the "gender" attribute.
- */
- public void setGender(String gender) {
- this.gender = gender;
- }
-
- /**
- * Sets the value of the "id" attribute.
- *
- * @param id
- * The value of the "id" attribute.
- */
- public void setId(int id) {
- this.id = id;
- }
-
- /**
- * Sets the value of the "motherName" attribute.
- *
- * @param motherName
- * The value of the "motherName" attribute.
- */
- public void setMotherName(String motherName) {
- this.motherName = motherName;
- }
-
- /**
- * Sets the value of the "name" attribute.
- *
- * @param name
- * The value of the "name" attribute.
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * Sets the value of the "notes" attribute.
- *
- * @param notes
- * The value of the "notes" attribute.
- */
- public void setNotes(String notes) {
- this.notes = notes;
- }
-
- /**
- * Sets the value of the "surname" attribute.
- *
- * @param surname
- * The value of the "surname" attribute.
- */
- public void setSurname(String surname) {
- this.surname = surname;
- }
-
- /**
- * Sets the value of the "userName" attribute.
- *
- * @param userName
- * The value of the "userName" attribute.
- */
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- /**
- * Sets the value of the "tracking" attribute.
- *
- * @param tracking
- * The value of the "tracking" attribute.
- */
- public void setTracking(Tracking tracking) {
- this.tracking = tracking;
- }
-
- /**
- * Sets the value of the "addresses" attribute.
- *
- * @param addresses
- * " The value of the "addresses" attribute.
- */
- public void setAddresses(List addresses) {
- this.addresses = addresses;
- }
-
- /**
- * Sets the value of the "defaultCoOp" attribute.
- *
- * @param defaultCoOp
- * " The value of the "defaultCoOp" attribute.
- */
- public void setDefaultCoOp(CoOp defaultCoOp) {
- this.defaultCoOp = defaultCoOp;
- }
-
- /**
- * Sets the value of the "department" attribute.
- *
- * @param department
- * " The value of the "department" attribute.
- */
- public void setDepartment(Department department) {
- this.department = department;
- }
-
- /**
- * Sets the value of the "preferredLanguage" attribute.
- *
- * @param preferredLanguage
- * " The value of the "preferredLanguage" attribute.
- */
- public void setPreferredLanguage(Language preferredLanguage) {
- this.preferredLanguage = preferredLanguage;
- }
-
- /**
- * Sets the value of the "reports" attribute.
- *
- * @param reports
- * " The value of the "reports" attribute.
- */
- public void setReports(List reports) {
- this.reports = reports;
- }
-
- /**
- * Sets the value of the "roles" attribute.
- *
- * @param roles
- * " The value of the "roles" attribute.
- */
- public void setRoles(List roles) {
- this.roles = roles;
- }
-
- /**
- * Sets the value of the "telephones" attribute.
- *
- * @param telephones
- * " The value of the "telephones" attribute.
- */
- public void setTelephones(List telephones) {
- this.telephones = telephones;
- }
+ /**
+ * Returns the value of the "dateOfBirth" attribute.
+ *
+ * @return The value of the "dateOfBirth" attribute.
+ */
+ public Date getDateOfBirth() {
+ return dateOfBirth;
+ }
+ /**
+ * Returns the value of the "email" attribute.
+ *
+ * @return The value of the "email" attribute.
+ */
+ public String getEmail() {
+ return email;
+ }
+ /**
+ * Returns the value of the "fatherName" attribute.
+ *
+ * @return The value of the "fatherName" attribute.
+ */
+ public String getFatherName() {
+ return fatherName;
+ }
+ /**
+ * Returns the value of the "gender" attribute.
+ *
+ * @return The value of the "gender" attribute.
+ */
+ public String getGender() {
+ return gender;
+ }
+ /**
+ * Returns the value of the "id" attribute.
+ *
+ * @return The value of the "id" attribute.
+ */
+ public int getId() {
+ return id;
+ }
+ /**
+ * Returns the value of the "motherName" attribute.
+ *
+ * @return The value of the "motherName" attribute.
+ */
+ public String getMotherName() {
+ return motherName;
+ }
+ /**
+ * Returns the value of the "name" attribute.
+ *
+ * @return The value of the "name" attribute.
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * Returns the value of the "notes" attribute.
+ *
+ * @return The value of the "notes" attribute.
+ */
+ public String getNotes() {
+ return notes;
+ }
+ /**
+ * Returns the value of the "surname" attribute.
+ *
+ * @return The value of the "surname" attribute.
+ */
+ public String getSurname() {
+ return surname;
+ }
+ /**
+ * Returns the value of the "userName" attribute.
+ *
+ * @return The value of the "userName" attribute.
+ */
+ public String getUserName() {
+ return userName;
+ }
+ /**
+ * Returns the value of the "tracking" attribute.
+ *
+ * @return The value of the "tracking" attribute.
+ */
+ public Tracking getTracking() {
+ return tracking;
+ }
+ /**
+ * Returns the value of the "addresses" attribute.
+ *
+ * @return The value of the "addresses" attribute.
+ */
+ public List getAddresses() {
+ return addresses;
+ }
+
+ /**
+ * Returns the value of the "defaultCoOp" attribute.
+ *
+ * @return The value of the "defaultCoOp" attribute.
+ */
+ public CoOp getDefaultCoOp() {
+ return defaultCoOp;
+ }
+
+ /**
+ * Returns the value of the "department" attribute.
+ *
+ * @return The value of the "department" attribute.
+ */
+ public Department getDepartment() {
+ return department;
+ }
+
+ /**
+ * Returns the value of the "preferredLanguage" attribute.
+ *
+ * @return The value of the "preferredLanguage" attribute.
+ */
+ public Language getPreferredLanguage() {
+ return preferredLanguage;
+ }
+
+ /**
+ * Returns the value of the "reports" attribute.
+ *
+ * @return The value of the "reports" attribute.
+ */
+ public List getReports() {
+ return reports;
+ }
+
+ /**
+ * Returns the value of the "roles" attribute.
+ *
+ * @return The value of the "roles" attribute.
+ */
+ public List getRoles() {
+ return roles;
+ }
+
+ /**
+ * Returns the value of the "telephones" attribute.
+ *
+ * @return The value of the "telephones" attribute.
+ */
+ public List getTelephones() {
+ return telephones;
+ }
+
+ /**
+ * Sets the value of the "dateOfBirth" attribute.
+ *
+ * @param dateOfBirth
+ * The value of the "dateOfBirth" attribute.
+ */
+ public void setDateOfBirth(Date dateOfBirth) {
+ this.dateOfBirth = dateOfBirth;
+ }
+ /**
+ * Sets the value of the "email" attribute.
+ *
+ * @param email
+ * The value of the "email" attribute.
+ */
+ public void setEmail(String email) {
+ this.email = email;
+ }
+ /**
+ * Sets the value of the "fatherName" attribute.
+ *
+ * @param fatherName
+ * The value of the "fatherName" attribute.
+ */
+ public void setFatherName(String fatherName) {
+ this.fatherName = fatherName;
+ }
+ /**
+ * Sets the value of the "gender" attribute.
+ *
+ * @param gender
+ * The value of the "gender" attribute.
+ */
+ public void setGender(String gender) {
+ this.gender = gender;
+ }
+ /**
+ * Sets the value of the "id" attribute.
+ *
+ * @param id
+ * The value of the "id" attribute.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+ /**
+ * Sets the value of the "motherName" attribute.
+ *
+ * @param motherName
+ * The value of the "motherName" attribute.
+ */
+ public void setMotherName(String motherName) {
+ this.motherName = motherName;
+ }
+ /**
+ * Sets the value of the "name" attribute.
+ *
+ * @param name
+ * The value of the "name" attribute.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+ /**
+ * Sets the value of the "notes" attribute.
+ *
+ * @param notes
+ * The value of the "notes" attribute.
+ */
+ public void setNotes(String notes) {
+ this.notes = notes;
+ }
+ /**
+ * Sets the value of the "surname" attribute.
+ *
+ * @param surname
+ * The value of the "surname" attribute.
+ */
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+ /**
+ * Sets the value of the "userName" attribute.
+ *
+ * @param userName
+ * The value of the "userName" attribute.
+ */
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+ /**
+ * Sets the value of the "tracking" attribute.
+ *
+ * @param tracking
+ * The value of the "tracking" attribute.
+ */
+ public void setTracking(Tracking tracking) {
+ this.tracking = tracking;
+ }
+
+ /**
+ * Sets the value of the "addresses" attribute.
+ *
+ * @param addresses"
+ * The value of the "addresses" attribute.
+ */
+ public void setAddresses(List addresses) {
+ this.addresses = addresses;
+ }
+
+ /**
+ * Sets the value of the "defaultCoOp" attribute.
+ *
+ * @param defaultCoOp"
+ * The value of the "defaultCoOp" attribute.
+ */
+ public void setDefaultCoOp(CoOp defaultCoOp) {
+ this.defaultCoOp = defaultCoOp;
+ }
+
+ /**
+ * Sets the value of the "department" attribute.
+ *
+ * @param department"
+ * The value of the "department" attribute.
+ */
+ public void setDepartment(Department department) {
+ this.department = department;
+ }
+
+ /**
+ * Sets the value of the "preferredLanguage" attribute.
+ *
+ * @param preferredLanguage"
+ * The value of the "preferredLanguage" attribute.
+ */
+ public void setPreferredLanguage(Language preferredLanguage) {
+ this.preferredLanguage = preferredLanguage;
+ }
+
+ /**
+ * Sets the value of the "reports" attribute.
+ *
+ * @param reports"
+ * The value of the "reports" attribute.
+ */
+ public void setReports(List reports) {
+ this.reports = reports;
+ }
+
+ /**
+ * Sets the value of the "roles" attribute.
+ *
+ * @param roles"
+ * The value of the "roles" attribute.
+ */
+ public void setRoles(List roles) {
+ this.roles = roles;
+ }
+
+ /**
+ * Sets the value of the "telephones" attribute.
+ *
+ * @param telephones"
+ * The value of the "telephones" attribute.
+ */
+ public void setTelephones(List telephones) {
+ this.telephones = telephones;
+ }
}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Branch.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Branch.java
index fc18b61cf0..931c13ffb6 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Branch.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Branch.java
@@ -33,6 +33,8 @@
package org.restlet.test.ext.odata.deepexpand.model;
+
+import java.util.ArrayList;
import java.util.List;
import org.restlet.test.ext.odata.deepexpand.model.Company;
@@ -42,35 +44,23 @@
import org.restlet.test.ext.odata.deepexpand.model.Multilingual;
/**
- * Generated by the generator tool for the OData extension for the Restlet
- * framework.
- *
- * @see Metadata
- * of the target OData service
- *
- */
+* Generated by the generator tool for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target OData service
+*
+*/
public class Branch {
private String fax;
-
private int id;
-
private String telephone;
-
private EmbeddableAddress address;
-
private Tracking tracking;
-
private Company company;
-
- private List jobParts;
-
- private List jobPostingParts;
-
+ private List jobParts = new ArrayList();
+ private List jobPostingParts = new ArrayList();
private Multilingual name;
-
- private List persons;
+ private List persons = new ArrayList();
/**
* Constructor without parameter.
@@ -91,194 +81,186 @@ public Branch(int id) {
this.id = id;
}
- /**
- * Returns the value of the "fax" attribute.
- *
- * @return The value of the "fax" attribute.
- */
- public String getFax() {
- return fax;
- }
-
- /**
- * Returns the value of the "id" attribute.
- *
- * @return The value of the "id" attribute.
- */
- public int getId() {
- return id;
- }
-
- /**
- * Returns the value of the "telephone" attribute.
- *
- * @return The value of the "telephone" attribute.
- */
- public String getTelephone() {
- return telephone;
- }
-
- /**
- * Returns the value of the "address" attribute.
- *
- * @return The value of the "address" attribute.
- */
- public EmbeddableAddress getAddress() {
- return address;
- }
-
- /**
- * Returns the value of the "tracking" attribute.
- *
- * @return The value of the "tracking" attribute.
- */
- public Tracking getTracking() {
- return tracking;
- }
-
- /**
- * Returns the value of the "company" attribute.
- *
- * @return The value of the "company" attribute.
- */
- public Company getCompany() {
- return company;
- }
-
- /**
- * Returns the value of the "jobParts" attribute.
- *
- * @return The value of the "jobParts" attribute.
- */
- public List getJobParts() {
- return jobParts;
- }
-
- /**
- * Returns the value of the "jobPostingParts" attribute.
- *
- * @return The value of the "jobPostingParts" attribute.
- */
- public List getJobPostingParts() {
- return jobPostingParts;
- }
-
- /**
- * Returns the value of the "name" attribute.
- *
- * @return The value of the "name" attribute.
- */
- public Multilingual getName() {
- return name;
- }
-
- /**
- * Returns the value of the "persons" attribute.
- *
- * @return The value of the "persons" attribute.
- */
- public List getPersons() {
- return persons;
- }
-
- /**
- * Sets the value of the "fax" attribute.
- *
- * @param fax
- * The value of the "fax" attribute.
- */
- public void setFax(String fax) {
- this.fax = fax;
- }
-
- /**
- * Sets the value of the "id" attribute.
- *
- * @param id
- * The value of the "id" attribute.
- */
- public void setId(int id) {
- this.id = id;
- }
-
- /**
- * Sets the value of the "telephone" attribute.
- *
- * @param telephone
- * The value of the "telephone" attribute.
- */
- public void setTelephone(String telephone) {
- this.telephone = telephone;
- }
-
- /**
- * Sets the value of the "address" attribute.
- *
- * @param address
- * The value of the "address" attribute.
- */
- public void setAddress(EmbeddableAddress address) {
- this.address = address;
- }
-
- /**
- * Sets the value of the "tracking" attribute.
- *
- * @param tracking
- * The value of the "tracking" attribute.
- */
- public void setTracking(Tracking tracking) {
- this.tracking = tracking;
- }
-
- /**
- * Sets the value of the "company" attribute.
- *
- * @param company
- * " The value of the "company" attribute.
- */
- public void setCompany(Company company) {
- this.company = company;
- }
-
- /**
- * Sets the value of the "jobParts" attribute.
- *
- * @param jobParts
- * " The value of the "jobParts" attribute.
- */
- public void setJobParts(List jobParts) {
- this.jobParts = jobParts;
- }
-
- /**
- * Sets the value of the "jobPostingParts" attribute.
- *
- * @param jobPostingParts
- * " The value of the "jobPostingParts" attribute.
- */
- public void setJobPostingParts(List jobPostingParts) {
- this.jobPostingParts = jobPostingParts;
- }
-
- /**
- * Sets the value of the "name" attribute.
- *
- * @param name
- * " The value of the "name" attribute.
- */
- public void setName(Multilingual name) {
- this.name = name;
- }
-
- /**
- * Sets the value of the "persons" attribute.
- *
- * @param persons
- * " The value of the "persons" attribute.
- */
- public void setPersons(List persons) {
- this.persons = persons;
- }
+ /**
+ * Returns the value of the "fax" attribute.
+ *
+ * @return The value of the "fax" attribute.
+ */
+ public String getFax() {
+ return fax;
+ }
+ /**
+ * Returns the value of the "id" attribute.
+ *
+ * @return The value of the "id" attribute.
+ */
+ public int getId() {
+ return id;
+ }
+ /**
+ * Returns the value of the "telephone" attribute.
+ *
+ * @return The value of the "telephone" attribute.
+ */
+ public String getTelephone() {
+ return telephone;
+ }
+ /**
+ * Returns the value of the "address" attribute.
+ *
+ * @return The value of the "address" attribute.
+ */
+ public EmbeddableAddress getAddress() {
+ return address;
+ }
+ /**
+ * Returns the value of the "tracking" attribute.
+ *
+ * @return The value of the "tracking" attribute.
+ */
+ public Tracking getTracking() {
+ return tracking;
+ }
+ /**
+ * Returns the value of the "company" attribute.
+ *
+ * @return The value of the "company" attribute.
+ */
+ public Company getCompany() {
+ return company;
+ }
+
+ /**
+ * Returns the value of the "jobParts" attribute.
+ *
+ * @return The value of the "jobParts" attribute.
+ */
+ public List getJobParts() {
+ return jobParts;
+ }
+
+ /**
+ * Returns the value of the "jobPostingParts" attribute.
+ *
+ * @return The value of the "jobPostingParts" attribute.
+ */
+ public List getJobPostingParts() {
+ return jobPostingParts;
+ }
+
+ /**
+ * Returns the value of the "name" attribute.
+ *
+ * @return The value of the "name" attribute.
+ */
+ public Multilingual getName() {
+ return name;
+ }
+
+ /**
+ * Returns the value of the "persons" attribute.
+ *
+ * @return The value of the "persons" attribute.
+ */
+ public List getPersons() {
+ return persons;
+ }
+
+ /**
+ * Sets the value of the "fax" attribute.
+ *
+ * @param fax
+ * The value of the "fax" attribute.
+ */
+ public void setFax(String fax) {
+ this.fax = fax;
+ }
+ /**
+ * Sets the value of the "id" attribute.
+ *
+ * @param id
+ * The value of the "id" attribute.
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+ /**
+ * Sets the value of the "telephone" attribute.
+ *
+ * @param telephone
+ * The value of the "telephone" attribute.
+ */
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+ /**
+ * Sets the value of the "address" attribute.
+ *
+ * @param address
+ * The value of the "address" attribute.
+ */
+ public void setAddress(EmbeddableAddress address) {
+ this.address = address;
+ }
+
+ /**
+ * Sets the value of the "tracking" attribute.
+ *
+ * @param tracking
+ * The value of the "tracking" attribute.
+ */
+ public void setTracking(Tracking tracking) {
+ this.tracking = tracking;
+ }
+
+ /**
+ * Sets the value of the "company" attribute.
+ *
+ * @param company"
+ * The value of the "company" attribute.
+ */
+ public void setCompany(Company company) {
+ this.company = company;
+ }
+
+ /**
+ * Sets the value of the "jobParts" attribute.
+ *
+ * @param jobParts"
+ * The value of the "jobParts" attribute.
+ */
+ public void setJobParts(List jobParts) {
+ this.jobParts = jobParts;
+ }
+
+ /**
+ * Sets the value of the "jobPostingParts" attribute.
+ *
+ * @param jobPostingParts"
+ * The value of the "jobPostingParts" attribute.
+ */
+ public void setJobPostingParts(List jobPostingParts) {
+ this.jobPostingParts = jobPostingParts;
+ }
+
+ /**
+ * Sets the value of the "name" attribute.
+ *
+ * @param name"
+ * The value of the "name" attribute.
+ */
+ public void setName(Multilingual name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the value of the "persons" attribute.
+ *
+ * @param persons"
+ * The value of the "persons" attribute.
+ */
+ public void setPersons(List persons) {
+ this.persons = persons;
+ }
}
\ No newline at end of file
diff --git a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Category.java b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Category.java
index 0bcd2f4690..4326619640 100644
--- a/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Category.java
+++ b/modules/org.restlet.test/src/org/restlet/test/ext/odata/deepexpand/model/Category.java
@@ -33,6 +33,8 @@
package org.restlet.test.ext.odata.deepexpand.model;
+
+import java.util.ArrayList;
import java.util.List;
import org.restlet.test.ext.odata.deepexpand.model.Category;
@@ -41,31 +43,21 @@
import org.restlet.test.ext.odata.deepexpand.model.Registration;
/**
- * Generated by the generator tool for the OData extension for the Restlet
- * framework.
- *
- * @see Metadata
- * of the target OData service
- *
- */
+* Generated by the generator tool for the OData extension for the Restlet framework.
+*
+* @see Metadata of the target OData service
+*
+*/
public class Category {
private int id;
-
private String path;
-
private Tracking tracking;
-
- private List childCategories;
-
- private List companies;
-
+ private List childCategories = new ArrayList();
+ private List companies = new ArrayList();
private Multilingual name;
-
private Category parentCategory;
-
- private List preferredByRegistrations;
+ private List preferredByRegistrations = new ArrayList