📄 modelbuilder.java
字号:
/* ========================================================================
* JCommon : a free general purpose class library for the Java(tm) platform
* ========================================================================
*
* (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jcommon/index.html
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* -----------------
* ModelBuilder.java
* -----------------
* (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
*
* Original Author: Thomas Morgner;
* Contributor(s): David Gilbert (for Object Refinery Limited);
*
* $Id: ModelBuilder.java,v 1.3 2005/10/18 13:32:20 mungady Exp $
*
* Changes
* -------
* 21-Jun-2003 : Initial version (TM);
* 26-Nov-2003 : Updated header and Javadocs (DG);
*
*/
package org.jfree.xml.generator;
import java.beans.BeanInfo;
import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Properties;
import org.jfree.util.HashNMap;
import org.jfree.xml.generator.model.ClassDescription;
import org.jfree.xml.generator.model.DescriptionModel;
import org.jfree.xml.generator.model.MultiplexMappingInfo;
import org.jfree.xml.generator.model.PropertyInfo;
import org.jfree.xml.generator.model.PropertyType;
import org.jfree.xml.generator.model.TypeInfo;
import org.jfree.xml.util.BasicTypeSupport;
/**
* A model builder. This class performs the work of creating a class description model from
* a set of source files.
*/
public final class ModelBuilder {
/** The single instance. */
private static ModelBuilder instance;
/**
* Returns the single instance of this class.
*
* @return the single instance of this class.
*/
public static ModelBuilder getInstance() {
if (instance == null) {
instance = new ModelBuilder();
}
return instance;
}
/** The handler mapping. */
private Properties handlerMapping;
/**
* Creates a single instance.
*/
private ModelBuilder() {
this.handlerMapping = new Properties();
}
/**
* Adds attribute handlers.
*
* @param p the handlers.
*/
public void addAttributeHandlers(final Properties p) {
this.handlerMapping.putAll(p);
}
/**
* Builds a model from the classes provided by the {@link SourceCollector}.
* <P>
* The {@link DescriptionGenerator} class invokes this.
*
* @param c the source collector.
* @param model the model under construction (<code>null</code> permitted).
*
* @return The completed model.
*/
public DescriptionModel buildModel(final SourceCollector c, DescriptionModel model) {
Class[] classes = c.getClasses();
if (model == null) {
model = new DescriptionModel();
}
while (classes.length != 0) {
classes = fillModel(classes, model);
}
fillSuperClasses(model);
// search for multiplexer classes
// first search all classes used in parameters and add them to
// our list of possible base classes
final Class[] baseClasses = findElementTypes(model);
final HashNMap classMap = new HashNMap();
for (int i = 0; i < baseClasses.length; i++) {
final Class base = baseClasses[i];
for (int j = 0; j < baseClasses.length; j++) {
final Class child = baseClasses[j];
if (Modifier.isAbstract(child.getModifiers())) {
continue;
}
if (base.isAssignableFrom(child)) {
classMap.add(base, child);
}
}
}
// at this point, the keys of 'classMap' represent all required
// multiplexers, while the values assigned to these keys define the
// possible childs
final Iterator keys = classMap.keys();
while (keys.hasNext()) {
final Class base = (Class) keys.next();
final Class[] childs = (Class[]) classMap.toArray(base, new Class[0]);
if (childs.length < 2) {
continue;
}
boolean isNew = false;
MultiplexMappingInfo mmi = model.getMappingModel().lookupMultiplexMapping(base);
final ArrayList typeInfoList;
if (mmi == null) {
mmi = new MultiplexMappingInfo(base);
typeInfoList = new ArrayList();
isNew = true;
}
else {
typeInfoList = new ArrayList(Arrays.asList(mmi.getChildClasses()));
}
for (int i = 0; i < childs.length; i++) {
// the generic information is only added, if no other information
// is already present ...
final TypeInfo typeInfo = new TypeInfo(childs[i].getName(), childs[i]);
if (!typeInfoList.contains(typeInfo)) {
typeInfoList.add(typeInfo);
}
}
mmi.setChildClasses((TypeInfo[]) typeInfoList.toArray(new TypeInfo[0]));
if (isNew) {
model.getMappingModel().addMultiplexMapping(mmi);
}
}
// when resolving a class to an handler, the resolver first has to
// search for an multiplexer before searching for handlers. Otherwise
// non-abstract baseclasses will be found before the multiplexer can
// resolve the situation.
return model;
}
private Class[] findElementTypes(final DescriptionModel model) {
final ArrayList baseClasses = new ArrayList();
for (int i = 0; i < model.size(); i++) {
final ClassDescription cd = model.get(i);
if (!baseClasses.contains(cd.getObjectClass())) {
baseClasses.add(cd.getObjectClass());
}
final PropertyInfo[] properties = cd.getProperties();
for (int p = 0; p < properties.length; p++) {
// filter primitive types ... they cannot form a generalization
// relation
if (!properties[p].getPropertyType().equals(PropertyType.ELEMENT)) {
continue;
}
final Class type = properties[p].getType();
if (baseClasses.contains(type)) {
continue;
}
// filter final classes, they too cannot have derived classes
if (Modifier.isFinal(type.getModifiers())) {
continue;
}
baseClasses.add(type);
}
}
return (Class[]) baseClasses.toArray(new Class[baseClasses.size()]);
}
/**
* Fills the super class for all object descriptions of the model. The
* super class is only filled, if the object's super class is contained
* in the model.
*
* @param model the model which should get its superclasses updated.
*/
private void fillSuperClasses(final DescriptionModel model) {
// Fill superclasses
for (int i = 0; i < model.size(); i++) {
final ClassDescription cd = model.get(i);
final Class parent = cd.getObjectClass().getSuperclass();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -