{-# LANGUAGE QuasiQuotes, OverloadedStrings, RecordWildCards #-}
module Language.Bond.Codegen.Java.Class_java
( class_java
, JavaFieldMapping(..)
) where
import Prelude
import Data.Text.Lazy (Text)
import Text.Shakespeare.Text
import Language.Bond.Syntax.Types
import Language.Bond.Syntax.Util
import Language.Bond.Util
import Language.Bond.Codegen.TypeMapping
import Language.Bond.Codegen.Util
import Language.Bond.Codegen.Java.Util
data JavaFieldMapping = JavaPublicFields deriving Eq
structFieldDescriptorTypeName :: MappingContext -> Type -> Text
structFieldDescriptorTypeName java = typeName
where
typeName (BT_Maybe BT_Int8) = [lt|org.bondlib.StructBondType.SomethingInt8StructField|]
typeName BT_Int8 = [lt|org.bondlib.StructBondType.Int8StructField|]
typeName (BT_Maybe BT_Int16) = [lt|org.bondlib.StructBondType.SomethingInt16StructField|]
typeName BT_Int16 = [lt|org.bondlib.StructBondType.Int16StructField|]
typeName (BT_Maybe BT_Int32) = [lt|org.bondlib.StructBondType.SomethingInt32StructField|]
typeName BT_Int32 = [lt|org.bondlib.StructBondType.Int32StructField|]
typeName (BT_Maybe BT_Int64) = [lt|org.bondlib.StructBondType.SomethingInt64StructField|]
typeName BT_Int64 = [lt|org.bondlib.StructBondType.Int64StructField|]
typeName (BT_Maybe BT_UInt8) = [lt|org.bondlib.StructBondType.SomethingUInt8StructField|]
typeName BT_UInt8 = [lt|org.bondlib.StructBondType.UInt8StructField|]
typeName (BT_Maybe BT_UInt16) = [lt|org.bondlib.StructBondType.SomethingUInt16StructField|]
typeName BT_UInt16 = [lt|org.bondlib.StructBondType.UInt16StructField|]
typeName (BT_Maybe BT_UInt32) = [lt|org.bondlib.StructBondType.SomethingUInt32StructField|]
typeName BT_UInt32 = [lt|org.bondlib.StructBondType.UInt32StructField|]
typeName (BT_Maybe BT_UInt64) = [lt|org.bondlib.StructBondType.SomethingUInt64StructField|]
typeName BT_UInt64 = [lt|org.bondlib.StructBondType.UInt64StructField|]
typeName (BT_Maybe BT_Float) = [lt|org.bondlib.StructBondType.SomethingFloatStructField|]
typeName BT_Float = [lt|org.bondlib.StructBondType.FloatStructField|]
typeName (BT_Maybe BT_Double) = [lt|org.bondlib.StructBondType.SomethingDoubleStructField|]
typeName BT_Double = [lt|org.bondlib.StructBondType.DoubleStructField|]
typeName (BT_Maybe BT_Bool) = [lt|org.bondlib.StructBondType.SomethingBoolStructField|]
typeName BT_Bool = [lt|org.bondlib.StructBondType.BoolStructField|]
typeName (BT_Maybe BT_String) = [lt|org.bondlib.StructBondType.SomethingStringStructField|]
typeName BT_String = [lt|org.bondlib.StructBondType.StringStructField|]
typeName (BT_Maybe BT_WString) = [lt|org.bondlib.StructBondType.SomethingWStringStructField|]
typeName BT_WString = [lt|org.bondlib.StructBondType.WStringStructField|]
typeName (BT_Maybe BT_MetaName) = [lt|org.bondlib.StructBondType.SomethingStringStructField|]
typeName BT_MetaName = [lt|org.bondlib.StructBondType.StringStructField|]
typeName (BT_Maybe BT_MetaFullName) = [lt|org.bondlib.StructBondType.SomethingStringStructField|]
typeName BT_MetaFullName = [lt|org.bondlib.StructBondType.StringStructField|]
typeName (BT_Maybe (BT_UserDefined e@Enum {} _)) = [lt|org.bondlib.StructBondType.SomethingEnumStructField<#{qualifiedDeclaredTypeName java e}>|]
typeName (BT_UserDefined e@Enum {} _) = [lt|org.bondlib.StructBondType.EnumStructField<#{qualifiedDeclaredTypeName java e}>|]
typeName (BT_Maybe (BT_UserDefined a@Alias {} args)) = structFieldDescriptorTypeName java (BT_Maybe (resolveAlias a args))
typeName (BT_UserDefined a@Alias {} args) = structFieldDescriptorTypeName java (resolveAlias a args)
typeName (BT_Maybe t) = [lt|org.bondlib.StructBondType.SomethingObjectStructField<#{getElementTypeName java t}>|]
typeName t = [lt|org.bondlib.StructBondType.ObjectStructField<#{getElementTypeName java t}>|]
isGenericStructFieldDescriptor :: Type -> Bool
isGenericStructFieldDescriptor (BT_Maybe t) = not (isPrimitiveNonEnumBondType t)
isGenericStructFieldDescriptor t = not (isPrimitiveNonEnumBondType t)
typeParamVarName :: TypeParam -> Text
typeParamVarName TypeParam {..} = [lt|#{paramName}|]
typeParamVarDecl :: TypeParam -> Text
typeParamVarDecl t@TypeParam {..} = [lt|org.bondlib.BondType<#{paramName}> #{typeParamVarName t}|]
typeParamNameList :: [TypeParam] -> Text
typeParamNameList declParams = [lt|#{sepBy ", " paramName declParams}|]
typeParamVarNameList :: [TypeParam] -> Text
typeParamVarNameList declParams = [lt|#{sepBy ", " typeParamVarName declParams}|]
typeParamVarDeclList :: [TypeParam] -> Text
typeParamVarDeclList declParams = [lt|#{sepBy ", " typeParamVarDecl declParams}|]
typeParamAnglesNameList :: [TypeParam] -> Text
typeParamAnglesNameList declParams = [lt|#{angles $ typeParamNameList declParams}|]
typeNameWithParams :: String -> [TypeParam] -> Text
typeNameWithParams declName declParams = [lt|#{declName}#{typeParamAnglesNameList declParams}|]
typeDescriptorNameWithParams :: String -> [TypeParam] -> Text
typeDescriptorNameWithParams declName declParams = [lt|org.bondlib.StructBondType<#{typeNameWithParams declName declParams}>|]
typeDescriptorName :: String -> Text
typeDescriptorName declName = [lt|org.bondlib.StructBondType<#{declName}>|]
ensureNotNullArgument :: Text -> Text
ensureNotNullArgument argName = [lt|org.bondlib.ArgumentHelper.ensureNotNull(#{argName}, "#{argName}")|]
fieldDefaultValueInitParamExpr :: MappingContext -> Type -> Maybe Default -> Text
fieldDefaultValueInitParamExpr _ _ (Just (DefaultBool val)) = if val
then [lt|, true|]
else [lt|, false|]
fieldDefaultValueInitParamExpr _ BT_Int8 (Just (DefaultInteger val)) = [lt|, (byte)#{val}|]
fieldDefaultValueInitParamExpr _ BT_Int16 (Just (DefaultInteger val)) = [lt|, (short)#{val}|]
fieldDefaultValueInitParamExpr _ BT_Int32 (Just (DefaultInteger val)) = [lt|, #{val}|]
fieldDefaultValueInitParamExpr _ BT_Int64 (Just (DefaultInteger val)) = [lt|, #{val}L|]
fieldDefaultValueInitParamExpr _ BT_UInt8 (Just (DefaultInteger val)) = [lt|, (byte)#{twosComplement 8 val}|]
fieldDefaultValueInitParamExpr _ BT_UInt16 (Just (DefaultInteger val)) = [lt|, (short)#{twosComplement 16 val}|]
fieldDefaultValueInitParamExpr _ BT_UInt32 (Just (DefaultInteger val)) = [lt|, #{twosComplement 32 val}|]
fieldDefaultValueInitParamExpr _ BT_UInt64 (Just (DefaultInteger val)) = [lt|, #{twosComplement 64 val}L|]
fieldDefaultValueInitParamExpr _ BT_Float (Just (DefaultFloat val)) = [lt|, #{val}F|]
fieldDefaultValueInitParamExpr _ BT_Float (Just (DefaultInteger val)) = [lt|, #{val}F|]
fieldDefaultValueInitParamExpr _ BT_Double (Just (DefaultFloat val)) = [lt|, #{val}D|]
fieldDefaultValueInitParamExpr _ BT_Double (Just (DefaultInteger val)) = [lt|, #{val}D|]
fieldDefaultValueInitParamExpr _ BT_String (Just (DefaultString val)) = [lt|, "#{val}"|]
fieldDefaultValueInitParamExpr _ BT_WString (Just (DefaultString val)) = [lt|, "#{val}"|]
fieldDefaultValueInitParamExpr java (BT_UserDefined e@Enum {..} _) (Just (DefaultEnum val)) = [lt|, #{qualifiedDeclaredTypeName java e}.#{val}|]
fieldDefaultValueInitParamExpr _ _ _ = mempty
structFieldDescriptorInitStructExpr :: MappingContext -> Type -> String -> [Type] -> Text
structFieldDescriptorInitStructExpr java fieldType typeName params = [lt|#{typeCastExpr} getStructType(#{typeName}.class#{paramExprList params})|]
where
typeCastExpr = [lt|(org.bondlib.StructBondType<#{(getTypeName java) fieldType}>)|]
paramExprList :: [Type] -> Text
paramExprList [] = mempty
paramExprList (x:xs) = [lt|, #{structFieldDescriptorInitTypeExpr java x}#{paramExprList xs}|]
structFieldDescriptorInitTypeExpr :: MappingContext -> Type -> Text
structFieldDescriptorInitTypeExpr java (BT_Maybe t) = structFieldDescriptorInitTypeExpr java t
structFieldDescriptorInitTypeExpr _ BT_Int8 = [lt|org.bondlib.BondTypes.INT8|]
structFieldDescriptorInitTypeExpr _ BT_Int16 = [lt|org.bondlib.BondTypes.INT16|]
structFieldDescriptorInitTypeExpr _ BT_Int32 = [lt|org.bondlib.BondTypes.INT32|]
structFieldDescriptorInitTypeExpr _ BT_Int64 = [lt|org.bondlib.BondTypes.INT64|]
structFieldDescriptorInitTypeExpr _ BT_UInt8 = [lt|org.bondlib.BondTypes.UINT8|]
structFieldDescriptorInitTypeExpr _ BT_UInt16 = [lt|org.bondlib.BondTypes.UINT16|]
structFieldDescriptorInitTypeExpr _ BT_UInt32 = [lt|org.bondlib.BondTypes.UINT32|]
structFieldDescriptorInitTypeExpr _ BT_UInt64 = [lt|org.bondlib.BondTypes.UINT64|]
structFieldDescriptorInitTypeExpr _ BT_Float = [lt|org.bondlib.BondTypes.FLOAT|]
structFieldDescriptorInitTypeExpr _ BT_Double = [lt|org.bondlib.BondTypes.DOUBLE|]
structFieldDescriptorInitTypeExpr _ BT_Bool = [lt|org.bondlib.BondTypes.BOOL|]
structFieldDescriptorInitTypeExpr _ BT_String = [lt|org.bondlib.BondTypes.STRING|]
structFieldDescriptorInitTypeExpr _ BT_WString = [lt|org.bondlib.BondTypes.WSTRING|]
structFieldDescriptorInitTypeExpr _ BT_Blob = [lt|org.bondlib.BondTypes.BLOB|]
structFieldDescriptorInitTypeExpr java (BT_Bonded t) = [lt|bondedOf(#{structFieldDescriptorInitTypeExpr java t})|]
structFieldDescriptorInitTypeExpr java (BT_Nullable t) = [lt|nullableOf(#{structFieldDescriptorInitTypeExpr java t})|]
structFieldDescriptorInitTypeExpr java (BT_Vector t) = [lt|vectorOf(#{structFieldDescriptorInitTypeExpr java t})|]
structFieldDescriptorInitTypeExpr java (BT_List t) = [lt|listOf(#{structFieldDescriptorInitTypeExpr java t})|]
structFieldDescriptorInitTypeExpr java (BT_Set t) = [lt|setOf(#{structFieldDescriptorInitTypeExpr java t})|]
structFieldDescriptorInitTypeExpr java (BT_Map k v) = [lt|mapOf(#{structFieldDescriptorInitTypeExpr java k}, #{structFieldDescriptorInitTypeExpr java v})|]
structFieldDescriptorInitTypeExpr _ (BT_TypeParam param) = [lt|#{paramName param}|]
structFieldDescriptorInitTypeExpr java (BT_UserDefined e@Enum {} _) = [lt|#{qualifiedDeclaredTypeName java e}.BOND_TYPE|]
structFieldDescriptorInitTypeExpr java t@(BT_UserDefined s@Struct {} params) = [lt|#{structFieldDescriptorInitStructExpr java t (qualifiedDeclaredTypeName java s) params}|]
structFieldDescriptorInitTypeExpr java t@(BT_UserDefined s@Forward {} params) = [lt|#{structFieldDescriptorInitStructExpr java t (qualifiedDeclaredTypeName java s) params}|]
structFieldDescriptorInitTypeExpr java (BT_UserDefined a@Alias {} params) = structFieldDescriptorInitTypeExpr java (resolveAlias a params)
structFieldDescriptorInitTypeExpr _ t = error $ "invalid declaration type for structFieldDescriptorInitTypeExpr: " ++ show t
structBaseDescriptorInitStructExpr :: MappingContext -> Maybe Type -> Text
structBaseDescriptorInitStructExpr java t = maybe [lt|null|] (structFieldDescriptorInitTypeExpr java) t
makeStructMember_GenericBondTypeBuilder :: String -> [TypeParam] -> Text
makeStructMember_GenericBondTypeBuilder declName declParams = [lt|
public static abstract class GenericBondTypeBuilder {
private GenericBondTypeBuilder() {
}
public abstract #{typeParamAnglesNameList declParams} #{typeDescriptorNameWithParams declName declParams} makeGenericType(#{typeParamVarDeclList declParams});
}
|]
makeStructBuilderMember_makeGenericType :: String -> [TypeParam] -> Text
makeStructBuilderMember_makeGenericType declName declParams = [lt|
private #{typeParamAnglesNameList declParams} #{typeDescriptorNameWithParams declName declParams} makeGenericType(#{typeParamVarDeclList declParams}) {
#{newlineSepEnd 4 checkArg declParams}return #{castExpr} this.getInitializedFromCache(#{typeParamVarNameList declParams});
}
|]
where
checkArg t@TypeParam {..} = [lt|#{ensureNotNullArgument (typeParamVarName t)};|]
castExpr = [lt|(StructBondTypeImpl)|]
makeStructBondTypeMember_StructBondTypeBuilderImpl :: String -> [TypeParam] -> Text
makeStructBondTypeMember_StructBondTypeBuilderImpl declName declParams = [lt|
static final class StructBondTypeBuilderImpl extends org.bondlib.StructBondType.StructBondTypeBuilder<#{declName}> {
#{ifThenElse (null declParams) mempty (makeStructBuilderMember_makeGenericType declName declParams)}
@Override
public final int getGenericTypeParameterCount() {
return #{length declParams};
}
@Override
protected final #{typeDescriptorName declName} buildNewInstance(org.bondlib.BondType[] genericTypeArguments) {
return new StructBondTypeImpl(#{ifThenElse (null declParams) nullText "new org.bondlib.GenericTypeSpecialization(genericTypeArguments)"});
}
static void register() {
registerStructType(#{declName}.class, new StructBondTypeBuilderImpl());
}
}|]
where
nullText = "null" :: Text
makeStructBondTypeMember_initialize :: MappingContext -> [TypeParam] -> [Field] -> Maybe Type -> Text
makeStructBondTypeMember_initialize java declParams structFields structBase = [lt|
@Override
protected final void initialize() {#{typeArgVarDeclList}#{fieldDescriptorInitList}
super.initializeBaseAndFields(#{baseTypeDescriptorParam}#{fieldTypeDescriptorParamsSeparator}#{fieldTypeDescriptorParams});
}|]
where
typeArgVarDeclList = newlineBeginSep 3 typeArgVarDecl indexedDeclParams
typeArgVarDecl (index, typeParam) = [lt|#{typeParamVarDecl typeParam} = this.getGenericSpecialization().getGenericTypeArgument(#{index});|]
indexedDeclParams = zip [0 :: Int ..] declParams
fieldDescriptorInitList = newlineBeginSep 3 fieldDescriptorInit structFields
fieldDescriptorInit Field {..} = [lt|this.#{fieldName} = new #{structFieldDescriptorTypeName java fieldType}(#{constructorParams});|]
where
constructorParams = [lt|this#{fieldTypeParam}, #{fieldOrdinal}, "#{fieldName}", #{modifierConstantName fieldModifier}#{fieldDefaultValueParam}|]
fieldTypeParam = if isGenericStructFieldDescriptor fieldType
then [lt|, #{structFieldDescriptorInitTypeExpr java fieldType}|]
else mempty
fieldDefaultValueParam = fieldDefaultValueInitParamExpr java fieldType fieldDefault
baseTypeDescriptorParam = structBaseDescriptorInitStructExpr java structBase
fieldTypeDescriptorParamsSeparator = ifThenElse (null structFields) mempty [lt|, |]
fieldTypeDescriptorParams = sepBy ", " structFieldReference structFields
structFieldReference Field {..} = [lt|this.#{fieldName}|]
makeStructBondTypeMember_serializeStructFields :: String -> [TypeParam] -> [Field] -> Text
makeStructBondTypeMember_serializeStructFields declName declParams structFields = [lt|
@Override
protected final void serializeStructFields(#{methodParamDecl}) throws java.io.IOException {#{newlineBeginSep 3 serializeField structFields}
}|]
where
methodParamDecl = [lt|org.bondlib.BondType.SerializationContext context, #{typeNameWithParams declName declParams} value|]
serializeField Field {..} = [lt|this.#{fieldName}.serialize(context, value.#{fieldName});|]
makeStructBondTypeMember_deserializeStructFields_tagged :: String -> [TypeParam] -> [Field] -> Text
makeStructBondTypeMember_deserializeStructFields_tagged declName declParams structFields = [lt|
@Override
protected final void deserializeStructFields(#{methodParamDecl}) throws java.io.IOException {#{newlineBeginSep 3 declareLocalVariable structFields}
while (this.readField(context)) {
switch (context.readFieldResult.id) {#{newlineBeginSep 5 deserializeField structFields}
default:
context.reader.skip(context.readFieldResult.type);
break;
}
}#{newlineBeginSep 3 verifyField structFields}
}|]
where
methodParamDecl = [lt|org.bondlib.BondType.TaggedDeserializationContext context, #{typeNameWithParams declName declParams} value|]
declareLocalVariable Field {..} = [lt|boolean __has_#{fieldName} = false;|]
deserializeField Field {..} = [lt|#{switchCasePart}#{newLine 6}#{deserializePart}#{newLine 6}#{setBooleanPart}#{newLine 6}break;|]
where
switchCasePart = [lt|case #{fieldOrdinal}:|]
deserializePart = [lt|value.#{fieldName} = this.#{fieldName}.deserialize(context, __has_#{fieldName});|]
setBooleanPart = [lt|__has_#{fieldName} = true;|]
verifyField Field {..} = [lt|this.#{fieldName}.verifyDeserialized(__has_#{fieldName});|]
makeStructBondTypeMember_deserializeStructFields_untagged :: String -> [TypeParam] -> [Field] -> Text
makeStructBondTypeMember_deserializeStructFields_untagged declName declParams structFields = [lt|
@Override
protected final void deserializeStructFields(#{methodParamDecl}) throws java.io.IOException {#{newlineBeginSep 3 declareLocalVariable structFields}
for (final org.bondlib.FieldDef field : structDef.fields) {
switch (field.id) {#{newlineBeginSep 5 deserializeField structFields}
default:
context.reader.skip(context.schema, field.type);
break;
}
}#{newlineBeginSep 3 verifyField structFields}
}|]
where
methodParamDecl = [lt|org.bondlib.BondType.UntaggedDeserializationContext context, org.bondlib.StructDef structDef, #{typeNameWithParams declName declParams} value|]
declareLocalVariable Field {..} = [lt|boolean __has_#{fieldName} = false;|]
deserializeField Field {..} = [lt|#{switchCasePart}#{newLine 6}#{deserializePart}#{newLine 6}#{setBooleanPart}#{newLine 6}break;|]
where
switchCasePart = [lt|case #{fieldOrdinal}:|]
deserializePart = [lt|value.#{fieldName} = this.#{fieldName}.deserialize(context, field.type);|]
setBooleanPart = [lt|__has_#{fieldName} = true;|]
verifyField Field {..} = [lt|this.#{fieldName}.verifyDeserialized(__has_#{fieldName});|]
makeStructBondTypeMember_initializeStructFields :: String -> [TypeParam] -> [Field] -> Text
makeStructBondTypeMember_initializeStructFields declName declParams structFields = [lt|
@Override
protected final void initializeStructFields(#{methodParamDecl}) {#{newlineBeginSep 3 initializeField structFields}
}|]
where
methodParamDecl = [lt|#{typeNameWithParams declName declParams} value|]
initializeField Field {..} = [lt|value.#{fieldName} = this.#{fieldName}.initialize();|]
makeStructBondTypeMember_cloneStructFields :: String -> [TypeParam] -> [Field] -> Text
makeStructBondTypeMember_cloneStructFields declName declParams structFields = [lt|
@Override
protected final void cloneStructFields(#{methodParamDecl}) {#{newlineBeginSep 3 cloneField structFields}
}|]
where
methodParamDecl = [lt|#{typeNameWithParams declName declParams} fromValue, #{typeNameWithParams declName declParams} toValue|]
cloneField Field {..} = [lt|toValue.#{fieldName} = this.#{fieldName}.clone(fromValue.#{fieldName});|]
bondTypeStaticVariableDeclAsGenericBondTypeBuilder :: String -> [TypeParam] -> Text
bondTypeStaticVariableDeclAsGenericBondTypeBuilder declName declParams = [lt|public static final GenericBondTypeBuilder BOND_TYPE = new GenericBondTypeBuilder() {
final StructBondTypeImpl.StructBondTypeBuilderImpl builder = new StructBondTypeImpl.StructBondTypeBuilderImpl();
@Override
public final <#{paramList}> org.bondlib.StructBondType<#{declName}<#{paramList}>> makeGenericType(#{sepBy ", " methodArg declParams}) {
return this.builder.makeGenericType(#{paramList});
}
};|]
where
paramList = sepBy ", " paramName declParams
methodArg TypeParam {..} = [lt|org.bondlib.BondType<#{paramName}> #{paramName}|]
publicConstructorDeclForNonGenericStruct :: MappingContext -> String -> Maybe Type -> Text
publicConstructorDeclForNonGenericStruct java declName maybeBase = [lt|
public #{declName}() {
super(#{superConstructorArgs maybeBase});
((StructBondTypeImpl)BOND_TYPE).initializeStructFields(this);
};
|]
where
superConstructorArgs Nothing = mempty
superConstructorArgs (Just t) = if isGenericBondStructType t
then [lt|(org.bondlib.StructBondType<#{getTypeName java t}>)BOND_TYPE.getBaseStructType()|]
else mempty
publicConstructorDeclForGenericStruct :: MappingContext -> String -> [TypeParam] -> Maybe Type -> Text
publicConstructorDeclForGenericStruct java declName declParams maybeBase = [lt|
public #{declName}(org.bondlib.StructBondType<#{declName}<#{paramList}>> genericType) {
super(#{superConstructorArgs maybeBase});
this.__genericType = (StructBondTypeImpl<#{paramList}>)genericType;
this.__genericType.initializeStructFields(this);
};
|]
where
paramList = sepBy ", " paramName declParams
superConstructorArgs Nothing = mempty
superConstructorArgs (Just t) = if isGenericBondStructType t
then [lt|(org.bondlib.StructBondType<#{getTypeName java t}>)org.bondlib.ArgumentHelper.ensureNotNull(genericType, "genericType").getBaseStructType()|]
else mempty
object_equals :: String -> [Field] -> Maybe Type -> Text
object_equals declName fields structBase = [lt|@Override
public boolean equals(Object o) {
if (!(o instanceof #{declName})) return false;
#{compareBase structBase}
final #{declName} other = (#{declName}) o;
#{newlineSep 2 compareField fields}
return true;
}
|]
where
compareBase (Just _) = [lt|if (!(super.equals(o))) return false;|]
compareBase Nothing = mempty
compareField Field {..} = [lt|if (!(#{equalsMember fieldType fieldName})) return false;|]
equalsMember BT_Float f = [lt|org.bondlib.FloatingPointHelper.floatEquals(this.#{f}, other.#{f})|]
equalsMember BT_Double f = [lt|org.bondlib.FloatingPointHelper.doubleEquals(this.#{f}, other.#{f})|]
equalsMember BT_Bool f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_Int8 f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_Int16 f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_Int32 f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_Int64 f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_UInt8 f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_UInt16 f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_UInt32 f = [lt|this.#{f} == other.#{f}|]
equalsMember BT_UInt64 f = [lt|this.#{f} == other.#{f}|]
equalsMember (BT_UserDefined a@Alias {} args) f = equalsMember (resolveAlias a args) f
equalsMember _ f = [lt|(this.#{f} == null && other.#{f} == null) || (this.#{f} != null && this.#{f}.equals(other.#{f}))|]
object_hashCode :: [Field] -> Maybe Type -> Text
object_hashCode fields structBase = [lt|@Override
public int hashCode() {
int result = 17;
#{newlineSep 2 hash hashInputs}
return result;
}
|]
where
hash codeExpr = [lt|result += #{codeExpr};
result *= 0xeadbeef;
result ^= result >> 16;|]
hashInputs = (hashBase structBase) ++ hashFields
hashBase (Just _) = [[lt|super.hashCode()|]]
hashBase Nothing = []
hashFields = map (\Field {..} -> hashCode fieldType fieldName) fields
hashCode BT_Bool f = [lt|(#{f} ? 0 : 1)|]
hashCode BT_Int64 f = [lt|#{f} ^ (#{f} >>> 32)|]
hashCode BT_UInt64 f = [lt|#{f} ^ (#{f} >>> 32)|]
hashCode BT_Float f = [lt|org.bondlib.FloatingPointHelper.floatHashCode(#{f})|]
hashCode BT_Double f = [lt|org.bondlib.FloatingPointHelper.doubleHashCode(#{f})|]
hashCode BT_Int8 f = [lt|#{f}|]
hashCode BT_Int16 f = [lt|#{f}|]
hashCode BT_Int32 f = [lt|#{f}|]
hashCode BT_UInt8 f = [lt|#{f}|]
hashCode BT_UInt16 f = [lt|#{f}|]
hashCode BT_UInt32 f = [lt|#{f}|]
hashCode (BT_UserDefined a@Alias {} args) f = hashCode (resolveAlias a args) f
hashCode _ f = [lt|#{f} == null ? 0 : #{f}.hashCode()|]
javaNativeSerializationGlue :: String -> Text
javaNativeSerializationGlue declName = [lt|
// Java native serialization
private static final long serialVersionUID = 0L;
private #{declName} __deserializedInstance;
@Override
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
final java.io.ByteArrayOutputStream outStream = new java.io.ByteArrayOutputStream();
final org.bondlib.ProtocolWriter writer = new org.bondlib.CompactBinaryWriter(outStream, 1);
org.bondlib.Marshal.marshal(this, writer);
final byte[] marshalled = outStream.toByteArray();
out.write(0); // This type is not generic and has zero type parameters.
out.writeInt(marshalled.length);
out.write(marshalled);
}
@Override
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, java.lang.ClassNotFoundException {
if (in.read() != 0) throw new java.io.IOException("type is not generic, but serialized data has type parameters.");
final int marshalledLength = in.readInt();
final byte[] marshalled = new byte[marshalledLength];
in.readFully(marshalled);
final java.io.ByteArrayInputStream inStream = new java.io.ByteArrayInputStream(marshalled);
this.__deserializedInstance = org.bondlib.Unmarshal.unmarshal(inStream, getBondType()).deserialize();
}
private Object readResolve() throws java.io.ObjectStreamException {
return this.__deserializedInstance;
}
// end Java native serialization
|]
javaNativeSerializationUnimpl :: Text
javaNativeSerializationUnimpl = [lt|
// Java native serialization
@Override
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
throw new java.lang.IllegalArgumentException("java.io.Serializable support is not implemented for generic types");
}
@Override
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, java.lang.ClassNotFoundException {
// This may actually fail before reaching this line with an InvalidClassException because
// generic types don't have the nullary constructor required by the Java serialization
// framework.
throw new java.lang.IllegalArgumentException("java.io.Serializable support is not implemented for generic types");
}
// end Java native serialization
|]
class_java :: MappingContext -> [Import] -> Declaration -> Text
class_java java _ declaration = [lt|
package #{javaPackage};
#{typeDefinition declaration}
|]
where
javaType = getTypeName java
javaPackage = sepBy "." toText $ getNamespace java
typeDefinition s@Struct {..} = [lt|
#{generatedClassAnnotations}
public class #{typeNameWithParams declName declParams}#{maybe interface baseClass structBase} {
#{ifThenElse (null declParams) mempty (makeStructMember_GenericBondTypeBuilder declName declParams)}
private static final class StructBondTypeImpl#{typeParamAnglesNameList declParams} extends #{typeDescriptorNameWithParams declName declParams} {
#{makeStructBondTypeMember_StructBondTypeBuilderImpl declName declParams}
#{doubleLineSep 2 fieldDescriptorFieldDecl structFields}
private StructBondTypeImpl(org.bondlib.GenericTypeSpecialization genericTypeSpecialization) {
super(genericTypeSpecialization);
}
#{makeStructBondTypeMember_initialize java declParams structFields structBase}
@Override
public final java.lang.String getName() {
return "#{declName}";
}
@Override
public final java.lang.String getQualifiedName() {
return "#{qualifiedDeclaredTypeName idl s}";
}
@Override
public final java.lang.Class<#{typeNameWithParams declName declParams}> getValueClass() {
return (java.lang.Class<#{typeNameWithParams declName declParams}>) (java.lang.Class) #{declName}.class;
}
@Override
public final #{typeNameWithParams declName declParams} newInstance() {
return new #{typeNameWithParams declName declParams}(#{ifThenElse (null declParams) mempty thisText});
}
#{makeStructBondTypeMember_serializeStructFields declName declParams structFields}
#{makeStructBondTypeMember_deserializeStructFields_tagged declName declParams structFields}
#{makeStructBondTypeMember_deserializeStructFields_untagged declName declParams structFields}
#{makeStructBondTypeMember_initializeStructFields declName declParams structFields}
#{makeStructBondTypeMember_cloneStructFields declName declParams structFields}
}
#{bondTypeStaticVariableDecl}
public static void initializeBondType() {
StructBondTypeImpl.StructBondTypeBuilderImpl.register();
}
static {
initializeBondType();
}
#{bondTypeDescriptorInstanceVariableDecl}
#{ifThenElse (null declParams) (javaNativeSerializationGlue declName) javaNativeSerializationUnimpl}
#{doubleLineSep 1 publicFieldDecl structFields}
#{publicConstructorDecl}
#{object_equals declName structFields structBase}
#{object_hashCode structFields structBase}
@Override
public org.bondlib.StructBondType<? extends #{typeNameWithParams declName declParams}> getBondType() {
return #{getBondTypeReturnValue};
}
}|]
where
idl = MappingContext idlTypeMapping [] [] []
interface = [lt| implements org.bondlib.BondSerializable|]
baseClass x = [lt| extends #{javaType x}|]
publicFieldDecl Field {..} = [lt|public #{javaType fieldType} #{fieldName};|]
fieldDescriptorFieldDecl Field {..} = [lt|private #{structFieldDescriptorTypeName java fieldType} #{fieldName};|]
bondTypeStaticVariableDecl = if null declParams
then [lt|public static final org.bondlib.StructBondType<#{declName}> BOND_TYPE = new StructBondTypeImpl.StructBondTypeBuilderImpl().getInitializedFromCache();|]
else bondTypeStaticVariableDeclAsGenericBondTypeBuilder declName declParams
bondTypeDescriptorInstanceVariableDecl = if null declParams
then mempty
else [lt|private final StructBondTypeImpl#{typeParamAnglesNameList declParams} __genericType;|]
getBondTypeReturnValue = if null declParams
then [lt|BOND_TYPE|]
else [lt|this.__genericType|]
publicConstructorDecl = if null declParams
then publicConstructorDeclForNonGenericStruct java declName structBase
else publicConstructorDeclForGenericStruct java declName declParams structBase
thisText = "this" :: Text
typeDefinition _ = mempty