class Firewall implements IFirewallService, IOFMessageListener,
IFloodlightModule {

	protected ArrayList<FirewallRule> readRulesFromStorage() {
		ArrayList<FirewallRule> l = new ArrayList<FirewallRule>();

		try {
			Map<String, Object> row;

			// (..., null, null) for no predicate, no ordering
			IResultSet resultSet = storageSource.executeQuery(TABLE_NAME, ColumnNames, null, null);

			// put retrieved rows into FirewallRules
			for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) {
				row = it.next().getRow();
				// now, parse row
				FirewallRule r = new FirewallRule();
				if (!row.containsKey(COLUMN_RULEID) || !row.containsKey(COLUMN_DPID)) {
					logger.error( "skipping entry with missing required 'ruleid' or 'switchid' entry: {}", row);
					return l;
				}
				try {
					r.ruleid = Integer
							.parseInt((String) row.get(COLUMN_RULEID));
					r.dpid = DatapathId.of((String) row.get(COLUMN_DPID));

					for (String key : row.keySet()) {
						if (row.get(key) == null) {
							continue;
						}
						if (key.equals(COLUMN_RULEID) || key.equals(COLUMN_DPID) || key.equals("id")) {
							continue; // already handled
						} else if (key.equals(COLUMN_IN_PORT)) {
							r.in_port = OFPort.of(Integer.parseInt((String) row.get(COLUMN_IN_PORT)));
						} else if (key.equals(COLUMN_DL_SRC)) {
							r.dl_src = MacAddress.of(Long.parseLong((String) row.get(COLUMN_DL_SRC)));
						}  else if (key.equals(COLUMN_DL_DST)) {
							r.dl_dst = MacAddress.of(Long.parseLong((String) row.get(COLUMN_DL_DST)));
						} else if (key.equals(COLUMN_DL_TYPE)) {
							r.dl_type = EthType.of(Integer.parseInt((String) row.get(COLUMN_DL_TYPE)));
						} else if (key.equals(COLUMN_NW_SRC_PREFIX)) {
							r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(IPv4Address.of(Integer.parseInt((String) row.get(COLUMN_NW_SRC_PREFIX))), r.nw_src_prefix_and_mask.getMask());
						} else if (key.equals(COLUMN_NW_SRC_MASKBITS)) {
							r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(r.nw_src_prefix_and_mask.getValue(), IPv4Address.of(Integer.parseInt((String) row.get(COLUMN_NW_SRC_MASKBITS))));
						} else if (key.equals(COLUMN_NW_DST_PREFIX)) {
							r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(IPv4Address.of(Integer.parseInt((String) row.get(COLUMN_NW_DST_PREFIX))), r.nw_dst_prefix_and_mask.getMask());
						} else if (key.equals(COLUMN_NW_DST_MASKBITS)) {
							r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(r.nw_dst_prefix_and_mask.getValue(), IPv4Address.of(Integer.parseInt((String) row.get(COLUMN_NW_DST_MASKBITS))));
						} else if (key.equals(COLUMN_NW_PROTO)) {
							r.nw_proto = IpProtocol.of(Short.parseShort((String) row.get(COLUMN_NW_PROTO)));
						} else if (key.equals(COLUMN_TP_SRC)) {
							r.tp_src = TransportPort.of(Integer.parseInt((String) row.get(COLUMN_TP_SRC)));
						} else if (key.equals(COLUMN_TP_DST)) {
							r.tp_dst = TransportPort.of(Integer.parseInt((String) row.get(COLUMN_TP_DST)));
						} else if (key.equals(COLUMN_WILDCARD_DPID)) {
							r.any_dpid = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DPID));
						} else if (key.equals(COLUMN_WILDCARD_IN_PORT)) {
							r.any_in_port = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_IN_PORT));
						} else if (key.equals(COLUMN_WILDCARD_DL_SRC)) {
							r.any_dl_src = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DL_SRC));
						} else if (key.equals(COLUMN_WILDCARD_DL_DST)) {
							r.any_dl_dst = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DL_DST));
						} else if (key.equals(COLUMN_WILDCARD_DL_TYPE)) {
							r.any_dl_type = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_DL_TYPE));
						} else if (key.equals(COLUMN_WILDCARD_NW_SRC)) {
							r.any_nw_src = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_NW_SRC));
						} else if (key.equals(COLUMN_WILDCARD_NW_DST)) {
							r.any_nw_dst = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_NW_DST));
						} else if (key.equals(COLUMN_WILDCARD_NW_PROTO)) {
							r.any_nw_proto = Boolean.parseBoolean((String) row.get(COLUMN_WILDCARD_NW_PROTO));
						} else if (key.equals(COLUMN_PRIORITY)) {
							r.priority = Integer.parseInt((String) row.get(COLUMN_PRIORITY));
						} else if (key.equals(COLUMN_ACTION)) {
							int tmp = Integer.parseInt((String) row.get(COLUMN_ACTION));
							if (tmp == FirewallRule.FirewallAction.DROP.ordinal()) {
								r.action = FirewallRule.FirewallAction.DROP;
							} else if (tmp == FirewallRule.FirewallAction.ALLOW.ordinal()) {
								r.action = FirewallRule.FirewallAction.ALLOW;
							} else {
								r.action = null;
								logger.error("action not recognized");
							}
						}
					}
				} catch (ClassCastException e) {
					logger.error("skipping rule {} with bad data : " + e.getMessage(), r.ruleid);
				}
				if (r.action != null) {
					l.add(r);
				}
			}
		} catch (StorageException e) {
			logger.error("failed to access storage: {}", e.getMessage());
			// if the table doesn't exist, then wait to populate later via
			// setStorageSource()
		}

		// now, sort the list based on priorities
		Collections.sort(l);

		return l;
	}

}