com.flexive.ejb.beans.search.ResultPreferencesEngineBean.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.ejb.beans.search.ResultPreferencesEngineBean.java

Source

/***************************************************************
 *  This file is part of the [fleXive](R) framework.
 *
 *  Copyright (c) 1999-2014
 *  UCS - unique computing solutions gmbh (http://www.ucs.at)
 *  All rights reserved
 *
 *  The [fleXive](R) project is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 or higher as published by the Free Software Foundation.
 *
 *  The GNU Lesser General Public License can be found at
 *  http://www.gnu.org/licenses/lgpl.html.
 *  A copy is found in the textfile LGPL.txt and important notices to the
 *  license from the author are found in LICENSE.txt distributed with
 *  these libraries.
 *
 *  This library 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.
 *
 *  For further information about UCS - unique computing solutions gmbh,
 *  please see the company website: http://www.ucs.at
 *
 *  For further information about [fleXive](R), please see the
 *  project website: http://www.flexive.org
 *
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package com.flexive.ejb.beans.search;

import com.flexive.shared.CacheAdmin;
import com.flexive.shared.FxContext;
import com.flexive.shared.configuration.SystemParameters;
import com.flexive.shared.exceptions.FxApplicationException;
import com.flexive.shared.exceptions.FxInvalidParameterException;
import com.flexive.shared.exceptions.FxNotFoundException;
import com.flexive.shared.exceptions.FxRuntimeException;
import com.flexive.shared.interfaces.*;
import com.flexive.shared.search.*;
import com.flexive.shared.structure.FxEnvironment;
import com.flexive.shared.structure.FxType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.ejb.*;
import java.util.Arrays;

/**
 * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 * @version $Rev$
 */
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless(name = "ResultPreferencesEngine", mappedName = "ResultPreferencesEngine")
public class ResultPreferencesEngineBean implements ResultPreferencesEngine, ResultPreferencesEngineLocal {
    private static final Log LOG = LogFactory.getLog(ResultPreferencesEngineBean.class);
    @EJB
    ConfigurationEngineLocal configuration;
    @EJB
    DivisionConfigurationEngineLocal divisionConfiguration;
    @EJB
    UserConfigurationEngineLocal userConfiguration;

    /** {@inheritDoc} */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public ResultPreferences load(long typeId, ResultViewType viewType, ResultLocation location)
            throws FxApplicationException {
        return loadWithType(typeId, viewType, location).getPreferences();
    }

    private LoadResult loadWithType(long typeId, ResultViewType viewType, ResultLocation location)
            throws FxApplicationException {
        ResultPreferences preferences = null;
        boolean reset = false;
        try {
            preferences = configuration.get(SystemParameters.USER_RESULT_PREFERENCES,
                    getKey(typeId, viewType, location));
        } catch (FxNotFoundException e) {
            if (typeId < -1) {
                // unknown type
                throw e;
            }
            reset = true;
        }
        if (reset || (preferences != null && preferences.getSelectedColumns().isEmpty())) {
            if (typeId >= 0) {
                final FxType type = CacheAdmin.getEnvironment().getType(typeId);
                // use parent type or global default (FX-482)
                return loadWithType(type.getParent() != null ? type.getParent().getId() : -1, viewType, location);
            } else if (typeId == -1) {
                // if no global default is defined, use hardcoded default settings
                preferences = new ResultPreferences(
                        Arrays.asList(new ResultColumnInfo(Table.CONTENT, "@pk", null),
                                new ResultColumnInfo(Table.CONTENT, "typedef", "description"),
                                new ResultColumnInfo(Table.CONTENT, "caption", null),
                                new ResultColumnInfo(Table.CONTENT, "modified_at", null),
                                new ResultColumnInfo(Table.CONTENT, "modified_by", "username"),
                                new ResultColumnInfo(Table.CONTENT, "@lock", null)),
                        Arrays.asList(new ResultOrderByInfo(Table.CONTENT, "@pk", null, SortDirection.ASCENDING)),
                        25, 100);
            }
        }

        final ResultPreferences checkedPreferences = checkProperties(preferences);
        if (checkedPreferences != null) {
            // check performed, store new version in configuration
            // We need to obey fallback preferences - i.e. use the source configuration for the preferences object
            try {
                FxContext.get().runAsSystem();
                // we may have to update the division configuration here, so we need superuser privileges
                configuration.putInSource(SystemParameters.USER_RESULT_PREFERENCES,
                        getKey(typeId, viewType, location), checkedPreferences);
            } catch (FxNotFoundException e) {
                LOG.warn("Using internal default result preferences [" + getKey(typeId, viewType, location)
                        + "], this may cause performance problems.");
            } finally {
                FxContext.get().stopRunAsSystem();
            }
            return new LoadResult(typeId, checkedPreferences);
        }
        return new LoadResult(typeId, preferences);
    }

    /** {@inheritDoc} */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public ResultPreferences loadSystemDefault(long typeId, ResultViewType viewType, ResultLocation location)
            throws FxApplicationException {
        try {
            return divisionConfiguration.get(SystemParameters.USER_RESULT_PREFERENCES,
                    getKey(typeId, viewType, location));
        } catch (FxNotFoundException e) {
            // return empty result preferences
            return new ResultPreferences();
        }
    }

    /** {@inheritDoc} */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public boolean isCustomized(long typeId, ResultViewType viewType, ResultLocation location)
            throws FxApplicationException {
        try {
            configuration.get(SystemParameters.USER_RESULT_PREFERENCES, getKey(typeId, viewType, location));
            return true;
        } catch (FxNotFoundException e) {
            return false;
        }
    }

    /** {@inheritDoc} */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void save(ResultPreferences preferences, long typeId, ResultViewType viewType, ResultLocation location)
            throws FxApplicationException {
        if (preferences.getSelectedColumns().isEmpty()) {
            throw new FxInvalidParameterException("preferences", "ex.ResultPreferences.save.empty");
        }
        configuration.put(SystemParameters.USER_RESULT_PREFERENCES, getKey(typeId, viewType, location),
                preferences);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void saveInSource(ResultPreferences preferences, long typeId, ResultViewType viewType,
            ResultLocation location) throws FxApplicationException {
        final LoadResult result = loadWithType(typeId, viewType, location);
        // save for the root type
        save(preferences, result.getTypeId(), viewType, location);
    }

    /** {@inheritDoc} */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void saveSystemDefault(ResultPreferences preferences, long typeId, ResultViewType viewType,
            ResultLocation... locations) throws FxApplicationException {
        if (preferences.getSelectedColumns().isEmpty()) {
            throw new FxInvalidParameterException("preferences", "ex.ResultPreferences.save.empty");
        }
        for (ResultLocation location : locations) {
            // div conf already checks for supervisor access
            divisionConfiguration.put(SystemParameters.USER_RESULT_PREFERENCES, getKey(typeId, viewType, location),
                    preferences);
        }
    }

    /** {@inheritDoc} */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void remove(long typeId, ResultViewType viewType, ResultLocation location)
            throws FxApplicationException {
        configuration.remove(SystemParameters.USER_RESULT_PREFERENCES, getKey(typeId, viewType, location));
    }

    private String getKey(long typeId, ResultViewType viewType, ResultLocation location) {
        return typeId + "/" + viewType.name() + "/" + location.getName();
    }

    /**
     * Check all properties in preferences for their validity. If no check was performed,
     * null is returned, otherwise a new result preferences object with the new timestamp is returned.
     *
     * @param preferences   the preferences to be checked
     * @return  returns null if no check was performed,
     * otherwise a new result preferences object with the new timestamp is returned.
     */
    private ResultPreferences checkProperties(ResultPreferences preferences) {
        final FxEnvironment environment = CacheAdmin.getEnvironment();
        if (preferences.getLastChecked() >= environment.getTimeStamp()) {
            return null;
        }
        ResultPreferencesEdit rpe = preferences.getEditObject();

        // clean up selected columns
        for (ResultColumnInfo info : preferences.getSelectedColumns()) {
            if (!info.isStructureNode()) {
                continue;
            }
            try {
                if (info.getPropertyName().startsWith("#")) {
                    environment.getAssignment(stripTableSelectors(info.getPropertyName().substring(1)));
                } else {
                    environment.getProperty(stripTableSelectors(info.getPropertyName()));
                }
            } catch (FxRuntimeException e) {
                if (LOG.isInfoEnabled()) {
                    LOG.info("Removing property " + info.getPropertyName() + " for user "
                            + FxContext.getUserTicket());
                }
                rpe.removeSelectedColumn(info);
            }
        }

        // clean up order by columns
        for (ResultOrderByInfo info : preferences.getOrderByColumns()) {
            if (!info.isStructureNode()) {
                continue;
            }
            try {
                if (info.getPropertyName().startsWith("#")) {
                    environment.getAssignment(stripTableSelectors(info.getPropertyName().substring(1)));
                } else {
                    environment.getProperty(stripTableSelectors(info.getPropertyName()));
                }
            } catch (FxRuntimeException e) {
                if (LOG.isInfoEnabled()) {
                    LOG.info("Removing property " + info.getPropertyName() + " for user "
                            + FxContext.getUserTicket());
                }
                rpe.removeOrderByColumn(info);
            }
        }
        rpe.setLastChecked(System.currentTimeMillis());
        return rpe;
    }

    private String stripTableSelectors(String name) {
        final int pos = name.indexOf('.');
        return pos != -1 ? name.substring(0, pos) : name;
    }

    private static class LoadResult {
        private final long typeId;
        private final ResultPreferences preferences;

        private LoadResult(long typeId, ResultPreferences preferences) {
            this.typeId = typeId;
            this.preferences = preferences;
        }

        public long getTypeId() {
            return typeId;
        }

        public ResultPreferences getPreferences() {
            return preferences;
        }
    }

}