/*
* Copyright (C) 2015, 2016 higherfrequencytrading.com
* Copyright (C) 2016 Roman Leventov
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.chronicle.values;
import com.squareup.javapoet.*;
import net.openhft.chronicle.bytes.NativeBytesStore;
import net.openhft.chronicle.core.Jvm;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import static javax.lang.model.element.Modifier.*;
class ValueBuilder {
final ValueModel model;
final String className;
final TypeSpec.Builder typeBuilder;
private FieldSpec unsafe;
private CodeBlock.Builder staticBlockBuilder;
private MethodSpec.Builder defaultConstructorBuilder;
private FieldSpec bytesStoreForPointers;
public ValueBuilder(ValueModel model, String className, TypeSpec.Builder typeBuilder) {
this.model = model;
this.className = className;
this.typeBuilder = typeBuilder;
}
ClassName className() {
return ClassName.get(model.valueType.getPackage().getName(), className);
}
FieldSpec unsafe() {
if (unsafe == null) {
unsafe = FieldSpec.builder(Unsafe.class, "UNSAFE", PRIVATE, STATIC, FINAL).build();
typeBuilder.addField(unsafe);
staticBlockBuilder()
.beginControlFlow("try")
.addStatement("$T theUnsafe = $T.getField($T.class, $S)",
Field.class, Jvm.class, Unsafe.class, "theUnsafe")
.addStatement("$N = ($T) theUnsafe.get(null)", unsafe, Unsafe.class);
}
return unsafe;
}
CodeBlock.Builder staticBlockBuilder() {
if (staticBlockBuilder == null)
staticBlockBuilder = CodeBlock.builder();
return staticBlockBuilder;
}
MethodSpec.Builder defaultConstructorBuilder() {
if (defaultConstructorBuilder == null) {
defaultConstructorBuilder = MethodSpec.constructorBuilder();
defaultConstructorBuilder.addModifiers(PUBLIC);
}
return defaultConstructorBuilder;
}
void closeConstructorsAndInitializationBlocks() {
if (staticBlockBuilder != null) {
staticBlockBuilder.nextControlFlow("catch ($T e)", IllegalAccessException.class);
staticBlockBuilder.addStatement("throw new $T(e)", AssertionError.class);
staticBlockBuilder.endControlFlow();
typeBuilder.addStaticBlock(staticBlockBuilder.build());
}
if (defaultConstructorBuilder != null) {
typeBuilder.addMethod(defaultConstructorBuilder.build());
}
}
FieldSpec bytesStoreForPointers() {
if (bytesStoreForPointers == null) {
ParameterizedTypeName bsType =
ParameterizedTypeName.get(NativeBytesStore.class, Void.class);
bytesStoreForPointers = FieldSpec
.builder(bsType, "bytesStoreForPointers", PRIVATE, STATIC, FINAL)
.initializer("$T.instance()", PointersBytesStore.class)
.build();
typeBuilder.addField(bytesStoreForPointers);
}
return bytesStoreForPointers;
}
}