/**
* 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:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyJoinColumn;
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 javax.portlet.WindowState;
import org.apache.commons.lang.Validate;
import org.apereo.portal.layout.dao.jpa.StylesheetDescriptorImpl;
import org.apereo.portal.layout.om.IStylesheetDescriptor;
import org.apereo.portal.portlet.om.IPortletDefinition;
import org.apereo.portal.portlet.om.IPortletDefinitionId;
import org.apereo.portal.portlet.om.IPortletEntity;
import org.apereo.portal.portlet.om.IPortletEntityId;
import org.apereo.portal.portlet.om.IPortletPreference;
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.Type;
/**
*/
@Entity
@Table(name = "UP_PORTLET_ENT")
@SequenceGenerator(
name = "UP_PORTLET_ENT_GEN",
sequenceName = "UP_PORTLET_ENT_SEQ",
allocationSize = 10
)
@TableGenerator(name = "UP_PORTLET_ENT_GEN", pkColumnValue = "UP_PORTLET_ENT", allocationSize = 10)
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
class PortletEntityImpl implements IPortletEntity {
//Properties are final to stop changes in code, hibernate overrides the final via reflection to set their values
@Id
@GeneratedValue(generator = "UP_PORTLET_ENT_GEN")
@Column(name = "PORTLET_ENT_ID")
private final long internalPortletEntityId;
@SuppressWarnings("unused")
@Version
@Column(name = "ENTITY_VERSION")
private final long entityVersion;
@NaturalId
@Column(name = "LAYOUT_NODE_ID", nullable = false)
private final String layoutNodeId;
@NaturalId
@Index(name = "IDX_UP_PORTLET_ENT__UP_USER")
@Column(name = "USER_ID", nullable = false)
private final int userId;
//Hidden reference to the parent portlet definition, used by hibernate for referential integrety
@ManyToOne(
targetEntity = PortletDefinitionImpl.class,
cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}
)
@JoinColumn(name = "PORTLET_DEF_ID", nullable = false)
private final IPortletDefinition portletDefinition;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name = "UP_PORTLET_ENT__STATES",
joinColumns = @JoinColumn(name = "PORTLET_ENT_ID")
)
@MapKeyJoinColumn(name = "STYLESHEET_DESCRIPTOR_ID")
@Column(name = "WINDOW_STATE")
@Type(type = "windowState")
private final Map<StylesheetDescriptorImpl, WindowState> windowStates =
new HashMap<StylesheetDescriptorImpl, WindowState>(0);
@OneToOne(
cascade = {CascadeType.ALL},
orphanRemoval = true
)
@JoinColumn(name = "PORTLET_PREFS_ID", nullable = false)
@Fetch(FetchMode.JOIN)
private final PortletPreferencesImpl portletPreferences;
@Transient private IPortletEntityId portletEntityId = null;
/** Used to initialize fields after persistence actions. */
@SuppressWarnings("unused")
@PostLoad
@PostPersist
@PostUpdate
@PostRemove
private void init() {
this.portletEntityId = new PortletEntityIdImpl(this.internalPortletEntityId);
}
/** Used by the ORM layer to create instances of the object. */
@SuppressWarnings("unused")
private PortletEntityImpl() {
this.internalPortletEntityId = -1;
this.entityVersion = -1;
this.portletDefinition = null;
this.layoutNodeId = null;
this.userId = -1;
this.portletPreferences = null;
}
public PortletEntityImpl(
IPortletDefinition portletDefinition, String channelSubscribeId, int userId) {
Validate.notNull(portletDefinition, "portletDefinition can not be null");
Validate.notNull(channelSubscribeId, "layoutNodeId can not be null");
this.internalPortletEntityId = -1;
this.entityVersion = -1;
this.portletDefinition = portletDefinition;
this.layoutNodeId = channelSubscribeId;
this.userId = userId;
this.portletPreferences = new PortletPreferencesImpl();
}
@Override
public IPortletDefinitionId getPortletDefinitionId() {
return this.portletDefinition.getPortletDefinitionId();
}
/* (non-Javadoc)
* @see org.apereo.portal.om.portlet.IPortletEntity#getPortletEntityId()
*/
@Override
public IPortletEntityId getPortletEntityId() {
return this.portletEntityId;
}
@Override
public IPortletDefinition getPortletDefinition() {
return this.portletDefinition;
}
/* (non-Javadoc)
* @see org.apereo.portal.om.portlet.IPortletEntity#getChannelSubscribeId()
*/
@Override
public String getLayoutNodeId() {
return this.layoutNodeId;
}
/* (non-Javadoc)
* @see org.apereo.portal.om.portlet.IPortletEntity#getUserId()
*/
@Override
public int getUserId() {
return this.userId;
}
@Override
public Map<Long, WindowState> getWindowStates() {
final Map<Long, WindowState> simpleWindowStates = new LinkedHashMap<Long, WindowState>();
synchronized (this.windowStates) {
for (Map.Entry<StylesheetDescriptorImpl, WindowState> windowStateEntry :
windowStates.entrySet()) {
final StylesheetDescriptorImpl stylesheetDescriptor = windowStateEntry.getKey();
final long stylesheetDescriptorId = stylesheetDescriptor.getId();
final WindowState windowState = windowStateEntry.getValue();
simpleWindowStates.put(stylesheetDescriptorId, windowState);
}
}
return Collections.unmodifiableMap(simpleWindowStates);
}
@Override
public WindowState getWindowState(IStylesheetDescriptor stylesheetDescriptor) {
synchronized (this.windowStates) {
return this.windowStates.get(stylesheetDescriptor);
}
}
@Override
public void setWindowState(IStylesheetDescriptor stylesheetDescriptor, WindowState state) {
synchronized (this.windowStates) {
if (state == null) {
this.windowStates.remove(stylesheetDescriptor);
} else {
this.windowStates.put((StylesheetDescriptorImpl) stylesheetDescriptor, state);
}
}
}
/* (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 int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.layoutNodeId == null) ? 0 : this.layoutNodeId.hashCode());
result =
prime * result
+ ((this.portletDefinition == null)
? 0
: this.portletDefinition.hashCode());
result = prime * result + this.userId;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (!IPortletEntity.class.isAssignableFrom(obj.getClass())) return false;
IPortletEntity other = (IPortletEntity) obj;
if (this.layoutNodeId == null) {
if (other.getLayoutNodeId() != null) return false;
} else if (!this.layoutNodeId.equals(other.getLayoutNodeId())) return false;
if (this.portletDefinition == null) {
if (other.getPortletDefinition() != null) return false;
} else if (!this.portletDefinition.equals(other.getPortletDefinition())) return false;
if (this.userId != other.getUserId()) return false;
return true;
}
@Override
public String toString() {
return "PortletEntity ["
+ "portletEntityId="
+ this.portletEntityId
+ ", "
+ "layoutNodeId="
+ this.layoutNodeId
+ ", "
+ "userId="
+ this.userId
+ ", "
+ "portletDefinition="
+ this.portletDefinition
+ "]";
}
}