All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.piax.util.ClassUtil Maven / Gradle / Ivy

The newest version!
/*
 * ClassUtil.java - A utlity for Class handling.
 * 
 * Copyright (c) 2009-2015 PIAX develoment team
 * Copyright (c) 2006-2008 Osaka University
 * Copyright (c) 2004-2005 BBR Inc, Osaka University
 * 
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the 
 * "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, 
 * distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to 
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * $Id: ClassUtil.java 718 2013-07-07 23:49:08Z yos $
 */

package org.piax.util;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.WeakHashMap;

//-- I am waiting for someone to translate the following doc into English. :-)

/**
 * クラスおよびインタフェースの継承関係の処理に関するユーティリティクラス。
 * 

* stubの生成に関するProxyクラスの生成に必要なsuperインタフェースの * 算出用メソッドが用意されている。 *

* 上記のsuperインタフェースの2回目以降の算出コストを抑えるため、計算結果は * キャッシュしている。 * * @see MethodUtil */ public class ClassUtil { /** key object for cache map */ private static class SubIfsKey { final Class clazz; final Class superIf; SubIfsKey(Class clazz, Class superIf) { this.clazz = clazz; this.superIf = superIf; } @Override public boolean equals(Object o) { if (o == null || !(o instanceof SubIfsKey)) return false; SubIfsKey mkey = (SubIfsKey) o; return clazz == mkey.clazz && superIf == mkey.superIf; } @Override public int hashCode() { return clazz.hashCode() ^ ((superIf == null) ? 0 : superIf.hashCode()); } } /** getIfList で用いるキャッシュ用のMap */ private static WeakHashMap[]> cashe = new WeakHashMap[]>(); public static boolean isSub(Class clazz1, Class clazz2) { return clazz2.isAssignableFrom(clazz1); } /** * poolに新しくinterfazeを追加する。 *

* 追加の際に、そのinterfazeのサブとなるinterfaceがある場合は追加しない。 * また、superとなるinterfaceがある場合はすべて削除して、interfazeを追加する。 * これにより、poolにはinterfaceの集合をlatticeと見た場合に常に下界な要素からなる集合が保持される。 * (つまい、pool内の各interfaceについて、そのsuperとなるinterfaceがpool内に存在することはない) * * @param pool interfaceのリスト * @param interfaze 追加を試みるinterface */ private static void addIf(List> pool, Class interfaze) { // 要素削除があるため、for eachではなく iteratorを使う ListIterator> it = pool.listIterator(); while (it.hasNext()) { Class cur = it.next(); if (isSub(cur, interfaze)) { // if cur < interfaze, do nothing return; } if (isSub(interfaze, cur)) { // if interfaze < cur, remove cur it.remove(); } } it.add(interfaze); } /** * clazzの持つinterface(super classから継承されたものも含めて)のうち、 * superIfと同じかまたはsubの関係にあるinterfaceのみをpoolに追加する。 * clazz自身がinterfaceの場合は、clazz自身も含める。 * * @param clazz 基準となるクラス * @param superIf 指定されたinterface * @param pool interfaceのリスト */ private static void gatherSubIfs0(Class clazz, Class superIf, List> pool) { if (clazz.isInterface()) { addIf(pool, clazz); } Class[] ifs = clazz.getInterfaces(); for (Class interfaze : ifs) { if (isSub(interfaze, superIf)) { addIf(pool, interfaze); } } Class superc = clazz.getSuperclass(); if (superc != null) { gatherSubIfs0(superc, superIf, pool); } } /** * 指定されたclazzの持つinterface(super classから継承されたものも含めて)の中で、 * 指定された superIfと同じかsub interface の関係にある interfaceの集合の中で、 * 下界(lower bound)なものを求める。clazz自身がinterfaceの場合は、clazz自身も含める。 *

* 効率化のため、計算した値はキャッシュに登録しておく。 * * @param clazz 基準となるクラス * @param superIf super interface * @param the type of the class. * @return clazz から見て super であり、superIf から見て subである * interface の中で下界なもの */ public static Class[] gatherLowerBoundSuperInterfaces( Class clazz, Class superIf) { assert clazz != null; assert superIf != null; // if (superIf == null) superIf = Object.class; if (!superIf.isInterface()) { throw new IllegalArgumentException("superIf is not Interface"); } SubIfsKey key = new SubIfsKey(clazz, superIf); Class[] result; synchronized (cashe) { result = cashe.get(key); if (result == null) { List> pool = new ArrayList>(); gatherSubIfs0(clazz, superIf, pool); result = new Class[pool.size()]; pool.toArray(result); cashe.put(key, result); } } return result; } }