package com.bao.lc.site.s3.bean; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.htmlparser.Parser; import org.htmlparser.filters.NodeClassFilter; import org.htmlparser.tags.InputTag; import org.htmlparser.util.NodeList; import org.htmlparser.util.ParserException; import com.bao.lc.AppConfig; import com.bao.lc.site.s3.TdUtils; import com.bao.lc.util.MiscUtils; public class TrainTicketInfo implements Columnable { private static Log log = LogFactory.getLog(TrainTicketInfo.class); public static final int RAW_FIELD_COUNT = 17; public static final int PARSE_ERROR = -2; public static final int NONE_EXIST = -1; //-- public static final int HAVE_NOT = 0; //无 public static final int HAVE = 1024; //有 private static Map<String, Integer> ticketNumMap = new HashMap<String, Integer>(); static { ticketNumMap.put(AppConfig.getInstance().getPropInternal("td.ticket.num.none"), NONE_EXIST); ticketNumMap.put(AppConfig.getInstance().getPropInternal("td.ticket.num.have_not"), HAVE_NOT); ticketNumMap.put(AppConfig.getInstance().getPropInternal("td.ticket.num.have"), HAVE); } public static final int CAT_STATION_FROM_TO = 0; public static final int CAT_TRAIN_NO = 1; public static final int CAT_TRAIN_CLASS = 2; public static final int CAT_COST_TIME = 3; public static final int CAT_SEAT_CLASS = 4; public static final int BUSINESS_SEAT = 0; // 商务座 public static final int SPECIAL_SEAT = 1; // 特等座 public static final int FIRST_CLASS_SEAT = 2; // 一等座 public static final int SECOND_CLASS_SEAT = 3; //二等座 public static final int ADVANCED_SOFT_SLEEPER = 4;// 高级软卧 public static final int SOFT_SLEEPER = 5; //软卧 public static final int HARD_SLEEPER = 6; //硬卧 public static final int SOFT_SEAT = 7; //软座 public static final int HARD_SEAT = 8; // 硬座 public static final int NONE_SEAT = 9; // 无座 public static final int OTHER_SEAT = 10; // 其他 public static final int SEAT_TYPE_COUNT = (OTHER_SEAT - BUSINESS_SEAT + 1); /*Raw informations*/ private String index; //序号 private String trainNo; // 车次 //查询区间 private String fromStation; // 发站 private String toStation; //到站 private String timeCost; //历时 private int[] seats; //购票 public String bookButton; /*Distilled informations*/ private String _bookButtonParameter = null; private String _station_train_code = null; //车次 private String _from_station_name = null; //发站 private String _to_station_name = null; //到站 private String _start_time = null; //发车时间 private String _end_time = null; //到站时间 public TrainTicketInfo(String[] args, int startIndex) { if(args.length < startIndex + RAW_FIELD_COUNT) { throw new IllegalArgumentException("No enough fields. args.length=" + args.length); } this.index = args[startIndex++]; this.trainNo = args[startIndex++]; this.fromStation = args[startIndex++]; this.toStation = args[startIndex++]; this.timeCost = args[startIndex++]; this.seats = new int[SEAT_TYPE_COUNT]; for(int i = BUSINESS_SEAT; i <= OTHER_SEAT; i++) { this.seats[i] = parseSeat(args[startIndex++]); } this.bookButton = args[startIndex++]; //distilled distill(); } private void distill() { parseGeneralInfo(); parseBookButtonParameter(); parseGeneralInfoByBookParameter(); } private int parseSeat(String seatContent) { String htmlContent = StringUtils.substringBetween(seatContent, ">", "</"); if(htmlContent != null) { seatContent = htmlContent; } seatContent = seatContent.trim(); int seatNum = 0; if(ticketNumMap.containsKey(seatContent)) { seatNum = ticketNumMap.get(seatContent); } else { try { seatNum = Integer.parseInt(seatContent); } catch(NumberFormatException e) { log.error("Can't convert seatContent [" + seatContent + "] to number."); seatNum = PARSE_ERROR; } } return seatNum; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("index=").append(index); sb.append(", TrainNo=").append(getStationTrainCode()).append(": "); sb.append(getFromStationName()).append("(").append(getStartTime()).append(")"); sb.append(" --> "); sb.append(getToStationName()).append("(").append(getEndTime()).append(")"); sb.append(", Seats={"); for(int i = BUSINESS_SEAT; i <= OTHER_SEAT; i++) { if(this.seats[i] > 0) { sb.append(TdUtils.getSeatClassName(i)).append("=").append(this.seats[i]).append(" "); } } sb.append("}"); return sb.toString(); } public String getBookButtonParameter() { return this._bookButtonParameter; } private void parseGeneralInfo() { this._station_train_code = MiscUtils.getPlainText(this.trainNo, "UTF-8"); String[] fromInfo = this.fromStation.split("<br>"); this._from_station_name = fromInfo[0].trim(); if(fromInfo.length >= 2) { this._start_time = fromInfo[1].trim(); } String[] toInfo = this.toStation.split("<br>"); this._to_station_name = toInfo[0].trim(); if(toInfo.length >= 2) { this._end_time = toInfo[1].trim(); } } private void parseBookButtonParameter() { Parser parser = MiscUtils.createParser(bookButton, "UTF-8", log); NodeList nodeList = null; try { nodeList = parser.parse(new NodeClassFilter(InputTag.class)); } catch(ParserException e) { log.error("parseBookButtonParameter failed.", e); return; } if(nodeList == null || nodeList.size() <= 0) { log.error("parseBookButtonParameter result nodeList is empty."); return; } InputTag input = (InputTag)nodeList.elementAt(0); String onclick = input.getAttribute("onclick"); if(onclick == null || onclick.isEmpty()) { log.error("parseBookButtonParameter error: onclick attribute doesn't exist."); return; } String parameter = StringUtils.substringBetween(onclick, "'", "'"); if(parameter == null || parameter.isEmpty()) { log.error("parseBookButtonParameter error: onclick parameter is empty."); return; } this._bookButtonParameter = parameter; log.info("index=" + index + ", bookButtonParameter=" + _bookButtonParameter); } private void parseGeneralInfoByBookParameter() { if(this._bookButtonParameter == null) { log.error("bookButtonParameter = null."); return; } String[] bookButtonParams = this._bookButtonParameter.split("#"); //let SubmitOrder#getCurrParamMap to check // String[] trainParams = { "station_train_code", "lishi", "train_start_time", "trainno", // "from_station_telecode", "to_station_telecode", "arrive_time", "from_station_name", // "to_station_name", "ypInfoDetail" }; // if(bookButtonParams.length != trainParams.length) // { // log.error("[parseOtherFields]: Book Button Parameter length is unexpected. bookButtonParams.length=" // + bookButtonParams.length); // return; // } if(bookButtonParams.length < 9) { log.error("[parseOtherFields]: Book Button Parameter length is too short. bookButtonParams.length=" + bookButtonParams.length); return; } _station_train_code = bookButtonParams[0]; _start_time = bookButtonParams[2]; _end_time = bookButtonParams[6]; _from_station_name = bookButtonParams[7]; _to_station_name = bookButtonParams[8]; } public String getTrainClass() { if(this._station_train_code == null || this._station_train_code.isEmpty()) { return null; } char c = this._station_train_code.charAt(0); if(Character.isLetter(c)) { return String.valueOf(c); } return null; } public String getStationTrainCode() { return this._station_train_code; } public String getFromStationName() { return this._from_station_name; } public String getToStationName() { return this._to_station_name; } public String getStartTime() { return this._start_time; } public String getEndTime() { return this._end_time; } @Override public ComparableFilter<TrainTicketInfo, ?> getColumn(int column, Object ... args) { ComparableFilter<TrainTicketInfo, ?> result = null; if(column == CAT_TRAIN_CLASS) { result = new ListElementIndex(getTrainClass(), (List<?>)args[0]); } else if(column == CAT_COST_TIME) { result = new ListFilter(this.timeCost, (List<?>)args[0]); } else if(column == CAT_SEAT_CLASS) { List<Integer> seatClassIndex = (List<Integer>)args[0]; List<Integer> seatClassCount = new ArrayList<Integer>(seatClassIndex.size()); for(int index : seatClassIndex) { seatClassCount.add(this.seats[index]); } return new ListElementCount(seatClassCount, (Integer)args[1]); } return result; } }