You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by ve...@jakarta.apache.org on 2004/11/05 06:55:37 UTC

[Jakarta-Velocity Wiki] New: MultiUberspect

   Date: 2004-11-04T21:55:37
   Editor: EricFixler <fi...@fixler.com>
   Wiki: Jakarta-Velocity Wiki
   Page: MultiUberspect
   URL: http://wiki.apache.org/jakarta-velocity/MultiUberspect

   no comment

New Page:

/** org.apache.velocity.tools.generic.introspection.MultiUberspect
    Allows Velocity to Introspect other types of Objects
    November 2004
    Eric Fixler <fi...@smete.org>
    $Id: MultiUberspect.java,v 1.1.2.2 2004/11/05 05:51:00 fix Exp $
*/

/*
 * Copyright 2003-2004 The Apache Software Foundation.
 *
 * 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 org.apache.velocity.tools.generic.introspection;

import java.util.*;

import org.apache.velocity.util.introspection.Info;
import org.apache.velocity.util.introspection.Uberspect;
import org.apache.velocity.util.introspection.UberspectImpl;
import org.apache.velocity.util.introspection.VelPropertyGet;
import org.apache.velocity.util.introspection.VelPropertySet;

/**
 * Expanded Uberspect implementation that allows you to designate custom Uberspects on 
 * a per class basis, so that classes that don't follow the Java Beans specification can
 * be handled like beans in Velocity Templates.
 *
 * <p>To use, tell Velocity to use this class for introspection
 * by adding the following to your velocity.properties:<br />
 *
 * <code>
 * runtime.introspector.uberspect = org.apache.velocity.tools.generic.introspection.MultiUberspect
 * </code>
 * </p>
 *
 * @author <a href="mailto:fix@smete.org">Eric Fixler</a>
 * @version $Id: MultiUberspect.java,v 1.1.2.2 2004/11/05 05:51:00 fix Exp $
 */    
 
 public class MultiUberspect extends UberspectImpl {
     private final Map    customIntrospectors = new HashMap();
     private final Map    derivedIntrospectors = new HashMap();
     
     public MultiUberspect() {}
     
     protected boolean useSuperclassIntrospector = false;
     
     /** <p>If true, and a class is encountered for which a custom Uberspect has not been registered, 
         will check to see if any superclasses of class have registered Uberspects.  If so, will use
         the superclass' Uberspect.</p>
         <p>When false (the default), will only return a custom Uberspect if the requested Objects  class
         has had a Uberspect explicitly registered.</p>
         
          @param b the flag
     */
     
     public void             setUseSuperclassIntrospector(boolean b) { this.useSuperclassIntrospector = b; }
     
     /** Whether of not we will look for a superclass Uberspect if an exact match for a custom Uberspect is not found. */
     
     public final boolean     getUseSuperclassIntrospector() { return this.useSuperclassIntrospector; }
     
     /** Register a custom uberspect
     
         @param clz     The class handled by this Uberspect
         @param u    The Uberspect
     */
     
     public void addIntrospector(Class clz, Uberspect u) {
         try {
             u.init();
         } catch (Exception e) {
             return;
         }
         this.customIntrospectors.put(clz, u);
         this.derivedIntrospectors.clear();
         this.derivedIntrospectors.put(clz, u);
     }
     
     /** Unregister a custom uberspect.
     
         @param clz     The class handled by the Uberspect
     */
     
     public void removeIntrospector(Class clz) {
         this.customIntrospectors.remove(clz);
         this.derivedIntrospectors.clear();
         this.derivedIntrospectors.putAll(this.customIntrospectors);
     }
     
     /** Get the Uberspect, if one exists 
     
         @param clz The class for which to get an Uberspect
         @return an Uberspect, or null if none exists
     */
     
     protected Uberspect getCustomIntrospector(Class clz) {
         Uberspect uber = (Uberspect) this.derivedIntrospectors.get(clz);
         if ((! this.useSuperclassIntrospector) || (uber != null)) return uber;
         synchronized(this.derivedIntrospectors) {
             Iterator it = this.customIntrospectors.entrySet().iterator();
             while (it.hasNext()) {
                 Map.Entry entry = (Map.Entry) it.next();
                Class checkClz     = (Class) entry.getKey();
                if (checkClz.isAssignableFrom(clz))  {
                    uber = (Uberspect) entry.getValue();
                    this.derivedIntrospectors.put(clz, uber);
                    return uber;
                }
             }
         }
         return null;
     }
     
     /**
     * Property getter - returns VelPropertyGet appropos for #set($foo = $bar.woogie).
     * <br />
     * Looks to see if a custom Uberspect has been registered for obj.getClass().  
     * If a getter was not found, tries the regular routine.
     *
     * @param obj the object
     * @param identifier the name of the property
     * @param info a bunch of information.
     * @return a valid <code>VelPropertyGet</code>, if it was found.
     * @throws Exception failed to create a valid <code>VelPropertyGet</code>.
     */
    public VelPropertyGet getPropertyGet(Object obj, String identifier, Info info)
            throws Exception
    {
        
        Uberspect uberspect = (Uberspect) this.getCustomIntrospector(obj.getClass());
        return (uberspect != null)  
                ? uberspect.getPropertyGet(obj, identifier, info)
                : super.getPropertyGet(obj, identifier, info);
    }
    
     /**
     * Property setter - returns VelPropertySet appropos for #set($foo.bar = "geir").
     * <br />
     * Looks to see if a custom Uberspect has been registered for obj.getClass().  
     * If a setter was not found, tries the regular routine.
     *
     * @param obj the object
     * @param identifier the name of the property
     * @param arg the value to set to the property
     * @param info a bunch of information.
     * @return a valid <code>VelPropertySet</code>, if it was found.
     * @throws Exception failed to create a valid <code>VelPropertySet</code>.
     */
    public VelPropertySet getPropertySet(Object obj, String identifier,
            Object arg, Info info) throws Exception
    {
        Uberspect uberspect = (Uberspect) this.getCustomIntrospector(obj.getClass());
        return (uberspect != null) 
            ? uberspect.getPropertySet(obj, identifier, arg, info)
            : super.getPropertySet(obj, identifier, arg, info);
    }
     
     /** 
         Change this source if you use this, since you won't have the classes referenced here.
         (Obviously, would be better to assign the mappings elsewhere)
     */
     public void init() throws Exception {
         super.init();
         this.addIntrospector(Class.forName("com.canto.cumulus.Record"), new CumulusRecordUberspect()); 
     }
     
 }
 
 // $Log: MultiUberspect.java,v $
 // Revision 1.1.2.2  2004/11/05 05:51:00  fix
 // Added useSuperclassIntrospector to turn superclass scaling on and off
 //

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org