blob: 781ff21da94f9629a68d1f309871d1d322905161 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 hessian2
import (
"fmt"
"reflect"
"strings"
"time"
)
import (
hessian "github.com/apache/dubbo-go-hessian2"
perrors "github.com/pkg/errors"
)
var (
NilError = perrors.Errorf("object should not be nil")
UnexpectedTypeError = perrors.Errorf("object should be a POJO")
notBasicClassError = perrors.Errorf("object isn't a basic class")
)
// GetJavaName returns java name of an object
func GetJavaName(obj interface{}) (string, error) {
if obj == nil {
return "", NilError
}
t := reflect.TypeOf(obj)
// basic types, e.g. bool, int, etc.
if jtype, err := getBasicJavaName(t); err == nil {
return jtype, nil
}
// complicated types, e.g. array, slice, etc.
switch t.Kind() {
case reflect.Array, reflect.Slice:
sb := &strings.Builder{}
itemtyp := t
for itemtyp.Kind() == reflect.Array || itemtyp.Kind() == reflect.Slice {
sb.WriteString("[]")
itemtyp = itemtyp.Elem()
}
var (
javaName string
err error
)
if javaName, err = getBasicJavaName(itemtyp); err != nil {
if javaName, err = GetJavaName(reflect.New(itemtyp).Elem().Interface()); err != nil {
return "", err
}
}
return fmt.Sprintf("%s%s", javaName, sb), nil
case reflect.Map:
return "java.util.Map", nil
default:
pojo, ok := obj.(hessian.POJO)
if !ok {
return "", UnexpectedTypeError
}
return pojo.JavaClassName(), nil
}
}
func getBasicJavaName(typ reflect.Type) (string, error) {
switch typ.Kind() {
case reflect.Bool:
return "boolean", nil
case reflect.Int, reflect.Int64: // in 64-bit processor, Int takes a 64-bit space
return "long", nil
case reflect.Int32:
return "int", nil
case reflect.Int8, reflect.Int16:
return "short", nil
case reflect.Uint, reflect.Uint64: // in 64-bit processor, Uint takes a 64-bit space
return "unsigned long", nil
case reflect.Uint32:
return "unsigned int", nil
case reflect.Uint16:
return "unsigned short", nil
case reflect.Uint8:
return "char", nil
case reflect.Float32:
return "float", nil
case reflect.Float64:
return "double", nil
case reflect.String:
return "java.lang.String", nil
}
return "", notBasicClassError
}
// GetClassDesc get class desc.
// - boolean[].class => "[Z"
// - Object.class => "Ljava/lang/Object;"
func GetClassDesc(v interface{}) string {
if v == nil {
return "V"
}
switch v := v.(type) {
// Serialized tags for base types
case nil:
return "V"
case bool:
return "Z"
case []bool:
return "[Z"
case byte:
return "B"
case []byte:
return "[B"
case int8:
return "B"
case []int8:
return "[B"
case int16:
return "S"
case []int16:
return "[S"
case uint16: // Equivalent to Char of Java
return "C"
case []uint16:
return "[C"
// case rune:
// return "C"
case int:
return "J"
case []int:
return "[J"
case int32:
return "I"
case []int32:
return "[I"
case int64:
return "J"
case []int64:
return "[J"
case time.Time:
return "java.util.Date"
case []time.Time:
return "[Ljava.util.Date"
case float32:
return "F"
case []float32:
return "[F"
case float64:
return "D"
case []float64:
return "[D"
case string:
return "java.lang.String"
case []string:
return "[Ljava.lang.String;"
case []hessian.Object:
return "[Ljava.lang.Object;"
case map[interface{}]interface{}:
// return "java.util.HashMap"
return "java.util.Map"
case hessian.POJOEnum:
return v.(hessian.POJOEnum).JavaClassName()
// Serialized tags for complex types
default:
t := reflect.TypeOf(v)
if reflect.Ptr == t.Kind() {
t = reflect.TypeOf(reflect.ValueOf(v).Elem())
}
switch t.Kind() {
case reflect.Struct:
return "java.lang.Object"
case reflect.Slice, reflect.Array:
if t.Elem().Kind() == reflect.Struct {
return "[Ljava.lang.Object;"
}
// return "java.util.ArrayList"
return "java.util.List"
case reflect.Map: // Enter here, map may be map[string]int
return "java.util.Map"
default:
return ""
}
}
}