/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * 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.CacheType; import org.eclipse.persistence.annotations.CacheCoordinationType; 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 Boolean m_shared; 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_shared = cache.getAttributeBooleanDefaultTrue("shared"); 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_shared, cache.getShared())) { 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_shared != null ? m_shared.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; } /** * INTERNAL: * Used for OX mapping. */ public Boolean getShared() { return m_shared; } 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 shared. if ( (m_shared !=null && !m_shared.booleanValue()) || (m_shared == null && descriptor.getProject().isSharedCacheModeEnableSelective())){ classDescriptor.getCachePolicy().setCacheIsolation(CacheIsolationType.ISOLATED); } 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; } /** * INTERNAL: * Used for OX mapping. */ public void setShared(Boolean shared) { m_shared = shared; } 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; } }