ExtJs의 Tree Panel구조를 이용하여 메뉴나 선택항목을 구성하는 경우 데이터를 Ajax 등을 통해 Data Model로 내려받아 Panel에 뿌려야 한다(그렇지 않으면 Tree를 갱신하기도 어려워지고 공통모듈을 사용하기 어려워 진다).
이 때 서버쪽에서 Tree구조의 json 데이터를 내려주기 위해서는 결국 서버쪽에서 json데이터를 만들기 전 먼저 tree 구조로 데이터를 재정렬해서 json데이터 형태로 전환해야 한다.

많은 검색 끝에 찾은 팁은 다음과 같다.

데이터 조회(php)

...
db조회
...
    $data = array();
    $i = 0;
    while ( $row = dbnext($result) ) { // 쿼리 결과를 loop 돌면서 배열에 채우는 부분
          $data[$i] = array();
          $data[$i]['id'] = $row[0];    // 정렬을 위한 키값을 읽음. 이를 id라고 하는 field에 저장
          $data[$i]['parent_id] = $row[4];  // 정렬을 위해 부모(parent) 키값을 읽음
          $data[$i]['leaf'] = true;         // 모든 노드를 잠정적으로 leaf로 저장
          for ( $idx = 1; $idx <= 3; $idx++ ) { // 조회한 field값을 배열에 입력 받음 
              $field_name = "field" . $idx;
              $data[$i][$field_name] = $row[$idx];
          }
          $i++;
    }
...
db close

정렬하는 부분(php)

         $itemsByReference = array();
         foreach($data as $key => &$item) {
               $itemsByReference[$item['id']] = &apm;$item;
         }

         foreach($data as $key => &$item)
               if($item['parent_id'] && isset($itemsByRefence[$item['parent_id']])) {
                    $itemsByReference[$item['parent_id']['children'][] = &$item;
                    $itemsByReference[$item[parent_id']['expanded'] = true;
                    unset($itemsByReference[$item['parent_id']]['leaf']);
               }

         foreach($data as $key => &$item) {
               if($item['parent_id'] && isset($itemsByReference[$item['parent_id']]))
                    unset($data[$key]);
         }

         if ($i > 0) {
             print json_encode($data);
         }

php에서 지원하는 json과 배열의 call by reference가 jsp에서는 지원되지 않는다.
그래서 json은 별도 class를 사용해서 해결했고(org.json.*), 데이터의 정렬은 stack 구조를 이용하여 구현했다.

데이터 조회(jsp)

    JSONArray   jData = new JSONArray();
    HashMap subData;
...
    데이터 조회
...
       i = 0;
       while ( row.next() ) {
            subData = new HashMap();
            subData.put("id", row.getString(2));         // 키값을 입력한다.
            if ( i == 0 ) thisTermAmount = Double.valueOf(row.getString(13));
            for ( idx = 1;  idx <= 3; n++ ){
                  subData.put("field" + String.valueOf(idx), row.getString(idx));
             }
             subData.put("seq", row.getString(4));    // seq와 depth 필드가 필수다
             subData.put("depth", row.getString(5));
             subData.put("parent_id", row.getString(6));
             subData.put("leaf", true);
             jData.put(i, subData);
             i++;
        }
     if ( i > 0 ) 
             out.println(Utils.TreeJson(jData).toString());

배열을 그대로 이용하여서는 json으로 변환하기 힘들어 JSONArray와 HashMap()을 이용하여 데이터를 저장하여 이를 다시 재정렬하는 구조로 작성하였다.

정렬하는 부분(jsp)

import java.util.*;
import org.json.*;

public class Utils {

    Utils() {}

    public static JSONArray TreeJson(JSONArray jData)
    {
        int     len, m;
        Stack   s1 = new Stack();
        Stack   s2 = new Stack();
        JSONObject  j1, j2;

        try {
            j1 = jData.getJSONObject(0);
            s1.push(j1);
            for ( m = 1; m < jData.length(); m++) {
                j2 = jData.getJSONObject(m);
                if ( Integer.parseInt(j1.get("depth").toString()) <= Integer.parseInt(j2.get("depth").toString()) ) {
                     s1.push(j2);
                     j1 = j2;
                 }
                 else if ( Integer.parseInt(j1.get("depth").toString()) > Integer.parseInt(j2.get("depth").toString())  ) {
                    while (  Integer.parseInt((s1.peek()).get("depth").toString()) > Integer.parseInt(j2.get("depth").toString()) ) {
                        JSONArray children = new JSONArray();
                        int     lvl = Integer.parseInt((s1.peek()).get("depth").toString());
                        while ( Integer.parseInt((s1.peek()).get("depth").toString()) == lvl ) {
                            s2.push(s1.pop());
                        }
                        while(s2.size() > 0 ) {
                            children.put(s2.pop());
                        }
                        j1 = s1.pop();
                        j1.put("children", children);
                        j1.remove("leaf");
                        j1.put("leaf", false);
                        s1.push(j1);
                    }
                    s1.push(j2);
                    j1 = j2;
                }
            }

            while ( s1.size() > 0 && Integer.parseInt((s1.peek()).get("depth").toString()) > 1 ) {// clear stack
                JSONArray children = new JSONArray();
                int     lvl = Integer.parseInt((s1.peek()).get("depth").toString());
                while ( Integer.parseInt((s1.peek()).get("depth").toString()) == lvl ) {
                    s2.push(s1.pop());
                }
                while(s2.size() > 0 ) {
                    children.put(s2.pop());
                }
                j1 = s1.pop();
                j1.put("children", children);
                j1.remove("leaf");
                j1.put("leaf", false);
                s1.push(j1);
            }
        }
        catch( JSONException je) {
        }

        return new JSONArray(s1);
    }
}

java expert가 아니라 코드가 비효율적으로 구성되었을 수 있으나 일단 php에 없는 json함수와 tree 정렬 함수를 구현했다.

실행 결과는 tree 구조의 데이터를 json 형태로 보내게 된다.

실행 결과 예

{id:001,field0:root,parent_id:NULL,leaf:false,child:[{id:002,field0:'노드1',parent_id:001,leaf:true},{id:003,field0:'노드100',parent_id:001,leaf:true}]}

 

 

 

By yaplab

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다