/*
* Copyright (c) 2013-2014 the original author or authors
*
* Licensed 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 io.werval.runtime.routes;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import io.werval.api.context.CurrentContext;
import io.werval.api.http.Method;
import io.werval.api.http.QueryString;
import io.werval.api.routes.ReverseRoute;
import io.werval.runtime.http.HttpConstants;
import io.werval.runtime.util.Comparators;
import io.werval.util.IllegalArguments;
import io.werval.util.Strings;
/**
* Reverse route instance.
*/
public class ReverseRouteInstance
implements ReverseRoute
{
private final Method method;
private final String uri;
private final Charset charset;
private final Map<String, List<String>> appendedQueryString = new TreeMap<>( Comparators.LOWER_CASE );
private String fragmentIdentifier;
public ReverseRouteInstance( Method method, String uri, Charset charset )
{
this.method = method;
this.uri = uri;
this.charset = charset;
}
@Override
public Method method()
{
return method;
}
@Override
public String uri()
{
QueryString.Encoder encoder = new QueryString.Encoder( uri, charset );
for( Map.Entry<String, List<String>> entry : appendedQueryString.entrySet() )
{
String key = entry.getKey();
for( String value : entry.getValue() )
{
encoder.addParam( key, value );
}
}
StringBuilder sb = new StringBuilder( encoder.toString() );
if( !Strings.isEmpty( fragmentIdentifier ) )
{
sb.append( "#" ).append( fragmentIdentifier );
}
return sb.toString();
}
@Override
public ReverseRoute appendQueryString( String key, String... values )
{
IllegalArguments.ensureNotEmpty( "key", key );
IllegalArguments.ensureNotEmpty( "values", values );
if( !appendedQueryString.containsKey( key ) )
{
appendedQueryString.put( key, new ArrayList<>() );
}
appendedQueryString.get( key ).addAll( Arrays.asList( values ) );
return this;
}
@Override
public ReverseRoute appendQueryString( Map<String, ?> parameters )
{
IllegalArguments.ensureNotNull( "parameters", parameters );
for( Map.Entry<String, ?> entry : parameters.entrySet() )
{
String key = entry.getKey();
IllegalArguments.ensureNotEmpty( "parameter key", key );
IllegalArguments.ensureNotNull( "parameter value for '" + key + "'", entry.getValue() );
if( !appendedQueryString.containsKey( key ) )
{
appendedQueryString.put( key, new ArrayList<>() );
}
if( entry.getValue() instanceof List )
{
for( Object value : (List) entry.getValue() )
{
appendedQueryString.get( key ).add( value.toString() );
}
}
else
{
appendedQueryString.get( key ).add( entry.getValue().toString() );
}
}
return this;
}
@Override
public ReverseRoute withFragmentIdentifier( String fragmentIdentifier )
{
this.fragmentIdentifier = fragmentIdentifier;
return this;
}
@Override
public String httpUrl()
{
return httpUrl( false );
}
@Override
public String httpUrl( boolean secure )
{
return absoluteUrl( "http", secure );
}
@Override
public String webSocketUrl()
{
return webSocketUrl( false );
}
@Override
public String webSocketUrl( boolean secure )
{
return absoluteUrl( "ws", secure );
}
private String absoluteUrl( String protocol, boolean secure )
{
StringBuilder absoluteUrl = new StringBuilder( protocol );
if( secure )
{
absoluteUrl.append( "s" );
}
absoluteUrl.append( "://" ).append( CurrentContext.request().domain() );
if( ( !secure && CurrentContext.request().port() != HttpConstants.DEFAULT_HTTP_PORT )
|| ( secure && CurrentContext.request().port() != HttpConstants.DEFAULT_HTTPS_PORT ) )
{
// With custom port
absoluteUrl.append( ":" ).append( CurrentContext.request().port() );
}
absoluteUrl.append( uri() );
return absoluteUrl.toString();
}
@Override
public String toString()
{
return uri();
}
}