org.apereo.portal.portlet.dao.jpa.PortletDefinitionImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.apereo.portal.portlet.dao.jpa.PortletDefinitionImpl.java

Source

/**
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo 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 the following location:
 *
 *   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 org.apereo.portal.portlet.dao.jpa;

import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.MapKey;
import javax.persistence.MapKeyColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Transient;
import javax.persistence.Version;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.annotations.Type;
import org.apereo.portal.EntityIdentifier;
import org.apereo.portal.portlet.marketplace.IMarketplaceRating;
import org.apereo.portal.portlet.om.IPortletDefinition;
import org.apereo.portal.portlet.om.IPortletDefinitionId;
import org.apereo.portal.portlet.om.IPortletDefinitionParameter;
import org.apereo.portal.portlet.om.IPortletDescriptorKey;
import org.apereo.portal.portlet.om.IPortletEntity;
import org.apereo.portal.portlet.om.IPortletPreference;
import org.apereo.portal.portlet.om.IPortletType;
import org.apereo.portal.portlet.om.PortletLifecycleState;
import org.springframework.util.StringUtils;

/**
 * @author Eric Dalquist
 * @version $Revision$
 */
@Entity
@Table(name = "UP_PORTLET_DEF")
@SequenceGenerator(name = "UP_PORTLET_DEF_GEN", sequenceName = "UP_PORTLET_DEF_SEQ", allocationSize = 5)
@TableGenerator(name = "UP_PORTLET_DEF_GEN", pkColumnValue = "UP_PORTLET_DEF", allocationSize = 5)
@NaturalIdCache(region = "org.apereo.portal.portlet.dao.jpa.PortletDefinitionImpl-NaturalId")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class PortletDefinitionImpl implements IPortletDefinition {
    //Properties are final to stop changes in code, hibernate overrides the final via reflection to set their values
    @Id
    @GeneratedValue(generator = "UP_PORTLET_DEF_GEN")
    @Column(name = "PORTLET_DEF_ID")
    private final long internalPortletDefinitionId;

    @Transient
    private IPortletDefinitionId portletDefinitionId = null;

    @SuppressWarnings("unused")
    @Version
    @Column(name = "ENTITY_VERSION")
    private final long entityVersion;

    //Hidden reference to the child portlet entities, used to allow cascading deletes where when a portlet definition is deleted all associated entities are also deleted
    //MUST BE LAZY FETCH, this set should never actually be populated at runtime or performance will be TERRIBLE
    @SuppressWarnings("unused")
    @OneToMany(mappedBy = "portletDefinition", targetEntity = PortletEntityImpl.class, cascade = {
            CascadeType.ALL }, fetch = FetchType.LAZY, orphanRemoval = true)
    private Set<IPortletEntity> portletEntities = null;

    @OneToOne(targetEntity = PortletPreferencesImpl.class, cascade = {
            CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "PORTLET_PREFS_ID", nullable = false)
    @Fetch(FetchMode.JOIN)
    private final PortletPreferencesImpl portletPreferences;

    /**
     * Name is used for admin tools, but will typically not be presented to end users.  It allows
     * for situations where you need to define multiple similar portlets, all sharing a title. but
     * still provides a way to distinguish between the portlets in admin tools.
     */
    @Column(name = "PORTLET_NAME", length = 128, nullable = false, unique = true)
    private String name;

    @NaturalId(mutable = true)
    @Column(name = "PORTLET_FNAME", length = 255, nullable = false)
    @Type(type = "fname")
    private String fname;

    @Column(name = "PORTLET_TITLE", length = 128, nullable = false)
    @Index(name = "IDX_PORTLET_DEF__TITLE")
    private String title;

    @ManyToOne(targetEntity = PortletTypeImpl.class, optional = false)
    @JoinColumn(name = "PORTLET_TYPE_ID", nullable = false)
    private IPortletType portletType;

    @Column(name = "PORTLET_DESC", length = 255)
    private String description;

    @Column(name = "AVG_RATING")
    private Double rating;

    @Column(name = "AVG_RATING_USER_COUNT")
    private Long usersRated;

    @Column(name = "PORTLET_TIMEOUT", nullable = false)
    private int timeout = 20000; //Default to a reasonable value
    @Column(name = "ACTION_TIMEOUT")
    private Integer actionTimeout = null;
    @Column(name = "EVENT_TIMEOUT")
    private Integer eventTimeout = null;
    @Column(name = "RENDER_TIMEOUT")
    private Integer renderTimeout = null;
    @Column(name = "RESOURCE_TIMEOUT")
    private Integer resourceTimeout = null;

    //TODO link to User object once it is JPA managed
    @Column(name = "PORTLET_PUBL_ID")
    private int publisherId = -1;

    //TODO link to User object once it is JPA managed
    @Column(name = "PORTLET_APVL_ID")
    private int approverId = -1;

    //TODO link to User object once it is JPA managed
    @Column(name = "PORTLET_EXP_ID")
    private int expirerId = -1;

    @Column(name = "PORTLET_PUBL_DT")
    private Date publishDate = null;

    @Column(name = "PORTLET_APVL_DT")
    private Date approvalDate = null;

    @Column(name = "PORTLET_EXP_DT")
    private Date expirationDate = null;

    @OneToMany(targetEntity = PortletDefinitionParameterImpl.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "PORLTET_DEF_ID", nullable = false)
    @MapKey(name = "name")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @Fetch(FetchMode.JOIN)
    private Map<String, IPortletDefinitionParameter> parameters = new LinkedHashMap<String, IPortletDefinitionParameter>();

    @ElementCollection(fetch = FetchType.EAGER, targetClass = PortletLocalizationData.class)
    @JoinTable(name = "UP_PORTLET_DEF_MDATA", joinColumns = @JoinColumn(name = "PORTLET_ID"))
    @MapKeyColumn(name = "LOCALE", length = 64, nullable = false)
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @Fetch(FetchMode.JOIN)
    private final Map<String, PortletLocalizationData> localizations = new LinkedHashMap<String, PortletLocalizationData>();

    @Embedded
    private PortletDescriptorKeyImpl portletDescriptorKey;

    /**
     * Used to initialize fields after persistence actions.
     */
    @PostLoad
    @PostPersist
    @PostUpdate
    @PostRemove
    private void init() {
        if (this.internalPortletDefinitionId != -1 && (this.portletDefinitionId == null
                || this.portletDefinitionId.getLongId() != this.internalPortletDefinitionId)) {
            this.portletDefinitionId = PortletDefinitionIdImpl.create(this.internalPortletDefinitionId);
        }
    }

    /**
     * Used by the ORM layer to create instances of the object.
     */
    @SuppressWarnings("unused")
    private PortletDefinitionImpl() {
        this.internalPortletDefinitionId = -1;
        this.entityVersion = -1;
        this.portletPreferences = null;
    }

    public PortletDefinitionImpl(IPortletType portletType, String fname, String name, String title,
            String applicationId, String portletName, boolean isFramework) {
        Validate.notNull(portletType);
        Validate.notNull(name);
        Validate.notNull(fname);
        Validate.notNull(title);
        if (!isFramework) {
            Validate.notNull(applicationId);
        }
        Validate.notNull(portletName);

        this.internalPortletDefinitionId = -1;
        this.entityVersion = -1;
        this.portletPreferences = new PortletPreferencesImpl();
        this.portletType = portletType;
        this.name = name;
        this.fname = fname;
        this.title = title;

        this.portletDescriptorKey = new PortletDescriptorKeyImpl();
        this.portletDescriptorKey.setWebAppName(applicationId);
        this.portletDescriptorKey.setPortletName(portletName);
        this.portletDescriptorKey.setFrameworkPortlet(isFramework);
    }

    public PortletDefinitionImpl(IPortletType portletType, String fname, String name, String title,
            String applicationId, String portletName, boolean isFramework, IPortletDefinitionId Id) {
        Validate.notNull(portletType);
        Validate.notNull(name);
        Validate.notNull(fname);
        Validate.notNull(title);
        if (!isFramework) {
            Validate.notNull(applicationId);
        }
        Validate.notNull(portletName);

        this.internalPortletDefinitionId = Id.getLongId();
        this.entityVersion = -1;
        this.portletPreferences = new PortletPreferencesImpl();
        this.portletType = portletType;
        this.name = name;
        this.fname = fname;
        this.title = title;

        this.portletDescriptorKey = new PortletDescriptorKeyImpl();
        this.portletDescriptorKey.setWebAppName(applicationId);
        this.portletDescriptorKey.setPortletName(portletName);
        this.portletDescriptorKey.setFrameworkPortlet(isFramework);
    }

    //** APIs for import/export support **//
    @Override
    public String getDataId() {
        return this.getFName();
    }

    @Override
    public String getDataTitle() {
        return this.getName();
    }

    @Override
    public String getDataDescription() {
        return this.getDescription();
    }

    //** APIs for portlet definitions **//

    /**
     * @return the rating
     */
    @Override
    public Double getRating() {
        return rating;
    }

    /**
     * @param rating the rating to set. Must be within marketplaceRating range (inclusive). Can not be null.
     * @throws IllegalArgumentException
     */
    @Override
    public void setRating(Double rating) {
        Validate.notNull(rating, "Rating cannot be null.  Maybe you meant 0?");
        if (rating > IMarketplaceRating.MAX_RATING || rating < IMarketplaceRating.MIN_RATING) {
            throw new IllegalArgumentException();
        }
        this.rating = rating;
    }

    /**
     * @return the count of users that rated this portlet.  Will not return null
     */
    @Override
    public Long getUsersRated() {
        return usersRated == null ? 0 : usersRated;
    }

    /**
     * @param usersRated - Number of users that rated this portlet.
     */
    @Override
    public void setUsersRated(Long usersRated) {
        Validate.isTrue(usersRated > -1L, "Number of Users that rated shouldn't be under zero");
        this.usersRated = usersRated;
    }

    /* (non-Javadoc)
     * @see org.apereo.portal.om.portlet.IPortletDefinition#getPortletDefinitionId()
     */
    @Override
    public IPortletDefinitionId getPortletDefinitionId() {
        init();
        return this.portletDefinitionId;
    }

    /* (non-Javadoc)
    * @see org.apereo.portal.portlet.om.IPortletEntity#getPortletPreferences()
    */
    @Override
    public List<IPortletPreference> getPortletPreferences() {
        return portletPreferences.getPortletPreferences();
    }

    /* (non-Javadoc)
     * @see org.apereo.portal.portlet.om.IPortletEntity#setPortletPreferences(java.util.List)
     */
    @Override
    public boolean setPortletPreferences(List<IPortletPreference> portletPreferences) {
        return this.portletPreferences.setPortletPreferences(portletPreferences);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getFName() {
        return fname;
    }

    @Override
    public void setFName(String fname) {
        this.fname = fname;
    }

    @Override
    public String getTitle() {
        return title;
    }

    @Override
    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public int getTimeout() {
        return timeout;
    }

    @Override
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    @Override
    public Integer getActionTimeout() {
        return actionTimeout;
    }

    @Override
    public void setActionTimeout(Integer actionTimeout) {
        this.actionTimeout = actionTimeout;
    }

    @Override
    public Integer getEventTimeout() {
        return eventTimeout;
    }

    @Override
    public void setEventTimeout(Integer eventTimeout) {
        this.eventTimeout = eventTimeout;
    }

    @Override
    public Integer getRenderTimeout() {
        return renderTimeout;
    }

    @Override
    public void setRenderTimeout(Integer renderTimeout) {
        this.renderTimeout = renderTimeout;
    }

    @Override
    public Integer getResourceTimeout() {
        return resourceTimeout;
    }

    @Override
    public void setResourceTimeout(Integer resourceTimeout) {
        this.resourceTimeout = resourceTimeout;
    }

    @Override
    public int getPublisherId() {
        return publisherId;
    }

    @Override
    public void setPublisherId(int publisherId) {
        this.publisherId = publisherId;
    }

    @Override
    public int getApproverId() {
        return approverId;
    }

    @Override
    public void setApproverId(int approverId) {
        this.approverId = approverId;
    }

    @Override
    public int getExpirerId() {
        return expirerId;
    }

    @Override
    public void setExpirerId(int expirerId) {
        this.expirerId = expirerId;
    }

    @Override
    public Date getPublishDate() {
        return publishDate;
    }

    @Override
    public void setPublishDate(Date publishDate) {
        this.publishDate = publishDate;
    }

    @Override
    public Date getApprovalDate() {
        return approvalDate;
    }

    @Override
    public void setApprovalDate(Date approvalDate) {
        this.approvalDate = approvalDate;
    }

    @Override
    public Date getExpirationDate() {
        return expirationDate;
    }

    @Override
    public void setExpirationDate(Date expirationDate) {
        this.expirationDate = expirationDate;
    }

    @Override
    public IPortletType getType() {
        return this.portletType;
    }

    @Override
    public String getName(String locale) {
        PortletLocalizationData localeData = localizations.get(locale);
        if (localeData != null && localeData.getName() != null) {
            return localeData.getName();
        }
        return name;
    }

    @Override
    public String getDescription(String locale) {
        PortletLocalizationData localeData = localizations.get(locale);
        if (localeData != null && localeData.getDescription() != null) {
            return localeData.getDescription();
        }
        return description;
    }

    @Override
    public String getTitle(String locale) {
        PortletLocalizationData localeData = localizations.get(locale);
        if (localeData != null && localeData.getTitle() != null) {
            return localeData.getTitle();
        }

        return title;
    }

    @Override
    public String getAlternativeMaximizedLink() {
        final IPortletDefinitionParameter alternativeMaximizedLinkParameter = getParameter(ALT_MAX_LINK_PARAM);

        if (null != alternativeMaximizedLinkParameter) {
            final String alternativeMaximizedLink = alternativeMaximizedLinkParameter.getValue();

            if (StringUtils.hasText(alternativeMaximizedLink)) {
                return alternativeMaximizedLink;
            }
        }

        return null;
    }

    @Override
    public String getTarget() {
        final IPortletDefinitionParameter targetParameter = getParameter(TARGET_PARAM);

        if (null != targetParameter) {
            final String target = targetParameter.getValue();

            if (StringUtils.hasText(target)) {
                return target;
            }
        }

        return null;
    }

    @Override
    public void setType(IPortletType portletType) {
        this.portletType = portletType;
    }

    @Override
    public IPortletDescriptorKey getPortletDescriptorKey() {
        return this.portletDescriptorKey;
    }

    @Override
    public void addLocalizedDescription(String locale, String chanDesc) {
        PortletLocalizationData localeData = localizations.get(locale);
        if (localeData == null) {
            localeData = new PortletLocalizationData();
        }
        localeData.setDescription(chanDesc);
        localizations.put(locale, localeData);
    }

    @Override
    public void addLocalizedName(String locale, String chanName) {
        PortletLocalizationData localeData = localizations.get(locale);
        if (localeData == null) {
            localeData = new PortletLocalizationData();
        }
        localeData.setName(chanName);
        localizations.put(locale, localeData);
    }

    @Override
    public void addLocalizedTitle(String locale, String chanTitle) {
        PortletLocalizationData localeData = localizations.get(locale);
        if (localeData == null) {
            localeData = new PortletLocalizationData();
        }
        localeData.setTitle(chanTitle);
        localizations.put(locale, localeData);
    }

    @Override
    public Set<IPortletDefinitionParameter> getParameters() {
        return Collections.unmodifiableSet(new LinkedHashSet<IPortletDefinitionParameter>(parameters.values()));
    }

    @Override
    public void setParameters(Set<IPortletDefinitionParameter> newParameters) {

        if (newParameters == null) {
            this.parameters = new LinkedHashMap<String, IPortletDefinitionParameter>();
        } else if (this.parameters == null) {
            this.parameters = new LinkedHashMap<String, IPortletDefinitionParameter>();
            for (final IPortletDefinitionParameter parameter : newParameters) {
                this.parameters.put(parameter.getName(), parameter);
            }
        } else {
            //Build map of existing parameters for tracking which parameters have been removed
            final Map<String, IPortletDefinitionParameter> oldPreferences = new LinkedHashMap<String, IPortletDefinitionParameter>(
                    this.parameters);

            for (final IPortletDefinitionParameter parameter : newParameters) {
                final String name = parameter.getName();

                //Remove the existing parameter from the map since it is supposed to be persisted 
                final IPortletDefinitionParameter existingParameter = oldPreferences.remove(name);
                if (existingParameter == null) {
                    //New parameter, add it to the list
                    this.parameters.put(name, parameter);
                } else {
                    //Existing parameter, update the fields
                    existingParameter.setDescription(parameter.getDescription());
                    existingParameter.setValue(parameter.getValue());
                    this.parameters.put(name, existingParameter);
                }
            }

            //Remove old parameters
            this.parameters.keySet().removeAll(oldPreferences.keySet());
        }
    }

    @Override
    public IPortletDefinitionParameter getParameter(String key) {
        return this.parameters.get(key);
    }

    @Override
    public Map<String, IPortletDefinitionParameter> getParametersAsUnmodifiableMap() {
        return Collections.unmodifiableMap(this.parameters);
    }

    @Override
    public void removeParameter(IPortletDefinitionParameter parameter) {
        this.parameters.remove(parameter.getName());
    }

    @Override
    public void removeParameter(String name) {
        this.parameters.remove(name);
    }

    @Override
    public void addParameter(IPortletDefinitionParameter parameter) {
        final String name = parameter.getName();
        final IPortletDefinitionParameter existingParameter = this.parameters.get(name);
        if (existingParameter != null) {
            existingParameter.setDescription(parameter.getDescription());
            existingParameter.setValue(parameter.getValue());
        } else {
            this.parameters.put(name, parameter);
        }
    }

    @Override
    public void addParameter(String name, String value) {
        final IPortletDefinitionParameter existingParameter = this.parameters.get(name);
        if (existingParameter != null) {
            existingParameter.setValue(value);
        } else {
            this.parameters.put(name, new PortletDefinitionParameterImpl(name, value));
        }
    }

    @Override
    public EntityIdentifier getEntityIdentifier() {
        return new EntityIdentifier(String.valueOf(this.portletDefinitionId.getStringId()),
                IPortletDefinition.class);
    }

    @Override
    public PortletLifecycleState getLifecycleState() {
        final Date now = new Date();
        if (parameters.containsKey(PortletLifecycleState.MAINTENANCE_MODE_PARAMETER_NAME)) {
            return PortletLifecycleState.MAINTENANCE;
        } else if (expirationDate != null && expirationDate.before(now)) {
            return PortletLifecycleState.EXPIRED;
        } else if (publishDate != null && publishDate.before(now)) {
            return PortletLifecycleState.PUBLISHED;
        } else if (approvalDate != null && approvalDate.before(now)) {
            return PortletLifecycleState.APPROVED;
        } else {
            return PortletLifecycleState.CREATED;
        }
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((this.fname == null) ? 0 : this.fname.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!IPortletDefinition.class.isAssignableFrom(obj.getClass()))
            return false;
        final IPortletDefinition other = (IPortletDefinition) obj;
        if (this.fname == null) {
            if (other.getFName() != null)
                return false;
        } else if (!this.fname.equals(other.getFName()))
            return false;
        return true;
    }

    @Override
    public String toString() {

        ToStringBuilder toStringBuilder = new ToStringBuilder(this).append("definitionId", portletDefinitionId)
                .append("fname", fname).append("descriptorKey", portletDescriptorKey).append("type", portletType);

        return toStringBuilder.toString();
    }
}