/*
* Copyright 2008-2011 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 com.nominanuda.urispec;
import static com.nominanuda.urispec.Assert.isFalse;
import java.net.URI;
import java.util.List;
import java.util.Map;
import org.antlr.runtime.Token;
public class URISpecNode extends AbstractNode implements MatchingNode {
private PathNode path;
private QueryNode query;
private FragmentNode fragment;
public URISpecNode(Token payload) {
super(payload);
}
@Override
public String template(Object model) {
StringBuilder sb = new StringBuilder();
String p = path.template(model);
if(p == null) {
return null;
}
sb.append(p);
if(query != null) {
String q = query.template(model);
if(q == null) {
return null;
}
if(q.length() > 0) {
sb.append("?").append(q);
}
}
if(fragment != null) {
String f = fragment.template(model);
if(f == null) {
return null;
}
if(f.length() > 0) {
sb.append("#").append(f);
}
}
return sb.toString();
}
@Override
public void initNode() {
isFalse(valid);
super.initNode();
path = (PathNode) getChild(0);
query = (QueryNode) getChild(1);
fragment = (FragmentNode) getChild(2);
}
public int match(String pattern, Object model) {
URI uri = URI.create(pattern).normalize();
String q = uri.getRawQuery();
int qlen = q == null ? 0 : q.length() + /* the '?' */1;
String f = uri.getRawFragment();
int flen = f == null ? 0 : f.length() + /* the '#' */1;
String uriStr = uri.toString();
int len = uriStr.length();
String p = uriStr.substring(0, len-qlen-flen);
StringModelAdapter<? super Object> ma = getNodeAdapter().getStringModelAdapter();
Object m = ma.createStringModel();
if(path.match(p, m) < p.length()) {
return -1;
}
if(query != null) {
if(q == null) {
q = "";
}
Map<String, List<String>> pMap = Utils.parseQueryString(q);
List<String> l = query.matchParam(pMap, m);
if(l == null) {
return -1;
}
}
if(fragment != null) {
if(path.match(p, m) < 0) {
return -1;
}
}
ma.setAll(m, model);
return pattern.length();
}
}