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

com.alogient.cameleon.sdk.content.service.impl.PageServiceImpl Maven / Gradle / Ivy

The newest version!
package com.alogient.cameleon.sdk.content.service.impl;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alogient.cameleon.sdk.content.dao.PageDao;
import com.alogient.cameleon.sdk.content.dao.model.Element;
import com.alogient.cameleon.sdk.content.dao.model.Nav;
import com.alogient.cameleon.sdk.content.dao.model.Option;
import com.alogient.cameleon.sdk.content.dao.model.OptionCulture;
import com.alogient.cameleon.sdk.content.dao.model.Page;
import com.alogient.cameleon.sdk.content.dao.model.Part;
import com.alogient.cameleon.sdk.content.dao.model.Template;
import com.alogient.cameleon.sdk.content.model.AbstractCameleonModel;
import com.alogient.cameleon.sdk.content.model.ImageModel;
import com.alogient.cameleon.sdk.content.model.ImageUpdateModel;
import com.alogient.cameleon.sdk.content.model.ResourceModel;
import com.alogient.cameleon.sdk.content.service.MediaService;
import com.alogient.cameleon.sdk.content.service.PageService;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModel;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelAllElements;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelClosestUpElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelElement.DataType;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelFirstElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelImage;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelLinkedElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelLinkedElements;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelParentElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelResource;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelReverseLinkedElements;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelSubElements;
import com.alogient.cameleon.sdk.content.util.InternalCameleonConfig;
import com.alogient.cameleon.sdk.content.util.exception.InvalidModelFieldAccessException;
import com.alogient.cameleon.sdk.content.util.exception.InvalidModelFieldConvertionException;
import com.alogient.cameleon.sdk.content.util.exception.ModelInstanciationException;
import com.alogient.cameleon.sdk.content.util.exception.NoCompatibleModelFoundException;
import com.alogient.cameleon.sdk.content.util.exception.PageNotFoundException;
import com.alogient.cameleon.sdk.content.util.exception.UnknowModelException;
import com.alogient.cameleon.sdk.content.util.nav.ModeType;
import com.alogient.cameleon.sdk.content.vo.CultureVo;
import com.alogient.cameleon.sdk.content.vo.media.ImageType;
import com.alogient.cameleon.sdk.content.vo.media.VideoVo;
import com.alogient.cameleon.sdk.form.service.FormService;
import com.alogient.cameleon.sdk.form.util.exception.FormNotFoundException;
import com.alogient.cameleon.sdk.form.vo.FormVo;
import com.alogient.cameleon.sdk.membership.dao.MembershipDao;
import com.alogient.cameleon.sdk.membership.dao.model.Pagegroupaccess;
import com.google.common.collect.ImmutableList;

public class PageServiceImpl implements PageService {
    /**
     * Logger for this class
     */
    private static transient Logger log = LoggerFactory.getLogger(PageServiceImpl.class);

    /**
     * The page data access object
     */
    private PageDao pageDao;

    /**
     * The media service
     */
    private MediaService mediaService;

    /**
     * The form service
     */
    private FormService formService;

    /**
     * The membership service
     */
    private MembershipDao membershipDao;

    /**
     * @param pageDao the pageDao to set
     */
    public void setPageDao(PageDao pageDao) {
        this.pageDao = pageDao;
    }

    /**
     * @param mediaService the mediaService to set
     */
    public void setMediaService(MediaService mediaService) {
        this.mediaService = mediaService;
    }

    /**
     * @param membershipDao the membershipDao to set
     */
    public void setMembershipDao(MembershipDao membershipDao) {
        this.membershipDao = membershipDao;
    }

    /**
     * @param formService the formService to set
     */
    public void setFormService(FormService formService) {
        this.formService = formService;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean exist(CultureVo cultureVo, Integer pageId, Boolean isLive) {
        return pageDao.exist(cultureVo.getCultureId(), pageId, isLive);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public  T getPage(Integer pageId, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass) throws PageNotFoundException {
        // Check the model
        checkModelsForAnnotation(modelClass);

        // Get the page from the database
        Page page = pageDao.getPage(pageId);

        // Does the page exist (since we need to process it afterwards getting
        // it is not a wastefull test)
        if (page == null) {
            throw new PageNotFoundException("Page does not exist.");
        }

        // Is the page visible in the targe environnement
        if (!page.isVisible(isLiveMode)) {
            throw new PageNotFoundException("Page is not visible in this environnement.");
        }

        // Check that the templates matches the model
        getPageClass(page, modelClass);

        return convertPageToModel(page, isLiveMode, isSecurityAware, modelClass);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public  T getPage(CultureVo cultureVo, Integer navId, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass)
            throws PageNotFoundException {
        // Check the model
        checkModelsForAnnotation(modelClass);

        // Get the page from the database
        Page page = pageDao.getPage(cultureVo.getCultureId(), navId);

        // Does the page exist (since we need to process it afterwards getting
        // it is not a wastefull test)
        if (page == null) {
            throw new PageNotFoundException("Page does not exist.");
        }

        // Is the page visible in the targe environnement
        if (!page.isVisible(isLiveMode)) {
            throw new PageNotFoundException("Page is not visible in this environnement.");
        }

        // Check that the templates matches the model
        getPageClass(page, modelClass);

        return convertPageToModel(page, isLiveMode, isSecurityAware, modelClass);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public  List getSubPages(Integer pageId, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass) throws PageNotFoundException {
        return getSubPages(modelClass, pageId, isLiveMode, isSecurityAware, modelClass);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public  List getSubPages(Class modelClass, Integer pageId, Boolean isLiveMode, Boolean isSecurityAware,
            Class... modelClasses) throws PageNotFoundException {

        // Check the model
        checkModelsForAnnotation(modelClasses);

        List subPages = pageDao.getSubPages(pageId);
        List subPageVos = new LinkedList();

        if (subPages != null) {
            for (Page childPage : subPages) {
                if (childPage.isVisible(isLiveMode)) {
                    try {
                        getPageClass(childPage, modelClasses);
                        subPageVos.add(convertPageToModel(childPage, isLiveMode, isSecurityAware, modelClass));
                    } catch (NoCompatibleModelFoundException e) {
                        // Ignore any kind of model which is not searched
                        if (log.isDebugEnabled()) {
                            log.debug(e.toString());
                        }

                    }
                }
            }
        }
        return subPageVos;

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List getSubPages(Integer pageId, Boolean isLiveMode, Boolean isSecurityAware, Class... modelClass)
            throws PageNotFoundException {
        // Check the model
        checkModelsForAnnotation(modelClass);

        List subPages = pageDao.getSubPages(pageId);
        List subPageVos = new LinkedList();

        if (subPages != null) {
            for (Page childPage : subPages) {

                if (childPage.isVisible(isLiveMode)) {
                    if (childPage.getNav().getTemplate() != null && "Virtual".equals(childPage.getNav().getTemplate().getTemplateName())) {
                        Integer targetNavId = null;
                        for (Element element : childPage.getElements()) {
                            if ("targetNavId".equals(element.getPart().getPartName())) {
                                if (StringUtils.isNotBlank(isLiveMode ? element.getValue() : element.getPreviewValue())
                                        && StringUtils.isNumeric(isLiveMode ? element.getValue() : element.getPreviewValue())) {
                                    targetNavId = new Integer(isLiveMode ? element.getValue() : element.getPreviewValue());
                                    break;
                                }
                            }
                        }

                        if (targetNavId != null) {
                            if (log.isDebugEnabled()) {
                                log.debug("Getting target of a vitural");
                            }
                            childPage = pageDao.getPage(childPage.getCulture().getCultureId(), targetNavId);
                        }
                    }

                    try {
                        subPageVos.add(convertPageToModel(childPage, isLiveMode, isSecurityAware, getPageClass(childPage, modelClass)));
                    } catch (Exception e) {
                        // Ignore any kind of model which is not searched
                        if (log.isDebugEnabled()) {
                            log.debug(e.toString());
                        }
                    }
                }
            }
        }

        return subPageVos;
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    public  List getSubPages(CultureVo cultureVo, Integer navId, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass)
            throws PageNotFoundException {
        // Check the model
        checkModelsForAnnotation(modelClass);

        List subPages = pageDao.getSubPages(cultureVo.getCultureId(), navId);
        List subPageVos = new LinkedList();

        if (subPages != null) {
            for (Page childPage : subPages) {
                if (childPage.isVisible(isLiveMode)) {
                    try {
                        getPageClass(childPage, modelClass);
                        subPageVos.add(convertPageToModel(childPage, isLiveMode, isSecurityAware, modelClass));
                    } catch (NoCompatibleModelFoundException e) {
                        // Ignore any kind of model which is not searched
                        if (log.isDebugEnabled()) {
                            log.debug(e.toString());
                        }

                    }
                }
            }
        }
        return subPageVos;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List getSubPages(CultureVo cultureVo, Integer navId, Boolean isLiveMode, Boolean isSecurityAware,
            Class... modelClass) throws PageNotFoundException {
        // Check the model
        checkModelsForAnnotation(modelClass);

        List subPages = pageDao.getSubPages(cultureVo.getCultureId(), navId);
        List subPageVos = new LinkedList();

        if (subPages != null) {
            for (Page childPage : subPages) {
                if (childPage.isVisible(isLiveMode)) {
                    try {
                        subPageVos.add(convertPageToModel(childPage, isLiveMode, isSecurityAware, getPageClass(childPage, modelClass)));
                    } catch (Exception e) {
                        // Ignore any kind of model which is not searched
                        if (log.isDebugEnabled()) {
                            log.debug(e.toString());
                        }
                    }
                }
            }
        }
        return subPageVos;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @SuppressWarnings("unchecked")
    public  List getPages(CultureVo cultureVo, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass) {
        CameleonModel targetModel = modelClass.getAnnotation(CameleonModel.class);
        List pages = pageDao.getTemplatePages(targetModel.templateName(), cultureVo.getCultureId());
        List pageVos = new LinkedList();

        if (pages != null) {
            for (Page childPage : pages) {
                if (childPage.isVisible(isLiveMode)) {
                    try {
                        getPageClass(childPage, modelClass);
                        pageVos.add(convertPageToModel(childPage, isLiveMode, isSecurityAware, modelClass));
                    } catch (Exception e) {
                        // Ignore any kind of model which is not searched
                        if (log.isDebugEnabled()) {
                            log.debug(e.toString());
                        }
                    }
                }
            }
        }
        return pageVos;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public  List getPages(CultureVo cultureVo, String multiAssociationNavIds, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass) {
        if (StringUtils.isBlank(multiAssociationNavIds)) {
            return null;
        }

        String[] navIds = multiAssociationNavIds.split(";");

        List pages = new ArrayList();
        for (String navIdStr : navIds) {
            if (StringUtils.isBlank(navIdStr) || !StringUtils.isNumeric(navIdStr)) {
                continue;
            }

            Integer navId = new Integer(navIdStr);
            try {
                pages.add(getPage(cultureVo, navId, isLiveMode, isSecurityAware, modelClass));
            } catch (PageNotFoundException e) {
                // Ignore any kind of model which is not searched
                if (log.isDebugEnabled()) {
                    log.debug(e.toString());
                }
            }
        }

        return pages;
    }

    /**
     * Verifies if all model classes are properly annoted to resolve to a template
     * 
     * @param modelClasses The classes to test
     * @throws UnknowModelException If the model is not mapped to a template this exception will be thrown
     */
    private void checkModelsForAnnotation(Class... modelClasses) throws UnknowModelException {
        for (Class modelClass : modelClasses) {
            CameleonModel cm = modelClass.getAnnotation(CameleonModel.class);

            if (cm == null) {
                throw new UnknowModelException("Model '" + modelClass.getName() + "' doesn't have the @CameleonModel. Cannot convert it.");
            }
        }
    }

    /**
     * Returns the model class associated with a page
     * 
     * @param page The page we want the model class for
     * @param modelClasses The available model classes
     * @return The associated model class (if any otherwise an exception is thrown)
     * @throws NoCompatibleModelFoundException Thrown of no modelClassess matches the template of the page
     */
    private Class getPageClass(Page page, Class... modelClasses) throws NoCompatibleModelFoundException {
        // Get page template
        String pageTemplateName = page.getNav().getTemplate().getTemplateName();

        for (Class modelClass : modelClasses) {
            CameleonModel cm = modelClass.getAnnotation(CameleonModel.class);

            if (pageTemplateName.equals(cm.templateName())) {
                return modelClass;
            }
        }

        // If we are here, it means that not correct class has been found. We
        // can afford to have a slow process because this is an error
        // case.
        StringBuffer sb = new StringBuffer("No class found for template '" + pageTemplateName + "' in templates :");
        for (Class modelClass : modelClasses) {
            CameleonModel cm = modelClass.getAnnotation(CameleonModel.class);
            sb.append("\n - ");
            sb.append(cm.templateName());
        }

        throw new NoCompatibleModelFoundException(sb.toString());
    }

    /**
     * Converts a page to it's associated model
     * 
     * @param  The target model class
     * @param page The page to convert
     * @param isLiveMode The mode to convert in
     * @param modelClass The target model class
     * @param isSecurityAware Should the security information be embeded into the menu
     * @return The converted model
     * @throws ModelInstanciationException If the model class could not be instanciated into an object
     * @throws InvalidModelFieldConvertionException Thrown if we cannot convert the string value into the field target
     *             type
     * @throws InvalidModelFieldAccessException Thrown if we cannot access the field
     */
    private  T convertPageToModel(Page page, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass) throws ModelInstanciationException,
            InvalidModelFieldConvertionException, InvalidModelFieldAccessException {
        // Build an element map
        Map elements = new HashMap();

        if (page.getElements() != null) {
            for (Element element : page.getElements()) {
                elements.put(element.getPart().getPartName(), element);
            }
        }

        T model;

        try {
            model = modelClass.newInstance();
        } catch (InstantiationException e) {
            throw new ModelInstanciationException("Model MUST be a valid non-abstract class with an empty constructor.", e);
        } catch (IllegalAccessException e) {
            throw new ModelInstanciationException("Model MUST be a valid non-abstract class with an empty constructor.", e);
        }

        // Set common fields
        model.setPageId(page.getPageId());
        model.setNavId(page.getNav().getNavId());
        model.setPageName(isLiveMode ? page.getPageName() : page.getPageNamePreview());
        model.setCreationDate(page.getCreationDate());
        model.setLastModified(page.getLastModified());
        model.setCultureCode(page.getCulture().getCultureCode());

        if (isSecurityAware) {
            Nav toProcess = page.getNav();

            do {
                List roles = membershipDao.getRolesForNavId(toProcess.getNavId());

                for (Pagegroupaccess role : roles) {
                    model.addRole(role.getPk().getRolename());
                }

                toProcess = toProcess.getParent();
            } while (toProcess != null);
        }

        Class aClass = modelClass;
        do {
            Field[] fields = aClass.getDeclaredFields();

            for (Field field : fields) {
                // Check cameleon model
                if (field.isAnnotationPresent(CameleonModelElement.class)) {
                    CameleonModelElement cme = field.getAnnotation(CameleonModelElement.class);

                    if (cme != null) {
                        Element element = elements.get(cme.elementName().trim());
                        if (element != null) {
                            if (cme.dataType() == DataType.Value) {
                                setFieldValue(isLiveMode ? element.getValue() : element.getPreviewValue(), model, field);
                            } else if (cme.dataType() == DataType.OptionValue) {
                                if (element.getPart() == null || element.getPart().getOptions() == null) {
                                    continue;
                                }

                                String selectedItem = isLiveMode ? element.getValue() : element.getPreviewValue();
                                Option selectedOption = null;
                                for (Option option : element.getPart().getOptions()) {
                                    if (option.getName().equals(selectedItem)) {
                                        selectedOption = option;
                                        break;
                                    }
                                }

                                if (selectedOption == null) {
                                    break;
                                }

                                for (OptionCulture optionCulture : selectedOption.getOptionCultures()) {
                                    if (optionCulture.getCulture().getCultureId().equals(page.getCulture().getCultureId())) {

                                        setFieldValue(optionCulture.getDisplayName(), model, field);
                                        break;
                                    }
                                }
                            } else if (cme.dataType() == DataType.PartId) {
                                setFieldValue(element.getPart().getPartId().toString(), model, field);
                            } else if (cme.dataType() == DataType.File) {
                                setFieldValue(isLiveMode ? element.getFile() : element.getPreviewFile(), model, field);
                            } else if (cme.dataType() == DataType.Form) {
                                String idStr = isLiveMode ? element.getValue() : element.getPreviewValue();
                                if (StringUtils.isNumeric(idStr)) {
                                    FormVo form;
                                    try {
                                        form = formService.getForm(new Integer(idStr), page.getCulture().getCultureId(), isLiveMode);
                                        setFieldValue(form, model, field);
                                    } catch (NumberFormatException e) {
                                        log.error(e.getMessage(), e);
                                    } catch (FormNotFoundException e) {
                                        log.error(e.getMessage(), e);
                                    }
                                }
                            } else if (cme.dataType() == DataType.Video) {
                                VideoVo video = null;

                                if ((isLiveMode ? element.getValue() : element.getPreviewValue()) != null) {
                                    try {
                                        video = mediaService.getVideo(new Integer(isLiveMode ? element.getValue() : element.getPreviewValue()), page.getCulture().getCultureId(),
                                                isLiveMode);
                                    } catch (NumberFormatException nfe) {
                                        // Just ignore it
                                    }
                                }

                                setFieldValue(video, model, field);
                            }
                        }
                    }
                }
                if (field.isAnnotationPresent(CameleonModelImage.class)) {
                    CameleonModelImage cme = field.getAnnotation(CameleonModelImage.class);

                    if (cme != null) {
                        Element element = elements.get(cme.elementName().trim());
                        if (element != null) {
                            String alt = isLiveMode ? element.getValue() : element.getPreviewValue();
                            String file = isLiveMode ? element.getFile() : element.getPreviewFile();
                            Integer partId = element.getPart().getPartId();

                            if (StringUtils.isNotBlank(file)) {
                                setFieldValue(new ImageModel(alt, file, partId), model, field);
                            }
                        }
                    }
                }
                if (field.isAnnotationPresent(CameleonModelResource.class)) {
                    CameleonModelResource cme = field.getAnnotation(CameleonModelResource.class);

                    if (cme != null) {
                        Element element = elements.get(cme.elementName().trim());
                        if (element != null) {
                            String file = isLiveMode ? element.getFile() : element.getPreviewFile();
                            Integer partId = element.getPart().getPartId();

                            if (StringUtils.isNotBlank(file)) {
                                setFieldValue(new ResourceModel(file, page.getNav().getNavId(), partId, page.getCulture().getCultureCode(), ModeType.getEnum(isLiveMode)), model,
                                        field);
                            }
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelLinkedElement.class)) {
                    CameleonModelLinkedElement cmle = field.getAnnotation(CameleonModelLinkedElement.class);

                    if (cmle != null) {
                        Element element = elements.get(cmle.elementName().trim());

                        if (element != null && StringUtils.isNotBlank(isLiveMode ? element.getValue() : element.getPreviewValue())
                                && StringUtils.isNumeric(isLiveMode ? element.getValue() : element.getPreviewValue())) {
                            Integer navId = Integer.parseInt(isLiveMode ? element.getValue() : element.getPreviewValue());

                            Object o = null;

                            try {
                                o = getPage(new CultureVo(page.getCulture()), navId, isLiveMode, isSecurityAware, cmle.templateClass());
                            } catch (PageNotFoundException pnfe) {
                                log.error("Could not find linked page " + navId + " isLiveMode " + isLiveMode + " template " + cmle.templateClass().getName());
                                log.debug(pnfe.getMessage(), pnfe);
                            }

                            setFieldValue(o, model, field);
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelLinkedElements.class)) {
                    CameleonModelLinkedElements cmles = field.getAnnotation(CameleonModelLinkedElements.class);

                    if (cmles != null) {
                        Element element = elements.get(cmles.elementName().trim());

                        if (element != null && StringUtils.isNotBlank(isLiveMode ? element.getValue() : element.getPreviewValue())) {
                            String[] idStr = (isLiveMode ? element.getValue() : element.getPreviewValue()).split(";");

                            List subElements = new ArrayList();

                            for (String id : idStr) {
                                if (StringUtils.isNotBlank(id) && StringUtils.isNumeric(id)) {
                                    try {
                                        AbstractCameleonModel o = getPage(new CultureVo(page.getCulture()), Integer.parseInt(id), isLiveMode, isSecurityAware,
                                                cmles.templateClass());

                                        if (o != null) {
                                            subElements.add(o);
                                        }
                                    } catch (PageNotFoundException pnfe) {
                                        log.debug(pnfe.getMessage(), pnfe);
                                    }
                                }
                            }

                            setFieldValue(ImmutableList.copyOf(subElements), model, field);
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelReverseLinkedElements.class)) {
                    CameleonModelReverseLinkedElements reverseLink = field.getAnnotation(CameleonModelReverseLinkedElements.class);

                    if (reverseLink != null && reverseLink.templateClass().isAnnotationPresent(CameleonModel.class)) {
                        CameleonModel targetModel = reverseLink.templateClass().getAnnotation(CameleonModel.class);

                        // Get all pages for target model template
                        List subElements = new ArrayList();

                        List targetPages = pageDao.getTemplatePages(targetModel.templateName(), page.getCulture().getCultureId());

                        for (Page targetPage : targetPages) {
                            if (targetPage.isVisible(isLiveMode)) {
                                for (Element element : targetPage.getElements()) {
                                    if (element.getPart().getPartName().equals(reverseLink.elementName())) {
                                        String idStrs = isLiveMode ? element.getValue() : element.getPreviewValue();
                                        if (StringUtils.isNotBlank(idStrs)) {
                                            String[] idStrArr = idStrs.split(";");

                                            for (String idStr : idStrArr) {
                                                if (StringUtils.isNumeric(idStr)) {
                                                    int id = Integer.parseInt(idStr);

                                                    if (id == page.getNav().getNavId().intValue()) {
                                                        subElements.add(convertPageToModel(targetPage, isLiveMode, isSecurityAware, reverseLink.templateClass()));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        setFieldValue(ImmutableList.copyOf(subElements), model, field);
                    }
                } else if (field.isAnnotationPresent(CameleonModelAllElements.class)) {
                    CameleonModelAllElements reverseLink = field.getAnnotation(CameleonModelAllElements.class);

                    if (reverseLink != null && reverseLink.templateClass().isAnnotationPresent(CameleonModel.class)) {
                        CameleonModel targetModel = reverseLink.templateClass().getAnnotation(CameleonModel.class);

                        // Get all pages for target model template
                        List subElements = new ArrayList();

                        List targetPages = pageDao.getTemplatePages(targetModel.templateName(), page.getCulture().getCultureId());

                        for (Page targetPage : targetPages) {
                            if (targetPage.isVisible(isLiveMode)) {
                                subElements.add(convertPageToModel(targetPage, isLiveMode, isSecurityAware, reverseLink.templateClass()));
                            }
                        }

                        setFieldValue(ImmutableList.copyOf(subElements), model, field);
                    }
                } else if (field.isAnnotationPresent(CameleonModelFirstElement.class)) {
                    CameleonModelFirstElement reverseLink = field.getAnnotation(CameleonModelFirstElement.class);

                    if (reverseLink != null && reverseLink.templateClass().isAnnotationPresent(CameleonModel.class)) {
                        CameleonModel targetModel = reverseLink.templateClass().getAnnotation(CameleonModel.class);

                        // Get all pages for target model template
                        List targetPages = pageDao.getTemplatePages(targetModel.templateName(), page.getCulture().getCultureId());

                        for (Page targetPage : targetPages) {
                            if (targetPage.isVisible(isLiveMode)) {
                                setFieldValue(convertPageToModel(targetPage, isLiveMode, isSecurityAware, reverseLink.templateClass()), model, field);
                                break;
                            }
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelSubElements.class)) {
                    CameleonModelSubElements cmse = field.getAnnotation(CameleonModelSubElements.class);

                    if (cmse != null) {
                        try {
                            // Default navId used the pageId of the current page
                            Integer navId = null;

                            if (cmse.elementName() != null) {
                                Element element = elements.get(cmse.elementName().trim());

                                if (element != null) {
                                    navId = Integer.parseInt(isLiveMode ? element.getValue() : element.getPreviewValue());
                                }
                            }

                            List subPageList;

                            // Retrieve the sub pages by pageId
                            if (navId == null) {
                                subPageList = getSubPages(page.getPageId(), isLiveMode, isSecurityAware, cmse.templateClass());
                            } else {
                                // Retrieve the suv pages by navId
                                try {
                                    subPageList = getSubPages(new CultureVo(page.getCulture()), navId, isLiveMode, isSecurityAware, cmse.templateClass());
                                } catch (Exception e) {
                                    throw new ModelInstanciationException("Unable to instanciate the method named getSubPages." + cmse.elementName(), e);
                                }

                            }

                            setFieldValue(ImmutableList.copyOf(subPageList), model, field);

                        } catch (PageNotFoundException e) {
                            throw new ModelInstanciationException("Unable to find sub elements for the template name." + cmse.elementName(), e);
                        }
                    }

                } else if (field.isAnnotationPresent(CameleonModelParentElement.class)) {
                    CameleonModelParentElement cmse = field.getAnnotation(CameleonModelParentElement.class);

                    if (cmse != null) {
                        try {
                            page.getNav().getParent();

                            Page targetPage = null;
                            if (page.getNav() != null && page.getNav().getParent() != null && page.getNav().getParent().getPages() != null) {
                                for (Page apage : page.getNav().getParent().getPages()) {
                                    if (apage.getCulture().equals(page.getCulture())) {
                                        if (apage.isVisible(isLiveMode)) {
                                            targetPage = apage;
                                            break;
                                        }
                                    }
                                }
                            }

                            if (targetPage != null) {
                                setFieldValue(convertPageToModel(targetPage, isLiveMode, isSecurityAware, cmse.templateClass()), model, field);
                            }
                        } catch (PageNotFoundException e) {
                            throw new ModelInstanciationException("Unable to find parent element for the template name.", e);
                        }
                    }

                } else if (field.isAnnotationPresent(CameleonModelClosestUpElement.class)) {
                    CameleonModelClosestUpElement cmcue = field.getAnnotation(CameleonModelClosestUpElement.class);

                    if (cmcue != null && cmcue.templateClass() != null && cmcue.templateClass().isAnnotationPresent(CameleonModel.class)) {
                        String templateName = cmcue.templateClass().getAnnotation(CameleonModel.class).templateName();

                        Nav travNav = page.getNav();

                        while (travNav != null && !travNav.getTemplate().getTemplateName().equals(templateName)) {
                            travNav = travNav.getParent();

                            if (travNav.getTemplate() == null) {
                                travNav = null;
                            }
                        }

                        Page targetPage = null;
                        if (travNav != null && travNav.getPages() != null) {
                            for (Page apage : travNav.getPages()) {
                                if (apage.getCulture().equals(page.getCulture())) {
                                    if (apage.isVisible(isLiveMode)) {
                                        targetPage = apage;
                                        break;
                                    }
                                }
                            }
                        }

                        if (targetPage != null) {
                            setFieldValue(convertPageToModel(targetPage, isLiveMode, isSecurityAware, cmcue.templateClass()), model, field);
                        }
                    }

                }
            }

            aClass = aClass.getSuperclass();
        } while (aClass != null);

        return model;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public  T getFirstTemplatePage(String templateName, CultureVo cultureVo, Boolean isLiveMode, Boolean isSecurityAware, Class modelClass)
            throws PageNotFoundException {
        List targetPages = pageDao.getTemplatePages(templateName, cultureVo.getCultureId());

        for (Page targetPage : targetPages) {
            if (targetPage.isVisible(isLiveMode)) {
                return convertPageToModel(targetPage, isLiveMode, isSecurityAware, modelClass);
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Integer createPage(Integer parentNavId, String templateName, CultureVo cultureVo, String pageName, String author) {
        return pageDao.createPage(parentNavId, templateName, cultureVo.getCultureCode(), pageName, author);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void updatePage(Integer navId, CultureVo cultureVo, Map values, String pageName, String author) {
        Page page = pageDao.getPage(cultureVo.getCultureId(), navId);
        Nav nav = page.getNav();
        Template template = nav.getTemplate();

        page.setPageNamePreview(pageName);

        // Update elements
        for (Part part : template.getParts()) {
            if (values.containsKey(part.getPartName())) {
                if (part.getIsMulticulture()) {
                    updatePart(page, part, values.get(part.getPartName()));
                } else {
                    updatePart(nav, part, values.get(part.getPartName()));
                }
            }
        }

        pageDao.pageUpdate(page, author);
    }

    /**
     * Updates a part in all it's culture
     * 
     * @param nav the nav to update
     * @param part the part to update
     * @param value the value to set
     */
    private void updatePart(Nav nav, Part part, Object value) {
        for (Page page : nav.getPages()) {
            updatePart(page, part, value);
        }
    }

    /**
     * Updates a part in a specific culture
     * 
     * @param page the page to update
     * @param part the part to update
     * @param value the value to set
     */
    private void updatePart(Page page, Part part, Object value) {
        for (Element element : page.getElements()) {
            if (element.getPart().getPartId().equals(part.getPartId())) {
                setElementValue(element, value);
                return;
            }
        }
    }

    /**
     * Updates an element to a certain value
     * 
     * @param element the element to update
     * @param value the value to set
     */
    private void setElementValue(Element element, Object value) {
        if (value == null) {
            element.setPreviewFile(null);
            element.setPreviewValue(null);
        } else if (value instanceof String) {
            element.setPreviewFile(null);
            element.setPreviewValue((String) value);
        } else if (value instanceof Integer) {
            element.setPreviewFile(null);
            element.setPreviewValue(((Integer) value).toString());
        } else if (value instanceof ImageUpdateModel) {
            String fileName = ((ImageUpdateModel) value).getFileName();
            fileName = fileName.replaceAll("([^a-zA-Z0-1_.])", "");
            ((ImageUpdateModel) value).setFileName(fileName);

            element.setPreviewFile(((ImageUpdateModel) value).getFileName());
            element.setPreviewValue(null);

            saveImages((ImageUpdateModel) value, element);
        } else {
            throw new IllegalArgumentException("Type cannot be converted to element value: " + value.getClass().toString());
        }
    }

    private void saveImages(ImageUpdateModel image, Element element) {
        // Copy file to correct directory
        String path = InternalCameleonConfig.getString(InternalCameleonConfig.CAMELEON_CMS_MEDIA_PATH, "/tmp");

        Integer navId = element.getPage().getNav().getNavId();
        Integer partId = element.getPart().getPartId();
        String cultureCode = element.getPage().getCulture().getCultureCode();

        String oFileName = "Preview_" + navId + "_" + partId + "_" + cultureCode + "_" + ImageType.ORIGINAL.getType() + "_" + image.getFileName();
        String pFileName = "Preview_" + navId + "_" + partId + "_" + cultureCode + "_" + ImageType.PRESENTATION.getType() + "_" + image.getFileName();
        String tFileName = "Preview_" + navId + "_" + partId + "_" + cultureCode + "_" + ImageType.THUMBNAIL.getType() + "_" + image.getFileName();

        File oFile = new File(path + oFileName);
        File pFile = new File(path + pFileName);
        File tFile = new File(path + tFileName);

        int pHeight = -1;
        int pWidth = 300;
        int tHeight = -1;
        int tWidth = 100;

        if (element.getPart().getPresentationHeight() != null) {
            pHeight = element.getPart().getPresentationHeight();
        }
        if (element.getPart().getPresentationWidth() != null) {
            pWidth = element.getPart().getPresentationWidth();
        }
        if (element.getPart().getThumbnailHeight() != null) {
            tHeight = element.getPart().getThumbnailHeight();
        }
        if (element.getPart().getThumbnailWidth() != null) {
            tWidth = element.getPart().getThumbnailWidth();
        }

        ByteArrayInputStream baIs = new ByteArrayInputStream(image.getData());

        try {
            if (oFile.exists()) {
                oFile.delete();
            }
            if (pFile.exists()) {
                pFile.delete();
            }
            if (tFile.exists()) {
                tFile.delete();
            }

            oFile.createNewFile();
            pFile.createNewFile();
            tFile.createNewFile();

            // Save the original
            FileOutputStream fos = new FileOutputStream(oFile);
            IOUtils.copy(baIs, fos);
            fos.close();

            baIs.reset();
            BufferedImage pImage = ImageIO.read(baIs);
            pImage = getScaledInstance(pImage, pWidth, pHeight, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);

            baIs.reset();
            BufferedImage tImage = ImageIO.read(baIs);
            tImage = getScaledInstance(pImage, tWidth, tHeight, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);

            if (image.getFileName().toLowerCase().endsWith("jpg")) {
                ImageIO.write(pImage, "jpg", pFile);
                ImageIO.write(tImage, "jpg", tFile);
            } else if (image.getFileName().toLowerCase().endsWith("png")) {
                ImageIO.write(pImage, "png", pFile);
                ImageIO.write(tImage, "png", tFile);
            } else if (image.getFileName().toLowerCase().endsWith("gif")) {
                ImageIO.write(pImage, "gif", pFile);
                ImageIO.write(tImage, "gif", tFile);
            }
        } catch (IOException ioExc) {
            log.error(ioExc.getMessage(), ioExc);
        }
    }

    /**
     * Taken from http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
     */
    public BufferedImage getScaledInstance(BufferedImage srcImage, int targetWidth, int targetHeight, Object hint, boolean higherQuality) {
        int imageWidth = srcImage.getWidth();
        int imageHeight = srcImage.getHeight();

        if (imageWidth <= targetWidth && imageHeight <= targetHeight) {
            return srcImage;
        }

        int newWidth = targetWidth;
        int newHeight = targetHeight;

        double ratio = (double) imageWidth / (double) imageHeight;
        if (newWidth <= 0) {
            newWidth = (int) Math.round(ratio * newHeight);
        } else if (newHeight <= 0) {
            newHeight = (int) Math.round(newWidth / ratio);
        } else {
            int newWidth1 = newWidth;
            int newHeight1 = (int) Math.round(newWidth / ratio);
            int newWidth2 = (int) Math.round(ratio * newHeight);
            int newHeight2 = newHeight;

            if (newWidth1 <= targetWidth && newHeight1 <= targetHeight) {
                newWidth = newWidth1;
                newHeight = newHeight1;
            } else {
                newWidth = newWidth2;
                newHeight = newHeight2;
            }
        }

        if (imageWidth <= newWidth && imageHeight <= newHeight) {
            return srcImage;
        }

        int type = srcImage.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage ret = srcImage;
        int w, h;
        if (higherQuality) {
            // Use multi-step technique: start with original size, then
            // scale down in multiple passes with drawImage()
            // until the target size is reached
            w = srcImage.getWidth();
            h = srcImage.getHeight();
        } else {
            // Use one-step technique: scale directly from original
            // size to target size with a single drawImage() call
            w = newWidth;
            h = newHeight;
        }

        do {
            if (higherQuality && w > newWidth) {
                w /= 2;
                if (w < newWidth) {
                    w = newWidth;
                }
            }

            if (higherQuality && h > newHeight) {
                h /= 2;
                if (h < newHeight) {
                    h = newHeight;
                }
            }

            BufferedImage tmp = new BufferedImage(w, h, type);
            Graphics2D g2 = tmp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(ret, 0, 0, w, h, null);
            g2.dispose();

            ret = tmp;
        } while (w != newWidth || h != newHeight);

        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void approvePage(Integer navId, CultureVo cultureVo, String author) {
        Page page = pageDao.getPage(cultureVo.getCultureId(), navId);

        for (Element element : page.getElements()) {
            if (element.getPart().getDatatype().getHasMedia()) {
                approveFile(element);
            }
        }

        pageDao.pageApprove(page.getNav().getNavId(), page.getCulture().getCultureCode(), author);
    }

    private void approveFile(Element element) {
        // Copy file to correct directory
        String path = InternalCameleonConfig.getString(InternalCameleonConfig.CAMELEON_CMS_MEDIA_PATH, "/tmp");

        Integer navId = element.getPage().getNav().getNavId();
        Integer partId = element.getPart().getPartId();
        String cultureCode = element.getPage().getCulture().getCultureCode();

        if ("Image".equals(element.getPart().getDatatype().getName())) {
            if (StringUtils.isNotBlank(element.getFile())) {
                String oFileName = navId + "_" + partId + "_" + cultureCode + "_" + ImageType.ORIGINAL.getType() + "_" + element.getFile();
                String pFileName = navId + "_" + partId + "_" + cultureCode + "_" + ImageType.PRESENTATION.getType() + "_" + element.getFile();
                String tFileName = navId + "_" + partId + "_" + cultureCode + "_" + ImageType.THUMBNAIL.getType() + "_" + element.getFile();

                File oFile = new File(path + oFileName);
                File pFile = new File(path + pFileName);
                File tFile = new File(path + tFileName);

                if (oFile.exists()) {
                    oFile.delete();
                }
                if (pFile.exists()) {
                    pFile.delete();
                }
                if (tFile.exists()) {
                    tFile.delete();
                }
            }

            if (StringUtils.isNotBlank(element.getPreviewFile())) {
                String srcoFileName = "Preview_" + navId + "_" + partId + "_" + cultureCode + "_" + ImageType.ORIGINAL.getType() + "_" + element.getPreviewFile();
                String srcpFileName = "Preview_" + navId + "_" + partId + "_" + cultureCode + "_" + ImageType.PRESENTATION.getType() + "_" + element.getPreviewFile();
                String srctFileName = "Preview_" + navId + "_" + partId + "_" + cultureCode + "_" + ImageType.THUMBNAIL.getType() + "_" + element.getPreviewFile();

                String destoFileName = navId + "_" + partId + "_" + cultureCode + "_" + ImageType.ORIGINAL.getType() + "_" + element.getPreviewFile();
                String destpFileName = navId + "_" + partId + "_" + cultureCode + "_" + ImageType.PRESENTATION.getType() + "_" + element.getPreviewFile();
                String desttFileName = navId + "_" + partId + "_" + cultureCode + "_" + ImageType.THUMBNAIL.getType() + "_" + element.getPreviewFile();

                File srcoFile = new File(path + srcoFileName);
                File srcpFile = new File(path + srcpFileName);
                File srctFile = new File(path + srctFileName);

                File destoFile = new File(path + destoFileName);
                File destpFile = new File(path + destpFileName);
                File desttFile = new File(path + desttFileName);

                if (destoFile.exists()) {
                    destoFile.delete();
                }
                if (destpFile.exists()) {
                    destpFile.delete();
                }
                if (desttFile.exists()) {
                    desttFile.delete();
                }

                try {
                    destoFile.createNewFile();
                    destpFile.createNewFile();
                    desttFile.createNewFile();

                    FileInputStream ofis = new FileInputStream(srcoFile);
                    FileInputStream pfis = new FileInputStream(srcpFile);
                    FileInputStream tfis = new FileInputStream(srctFile);

                    FileOutputStream ofos = new FileOutputStream(destoFile);
                    FileOutputStream pfos = new FileOutputStream(destpFile);
                    FileOutputStream tfos = new FileOutputStream(desttFile);

                    IOUtils.copy(ofis, ofos);
                    IOUtils.copy(pfis, pfos);
                    IOUtils.copy(tfis, tfos);

                    ofis.close();
                    pfis.close();
                    tfis.close();

                    ofos.close();
                    pfos.close();
                    tfos.close();
                } catch (IOException ioExc) {
                    log.error(ioExc.getMessage(), ioExc);
                }
            }
        } else if ("Media".equals(element.getPart().getDatatype().getName())) {
            if (StringUtils.isNotBlank(element.getFile())) {
                String oFileName = navId + "_" + partId + "_" + cultureCode + "_0_" + element.getFile();

                File oFile = new File(path + oFileName);

                if (oFile.exists()) {
                    oFile.delete();
                }
            }

            if (StringUtils.isNotBlank(element.getPreviewFile())) {
                String srcoFileName = "Preview_" + navId + "_" + partId + "_" + cultureCode + "_0_" + element.getPreviewFile();

                String destoFileName = navId + "_" + partId + "_" + cultureCode + "_0_" + element.getPreviewFile();

                File srcoFile = new File(path + srcoFileName);

                File destoFile = new File(path + destoFileName);

                if (destoFile.exists()) {
                    destoFile.delete();
                }

                try {
                    destoFile.createNewFile();

                    FileInputStream ofis = new FileInputStream(srcoFile);

                    FileOutputStream ofos = new FileOutputStream(destoFile);

                    IOUtils.copy(ofis, ofos);

                    ofis.close();

                    ofos.close();
                } catch (IOException ioExc) {
                    log.error(ioExc.getMessage(), ioExc);
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void changePageVisibility(Integer navId, CultureVo cultureVo, boolean isLive, boolean isVisible, String author) {
        pageDao.pageVisibilityUpdate(navId, cultureVo.getCultureCode(), isLive, isVisible, author);
    }

    /**
     * Sets a value on an object property by reflection (ignoring public, protected and private flags)
     * 
     * @param value The value to set
     * @param target The object to set it on
     * @param field The field to set on
     * @throws InvalidModelFieldConvertionException Thrown if we cannot convert the string value into the field target
     *             type
     * @throws InvalidModelFieldAccessException Thrown if we cannot access the field
     */
    private void setFieldValue(String value, AbstractCameleonModel target, Field field) throws InvalidModelFieldConvertionException, InvalidModelFieldAccessException {
        // Shortcircut the null value case
        if (value == null) {
            return;
        }

        // Try to get the correct value to set in the correct type
        Class fieldType = field.getType();
        Object targetValue;

        if (fieldType == String.class) {
            targetValue = value;
        } else if (fieldType == Boolean.class) {
            targetValue = BooleanUtils.toBoolean(value);
        } else if (fieldType == Integer.class) {
            try {
                targetValue = Integer.valueOf(value);
            } catch (NumberFormatException nfe) {
                throw new InvalidModelFieldConvertionException("There was an error converting " + value + " to an Integer.", nfe);
            }
        } else if (fieldType == BigDecimal.class) {
            try {
                targetValue = new BigDecimal(value);
            } catch (NumberFormatException nfe) {
                throw new InvalidModelFieldConvertionException("There was an error converting " + value + " to an BigDecimal.", nfe);
            }
        } else if (fieldType == Date.class) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            String valueToParse = value.replace('/', '-');
            valueToParse = valueToParse.replace('.', '-');
            try {
                targetValue = sdf.parse(valueToParse);
            } catch (ParseException e) {
                throw new InvalidModelFieldConvertionException("There was an error converting " + value + " to a Date.", e);
            }
        } else {
            throw new InvalidModelFieldConvertionException("The system doesn't know how to convert to: " + fieldType.getName());
        }

        setFieldValue(targetValue, target, field);
    }

    /**
     * Sets a value on an object property by reflection (ignoring public, protected and private flags)
     * 
     * @param value The value to set
     * @param target The object to set it on
     * @param field The field to set on
     * @throws InvalidModelFieldConvertionException Thrown if we cannot convert the string value into the field target
     *             type
     * @throws InvalidModelFieldAccessException Thrown if we cannot access the field
     */
    private void setFieldValue(VideoVo value, AbstractCameleonModel target, Field field) throws InvalidModelFieldConvertionException, InvalidModelFieldAccessException {
        // Set the value (using a spring provided class)
        try {
            field.setAccessible(true);
            field.set(target, value);
        } catch (IllegalArgumentException e) {
            // No test case exist for this catch. The code structure should
            // prevent this block from event being executed
            throw new InvalidModelFieldAccessException("Error setting value on the model.", e);
        } catch (IllegalAccessException e) {
            // No test case exist for this catch. The code structure should
            // prevent this block from event being executed
            throw new InvalidModelFieldAccessException("Error setting value on the model.", e);
        }
    }

    /**
     * Sets a value on an object property by reflection (ignoring public, protected and private flags)
     * 
     * @param value The value to set
     * @param target The object to set it on
     * @param field The field to set on
     * @throws InvalidModelFieldConvertionException Thrown if we cannot convert the string value into the field target
     *             type
     * @throws InvalidModelFieldAccessException Thrown if we cannot access the field
     */
    private void setFieldValue(Object value, AbstractCameleonModel target, Field field) throws InvalidModelFieldConvertionException, InvalidModelFieldAccessException {
        // Set the value (using a spring provided class)
        try {
            field.setAccessible(true);
            field.set(target, value);
        } catch (IllegalArgumentException e) {
            // No test case exist for this catch. The code structure should
            // prevent this block from event being executed
            throw new InvalidModelFieldAccessException("Error setting value on the model.", e);
        } catch (IllegalAccessException e) {
            // No test case exist for this catch. The code structure should
            // prevent this block from event being executed
            throw new InvalidModelFieldAccessException("Error setting value on the model.", e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy