/* * Copyright (c) 2011 Google Inc. * * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse * Public License v1.0 which accompanies this distribution, and is available at * * http://www.eclipse.org/legal/epl-v10.html */ package com.google.eclipse.protobuf.model.util; import static com.google.eclipse.protobuf.grammar.CommonKeyword.BOOL; import static com.google.eclipse.protobuf.grammar.CommonKeyword.BYTES; import static com.google.eclipse.protobuf.grammar.CommonKeyword.DOUBLE; import static com.google.eclipse.protobuf.grammar.CommonKeyword.FIXED32; import static com.google.eclipse.protobuf.grammar.CommonKeyword.FIXED64; import static com.google.eclipse.protobuf.grammar.CommonKeyword.FLOAT; import static com.google.eclipse.protobuf.grammar.CommonKeyword.INT32; import static com.google.eclipse.protobuf.grammar.CommonKeyword.INT64; import static com.google.eclipse.protobuf.grammar.CommonKeyword.SFIXED32; import static com.google.eclipse.protobuf.grammar.CommonKeyword.SFIXED64; import static com.google.eclipse.protobuf.grammar.CommonKeyword.SINT32; import static com.google.eclipse.protobuf.grammar.CommonKeyword.SINT64; import static com.google.eclipse.protobuf.grammar.CommonKeyword.STRING; import static com.google.eclipse.protobuf.grammar.CommonKeyword.UINT32; import static com.google.eclipse.protobuf.grammar.CommonKeyword.UINT64; import static com.google.eclipse.protobuf.protobuf.ModifierEnum.OPTIONAL; import com.google.eclipse.protobuf.grammar.CommonKeyword; import com.google.eclipse.protobuf.protobuf.ComplexType; import com.google.eclipse.protobuf.protobuf.ComplexTypeLink; import com.google.eclipse.protobuf.protobuf.Enum; import com.google.eclipse.protobuf.protobuf.MapType; import com.google.eclipse.protobuf.protobuf.MapTypeLink; import com.google.eclipse.protobuf.protobuf.Message; import com.google.eclipse.protobuf.protobuf.MessageField; import com.google.eclipse.protobuf.protobuf.ModifierEnum; import com.google.eclipse.protobuf.protobuf.ScalarType; import com.google.eclipse.protobuf.protobuf.ScalarTypeLink; import com.google.eclipse.protobuf.protobuf.TypeLink; import com.google.inject.Singleton; /** * Utility methods related to <code>{@link MessageField}</code>s. * * @author alruiz@google.com (Alex Ruiz) */ @Singleton public class MessageFields { /** * Indicates whether the modifier of the given field is <code>{@link * ModifierEnum#OPTIONAL}</code>. * * @param field the given field. * @return {@code true} if the modifier of the given field is "optional," {@code false} otherwise. */ public boolean isOptional(MessageField field) { return OPTIONAL.equals(field.getModifier()); } /** * Indicates whether the type of the given field is primitive. Primitive types include: {@code * double}, {@code float}, {@code int32}, {@code int64}, {@code uint32}, {@code uint64}, {@code * sint32}, {@code sint64}, {@code fixed32}, {@code fixed64}, {@code sfixed32}, {@code sfixed64} * and {@code bool}. * * @param field the given field. * @return {@code true} if the type of the given field is primitive, {@code false} otherwise. */ public boolean isPrimitive(MessageField field) { TypeLink link = field.getType(); if (!(link instanceof ScalarTypeLink)) { return false; } String typeName = ((ScalarTypeLink) link).getTarget().getName(); return !STRING.hasValue(typeName) && !BYTES.hasValue(typeName); } /** * Indicates whether the given field is of type {@code bool}. * * @param field the given field. * @return {@code true} if the given field is of type {@code bool}, {@code false} otherwise. */ public boolean isBool(MessageField field) { return isScalarType(field, BOOL); } /** * Indicates whether the given field is of type {@code bytes}. * * @param field the given field. * @return {@code true} if the given field is of type {@code bytes}, {@code false} otherwise. */ public boolean isBytes(MessageField field) { return isScalarType(field, BYTES); } /** * Indicates whether the given field is of type {@code float} or {@code double}. * * @param field the given field. * @return {@code true} if the given field is a floating point number, {@code false} otherwise. */ public boolean isFloatingPointNumber(MessageField field) { return isScalarType(field, FLOAT, DOUBLE); } /** * Indicates whether the given field is of type {@code fixed32}, {@code fixed64}, {@code int32}, * {@code int64}, {@code sfixed32}, {@code sfixed64}, {@code sint32}, {@code sint64}, {@code * uint32} or {@code uint64}. * * @param field the given field. * @return {@code true} if the given field is an integer, {@code false} otherwise. */ public boolean isInteger(MessageField field) { return isScalarType( field, FIXED32, FIXED64, INT32, INT64, SFIXED32, SFIXED64, SINT32, SINT64, UINT32, UINT64); } /** * Indicates whether the given field is of type {@code string}. * * @param field the given field. * @return {@code true} if the given field is of type {@code string}, {@code false} otherwise. */ public boolean isString(MessageField field) { return isScalarType(field, STRING); } /** * Indicates whether the given field is of type {@code fixed32}, {@code fixed64}, {@code uint32} * or {@code uint64}. * * @param field the given field. * @return {@code true} if the given field is an unsigned integer, {@code false} otherwise. */ public boolean isUnsignedInteger(MessageField field) { return isScalarType(field, FIXED32, FIXED64, UINT32, UINT64); } private boolean isScalarType(MessageField field, CommonKeyword... scalarNames) { TypeLink link = field.getType(); if (link instanceof ScalarTypeLink) { String typeName = ((ScalarTypeLink) link).getTarget().getName(); for (CommonKeyword scalarName : scalarNames) { if (scalarName.hasValue(typeName)) { return true; } } } return false; } /** * Returns the name of the type of the given field. * * @param field the given field. * @return the name of the type of the given field. */ public String typeNameOf(MessageField field) { return typeNameOf(field.getType()); } private String typeNameOf(TypeLink typeLink) { ScalarType scalarType = scalarTypeOf(typeLink); if (scalarType != null) { return scalarType.getName(); } MapType mapType = mapTypeOf(typeLink); if (mapType != null) { return String.format( "map<%s, %s>", typeNameOf(mapType.getKeyType()), typeNameOf(mapType.getValueType())); } ComplexType complexType = complexTypeOf(typeLink); if (complexType != null) { return complexType.getName(); } return null; } /** * Returns the message type of the given field, only if the type of the given field is a message. * * @param field the given field. * @return the message type of the given field or {@code null} if the type of the given field is * not message. */ public Message messageTypeOf(MessageField field) { ComplexType fieldType = complexTypeOf(field.getType()); return fieldType instanceof Message ? (Message) fieldType : null; } /** * Returns the enum type of the given field, only if the type of the given field is an enum. * * @param field the given field. * @return the enum type of the given field or {@code null} if the type of the given field is not * enum. */ public Enum enumTypeOf(MessageField field) { ComplexType fieldType = complexTypeOf(field.getType()); return fieldType instanceof Enum ? (Enum) fieldType : null; } private ComplexType complexTypeOf(TypeLink link) { return link instanceof ComplexTypeLink ? ((ComplexTypeLink) link).getTarget() : null; } /** * Returns the scalar type of the given field, only if the type of the given field is a scalar. * * @param field the given field. * @return the scalar type of the given field or {@code null} if the type of the given field is * not a scalar. */ public ScalarType scalarTypeOf(MessageField field) { return scalarTypeOf(field.getType()); } private ScalarType scalarTypeOf(TypeLink link) { return link instanceof ScalarTypeLink ? ((ScalarTypeLink) link).getTarget() : null; } private MapType mapTypeOf(TypeLink typeLink) { return typeLink instanceof MapTypeLink ? ((MapTypeLink) typeLink).getTarget() : null; } }