com.isotrol.impe3.freemarker.wrap.PortalObjectWrapper.java Source code

Java tutorial

Introduction

Here is the source code for com.isotrol.impe3.freemarker.wrap.PortalObjectWrapper.java

Source

/**
 * This file is part of Port@l
 * Port@l 3.0 - Portal Engine and Management System
 * Copyright (C) 2010  Isotrol, SA.  http://www.isotrol.com
 *
 * Port@l is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Port@l is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Port@l.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.isotrol.impe3.freemarker.wrap;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.isotrol.impe3.freemarker.wrap.PortalAPIModel.newModel;

import java.util.Arrays;
import java.util.Map;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.MapMaker;
import com.isotrol.impe3.api.ContentKey;
import com.isotrol.impe3.api.NavigationKey;
import com.isotrol.impe3.api.PageKey;
import com.isotrol.impe3.api.Route;
import com.isotrol.impe3.api.component.RenderContext;

import freemarker.template.DefaultObjectWrapper;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;

/**
 * FreeMarker object wrapper. This class is NOT THREAD SAFE.
 * @author Andres Rodriguez
 */
public final class PortalObjectWrapper extends DefaultObjectWrapper {
    private final RenderContext context;
    private final Map<Object, TemplateModel> models = new MapMaker().weakKeys().makeMap();
    private final Iterable<? extends PortalFreeMarkerModelFactory> factories;

    /**
     * Creates a new object wrapper.
     * @param context Render context.
     * @return The object wrapper to use.
     */
    public static ObjectWrapper create(RenderContext context) {
        return new PortalObjectWrapper(context, null);
    }

    /**
     * Creates a new object wrapper.
     * @param context Render context.
     * @param factories Additional factories.
     * @return The object wrapper to use.
     */
    public static ObjectWrapper create(RenderContext context,
            Iterable<? extends PortalFreeMarkerModelFactory> factories) {
        return new PortalObjectWrapper(context, factories);
    }

    PortalObjectWrapper(RenderContext context, Iterable<? extends PortalFreeMarkerModelFactory> factories) {
        this.context = checkNotNull(context, "The render context must be provided");
        if (factories == null || Iterables.isEmpty(factories)) {
            this.factories = Arrays.asList(Factory.values());
        } else {
            this.factories = ImmutableList.<PortalFreeMarkerModelFactory>builder()
                    .addAll(Arrays.asList(Factory.values())).addAll(factories).build();
        }
    }

    public RenderContext getContext() {
        return context;
    }

    @Override
    protected TemplateModel handleUnknownType(Object obj) throws TemplateModelException {
        // Should not happen.
        if (obj == null) {
            return super.wrap(null);
        }
        if (models.containsKey(obj)) {
            return models.get(obj);
        }
        for (PortalFreeMarkerModelFactory f : factories) {
            if (f.isInstance(obj)) {
                TemplateModel model = f.build(this, obj);
                models.put(obj, model);
                return model;
            }
        }
        return super.handleUnknownType(obj);
    }

    private enum Factory implements PortalFreeMarkerModelFactory {
        ROUTE(Route.class) {
            public TemplateModel build(PortalObjectWrapper wrapper, Object obj) {
                return newModel(wrapper, (Route) obj, PortalAPIMethodMap.ROUTE);
            }
        },
        PAGE_KEY(PageKey.class) {
            public TemplateModel build(PortalObjectWrapper wrapper, Object obj) {
                return newModel(wrapper, (PageKey) obj, PortalAPIMethodMap.PAGE_KEY);
            }
        },
        CONTENT_KEY(ContentKey.class) {
            public TemplateModel build(PortalObjectWrapper wrapper, Object obj) {
                return newModel(wrapper, (ContentKey) obj, PortalAPIMethodMap.CONTENT_KEY);
            }
        },
        NAVIGATION_KEY(PageKey.class) {
            public TemplateModel build(PortalObjectWrapper wrapper, Object obj) {
                return newModel(wrapper, (NavigationKey) obj, PortalAPIMethodMap.NAVIGATION_KEY);
            }
        };

        /** Object to wrap class. */
        private final Class<?> klass;

        private Factory(Class<?> klass) {
            this.klass = klass;
        }

        public final boolean isInstance(Object obj) {
            return klass.isInstance(obj);
        }
    };

}