You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@freemarker.apache.org by Joson Choo <jo...@gmail.com> on 2019/11/01 02:49:30 UTC

How to pass Object parameter to an user-defined directive?

Hi all,
  I'm new for freemarker. I tried to create my customized directive as
below but could not run it in a right way:


public class TypeSimpleNameDirective implements TemplateDirectiveModel {

   private static final String PARAM_CLAZZ = "clazz";

   @Override
   public void execute(Environment env, Map params, TemplateModel[]
loopVars, TemplateDirectiveBody body) throws TemplateException,
IOException {
      // Check if no parameters were given:
      if (!params.containsKey(PARAM_CLAZZ)) {
         throw new TemplateModelException(
               "typeSimpleName required parameter clazz.");
      }
      if (!(params.get(PARAM_CLAZZ) instanceof ClassDescription)) {
         throw new TemplateModelException(
               "clazz should be a instance of ClassDescription but " +
ClassUtils.getShortClassName(params.get(PARAM_CLAZZ), "null") + " is
given.");
      }
      ClassDescription cls = (ClassDescription) params.get(PARAM_CLAZZ);
  ......
}


And then I used it like this:

<@typeSimpleName clazz=api.returnType></...@typeSimpleName>

The api.returnType is ClassDescription.

Then it threw an error:

> clazz should be a instance of ClassDescription but StringModel is given.


Any help is appreciated.

Re: How to pass Object parameter to an user-defined directive?

Posted by Joson Choo <jo...@gmail.com>.
Thanks a lot. I've fellow your guide and fixed the issue well.

Daniel Dekany <da...@gmail.com> 于2019年11月1日周五 下午7:33写道:

> TemplateDirectiveModel (and TemplateMethodModelEx) gets values as
> TemplateModel-s, so they behave similarly to the template language. (The
> template language treats objects according TemplateModel interfaces they
> implement, not based on their "original" type, if they had an original type
> at all.) Now, if you need to get back the original object, then you need to
> unwrap it, like this:
>
> // Let's assume we know that param is not null.
> Object unwapped;
> if (param instanceof AdapterTemplateModel) {
>    unwrapped = ((AdapterTemplateModel) tm).getAdaptedObject(Object.class);
> } else {
>   // Fail as it's not the expected type
>   ...
> }
>
> if (!(unwrapped instanceof ClassDescription)) {
>   // Fail as it's not the expected type
>   ...
> }
> ClassDescription cls = (ClassDescription) unwrapped;
>
>
> You can write a static utility method that does this easily. There's no
> such utility method in FreeMarker sadly... yet. Well, DeepUnwrap.unwrap is
> similar, but an overkill on one hand, and doesn't check for the expected
> class on the other.
>
> On Fri, Nov 1, 2019 at 3:49 AM Joson Choo <jo...@gmail.com> wrote:
>
> > Hi all,
> >   I'm new for freemarker. I tried to create my customized directive as
> > below but could not run it in a right way:
> >
> >
> > public class TypeSimpleNameDirective implements TemplateDirectiveModel {
> >
> >    private static final String PARAM_CLAZZ = "clazz";
> >
> >    @Override
> >    public void execute(Environment env, Map params, TemplateModel[]
> > loopVars, TemplateDirectiveBody body) throws TemplateException,
> > IOException {
> >       // Check if no parameters were given:
> >       if (!params.containsKey(PARAM_CLAZZ)) {
> >          throw new TemplateModelException(
> >                "typeSimpleName required parameter clazz.");
> >       }
> >       if (!(params.get(PARAM_CLAZZ) instanceof ClassDescription)) {
> >          throw new TemplateModelException(
> >                "clazz should be a instance of ClassDescription but " +
> > ClassUtils.getShortClassName(params.get(PARAM_CLAZZ), "null") + " is
> > given.");
> >       }
> >       ClassDescription cls = (ClassDescription) params.get(PARAM_CLAZZ);
> >   ......
> > }
> >
> >
> > And then I used it like this:
> >
> > <@typeSimpleName clazz=api.returnType></...@typeSimpleName>
> >
> > The api.returnType is ClassDescription.
> >
> > Then it threw an error:
> >
> > > clazz should be a instance of ClassDescription but StringModel is
> given.
> >
> >
> > Any help is appreciated.
> >
>
>
> --
> Best regards,
> Daniel Dekany
>

Re: How to pass Object parameter to an user-defined directive?

Posted by Daniel Dekany <da...@gmail.com>.
TemplateDirectiveModel (and TemplateMethodModelEx) gets values as
TemplateModel-s, so they behave similarly to the template language. (The
template language treats objects according TemplateModel interfaces they
implement, not based on their "original" type, if they had an original type
at all.) Now, if you need to get back the original object, then you need to
unwrap it, like this:

// Let's assume we know that param is not null.
Object unwapped;
if (param instanceof AdapterTemplateModel) {
   unwrapped = ((AdapterTemplateModel) tm).getAdaptedObject(Object.class);
} else {
  // Fail as it's not the expected type
  ...
}

if (!(unwrapped instanceof ClassDescription)) {
  // Fail as it's not the expected type
  ...
}
ClassDescription cls = (ClassDescription) unwrapped;


You can write a static utility method that does this easily. There's no
such utility method in FreeMarker sadly... yet. Well, DeepUnwrap.unwrap is
similar, but an overkill on one hand, and doesn't check for the expected
class on the other.

On Fri, Nov 1, 2019 at 3:49 AM Joson Choo <jo...@gmail.com> wrote:

> Hi all,
>   I'm new for freemarker. I tried to create my customized directive as
> below but could not run it in a right way:
>
>
> public class TypeSimpleNameDirective implements TemplateDirectiveModel {
>
>    private static final String PARAM_CLAZZ = "clazz";
>
>    @Override
>    public void execute(Environment env, Map params, TemplateModel[]
> loopVars, TemplateDirectiveBody body) throws TemplateException,
> IOException {
>       // Check if no parameters were given:
>       if (!params.containsKey(PARAM_CLAZZ)) {
>          throw new TemplateModelException(
>                "typeSimpleName required parameter clazz.");
>       }
>       if (!(params.get(PARAM_CLAZZ) instanceof ClassDescription)) {
>          throw new TemplateModelException(
>                "clazz should be a instance of ClassDescription but " +
> ClassUtils.getShortClassName(params.get(PARAM_CLAZZ), "null") + " is
> given.");
>       }
>       ClassDescription cls = (ClassDescription) params.get(PARAM_CLAZZ);
>   ......
> }
>
>
> And then I used it like this:
>
> <@typeSimpleName clazz=api.returnType></...@typeSimpleName>
>
> The api.returnType is ClassDescription.
>
> Then it threw an error:
>
> > clazz should be a instance of ClassDescription but StringModel is given.
>
>
> Any help is appreciated.
>


-- 
Best regards,
Daniel Dekany