blob: 1107a3dd37534251eec77d0f891f95483f57aaba [file] [log] [blame]
/*
* 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.eclipse.protobuf.scoping.ProtoDescriptorProvider;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* Utility methods related to <code>{@link MessageField}</code>s.
*
* @author alruiz@google.com (Alex Ruiz)
*/
@Singleton public class MessageFields {
@Inject private ProtoDescriptorProvider descriptorProvider;
/**
* 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;
}
/**
* Returns a Message representing an entry in a map of the given field's type, or null if the
* given field is not of map type.
*/
public Message mapEntryTypeOf(MessageField field) {
// TODO(jogl): Dynamically create and return a message type with key and value fields matching
// the key and value types of the target MapType.
return field.getType() instanceof MapTypeLink
? (Message) descriptorProvider.mapEntryDescriptor().allTypes().get(0) : null;
}
}