Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
   * 
   * 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 freemarker.template;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 
The default implementation of the ObjectWrapper interface. Usually, you don't need to create instances of this, as an instance of this is already the default value of the object_wrapper setting. Then the incompatibleImprovements of the DefaultObjectWrapper will be the same that you have set for the Configuration itself. As of this writing, it's highly recommended to use incompatibleImprovements 2.3.22 (or higher).

If you still need to create an instance, that should be done with an DefaultObjectWrapperBuilder, not with its constructor, as that allows FreeMarker to reuse singletons. For new projects, it's recommended to set forceLegacyNonListCollections to false - something that setting incompatibleImprovements to 2.3.22 won't do.

This class is only thread-safe after you have finished calling its setter methods, and then safely published it (see JSR 133 and related literature). When used as part of Configuration, of course it's enough if that was safely published and then left unmodified.

 
 public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
    
    

Deprecated:
Use DefaultObjectWrapperBuilder instead, but mind its performance
 
     static final DefaultObjectWrapper instance = new DefaultObjectWrapper();
     
     static final private Class JYTHON_OBJ_CLASS;
     
     static final private ObjectWrapper JYTHON_WRAPPER;
     
     private boolean useAdaptersForContainers;
     private boolean forceLegacyNonListCollections;
    
    
Creates a new instance with the incompatible-improvements-version specified in Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS.

 
     public DefaultObjectWrapper() {
     }
    
    
Use DefaultObjectWrapperBuilder instead if possible. Instances created with this constructor won't share the class introspection caches with other instances. See freemarker.ext.beans.BeansWrapper.(freemarker.template.Version) (the superclass constructor) for more details.

Parameters:
incompatibleImprovements It's the same as in freemarker.ext.beans.BeansWrapper.(freemarker.template.Version), plus these changes:
  • 2.3.22 (or higher): The default value of useAdaptersForContainers changes to true.
Since:
2.3.21
 
     public DefaultObjectWrapper(Version incompatibleImprovements) {
         this(new DefaultObjectWrapperConfiguration(incompatibleImprovements) { }, false);
     }

    
Use DefaultObjectWrapper(freemarker.template.DefaultObjectWrapperConfiguration,boolean) instead if possible; it does the same, except that it tolerates a non-DefaultObjectWrapperConfiguration configuration too.

Since:
2.3.21
    protected DefaultObjectWrapper(BeansWrapperConfiguration bwCfgboolean writeProtected) {
        super(bwCfgwriteProtectedfalse);
        DefaultObjectWrapperConfiguration dowDowCfg = bwCfg instanceof DefaultObjectWrapperConfiguration
                ? (DefaultObjectWrapperConfigurationbwCfg
                : new DefaultObjectWrapperConfiguration(bwCfg.getIncompatibleImprovements()) { }; 
        finalizeConstruction(writeProtected);
    }

    
    protected DefaultObjectWrapper(DefaultObjectWrapperConfiguration dowCfgboolean writeProtected) {
        this((BeansWrapperConfigurationdowCfgwriteProtected);
    }
    
    static {
        Class cl;
        ObjectWrapper ow;
        try {
            cl = Class.forName("org.python.core.PyObject");
            ow = (ObjectWrapper) Class.forName(
                    "freemarker.ext.jython.JythonWrapper")
                    .getField("INSTANCE").get(null);
        } catch (Throwable e) {
            cl = null;
            ow = null;
            if (!(e instanceof ClassNotFoundException)) {
                try {
                    Logger.getLogger("freemarker.template.DefaultObjectWrapper")
                            .error("Failed to init Jython support, so it was disabled."e);
                } catch (Throwable e2) {
                    // ignore
                }
            }
        }
         = cl;
         = ow;
    }

    
Wraps the parameter object to TemplateModel interface(s). Simple types like numbers, strings, booleans and dates will be wrapped into the corresponding SimpleXxx classes (like SimpleNumber). java.util.Map-s, java.util.List-s, other java.util.Collection-s, arrays and java.util.Iterator-s will be wrapped into the corresponding SimpleXxx or DefaultXxxAdapter classes (like SimpleHash or DefaultMapAdapter), depending on getUseAdaptersForContainers() and getForceLegacyNonListCollections(). After that, the wrapping is handled by handleUnknownType(java.lang.Object), so see more there.
    public TemplateModel wrap(Object objthrows TemplateModelException {
        if (obj == null) {
            return super.wrap(null);
        }
        if (obj instanceof TemplateModel) {
            return (TemplateModelobj;
        }
        if (obj instanceof String) {
            return new SimpleScalar((Stringobj);
        }
        if (obj instanceof Number) {
            return new SimpleNumber((Numberobj);
        }
        if (obj instanceof java.util.Date) {
            if(obj instanceof java.sql.Date) {
                return new SimpleDate((java.sql.Dateobj);
            }
            if(obj instanceof java.sql.Time) {
                return new SimpleDate((java.sql.Timeobj);
            }
            if(obj instanceof java.sql.Timestamp) {
                return new SimpleDate((java.sql.Timestampobj);
            }
            return new SimpleDate((java.util.DateobjgetDefaultDateType());
        }
        final Class objClass = obj.getClass();
        if (objClass.isArray()) {
            if () {
                return DefaultArrayAdapter.adapt(objthis);
            } else {
                obj = convertArray(obj);
                // Falls through (a strange legacy...)
            }
        }
        if (obj instanceof Collection) {
            if () {
                if (obj instanceof List) {
                    return DefaultListAdapter.adapt((Listobjthis);
                } else {
                    return 
                            ? (TemplateModelnew SimpleSequence((Collectionobjthis)
                            : (TemplateModel) DefaultNonListCollectionAdapter.adapt((Collectionobjthis);
                }
            } else {
                return new SimpleSequence((Collectionobjthis);
            }
        }
        if (obj instanceof Map) {
            return 
                    ? (TemplateModel) DefaultMapAdapter.adapt((Mapobjthis)
                    : (TemplateModelnew SimpleHash((Mapobjthis);
        }
        if (obj instanceof Boolean) {
            return obj.equals(.) ? . : .;
        }
        if (obj instanceof Iterator) {
            return 
                    ? (TemplateModel) DefaultIteratorAdapter.adapt((Iteratorobjthis)
                    : (TemplateModelnew SimpleCollection((Iteratorobjthis);
        }
        return handleUnknownType(obj);
    }
    
    
Called for an object that aren't considered to be of a "basic" Java type, like for an application specific type, or for a W3C DOM node. In its default implementation, W3C org.w3c.dom.Node-s will be wrapped as freemarker.ext.dom.NodeModel-s (allows DOM tree traversal), Jython objects will be delegated to the JythonWrapper, others will be wrapped using freemarker.ext.beans.BeansWrapper.wrap(java.lang.Object).

When you override this method, you should first decide if you want to wrap the object in a custom way (and if so then do it and return with the result), and if not, then you should call the super method (assuming the default behavior is fine with you).

    protected TemplateModel handleUnknownType(Object objthrows TemplateModelException {
        if (obj instanceof Node) {
            return wrapDomNode(obj);
        }
        if ( != null  && .isInstance(obj)) {
            return .wrap(obj);
        }
        return super.wrap(obj); 
    }
    
    public TemplateModel wrapDomNode(Object obj) {
        return NodeModel.wrap((Nodeobj);
    }

    
Converts an array to a java.util.List.
    protected Object convertArray(Object arr) {
        final int size = Array.getLength(arr);
        ArrayList list = new ArrayList(size);
        for (int i=0;i<sizei++) {
            list.add(Array.get(arri));
        }
        return list;
    }

    
The getter pair of setUseAdaptersForContainers(boolean).

Since:
2.3.22
    public boolean getUseAdaptersForContainers() {
        return ;
    }

    
Sets if to wrap container objects (java.util.Map-s, java.util.List-s, arrays and such) the legacy copying approach or the newer adapter approach should be used. true is recommended, which is also the default when the incompatible_improvements of this instance was set to Configuration.VERSION_2_3_22 or higher. To understand the difference, check some of the classes that implement the two approaches:

See also the related Version History entry under 2.3.22 in the FreeMarker Manual, which gives a breakdown of the consequences.

Attention: For backward compatibility, currently, non-java.util.List collections (like java.util.Set-s) will only be wrapped with adapter approach (with DefaultNonListCollectionAdapter) if forceLegacyNonListCollections was set to false. Currently the default is true, but in new projects you should set it to false. See setForceLegacyNonListCollections(boolean) for more.

    public void setUseAdaptersForContainers(boolean useAdaptersForContainers) {
        checkModifiable();
        this. = useAdaptersForContainers;
    }
    
    
Getter pair of setForceLegacyNonListCollections(boolean); see there.

Since:
2.3.22
    public boolean getForceLegacyNonListCollections() {
        return ;
    }

    
Specifies whether non-java.util.List java.util.Collection-s (like java.util.Set-s) must be wrapped by pre-fetching into a SimpleSequence. The modern approach is wrapping into a DefaultNonListCollectionAdapter. This setting only has effect when getUseAdaptersForContainers() is also true, as otherwise SimpleSequence will be used regardless of this. In new projects you should set this to false. At least before incompatible_improvements 2.4.0 it defaults to true, because of backward compatibility concerns: with TemplateSequenceModel templates could access the items by index if they wanted to (the index values were defined by the iteration order). This was not very useful, or was even confusing, and it conflicts with the adapter approach.

    public void setForceLegacyNonListCollections(boolean forceLegacyNonListCollections) {
        checkModifiable();
        this. = forceLegacyNonListCollections;
    }

    
Returns the lowest version number that is equivalent with the parameter version.

Since:
2.3.22
    protected static Version normalizeIncompatibleImprovementsVersion(Version incompatibleImprovements) {
        _TemplateAPI.checkVersionNotNullAndSupported(incompatibleImprovements);
        Version bwIcI = BeansWrapper.normalizeIncompatibleImprovementsVersion(incompatibleImprovements);
        return incompatibleImprovements.intValue() < .
                || bwIcI.intValue() >= .
                ? bwIcI : .;
    }

    

Since:
2.3.22
    protected String toPropertiesString() {
        String bwProps = super.toPropertiesString();
        
        // Remove simpleMapWrapper, as its irrelevant for this wrapper:
        if (bwProps.startsWith("simpleMapWrapper")) {
            int smwEnd = bwProps.indexOf(',');
            if (smwEnd != -1) {
                bwProps = bwProps.substring(smwEnd + 1).trim();
            }
        }
        
        return "useAdaptersForContainers=" +  + ", forceLegacyNonListCollections="
                +  + ", " + bwProps;
    }
    
New to GrepCode? Check out our FAQ X