package com.onaro.sanscreen.client.view.task.actions.inventory; import com.onaro.sanscreen.task.interfaces.data.inventory.*; import com.onaro.sanscreen.types.ObjectType; import com.onaro.sanscreen.client.view.task.actions.ParamEditorFactory; import com.onaro.sanscreen.client.view.task.Inventory; import com.onaro.sanscreen.client.error.CentralErrorHandler; import com.onaro.util.ListenerList; import com.onaro.util.jfc.TreeModelEvents; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.event.TreeModelListener; import java.util.*; public class InventoryTreeModel implements TreeModel { private ListNode[] root; private ListenerList treeModelListener = new ListenerList(); private Map> storageToVolumes = new HashMap>(); /** * Keeps track of the lists that were sorted to avoid duplicate sorting. */ private Set> sortedLists = new HashSet>(); protected final static DeviceByWwnComparator wwnComparator = new DeviceByWwnComparator(); public final static DeviceByAliasComparator aliasComparator = new DeviceByAliasComparator(); protected final static PortComparator portComparator = new PortComparator(); public final static VolumeComparator volumeComparator = new VolumeComparator(); protected final static VolumeMapComparator VOLUMEMAPPINGCOMPARATOR = new VolumeMapComparator(); protected final static VolumeMaskComparator VOLUMEMASKINGCOMPARATOR = new VolumeMaskComparator(); protected final static ZoneComparator zoneComparator = new ZoneComparator(); protected final static ZoneConfigComparator zoneConfigComparator = new ZoneConfigComparator(); private ZoneMemberComparator zoneMemberComparator = new ZoneMemberComparator(); private ListNode fabricsListNode; private ListNode hostsListNode; private ListNode switchesListNode; private ListNode genericsListNode; private ListNode storageListNode; private ListNode tapesListNode; private final Inventory inventory; public InventoryTreeModel(final Inventory inventory) { this.inventory = inventory; this.fabricsListNode = new ListNode(ParamEditorFactory.resources.getString("list.fabrics")) { //$NON-NLS-1$ List loadList() throws InventoryException { List devices = inventory.getFabrics(); Collections.sort(devices, wwnComparator); return devices; } }; this.hostsListNode = new ListNode(ParamEditorFactory.resources.getString("list.hosts")) { //$NON-NLS-1$ List loadList() throws InventoryException { List devices = inventory.getHosts(); Collections.sort(devices, aliasComparator); return devices; } }; this.switchesListNode = new ListNode(ParamEditorFactory.resources.getString("list.switches")) { //$NON-NLS-1$ List loadList() throws InventoryException { List devices = inventory.getSwitches(); Collections.sort(devices, aliasComparator); return devices; } }; this.genericsListNode = new ListNode(ParamEditorFactory.resources.getString("list.generics")) { //$NON-NLS-1$ List loadList() throws InventoryException { List devices = inventory.getGenerics(); Collections.sort(devices, aliasComparator); return devices; } }; this.storageListNode = new ListNode(ParamEditorFactory.resources.getString("list.storages")) { //$NON-NLS-1$ List loadList() throws InventoryException { List devices = inventory.getStorages(); Collections.sort(devices, aliasComparator); return devices; } }; this.tapesListNode = new ListNode(ParamEditorFactory.resources.getString("list.tapes")) { //$NON-NLS-1$ List loadList() throws InventoryException { List devices = inventory.getTapes(); Collections.sort(devices, aliasComparator); return devices; } }; root = new ListNode[]{fabricsListNode, hostsListNode, switchesListNode, genericsListNode, storageListNode, tapesListNode, }; } public ListNode getFabricsListNode() { return fabricsListNode; } public ListNode getGenericsListNode() { return genericsListNode; } public ListNode getHostsListNode() { return hostsListNode; } public ListNode getStorageListNode() { return storageListNode; } public ListNode getSwitchesListNode() { return switchesListNode; } public ListNode getTapesListNode() { return tapesListNode; } public Object getRoot() { return root; } public Object getChild(Object parent, int index) { try { if (parent == root) { return root[index]; } else if (parent instanceof ListNode) { return ((ListNode) parent).getChild(index); } else if (parent instanceof Device) { return getDeviceChild((Device) parent, index); } else if (parent instanceof Zone) { return getZoneMembers((Zone) parent).get(index); } else if (parent instanceof Volume) { return getVolumeMaskingAndMappingChild((Volume) parent, index); } } catch (InventoryException e) { CentralErrorHandler.handle("Failed getting inventory data from the server", this, e); //$NON-NLS-1$ } return null; } public int getChildCount(Object parent) { try { if (parent == root) { return root.length; } else if (parent instanceof ListNode) { return ((ListNode) parent).getChildCount(); } else if (parent instanceof Device) { return getDeviceChildCount((Device) parent); } else if (parent instanceof Zone) { return getZoneMembers((Zone) parent).size(); } else if (parent instanceof Volume) { return getVolumeMaskingAndMappingCount((Volume) parent); } } catch (InventoryException e) { CentralErrorHandler.handle("Failed getting inventory data from the server", this, e); //$NON-NLS-1$ } return 0; } public boolean isLeaf(Object node) { return node instanceof Port || node instanceof Volume || node instanceof VolumeMask || node instanceof VolumeMap || node instanceof ZoneMember; } /** * Ignored because the tree is not editable. * * @param path * @param newValue */ public void valueForPathChanged(TreePath path, Object newValue) { } public int getIndexOfChild(Object parent, Object child) { if (parent == null || child == null) { return -1; } try { if (parent == root) { for (int i = 0; i < root.length; ++i) { if (root[i] == parent) return i; } return root.length; } else if (parent instanceof ListNode) { return ((ListNode) parent).indexOf(child); } else if (parent instanceof Device) { return getDeviceIndexOfChild((Device) parent, child); } else if (parent instanceof Zone) { return getZoneMembers((Zone) parent).indexOf(child); } else if (parent instanceof Volume) { return getVolumeMaskingAndMappingIndexOfChild((Volume) parent, child); } } catch (InventoryException e) { CentralErrorHandler.handle("Failed getting inventory data from the server", this, e); //$NON-NLS-1$ } return -1; } /** * Adds a listener for the {@link javax.swing.event.TreeModelEvent} posted after the tree changes. * * @param l the listener to add */ public void addTreeModelListener(TreeModelListener l) { treeModelListener.addListener(TreeModelListener.class, l); } /** * Removes a listener previously added with {@link #addTreeModelListener}. * * @param l the listener to remove */ public void removeTreeModelListener(TreeModelListener l) { treeModelListener.removeListener(TreeModelListener.class, l); } public void fireStructureChanged() { treeModelListener.fireEvent(TreeModelListener.class, new TreeModelEvents(this, 0, new TreePath(getRoot()), null, null, //eventId)); TreeModelEvents.TREE_STRUCTURE_CHANGED_EVENT)); } private Object getDeviceChild(final Device device, int index) throws InventoryException { ObjectType type = device.getType(); if (ObjectType.isNodeContainer(type)) { /** Gets the children of a storage device */ if (ObjectType.STORAGE.equals(type)) { if (index == 0) { /** A storage's first child is the list of Volumes */ ListNode listNode = storageToVolumes.get(device.getId()); if (listNode == null) { listNode = new ListNode(ParamEditorFactory.resources.getString("list.volumes")) { //$NON-NLS-1$ List loadList() throws InventoryException { List volumes = inventory.getVolumes(device.getId()); Collections.sort(volumes, volumeComparator); return volumes; } }; storageToVolumes.put(device.getId(), listNode); } return listNode; } else { /** Next are the storage's controllers */ List childDevices = inventory.getChilds(device.getId()); if (!sortedLists.contains(childDevices)) { Collections.sort(childDevices, wwnComparator); sortedLists.add(childDevices); } return childDevices.get(index - 1); } } /** Any other device, list the adapters/controllers of host or tape */ List childDevices = inventory.getChilds(device.getId()); if (!sortedLists.contains(childDevices)) { Collections.sort(childDevices, wwnComparator); sortedLists.add(childDevices); } return childDevices.get(index); } else if (ObjectType.isPortContainer(type)) { /** * The chidlren of a switch, genreric, adapter or controller are ports. */ List ports = inventory.getPorts(device.getId()); if (index < ports.size()) { if (!sortedLists.contains(ports)) { Collections.sort(ports, portComparator); sortedLists.add(ports); } return ports.get(index); } } else if (ObjectType.FABRIC.equals(type)) { List zones = inventory.getActiveZones(device.getId()); if (index < zones.size()) { /** The first children of a fabric are the zones*/ if (!sortedLists.contains(zones)) { Collections.sort(zones, zoneComparator); sortedLists.add(zones); } return zones.get(index); } else { /** After the zones come the configurations */ List zoneConfigs = inventory.getInactiveZoneConfigs(device.getId()); if (!sortedLists.contains(zoneConfigs)) { Collections.sort(zoneConfigs, zoneConfigComparator); sortedLists.add(zoneConfigs); } return zoneConfigs.get(index - zones.size()); } } throw new IllegalArgumentException("Index " + index + " is out of bounds for device " + device); //$NON-NLS-1$ //$NON-NLS-2$ } private int getDeviceChildCount(Device device) throws InventoryException { ObjectType type = device.getType(); if (ObjectType.STORAGE.equals(type)) { return inventory.getChilds(device.getId()).size() + 1; } else if (ObjectType.isNodeContainer(type)) { return inventory.getChilds(device.getId()).size(); } else if (ObjectType.isPortContainer(type)) { return inventory.getPorts(device.getId()).size(); } else if (ObjectType.FABRIC.equals(type)) { return inventory.getActiveZones(device.getId()).size() + inventory.getInactiveZoneConfigs(device.getId()).size(); } return 0; } private int getDeviceIndexOfChild(Device parent, Object child) throws InventoryException { ObjectType type = parent.getType(); if (ObjectType.isNodeContainer(type)) { if (ObjectType.STORAGE.equals(type)) { // if (inventory.getVolumes(parent.getId()) == child) // return 0; // else return inventory.getChilds(parent.getId()).indexOf(child) + 1; } return inventory.getChilds(parent.getId()).indexOf(child); } else if (ObjectType.isPortContainer(type)) { return inventory.getPorts(parent.getId()).indexOf(child); } else if (ObjectType.FABRIC.equals(type)) { if (child instanceof Zone) return inventory.getActiveZones(parent.getId()).indexOf(child); else if (child instanceof ZoneConfig) return inventory.getActiveZones(parent.getId()).indexOf(child) + inventory.getInactiveZoneConfigs(parent.getId()).size(); } return -1; } private List getZoneMembers(Zone zone) throws InventoryException { List members = inventory.getZoneMembers(zone.getId()); if (!sortedLists.contains(members)) { Collections.sort(members, zoneMemberComparator); sortedLists.add(members); } return members; } public int getVolumeMaskingAndMappingCount(Volume volume) throws InventoryException { return inventory.getVolumeMaps(volume.getId()).size() + inventory.getVolumeMasks(volume.getId()).size(); } public Object getVolumeMaskingAndMappingChild(Volume volume, int index) throws InventoryException { List mapping = inventory.getVolumeMaps(volume.getId()); if (!sortedLists.contains(mapping)) { Collections.sort(mapping, VOLUMEMAPPINGCOMPARATOR); sortedLists.add(mapping); } if (index < mapping.size()) return mapping.get(index); List masking = inventory.getVolumeMasks(volume.getId()); if (!sortedLists.contains(masking)) { Collections.sort(masking, VOLUMEMASKINGCOMPARATOR); sortedLists.add(masking); } return masking.get(index - mapping.size()); } public int getVolumeMaskingAndMappingIndexOfChild(Volume volume, Object child) throws InventoryException { List mapping = inventory.getVolumeMaps(volume.getId()); if (!sortedLists.contains(mapping)) { Collections.sort(mapping, VOLUMEMAPPINGCOMPARATOR); sortedLists.add(mapping); } int index = mapping.indexOf(child); if (index >= 0) return index; List masking = inventory.getVolumeMasks(volume.getId()); if (!sortedLists.contains(masking)) { Collections.sort(masking, VOLUMEMASKINGCOMPARATOR); sortedLists.add(masking); } return masking.indexOf(child) + mapping.size(); } public Object getVolumeMappingChild(Volume volume, int index) throws InventoryException { List mapping = inventory.getVolumeMaps(volume.getId()); if (!sortedLists.contains(mapping)) { Collections.sort(mapping, VOLUMEMAPPINGCOMPARATOR); sortedLists.add(mapping); } return mapping.get(index); } public int getVolumeMappingIndexOfChild(Volume volume, Object child) throws InventoryException { List mapping = inventory.getVolumeMaps(volume.getId()); if (!sortedLists.contains(mapping)) { Collections.sort(mapping, VOLUMEMAPPINGCOMPARATOR); sortedLists.add(mapping); } return mapping.indexOf(child); } public Object getVolumeMaskingChild(Volume volume, int index) throws InventoryException { List masking = inventory.getVolumeMasks(volume.getId()); if (!sortedLists.contains(masking)) { Collections.sort(masking, VOLUMEMASKINGCOMPARATOR); sortedLists.add(masking); } return masking.get(index); } public int getVolumeMaskingIndexOfChild(Volume volume, Object child) throws InventoryException { List masking = inventory.getVolumeMasks(volume.getId()); if (!sortedLists.contains(masking)) { Collections.sort(masking, VOLUMEMASKINGCOMPARATOR); sortedLists.add(masking); } return masking.indexOf(child); } public Inventory getInventory() { return inventory; } private static int compareStrings(String s1, String s2) { if (s1 == s2) return 0; if (s1 == null) return -1; //s2 cannot be null if s1==null if (s2 == null) return 1; //s1 cannot be null if s2==null return s1.compareToIgnoreCase(s2); } static class DeviceByWwnComparator implements Comparator { public int compare(Device d1, Device d2) { int cmp = compareStrings(d1.getWwn(), d2.getWwn()); if (cmp == 0) { cmp = d1.getId().compareTo(d2.getId()); } return cmp; } } static class DeviceByAliasComparator implements Comparator { public int compare(Device d1, Device d2) { int cmp = compareStrings(d1.getAlias(), d2.getAlias()); if (cmp == 0) { cmp = d1.getId().compareTo(d2.getId()); } return cmp; } } static class PortComparator implements Comparator { public int compare(Port p1, Port p2) { int cmp = p1.getBlade() - p2.getBlade(); if (cmp == 0) { cmp = p1.getNumber() - p2.getNumber(); } if (cmp == 0) { cmp = compareStrings(p1.getName(), p2.getName()); } if (cmp == 0) { cmp = compareStrings(p1.getWwn(), p2.getWwn()); } if (cmp == 0) { cmp = p1.getId().compareTo(p2.getId()); } return cmp; } } static class VolumeComparator implements Comparator { public int compare(Volume v1, Volume v2) { try { long long1 = Long.parseLong(v1.getName(), 16); long long2 = Long.parseLong(v2.getName(), 16); return (long1 < long2 ? -1 : (long1 == long2 ? 0 : 1)); } catch (NumberFormatException e) { // failed to compare as numbers, try as strings } int cmp = compareStrings(v1.getName(), v2.getName()); if (cmp != 0) return cmp; cmp = v1.getId().compareTo(v2.getId()); if (cmp != 0) return cmp; return cmp; } } static class ZoneComparator implements Comparator { public int compare(Zone z1, Zone z2) { int cmp = compareStrings(z1.getName(), z2.getName()); if (cmp == 0) { cmp = z1.getId().compareTo(z2.getId()); } return cmp; } } class ZoneMemberComparator implements Comparator { public int compare(ZoneMember zm1, ZoneMember zm2) { int cmp; try { cmp = zoneComparator.compare(getInventory().getZone(zm1.getZoneId()), getInventory().getZone(zm2.getZoneId())); if (cmp != 0) return cmp; } catch (InventoryException e) { CentralErrorHandler.handle("Failed to get zone from zone member", e); //$NON-NLS-1$ return 0; } cmp = zm1.getType().getTypeId() - zm2.getType().getTypeId(); if (cmp != 0) return cmp; cmp = compareStrings(zm1.getWwn(), zm2.getWwn()); if (cmp != 0) return cmp; cmp = zm1.getDeviceId().compareTo(zm2.getDeviceId()); if (cmp != 0) return cmp; cmp = zm1.getPortId().compareTo(zm2.getPortId()); if (cmp != 0) return cmp; cmp = zm1.getId().compareTo(zm2.getId()); return cmp; } } static class ZoneConfigComparator implements Comparator { public int compare(ZoneConfig z1, ZoneConfig z2) { int cmp = compareStrings(z1.getName(), z2.getName()); if (cmp == 0) { cmp = z1.getId().compareTo(z2.getId()); } return cmp; } } static class VolumeMapComparator implements Comparator { public int compare(VolumeMap map1, VolumeMap map2) { int cmp = compareStrings(map1.getVolumeName(), map2.getVolumeName()); if (cmp != 0) return cmp; cmp = compareStrings(map1.getStorageAlias(), map2.getStorageAlias()); if (cmp != 0) return cmp; cmp = compareStrings(map1.getStoragePortName(), map2.getStoragePortName()); if (cmp != 0) return cmp; cmp = compareStrings(map1.getStoragePortWwn(), map2.getStoragePortWwn()); if (cmp != 0) return cmp; cmp = compareStrings(map1.getLun(), map2.getLun()); if (cmp != 0) return cmp; return cmp; } } static class VolumeMaskComparator implements Comparator { public int compare(VolumeMask mask1, VolumeMask mask2) { int cmp = compareObjects(mask1.getInitiatorRootType(), mask2.getInitiatorRootType()); if (cmp != 0) return cmp; cmp = compareStrings(mask1.getInitiatorRootAlias(), mask2.getInitiatorRootAlias()); if (cmp != 0) return cmp; String type1 = ObjectType.PORT.equals(mask1.getInitiatorRootType()) ? "port" : "node"; //$NON-NLS-1$ //$NON-NLS-2$ String type2 = ObjectType.PORT.equals(mask2.getInitiatorRootType()) ? "port" : "node"; //$NON-NLS-1$ //$NON-NLS-2$ cmp = compareStrings(type1, type2); if (cmp != 0) return cmp; cmp = compareStrings(mask1.getInitiatorWwn(), mask2.getInitiatorWwn()); if (cmp != 0) return cmp; String storagePortDesc1 = mask1.getStoragePortName() != null ? mask1.getStoragePortName() : mask1.getStoragePortWwn(); String storagePortDesc2 = mask2.getStoragePortName() != null ? mask2.getStoragePortName() : mask2.getStoragePortWwn(); cmp = compareStrings(storagePortDesc1, storagePortDesc2); if (cmp != 0) return cmp; return cmp; } } /** * compares two objects using with string comparison using their toString() * * @param o1 * @param o2 * @return 0 for equal, -1/1 when o1 or o2 is larger, respectively */ private static int compareObjects(Object o1, Object o2) { if (o1 == o2) return 0; if (o1 == null) return -1; //o2 cannot be null if o1==null if (o2 == null) return 1; //o1 cannot be null if o2==null return compareStrings(o1.toString(), o2.toString()); } public static abstract class ListNode { protected List list = null; private String type; public ListNode(String type) { this.type = type; } public int getChildCount() throws InventoryException { return getList().size(); } public Object getChild(int index) throws InventoryException { return getList().get(index); } public int indexOf(Object child) throws InventoryException { return getList().indexOf(child); } public String toString() { return type; } public List getList() throws InventoryException { if (list == null) list = loadList(); return list; } abstract List loadList() throws InventoryException; public String getType() { return type; } } public static class SimpleListNode extends ListNode { public SimpleListNode(String type, List list) { super(type); this.list = list; } public SimpleListNode(String type, List list, Comparator comparator) { this(type, list); Collections.sort(list, comparator); } List loadList() throws InventoryException { return null; } } }