Author: sergeyb
Date: Wed Dec 12 22:22:08 2012
New Revision: 1421027
URL: http://svn.apache.org/viewvc?rev=1421027&view=rev
Log:
Prototyping the implementation of new and messy replaceTemplate and co methods
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java?rev=1421027&r1=1421026&r2=1421027&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriBuilderImpl.java
Wed Dec 12 22:22:08 2012
@@ -23,9 +23,11 @@ import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -54,6 +56,10 @@ public class UriBuilderImpl extends UriB
private MultivaluedMap<String, String> query = new MetadataMap<String,
String>();
private MultivaluedMap<String, String> matrix = new MetadataMap<String,
String>();
+ private Map<String, Object> resolvedTemplates;
+ private Map<String, Object> resolvedTemplatesPathEnc;
+ private Map<String, Object> resolvedEncodedTemplates;
+
/**
* Creates builder with empty URI.
*/
@@ -75,37 +81,64 @@ public class UriBuilderImpl extends UriB
return doBuild(false, true, values);
}
+ private static Map<String, Object> getResolvedTemplates(Map<String,
Object> rtemplates) {
+ return rtemplates == null
+ ? Collections.<String, Object>emptyMap() : new
LinkedHashMap<String, Object>(rtemplates);
+ }
+
private URI doBuild(boolean fromEncoded, boolean encodePathSlash,
Object... values) {
+ UriParts parts = doBuildUriParts(fromEncoded, encodePathSlash, values);
+ try {
+ return buildURI(fromEncoded, parts.path, parts.query,
parts.fragment);
+ } catch (URISyntaxException ex) {
+ throw new UriBuilderException("URI can not be built", ex);
+ }
+ }
+
+ private UriParts doBuildUriParts(boolean fromEncoded, boolean
encodePathSlash, Object... values) {
+
+ Map<String, Object> alreadyResolvedTs =
getResolvedTemplates(resolvedTemplates);
+ Map<String, Object> alreadyResolvedTsPathEnc =
getResolvedTemplates(resolvedTemplatesPathEnc);
+ Map<String, Object> alreadyResolvedEncTs =
getResolvedTemplates(resolvedEncodedTemplates);
+ final int resolvedTsSize = alreadyResolvedTs.size()
+ + alreadyResolvedEncTs.size()
+ + alreadyResolvedTsPathEnc.size();
String thePath = buildPath(fromEncoded);
URITemplate pathTempl = new URITemplate(thePath);
- thePath = substituteVarargs(pathTempl, values, 0, encodePathSlash);
+ thePath = substituteVarargs(pathTempl, alreadyResolvedTs,
alreadyResolvedTsPathEnc,
+ alreadyResolvedEncTs, values, 0, false,
fromEncoded, encodePathSlash);
+ int pathTemplateVarsSize = pathTempl.getVariables().size();
String theQuery = buildQuery(fromEncoded);
int queryTemplateVarsSize = 0;
if (theQuery != null) {
URITemplate queryTempl = new URITemplate(theQuery);
- int lengthDiff = values.length - pathTempl.getVariables().size();
+ int lengthDiff = values.length + resolvedTsSize
+ - alreadyResolvedTs.size() - alreadyResolvedTsPathEnc.size() -
alreadyResolvedEncTs.size()
+ - pathTemplateVarsSize;
if (lengthDiff > 0) {
- queryTemplateVarsSize = queryTempl.getVariables().size();
- theQuery = substituteVarargs(queryTempl, values, values.length
- lengthDiff, false);
+ queryTemplateVarsSize = queryTempl.getVariables().size();
+ theQuery = substituteVarargs(queryTempl, alreadyResolvedTs,
alreadyResolvedTsPathEnc,
+ alreadyResolvedEncTs, values,
values.length - lengthDiff,
+ true, fromEncoded, false);
}
}
String theFragment = fragment;
if (theFragment != null) {
URITemplate fragmentTempl = new URITemplate(theFragment);
- int lengthDiff = values.length - pathTempl.getVariables().size() -
queryTemplateVarsSize;
+ int lengthDiff = values.length + resolvedTsSize
+ - alreadyResolvedTs.size() - alreadyResolvedTsPathEnc.size() -
alreadyResolvedEncTs.size()
+ - pathTemplateVarsSize - queryTemplateVarsSize;
if (lengthDiff > 0) {
- theFragment = substituteVarargs(fragmentTempl, values,
values.length - lengthDiff, false);
+ theFragment = substituteVarargs(fragmentTempl,
alreadyResolvedTs, alreadyResolvedTsPathEnc,
+ alreadyResolvedEncTs, values,
values.length - lengthDiff,
+ true, fromEncoded, false);
}
}
- try {
- return buildURI(fromEncoded, thePath, theQuery, theFragment);
- } catch (URISyntaxException ex) {
- throw new UriBuilderException("URI can not be built", ex);
- }
+ return new UriParts(thePath, theQuery, theFragment);
}
private URI buildURI(boolean fromEncoded, String thePath, String theQuery,
String theFragment)
@@ -211,61 +244,124 @@ public class UriBuilderImpl extends UriB
boolean encodePathSlash)
throws IllegalArgumentException, UriBuilderException {
try {
+ Map<String, Object> alreadyResolvedTs =
getResolvedTemplates(resolvedTemplates);
+ Map<String, Object> alreadyResolvedTsPathEnc =
getResolvedTemplates(resolvedTemplatesPathEnc);
+ Map<String, Object> alreadyResolvedEncTs =
getResolvedTemplates(resolvedEncodedTemplates);
+
String thePath = buildPath(fromEncoded);
- thePath = substituteMapped(thePath, map, encodePathSlash);
+ thePath = substituteMapped(thePath, map, alreadyResolvedTs,
alreadyResolvedTsPathEnc,
+ alreadyResolvedEncTs, false,
fromEncoded, encodePathSlash);
String theQuery = buildQuery(fromEncoded);
if (theQuery != null) {
- theQuery = substituteMapped(theQuery, map, false);
+ theQuery = substituteMapped(theQuery, map, alreadyResolvedTs,
alreadyResolvedTsPathEnc,
+ alreadyResolvedEncTs, true,
fromEncoded, false);
}
String theFragment = fragment == null
- ? null : substituteMapped(fragment, map, encodePathSlash);
+ ? null : substituteMapped(fragment, map, alreadyResolvedTs,
alreadyResolvedTsPathEnc,
+ alreadyResolvedEncTs, true,
fromEncoded, encodePathSlash);
return buildURI(fromEncoded, thePath, theQuery, theFragment);
} catch (URISyntaxException ex) {
throw new UriBuilderException("URI can not be built", ex);
}
}
-
+ //CHECKSTYLE:OFF
private String substituteVarargs(URITemplate templ,
+ Map<String, Object> alreadyResolvedTs,
+ Map<String, Object>
alreadyResolvedTsPathEnc,
+ Map<String, Object> alreadyResolvedTsEnc,
Object[] values,
int ind,
+ boolean isQuery,
+ boolean fromEncoded,
boolean encodePathSlash) {
+ //CHECKSTYLE:ON
Map<String, String> varValueMap = new HashMap<String, String>();
// vars in set are properly ordered due to linking in hash set
Set<String> uniqueVars = new
LinkedHashSet<String>(templ.getVariables());
- if (values.length < uniqueVars.size()) {
+ if (values.length + alreadyResolvedTs.size() +
alreadyResolvedTsEnc.size()
+ + alreadyResolvedTsPathEnc.size() < uniqueVars.size()) {
throw new IllegalArgumentException("Unresolved variables; only " +
values.length
+ " value(s) given for " +
uniqueVars.size()
+ " unique variable(s)");
}
int idx = ind;
+ Set<String> pathEncodeVars = alreadyResolvedTsPathEnc.isEmpty() &&
!encodePathSlash
+ ? Collections.<String>emptySet() : new HashSet<String>();
for (String var : uniqueVars) {
- Object oval = values[idx++];
+
+ boolean isPathEncVar = !isQuery &&
alreadyResolvedTsPathEnc.containsKey(var);
+
+ boolean isVarEncoded = isPathEncVar ||
alreadyResolvedTs.containsKey(var) ? false : true;
+ Map<String, Object> resolved = isVarEncoded ? alreadyResolvedTsEnc
+ : isPathEncVar ? alreadyResolvedTsPathEnc : alreadyResolvedTs;
+ Object oval = resolved.isEmpty() ? null : resolved.remove(var);
+ if (oval == null) {
+ oval = values[idx++];
+ } else if (fromEncoded) {
+ oval = HttpUtils.encodePartiallyEncoded(oval.toString(),
isQuery);
+ }
if (oval == null) {
throw new IllegalArgumentException("No object for " + var);
}
String value = oval.toString();
varValueMap.put(var, value);
+
+ if (!isQuery && (isPathEncVar || encodePathSlash)) {
+ pathEncodeVars.add(var);
+ }
}
- return templ.substitute(varValueMap, encodePathSlash);
+ return templ.substitute(varValueMap, pathEncodeVars);
}
+ //CHECKSTYLE:OFF
private String substituteMapped(String path,
Map<String, ? extends Object> varValueMap,
+ Map<String, Object> alreadyResolvedTs,
+ Map<String, Object>
alreadyResolvedTsPathEnc,
+ Map<String, Object> alreadyResolvedTsEnc,
+ boolean isQuery,
+ boolean fromEncoded,
boolean encodePathSlash) {
-
+ //CHECKSTYLE:ON
URITemplate templ = new URITemplate(path);
Set<String> uniqueVars = new HashSet<String>(templ.getVariables());
- if (varValueMap.size() < uniqueVars.size()) {
+ if (varValueMap.size() + alreadyResolvedTs.size() +
alreadyResolvedTsEnc.size()
+ + alreadyResolvedTsPathEnc.size() < uniqueVars.size()) {
throw new IllegalArgumentException("Unresolved variables; only " +
varValueMap.size()
+ " value(s) given for " +
uniqueVars.size()
+ " unique variable(s)");
}
- return templ.substitute(varValueMap, encodePathSlash);
+
+ Set<String> pathEncodeVars = alreadyResolvedTsPathEnc.isEmpty() &&
!encodePathSlash
+ ? Collections.<String>emptySet() : new HashSet<String>();
+
+ Map<String, Object> theMap = new LinkedHashMap<String, Object>();
+ for (String var : uniqueVars) {
+ boolean isPathEncVar = !isQuery &&
alreadyResolvedTsPathEnc.containsKey(var);
+
+ boolean isVarEncoded = isPathEncVar ||
alreadyResolvedTs.containsKey(var) ? false : true;
+ Map<String, Object> resolved = isVarEncoded ? alreadyResolvedTsEnc
+ : isPathEncVar ? alreadyResolvedTsPathEnc : alreadyResolvedTs;
+ Object oval = resolved.isEmpty() ? null : resolved.remove(var);
+ if (oval == null) {
+ oval = varValueMap.get(var);
+ } else if (fromEncoded) {
+ oval = HttpUtils.encodePartiallyEncoded(oval.toString(),
isQuery);
+ }
+ if (oval == null) {
+ throw new IllegalArgumentException("No object for " + var);
+ }
+ theMap.put(var, oval);
+ if (!isQuery && (isPathEncVar || encodePathSlash)) {
+ pathEncodeVars.add(var);
+ }
+ }
+ return templ.substitute(theMap, pathEncodeVars);
}
@Override
@@ -760,9 +856,8 @@ public class UriBuilderImpl extends UriB
@Override
public String toTemplate() {
- final String thePath = buildPath(true);
- final String theQuery = buildQuery(true);
- return buildUriString(thePath, theQuery, fragment);
+ UriParts parts = doBuildUriParts(false, false);
+ return buildUriString(parts.path, parts.query, parts.fragment);
}
public UriBuilder resolveTemplate(String name, Object value) throws
IllegalArgumentException {
@@ -771,11 +866,7 @@ public class UriBuilderImpl extends UriB
public UriBuilder resolveTemplate(String name, Object value, boolean
encodePathSlash)
throws IllegalArgumentException {
- throw new UnsupportedOperationException();
- }
-
- public UriBuilder resolveTemplateFromEncoded(String name, Object value)
throws IllegalArgumentException {
- throw new UnsupportedOperationException();
+ return resolveTemplates(Collections.singletonMap(name, value),
encodePathSlash);
}
public UriBuilder resolveTemplates(Map<String, Object> values) throws
IllegalArgumentException {
@@ -784,12 +875,51 @@ public class UriBuilderImpl extends UriB
public UriBuilder resolveTemplates(Map<String, Object> values, boolean
encodePathSlash)
throws IllegalArgumentException {
- throw new UnsupportedOperationException();
+ if (encodePathSlash) {
+ resolvedTemplatesPathEnc =
fillInResolveTemplates(resolvedTemplatesPathEnc, values);
+ } else {
+ resolvedTemplates = fillInResolveTemplates(resolvedTemplates,
values);
+ }
+ return this;
+ }
+
+ public UriBuilder resolveTemplateFromEncoded(String name, Object value)
throws IllegalArgumentException {
+ return resolveTemplatesFromEncoded(Collections.singletonMap(name,
value));
}
public UriBuilder resolveTemplatesFromEncoded(Map<String, Object> values)
throws IllegalArgumentException {
- throw new UnsupportedOperationException();
+ resolvedEncodedTemplates =
fillInResolveTemplates(resolvedEncodedTemplates, values);
+ return this;
+ }
+
+ private static Map<String, Object> fillInResolveTemplates(Map<String,
Object> map, Map<String, Object> values)
+ throws IllegalArgumentException {
+ if (values == null) {
+ throw new IllegalArgumentException();
+ }
+ if (map == null) {
+ map = new LinkedHashMap<String, Object>();
+ }
+
+ for (Map.Entry<String, Object> entry : values.entrySet()) {
+ if (entry.getKey() == null || entry.getValue() == null) {
+ throw new IllegalArgumentException();
+ }
+ map.put(entry.getKey(), entry.getValue());
+ }
+ return map;
}
+ private class UriParts {
+ String path;
+ String query;
+ String fragment;
+
+ public UriParts(String path, String query, String fragment) {
+ this.path = path;
+ this.query = query;
+ this.fragment = fragment;
+ }
+ }
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java?rev=1421027&r1=1421026&r2=1421027&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
Wed Dec 12 22:22:08 2012
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -249,7 +250,7 @@ public final class URITemplate {
}
public String substitute(Map<String, ? extends Object> valuesMap) throws
IllegalArgumentException {
- return this.substitute(valuesMap, false);
+ return this.substitute(valuesMap, Collections.<String>emptySet());
}
/**
@@ -265,7 +266,7 @@ public final class URITemplate {
* @return template with bound variables.
*/
public String substitute(Map<String, ? extends Object> valuesMap,
- boolean encodePathSlash) throws
IllegalArgumentException {
+ Set<String> encodePathSlashVars) throws
IllegalArgumentException {
if (valuesMap == null) {
throw new IllegalArgumentException("valuesMap is null");
}
@@ -281,7 +282,7 @@ public final class URITemplate {
+ var.getName() + "
with pattern "
+ var.getPattern());
}
- if (encodePathSlash) {
+ if (encodePathSlashVars.contains(var.getName())) {
sval = sval.replaceAll("/", "%2F");
}
sb.append(sval);
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java?rev=1421027&r1=1421026&r2=1421027&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriBuilderImplTest.java
Wed Dec 12 22:22:08 2012
@@ -40,6 +40,62 @@ import org.junit.Test;
public class UriBuilderImplTest extends Assert {
@Test
+ public void testResolveTemplate() {
+ URI uri;
+ uri =
((UriBuilderImpl)UriBuilder.fromPath("/{a}")).resolveTemplate("a", "1").build();
+ assertEquals("/1", uri.toString());
+ }
+
+ @Test
+ public void testResolveTemplate2() {
+ URI uri;
+ uri =
((UriBuilderImpl)UriBuilder.fromPath("/{a}/{b}")).resolveTemplate("a",
"1").build("2");
+ assertEquals("/1/2", uri.toString());
+ }
+
+ @Test
+ public void testResolveTemplate3() {
+ URI uri;
+ uri =
((UriBuilderImpl)UriBuilder.fromPath("/{a}/{b}")).resolveTemplate("b",
"1").build("2");
+ assertEquals("/2/1", uri.toString());
+ }
+
+ @Test
+ public void testResolveTemplate4() {
+ URI uri;
+ uri = ((UriBuilderImpl)UriBuilder.fromPath("/{a}/{b}").queryParam("c",
"{c}"))
+ .resolveTemplate("a", "1").build("2", "3");
+ assertEquals("/1/2?c=3", uri.toString());
+ }
+
+ @Test
+ public void testResolveTemplate5() {
+ Map<String, Object> templs = new HashMap<String, Object>();
+ templs.put("a", "1");
+ templs.put("b", "2");
+ URI uri;
+ uri = ((UriBuilderImpl)UriBuilder.fromPath("/{a}/{b}").queryParam("c",
"{c}"))
+ .resolveTemplates(templs).build("3");
+ assertEquals("/1/2?c=3", uri.toString());
+ }
+
+
+ @Test
+ public void testResolveTemplateFromEncoded() {
+ URI uri;
+ uri =
((UriBuilderImpl)UriBuilder.fromPath("/{a}")).resolveTemplate("a", "%20
").buildFromEncoded();
+ assertEquals("/%20%20", uri.toString());
+ }
+
+ @Test
+ public void testResolveTemplateFromMap() {
+ URI uri;
+ uri =
((UriBuilderImpl)UriBuilder.fromPath("/{a}/{b}")).resolveTemplate("a", "1")
+ .buildFromMap(Collections.singletonMap("b", "2"));
+ assertEquals("/1/2", uri.toString());
+ }
+
+ @Test
public void testQueryParamWithTemplateValues() {
URI uri;
uri = UriBuilder.fromPath("/index.jsp").queryParam("a",
"{a}").queryParam("b", "{b}")
@@ -957,6 +1013,16 @@ public class UriBuilderImplTest extends
}
@Test
+ public void testToTemplateAndResolved() {
+ Map<String, Object> templs = new HashMap<String, Object>();
+ templs.put("a", "1");
+ templs.put("b", "2");
+ String template =
((UriBuilderImpl)UriBuilder.fromPath("/{a}/{b}").queryParam("c", "{c}"))
+ .resolveTemplates(templs).toTemplate();
+ assertEquals("/1/2?c={c}", template);
+ }
+
+ @Test
public void testSegments4() {
String path1 = "ab";
String[] path2 = {"a1", "{xy}", "3b "};