blob: 8bc9e172234309877cc471b14ba3c84a31d4b06b [file] [log] [blame]
/*
* Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// 05/16/2008-1.0M8 Guy Pelletier
// - 218084: Implement metadata merging functionality between mapping files
// 04/27/2010-2.1 Guy Pelletier
// - 309856: MappedSuperclasses from XML are not being initialized properly
// 03/24/2011-2.3 Guy Pelletier
// - 337323: Multi-tenant with shared schema support (part 1)
package org.eclipse.persistence.internal.jpa.metadata.cache;
import org.eclipse.persistence.annotations.CacheCoordinationType;
import org.eclipse.persistence.annotations.CacheType;
import org.eclipse.persistence.annotations.DatabaseChangeNotificationType;
import org.eclipse.persistence.config.CacheIsolationType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.invalidation.DailyCacheInvalidationPolicy;
import org.eclipse.persistence.descriptors.invalidation.TimeToLiveCacheInvalidationPolicy;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.jpa.metadata.MetadataDescriptor;
import org.eclipse.persistence.internal.jpa.metadata.ORMetadata;
import org.eclipse.persistence.internal.jpa.metadata.accessors.MetadataAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
/**
* Object to hold onto cache metadata.
*
* Key notes:
* - any metadata mapped from XML to this class must be compared in the
* equals method.
* - when loading from annotations, the constructor accepts the metadata
* accessor this metadata was loaded from. Used it to look up any
* 'companion' annotation needed for processing.
* - methods should be preserved in alphabetical order.
*
* @author Guy Pelletier
* @since TopLink 11g
*/
public class CacheMetadata extends ORMetadata {
protected Boolean m_alwaysRefresh;
protected Boolean m_disableHits;
protected String m_isolation;
protected Boolean m_refreshOnlyIfNewer;
protected String m_coordinationType;
protected String m_databaseChangeNotificationType;
protected String m_type;
protected Integer m_expiry;
protected Integer m_size;
protected TimeOfDayMetadata m_expiryTimeOfDay;
/**
* INTERNAL:
* Used for XML loading.
*/
public CacheMetadata() {
super("<cache>");
}
/**
* INTERNAL:
* Used for annotation loading.
*/
public CacheMetadata(MetadataAnnotation cache, MetadataAccessor accessor) {
super(cache, accessor);
m_alwaysRefresh = cache.getAttributeBooleanDefaultFalse("alwaysRefresh");
m_disableHits = cache.getAttributeBooleanDefaultFalse("disableHits");
m_coordinationType = cache.getAttributeString("coordinationType");
m_databaseChangeNotificationType = cache.getAttributeString("databaseChangeNotificationType");
m_expiry = cache.getAttributeInteger("expiry");
MetadataAnnotation expiryTimeOfDay = cache.getAttributeAnnotation("expiryTimeOfDay");
if (expiryTimeOfDay != null) {
m_expiryTimeOfDay = new TimeOfDayMetadata(expiryTimeOfDay, accessor);
}
m_isolation = cache.getAttributeString("isolation");
m_size = cache.getAttributeInteger("size");
m_type = cache.getAttributeString("type");
m_refreshOnlyIfNewer = cache.getAttributeBooleanDefaultFalse("refreshOnlyIfNewer");
}
/**
* INTERNAL:
*/
@Override
public boolean equals(Object objectToCompare) {
if (objectToCompare instanceof CacheMetadata) {
CacheMetadata cache = (CacheMetadata) objectToCompare;
if (! valuesMatch(m_alwaysRefresh, cache.getAlwaysRefresh())) {
return false;
}
if (! valuesMatch(m_disableHits, cache.getDisableHits())) {
return false;
}
if (! valuesMatch(m_isolation, cache.getIsolation())) {
return false;
}
if (! valuesMatch(m_refreshOnlyIfNewer, cache.getRefreshOnlyIfNewer())) {
return false;
}
if (! valuesMatch(m_coordinationType, cache.getCoordinationType())) {
return false;
}
if (! valuesMatch(m_databaseChangeNotificationType, cache.getDatabaseChangeNotificationType())) {
return false;
}
if (! valuesMatch(m_type, cache.getType())) {
return false;
}
if (! valuesMatch(m_expiry, cache.getExpiry())) {
return false;
}
if (! valuesMatch(m_size, cache.getSize())) {
return false;
}
return valuesMatch(m_expiryTimeOfDay, cache.getExpiryTimeOfDay());
}
return false;
}
@Override
public int hashCode() {
int result = m_alwaysRefresh != null ? m_alwaysRefresh.hashCode() : 0;
result = 31 * result + (m_disableHits != null ? m_disableHits.hashCode() : 0);
result = 31 * result + (m_isolation != null ? m_isolation.hashCode() : 0);
result = 31 * result + (m_refreshOnlyIfNewer != null ? m_refreshOnlyIfNewer.hashCode() : 0);
result = 31 * result + (m_coordinationType != null ? m_coordinationType.hashCode() : 0);
result = 31 * result + (m_databaseChangeNotificationType != null ? m_databaseChangeNotificationType.hashCode() : 0);
result = 31 * result + (m_type != null ? m_type.hashCode() : 0);
result = 31 * result + (m_expiry != null ? m_expiry.hashCode() : 0);
result = 31 * result + (m_size != null ? m_size.hashCode() : 0);
result = 31 * result + (m_expiryTimeOfDay != null ? m_expiryTimeOfDay.hashCode() : 0);
return result;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public Boolean getAlwaysRefresh() {
return m_alwaysRefresh;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public String getCoordinationType() {
return m_coordinationType;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public Boolean getDisableHits() {
return m_disableHits;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public Integer getExpiry() {
return m_expiry;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public TimeOfDayMetadata getExpiryTimeOfDay() {
return m_expiryTimeOfDay;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public Boolean getRefreshOnlyIfNewer() {
return m_refreshOnlyIfNewer;
}
public String getIsolation(){
return m_isolation;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public Integer getSize() {
return m_size;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public String getType() {
return m_type;
}
/**
* INTERNAL:
*/
public void process(MetadataDescriptor descriptor, MetadataClass javaClass) {
// Set the cache flag on the metadata Descriptor.
descriptor.setHasCache();
// Process the cache metadata.
ClassDescriptor classDescriptor = descriptor.getClassDescriptor();
// Process type
if (m_type == null) {
// Leave as default.
} else if (m_type.equals(CacheType.SOFT_WEAK.name())) {
classDescriptor.useSoftCacheWeakIdentityMap();
} else if (m_type.equals(CacheType.FULL.name())) {
classDescriptor.getCachePolicy().useFullIdentityMap();
} else if (m_type.equals(CacheType.WEAK.name())) {
classDescriptor.getCachePolicy().useWeakIdentityMap();
} else if (m_type.equals(CacheType.SOFT.name())) {
classDescriptor.getCachePolicy().useSoftIdentityMap();
} else if (m_type.equals(CacheType.HARD_WEAK.name())) {
classDescriptor.getCachePolicy().useHardCacheWeakIdentityMap();
} else if (m_type.equals(CacheType.CACHE.name())) {
classDescriptor.useCacheIdentityMap();
} else if (m_type.equals(CacheType.NONE.name())) {
classDescriptor.getCachePolicy().useNoIdentityMap();
}
// Process size.
if (m_size != null) {
classDescriptor.getCachePolicy().setIdentityMapSize(m_size);
}
// Process isolation.
if (m_isolation != null){
classDescriptor.getCachePolicy().setCacheIsolation(CacheIsolationType.valueOf(m_isolation));
}
// Process expiry or expiry time of day.
if (m_expiryTimeOfDay == null) {
// Expiry time of day is not specified, look for an expiry.
if (m_expiry != null && m_expiry != -1) {
classDescriptor.setCacheInvalidationPolicy(new TimeToLiveCacheInvalidationPolicy(m_expiry));
}
} else {
// Expiry time of day is specified, if expiry is also specified,
// throw an exception.
if (m_expiry == null || m_expiry == -1) {
classDescriptor.setCacheInvalidationPolicy(new DailyCacheInvalidationPolicy(m_expiryTimeOfDay.processHour(), m_expiryTimeOfDay.processMinute(), m_expiryTimeOfDay.processSecond(), m_expiryTimeOfDay.processMillisecond()));
} else {
throw ValidationException.cacheExpiryAndExpiryTimeOfDayBothSpecified(javaClass);
}
}
// Process always refresh.
if (m_alwaysRefresh != null) {
classDescriptor.getCachePolicy().setShouldAlwaysRefreshCache(m_alwaysRefresh);
}
// Process refresh only if newer.
if (m_refreshOnlyIfNewer != null) {
classDescriptor.getCachePolicy().setShouldOnlyRefreshCacheIfNewerVersion(m_refreshOnlyIfNewer);
}
// Process disable hits.
if (m_disableHits != null) {
classDescriptor.getCachePolicy().setShouldDisableCacheHits(m_disableHits);
}
// Process coordination type.
if (m_coordinationType == null) {
// Leave as default.
} else if (m_coordinationType.equals(CacheCoordinationType.SEND_OBJECT_CHANGES.name())) {
classDescriptor.getCachePolicy().setCacheSynchronizationType(ClassDescriptor.SEND_OBJECT_CHANGES);
} else if (m_coordinationType.equals(CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS.name())) {
classDescriptor.getCachePolicy().setCacheSynchronizationType(ClassDescriptor.INVALIDATE_CHANGED_OBJECTS);
} else if (m_coordinationType.equals(CacheCoordinationType.SEND_NEW_OBJECTS_WITH_CHANGES.name())) {
classDescriptor.getCachePolicy().setCacheSynchronizationType(ClassDescriptor.SEND_NEW_OBJECTS_WITH_CHANGES);
} else if (m_coordinationType.equals(CacheCoordinationType.NONE.name())) {
classDescriptor.getCachePolicy().setCacheSynchronizationType(ClassDescriptor.DO_NOT_SEND_CHANGES);
}
// Process database change notification type.
if (m_databaseChangeNotificationType == null) {
// Leave as default.
} else if (m_databaseChangeNotificationType.equals(DatabaseChangeNotificationType.NONE.name())) {
classDescriptor.getCachePolicy().setDatabaseChangeNotificationType(DatabaseChangeNotificationType.NONE);
} else if (m_databaseChangeNotificationType.equals(DatabaseChangeNotificationType.INVALIDATE.name())) {
classDescriptor.getCachePolicy().setDatabaseChangeNotificationType(DatabaseChangeNotificationType.INVALIDATE);
}
}
/**
* INTERNAL:
* Used for OX mapping
*/
public void setAlwaysRefresh(Boolean alwaysRefresh) {
m_alwaysRefresh = alwaysRefresh;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setCoordinationType(String coordinationType) {
m_coordinationType = coordinationType;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public String getDatabaseChangeNotificationType() {
return m_databaseChangeNotificationType;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setDatabaseChangeNotificationType(String databaseChangeNotificationType) {
m_databaseChangeNotificationType = databaseChangeNotificationType;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setDisableHits(Boolean disableHits) {
m_disableHits = disableHits;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setExpiry(Integer expiry) {
m_expiry = expiry;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setExpiryTimeOfDay(TimeOfDayMetadata expiryTimeOfDay) {
m_expiryTimeOfDay = expiryTimeOfDay;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setRefreshOnlyIfNewer(Boolean refreshOnlyIfNewer) {
m_refreshOnlyIfNewer = refreshOnlyIfNewer;
}
public void setIsolation(String isolation){
m_isolation = isolation;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setSize(Integer size) {
m_size = size;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setType(String type) {
m_type = type;
}
}