[Jiemamy-notify:1433] commit [2662] 親子関係かどうかを検索するユーティリティメソッドを追加する。

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2009年 2月 13日 (金) 02:18:29 JST


Revision: 2662
          http://svn.sourceforge.jp/view?root=jiemamy&view=rev&rev=2662
Author:   shin1
Date:     2009-02-13 02:18:29 +0900 (Fri, 13 Feb 2009)

Log Message:
-----------
親子関係かどうかを検索するユーティリティメソッドを追加する。
作業中だが一旦コミットしておく(まだどこからも使っていないため影響は無い)。

Modified Paths:
--------------
    artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/ReferenceResolverImpl.java


-------------- next part --------------
Modified: artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/ReferenceResolverImpl.java
===================================================================
--- artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/ReferenceResolverImpl.java	2009-02-12 16:42:07 UTC (rev 2661)
+++ artemis/trunk/jiemamy-core/src/main/java/org/jiemamy/ReferenceResolverImpl.java	2009-02-12 17:18:29 UTC (rev 2662)
@@ -18,12 +18,19 @@
  */
 package org.jiemamy;
 
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.Map.Entry;
 
+import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.commons.lang.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import org.jiemamy.model.ElementReference;
 import org.jiemamy.model.JiemamyElement;
@@ -41,6 +48,8 @@
  */
 public class ReferenceResolverImpl implements ReferenceResolver {
 	
+	static Logger logger = LoggerFactory.getLogger(ReferenceResolver.class);
+	
 	/**
 	 * {@link JiemamyElement}のidと{@link JiemamyElement}の実体をマップする。
 	 */
@@ -67,6 +76,101 @@
 		return false;
 	}
 	
+	/**
+	 * 指定された{@link UUID}が、指定されたElementから見た関係者かどうかを深く探索する。
+	 * <p>CollectionやMapはその要素を対象にさらに深く検索するが、ElementReferenceの中は一階層だけしか見ない。</p>
+	 * <p>イベントの通知対象かどうかを判断するために導入した。</p>
+	 * 
+	 * @param element
+	 * @param uuid
+	 * @return 関係があるなら{@code true}、そうでないなら{@code false}
+	 */
+	public static boolean isDescendFromElement(JiemamyElement element, UUID uuid) {
+		boolean traceEnabled = logger.isTraceEnabled();
+		if (traceEnabled) {
+			logger.trace("isDescend() uuid=" + uuid + ", " + element);
+		}
+		if (element == null) {
+			return false;
+		}
+		try {
+			// 調査対象のモデルのフィールドを全部調べる。
+			@SuppressWarnings("unchecked")
+			Map<String, Object> description = PropertyUtils.describe(element);
+			Iterator<Entry<String, Object>> i = description.entrySet().iterator();
+			while (i.hasNext()) {
+				Entry<String, Object> next = i.next();
+				Object value = next.getValue();
+				logger.debug("  field:name=" + next.getKey() + ", value=" + value);
+				if (isDescendFromFieldValue(value, uuid)) {
+					return true;
+				}
+			}
+			// 登録されたAdapterもフィールドと同じ扱いで調査対象にsする。
+			Iterator<Object> adapters = element.getAdapters().iterator();
+			while (adapters.hasNext()) {
+				Object value = adapters.next();
+				logger.debug("  adapter=" + value);
+				if (isDescendFromFieldValue(value, uuid)) {
+					return true;
+				}
+			}
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		} catch (InvocationTargetException e) {
+			e.printStackTrace();
+		} catch (NoSuchMethodException e) {
+			e.printStackTrace();
+		}
+		return false;
+	}
+	
+	/**
+	 * {@link #isDescendFromElement(JiemamyElement, UUID)}のヘルパーメソッド。
+	 * 
+	 * @param fieldValue 調査する対象のFieldの値
+	 * @param uuid
+	 * @return 関係があるなら{@code true}、そうでないなら{@code false}
+	 */
+	private static boolean isDescendFromFieldValue(Object fieldValue, UUID uuid) {
+		if (fieldValue == null) {
+			return false;
+		}
+		if (fieldValue instanceof JiemamyElement) {
+			JiemamyElement e = (JiemamyElement) fieldValue;
+			if (uuid.equals(e.getId())) {
+				return true;
+			} else {
+				// JiemamyElementで、検索対象でなかった場合は再起して調査する。
+				if (isDescendFromElement(e, uuid)) {
+					return true;
+				}
+			}
+		} else if (fieldValue instanceof ElementReference) {
+			// ElementReferenceだった場合は一階層だけ調査する。
+			if (uuid.equals(((ElementReference<JiemamyElement>) fieldValue).getReferenceId())) {
+				return true;
+			}
+		} else if (fieldValue instanceof Collection) {
+			// Collectionだった場合は要素に対して再起して調査する。
+			Collection<? extends Object> collection = (Collection) fieldValue;
+			for (Object element : collection) {
+				if (isDescendFromFieldValue(element, uuid)) {
+					return true;
+				}
+			}
+		} else if (fieldValue instanceof Map) {
+			// Mapだった場合は要素に対して再起して調査する。
+			Map<?, ? extends Object> collection = (Map<?, ? extends Object>) fieldValue;
+			for (Object element : collection.values()) {
+				if (isDescendFromFieldValue(element, uuid)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
 	private static boolean isPrimaryKeyChild(PrimaryKeyModel parent, JiemamyElement child) {
 		List<ColumnRef> columnRefs = parent.getKeyColumns();
 		for (ColumnRef ref : columnRefs) {



Jiemamy-notify メーリングリストの案内
Back to archive index