578 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			578 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package jsonpath
 | 
						|
 | 
						|
import (
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
func TestGetWithPathsBasic(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name     string
 | 
						|
		data     map[string]interface{}
 | 
						|
		path     string
 | 
						|
		expected []JSONNode
 | 
						|
		error    bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "simple property",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"name": "John",
 | 
						|
				"age":  30,
 | 
						|
			},
 | 
						|
			path: "$.name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "John", Path: "$.name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "nested property",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"user": map[string]interface{}{
 | 
						|
					"name": "John",
 | 
						|
					"age":  30,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$.user.name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "John", Path: "$.user.name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "array access",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"users": []interface{}{
 | 
						|
					map[string]interface{}{"name": "John", "age": 30},
 | 
						|
					map[string]interface{}{"name": "Jane", "age": 25},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$.users[1].name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "Jane", Path: "$.users[1].name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "wildcard",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"users": []interface{}{
 | 
						|
					map[string]interface{}{"name": "John", "age": 30},
 | 
						|
					map[string]interface{}{"name": "Jane", "age": 25},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$.users[*].name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "John", Path: "$.users[0].name"},
 | 
						|
				{Value: "Jane", Path: "$.users[1].name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "recursive descent",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"user": map[string]interface{}{
 | 
						|
					"name": "John",
 | 
						|
					"profile": map[string]interface{}{
 | 
						|
						"email": "john@example.com",
 | 
						|
					},
 | 
						|
				},
 | 
						|
				"admin": map[string]interface{}{
 | 
						|
					"email": "admin@example.com",
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$..email",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "john@example.com", Path: "$.user.profile.email"},
 | 
						|
				{Value: "admin@example.com", Path: "$.admin.email"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "nonexistent path",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"user": map[string]interface{}{
 | 
						|
					"name": "John",
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path:     "$.user.email",
 | 
						|
			expected: []JSONNode{},
 | 
						|
			error:    true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			result, err := Get(tt.data, tt.path)
 | 
						|
			if err != nil {
 | 
						|
				if !tt.error {
 | 
						|
					t.Errorf("GetWithPaths() returned error: %v", err)
 | 
						|
				}
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			// For nonexistent path, we expect empty slice
 | 
						|
			if tt.name == "nonexistent path" {
 | 
						|
				if len(result) > 0 {
 | 
						|
					t.Errorf("GetWithPaths() returned %v, expected empty result", result)
 | 
						|
				}
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			// Check if lengths match
 | 
						|
			if len(result) != len(tt.expected) {
 | 
						|
				t.Errorf("GetWithPaths() returned %d items, expected %d", len(result), len(tt.expected))
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			// For wildcard results, we need to check containment rather than exact order
 | 
						|
			if tt.name == "wildcard" || tt.name == "recursive descent" {
 | 
						|
				// For each expected item, check if it exists in the results by both value and path
 | 
						|
				for _, expected := range tt.expected {
 | 
						|
					found := false
 | 
						|
					for _, r := range result {
 | 
						|
						if reflect.DeepEqual(r.Value, expected.Value) && r.Path == expected.Path {
 | 
						|
							found = true
 | 
						|
							break
 | 
						|
						}
 | 
						|
					}
 | 
						|
					if !found {
 | 
						|
						t.Errorf("GetWithPaths() missing expected value: %v with path: %s", expected.Value, expected.Path)
 | 
						|
					}
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				// Otherwise check exact equality of both values and paths
 | 
						|
				for i, expected := range tt.expected {
 | 
						|
					if !reflect.DeepEqual(result[i].Value, expected.Value) {
 | 
						|
						t.Errorf("GetWithPaths() value at [%d] = %v, expected %v", i, result[i].Value, expected.Value)
 | 
						|
					}
 | 
						|
					if result[i].Path != expected.Path {
 | 
						|
						t.Errorf("GetWithPaths() path at [%d] = %s, expected %s", i, result[i].Path, expected.Path)
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestSet(t *testing.T) {
 | 
						|
	t.Run("simple property", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"name": "John",
 | 
						|
			"age":  30,
 | 
						|
		}
 | 
						|
		 err := Set(data, "$.name", "Jane")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		if data["name"] != "Jane" {
 | 
						|
			t.Errorf("Set() failed: expected name to be 'Jane', got %v", data["name"])
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("nested property", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"user": map[string]interface{}{
 | 
						|
				"name": "John",
 | 
						|
				"age":  30,
 | 
						|
			},
 | 
						|
		}
 | 
						|
		err := Set(data, "$.user.name", "Jane")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		user, ok := data["user"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("User is not a map")
 | 
						|
		}
 | 
						|
		if user["name"] != "Jane" {
 | 
						|
			t.Errorf("Set() failed: expected user.name to be 'Jane', got %v", user["name"])
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("array element", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"users": []interface{}{
 | 
						|
				map[string]interface{}{"name": "John", "age": 30},
 | 
						|
				map[string]interface{}{"name": "Jane", "age": 25},
 | 
						|
			},
 | 
						|
		}
 | 
						|
		err := Set(data, "$.users[0].name", "Bob")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		users, ok := data["users"].([]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("Users is not a slice")
 | 
						|
		}
 | 
						|
		user0, ok := users[0].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("User is not a map")
 | 
						|
		}
 | 
						|
		if user0["name"] != "Bob" {
 | 
						|
			t.Errorf("Set() failed: expected users[0].name to be 'Bob', got %v", user0["name"])
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("complex value", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"user": map[string]interface{}{
 | 
						|
				"name": "John",
 | 
						|
				"profile": map[string]interface{}{
 | 
						|
					"email": "john@example.com",
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		newProfile := map[string]interface{}{
 | 
						|
			"email": "john.doe@example.com",
 | 
						|
			"phone": "123-456-7890",
 | 
						|
		}
 | 
						|
 | 
						|
		err := Set(data, "$.user.profile", newProfile)
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		userMap, ok := data["user"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("User is not a map")
 | 
						|
		}
 | 
						|
 | 
						|
		profile, ok := userMap["profile"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("Profile is not a map")
 | 
						|
		}
 | 
						|
 | 
						|
		if profile["email"] != "john.doe@example.com" || profile["phone"] != "123-456-7890" {
 | 
						|
			t.Errorf("Set() failed: expected profile to be updated with new values")
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("create new property", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"user": map[string]interface{}{
 | 
						|
				"name": "John",
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		err := Set(data, "$.user.email", "john@example.com")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		userMap, ok := data["user"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("User is not a map")
 | 
						|
		}
 | 
						|
 | 
						|
		if email, exists := userMap["email"]; !exists || email != "john@example.com" {
 | 
						|
			t.Errorf("Set() failed: expected user.email to be 'john@example.com', got %v", userMap["email"])
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("create nested properties", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"user": map[string]interface{}{
 | 
						|
				"name": "John",
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		err := Set(data, "$.user.contact.email", "john@example.com")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		userMap, ok := data["user"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("User is not a map")
 | 
						|
		}
 | 
						|
 | 
						|
		contact, ok := userMap["contact"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("Contact is not a map")
 | 
						|
		}
 | 
						|
 | 
						|
		if email, exists := contact["email"]; !exists || email != "john@example.com" {
 | 
						|
			t.Errorf("Set() failed: expected user.contact.email to be 'john@example.com', got %v", contact["email"])
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("create array and element", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"user": map[string]interface{}{
 | 
						|
				"name": "John",
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		// This should create an empty addresses array, but won't be able to set index 0
 | 
						|
		// since the array is empty
 | 
						|
		err := Set(data, "$.user.addresses[0].street", "123 Main St")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("multiple targets (should only update first)", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"users": []interface{}{
 | 
						|
				map[string]interface{}{"active": true},
 | 
						|
				map[string]interface{}{"active": true},
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		err := Set(data, "$.users[*].active", false)
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		users, ok := data["users"].([]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("Users is not a slice")
 | 
						|
		}
 | 
						|
 | 
						|
		user0, ok := users[0].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("User0 is not a map")
 | 
						|
		}
 | 
						|
 | 
						|
		user1, ok := users[1].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("User1 is not a map")
 | 
						|
		}
 | 
						|
 | 
						|
		// Only the first one should be changed
 | 
						|
		if active, exists := user0["active"]; !exists || active != false {
 | 
						|
			t.Errorf("Set() failed: expected users[0].active to be false, got %v", user0["active"])
 | 
						|
		}
 | 
						|
 | 
						|
		// The second one should remain unchanged
 | 
						|
		if active, exists := user1["active"]; !exists || active != true {
 | 
						|
			t.Errorf("Set() incorrectly modified users[1].active: expected true, got %v", user1["active"])
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("setting on root should not fail (anymore)", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"name": "John",
 | 
						|
		}
 | 
						|
 | 
						|
		err := Set(data, "$", "Jane")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("Set() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		// Data should be unchanged
 | 
						|
		if data["name"] != "John" {
 | 
						|
			t.Errorf("Data was modified when setting on root")
 | 
						|
		}
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func TestSetAll(t *testing.T) {
 | 
						|
	t.Run("simple property", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"name": "John",
 | 
						|
			"age":  30,
 | 
						|
		}
 | 
						|
		err := SetAll(data, "$.name", "Jane")
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("SetAll() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		if data["name"] != "Jane" {
 | 
						|
			t.Errorf("SetAll() failed: expected name to be 'Jane', got %v", data["name"])
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("all array elements", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"users": []interface{}{
 | 
						|
				map[string]interface{}{"active": true},
 | 
						|
				map[string]interface{}{"active": true},
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		err := SetAll(data, "$.users[*].active", false)
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("SetAll() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		users, ok := data["users"].([]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("Users is not a slice")
 | 
						|
		}
 | 
						|
 | 
						|
		// Both elements should be updated
 | 
						|
		for i, user := range users {
 | 
						|
			userMap, ok := user.(map[string]interface{})
 | 
						|
			if !ok {
 | 
						|
				t.Fatalf("User%d is not a map", i)
 | 
						|
			}
 | 
						|
 | 
						|
			if active, exists := userMap["active"]; !exists || active != false {
 | 
						|
				t.Errorf("SetAll() failed: expected users[%d].active to be false, got %v", i, userMap["active"])
 | 
						|
			}
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	t.Run("recursive descent", func(t *testing.T) {
 | 
						|
		data := map[string]interface{}{
 | 
						|
			"user": map[string]interface{}{
 | 
						|
				"profile": map[string]interface{}{
 | 
						|
					"active": true,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			"admin": map[string]interface{}{
 | 
						|
				"profile": map[string]interface{}{
 | 
						|
					"active": true,
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}
 | 
						|
 | 
						|
		err := SetAll(data, "$..active", false)
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("SetAll() returned error: %v", err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		// Check user profile
 | 
						|
		userProfile, ok := data["user"].(map[string]interface{})["profile"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("Failed to access user.profile")
 | 
						|
		}
 | 
						|
		if active, exists := userProfile["active"]; !exists || active != false {
 | 
						|
			t.Errorf("SetAll() didn't update user.profile.active, got: %v", active)
 | 
						|
		}
 | 
						|
 | 
						|
		// Check admin profile
 | 
						|
		adminProfile, ok := data["admin"].(map[string]interface{})["profile"].(map[string]interface{})
 | 
						|
		if !ok {
 | 
						|
			t.Fatalf("Failed to access admin.profile")
 | 
						|
		}
 | 
						|
		if active, exists := adminProfile["active"]; !exists || active != false {
 | 
						|
			t.Errorf("SetAll() didn't update admin.profile.active, got: %v", active)
 | 
						|
		}
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func TestGetWithPathsExtended(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name     string
 | 
						|
		data     map[string]interface{}
 | 
						|
		path     string
 | 
						|
		expected []JSONNode
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "simple property",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"name": "John",
 | 
						|
				"age":  30,
 | 
						|
			},
 | 
						|
			path: "$.name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "John", Path: "$.name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "nested property",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"user": map[string]interface{}{
 | 
						|
					"name": "John",
 | 
						|
					"age":  30,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$.user.name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "John", Path: "$.user.name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "array access",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"users": []interface{}{
 | 
						|
					map[string]interface{}{"name": "John", "age": 30},
 | 
						|
					map[string]interface{}{"name": "Jane", "age": 25},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$.users[1].name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "Jane", Path: "$.users[1].name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "wildcard",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"users": []interface{}{
 | 
						|
					map[string]interface{}{"name": "John", "age": 30},
 | 
						|
					map[string]interface{}{"name": "Jane", "age": 25},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$.users[*].name",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "John", Path: "$.users[0].name"},
 | 
						|
				{Value: "Jane", Path: "$.users[1].name"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "recursive descent",
 | 
						|
			data: map[string]interface{}{
 | 
						|
				"user": map[string]interface{}{
 | 
						|
					"name": "John",
 | 
						|
					"profile": map[string]interface{}{
 | 
						|
						"email": "john@example.com",
 | 
						|
					},
 | 
						|
				},
 | 
						|
				"admin": map[string]interface{}{
 | 
						|
					"email": "admin@example.com",
 | 
						|
				},
 | 
						|
			},
 | 
						|
			path: "$..email",
 | 
						|
			expected: []JSONNode{
 | 
						|
				{Value: "john@example.com", Path: "$.user.profile.email"},
 | 
						|
				{Value: "admin@example.com", Path: "$.admin.email"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			result, err := Get(tt.data, tt.path)
 | 
						|
			if err != nil {
 | 
						|
				t.Errorf("GetWithPaths() returned error: %v", err)
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			// Check if lengths match
 | 
						|
			if len(result) != len(tt.expected) {
 | 
						|
				t.Errorf("GetWithPaths() returned %d items, expected %d", len(result), len(tt.expected))
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			// For each expected item, find its match in the results and verify both value and path
 | 
						|
			for _, expected := range tt.expected {
 | 
						|
				found := false
 | 
						|
				for _, r := range result {
 | 
						|
					// Check if value matches
 | 
						|
					if reflect.DeepEqual(r.Value, expected.Value) {
 | 
						|
						found = true
 | 
						|
						// Check if path matches
 | 
						|
						if r.Path != expected.Path {
 | 
						|
							t.Errorf("Path mismatch for value %v: got %s, expected %s", r.Value, r.Path, expected.Path)
 | 
						|
						}
 | 
						|
						break
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if !found {
 | 
						|
					t.Errorf("Expected node with value %v and path %s not found in results", expected.Value, expected.Path)
 | 
						|
				}
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |