| /* | 
 |  * 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 hessian | 
 |  | 
 | import ( | 
 | 	"reflect" | 
 | ) | 
 |  | 
 | import ( | 
 | 	perrors "github.com/pkg/errors" | 
 | ) | 
 |  | 
 | type JavaCollectionObject interface { | 
 | 	Get() []interface{} | 
 | 	Set([]interface{}) | 
 | 	JavaClassName() string | 
 | } | 
 |  | 
 | var collectionTypeMap = make(map[string]reflect.Type, 16) | 
 |  | 
 | func SetCollectionSerialize(collection JavaCollectionObject) { | 
 | 	name := collection.JavaClassName() | 
 | 	v := reflect.ValueOf(collection) | 
 | 	var typ reflect.Type | 
 | 	switch v.Kind() { | 
 | 	case reflect.Struct: | 
 | 		typ = v.Type() | 
 | 	case reflect.Ptr: | 
 | 		typ = v.Elem().Type() | 
 | 	default: | 
 | 		typ = reflect.TypeOf(collection) | 
 | 	} | 
 | 	SetSerializer(name, JavaCollectionSerializer{}) | 
 | 	RegisterPOJO(collection) | 
 | 	collectionTypeMap[name] = typ | 
 | } | 
 |  | 
 | func getCollectionSerialize(name string) reflect.Type { | 
 | 	return collectionTypeMap[name] | 
 | } | 
 |  | 
 | func isCollectionSerialize(name string) bool { | 
 | 	return getCollectionSerialize(name) != nil | 
 | } | 
 |  | 
 | type JavaCollectionSerializer struct{} | 
 |  | 
 | func (JavaCollectionSerializer) EncObject(e *Encoder, vv POJO) error { | 
 | 	var err error | 
 | 	v, ok := vv.(JavaCollectionObject) | 
 | 	if !ok { | 
 | 		return perrors.New("can not be converted into java collection object") | 
 | 	} | 
 | 	collectionName := v.JavaClassName() | 
 | 	if collectionName == "" { | 
 | 		return perrors.New("collection name empty") | 
 | 	} | 
 | 	list := v.Get() | 
 | 	length := len(list) | 
 | 	typeName := v.JavaClassName() | 
 | 	err = writeCollectionBegin(length, typeName, e) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	for i := 0; i < length; i++ { | 
 | 		if err = e.Encode(list[i]); err != nil { | 
 | 			return err | 
 | 		} | 
 | 	} | 
 | 	return nil | 
 | } | 
 |  | 
 | func (JavaCollectionSerializer) DecObject(d *Decoder, typ reflect.Type, cls *ClassInfo) (interface{}, error) { | 
 | 	// for the java impl of hessian encode collections as list, which will not be decoded as object in go impl, this method should not be called | 
 | 	return nil, perrors.New("unexpected collection decode call") | 
 | } | 
 |  | 
 | func (d *Decoder) decodeCollection(length int, listTyp string) (interface{}, error) { | 
 | 	typ := getCollectionSerialize(listTyp) | 
 | 	if typ == nil { | 
 | 		return nil, perrors.New("no collection deserialize set as " + listTyp) | 
 | 	} | 
 | 	v := reflect.New(typ).Interface() | 
 | 	collcetionV, ok := v.(JavaCollectionObject) | 
 | 	if !ok { | 
 | 		return nil, perrors.New("collection deserialize err " + listTyp) | 
 | 	} | 
 | 	list, err := d.readTypedListValue(length, "", false) | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	listInterface := EnsureRawAny(list) | 
 | 	listV, listOk := listInterface.([]interface{}) | 
 | 	if !listOk { | 
 | 		return nil, perrors.New("collection deserialize err " + listTyp) | 
 | 	} | 
 | 	collcetionV.Set(listV) | 
 | 	return collcetionV, nil | 
 | } | 
 |  | 
 | func writeCollectionBegin(length int, typeName string, e *Encoder) error { | 
 | 	var err error | 
 | 	if length <= int(LIST_DIRECT_MAX) { | 
 | 		e.Append([]byte{BC_LIST_DIRECT + byte(length)}) | 
 | 		err = e.Encode(typeName) | 
 | 		if err != nil { | 
 | 			return err | 
 | 		} | 
 | 	} else { | 
 | 		e.Append([]byte{BC_LIST_FIXED}) | 
 | 		err = e.Encode(typeName) | 
 | 		if err != nil { | 
 | 			return err | 
 | 		} | 
 | 		err = e.Encode(int32(length)) | 
 | 		if err != nil { | 
 | 			return nil | 
 | 		} | 
 | 	} | 
 | 	return nil | 
 | } |