Java tutorial
/************************************************************************* * Copyright 2009-2014 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. ************************************************************************/ package com.eucalyptus.entities; import java.util.Date; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import javax.annotation.Nullable; import org.hibernate.criterion.Criterion; import com.eucalyptus.auth.principal.AccountFullName; import com.eucalyptus.util.Callback; import com.eucalyptus.util.Exceptions; import com.eucalyptus.util.LogUtil; import com.eucalyptus.auth.principal.OwnerFullName; import com.eucalyptus.auth.type.RestrictedType; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; /** * Support for persistence DAOs. * * @param <RT> The RestrictedType for the AbstractOwnedPersistent * @param <AP> The AbstractOwnedPersistent type * @param <PE> The base persistence exception type. */ public abstract class AbstractPersistentSupport<RT extends RestrictedType, AP extends AbstractPersistent & RestrictedType, PE extends Exception> { protected final String typeDescription; protected AbstractPersistentSupport(final String typeDescription) { this.typeDescription = typeDescription; } public <T> T lookupByName(@Nullable final OwnerFullName ownerFullName, final String name, final Function<? super AP, T> transform) throws PE { return lookupByName(ownerFullName, name, Predicates.alwaysTrue(), transform); } public <T> T lookupByName(@Nullable final OwnerFullName ownerFullName, final String name, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { return lookupByExample(exampleWithName(ownerFullName, name), ownerFullName, name, filter, transform); } public <T> T lookupByExample(final AP example, @Nullable final OwnerFullName ownerFullName, final String key, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { try { return Transactions.one(example, filter, transform); } catch (NoSuchElementException e) { throw notFoundException( qualifyOwner("Unable to find " + typeDescription + " '" + key + "'", ownerFullName), e); } catch (Exception e) { throw metadataException( qualifyOwner("Error finding " + typeDescription + " '" + key + "'", ownerFullName), e); } } public List<AP> list(final OwnerFullName ownerFullName) throws PE { try { return Transactions.findAll(exampleWithOwner(ownerFullName)); } catch (Exception e) { throw metadataException(qualifyOwner("Failed to find " + typeDescription + "s", ownerFullName), e); } } public <T> List<T> list(final OwnerFullName ownerFullName, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { try { return Transactions.filteredTransform(exampleWithOwner(ownerFullName), filter, transform); } catch (Exception e) { throw metadataException(qualifyOwner("Failed to find " + typeDescription + "s", ownerFullName), e); } } public <T> List<T> list(final OwnerFullName ownerFullName, final Criterion criterion, final Map<String, String> aliases, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { try { return Transactions.filteredTransform(exampleWithOwner(ownerFullName), criterion, aliases, filter, transform); } catch (Exception e) { throw metadataException(qualifyOwner("Failed to find " + typeDescription + "s", ownerFullName), e); } } public <T> List<T> listByExample(final AP example, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { try { return Transactions.filteredTransform(example, filter, transform); } catch (Exception e) { throw metadataException( "Failed to find " + typeDescription + "s by example: " + LogUtil.dumpObject(example), e); } } public <T> List<T> listByExample(final AP example, final Predicate<? super AP> filter, final Criterion criterion, final Map<String, String> aliases, final Function<? super AP, T> transform) throws PE { try { return Transactions.filteredTransform(example, criterion, aliases, filter, transform); } catch (Exception e) { throw metadataException( "Failed to find " + typeDescription + "s by example: " + LogUtil.dumpObject(example), e); } } public long countByExample(final AP example) throws PE { try { return Entities.count(example); } catch (Exception e) { throw metadataException( "Failed to count " + typeDescription + "s by example: " + LogUtil.dumpObject(example), e); } } public long countByExample(final AP example, final Criterion criterion, final Map<String, String> aliases) throws PE { try { return Entities.count(example, criterion, aliases); } catch (Exception e) { throw metadataException( "Failed to count " + typeDescription + "s by example: " + LogUtil.dumpObject(example), e); } } public AP updateByExample(final AP example, final OwnerFullName ownerFullName, final String key, final Callback<AP> updateCallback) throws PE { try { return Transactions.one(example, updateCallback); } catch (NoSuchElementException e) { throw notFoundException( qualifyOwner("Unable to find " + typeDescription + " '" + key + "'", ownerFullName), e); } catch (Exception e) { throw metadataException( qualifyOwner("Error updating " + typeDescription + " '" + key + "'", ownerFullName), e); } } public <T> T updateByExample(final AP example, final OwnerFullName ownerFullName, final String key, final Function<? super AP, T> updateTransform) throws PE { try { return Transactions.one(example, updateTransform); } catch (NoSuchElementException e) { throw notFoundException( qualifyOwner("Unable to find " + typeDescription + " '" + key + "'", ownerFullName), e); } catch (Exception e) { throw metadataException( qualifyOwner("Error updating " + typeDescription + " '" + key + "'", ownerFullName), e); } } public <T> T updateByExample(final AP example, final Criterion criterion, final Map<String, String> aliases, final OwnerFullName ownerFullName, final String key, final Function<? super AP, T> updateTransform) throws PE { try { return Transactions.one(example, criterion, aliases, Predicates.alwaysTrue(), updateTransform); } catch (NoSuchElementException e) { throw notFoundException( qualifyOwner("Unable to find " + typeDescription + " '" + key + "'", ownerFullName), e); } catch (Exception e) { throw metadataException( qualifyOwner("Error updating " + typeDescription + " '" + key + "'", ownerFullName), e); } } public AP save(final AP metadata) throws PE { try { return Transactions.saveDirect(metadata); } catch (Exception e) { throw metadataException("Error creating " + typeDescription + " '" + metadata.getDisplayName() + "'", e); } } public boolean delete(final RT metadata) throws PE { return delete(metadata, Predicates.<AP>alwaysTrue()); } public boolean delete(final RT metadata, final Predicate<? super AP> precondition) throws PE { try { final String accountNumber = metadata instanceof RestrictedType.AccountRestrictedType ? ((RestrictedType.AccountRestrictedType) metadata).getOwnerAccountNumber() : metadata.getOwner().getAccountNumber(); return Transactions.delete( exampleWithName(AccountFullName.getInstance(accountNumber), metadata.getDisplayName()), precondition); } catch (NoSuchElementException e) { return false; } catch (Exception e) { throw metadataException("Error deleting " + typeDescription + " '" + describe(metadata) + "'", e); } } public List<AP> deleteByExample(final AP example) throws PE { try { return Transactions.each(example, new Callback<AP>() { @Override public void fire(final AP input) { Entities.delete(input); } }); } catch (Exception e) { throw metadataException( "Error deleting " + typeDescription + "s by example: " + LogUtil.dumpObject(example), e); } } public List<AP> deleteByExample(final AP example, final Criterion criterion, final Map<String, String> aliases) throws PE { try { return Transactions.each(example, criterion, aliases, new Callback<AP>() { @Override public void fire(final AP input) { Entities.delete(input); } }); } catch (Exception e) { throw metadataException( "Error deleting " + typeDescription + "s by example: " + LogUtil.dumpObject(example), e); } } protected String describe(final RestrictedType metadata) { return metadata.getDisplayName(); } protected abstract PE notFoundException(String message, Throwable cause); protected abstract PE metadataException(String message, Throwable cause); protected abstract AP exampleWithOwner(OwnerFullName ownerFullName); protected abstract AP exampleWithName(OwnerFullName ownerFullName, String name); protected String qualifyOwner(final String text, final OwnerFullName ownerFullName) { return ownerFullName == null ? text : text + " for " + ownerFullName; } public static Function<AbstractPersistent, Date> creation() { return AbstractPersistentDateFunctions.CREATION; } public static Function<AbstractPersistent, Date> lastUpdate() { return AbstractPersistentDateFunctions.LAST_UPDATE; } public AbstractPersistentSupport<RT, AP, PE> withRetries() { return withRetries(Entities.CONCURRENT_UPDATE_RETRIES); } public AbstractPersistentSupport<RT, AP, PE> withRetries(final int retries) { return new RetryingAbstractPersistentSupport<>(this, retries); } private static class RetryingAbstractPersistentSupport<RT extends RestrictedType, AP extends AbstractPersistent & RestrictedType, PE extends Exception> extends DelegatingAbstractPersistentSupport<RT, AP, PE> { private final int retries; private RetryingAbstractPersistentSupport(final AbstractPersistentSupport<RT, AP, PE> delegate, final int retries) { super(delegate); this.retries = retries; } @Override public <T> T updateByExample(final AP example, final OwnerFullName ownerFullName, final String key, final Function<? super AP, T> updateTransform) throws PE { return updateWithRetries(example.getClass(), new Function<Void, T>() { @Override public T apply(@Nullable final Void nothing) { try { return RetryingAbstractPersistentSupport.super.updateByExample(example, ownerFullName, key, updateTransform); } catch (final Exception e) { throw Exceptions.toUndeclared(e); } } }, ownerFullName, key); } @Override public AP updateByExample(final AP example, final OwnerFullName ownerFullName, final String key, final Callback<AP> updateCallback) throws PE { return updateWithRetries(example.getClass(), new Function<Void, AP>() { @Override public AP apply(@Nullable final Void nothing) { try { return RetryingAbstractPersistentSupport.super.updateByExample(example, ownerFullName, key, updateCallback); } catch (final Exception e) { throw Exceptions.toUndeclared(e); } } }, ownerFullName, key); } @Override public <T> T updateByExample(final AP example, final Criterion criterion, final Map<String, String> aliases, final OwnerFullName ownerFullName, final String key, final Function<? super AP, T> updateTransform) throws PE { return updateWithRetries(example.getClass(), new Function<Void, T>() { @Override public T apply(@Nullable final Void nothing) { try { return RetryingAbstractPersistentSupport.super.updateByExample(example, criterion, aliases, ownerFullName, key, updateTransform); } catch (final Exception e) { throw Exceptions.toUndeclared(e); } } }, ownerFullName, key); } @Override public List<AP> deleteByExample(final AP example) throws PE { return deleteWithRetries(example.getClass(), new Function<Void, List<AP>>() { @Override public List<AP> apply(@Nullable final Void nothing) { try { return RetryingAbstractPersistentSupport.super.deleteByExample(example); } catch (final Exception e) { throw Exceptions.toUndeclared(e); } } }, example); } @Override public List<AP> deleteByExample(final AP example, final Criterion criterion, final Map<String, String> aliases) throws PE { return deleteWithRetries(example.getClass(), new Function<Void, List<AP>>() { @Override public List<AP> apply(@Nullable final Void nothing) { try { return RetryingAbstractPersistentSupport.super.deleteByExample(example, criterion, aliases); } catch (final Exception e) { throw Exceptions.toUndeclared(e); } } }, example); } @Override public AbstractPersistentSupport<RT, AP, PE> withRetries() { return this; } @Override public AbstractPersistentSupport<RT, AP, PE> withRetries(final int retries) { return this; } private <T> T updateWithRetries(final Class<?> type, final Function<Void, T> updateFunction, final OwnerFullName ownerFullName, final String key) throws PE { try { return Entities.asTransaction(type, updateFunction, retries).apply(null); } catch (final Exception e) { throw metadataException( qualifyOwner("Error updating " + typeDescription + " '" + key + "'", ownerFullName), e); } } private <T> T deleteWithRetries(final Class<?> type, final Function<Void, T> deleteFunction, final AP example) throws PE { try { return Entities.asTransaction(type, deleteFunction, retries).apply(null); } catch (final Exception e) { throw metadataException( "Error deleting " + typeDescription + "s by example: " + LogUtil.dumpObject(example), e); } } } private static class DelegatingAbstractPersistentSupport<RT extends RestrictedType, AP extends AbstractPersistent & RestrictedType, PE extends Exception> extends AbstractPersistentSupport<RT, AP, PE> { private final AbstractPersistentSupport<RT, AP, PE> delegate; private DelegatingAbstractPersistentSupport(final AbstractPersistentSupport<RT, AP, PE> delegate) { super(delegate.typeDescription); this.delegate = delegate; } public <T> T lookupByName(@Nullable final OwnerFullName ownerFullName, final String name, final Function<? super AP, T> transform) throws PE { return delegate.lookupByName(ownerFullName, name, transform); } @Override public <T> T lookupByName(@Nullable final OwnerFullName ownerFullName, final String name, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { return delegate.lookupByName(ownerFullName, name, filter, transform); } public <T> T lookupByExample(final AP example, @Nullable final OwnerFullName ownerFullName, final String key, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { return delegate.lookupByExample(example, ownerFullName, key, filter, transform); } @Override public List<AP> list(final OwnerFullName ownerFullName) throws PE { return delegate.list(ownerFullName); } public <T> List<T> list(final OwnerFullName ownerFullName, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { return delegate.list(ownerFullName, filter, transform); } public <T> List<T> list(final OwnerFullName ownerFullName, final Criterion criterion, final Map<String, String> aliases, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { return delegate.list(ownerFullName, criterion, aliases, filter, transform); } public <T> List<T> listByExample(final AP example, final Predicate<? super AP> filter, final Function<? super AP, T> transform) throws PE { return delegate.listByExample(example, filter, transform); } public <T> List<T> listByExample(final AP example, final Predicate<? super AP> filter, final Criterion criterion, final Map<String, String> aliases, final Function<? super AP, T> transform) throws PE { return delegate.listByExample(example, filter, criterion, aliases, transform); } public long countByExample(final AP example) throws PE { return delegate.countByExample(example); } public long countByExample(final AP example, final Criterion criterion, final Map<String, String> aliases) throws PE { return delegate.countByExample(example, criterion, aliases); } public AP updateByExample(final AP example, final OwnerFullName ownerFullName, final String key, final Callback<AP> updateCallback) throws PE { return delegate.updateByExample(example, ownerFullName, key, updateCallback); } public <T> T updateByExample(final AP example, final OwnerFullName ownerFullName, final String key, final Function<? super AP, T> updateTransform) throws PE { return delegate.updateByExample(example, ownerFullName, key, updateTransform); } @Override public <T> T updateByExample(final AP example, final Criterion criterion, final Map<String, String> aliases, final OwnerFullName ownerFullName, final String key, final Function<? super AP, T> updateTransform) throws PE { return delegate.updateByExample(example, criterion, aliases, ownerFullName, key, updateTransform); } public AP save(final AP metadata) throws PE { return delegate.save(metadata); } public boolean delete(final RT metadata) throws PE { return delegate.delete(metadata); } @Override public boolean delete(final RT metadata, final Predicate<? super AP> precondition) throws PE { return delegate.delete(metadata, precondition); } public List<AP> deleteByExample(final AP example) throws PE { return delegate.deleteByExample(example); } public List<AP> deleteByExample(final AP example, final Criterion criterion, final Map<String, String> aliases) throws PE { return delegate.deleteByExample(example, criterion, aliases); } @Override public String describe(final RestrictedType metadata) { return delegate.describe(metadata); } @Override public PE notFoundException(final String message, final Throwable cause) { return delegate.notFoundException(message, cause); } @Override public PE metadataException(final String message, final Throwable cause) { return delegate.metadataException(message, cause); } @Override public AP exampleWithOwner(final OwnerFullName ownerFullName) { return delegate.exampleWithOwner(ownerFullName); } @Override public AP exampleWithName(final OwnerFullName ownerFullName, final String name) { return delegate.exampleWithName(ownerFullName, name); } @Override public String qualifyOwner(final String text, final OwnerFullName ownerFullName) { return delegate.qualifyOwner(text, ownerFullName); } public static Function<AbstractPersistent, Date> creation() { return AbstractPersistentSupport.creation(); } public static Function<AbstractPersistent, Date> lastUpdate() { return AbstractPersistentSupport.lastUpdate(); } @Override public AbstractPersistentSupport<RT, AP, PE> withRetries() { return delegate.withRetries(); } @Override public AbstractPersistentSupport<RT, AP, PE> withRetries(final int retries) { return delegate.withRetries(retries); } } private enum AbstractPersistentDateFunctions implements Function<AbstractPersistent, Date> { CREATION { @Nullable @Override public Date apply(@Nullable final AbstractPersistent abstractPersistent) { return abstractPersistent == null ? null : abstractPersistent.getCreationTimestamp(); } }, LAST_UPDATE { @Nullable @Override public Date apply(@Nullable final AbstractPersistent abstractPersistent) { return abstractPersistent == null ? null : abstractPersistent.getLastUpdateTimestamp(); } }, } }