/*
* HJB4U is toolchain for creating a HyperJAXB front end for database users.
* Copyright (C) 2010 NigelB
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package hjb4u;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;
/**
* <code>ClassFinder</code>
* Date: 14/06/2010
* Time: 9:40:58 PM
*
* @author Nigel B
*/
public class ClassFinder {
private static final Logger logger = Logger.getLogger(ClassFinder.class.getName());
private static Class[] findClasses(InputStream is, Hashtable<String, Integer> packages) {
ArrayList<Class> toRet = new ArrayList<Class>();
Class[] _toRet;
Class current;
Integer val;
try {
// URL nsmap = new URL();new File().
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
Element root = doc.getDocumentElement();
NodeList nl = doc.getElementsByTagName("class");
Node n;
Element e;
int nscount = 1;
for (int i = nl.getLength(); i >= 0; i--) {
n = nl.item(i);
if (n instanceof Element) {
e = (Element) n;
try {
toRet.add(current = Class.forName(e.getAttribute("ref")));
if (packages != null) {
val = packages.get(current.getPackage().getName());
if (val == null) {
val = -1;
}
packages.put(current.getPackage().getName(), val + 1);
}
logger.debug("Found JAXB Element: " + e.getAttribute("ref"));
} catch (ClassNotFoundException e1) {
logger.info("Found JAXB Element: " + e.getAttribute("ref") + " But cannot load it.");
}
}
}
}
catch (Exception e) {
logger.debug(e, e);
_toRet = new Class[toRet.size()];
toRet.toArray(_toRet);
return _toRet;
}
_toRet = new Class[toRet.size()];
toRet.toArray(_toRet);
return _toRet;
}
public static Class[] getEpisodeClasses(URL location) throws IOException {
return findClasses(location.openStream(), null);
}
public static Class[] findAllJAXBClasses(URL location) throws IOException {
Hashtable<String, Integer> packages = new Hashtable<String, Integer>();
Class[] cls = findClasses(location.openStream(), packages);
Hashtable<String, Class> done = new Hashtable<String, Class>();
for (Class cl : cls) {
recurse(cl, packages, done);
}
Set<String> keys = done.keySet();
cls = new Class[keys.size()];
int i = 0;
for (String key : keys) {
try {
cls[i++] = Class.forName(key);
} catch (ClassNotFoundException e) {
logger.error(String.format("Could not find Class: %s", e.getMessage()));
logger.trace(e, e);
}
}
return cls;
}
private static void recurse(Class cls, Hashtable<String, Integer> packages, Hashtable<String, Class> done) {
if(cls.isArray()){cls = cls.getComponentType();}
if (done.get(cls.getName()) != null || cls.isPrimitive() || !in(cls.getPackage().getName(), packages)) return;
System.out.println(cls);
done.put(cls.getName(), cls);
if (cls.isEnum()) return;
Field[] fields = cls.getDeclaredFields();
Class type;
for (Field field : fields) {
type = field.getType();
if (field.getType() == List.class) {
try{
type = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
}catch(ClassCastException c)
{
logger.warn("Issue generating table listing.");
}
}
recurse(type, packages, done);
}
}
private static boolean in(String name, Hashtable<String, Integer> packages) {
return packages.get(name) != null;
}
}