/* * Copyright (C) NetStruxr, Inc. All rights reserved. * * This software is published under the terms of the NetStruxr * Public Software License version 0.5, a copy of which has been * included with this distribution in the LICENSE.NPL file. */ package com.webobjects.directtoweb; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.webobjects.appserver.WOComponent; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSKeyValueCoding; import er.directtoweb.interfaces.ERDPickPageInterface; // This is needed because pageFinalized is a protected method. public class ERD2WUtilities { private static final Logger log = LoggerFactory.getLogger(ERD2WUtilities.class); public static void finalizeContext(D2WContext context) { if (context != null) context.pageFinalized(); } public static void resetContextCache(D2WContext context) { if (context != null) context._localValues.clear(); } public static boolean assignmentsAreEqual(Assignment a1, Assignment a2) { boolean areEqual = false; if (a1.getClass().equals(a2.getClass()) && a1.keyPath() != null && a2.keyPath() != null && a1.value() != null && a2.value() != null) { areEqual = a1.keyPath().equals(a2.keyPath()) && a1.value().equals(a2.value()); } return areEqual; } // This prevents the dreaded KeyValueCoding null object exception, for say key paths: object.entityName // Should just return null instead of throwing. public static Object contextValueForKeyNoInferenceNoException(D2WContext c, String keyPath) { Object result = null; int i = keyPath.indexOf("."); if (i == -1) { result = c.valueForKeyNoInference(keyPath); } else { String first = keyPath.substring(0, i); String second = keyPath.substring(i + 1); result = c.valueForKeyNoInference(first); if (result != null) { // Optimized for two paths deep try { if (second.indexOf(".") == -1) { result = NSKeyValueCoding.Utility.valueForKey(result, second); } else { NSArray parts = NSArray.componentsSeparatedByString(second, "."); for (int j = 0; j < parts.count(); j++) { String part = (String)parts.objectAtIndex(j); result = NSKeyValueCoding.Utility.valueForKey(result, part); if (result == null) break; } } } catch (NSKeyValueCoding.UnknownKeyException e) { if (log.isDebugEnabled()) { log.debug("keyPath {} is not available for context with entity: {}; task: {}", keyPath, c.entity().name(), c.task()); } return null; } } } return result; } /** Utility to return the next page in the enclosing page. */ public static WOComponent nextPageInPage(D2WPage parent) { WOComponent result = parent.context().page(); WOComponent old = parent.context().component(); try { parent.context()._setCurrentComponent(parent); if(parent.nextPageDelegate() != null) { NextPageDelegate delegate = parent.nextPageDelegate(); result = delegate.nextPage(parent); } else { result = parent.nextPage(); } } finally { parent.context()._setCurrentComponent(old); } return result; } /** Utility to return the first enclosing component that matches the given class, if there is one. */ public static WOComponent enclosingPageOfClass(WOComponent sender, Class c) { WOComponent p = sender.parent(); while(p != null) { if(c.isAssignableFrom(p.getClass())) return p; p = p.parent(); } return null; } /** * This method is similar to enclosingPageOfClass. It differs in that it is generic * and it inspects the sender argument as well as its parents. * @param <T> The class type * @param sender the sender component * @param c the class * @return sender or the first of sender's parents that is assignable from class c */ public static <T> T enclosingComponentOfClass(WOComponent sender, Class<T> c) { WOComponent p = sender; while(p != null) { if(c.isAssignableFrom(p.getClass())) return (T)p; p = p.parent(); } return null; } /** Utility to return the outermost page that is a D2W page. This is needed because this component might be embedded inside a plain page. */ public static D2WPage topLevelD2WPage(WOComponent sender) { WOComponent p = sender.parent(); WOComponent last = null; while(p != null) { if(p instanceof D2WPage) { last = p; } p = p.parent(); } return (D2WPage)last; } /** Utility to return the enclosing list page, if there is one. */ public static ListPageInterface parentListPage(WOComponent sender) { return (ListPageInterface)enclosingPageOfClass(sender, ListPageInterface.class); } /** Utility to return the enclosing edit page, if there is one. */ public static EditPageInterface parentEditPage(WOComponent sender) { return (EditPageInterface)enclosingPageOfClass(sender, EditPageInterface.class); } /** Utility to return the enclosing select page, if there is one. */ public static SelectPageInterface parentSelectPage(WOComponent sender) { return (SelectPageInterface)enclosingPageOfClass(sender, SelectPageInterface.class); } /** Utility to return the enclosing query page, if there is one. */ public static QueryPageInterface parentQueryPage(WOComponent sender) { return (QueryPageInterface)enclosingPageOfClass(sender, QueryPageInterface.class); } /** Utility to return the enclosing pick page, if there is one. */ public static ERDPickPageInterface parentPickPage(WOComponent sender) { return (ERDPickPageInterface)enclosingPageOfClass(sender, ERDPickPageInterface.class); } /** Utility to return the enclosing D2W page, if there is one. */ public D2WPage parentD2WPage(WOComponent sender) { return (D2WPage)enclosingPageOfClass(sender, D2WPage.class); } }