All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.gilbertotorrezan.gwtviews.client.URLToken Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License (MIT)
 * 
 * Copyright (c) 2015 Gilberto Torrezan Filho
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * 
 */
package com.github.gilbertotorrezan.gwtviews.client;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.History;

/**
 * 

* A URLToken represents the state of a URL. It parses the parameters in the following form: *

{@code tokenId¶m1=value1¶m2¶m3='complex&value' }
*

*

* Calling {@link #toString()} will return a valid token with all parameters to be used at {@link History#newItem(String)} or anchors. *

* * @author Gilberto Torrezan Filho * * @since v.1.0.0 */ public class URLToken extends Place implements Cloneable { private String id = ""; private Map parameters = new LinkedHashMap<>(); private enum TokenParseState { PARSING_ID, PARSING_KEY, PARSING_VALUE, PARSING_COMPLEX_VALUE, PARSED_COMPLEX_VALUE; } /** * Creates a new URLToken using the current state of the application. * * @see History#getToken() */ public URLToken() { this(History.getToken()); } /** * Creates a new URLToken using the provided token. * * @param completeToken The History token to be parsed, in the form of:
{@code tokenId¶m1=value1¶m2¶m3='complex&value' }
*/ public URLToken(String completeToken) { setToken(completeToken); } /** * Clones a URLToken, copying the id and all parameters. * * @see #clone() */ public URLToken(URLToken source) { this.id = source.id; this.parameters.putAll(source.parameters); } /** * Sets the current token, causing it to parse the parameters and the tokenId. * * @param completeToken The History token to be parsed, in the form of:
{@code tokenId¶m1=value1¶m2¶m3='complex&value' }
*/ public void setToken(String completeToken) { clearParameters(); id = ""; if (completeToken != null) { StringBuilder builder = new StringBuilder(); char[] chs = completeToken.toCharArray(); String currentKey = null; TokenParseState state = TokenParseState.PARSING_ID; for (char ch : chs) { switch (state) { case PARSING_ID: if (ch == '&') { state = TokenParseState.PARSING_KEY; id = builder.toString(); builder.delete(0, builder.length()); } else { builder.append(ch); } break; case PARSING_KEY: if (ch == '=') { state = TokenParseState.PARSING_VALUE; currentKey = builder.toString(); if (!currentKey.isEmpty()) { parameters.put(currentKey, ""); builder.delete(0, builder.length()); } } else if (ch == '&') { currentKey = builder.toString(); if (!currentKey.isEmpty()) { parameters.put(currentKey, ""); builder.delete(0, builder.length()); } } else { builder.append(ch); } break; case PARSING_VALUE: if (ch == '\'') { state = TokenParseState.PARSING_COMPLEX_VALUE; } else if (ch == '&') { state = TokenParseState.PARSING_KEY; parameters.put(currentKey, builder.toString()); builder.delete(0, builder.length()); } else { builder.append(ch); } break; case PARSING_COMPLEX_VALUE: if (ch == '\'') { state = TokenParseState.PARSED_COMPLEX_VALUE; parameters.put(currentKey, builder.toString()); builder.delete(0, builder.length()); } else { builder.append(ch); } break; case PARSED_COMPLEX_VALUE: if (ch == '&') { state = TokenParseState.PARSING_KEY; } break; } } switch (state) { case PARSING_ID: id = builder.toString(); break; case PARSING_KEY: currentKey = builder.toString(); if (!currentKey.isEmpty()) { parameters.put(currentKey, ""); } break; case PARSING_COMPLEX_VALUE: case PARSING_VALUE: String value = builder.toString(); if (!value.isEmpty() && currentKey != null) { parameters.put(currentKey, value); } break; default: break; } } } /** * Gets a parameter extracted from the History token. * For example, if the token is:
{@code tokenId¶m1=value1 }
the call to getParameter("param1") will return value1. * * @param name The name of the parameter * @return The value of the parameter, or null if not found. * When the token is something like
{@code tokenId¶m1¶m2 }
with a name without a explicit value, an empty String is returned. */ public String getParameter(String name) { return parameters.get(name); } /** * Gets a parameter extracted from the History token. * For example, if the token is:
{@code tokenId¶m1=value1 }
the call to getParameter("param1", "def") will return value1. * * @param name The name of the parameter * @param defaultValue The value to be returned when the parameter value is null * @return The value of the parameter, or defaultValue if not found. * When the token is something like
{@code tokenId¶m1¶m2 }
with a name without a explicit value, an empty String is returned. */ public String getParameter(String name, String defaultValue) { String value = parameters.get(name); if (value == null){ value = defaultValue; } return value; } /** * Gets an integer parameter extracted from the History token. * For example, if the token is:
{@code tokenId¶m1=1 }
the call to getParameterAsInt("param1", 0) will return 1. * * @param name The name of the parameter * @param defaultValue The value to be returned when the parameter is null or not parseable to int * @return The integer value of the parameter, or defaultValue if not parseable. * When the token is something like
{@code tokenId¶m1¶m2 }
with a name without a explicit value, the default value is returned. */ public int getParameterAsInt(String name, int defaultValue){ String value = parameters.get(name); if (value == null || value.isEmpty()){ return defaultValue; } try { return Integer.parseInt(value); } catch (Exception e) { return defaultValue; } } /** * Gets a boolean parameter extracted from the History token. * For example, if the token is:
{@code tokenId¶m1=true }
the call to getParameterAsBoolean("param1") will return true. * * @param name The name of the parameter * @return true if the value is equals ignoring case to the String "true", false otherwise */ public boolean getParameterAsBoolean(String name){ String value = parameters.get(name); return Boolean.parseBoolean(value); } /** * Gets a double parameter extracted from the History token. * For example, if the token is:
{@code tokenId¶m1=0.1 }
the call to getParameterAsBoolean("param1", 0) will return 0.1. * * @param name The name of the parameter * @param defaultValue The value to be returned when the parameter is null or not parseable to double * @return The boolean value of the parameter, or defaultValue if not parseable. * When the token is something like
{@code tokenId¶m1¶m2 }
with a name without a explicit value, the default value is returned. */ public double getParameterAsDouble(String name, double defaultValue){ String value = parameters.get(name); if (value == null || value.isEmpty()){ return defaultValue; } try { return Double.parseDouble(value); } catch (Exception e) { return defaultValue; } } /** * Sets a new value to a parameter, or put a new parameter if not existant. * If the value is null, the parameter is removed (same as calling the {@link #removeParameter(String)} method). * * @param name The name of the parameter * @param value The value of the parameter * @return the previous value associated with name, or null if there * wasn't an associated value to the name. */ public String setParameter(String name, String value) { if (value == null){ return removeParameter(name); } return parameters.put(name, value); } /** * Removes a parameter from the URLToken. * * @param name The name of the parameter to be removed * @return the previous value associated with name, or null if there * wasn't an associated value to the name. */ public String removeParameter(String name) { return parameters.remove(name); } /** * Clears all the parameters (but not the tokenId). */ public void clearParameters(){ parameters.clear(); } /** * Verifies if a parameter with the defined name is present on the URL. * * @param name The name of the parameter * @return true if the parameter is present, even with an empty value, false otherwise */ public boolean containsParameter(String name){ return parameters.containsKey(name); } /** * Gets the tokenId of the URL. The tokenId is the value associated with a {@link View#value()}. */ public String getId() { return id; } /** * Sets the tokenId of the URL. The tokenId is the value associated with a {@link View#value()}. */ public void setId(String id) { if (id == null){ id = ""; } this.id = id; } /** * Same as calling {@link #setId(String)}, but returning this instance for method chaining. */ public URLToken withId(String id) { setId(id); return this; } /** * Same as calling {@link #setParameter(String, String)}, but returning this instance for method chaining. */ public URLToken withParameter(String name, String value) { setParameter(name, value); return this; } /** * Changes the URL of the application to match the state of this URLToken. It has the same effect as calling * History.newItem(urlToken.toString(), true). * * @see History#newItem(String, boolean) */ public void go() { History.newItem(this.toString(), true); } /** * Creates a valid History token with the tokenId and all the parameters. Can be used in anchors (with the # sign) or at * calls to {@link History#newItem(String)}. * * @return The current URL represented by this URLToken, without the # sign */ @Override public String toString() { StringBuilder builder = new StringBuilder(id); Set> entrySet = parameters.entrySet(); for (Entry entry : entrySet) { builder.append("&").append(entry.getKey()); String v = entry.getValue(); if (v != null && !v.isEmpty()) { builder.append("="); if (v.contains("&") || v.contains("=") || v.contains(" ") || v.contains(":") || v.contains("#") || v.contains("?")) { builder.append("'").append(v).append("'"); } else { builder.append(v); } } } return builder.toString(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof Place) { return this.toString().equals(obj.toString()); } if (obj instanceof String){ return this.toString().equals(obj); } return false; } @Override public int hashCode() { return toString().hashCode(); } /** * Clones this URLToken, using the {@link #URLToken(URLToken)} constructor. */ public URLToken clone() { URLToken clone = new URLToken(this); return clone; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy