-/*\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();
+ }
+ }
+
+}