Author: ivaynberg
Date: Sun Nov 1 17:12:13 2009
New Revision: 831710
URL: http://svn.apache.org/viewvc?rev=831710&view=rev
Log:
optimization tweaks for Url
Modified:
wicket/trunk/wicket/.settings/org.eclipse.jdt.core.prefs
wicket/trunk/wicket/.settings/org.eclipse.jdt.ui.prefs
wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java
Modified: wicket/trunk/wicket/.settings/org.eclipse.jdt.core.prefs
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/.settings/org.eclipse.jdt.core.prefs?rev=831710&r1=831709&r2=831710&view=diff
==============================================================================
--- wicket/trunk/wicket/.settings/org.eclipse.jdt.core.prefs (original)
+++ wicket/trunk/wicket/.settings/org.eclipse.jdt.core.prefs Sun Nov 1
17:12:13 2009
@@ -1,4 +1,4 @@
-#Wed Sep 10 11:28:56 PDT 2008
+#Sun Oct 25 10:35:43 PDT 2009
eclipse.preferences.version=1
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
@@ -97,15 +97,15 @@
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=20
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=48
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=80
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=64
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=64
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
@@ -146,9 +146,9 @@
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.jdt.core.formatter.comment.line_length=100
+org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=1
+org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
@@ -163,6 +163,9 @@
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do
not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do
not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do
not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
@@ -331,19 +334,21 @@
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do
not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do
not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do
not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=100
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=2
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error
Modified: wicket/trunk/wicket/.settings/org.eclipse.jdt.ui.prefs
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/.settings/org.eclipse.jdt.ui.prefs?rev=831710&r1=831709&r2=831710&view=diff
==============================================================================
--- wicket/trunk/wicket/.settings/org.eclipse.jdt.ui.prefs (original)
+++ wicket/trunk/wicket/.settings/org.eclipse.jdt.ui.prefs Sun Nov 1 17:12:13
2009
@@ -1,4 +1,4 @@
-#Wed Aug 01 11:37:07 CEST 2007
+#Sun Oct 25 10:35:43 PDT 2009
comment_clear_blank_lines=false
comment_format_comments=true
comment_format_header=true
@@ -11,7 +11,7 @@
comment_separate_root_tags=true
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
-formatter_profile=_wicket
+formatter_profile=_Wicket
formatter_settings_version=11
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0"
encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false"
context\="gettercomment_context" deleted\="false" description\="Comment for
getter method" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment"
name\="gettercomment">/**\r\n * Gets ${bare_field_name}.\r\n * @return
${bare_field_name}\r\n */</template><template autoinsert\="false"
context\="settercomment_context" deleted\="false" description\="Comment for
setter method" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.settercomment"
name\="settercomment">/**\r\n * Sets ${bare_field_name}.\r\n * @param ${param}
${bare_field_name}\r\n */</template><template autoinsert\="false"
context\="constructorcomment_context" deleted\="false" description\="Comment
for created constructors" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment"
name\="constructorcomment">/**\r\n * Construct.\r\n
* ${tags}\r\n */</template><template autoinsert\="false"
context\="filecomment_context" deleted\="false" description\="Comment for
created Java files" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.filecomment"
name\="filecomment"/><template autoinsert\="false"
context\="typecomment_context" deleted\="false" description\="Comment for
created types" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.typecomment"
name\="typecomment">/**\r\n * @author ${user}\r\n * ${tags}\r\n
*/</template><template autoinsert\="true" context\="fieldcomment_context"
deleted\="false" description\="Comment for fields" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment"
name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true"
context\="methodcomment_context" deleted\="false" description\="Comment for
non-overriding methods" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment"
name\="methodcomment">/**\r\n * ${tags}
\r\n */</template><template autoinsert\="false"
context\="overridecomment_context" deleted\="false" description\="Comment for
overriding methods" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment"
name\="overridecomment">/**\r\n * ${see_to_overridden}\r\n
*/</template><template autoinsert\="false" context\="newtype_context"
deleted\="false" description\="Newly created files" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">/*\r\n *
Licensed to the Apache Software Foundation (ASF) under one or more\r\n *
contributor license agreements. See the NOTICE file distributed with\r\n *
this work for additional information regarding copyright ownership.\r\n * The
ASF licenses this file to You under the Apache License, Version 2.0\r\n * (the
"License"); you may not use this file except in compliance with\r\n * the
License. You may obtain a copy of the License at\r\n *\r\n *
http\://www.apache.org/licenses/LICENSE-2.0\r\
n *\r\n * Unless required by applicable law or agreed to in writing,
software\r\n * distributed under the License is distributed on an "AS IS"
BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.\r\n * See the License for the specific language governing permissions
and\r\n * limitations under the License.\r\n
*/\r\n${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template
autoinsert\="false" context\="catchblock_context" deleted\="false"
description\="Code in new catch blocks" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">throw
new RuntimeException(${exception_var});</template><template autoinsert\="false"
context\="methodbody_context" deleted\="false" description\="Code in created
method stubs" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.methodbody"
name\="methodbody">${body_statement}</template><template autoinsert\="false"
context\="c
onstructorbody_context" deleted\="false" description\="Code in created
constructor stubs" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody"
name\="constructorbody">${body_statement}</template><template
autoinsert\="true" context\="getterbody_context" deleted\="false"
description\="Code in created getters" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.getterbody"
name\="getterbody">return ${field};</template><template autoinsert\="true"
context\="setterbody_context" deleted\="false" description\="Code in created
setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody"
name\="setterbody">${field} \= ${param};</template><template autoinsert\="true"
context\="classbody_context" deleted\="false" description\="Code in new class
type bodies" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.classbody"
name\="classbody">\r\n</template><template autoinsert\="true"
context\="interfacebody_context" deleted\="false"
description\="Code in new interface type bodies" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody"
name\="interfacebody">\r\n</template><template autoinsert\="true"
context\="enumbody_context" deleted\="false" description\="Code in new enum
type bodies" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.enumbody"
name\="enumbody">\r\n</template><template autoinsert\="true"
context\="annotationbody_context" deleted\="false" description\="Code in new
annotation type bodies" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody"
name\="annotationbody">\r\n</template><template autoinsert\="true"
context\="delegatecomment_context" deleted\="false" description\="Comment for
delegate methods" enabled\="true"
id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment"
name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n
*/</template></templates>
Modified:
wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java?rev=831710&r1=831709&r2=831710&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java
(original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java Sun
Nov 1 17:12:13 2009
@@ -46,433 +46,439 @@
* an additional slash, i.e. //
* </pre>
*
- * The Url class takes care of encoding and decoding of the segments and
parameters.
+ * The Url class takes care of encoding and decoding of the segments and
+ * parameters.
*
* @author Matej Knopp
* @author Igor Vaynberg
*/
public final class Url implements Serializable
{
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- private final List<String> segments = new ArrayList<String>();
+ private final List<String> segments = new ArrayList<String>();
- private List<QueryParameter> parameters = new ArrayList<QueryParameter>();
+ private final List<QueryParameter> parameters = new
ArrayList<QueryParameter>();
- /**
- * Construct.
- */
- public Url()
- {
- }
-
- /**
- * Construct.
- *
- * @param url
- * url being copied
- */
- public Url(Url url)
- {
- Checks.argumentNotNull(url, "url");
-
- segments.addAll(url.getSegments());
- parameters.addAll(url.getQueryParameters());
- }
-
- /**
- * Construct.
- *
- * @param segments
- * @param parameters
- */
- public Url(List<String> segments, List<QueryParameter> parameters)
- {
- Checks.argumentNotNull(segments, "segments");
- Checks.argumentNotNull(parameters, "parameters");
-
- this.segments.addAll(segments);
- this.parameters.addAll(parameters);
- }
-
- /**
- * Returns segments of the URL. Segments form the part before query string.
- *
- * @return mutable list of segments
- */
- public List<String> getSegments()
- {
- return segments;
- }
-
- /**
- * Returns query parameters of the URL.
- *
- * @return mutable list of query parameters
- */
- public List<QueryParameter> getQueryParameters()
- {
- return parameters;
- }
-
- /**
- * Returns whether the URL is absolute.
- *
- * @return <code>true</code> if URL is absolute, <code>false</code>
otherwise.
- */
- public boolean isAbsolute()
- {
- return !getSegments().isEmpty() &&
Strings.isEmpty(getSegments().get(0));
- }
-
- /**
- * Convenience method that removes all query parameters with given name.
- *
- * @param name
- * query parameter name
- */
- public void removeQueryParameters(String name)
- {
- for (Iterator<QueryParameter> i = getQueryParameters().iterator();
i.hasNext();)
- {
- QueryParameter param = i.next();
- if (Objects.equal(name, param.getName()))
- {
- i.remove();
- }
- }
- }
-
- /**
- * Convenience method that removes <code>count</code> leading segments
- *
- * @param count
- */
- public void removeLeadingSegments(int count)
- {
- Checks.argumentWithinRange(0, segments.size(), count, "count");
- for (int i = 0; i < count; i++)
- {
- segments.remove(0);
- }
- }
-
- /**
- * Convenience method that prepends <code>segments</code> to the segments
collection
- *
- * @param newSegments
- */
- public void prependLeadingSegments(List<String> newSegments)
- {
- Checks.argumentNotNull(newSegments, "segments");
- segments.addAll(0, newSegments);
- }
-
- /**
- * Convenience method that removes all query parameters with given name
and adds new query
- * parameter with specified name and value
- *
- * @param name
- * @param value
- */
- public void setQueryParameter(String name, Object value)
- {
- removeQueryParameters(name);
- if (value != null)
- {
- QueryParameter parameter = new QueryParameter(name,
value.toString());
- getQueryParameters().add(parameter);
- }
- }
-
- /**
- * Returns first query parameter with specified name or null if such query
parameter doesn't
- * exist.
- *
- * @param name
- * @return query parameter or <code>null</code>
- */
- public QueryParameter getQueryParameter(String name)
- {
- for (QueryParameter parameter : parameters)
- {
- if (Objects.equal(name, parameter.getName()))
- {
- return parameter;
- }
- }
- return null;
- }
-
- /**
- * Returns the value of first query parameter with specified name. Note
that this method never
- * returns <code>null</code>. Not even if the parameter does not exist.
- *
- * @see StringValue#isNull()
- *
- * @param name
- * @return {...@link StringValue} instance wrapping the parameter value
- */
- public StringValue getQueryParameterValue(String name)
- {
- QueryParameter parameter = getQueryParameter(name);
- if (parameter == null)
- {
- return StringValue.valueOf((String)null);
- }
- else
- {
- return StringValue.valueOf(parameter.getValue());
- }
- }
-
- /**
- * Represents a single query parameter
- *
- * @author Matej Knopp
- */
- public final static class QueryParameter
- {
- private final String name;
- private final String value;
-
- /**
- * Creates new {...@link QueryParameter} instance. The
<code>name</code> and <code>value</code>
- * parameters must not be <code>null</code>, though they can be empty
strings.
- *
- * @param name
- * parameter name
- * @param value
- * parameter value
- */
- public QueryParameter(String name, String value)
- {
- Checks.argumentNotNull(name, "name");
- Checks.argumentNotNull(value, "value");
-
- this.name = name;
- this.value = value;
- }
-
- /**
- * Returns query parameter name.
- *
- * @return query parameter name
- */
- public String getName()
- {
- return name;
- }
-
- /**
- * Returns query parameter value.
- *
- * @return query parameter value
- */
- public String getValue()
- {
- return value;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj instanceof QueryParameter == false)
- {
- return false;
- }
- QueryParameter rhs = (QueryParameter)obj;
- return Objects.equal(this.getName(), rhs.getName()) &&
- Objects.equal(this.getValue(), rhs.getValue());
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hashCode(getName(), getValue());
- }
-
- @Override
- public String toString()
- {
- StringBuilder result = new StringBuilder();
- result.append(encodeParameter(getName()));
- if (!Strings.isEmpty(getValue()))
- {
- result.append('=');
- result.append(encodeParameter(getValue()));
- }
- return result.toString();
- }
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj instanceof Url == false)
- {
- return false;
- }
- Url rhs = (Url)obj;
-
- return getSegments().equals(rhs.getSegments()) &&
- getQueryParameters().equals(rhs.getQueryParameters());
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hashCode(getSegments(), getQueryParameters());
- }
-
- private static String encodeSegment(String string)
- {
- return WicketURLEncoder.PATH_INSTANCE.encode(string);
- }
-
- private static String decodeSegment(String string)
- {
- return WicketURLDecoder.PATH_INSTANCE.decode(string);
- }
-
- private static String encodeParameter(String string)
- {
- return WicketURLEncoder.QUERY_INSTANCE.encode(string);
- }
-
- private static String decodeParameter(String string)
- {
- return WicketURLDecoder.QUERY_INSTANCE.decode(string);
- }
-
- @Override
- public String toString()
- {
- StringBuilder result = new StringBuilder();
- boolean first = true;
- for (String s : getSegments())
- {
- if (!first)
- {
- result.append('/');
- }
- first = false;
- result.append(encodeSegment(s));
- }
-
- first = true;
-
- for (QueryParameter p : getQueryParameters())
- {
- if (first)
- {
- result.append("?");
- first = false;
- }
- else
- {
- result.append("&");
- }
- result.append(p.toString());
- }
-
- return result.toString();
- }
-
- private static QueryParameter parseQueryParameter(String qp)
- {
- if (qp.indexOf('=') == -1)
- {
- return new QueryParameter(decodeParameter(qp), "");
- }
- String parts[] = qp.split("=");
- if (parts.length == 0)
- {
- return new QueryParameter("", "");
- }
- else if (parts.length == 1)
- {
- return new QueryParameter("", decodeParameter(parts[0]));
- }
- else
- {
- return new QueryParameter(decodeParameter(parts[0]),
decodeParameter(parts[1]));
- }
- }
-
- /**
- * Parses the given URL string.
- *
- * @param url
- * @return Url object
- */
- public static Url parse(String url)
- {
- Checks.argumentNotNull(url, "url");
-
- Url result = new Url();
-
- String segments;
- String query;
-
- int qIndex = url.indexOf('?');
-
- if (qIndex == -1)
- {
- segments = url;
- query = "";
- }
- else
- {
- segments = url.substring(0, qIndex);
- query = url.substring(qIndex + 1);
- }
-
- if (segments.length() > 0)
- {
-
- boolean removeLast = false;
- if (segments.endsWith("/"))
- {
- // we need to append something and remove it after splitting
because otherwise the
- // trailing slashes will be lost
- segments += "/x";
- removeLast = true;
- }
-
- String segmentArray[] = segments.split("/");
-
- if (removeLast)
- {
- segmentArray[segmentArray.length - 1] = null;
- }
-
- for (String s : segmentArray)
- {
- if (s != null)
- {
- result.segments.add(decodeSegment(s));
- }
- }
- }
-
- if (query.length() > 0)
- {
- String queryArray[] = query.split("&");
- for (String s : queryArray)
- {
- result.parameters.add(parseQueryParameter(s));
- }
- }
+ /**
+ * Construct.
+ */
+ public Url()
+ {
+ }
+
+ /**
+ * Construct.
+ *
+ * @param url
+ * url being copied
+ */
+ public Url(Url url)
+ {
+ Checks.argumentNotNull(url, "url");
+
+ segments.addAll(url.getSegments());
+ parameters.addAll(url.getQueryParameters());
+ }
+
+ /**
+ * Construct.
+ *
+ * @param segments
+ * @param parameters
+ */
+ public Url(List<String> segments, List<QueryParameter> parameters)
+ {
+ Checks.argumentNotNull(segments, "segments");
+ Checks.argumentNotNull(parameters, "parameters");
+
+ this.segments.addAll(segments);
+ this.parameters.addAll(parameters);
+ }
+
+ /**
+ * Returns segments of the URL. Segments form the part before query
string.
+ *
+ * @return mutable list of segments
+ */
+ public List<String> getSegments()
+ {
+ return segments;
+ }
+
+ /**
+ * Returns query parameters of the URL.
+ *
+ * @return mutable list of query parameters
+ */
+ public List<QueryParameter> getQueryParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Returns whether the URL is absolute.
+ *
+ * @return <code>true</code> if URL is absolute, <code>false</code>
+ * otherwise.
+ */
+ public boolean isAbsolute()
+ {
+ return !getSegments().isEmpty() &&
Strings.isEmpty(getSegments().get(0));
+ }
+
+ /**
+ * Convenience method that removes all query parameters with given name.
+ *
+ * @param name
+ * query parameter name
+ */
+ public void removeQueryParameters(String name)
+ {
+ for (Iterator<QueryParameter> i =
getQueryParameters().iterator(); i.hasNext();)
+ {
+ QueryParameter param = i.next();
+ if (Objects.equal(name, param.getName()))
+ {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * Convenience method that removes <code>count</code> leading segments
+ *
+ * @param count
+ */
+ public void removeLeadingSegments(int count)
+ {
+ Checks.argumentWithinRange(0, segments.size(), count, "count");
+ for (int i = 0; i < count; i++)
+ {
+ segments.remove(0);
+ }
+ }
+
+ /**
+ * Convenience method that prepends <code>segments</code> to the
segments
+ * collection
+ *
+ * @param newSegments
+ */
+ public void prependLeadingSegments(List<String> newSegments)
+ {
+ Checks.argumentNotNull(newSegments, "segments");
+ segments.addAll(0, newSegments);
+ }
+
+ /**
+ * Convenience method that removes all query parameters with given name
and
+ * adds new query parameter with specified name and value
+ *
+ * @param name
+ * @param value
+ */
+ public void setQueryParameter(String name, Object value)
+ {
+ removeQueryParameters(name);
+ if (value != null)
+ {
+ QueryParameter parameter = new QueryParameter(name,
value.toString());
+ getQueryParameters().add(parameter);
+ }
+ }
+
+ /**
+ * Returns first query parameter with specified name or null if such
query
+ * parameter doesn't exist.
+ *
+ * @param name
+ * @return query parameter or <code>null</code>
+ */
+ public QueryParameter getQueryParameter(String name)
+ {
+ for (QueryParameter parameter : parameters)
+ {
+ if (Objects.equal(name, parameter.getName()))
+ {
+ return parameter;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the value of first query parameter with specified name. Note
that
+ * this method never returns <code>null</code>. Not even if the
parameter
+ * does not exist.
+ *
+ * @see StringValue#isNull()
+ *
+ * @param name
+ * @return {...@link StringValue} instance wrapping the parameter value
+ */
+ public StringValue getQueryParameterValue(String name)
+ {
+ QueryParameter parameter = getQueryParameter(name);
+ if (parameter == null)
+ {
+ return StringValue.valueOf((String)null);
+ }
+ else
+ {
+ return StringValue.valueOf(parameter.getValue());
+ }
+ }
+
+ /**
+ * Represents a single query parameter
+ *
+ * @author Matej Knopp
+ */
+ public final static class QueryParameter
+ {
+ private final String name;
+ private final String value;
+
+ /**
+ * Creates new {...@link QueryParameter} instance. The
<code>name</code>
+ * and <code>value</code> parameters must not be
<code>null</code>,
+ * though they can be empty strings.
+ *
+ * @param name
+ * parameter name
+ * @param value
+ * parameter value
+ */
+ public QueryParameter(String name, String value)
+ {
+ Checks.argumentNotNull(name, "name");
+ Checks.argumentNotNull(value, "value");
+
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Returns query parameter name.
+ *
+ * @return query parameter name
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Returns query parameter value.
+ *
+ * @return query parameter value
+ */
+ public String getValue()
+ {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj instanceof QueryParameter == false)
+ {
+ return false;
+ }
+ QueryParameter rhs = (QueryParameter)obj;
+ return Objects.equal(getName(), rhs.getName())
+ && Objects.equal(getValue(),
rhs.getValue());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(getName(), getValue());
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder result = new StringBuilder();
+ result.append(encodeParameter(getName()));
+ if (!Strings.isEmpty(getValue()))
+ {
+ result.append('=');
+ result.append(encodeParameter(getValue()));
+ }
+ return result.toString();
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj instanceof Url == false)
+ {
+ return false;
+ }
+ Url rhs = (Url)obj;
+
+ return getSegments().equals(rhs.getSegments())
+ &&
getQueryParameters().equals(rhs.getQueryParameters());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(getSegments(), getQueryParameters());
+ }
+
+ private static String encodeSegment(String string)
+ {
+ return WicketURLEncoder.PATH_INSTANCE.encode(string);
+ }
+
+ private static String decodeSegment(String string)
+ {
+ return WicketURLDecoder.PATH_INSTANCE.decode(string);
+ }
+
+ private static String encodeParameter(String string)
+ {
+ return WicketURLEncoder.QUERY_INSTANCE.encode(string);
+ }
+
+ private static String decodeParameter(String string)
+ {
+ return WicketURLDecoder.QUERY_INSTANCE.decode(string);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder result = new StringBuilder();
+ boolean first = true;
+ for (String s : getSegments())
+ {
+ if (!first)
+ {
+ result.append('/');
+ }
+ first = false;
+ result.append(encodeSegment(s));
+ }
+
+ first = true;
+
+ for (QueryParameter p : getQueryParameters())
+ {
+ if (first)
+ {
+ result.append("?");
+ first = false;
+ }
+ else
+ {
+ result.append("&");
+ }
+ result.append(p.toString());
+ }
+
+ return result.toString();
+ }
+
+ private static QueryParameter parseQueryParameter(String qp)
+ {
+ if (qp.indexOf('=') == -1)
+ {
+ return new QueryParameter(decodeParameter(qp), "");
+ }
+ String parts[] = Strings.split(qp, '=');
+ if (parts.length == 0)
+ {
+ return new QueryParameter("", "");
+ }
+ else if (parts.length == 1)
+ {
+ return new QueryParameter("",
decodeParameter(parts[0]));
+ }
+ else
+ {
+ return new QueryParameter(decodeParameter(parts[0]),
decodeParameter(parts[1]));
+ }
+ }
+
+ /**
+ * Parses the given URL string.
+ *
+ * @param url
+ * @return Url object
+ */
+ public static Url parse(String url)
+ {
+ Checks.argumentNotNull(url, "url");
+
+ Url result = new Url();
+
+ String segments;
+ String query;
+
+ int qIndex = url.indexOf('?');
+
+ if (qIndex == -1)
+ {
+ segments = url;
+ query = "";
+ }
+ else
+ {
+ segments = url.substring(0, qIndex);
+ query = url.substring(qIndex + 1);
+ }
+
+ if (segments.length() > 0)
+ {
+
+ boolean removeLast = false;
+ if (segments.endsWith("/"))
+ {
+ // we need to append something and remove it
after splitting
+ // because otherwise the
+ // trailing slashes will be lost
+ segments += "/x";
+ removeLast = true;
+ }
+
+ String segmentArray[] = Strings.split(segments, '/');
+
+ if (removeLast)
+ {
+ segmentArray[segmentArray.length - 1] = null;
+ }
+
+ for (String s : segmentArray)
+ {
+ if (s != null)
+ {
+ result.segments.add(decodeSegment(s));
+ }
+ }
+ }
+
+ if (query.length() > 0)
+ {
+ String queryArray[] = Strings.split(query, '&');
+ for (String s : queryArray)
+ {
+ result.parameters.add(parseQueryParameter(s));
+ }
+ }
- return result;
- };
+ return result;
+ };
}