/*
* CCVisu is a tool for visual graph clustering
* and general force-directed graph layout.
* This file is part of CCVisu.
*
* Copyright (C) 2005-2012 Dirk Beyer
*
* CCVisu is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* CCVisu is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CCVisu; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Please find the GNU Lesser General Public License in file
* license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
*
* Dirk Beyer (firstname.lastname@uni-passau.de)
* University of Passau, Bavaria, Germany
*/
package org.sosy_lab.ccvisu.readers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.sosy_lab.ccvisu.graph.Relation;
import org.sosy_lab.ccvisu.graph.Tuple;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXHandlerDOXIndex extends DefaultHandler {
// COMPOUND kind values: class, struct, union, interface, protocol, category,
// exception, file, namespace, group, page, example, dir
// MEMBER kind values: define, property, event, variable, typedef,
// enum, enumvalue, function, signal, prototype,
// friend, dcop, slot
private enum TagType {
UNKNOWN, COMPOUND, MEMBER
};
private class Entry {
private int level = 1;
private String kind = "";
private String id = "";
private String name = "";
Entry(int level, String kind, String id) {
assert (level > 0);
this.level = level;
this.kind = kind;
this.id = id;
}
}
private int xmlLevel = 0;
private TagType detectingNameOfTagType = TagType.UNKNOWN;
private Entry currentCompound = new Entry(1, "", "");
private Entry currentMember = new Entry(1, "", "");
private List<String> xmlFileIds = new ArrayList<String>();
private Relation relations;
public SAXHandlerDOXIndex(Relation relations) {
super();
this.relations = relations;
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attrs) throws SAXException {
xmlLevel++;
detectingNameOfTagType = TagType.UNKNOWN;
if (qName.toLowerCase().equals("compound")
|| qName.toLowerCase().equals("member")) { // COMPOUND and MEMBER
assert (attrs != null);
String id = attrs.getValue("refid");
assert (id != null);
String kind = attrs.getValue("kind");
assert (kind != null);
if (qName.toLowerCase().equals("compound")) {
currentCompound = new Entry(xmlLevel, kind, id);
} else {
currentMember = new Entry(xmlLevel, kind, id);
}
} else if (qName.toLowerCase().equals("name")) { // NAME
if (xmlLevel == currentCompound.level + 1) {
detectingNameOfTagType = TagType.COMPOUND;
} else {
assert (xmlLevel == currentCompound.level + 2);
assert (xmlLevel == currentMember.level + 1);
detectingNameOfTagType = TagType.MEMBER;
}
} else if (qName.toLowerCase().equals("doxygenindex")) { // DOXYGENINDEX
// Not needed.
} else {
assert (false);
}
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
detectingNameOfTagType = TagType.UNKNOWN;
if (qName.toLowerCase().equals("compound")) { // COMPOUND
assert (xmlLevel == currentCompound.level);
if (currentCompound.name.equals("")) {
System.err.println("Runtime Error: No name found for compound "
+ currentCompound.id + ".");
System.exit(1);
}
List<String> tuple = new ArrayList<String>();
tuple.add(currentCompound.kind);
tuple.add(currentCompound.id);
tuple.add(currentCompound.name);
relations.addTuple(new Tuple("COMPOUND", tuple));
} else if (qName.toLowerCase().equals("member")) { // MEMBER
assert (xmlLevel == currentCompound.level + 1);
assert (xmlLevel == currentMember.level);
if (currentMember.name.equals("")) {
System.err.println("Runtime Error: No name found for member "
+ currentMember.id + ".");
System.exit(1);
}
{
List<String> newTuple = new ArrayList<String>(3);
newTuple.add(currentMember.kind);
newTuple.add(currentMember.id);
newTuple.add(currentCompound.name + "." + currentMember.name);
relations.addTuple(new Tuple("MEMBER", newTuple));
}
{
List<String> newTuple = new ArrayList<String>(2);
newTuple.add(currentMember.id);
newTuple.add(currentCompound.id);
relations.addTuple(new Tuple("CONTAINEDIN", newTuple));
}
}
xmlLevel--;
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
@Override
public void characters(char[] ch, int start, int len) throws SAXException {
String name = new String(ch, start, len);
if (name.trim().equals("")) { return; }
if (detectingNameOfTagType == TagType.COMPOUND) { // COMPOUND name
xmlFileIds.add(currentCompound.id);
// Concatenate the two strings (e.g. "MyClass<T" + ">").
currentCompound.name += name;
} else if (detectingNameOfTagType == TagType.MEMBER) { // MEMBER name
// Concatenate the two strings (e.g. "operator" + "<=").
currentMember.name += name;
}
}
/**
* @return list of file names to process.
*/
public List<String> getXmlFileIds() {
return Collections.unmodifiableList(xmlFileIds);
}
}