/**
* Copyright 2015 Santhosh Kumar Tekuri
*
* The JLibs authors license this file to you 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 jlibs.xml.sax.binding.impl.processor;
import jlibs.core.annotation.processing.AnnotationError;
import jlibs.xml.sax.binding.impl.Registry;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.xml.namespace.QName;
import java.util.*;
/**
* @author Santhosh Kumar T
*/
class Binding{
int id;
ExecutableElement startMethod;
ExecutableElement textMethod;
ExecutableElement finishMethod;
TypeElement element;
Map<QName, BindingRelation> registry = new LinkedHashMap<QName, BindingRelation>();
Binding getBinding(ExecutableElement method, AnnotationMirror mirror, String xpath){
if(xpath.length()==0)
return this;
else
return getBindingRelation(method, mirror, xpath).binding;
}
Relation getRelation(ExecutableElement method, AnnotationMirror mirror, String xpath){
return getBindingRelation(method, mirror, xpath).relation;
}
BindingRelation getBindingRelation(ExecutableElement method, AnnotationMirror mirror, String xpath){
Binding binding = this;
BindingRelation bindingRelation = null;
StringTokenizer stok = new StringTokenizer(xpath, "/");
Map<QName, BindingRelation> registry = binding.registry;
while(stok.hasMoreTokens()){
String token = stok.nextToken();
QName qname = toQName(method, mirror, token);
bindingRelation = registry.get(qname);
if(bindingRelation==null){
registry.put(qname, new BindingRelation());
bindingRelation = registry.get(qname);
}
registry = bindingRelation.binding.registry;
}
return bindingRelation;
}
public void handleStar(){
BindingRelation startBindingRelation = registry.get(Registry.ANY);
if(startBindingRelation!=null){
for(BindingRelation bindingRelation: registry.values()){
// what about binding???
if(bindingRelation.relation.startedMethod==null)
bindingRelation.relation.startedMethod = startBindingRelation.relation.startedMethod;
if(bindingRelation.relation.finishedMethod==null)
bindingRelation.relation.finishedMethod = startBindingRelation.relation.finishedMethod;
}
}
}
public void initID(int id){
initID(id, idMap, new Stack<QName>());
}
public Map<Integer, List<QName>> idMap = new HashMap<Integer, List<QName>>();
private int initID(int id, Map<Integer, List<QName>> idMap, Stack<QName> path){
this.id = id;
idMap.put(id, new ArrayList<QName>(path));
for(Map.Entry<QName, BindingRelation> entry: registry.entrySet()){
path.push(entry.getKey());
id = entry.getValue().binding.initID(++id, idMap, path);
path.pop();
}
return id;
}
static QName toQName(Element pos1, AnnotationMirror pos2, String token){
if(token.equals(Registry.STAR))
return Registry.ANY;
Properties nsContext = Namespaces.get(pos1);
String prefix, localName;
int colon = token.indexOf(':');
if(colon==-1){
prefix = "";
localName = token;
}else{
prefix = token.substring(0, colon);
localName = token.substring(colon+1);
}
String uri = prefix.equals(Registry.STAR) ? prefix : nsContext.getProperty(prefix);
if(uri==null)
throw new AnnotationError(pos1, pos2, "no namespace mapping found for prefix "+prefix);
return new QName(uri, localName);
}
static String toJava(QName qname){
if(qname==null)
return null;
else if(qname.getNamespaceURI().length()==0)
return "new QName(\""+qname.getLocalPart()+"\")";
else
return "new QName(\""+qname.getNamespaceURI()+"\", \""+qname.getLocalPart()+"\")";
}
}
class Relation{
ExecutableElement startedMethod;
ExecutableElement finishedMethod;
}
class BindingRelation{
Binding binding;
Relation relation;
BindingRelation(){
binding = new Binding();
relation = new Relation();
}
}