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.
com.enigmabridge.ebuilder.processor.DefaultPropertyFactory Maven / Gradle / Ivy
/*
* Copyright 2014 Google Inc. 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.
*/
package com.enigmabridge.ebuilder.processor;
import static com.enigmabridge.ebuilder.processor.BuilderMethods.*;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.enigmabridge.ebuilder.processor.util.PreconditionExcerpts.checkNotNullInline;
import static com.enigmabridge.ebuilder.processor.util.PreconditionExcerpts.checkNotNullPreamble;
import static com.enigmabridge.ebuilder.processor.util.feature.FunctionPackage.FUNCTION_PACKAGE;
import com.enigmabridge.ebuilder.processor.util.Excerpt;
import com.enigmabridge.ebuilder.processor.util.feature.FunctionPackage;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.enigmabridge.ebuilder.processor.Metadata.Property;
import com.enigmabridge.ebuilder.processor.PropertyCodeGenerator.Config;
import com.enigmabridge.ebuilder.processor.util.Block;
import com.enigmabridge.ebuilder.processor.util.Excerpts;
import com.enigmabridge.ebuilder.processor.util.ParameterizedType;
import com.enigmabridge.ebuilder.processor.util.PreconditionExcerpts;
import com.enigmabridge.ebuilder.processor.util.SourceBuilder;
import javax.lang.model.type.TypeMirror;
/** Default {@link PropertyCodeGenerator.Factory}, providing reference semantics for any type. */
public class DefaultPropertyFactory implements PropertyCodeGenerator.Factory {
@Override
public Optional create(Config config) {
Property property = config.getProperty();
boolean hasDefault = config.getMethodsInvokedInBuilderConstructor().contains(setter(property));
return Optional.of(new CodeGenerator(config.getMetadata(), property, hasDefault));
}
@VisibleForTesting static class CodeGenerator extends PropertyCodeGenerator {
private final boolean hasDefault;
private final boolean isPrimitive;
CodeGenerator(Metadata metadata, Property property, boolean hasDefault) {
super(metadata, property);
this.hasDefault = hasDefault;
this.isPrimitive = property.getType().getKind().isPrimitive();
}
@Override
public Type getType() {
return hasDefault ? Type.HAS_DEFAULT : Type.REQUIRED;
}
@Override
public void addBuilderFieldDeclaration(SourceBuilder code) {
code.addLine("%s %s;", property.getType(), property.getName());
}
@Override
public void addBuilderFieldAccessors(SourceBuilder code) {
addSetter(code, metadata);
addMapper(code, metadata);
addGetter(code, metadata);
}
private void addSetter(SourceBuilder code, final Metadata metadata) {
code.addLine("")
.addLine("/**")
.addLine(" * Sets the value to be returned by %s.",
metadata.getType().javadocNoArgMethodLink(property.getGetterName()))
.addLine(" *")
.addLine(" * @return this {@code %s} object", metadata.getBuilder().getSimpleName());
if (!isPrimitive) {
code.addLine(" * @throws NullPointerException if {@code %s} is null", property.getName());
}
code.addLine(" */");
addAccessorAnnotations(code);
code.addLine("public %s %s(%s %s) {",
metadata.getBuildGen(), setter(property), property.getType(), property.getName());
if (isPrimitive) {
code.addLine(" this.%1$s = %1$s;", property.getName());
} else {
code.add(checkNotNullPreamble(property.getName()))
.addLine(" this.%s = %s;", property.getName(), checkNotNullInline(property.getName()));
}
if (!hasDefault) {
code.addLine(" _unsetProperties.remove(%s.%s);",
metadata.getPropertyEnum(), property.getAllCapsName());
}
code.addLine(" return getThisBuilder();");
// if ((metadata.getBuilder() == metadata.getGeneratedABuilder())) {
// code.addLine(" return this;");
// } else {
// code.addLine(" return (%s) this;", metadata.getBuilder());
// }
code.addLine("}");
}
private void addMapper(SourceBuilder code, final Metadata metadata) {
ParameterizedType unaryOperator = code.feature(FunctionPackage.FUNCTION_PACKAGE).unaryOperator().orNull();
if (unaryOperator == null) {
return;
}
code.addLine("")
.addLine("/**")
.addLine(" * Replaces the value to be returned by %s",
metadata.getType().javadocNoArgMethodLink(property.getGetterName()))
.addLine(" * by applying {@code mapper} to it and using the result.")
.addLine(" *")
.addLine(" * @return this {@code %s} object", metadata.getBuilder().getSimpleName())
.addLine(" * @throws NullPointerException if {@code mapper} is null"
+ " or returns null");
if (!hasDefault) {
code.addLine(" * @throws IllegalStateException if the field has not been set");
}
TypeMirror typeParam = firstNonNull(property.getBoxedType(), property.getType());
code.addLine(" */")
.add("public %s %s(%s mapper) {",
metadata.getBuildGen(),
mapper(property),
unaryOperator.withParameters(typeParam));
if (!hasDefault) {
code.add(PreconditionExcerpts.checkNotNull("mapper"));
}
code.addLine(" return %s(mapper.apply(%s()));", setter(property), getter(property))
.addLine("}");
}
private void addGetter(SourceBuilder code, final Metadata metadata) {
code.addLine("")
.addLine("/**")
.addLine(" * Returns the value that will be returned by %s.",
metadata.getType().javadocNoArgMethodLink(property.getGetterName()));
if (!hasDefault) {
code.addLine(" *")
.addLine(" * @throws IllegalStateException if the field has not been set");
}
code.addLine(" */")
.addLine("public %s %s() {", property.getType(), getter(property));
if (!hasDefault) {
Excerpt propertyIsSet = Excerpts.add("!_unsetProperties.contains(%s.%s)",
metadata.getPropertyEnum(), property.getAllCapsName());
code.add(PreconditionExcerpts.checkState(propertyIsSet, property.getName() + " not set"));
}
code.addLine(" return %s;", property.getName())
.addLine("}");
}
@Override
public void addValueFieldDeclaration(SourceBuilder code, String finalField) {
code.add("private final %s %s;\n", property.getType(), finalField);
}
@Override
public void addFinalFieldAssignment(SourceBuilder code, String finalField, String builder) {
code.addLine("%s = %s.%s;", finalField, builder, property.getName());
}
@Override
public void addMergeFromValue(Block code, String value) {
Excerpt defaults = Declarations.freshBuilder(code, metadata).orNull();
if (defaults != null) {
code.add("if (");
if (!hasDefault) {
code.add("%s._unsetProperties.contains(%s.%s) || ",
defaults, metadata.getPropertyEnum(), property.getAllCapsName());
}
if (isPrimitive) {
code.add("%s.%s() != %s.%s()",
value, property.getGetterName(), defaults, getter(property));
} else {
code.add("!%s.%s().equals(%s.%s())",
value, property.getGetterName(), defaults, getter(property));
}
code.add(") {%n");
}
code.addLine(" %s(%s.%s());", setter(property), value, property.getGetterName());
if (defaults != null) {
code.addLine("}");
}
}
@Override
public void addMergeFromSuperValue(Block code, String value) {
addMergeFromValue(code, value);
}
@Override
public void addMergeFromBuilder(Block code, String builder) {
addMergeFromBuilder(code, builder, false);
}
@Override
public void addMergeFromSuperBuilder(Block code, String builder) {
addMergeFromBuilder(code, builder, true);
}
public void addMergeFromBuilder(Block code, String builder, boolean fromSuper) {
Excerpt base = hasDefault || fromSuper ? null : Declarations.upcastToGeneratedBuilder(
code, metadata, builder);
Excerpt defaults = Declarations.freshBuilder(code, metadata).orNull();
Block unsetContains = new Block(code);
String isPropertySetPositive = fromSuper ? "" : "!";
String isPropertySetNegative = fromSuper ? "!" : "";
if (fromSuper) {
unsetContains.add("%s()", isPropertySetMethod(property));
base = new Block(code).add(builder);
} else {
unsetContains.add("_unsetProperties.contains(%s.%s)",
metadata.getPropertyEnum(), property.getAllCapsName());
}
if (defaults != null) {
code.add("if (");
if (!hasDefault) {
code.add("%s%s.%s && ",
isPropertySetPositive, base, unsetContains)
.add("(%s%s.%s ||",
isPropertySetNegative, defaults, unsetContains);
}
if (isPrimitive) {
code.add("%1$s.%2$s() != %3$s.%2$s()", builder, getter(property), defaults);
} else {
code.add("!%1$s.%2$s().equals(%3$s.%2$s())", builder, getter(property), defaults);
}
if (!hasDefault) {
code.add(")");
}
code.add(") {%n");
} else if (!hasDefault) {
code.addLine("if (%s%s.%s) {",
isPropertySetPositive, base, unsetContains);
}
code.addLine(" %s(%s.%s());", setter(property), builder, getter(property));
if (defaults != null || !hasDefault) {
code.addLine("}");
}
}
@Override
public void addSetFromResult(SourceBuilder code, String builder, String variable) {
code.addLine("%s.%s(%s);", builder, setter(property), variable);
}
@Override
public void addClearField(Block code) {
Optional defaults = Declarations.freshBuilder(code, metadata);
// Cannot clear property without defaults
if (defaults.isPresent()) {
code.addLine("%1$s = %2$s.%1$s;", property.getName(), defaults.get());
}
}
}
}