org.jooq.impl.RecordDelegate Maven / Gradle / Ivy
/**
* Copyright (c) 2009-2015, Data Geekery GmbH (http://www.datageekery.com)
* All rights reserved.
*
* 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.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import static org.jooq.ExecuteType.READ;
import static org.jooq.ExecuteType.WRITE;
import static org.jooq.impl.RecordDelegate.RecordLifecycleType.LOAD;
import static org.jooq.impl.RecordDelegate.RecordLifecycleType.REFRESH;
import static org.jooq.impl.Utils.attachRecords;
import org.jooq.Configuration;
import org.jooq.ExecuteType;
import org.jooq.Record;
import org.jooq.RecordListener;
import org.jooq.RecordListenerProvider;
import org.jooq.exception.ControlFlowSignal;
/**
* A stub for {@link Record} objects, abstracting {@link RecordListener}
* lifecycle handling.
*
* @author Lukas Eder
*/
class RecordDelegate {
private final Configuration configuration;
private final R record;
private final RecordLifecycleType type;
RecordDelegate(Configuration configuration, R record) {
this(configuration, record, LOAD);
}
RecordDelegate(Configuration configuration, R record, RecordLifecycleType type) {
this.configuration = configuration;
this.record = record;
this.type = type;
}
static final RecordDelegate delegate(Configuration configuration, R record) {
return new RecordDelegate(configuration, record);
}
static final RecordDelegate delegate(Configuration configuration, R record, RecordLifecycleType type) {
return new RecordDelegate(configuration, record, type);
}
@SuppressWarnings("unchecked")
final R operate(RecordOperation super R, E> operation) throws E {
RecordListenerProvider[] providers = null;
RecordListener[] listeners = null;
DefaultRecordContext ctx = null;
E exception = null;
if (configuration != null) {
providers = configuration.recordListenerProviders();
if (providers != null && providers.length > 0) {
listeners = new RecordListener[providers.length];
ctx = new DefaultRecordContext(configuration, executeType(), record);
for (int i = 0; i < providers.length; i++) {
listeners[i] = providers[i].provide();
}
}
}
if (listeners != null) {
for (RecordListener listener : listeners) {
switch (type) {
case LOAD: listener.loadStart(ctx); break;
case REFRESH: listener.refreshStart(ctx); break;
case STORE: listener.storeStart(ctx); break;
case INSERT: listener.insertStart(ctx); break;
case UPDATE: listener.updateStart(ctx); break;
case DELETE: listener.deleteStart(ctx); break;
default:
throw new IllegalStateException("Type not supported: " + type);
}
}
}
if (operation != null) {
try {
operation.operate(record);
}
// [#2770][#3036] Exceptions must not propagate before listeners receive "end" events
catch (Exception e) {
exception = (E) e;
// Do not propagate these exception types to client code as they're not really "exceptions"
if (!(e instanceof ControlFlowSignal)) {
if (ctx != null)
ctx.exception = e;
if (listeners != null)
for (RecordListener listener : listeners)
listener.exception(ctx);
}
}
}
// [#1684] Do not attach configuration if settings say no
if (attachRecords(configuration)) {
record.attach(configuration);
}
if (listeners != null) {
for (RecordListener listener : listeners) {
switch (type) {
case LOAD: listener.loadEnd(ctx); break;
case REFRESH: listener.refreshEnd(ctx); break;
case STORE: listener.storeEnd(ctx); break;
case INSERT: listener.insertEnd(ctx); break;
case UPDATE: listener.updateEnd(ctx); break;
case DELETE: listener.deleteEnd(ctx); break;
default:
throw new IllegalStateException("Type not supported: " + type);
}
}
}
if (exception != null) {
throw exception;
}
return record;
}
private final ExecuteType executeType() {
return type == LOAD || type == REFRESH ? READ : WRITE;
}
enum RecordLifecycleType {
LOAD,
REFRESH,
STORE,
INSERT,
UPDATE,
DELETE
}
}