OSDN Git Service

Merge branch 'Branch_release-'
[jindolf/Jindolf.git] / src / main / java / jp / sfjp / jindolf / data / LandsModel.java
-/*\r
- * model of lands for JTree view\r
- *\r
- * Copyright(c) 2008 olyutorskii\r
- * $Id: LandsModel.java 953 2009-12-06 16:42:14Z olyutorskii $\r
- */\r
-\r
-package jp.sourceforge.jindolf;\r
-\r
-import java.io.IOException;\r
-import java.net.URISyntaxException;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import javax.swing.event.EventListenerList;\r
-import javax.swing.event.TreeModelEvent;\r
-import javax.swing.event.TreeModelListener;\r
-import javax.swing.tree.TreeModel;\r
-import javax.swing.tree.TreePath;\r
-import javax.xml.parsers.DocumentBuilder;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import org.xml.sax.SAXException;\r
-\r
-/**\r
- * 国の集合。あらゆるデータモデルの大元。\r
- * 国一覧と村一覧を管理。\r
- * JTreeのモデルも兼用。\r
- */\r
-public class LandsModel implements TreeModel{ // ComboBoxModelも付けるか?\r
-\r
-    /**\r
-     * 村IDで範囲指定した、村のセクション集合。国-村間の中間ツリー。\r
-     * @see javax.swing.tree.TreeModel\r
-     */\r
-    private static final class VillageSection{\r
-\r
-        /**\r
-         * 与えられた国の全ての村を、指定されたinterval間隔でセクション化する。\r
-         * @param land 国\r
-         * @param interval セクションの間隔\r
-         * @return セクションのリスト\r
-         * @throws java.lang.IllegalArgumentException intervalが正でない\r
-         */\r
-        private static List<VillageSection> getSectionList(Land land,\r
-                                                             int interval )\r
-                throws IllegalArgumentException{\r
-            if(interval <= 0){\r
-                throw new IllegalArgumentException();\r
-            }\r
-\r
-            List<Village> villageList = land.getVillageList();\r
-            Village village1st = villageList.get(0);\r
-            Village villageLast = villageList.get(villageList.size() - 1);\r
-\r
-            int startID = village1st.getVillageIDNum();\r
-            int endID = villageLast.getVillageIDNum();\r
-\r
-            List<VillageSection> result = new LinkedList<VillageSection>();\r
-\r
-            int fixedStart = startID / interval * interval;\r
-            for(int ct = fixedStart; ct <= endID; ct += interval){\r
-                VillageSection section =\r
-                        new VillageSection(land, ct, ct + interval - 1);\r
-                result.add(section);\r
-            }\r
-\r
-            return Collections.unmodifiableList(result);\r
-        }\r
-\r
-        private final int startID;\r
-        private final int endID;\r
-        private final String prefix;\r
-\r
-        private final List<Village> villageList = new LinkedList<Village>();\r
-\r
-        /**\r
-         * セクション集合を生成する。\r
-         * @param land 国\r
-         * @param startID 開始村ID\r
-         * @param endID 終了村ID\r
-         * @throws java.lang.IndexOutOfBoundsException IDの範囲指定が変\r
-         */\r
-        private VillageSection(Land land, int startID, int endID)\r
-                throws IndexOutOfBoundsException{\r
-            super();\r
-\r
-            if(startID < 0 || startID > endID){\r
-                throw new IndexOutOfBoundsException();\r
-            }\r
-\r
-            this.startID = startID;\r
-            this.endID = endID;\r
-            this.prefix = land.getLandDef().getLandPrefix();\r
-\r
-            for(Village village : land.getVillageList()){\r
-                int id = village.getVillageIDNum();\r
-                if(startID <= id && id <= endID){\r
-                    this.villageList.add(village);\r
-                }\r
-            }\r
-\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * セクションに含まれる村の総数を返す。\r
-         * @return 村の総数\r
-         */\r
-        private int getVillageCount(){\r
-            return this.villageList.size();\r
-        }\r
-\r
-        /**\r
-         * セクションに含まれるindex番目の村を返す。\r
-         * @param index インデックス\r
-         * @return index番目の村\r
-         */\r
-        private Village getVillage(int index){\r
-            return this.villageList.get(index);\r
-        }\r
-\r
-        /**\r
-         * セクションにおける、指定された子(村)のインデックス位置を返す。\r
-         * @param child 子\r
-         * @return インデックス位置\r
-         */\r
-        private int getIndexOfVillage(Object child){\r
-            return this.villageList.indexOf(child);\r
-        }\r
-\r
-        /**\r
-         * セクションの文字列表記。\r
-         * JTree描画に反映される。\r
-         * @return 文字列表記\r
-         */\r
-        @Override\r
-        public String toString(){\r
-            StringBuilder result = new StringBuilder();\r
-            result.append(this.prefix).append(this.startID);\r
-            result.append(" ~ ");\r
-            result.append(this.prefix).append(this.endID);\r
-            return result.toString();\r
-        }\r
-    }\r
-\r
-    private static final String ROOT = "ROOT";\r
-    private static final int SECTION_INTERVAL = 100;\r
-\r
-    private final List<Land> landList = new LinkedList<Land>();\r
-    private final List<Land> unmodList =\r
-            Collections.unmodifiableList(this.landList);\r
-    private final Map<Land, List<VillageSection>> sectionMap =\r
-            new HashMap<Land, List<VillageSection>>();\r
-    private boolean isLandListLoaded = false;\r
-\r
-    private final EventListenerList listeners = new EventListenerList();\r
-\r
-    private boolean ascending = false;\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * この時点ではまだ国一覧が読み込まれない。\r
-     */\r
-    public LandsModel(){\r
-        super();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 指定した国の村一覧を読み込む。\r
-     * @param land 国\r
-     * @throws java.io.IOException ネットワーク入出力の異常\r
-     */\r
-    public void loadVillageList(Land land) throws IOException{\r
-        land.updateVillageList();\r
-\r
-        List<VillageSection> sectionList =\r
-                VillageSection.getSectionList(land, SECTION_INTERVAL);\r
-        this.sectionMap.put(land, sectionList);\r
-\r
-        int[] childIndices = new int[sectionList.size()];\r
-        for(int ct = 0; ct < childIndices.length; ct++){\r
-            childIndices[ct] = ct;\r
-        }\r
-        Object[] children = sectionList.toArray();\r
-\r
-        Object[] path = {ROOT, land};\r
-        TreePath treePath = new TreePath(path);\r
-        TreeModelEvent event = new TreeModelEvent(this,\r
-                                                  treePath,\r
-                                                  childIndices,\r
-                                                  children     );\r
-        fireTreeStructureChanged(event);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 国一覧を読み込む。\r
-     */\r
-    // TODO static にできない?\r
-    public void loadLandList(){\r
-        if(this.isLandListLoaded) return;\r
-\r
-        this.landList.clear();\r
-\r
-        List<LandDef> landDefList;\r
-        try{\r
-            DocumentBuilder builder = XmlUtils.createDocumentBuilder();\r
-            landDefList = LandDef.buildLandDefList(builder);\r
-        }catch(IOException e){\r
-            Jindolf.logger().fatal("failed to load land list", e);\r
-            return;\r
-        }catch(SAXException e){\r
-            Jindolf.logger().fatal("failed to load land list", e);\r
-            return;\r
-        }catch(URISyntaxException e){\r
-            Jindolf.logger().fatal("failed to load land list", e);\r
-            return;\r
-        }catch(ParserConfigurationException e){\r
-            Jindolf.logger().fatal("failed to load land list", e);\r
-            return;\r
-        }\r
-\r
-        for(LandDef landDef : landDefList){\r
-            Land land = new Land(landDef);\r
-            this.landList.add(land);\r
-        }\r
-\r
-        this.isLandListLoaded = true;\r
-\r
-        fireLandListChanged();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ツリー内容が更新された事をリスナーに通知する。\r
-     */\r
-    private void fireLandListChanged(){\r
-        int size = this.landList.size();\r
-        int[] childIndices = new int[size];\r
-        for(int ct = 0; ct < size; ct++){\r
-            int index = ct;\r
-            childIndices[ct] = index;\r
-        }\r
-\r
-        Object[] children = this.landList.toArray();\r
-\r
-        TreePath treePath = new TreePath(ROOT);\r
-        TreeModelEvent event = new TreeModelEvent(this,\r
-                                                  treePath,\r
-                                                  childIndices,\r
-                                                  children     );\r
-        fireTreeStructureChanged(event);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * ツリーの並び順を設定する。\r
-     * 場合によってはTreeModelEventが発生する。\r
-     * @param ascending trueなら昇順\r
-     */\r
-    public void setAscending(boolean ascending){\r
-        if(this.ascending == ascending) return;\r
-\r
-        this.ascending = ascending;\r
-        fireLandListChanged();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param l {@inheritDoc}\r
-     */\r
-    public void addTreeModelListener(TreeModelListener l){\r
-        this.listeners.add(TreeModelListener.class, l);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param l {@inheritDoc}\r
-     */\r
-    public void removeTreeModelListener(TreeModelListener l){\r
-        this.listeners.remove(TreeModelListener.class, l);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 登録中のリスナーのリストを得る。\r
-     * @return リスナーのリスト\r
-     */\r
-    private TreeModelListener[] getTreeModelListeners(){\r
-        return this.listeners.getListeners(TreeModelListener.class);\r
-    }\r
-\r
-    /**\r
-     * 全リスナーにイベントを送出する。\r
-     * @param event ツリーイベント\r
-     */\r
-    protected void fireTreeStructureChanged(TreeModelEvent event){\r
-        for(TreeModelListener listener : getTreeModelListeners()){\r
-            listener.treeStructureChanged(event);\r
-        }\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 国リストを得る。\r
-     * @return 国のリスト\r
-     */\r
-    public List<Land> getLandList(){\r
-        return this.unmodList;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param parent {@inheritDoc}\r
-     * @param index {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    public Object getChild(Object parent, int index){\r
-        if(index < 0)                      return null;\r
-        if(index >= getChildCount(parent)) return null;\r
-\r
-        if(parent == ROOT){\r
-            List<Land> list = getLandList();\r
-            int landIndex = index;\r
-            if( ! this.ascending) landIndex = list.size() - index - 1;\r
-            Land land = list.get(landIndex);\r
-            return land;\r
-        }\r
-        if(parent instanceof Land){\r
-            Land land = (Land)parent;\r
-            List<VillageSection> sectionList = this.sectionMap.get(land);\r
-            int sectIndex = index;\r
-            if( ! this.ascending) sectIndex = sectionList.size() - index - 1;\r
-            VillageSection section = sectionList.get(sectIndex);\r
-            return section;\r
-        }\r
-        if(parent instanceof VillageSection){\r
-            VillageSection section = (VillageSection)parent;\r
-            int vilIndex = index;\r
-            if( ! this.ascending){\r
-                vilIndex = section.getVillageCount() - index - 1;\r
-            }\r
-            Village village = section.getVillage(vilIndex);\r
-            return village;\r
-        }\r
-        return null;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param parent {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    public int getChildCount(Object parent){\r
-        if(parent == ROOT){\r
-            return getLandList().size();\r
-        }\r
-        if(parent instanceof Land){\r
-            Land land = (Land)parent;\r
-            List<VillageSection> sectionList = this.sectionMap.get(land);\r
-            if(sectionList == null) return 0;\r
-            return sectionList.size();\r
-        }\r
-        if(parent instanceof VillageSection){\r
-            VillageSection section = (VillageSection)parent;\r
-            return section.getVillageCount();\r
-        }\r
-        return 0;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param parent {@inheritDoc}\r
-     * @param child {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    public int getIndexOfChild(Object parent, Object child){\r
-        if(child == null) return -1;\r
-        if(parent == ROOT){\r
-            List<Land> list = getLandList();\r
-            int index = list.indexOf(child);\r
-            if( ! this.ascending) index = list.size() - index - 1;\r
-            return index;\r
-        }\r
-        if(parent instanceof Land){\r
-            Land land = (Land)parent;\r
-            List<VillageSection> sectionList = this.sectionMap.get(land);\r
-            int index = sectionList.indexOf(child);\r
-            if( ! this.ascending) index = sectionList.size() - index - 1;\r
-            return index;\r
-        }\r
-        if(parent instanceof VillageSection){\r
-            VillageSection section = (VillageSection)parent;\r
-            int index = section.getIndexOfVillage(child);\r
-            if( ! this.ascending){\r
-                index = section.getVillageCount() - index - 1;\r
-            }\r
-            return index;\r
-        }\r
-        return -1;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    public Object getRoot(){\r
-        return ROOT;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param node {@inheritDoc}\r
-     * @return {@inheritDoc}\r
-     */\r
-    public boolean isLeaf(Object node){\r
-        if(node == ROOT)                   return false;\r
-        if(node instanceof Land)           return false;\r
-        if(node instanceof VillageSection) return false;\r
-        if(node instanceof Village)        return true;\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * ※ たぶん使わないので必ず失敗させている。\r
-     * @param path {@inheritDoc}\r
-     * @param newValue {@inheritDoc}\r
-     */\r
-    public void valueForPathChanged(TreePath path, Object newValue){\r
-        throw new UnsupportedOperationException("Not supported yet.");\r
-    }\r
-\r
-}\r
+/*
+ * model of lands for JTree view
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sfjp.jindolf.data;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import jp.sfjp.jindolf.dxchg.XmlUtils;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import org.xml.sax.SAXException;
+
+/**
+ * 国の集合。あらゆるデータモデルの大元。
+ * 国一覧と村一覧を管理。
+ * JTreeのモデルも兼用。
+ */
+public class LandsModel implements TreeModel{ // ComboBoxModelも付けるか?
+
+    private static final String ROOT = "ROOT";
+    private static final int SECTION_INTERVAL = 100;
+
+    private static final Logger LOGGER = Logger.getAnonymousLogger();
+
+
+    private final List<Land> landList = new LinkedList<>();
+    private final List<Land> unmodList =
+            Collections.unmodifiableList(this.landList);
+    private final Map<Land, List<VillageSection>> sectionMap =
+            new HashMap<>();
+    private boolean isLandListLoaded = false;
+
+    private final EventListenerList listeners = new EventListenerList();
+
+    private boolean ascending = false;
+
+    /**
+     * コンストラクタ。
+     * この時点ではまだ国一覧が読み込まれない。
+     */
+    public LandsModel(){
+        super();
+        return;
+    }
+
+    /**
+     * 指定した国の村一覧を更新しイベントを投げる。
+     * @param land 国
+     */
+    public void updateVillageList(Land land){
+        List<VillageSection> sectionList =
+                VillageSection.getSectionList(land, SECTION_INTERVAL);
+        this.sectionMap.put(land, sectionList);
+
+        int[] childIndices = new int[sectionList.size()];
+        for(int ct = 0; ct < childIndices.length; ct++){
+            childIndices[ct] = ct;
+        }
+        Object[] children = sectionList.toArray();
+
+        Object[] path = {ROOT, land};
+        TreePath treePath = new TreePath(path);
+        TreeModelEvent event = new TreeModelEvent(this,
+                                                  treePath,
+                                                  childIndices,
+                                                  children     );
+        fireTreeStructureChanged(event);
+
+        return;
+    }
+
+    /**
+     * 国一覧を読み込む。
+     */
+    // TODO static にできない?
+    public void loadLandList(){
+        if(this.isLandListLoaded) return;
+
+        this.landList.clear();
+
+        List<LandDef> landDefList;
+        try{
+            DocumentBuilder builder = XmlUtils.createDocumentBuilder();
+            landDefList = LandDef.buildLandDefList(builder);
+        }catch(   IOException
+                | SAXException
+                | URISyntaxException
+                | ParserConfigurationException
+                e){
+            LOGGER.log(Level.SEVERE, "failed to load land list", e);
+            return;
+        }
+
+        for(LandDef landDef : landDefList){
+            Land land = new Land(landDef);
+            this.landList.add(land);
+        }
+
+        this.isLandListLoaded = true;
+
+        fireLandListChanged();
+
+        return;
+    }
+
+    /**
+     * ツリー内容が更新された事をリスナーに通知する。
+     */
+    private void fireLandListChanged(){
+        int size = this.landList.size();
+        int[] childIndices = new int[size];
+        for(int ct = 0; ct < size; ct++){
+            int index = ct;
+            childIndices[ct] = index;
+        }
+
+        Object[] children = this.landList.toArray();
+
+        TreePath treePath = new TreePath(ROOT);
+        TreeModelEvent event = new TreeModelEvent(this,
+                                                  treePath,
+                                                  childIndices,
+                                                  children     );
+        fireTreeStructureChanged(event);
+
+        return;
+    }
+
+    /**
+     * ツリーの並び順を設定する。
+     * 場合によってはTreeModelEventが発生する。
+     * @param ascending trueなら昇順
+     */
+    public void setAscending(boolean ascending){
+        if(this.ascending == ascending) return;
+
+        this.ascending = ascending;
+        fireLandListChanged();
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param l {@inheritDoc}
+     */
+    @Override
+    public void addTreeModelListener(TreeModelListener l){
+        this.listeners.add(TreeModelListener.class, l);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param l {@inheritDoc}
+     */
+    @Override
+    public void removeTreeModelListener(TreeModelListener l){
+        this.listeners.remove(TreeModelListener.class, l);
+        return;
+    }
+
+    /**
+     * 登録中のリスナーのリストを得る。
+     * @return リスナーのリスト
+     */
+    private TreeModelListener[] getTreeModelListeners(){
+        return this.listeners.getListeners(TreeModelListener.class);
+    }
+
+    /**
+     * 全リスナーにイベントを送出する。
+     * @param event ツリーイベント
+     */
+    protected void fireTreeStructureChanged(TreeModelEvent event){
+        for(TreeModelListener listener : getTreeModelListeners()){
+            listener.treeStructureChanged(event);
+        }
+        return;
+    }
+
+    /**
+     * 国リストを得る。
+     * @return 国のリスト
+     */
+    public List<Land> getLandList(){
+        return this.unmodList;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param parent {@inheritDoc}
+     * @param index {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Object getChild(Object parent, int index){
+        if(index < 0)                      return null;
+        if(index >= getChildCount(parent)) return null;
+
+        if(parent == ROOT){
+            List<Land> list = getLandList();
+            int landIndex = index;
+            if( ! this.ascending) landIndex = list.size() - index - 1;
+            Land land = list.get(landIndex);
+            return land;
+        }
+        if(parent instanceof Land){
+            Land land = (Land) parent;
+            List<VillageSection> sectionList = this.sectionMap.get(land);
+            int sectIndex = index;
+            if( ! this.ascending) sectIndex = sectionList.size() - index - 1;
+            VillageSection section = sectionList.get(sectIndex);
+            return section;
+        }
+        if(parent instanceof VillageSection){
+            VillageSection section = (VillageSection) parent;
+            int vilIndex = index;
+            if( ! this.ascending){
+                vilIndex = section.getVillageCount() - index - 1;
+            }
+            Village village = section.getVillage(vilIndex);
+            return village;
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param parent {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getChildCount(Object parent){
+        if(parent == ROOT){
+            return getLandList().size();
+        }
+        if(parent instanceof Land){
+            Land land = (Land) parent;
+            List<VillageSection> sectionList = this.sectionMap.get(land);
+            if(sectionList == null) return 0;
+            return sectionList.size();
+        }
+        if(parent instanceof VillageSection){
+            VillageSection section = (VillageSection) parent;
+            return section.getVillageCount();
+        }
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param parent {@inheritDoc}
+     * @param child {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getIndexOfChild(Object parent, Object child){
+        if(child == null) return -1;
+        if(parent == ROOT){
+            List<Land> list = getLandList();
+            int index = list.indexOf(child);
+            if( ! this.ascending) index = list.size() - index - 1;
+            return index;
+        }
+        if(parent instanceof Land){
+            Land land = (Land) parent;
+            List<VillageSection> sectionList = this.sectionMap.get(land);
+            int index = sectionList.indexOf(child);
+            if( ! this.ascending) index = sectionList.size() - index - 1;
+            return index;
+        }
+        if(parent instanceof VillageSection){
+            VillageSection section = (VillageSection) parent;
+            int index = section.getIndexOfVillage(child);
+            if( ! this.ascending){
+                index = section.getVillageCount() - index - 1;
+            }
+            return index;
+        }
+        return -1;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public Object getRoot(){
+        return ROOT;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param node {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public boolean isLeaf(Object node){
+        if(node == ROOT)                   return false;
+        if(node instanceof Land)           return false;
+        if(node instanceof VillageSection) return false;
+        if(node instanceof Village)        return true;
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * ※ たぶん使わないので必ず失敗させている。
+     * @param path {@inheritDoc}
+     * @param newValue {@inheritDoc}
+     */
+    @Override
+    public void valueForPathChanged(TreePath path, Object newValue){
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    /**
+     * 村IDで範囲指定した、村のセクション集合。国-村間の中間ツリー。
+     * @see javax.swing.tree.TreeModel
+     */
+    private static final class VillageSection{
+
+        private final int startID;
+        private final int endID;
+        private final String prefix;
+
+        private final List<Village> villageList = new LinkedList<>();
+
+
+        /**
+         * セクション集合を生成する。
+         * @param land 国
+         * @param startID 開始村ID
+         * @param endID 終了村ID
+         * @throws java.lang.IndexOutOfBoundsException IDの範囲指定が変
+         */
+        private VillageSection(Land land, int startID, int endID)
+                throws IndexOutOfBoundsException{
+            super();
+
+            if(startID < 0 || startID > endID){
+                throw new IndexOutOfBoundsException();
+            }
+
+            this.startID = startID;
+            this.endID = endID;
+            this.prefix = land.getLandDef().getLandPrefix();
+
+            for(Village village : land.getVillageList()){
+                int id = village.getVillageIDNum();
+                if(startID <= id && id <= endID){
+                    this.villageList.add(village);
+                }
+            }
+
+            return;
+        }
+
+
+        /**
+         * 与えられた国の全ての村を、指定されたinterval間隔でセクション化する。
+         * @param land 国
+         * @param interval セクションの間隔
+         * @return セクションのリスト
+         * @throws java.lang.IllegalArgumentException intervalが正でない
+         */
+        private static List<VillageSection> getSectionList(Land land,
+                                                             int interval )
+                throws IllegalArgumentException{
+            if(interval <= 0){
+                throw new IllegalArgumentException();
+            }
+
+            List<Village> villageList = land.getVillageList();
+            Village village1st = villageList.get(0);
+            Village villageLast = villageList.get(villageList.size() - 1);
+
+            int startID = village1st.getVillageIDNum();
+            int endID = villageLast.getVillageIDNum();
+
+            List<VillageSection> result = new LinkedList<>();
+
+            int fixedStart = startID / interval * interval;
+            for(int ct = fixedStart; ct <= endID; ct += interval){
+                VillageSection section =
+                        new VillageSection(land, ct, ct + interval - 1);
+                result.add(section);
+            }
+
+            return Collections.unmodifiableList(result);
+        }
+
+        /**
+         * セクションに含まれる村の総数を返す。
+         * @return 村の総数
+         */
+        private int getVillageCount(){
+            return this.villageList.size();
+        }
+
+        /**
+         * セクションに含まれるindex番目の村を返す。
+         * @param index インデックス
+         * @return index番目の村
+         */
+        private Village getVillage(int index){
+            return this.villageList.get(index);
+        }
+
+        /**
+         * セクションにおける、指定された子(村)のインデックス位置を返す。
+         * @param child 子
+         * @return インデックス位置
+         */
+        private int getIndexOfVillage(Object child){
+            return this.villageList.indexOf(child);
+        }
+
+        /**
+         * セクションの文字列表記。
+         * JTree描画に反映される。
+         * @return 文字列表記
+         */
+        @Override
+        public String toString(){
+            StringBuilder result = new StringBuilder();
+            result.append(this.prefix).append(this.startID);
+            result.append(" ~ ");
+            result.append(this.prefix).append(this.endID);
+            return result.toString();
+        }
+    }
+
+}