Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.dbflute.optional.OptionalEntity Maven / Gradle / Ivy
/*
* Copyright 2014-2020 the original author or authors.
*
* Licensed 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
*
* 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.dbflute.optional;
import org.dbflute.exception.EntityAlreadyDeletedException;
import org.dbflute.exception.NonSetupSelectRelationAccessException;
import org.dbflute.helper.message.ExceptionMessageBuilder;
/**
* The entity as optional object, which has entity instance in it.
* You can handle null value by this methods without direct null handling.
*
* // if the data always exists as your business rule
* memberBhv .selectEntity (cb - > {
* cb .setupSelect_MemberStatus();
* cb .query().setMemberId_Equal(1 );
* }).alwaysPresent (member - > {
* // called if present, or exception
* ... = member .getMemberName();
* });
*
* // if it might be no data, ...
* memberBhv .selectEntity (cb - > cb .acceptPK(1 )).ifPresent (member - > {
* // called if present
* ... = member .getMemberName();
* }).orElse (() - > {
* // called if not present
* });
*
* @param The type of entity.
* @author jflute
* @since 1.0.5F (2014/05/05 Monday)
*/
public class OptionalEntity extends BaseOptional {
// ===================================================================================
// Definition
// ==========
private static final long serialVersionUID = 1L; // basically for relation entity's optional
protected static final OptionalEntity EMPTY_INSTANCE;
static {
EMPTY_INSTANCE = new OptionalEntity(null, new SerializableOptionalThingExceptionThrower() {
private static final long serialVersionUID = 1L;
public void throwNotFoundException() {
String msg = "The empty optional so the value is null.";
throw new EntityAlreadyDeletedException(msg);
}
});
}
protected static final OptionalThingExceptionThrower NOWAY_THROWER = new SerializableOptionalThingExceptionThrower() {
private static final long serialVersionUID = 1L;
@Override
public void throwNotFoundException() {
throw new EntityAlreadyDeletedException("no way");
}
};
// ===================================================================================
// Constructor
// ===========
/**
* @param entity The wrapped instance of entity. (NullAllowed)
* @param thrower The exception thrower when illegal access. (NotNull)
*/
public OptionalEntity(ENTITY entity, OptionalThingExceptionThrower thrower) { // basically called by DBFlute
super(entity, thrower);
}
/**
* @param The type of empty optional entity.
* @return The fixed instance as empty. (NotNull)
*/
@SuppressWarnings("unchecked")
public static OptionalEntity empty() {
return (OptionalEntity) EMPTY_INSTANCE;
}
/**
* @param The type of entity wrapped in the optional entity.
* @param entity The wrapped entity for the optional object. (NotNull)
* @return The new-created instance as existing optional object. (NotNull)
*/
public static OptionalEntity of(ENTITY entity) {
if (entity == null) {
String msg = "The argument 'entity' should not be null.";
throw new IllegalArgumentException(msg);
}
return new OptionalEntity(entity, NOWAY_THROWER);
}
/**
* @param The type of entity for the optional type.
* @param entity The wrapped instance or entity. (NullAllowed)
* @param noArgLambda The exception thrower when illegal access. (NotNull)
* @return The new-created instance as existing or empty optional object. (NotNull)
*/
public static OptionalEntity ofNullable(ENTITY entity, OptionalThingExceptionThrower noArgLambda) {
if (entity != null) {
return of(entity);
} else {
return new OptionalEntity(entity, noArgLambda);
}
}
/**
* @param The type of empty optional entity.
* @param entity The base entity of the relation for exception message. (NotNull)
* @param relation The property name of the relation for exception message. (NotNull)
* @return The new-created instance as existing or empty optional object. (NotNull)
*/
public static OptionalEntity relationEmpty(final Object entity, final String relation) {
if (entity == null) {
String msg = "The argument 'entity' should not be null.";
throw new IllegalArgumentException(msg);
}
if (relation == null) {
String msg = "The argument 'relation' should not be null.";
throw new IllegalArgumentException(msg);
}
return new OptionalEntity(null, new OptionalThingExceptionThrower() {
public void throwNotFoundException() {
throwNonSetupSelectRelationAccessException(entity, relation);
}
});
}
protected static void throwNonSetupSelectRelationAccessException(Object entity, String relation) {
final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
br.addNotice("Non-setupSelect relation was accessed.");
br.addItem("Advice");
br.addElement("Confirm your access to the relation.");
br.addElement("Call setupSelect or fix your access.");
br.addElement("For example:");
br.addElement(" (x):");
br.addElement(" memberBhv.selectList(cb -> {");
br.addElement(" cb.setupSelect_MemberStatus();");
br.addElement(" }).forEach(member -> {");
br.addElement(" ... = member.getMemberSecurityAsOne().alwaysPresent(...); // *NG");
br.addElement(" });");
br.addElement(" (o): (fix access mistake)");
br.addElement(" List memberList = memberBhv.selectList(cb -> {");
br.addElement(" cb.setupSelect_MemberStatus();");
br.addElement(" }).forEach(member -> {");
br.addElement(" ... = member.getMemberStatus().alwaysPresent(...); // OK");
br.addElement(" });");
br.addElement(" (o): (fix setupSelect mistake)");
br.addElement(" List memberList = memberBhv.selectList(cb -> {");
br.addElement(" cb.setupSelect_MemberSecurityAsOne(); // OK");
br.addElement(" }).forEach(member -> {");
br.addElement(" ... = member.getMemberSecurityAsOne().alwaysPresent(...);");
br.addElement(" });");
br.addItem("Your Relation");
br.addElement(entity.getClass().getSimpleName() + "." + relation);
final String msg = br.buildExceptionMessage();
throw new NonSetupSelectRelationAccessException(msg);
}
// ===================================================================================
// Standard Handling
// =================
/**
* Handle the wrapped entity if it is present.
* You should call this if null entity handling is unnecessary (do nothing if null).
* If exception is preferred when null entity, use required().
*
* memberBhv .selectEntity (cb - > {
* cb .setupSelect_MemberWithdrawal();
* cb .query().setMemberId_Equal(1 );
* }).ifPresent (member - > { // called if value exists, or not called
* ... = member .getMemberName();
* member .getMemberWithdrawal().ifPresent (withdrawal - > { // also relation
* ... = withdrawal .getWithdrawalDatetime();
* });
* }).orElse (() - > {
* // called if no value
* });
*
* @param entityLambda The callback interface to consume the optional entity. (NotNull)
* @return The handler of after process when if not present. (NotNull)
*/
public OptionalThingIfPresentAfter ifPresent(OptionalThingConsumer entityLambda) {
assertEntityLambdaNotNull(entityLambda);
return callbackIfPresent(entityLambda);
}
/**
* Is the entity instance present? (existing?)
*
* OptionalEntity<Member> optMember = memberBhv .selectEntity (cb - > {
* cb.query()...;
* });
* if (optMember .isPresent() ) { // true if the entity exists
* Member member = optMember .get();
* } else {
* ...
* }
*
* @return The determination, true or false.
*/
public boolean isPresent() {
return exists();
}
/**
* Get the entity or exception if null.
*
* OptionalEntity<Member> optMember = memberBhv .selectEntity(cb - > {
* cb .setupSelect_MemberStatus();
* cb .query().setMemberId_Equal(1 );
* });
*
* // if the data always exists as your business rule
* Member member = optMember .get() ;
*
* // if it might be no data, isPresent(), orElse(), ...
* if (optMember .isPresent() ) {
* Member member = optMember .get() ;
* } else {
* ...
* }
*
* @return The entity instance wrapped in this optional object. (NotNull)
* @throws EntityAlreadyDeletedException When the entity instance wrapped in this optional object is null, which means entity has already been deleted (point is not found).
*/
public ENTITY get() {
return directlyGet();
}
/**
* Filter the entity by the predicate.
*
* memberBhv .selectEntity (cb - > cb .acceptPK(1 )).filter (member - > {
* // called if value exists, not called if not present
* return member .getMemberId() % 2 == 0;
* }).ifPresent (member - > {
* ...
* });
*
* @param entityLambda The callback to predicate whether the entity is remained. (NotNull)
* @return The filtered optional entity, might be empty. (NotNull)
*/
public OptionalEntity filter(OptionalThingPredicate entityLambda) {
assertEntityLambdaNotNull(entityLambda);
return (OptionalEntity) callbackFilter(entityLambda);
}
/** {@inheritDoc} */
protected OptionalEntity createOptionalFilteredObject(ARG obj) {
return new OptionalEntity(obj, _thrower);
}
/**
* Apply the mapping of entity to result object.
*
* memberBhv .selectEntity (cb - > cb .acceptPK(1 )).map (member - > {
* // called if value exists, not called if not present
* return new MemberWebBean(member );
* }).alwaysPresent (member - > {
* ...
* });
*
* @param The type of mapping result.
* @param entityLambda The callback interface to apply, null return allowed as empty. (NotNull)
* @return The optional thing as mapped result. (NotNull, EmptyOptionalAllowed: if not present or callback returns null)
*/
@SuppressWarnings("unchecked")
public OptionalEntity map(OptionalThingFunction super ENTITY, ? extends RESULT> entityLambda) {
assertEntityLambdaNotNull(entityLambda);
return (OptionalEntity) callbackMapping(entityLambda); // downcast allowed because factory is overridden
}
/** {@inheritDoc} */
protected OptionalEntity createOptionalMappedObject(ARG obj) {
return new OptionalEntity(obj, _thrower);
}
/**
* Apply the flat-mapping of entity to result object.
*
* memberBhv .selectEntity (cb - > cb .acceptPK(1 )).flatMap (member - > {
* // called if value exists, not called if not present
* return member .getMemberWithdrawal();
* }).ifPresent (withdrawal - > {
* ...
* });
*
* @param The type of mapping result.
* @param entityLambda The callback interface to apply, cannot return null. (NotNull)
* @return The optional thing as mapped result. (NotNull, EmptyOptionalAllowed: when not present)
*/
public OptionalThing flatMap(OptionalThingFunction super ENTITY, OptionalThing> entityLambda) {
assertEntityLambdaNotNull(entityLambda);
return callbackFlatMapping(entityLambda);
}
/** {@inheritDoc} */
protected OptionalEntity createOptionalFlatMappedObject(ARG obj) {
return new OptionalEntity(obj, _thrower);
}
// _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
// following methods might be rare case...
// _/_/_/_/_/_/_/_/_/_/
/** {@inheritDoc} */
public ENTITY orElse(ENTITY other) {
return directlyGetOrElse(other);
}
/** {@inheritDoc} */
public ENTITY orElseGet(OptionalThingSupplier noArgLambda) {
return directlyGetOrElseGet(noArgLambda);
}
/** {@inheritDoc} */
public ENTITY orElseThrow(OptionalThingSupplier extends CAUSE> noArgLambda) throws CAUSE {
return directlyGetOrElseThrow(noArgLambda);
}
/** {@inheritDoc} */
public ENTITY orElseTranslatingThrow(
OptionalThingFunction oneArgLambda) throws TRANSLATED {
return directlyGetOrElseTranslatingThrow(oneArgLambda);
}
// ===================================================================================
// DBFlute Extension
// =================
/**
* Handle the entity in the optional object or exception if not present.
*
* memberBhv .selectEntity (cb - > {
* cb .setupSelect_MemberStatus();
* cb .query().setMemberId_Equal(1 );
* }).alwaysPresent (member - > { // called if value exists, or exception
* ... = member .getMemberName();
* member .getMemberStatus().alwaysPresent (status - > { // also relation
* ... = status .getMemberStatusName();
* });
* });
*
* @param entityLambda The callback interface to consume the optional value. (NotNull)
* @throws EntityAlreadyDeletedException When the entity instance wrapped in this optional object is null, which means entity has already been deleted (point is not found).
*/
public void alwaysPresent(OptionalThingConsumer entityLambda) {
assertEntityLambdaNotNull(entityLambda);
callbackAlwaysPresent(entityLambda);
}
/**
* Get the entity instance or null if not present.
* basically use ifPresent() if might be not present, this is for emergency
* @return The object instance wrapped in this optional object or null. (NullAllowed: if not present)
* @deprecated basically use ifPresent() or use orElse(null)
*/
public ENTITY orElseNull() {
return directlyGetOrElse(null);
}
// ===================================================================================
// Assert Helper
// =============
protected void assertEntityLambdaNotNull(Object entityLambda) {
if (entityLambda == null) {
throw new IllegalArgumentException("The argument 'entityLambda' should not be null.");
}
}
}