Java tutorial
/* * Thrifty * * Copyright (c) Microsoft Corporation * * 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 * * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING * WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, * FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. * * See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ package com.microsoft.thrifty.schema; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.microsoft.thrifty.schema.parser.AnnotationElement; import com.microsoft.thrifty.schema.parser.EnumElement; import com.microsoft.thrifty.schema.parser.EnumMemberElement; import com.microsoft.thrifty.schema.parser.FieldElement; import com.microsoft.thrifty.schema.parser.FunctionElement; import com.microsoft.thrifty.schema.parser.ServiceElement; import com.microsoft.thrifty.schema.parser.StructElement; import com.microsoft.thrifty.schema.parser.TypedefElement; import java.util.Locale; import java.util.Map; import javax.annotation.Nullable; /** * A mixin encapsulating a common implementation of {@link UserElement}, * which does not conveniently fit in a single base class. */ class UserElementMixin implements UserElement { private final String name; private final Location location; private final String documentation; private final ImmutableMap<String, String> annotations; UserElementMixin(StructElement struct) { this(struct.name(), struct.location(), struct.documentation(), struct.annotations()); } UserElementMixin(FieldElement field) { this(field.name(), field.location(), field.documentation(), field.annotations()); } UserElementMixin(EnumElement enumElement) { this(enumElement.name(), enumElement.location(), enumElement.documentation(), enumElement.annotations()); } UserElementMixin(EnumMemberElement member) { this(member.name(), member.location(), member.documentation(), member.annotations()); } UserElementMixin(TypedefElement element) { this(element.newName(), element.location(), element.documentation(), element.annotations()); } UserElementMixin(ServiceElement element) { this(element.name(), element.location(), element.documentation(), element.annotations()); } UserElementMixin(FunctionElement element) { this(element.name(), element.location(), element.documentation(), element.annotations()); } UserElementMixin(String name, Location location, String documentation, @Nullable AnnotationElement annotationElement) { this.name = name; this.location = location; this.documentation = documentation; ImmutableMap.Builder<String, String> annotations = ImmutableMap.builder(); if (annotationElement != null) { annotations.putAll(annotationElement.values()); } this.annotations = annotations.build(); } private UserElementMixin(Builder builder) { this.name = builder.name; this.location = builder.location; this.documentation = builder.documentation; this.annotations = builder.annotations; } @Override public Location location() { return location; } @Override public String name() { return name; } @Override public String documentation() { return documentation; } @Override public ImmutableMap<String, String> annotations() { return annotations; } @Override public boolean isDeprecated() { return hasThriftOrJavadocAnnotation("deprecated"); } /** * Checks for the presence of the given annotation name, in several possible * varieties. Returns true if: * * <ul> * <li>A Thrift annotation matching the exact name is present</li> * <li>A Thrift annotation equal to the string "thrifty." plus the name is present</li> * <li>The Javadoc contains "@" plus the annotation name</li> * </ul> * * The latter two conditions are officially undocumented, but are present for * legacy use. This behavior is subject to change without notice! */ boolean hasThriftOrJavadocAnnotation(String name) { return annotations().containsKey(name) || annotations().containsKey("thrifty." + name) || (hasJavadoc() && documentation().toLowerCase(Locale.US).contains("@" + name)); } @Override public String toString() { return "UserElementMixin{" + "name='" + name + '\'' + ", location=" + location + ", documentation='" + documentation + '\'' + ", annotations=" + annotations + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UserElementMixin that = (UserElementMixin) o; if (!name.equals(that.name)) return false; if (!location.equals(that.location)) return false; if (!documentation.equals(that.documentation)) return false; return annotations.equals(that.annotations); } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + location.hashCode(); result = 31 * result + documentation.hashCode(); result = 31 * result + annotations.hashCode(); return result; } Builder toBuilder() { return new Builder(this); } static class Builder { private String name; private Location location; private String documentation; private ImmutableMap<String, String> annotations; private Builder(UserElement userElement) { this.name = userElement.name(); this.location = userElement.location(); this.documentation = userElement.documentation(); this.annotations = userElement.annotations(); } Builder name(String name) { this.name = Preconditions.checkNotNull(name, "name"); return this; } Builder location(Location location) { this.location = Preconditions.checkNotNull(location, "name"); return this; } Builder documentation(String documentation) { if (UserElement.isNonEmptyJavadoc(documentation)) { this.documentation = documentation; } else { this.documentation = ""; } return this; } Builder annotations(Map<String, String> annotations) { this.annotations = ImmutableMap.copyOf(Preconditions.checkNotNull(annotations)); return this; } UserElementMixin build() { return new UserElementMixin(this); } } }