package com.griddynamics.jagger.webclient.client.mvp;
import com.google.gwt.core.client.GWT;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceHistoryMapper;
import java.util.*;
/**
* @author "Artem Kirillov" (akirillov@griddynamics.com)
* @since 6/20/12
*/
public abstract class AbstractPlaceHistoryMapper implements PlaceHistoryMapper {
protected static final String SEPARATOR_TOKEN_PARAMETERS = "?";
protected static final String SEPARATOR_PARAMETERS = "&";
protected static final String SEPARATOR_PARAMETER_ID_VALUE = "=";
@Override
public Place getPlace(String token) {
if (null == token || "".equals(token)) {
// it will show the default place
return null;
}
Place place = getPlaceFromToken(token);
if (null == place) {
GWT.log("No corresponding place found for the token " + token);
return null;
}
// if the place has parameters, retrieving them from token
if (place instanceof PlaceWithParameters) {
int index = token.indexOf(SEPARATOR_TOKEN_PARAMETERS);
if (index != -1) {
((PlaceWithParameters) place).setParameters(getParameters(token.substring(index+1)));
}
}
return place;
}
public static Map<String, Set<String>> getParameters(String line){
Map<String, Set<String>> mapParameters = new HashMap<String, Set<String>>();
String[] parameters = complexSplit(line, '&');
for (String parameter : parameters) {
String[] paramIdValue = complexSplit(parameter, '=');
if (!mapParameters.containsKey(paramIdValue[0])) {
String[] values = complexSplit(paramIdValue[1], ',');
if (values.length > 0){
HashSet<String> set = new HashSet<String>(Arrays.asList(values));
mapParameters.put(paramIdValue[0], set);
}
}
}
return mapParameters;
}
public static String[] complexSplit(String line, char separator){
ArrayList<String> elements = new ArrayList<String>();
int startPos = 0;
int bracketCount = 0;
for (int i=0; i<line.length(); i++){
char current = line.charAt(i);
if (current == '('){
bracketCount++;
i++;
while (bracketCount!=0 && i<line.length()){
if (line.charAt(i)=='('){
bracketCount++;
}
if (line.charAt(i)==')'){
bracketCount--;
}
i++;
}
}
if (i<line.length() && line.charAt(i) == separator){
elements.add(line.substring(startPos, i));
startPos = i+1;
}
}
elements.add(line.substring(startPos, line.length()));
return elements.toArray(new String[]{});
}
@Override
public String getToken(Place place) {
String token = getTokenFromPlace(place);
if (place instanceof PlaceWithParameters) {
Map<String, Set<String>> parameters = ((PlaceWithParameters) place).getParameters();
if (null != parameters && !parameters.isEmpty()) {
StringBuilder tokenBuilder = new StringBuilder(token);
tokenBuilder.append(SEPARATOR_TOKEN_PARAMETERS);
for (Map.Entry<String, Set<String>> parameter : parameters.entrySet()) {
tokenBuilder.append(parameter.getKey());
tokenBuilder.append(SEPARATOR_PARAMETER_ID_VALUE);
StringBuilder paramBuilder = new StringBuilder();
for (String paramValue : parameter.getValue()) {
paramBuilder.append(paramValue);
paramBuilder.append(',');
}
tokenBuilder.append(paramBuilder.toString().substring(0, paramBuilder.length()-1));
tokenBuilder.append(SEPARATOR_PARAMETERS);
}
token = tokenBuilder.toString().substring(0, tokenBuilder.length()-1);
}
}
return token;
}
/**
* Find a place corresponding to the token given in parameters.
*
* @param token a String token
* @return the place corresponding to the token, throw UnsupportedOperationException if none found
*/
protected abstract Place getPlaceFromToken(String token);
/**
* Find a string token corresponding to the place given in parameters.
*
* @param place a place
* @return the token corresponding to the place, throw UnsupportedOperationException if none found
*/
protected abstract String getTokenFromPlace(Place place);
}