📄 model.java
字号:
/*
// $Id: //open/mondrian/src/main/mondrian/jolap/util/Model.java#4 $
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// (C) Copyright 2002-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, Dec 25, 2002
*/
package mondrian.jolap.util;
import mondrian.olap.Util;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import org.apache.log4j.Logger;
/**
* <code>Model</code> attempts to deduce an object model consisting of
* entities, attributes and relationships using Java reflection.
*
* @author jhyde
* @since Dec 25, 2002
* @version $Id: //open/mondrian/src/main/mondrian/jolap/util/Model.java#4 $
**/
public class Model {
private static final Logger LOGGER = Logger.getLogger(Model.class);
private static Model instance;
private HashMap mapClassToEntity = new HashMap();
private static final Entity noEntity = new Entity(null, Object.class);
private static final Relationship noRelationship = new Relationship(noEntity, null, null);
private static final Attribute[] emptyAttributeArray = new Attribute[0];
private static final Relationship[] emptyRelationshipArray = new Relationship[0];
private static final Class[] emptyClassArray = new Class[0];
static int nextOrdinal;
/** Returns the singleton instance. **/
public static synchronized Model instance() {
if (instance == null) {
instance = new Model();
}
return instance;
}
public Entity getEntity(Object o) {
return getEntityForClass(o.getClass());
}
private Entity getEntityForClass(Class clazz) {
Entity entity = (Entity) mapClassToEntity.get(clazz);
if (entity == null) {
entity = deduceEntity(clazz);
if (entity == null) {
entity = noEntity;
}
mapClassToEntity.put(clazz, entity);
}
if (entity == noEntity) {
return null;
}
return entity;
}
private Entity deduceEntity(Class clazz) {
return new Entity(this, clazz);
}
private static String getShortName(Class clazz) {
final String clazzName = clazz.toString();
final int i = clazzName.lastIndexOf(".");
if (i < 0) {
return clazzName;
} else {
return clazzName.substring(i + 1);
}
}
static class Entity {
Model model;
Class clazz;
int ordinal;
Entity(Model model, Class clazz) {
this.model = model;
this.clazz = clazz;
this.ordinal = nextOrdinal++;
}
public String toString() {
return getShortName(clazz);
}
public String getDescription() {
return toString() + " (class " + clazz.getName() + ")";
}
Model getModel() {
return model;
}
Attribute[] getDeclaredAttributes() {
ArrayList attributeList = new ArrayList();
ArrayList relationshipList = new ArrayList();
computeMembers(attributeList, relationshipList);
return (Attribute[]) attributeList.toArray(emptyAttributeArray);
}
Attribute[] getAttributes() {
final Class[] ancestors = getAncestors(clazz);
ArrayList attributeList = new ArrayList();
ArrayList relationshipList = new ArrayList();
for (int i = 0; i < ancestors.length; i++) {
Class ancestor = ancestors[i];
getModel().getEntityForClass(ancestor).computeMembers(attributeList, relationshipList);
}
return (Attribute[]) attributeList.toArray(emptyAttributeArray);
}
Relationship[] getRelationships() {
final Class[] ancestors = getAncestors(clazz);
ArrayList attributeList = new ArrayList();
ArrayList relationshipList = new ArrayList();
for (int i = 0; i < ancestors.length; i++) {
Class ancestor = ancestors[i];
getModel().getEntity(ancestor).computeMembers(attributeList, relationshipList);
}
return (Relationship[]) relationshipList.toArray(emptyRelationshipArray);
}
private Class[] getAncestors(Class clazz) {
HashSet ancestors = new HashSet();
ancestors.add(clazz);
ArrayList extra = new ArrayList();
while (true) {
for (Iterator iterator = ancestors.iterator(); iterator.hasNext();) {
Class ancestor = (Class) iterator.next();
final Class superclass = ancestor.getSuperclass();
if (superclass != null &&
!ancestors.contains(superclass)) {
extra.add(superclass);
}
final Class[] interfaces = ancestor.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
Class anInterface = interfaces[i];
if (!ancestors.contains(anInterface)) {
extra.add(anInterface);
}
}
}
if (extra.isEmpty()) {
return (Class[]) ancestors.toArray(emptyClassArray);
}
ancestors.addAll(extra);
extra.clear();
}
}
Relationship[] getDeclaredRelationships() {
ArrayList attributeList = new ArrayList();
ArrayList relationshipList = new ArrayList();
computeMembers(attributeList, relationshipList);
return (Relationship[]) relationshipList.toArray(emptyRelationshipArray);
}
private void computeMembers(ArrayList attributeList, ArrayList relationshipList) {
final int clazzModifiers = clazz.getModifiers();
if (!Modifier.isPublic(clazzModifiers)) {
// Somewhat controversial. But public members of a non-public
// class are not callable. If they happen to implement an
// interface, we will see them again.
return;
}
// Each public, non-static field "x" is an attribute.
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
final int modifiers = field.getModifiers();
if (Modifier.isPublic(modifiers) &&
!Modifier.isStatic(modifiers)) {
attributeList.add(new FieldAttribute(this, field, field.getName()));
}
}
// Each public, non-static method "getFoo()" is an attribute "foo",
// unless there is also a method "addFoo()".
final Method[] declaredMethods = clazz.getDeclaredMethods();
HashSet methodNames = new HashSet();
for (int i = 0; i < declaredMethods.length; i++) {
Method declaredMethod = declaredMethods[i];
methodNames.add(declaredMethod.getName());
}
for (int i = 0; i < declaredMethods.length; i++) {
Method method = declaredMethods[i];
final int modifiers = method.getModifiers();
if (!Modifier.isPublic(modifiers) ||
Modifier.isStatic(modifiers)) {
continue;
}
final String name = method.getName();
if (name.startsWith("get")) {
if (method.getParameterTypes().length > 0) {
continue;
}
if (method.getReturnType() == void.class) {
continue;
}
String suffix = name.substring("add".length());
if (methodNames.contains("remove" + suffix)) {
// There is a "remove" method, so this is probably a
// relationship accessor, not an attribute.
continue;
}
String lowerSuffix = suffix.substring(0,1).toLowerCase() +
suffix.substring(1);
attributeList.add(new MethodAttribute(this, method, lowerSuffix));
} else if (name.startsWith("remove")) {
if (method.getParameterTypes().length != 1) {
continue;
}
if (method.getReturnType() != void.class) {
continue;
}
String suffix = name.substring("remove".length());
String lowerSuffix = suffix.substring(0,1).toLowerCase() +
suffix.substring(1);
relationshipList.add(new Relationship(this, method, lowerSuffix));
}
}
}
}
static class Member {
Entity entity;
java.lang.reflect.Member member;
String name;
Member(Entity entity, java.lang.reflect.Member member, String name) {
this.entity = entity;
this.member = member;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -