/*
* Copyright 2013 Nicolas Morel
*
* 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 com.github.nmorel.gwtjackson.rebind.property;
import javax.lang.model.element.Modifier;
import com.github.nmorel.gwtjackson.rebind.property.FieldAccessor;
import com.github.nmorel.gwtjackson.rebind.writer.JsniCodeBlockBuilder;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.thirdparty.guava.common.base.Optional;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import static com.github.nmorel.gwtjackson.rebind.writer.JTypeName.typeName;
/**
* @author Nicolas Morel
*/
final class FieldReadAccessor extends FieldAccessor {
FieldReadAccessor( String propertyName, boolean samePackage, boolean fieldAutoDetect, Optional<JField> field,
boolean getterAutoDetect, Optional<JMethod> getter ) {
super( propertyName, samePackage, fieldAutoDetect, field, getterAutoDetect, getter );
}
/** {@inheritDoc} */
@Override
protected Accessor getAccessor( final String beanName, final boolean useMethod, final boolean useJsni, Object... params ) {
if ( !useJsni ) {
if ( useMethod ) {
return new Accessor( CodeBlock.builder().add( beanName + "." + method.get().getName() + "()" ).build() );
} else {
return new Accessor( CodeBlock.builder().add( beanName + "." + field.get().getName() ).build() );
}
}
// field/getter has not been detected or is private or is in a different package. We use JSNI to access getter/field.
final JType fieldType;
final JClassType enclosingType;
if ( useMethod ) {
fieldType = method.get().getReturnType();
enclosingType = method.get().getEnclosingType();
} else {
fieldType = field.get().getType();
enclosingType = field.get().getEnclosingType();
}
JsniCodeBlockBuilder jsniCode = JsniCodeBlockBuilder.builder();
if ( useMethod ) {
jsniCode.addStatement( "return bean.@$L::$L()()", enclosingType.getQualifiedSourceName(), method.get().getName() );
} else {
jsniCode.addStatement( "return bean.@$L::$L", enclosingType.getQualifiedSourceName(), field.get().getName() );
}
MethodSpec additionalMethod = MethodSpec.methodBuilder( "getValueWithJsni" )
.addModifiers( Modifier.PRIVATE, Modifier.NATIVE )
.returns( typeName( fieldType ) )
.addParameter( typeName( enclosingType ), "bean" )
.addCode( jsniCode.build() )
.build();
CodeBlock accessor = CodeBlock.builder().add( "$N($L)", additionalMethod, beanName ).build();
return new Accessor( accessor, additionalMethod );
}
}