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

freemarker.ext.beans.BeansWrapperConfiguration Maven / Gradle / Ivy

There is a newer version: 7.0.58
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.ext.beans;

import freemarker.template.DefaultObjectWrapperBuilder;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateDateModel;
import freemarker.template.Version;
import freemarker.template._TemplateAPI;
import freemarker.template._VersionInts;

/**
 * Holds {@link BeansWrapper} configuration settings and defines their defaults.
 * You will not use this abstract class directly, but concrete subclasses like {@link BeansWrapperBuilder} and
 * {@link DefaultObjectWrapperBuilder}. Unless, you are developing a builder for a custom {@link BeansWrapper} subclass.
 * 
 * 

This class is designed so that its instances can be used as lookup keys in a singleton cache. This is also why * this class defines the configuration setting defaults for {@link BeansWrapper}, instead of leaving that to * {@link BeansWrapper} itself. (Because, the default values influence the lookup key, and the singleton needs to be * looked up without creating a {@link BeansWrapper} instance.) However, because instances are mutable, you should * deep-clone it with {@link #clone(boolean)} before using it as cache key. * * @since 2.3.21 */ public abstract class BeansWrapperConfiguration implements Cloneable { private final Version incompatibleImprovements; private ClassIntrospectorBuilder classIntrospectorBuilder; // Properties and their *defaults*: private boolean simpleMapWrapper = false; private boolean preferIndexedReadMethod; private int defaultDateType = TemplateDateModel.UNKNOWN; private ObjectWrapper outerIdentity = null; private boolean strict = false; private boolean useModelCache = false; // Attention! // - As this object is a cache key, non-normalized field values should be avoided. // - Fields with default values must be set until the end of the constructor to ensure that when the lookup happens, // there will be no unset fields. // - If you add a new field, review all methods in this class /** * @param incompatibleImprovements * See the corresponding parameter of {@link BeansWrapper#BeansWrapper(Version)}. Not {@code null}. Note * that the version will be normalized to the lowest version where the same incompatible * {@link BeansWrapper} improvements were already present, so for the returned instance * {@link #getIncompatibleImprovements()} might return a lower version than what you have specified * here. * @param isIncompImprsAlreadyNormalized * Tells if the {@code incompatibleImprovements} parameter contains an already normalized value. * This parameter meant to be {@code true} when the class that extends {@link BeansWrapper} needs to add * additional breaking versions over those of {@link BeansWrapper}. Thus, if this parameter is * {@code true}, the versions where {@link BeansWrapper} had breaking changes must be already factored * into the {@code incompatibleImprovements} parameter value, as no more normalization will happen. (You * can use {@link BeansWrapper#normalizeIncompatibleImprovementsVersion(Version)} to discover those.) * * @since 2.3.22 */ protected BeansWrapperConfiguration(Version incompatibleImprovements, boolean isIncompImprsAlreadyNormalized) { _TemplateAPI.checkVersionNotNullAndSupported(incompatibleImprovements); // We can't do this in the BeansWrapper constructor, as by that time the version is normalized. if (!isIncompImprsAlreadyNormalized) { _TemplateAPI.checkCurrentVersionNotRecycled( incompatibleImprovements, "freemarker.beans", "BeansWrapper"); } incompatibleImprovements = isIncompImprsAlreadyNormalized ? incompatibleImprovements : BeansWrapper.normalizeIncompatibleImprovementsVersion(incompatibleImprovements); this.incompatibleImprovements = incompatibleImprovements; preferIndexedReadMethod = incompatibleImprovements.intValue() < _VersionInts.V_2_3_27; classIntrospectorBuilder = new ClassIntrospectorBuilder(incompatibleImprovements); } /** * Same as {@link #BeansWrapperConfiguration(Version, boolean) BeansWrapperConfiguration(Version, false)}. */ protected BeansWrapperConfiguration(Version incompatibleImprovements) { this(incompatibleImprovements, false); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + incompatibleImprovements.hashCode(); result = prime * result + (simpleMapWrapper ? 1231 : 1237); result = prime * result + (preferIndexedReadMethod ? 1231 : 1237); result = prime * result + defaultDateType; result = prime * result + (outerIdentity != null ? outerIdentity.hashCode() : 0); result = prime * result + (strict ? 1231 : 1237); result = prime * result + (useModelCache ? 1231 : 1237); result = prime * result + classIntrospectorBuilder.hashCode(); return result; } /** * Two {@link BeansWrapperConfiguration}-s are equal exactly if their classes are identical ({@code ==}), and their * field values are equal. */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; BeansWrapperConfiguration other = (BeansWrapperConfiguration) obj; if (!incompatibleImprovements.equals(other.incompatibleImprovements)) return false; if (simpleMapWrapper != other.simpleMapWrapper) return false; if (preferIndexedReadMethod != other.preferIndexedReadMethod) return false; if (defaultDateType != other.defaultDateType) return false; if (outerIdentity != other.outerIdentity) return false; if (strict != other.strict) return false; if (useModelCache != other.useModelCache) return false; if (!classIntrospectorBuilder.equals(other.classIntrospectorBuilder)) return false; return true; } protected Object clone(boolean deepCloneKey) { try { BeansWrapperConfiguration clone = (BeansWrapperConfiguration) super.clone(); if (deepCloneKey) { clone.classIntrospectorBuilder = (ClassIntrospectorBuilder) classIntrospectorBuilder.clone(); } return clone; } catch (CloneNotSupportedException e) { throw new RuntimeException("Failed to clone BeansWrapperConfiguration", e); } } public boolean isSimpleMapWrapper() { return simpleMapWrapper; } /** See {@link BeansWrapper#setSimpleMapWrapper(boolean)}. */ public void setSimpleMapWrapper(boolean simpleMapWrapper) { this.simpleMapWrapper = simpleMapWrapper; } /** @since 2.3.27 */ public boolean getPreferIndexedReadMethod() { return preferIndexedReadMethod; } /** See {@link BeansWrapper#setPreferIndexedReadMethod(boolean)}. @since 2.3.27 */ public void setPreferIndexedReadMethod(boolean preferIndexedReadMethod) { this.preferIndexedReadMethod = preferIndexedReadMethod; } public int getDefaultDateType() { return defaultDateType; } /** See {@link BeansWrapper#setDefaultDateType(int)}. */ public void setDefaultDateType(int defaultDateType) { this.defaultDateType = defaultDateType; } public ObjectWrapper getOuterIdentity() { return outerIdentity; } /** * See {@link BeansWrapper#setOuterIdentity(ObjectWrapper)}, except here the default is {@code null} that means * the {@link ObjectWrapper} that you will set up with this {@link BeansWrapperBuilder} object. */ public void setOuterIdentity(ObjectWrapper outerIdentity) { this.outerIdentity = outerIdentity; } public boolean isStrict() { return strict; } /** See {@link BeansWrapper#setStrict(boolean)}. */ public void setStrict(boolean strict) { this.strict = strict; } public boolean getUseModelCache() { return useModelCache; } /** See {@link BeansWrapper#setUseCache(boolean)} (it means the same). */ public void setUseModelCache(boolean useModelCache) { this.useModelCache = useModelCache; } public Version getIncompatibleImprovements() { return incompatibleImprovements; } public int getExposureLevel() { return classIntrospectorBuilder.getExposureLevel(); } /** See {@link BeansWrapper#setExposureLevel(int)}. */ public void setExposureLevel(int exposureLevel) { classIntrospectorBuilder.setExposureLevel(exposureLevel); } public boolean getExposeFields() { return classIntrospectorBuilder.getExposeFields(); } /** See {@link BeansWrapper#setExposeFields(boolean)}. */ public void setExposeFields(boolean exposeFields) { classIntrospectorBuilder.setExposeFields(exposeFields); } public MemberAccessPolicy getMemberAccessPolicy() { return classIntrospectorBuilder.getMemberAccessPolicy(); } /** See {@link BeansWrapper#setMemberAccessPolicy(MemberAccessPolicy)}. */ public void setMemberAccessPolicy(MemberAccessPolicy memberAccessPolicy) { classIntrospectorBuilder.setMemberAccessPolicy(memberAccessPolicy); } public boolean getTreatDefaultMethodsAsBeanMembers() { return classIntrospectorBuilder.getTreatDefaultMethodsAsBeanMembers(); } /** See {@link BeansWrapper#setTreatDefaultMethodsAsBeanMembers(boolean)} */ public void setTreatDefaultMethodsAsBeanMembers(boolean treatDefaultMethodsAsBeanMembers) { classIntrospectorBuilder.setTreatDefaultMethodsAsBeanMembers(treatDefaultMethodsAsBeanMembers); } public MethodAppearanceFineTuner getMethodAppearanceFineTuner() { return classIntrospectorBuilder.getMethodAppearanceFineTuner(); } /** * See {@link BeansWrapper#setMethodAppearanceFineTuner(MethodAppearanceFineTuner)}; additionally, * note that currently setting this to non-{@code null} will disable class introspection cache sharing, unless * the value implements {@link SingletonCustomizer}. */ public void setMethodAppearanceFineTuner(MethodAppearanceFineTuner methodAppearanceFineTuner) { classIntrospectorBuilder.setMethodAppearanceFineTuner(methodAppearanceFineTuner); } MethodSorter getMethodSorter() { return classIntrospectorBuilder.getMethodSorter(); } void setMethodSorter(MethodSorter methodSorter) { classIntrospectorBuilder.setMethodSorter(methodSorter); } ClassIntrospectorBuilder getClassIntrospectorBuilder() { return classIntrospectorBuilder; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy