org.dbflute.s2dao.extension.TnRelationRowOptionalHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dbflute-runtime Show documentation
Show all versions of dbflute-runtime Show documentation
The runtime library of DBFlute
/*
* Copyright 2014-2015 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.s2dao.extension;
import java.util.Map;
import org.dbflute.Entity;
import org.dbflute.bhv.core.context.ConditionBeanContext;
import org.dbflute.cbean.ConditionBean;
import org.dbflute.dbmeta.DBMeta;
import org.dbflute.exception.RelationEntityNotFoundException;
import org.dbflute.helper.beans.DfPropertyDesc;
import org.dbflute.helper.message.ExceptionMessageBuilder;
import org.dbflute.optional.OptionalThingExceptionThrower;
import org.dbflute.optional.RelationOptionalFactory;
import org.dbflute.outsidesql.OutsideSqlContext;
import org.dbflute.s2dao.metadata.TnRelationPropertyType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author jflute
* @since 1.0.5G (2014/05/20 Tuesday)
*/
public class TnRelationRowOptionalHandler {
// ===================================================================================
// Definition
// ==========
private static final Logger _log = LoggerFactory.getLogger(TnRelationRowOptionalHandler.class);
// ===================================================================================
// Attribute
// =========
protected final RelationOptionalFactory _relationOptionalFactory;
// ===================================================================================
// Constructor
// ===========
public TnRelationRowOptionalHandler(RelationOptionalFactory relationOptionalFactory) {
_relationOptionalFactory = relationOptionalFactory;
}
// ===================================================================================
// Filtering
// =========
/**
* Filter the relation row as optional object if it needs.
* @param row The base point row, which is previous relation row. (NotNull)
* @param rpt The property type for the relation. (NotNull)
* @param relationRow The row instance of relation entity. (NullAllowed)
* @return The filtered instance of relation entity. (NullAllowed)
*/
public Object filterOptionalRelationRowIfNeeds(Object row, TnRelationPropertyType rpt, Object relationRow) {
final Class> optionalType = getOptionalEntityType();
final DfPropertyDesc pd = rpt.getPropertyDesc();
if (optionalType.isAssignableFrom(pd.getPropertyType())) {
if (relationRow == null) {
return createOptionalNullEntity(row, rpt);
}
if (!optionalType.isInstance(relationRow)) {
return createOptionalPresentEntity(relationRow);
}
}
return relationRow;
}
// ===================================================================================
// Null Entity
// ===========
/**
* Create optional null entity.
* @param row The base point row, which is previous relation row. (NotNull)
* @param rpt The property type for the relation. (NotNull)
* @return The optional object for the relation. (NotNull)
*/
protected Object createOptionalNullEntity(Object row, TnRelationPropertyType rpt) { // object for override
return _relationOptionalFactory.createOptionalNullEntity(createOptionalNullableThrower(row, rpt));
}
protected OptionalThingExceptionThrower createOptionalNullableThrower(final Object row, TnRelationPropertyType rpt) {
final String propertyName = rpt.getPropertyDesc().getPropertyName();
final DBMeta localDBMeta = rpt.getMyBeanMetaData().getDBMeta();
final ConditionBean cb;
if (ConditionBeanContext.isExistConditionBeanOnThread()) {
cb = ConditionBeanContext.getConditionBeanOnThread();
} else {
cb = null;
}
final String outsideSqlPath;
final Object parameterBean;
if (OutsideSqlContext.isExistOutsideSqlContextOnThread()) {
final OutsideSqlContext context = OutsideSqlContext.getOutsideSqlContextOnThread();
outsideSqlPath = context.getOutsideSqlPath();
parameterBean = context.getParameterBean();
} else {
outsideSqlPath = null;
parameterBean = null;
}
return new OptionalThingExceptionThrower() {
public void throwNotFoundException() {
throwRelationEntityNotFoundException(row, propertyName, localDBMeta, cb, outsideSqlPath, parameterBean);
}
};
}
protected void throwRelationEntityNotFoundException(Object row, String propertyName, DBMeta localDBMeta, ConditionBean cb,
String outsideSqlPath, Object parameterBean) {
final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
br.addNotice("Not found the relation entity.");
br.addItem("Advice");
br.addElement("Confirm the existence in your business rule.");
br.addElement("If the relation entity might not exist, check it.");
br.addElement("For example:");
br.addElement(" (x):");
br.addElement(" List memberList = memberBhv.selectList(cb -> {");
br.addElement(" cb.setupSelect_MemberServiceAsOne();");
br.addElement(" });");
br.addElement(" for (Member member : memberList) {");
br.addElement(" ... = member.getMemberServiceAsOne().alwaysPresent(...); // *No");
br.addElement(" }");
br.addElement(" (o):");
br.addElement(" List memberList = memberBhv.selectList(cb -> {");
br.addElement(" cb.setupSelect_MemberServiceAsOne();");
br.addElement(" });");
br.addElement(" for (Member member : memberList) {");
br.addElement(" member.getMemberServiceAsOne().ifPresent(service -> { // OK");
br.addElement(" ... = service.getServicePointCount();");
br.addElement(" });");
br.addElement(" }");
br.addItem("Your Operation");
final String localTable = localDBMeta.getTableDbName();
final String localSuffix;
if (row instanceof Entity) { // basically here
final Map pkMap = localDBMeta.extractPrimaryKeyMap((Entity) row);
localSuffix = pkMap.toString();
} else {
localSuffix = "{" + row + "}";
}
br.addElement(localTable + ":" + localSuffix + " => " + propertyName);
if (row instanceof Entity) { // basically here
final Entity entity = ((Entity) row);
br.addItem("Local Entity");
try {
br.addElement(entity.toStringWithRelation());
} catch (RuntimeException continued) {
final String tableDbName = entity.asTableDbName();
final String msg = "*Failed to build string from the entity for debug: " + tableDbName;
if (_log.isDebugEnabled()) {
_log.debug(msg);
}
br.addElement(msg);
}
} else {
br.addItem("Local Entity");
br.addElement(row);
}
// cannot get it because this exception is after behavior command
// (thread locals are destroyed at that time)
//final InvokePathProvider invokePathProvider = InternalMapContext.getInvokePathProvider();
//if (invokePathProvider != null) {
// final String invokePath = invokePathProvider.provide();
// br.addItem("Behavior");
// br.addElement(invokePath);
//}
if (cb != null) {
br.addItem("ConditionBean");
try {
final String displaySql = cb.toDisplaySql();
br.addElement(displaySql);
} catch (RuntimeException continued) {
final String tableDbName = cb.asTableDbName();
final String msg = "*Failed to get display SQL from the condition-bean for debug: " + tableDbName;
if (_log.isDebugEnabled()) {
_log.debug(msg);
}
br.addElement(msg);
}
}
if (outsideSqlPath != null) {
br.addItem("OutsideSql");
br.addElement("path : " + outsideSqlPath);
br.addElement("pmb : " + parameterBean);
}
final String msg = br.buildExceptionMessage();
throw new RelationEntityNotFoundException(msg);
}
// ===================================================================================
// Present Entity
// ==============
/**
* Create optional present entity.
* @param relationRow The row instance of relation entity. (NullAllowed)
* @return The optional object for the relation. (NotNull)
*/
protected Object createOptionalPresentEntity(Object relationRow) { // object for override
return _relationOptionalFactory.createOptionalPresentEntity(relationRow);
}
// ===================================================================================
// OptionalEntity Type
// ===================
/**
* Get the type of optional entity for relation.
* @return The class type of optional entity. (NotNull)
*/
public Class> getOptionalEntityType() {
return _relationOptionalFactory.getOptionalEntityType();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy