[OLINGO-194] complex and collection literals + URI escape tests

This commit is contained in:
Francesco Chicchiriccò 2014-03-26 18:15:16 +01:00
parent 7651350846
commit 3e53ac5b7d
7 changed files with 176 additions and 42 deletions

View File

@ -153,7 +153,7 @@ public class ODataInvokeRequestImpl<T extends ODataInvokeResult>
throw new IllegalArgumentException("Only primitive values can be passed via GET");
}
uriBuilder.addParameter(param.getKey(), param.getValue().toString());
uriBuilder.addParameter(param.getKey(), URIUtils.escape(odataClient.getServiceVersion(), param.getValue()));
}
try {
((HttpRequestBase) this.request).setURI(uriBuilder.build());

View File

@ -27,7 +27,11 @@ import java.net.URI;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;
import javax.xml.datatype.Duration;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
@ -67,6 +71,8 @@ public final class URIUtils {
*/
private static final Logger LOG = LoggerFactory.getLogger(URIUtils.class);
private static final Pattern ENUM_VALUE = Pattern.compile("(.+\\.)?.+'.+'");
private URIUtils() {
// Empty private constructor for static utility classes
}
@ -274,53 +280,102 @@ public final class URIUtils {
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null), Constants.UTF8));
}
private static String quoteString(final String string, final boolean singleQuoteEscape)
throws UnsupportedEncodingException {
final String encoded = URLEncoder.encode(string, Constants.UTF8);
return ENUM_VALUE.matcher(string).matches()
? encoded
: singleQuoteEscape
? "'" + encoded + "'"
: "\"" + encoded + "\"";
}
/**
* Turns primitive values into their respective URI representation.
*
* @param version OData protocol version
* @param obj primitive value
* @return URI representation
*/
public static String escape(final ODataServiceVersion version, final Object obj) {
return escape(version, obj, true);
}
private static String escape(final ODataServiceVersion version, final Object obj, final boolean singleQuoteEscape) {
String value;
try {
value = (obj instanceof Boolean)
? BooleanUtils.toStringTrueFalse((Boolean) obj)
: (obj instanceof UUID)
? prefix(version, EdmPrimitiveTypeKind.Guid)
+ obj.toString()
+ suffix(version, EdmPrimitiveTypeKind.Guid)
: (obj instanceof byte[])
? EdmBinary.getInstance().toUriLiteral(Hex.encodeHexString((byte[]) obj))
: (obj instanceof Timestamp)
? timestamp(version, (Timestamp) obj)
: (obj instanceof Calendar)
? calendar(version, (Calendar) obj)
: (obj instanceof Duration)
? duration(version, (Duration) obj)
: (obj instanceof BigDecimal)
? EdmDecimal.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Decimal)
: (obj instanceof Double)
? EdmDouble.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Double)
: (obj instanceof Float)
? EdmSingle.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Single)
: (obj instanceof Long)
? EdmInt64.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Int64)
: (obj instanceof Geospatial)
? URLEncoder.encode(EdmPrimitiveTypeFactory.getInstance(((Geospatial) obj).getEdmPrimitiveTypeKind()).
valueToString(obj, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null),
Constants.UTF8)
: (obj instanceof String)
? "'" + URLEncoder.encode((String) obj, Constants.UTF8) + "'"
: obj.toString();
if (obj == null) {
value = Constants.ATTR_NULL;
} else if (version == ODataServiceVersion.V40 && obj instanceof Collection) {
final StringBuffer buffer = new StringBuffer("[");
for (@SuppressWarnings("unchecked")
final Iterator<Object> itor = ((Collection<Object>) obj).iterator(); itor.hasNext();) {
buffer.append(escape(version, itor.next(), false));
if (itor.hasNext()) {
buffer.append(',');
}
}
buffer.append(']');
value = buffer.toString();
} else if (version == ODataServiceVersion.V40 && obj instanceof Map) {
final StringBuffer buffer = new StringBuffer("{");
for (@SuppressWarnings("unchecked")
final Iterator<Map.Entry<Object, Object>> itor =
((Map<Object, Object>) obj).entrySet().iterator(); itor.hasNext();) {
final Map.Entry<Object, Object> entry = itor.next();
buffer.append("\"").append(URLEncoder.encode(entry.getKey().toString(), Constants.UTF8)).append("\"");
buffer.append(':').append(escape(version, entry.getValue(), false));
if (itor.hasNext()) {
buffer.append(',');
}
}
buffer.append('}');
value = buffer.toString();
} else {
value = (obj instanceof Boolean)
? BooleanUtils.toStringTrueFalse((Boolean) obj)
: (obj instanceof UUID)
? prefix(version, EdmPrimitiveTypeKind.Guid)
+ obj.toString()
+ suffix(version, EdmPrimitiveTypeKind.Guid)
: (obj instanceof byte[])
? EdmBinary.getInstance().toUriLiteral(Hex.encodeHexString((byte[]) obj))
: (obj instanceof Timestamp)
? timestamp(version, (Timestamp) obj)
: (obj instanceof Calendar)
? calendar(version, (Calendar) obj)
: (obj instanceof Duration)
? duration(version, (Duration) obj)
: (obj instanceof BigDecimal)
? EdmDecimal.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Decimal)
: (obj instanceof Double)
? EdmDouble.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Double)
: (obj instanceof Float)
? EdmSingle.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Single)
: (obj instanceof Long)
? EdmInt64.getInstance().valueToString(obj, null, null,
Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null)
+ suffix(version, EdmPrimitiveTypeKind.Int64)
: (obj instanceof Geospatial)
? URLEncoder.encode(EdmPrimitiveTypeFactory.getInstance(((Geospatial) obj).getEdmPrimitiveTypeKind()).
valueToString(obj, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null),
Constants.UTF8)
: (obj instanceof String)
? quoteString((String) obj, singleQuoteEscape)
: obj.toString();
}
} catch (Exception e) {
LOG.warn("While escaping '{}', using toString()", obj, e);
value = obj.toString();

View File

@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.olingo.client.core.uri;
import static org.junit.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Collections;
import org.apache.olingo.client.core.edm.EdmEnumTypeImpl;
import org.apache.olingo.client.core.edm.xml.v4.EnumTypeImpl;
import org.apache.olingo.commons.api.Constants;
import org.apache.olingo.commons.api.edm.EdmEnumType;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.apache.olingo.commons.api.edm.geo.Geospatial;
import org.apache.olingo.commons.api.edm.geo.Point;
import org.junit.Test;
public class URIEscapeTest {
@Test
public void _null() {
assertEquals("null", URIUtils.escape(ODataServiceVersion.V40, null));
}
@Test
public void _boolean() {
assertEquals("true", URIUtils.escape(ODataServiceVersion.V40, Boolean.TRUE));
}
@Test
public void _enum() throws UnsupportedEncodingException {
final EdmEnumType pattern = new EdmEnumTypeImpl(ODataServiceVersion.V40,
null, new FullQualifiedName("Sales", "Pattern"), new EnumTypeImpl());
assertEquals(URLEncoder.encode("Sales.Pattern'Yellow'", Constants.UTF8),
URIUtils.escape(ODataServiceVersion.V40, pattern.toUriLiteral("Yellow")));
}
@Test
public void geospatial() throws UnsupportedEncodingException {
final Point point = new Point(Geospatial.Dimension.GEOGRAPHY, 0);
point.setX(142.1);
point.setY(64.1);
assertEquals(URLEncoder.encode("geography'SRID=0;Point(142.1 64.1)'", Constants.UTF8),
URIUtils.escape(ODataServiceVersion.V40, point));
}
@Test
public void collection() {
assertEquals("[\"red\",\"green\"]",
URIUtils.escape(ODataServiceVersion.V40, Arrays.asList(new String[] {"red", "green"})));
}
@Test
public void complex() {
assertEquals("{\"Name\":\"Value\"}",
URIUtils.escape(ODataServiceVersion.V40, Collections.singletonMap("Name", "Value")));
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.core.v3;
package org.apache.olingo.client.core.uri.v3;
import org.apache.olingo.client.api.v3.ODataClient;
import org.apache.olingo.client.api.uri.URIFilter;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.core.v3;
package org.apache.olingo.client.core.uri.v3;
import static org.junit.Assert.assertEquals;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.core.v4;
package org.apache.olingo.client.core.uri.v4;
import org.apache.olingo.client.api.v4.ODataClient;
import org.apache.olingo.client.api.uri.URIFilter;

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.client.core.v4;
package org.apache.olingo.client.core.uri.v4;
import java.net.URI;
import java.net.URISyntaxException;