URIPrefixDispatcher.java
/***************************************************************************
Copyright 2012 Emily Estes
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 net.metanotion.web.concrete;
import java.util.NoSuchElementException;
import net.metanotion.util.Dispatcher;
import net.metanotion.util.Message;
import net.metanotion.util.PrefixConcurrentDictionary;
import net.metanotion.web.RequestObject;
/** This dispatcher stores a set of dispatchers and prefixes.
The resource of a Request is matched to the longest prefix, and then the dispatching
is delegated to the dispatcher associated with that prefix. By default, the delegated
dispatcher only sees the resource with the prefix removed. However, by setting "reducingMode"
to true in the appropriate constructor, delegated dispatchers will see the whole resource. */
public final class URIPrefixDispatcher implements Dispatcher<Object,RequestObject> {
private final PrefixConcurrentDictionary<Dispatcher> uriBaseToDecoder = new PrefixConcurrentDictionary<>();
private final boolean reducingMode;
/** Create a URIPrefixDispatcher instance with the reducing mode set to "true". */
public URIPrefixDispatcher() { this(true); }
/** Create a URIPrefixDispatcher instance and set the reducing mode.
@param reducingMode If this is false, the delegated dispatchers will see the whole resource, otherwise,
delegated dispatchers only see the part of the resource available after removing the prefix. */
public URIPrefixDispatcher(final boolean reducingMode) { this.reducingMode = reducingMode; }
/** Associate a prefix with a dispatcher.
@param base The resource prefix.
@param decoder The dispatcher to use for that prefix.
@return This instance of the URIPrefixDispatcher(i.e. you can chain add dispatchers.) */
public URIPrefixDispatcher addDispatcher(final String base, final Dispatcher decoder) {
uriBaseToDecoder.put(base, decoder);
return this;
}
/** Remove a dispatcher for a given prefix.
@param base The resource prefix to remove.
@return This instance of the URIPrefixDispatcher(i.e. you can chain remove dispatchers.) */
public URIPrefixDispatcher removeDispatcher(final String base) {
uriBaseToDecoder.remove(base);
return this;
}
// Dispatcher
@Override public Message<Object> dispatch(final RequestObject request) {
final String prefix = uriBaseToDecoder.findKey(request.getResource());
if(prefix==null) { throw new NoSuchElementException("URL does not match any defined prefixes."); }
return uriBaseToDecoder.get(prefix).dispatch(reducingMode ? new PrefixedRequestObject(request, prefix) : request);
}
}