/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed 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 com.alibaba.citrus.generictype.introspect.impl;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static java.lang.reflect.Modifier.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.citrus.generictype.TypeInfo;
import com.alibaba.citrus.generictype.introspect.Introspector;
import com.alibaba.citrus.generictype.introspect.PropertyInfo;
/**
* 实现{@link Introspector}。
*
* @author Michael Zhou
*/
public class IntrospectorImpl extends Introspector {
private final TypeInfo type;
private final Map<String, List<PropertyInfo>> props;
/** 创建一个{@link Introspector}实例。 */
IntrospectorImpl(TypeInfo type) {
this.type = assertNotNull(type, "type");
this.props = new TypeScanner().scan();
}
private TypeVisitor[] getVisitors() {
return new TypeVisitor[] { new SimplePropertiesFinder(), new IndexedPropertiesFinder(),
new MappedPropertiesFinder(), new ArrayPropertiesFinder(), new MapPropertiesFinder() };
}
@Override
public Map<String, List<PropertyInfo>> getProperties() {
return props;
}
/** 扫描并分析类型。 */
private class TypeScanner {
private final TypeVisitor[] visitors = getVisitors();
private final Map<MethodSignature, Method> methods = createHashMap();
/** 分析一个类,及其基类和接口。 */
public Map<String, List<PropertyInfo>> scan() {
boolean first = true;
// 开始
for (TypeVisitor visitor : visitors) {
visitor.visit();
}
// 分析
for (TypeInfo t : type.getSupertypes()) {
scanType(t, true, first);
first = false;
}
// 结束
for (TypeVisitor visitor : visitors) {
visitor.visitEnd();
}
// 收集结果
PropertiesMap props = new PropertiesMap();
for (TypeVisitor visitor : visitors) {
if (visitor instanceof PropertiesFinder) {
props.addAll(((PropertiesFinder) visitor).getProperties());
}
}
return unmodifiableMap(props);
}
/** 分析一个类。 */
private void scanType(TypeInfo type, boolean scanFields, boolean scanConstructors) {
for (TypeVisitor visitor : visitors) {
visitor.visitType(type);
}
Class<?> clazz = type.getRawType();
// 扫描class序列中的每一个field,无论其访问性是什么。
if (scanFields) {
for (Field field : clazz.getDeclaredFields()) {
for (TypeVisitor visitor : visitors) {
visitor.visitField(field);
}
}
}
// 只扫描第一个class中的constructor,无论其访问性是什么。
if (scanConstructors) {
for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
for (TypeVisitor visitor : visitors) {
visitor.visitConstructor(constructor);
}
}
}
// 扫描class序列中的每一个method,无论其访问性是什么。
// 然而,对于public和protected method,只有最顶部的那个实现会被访问。
for (Method method : clazz.getDeclaredMethods()) {
MethodSignature sig = new MethodSignature(method);
boolean accessible = (method.getModifiers() & (PUBLIC | PROTECTED)) != 0;
if (!accessible || !methods.containsKey(sig)) {
if (accessible) {
methods.put(sig, method);
}
for (TypeVisitor visitor : visitors) {
visitor.visitMethod(method);
}
}
}
}
}
/** 代表一个Properties的映射表。 */
private static class PropertiesMap extends HashMap<String, List<PropertyInfo>> {
private static final long serialVersionUID = 3899442980552826145L;
public void addAll(Map<String, List<PropertyInfo>> props) {
if (props != null) {
for (Map.Entry<String, List<PropertyInfo>> entry : props.entrySet()) {
String propName = assertNotNull(entry.getKey(), "property name is null: %s", entry);
List<PropertyInfo> propsWithSameName = super.get(propName);
if (propsWithSameName == null) {
propsWithSameName = createLinkedList();
super.put(propName, propsWithSameName);
}
propsWithSameName.addAll(entry.getValue());
}
}
}
@Override
public String toString() {
String[] names = keySet().toArray(new String[size()]);
sort(names);
StringBuilder buf = new StringBuilder();
int i = 0;
buf.append("Properties:\n");
for (String name : names) {
List<PropertyInfo> props = get(name);
for (PropertyInfo prop : props) {
buf.append("\n--- ").append(++i).append(" ------------------------------\n");
buf.append(prop).append("\n");
}
}
buf.append("==============================\n");
return buf.toString();
}
}
/** 创建{@link Introspector}的工厂。 */
public static class FactoryImpl implements Factory {
public Introspector getInstance(TypeInfo type) {
return new IntrospectorImpl(type);
}
}
}