Java tutorial
/* * Distributable under LGPL v3 license. * See terms of license at https://github.com/Yunfeng/schotel/blob/master/LICENSE */ package cn.buk.api.service; import cn.buk.api.dto.hotel.*; import cn.buk.api.dto.hotel.DateRange; import cn.buk.api.dto.hotel.HotelInfo; import cn.buk.api.dto.hotel.HotelRatePlan; import cn.buk.api.util.ConvertUtil; import cn.buk.hotel.dao.CityDao; import cn.buk.hotel.dao.HotelDao; import cn.buk.hotel.dto.DocumentDto; import cn.buk.hotel.dto.HotelAvailResult; import cn.buk.hotel.entity.*; import cn.buk.hotel.entity.Zone; import cn.buk.qms.AppConfig; import cn.buk.qms.util.PropertiesUtil; import cn.buk.util.DateUtil; import com.ctrip.openapi.java.base.HttpAccessAdapter; import com.ctrip.openapi.java.utils.ConfigData; import com.ctrip.openapi.java.utils.SignatureUtils; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStreamException; import com.thoughtworks.xstream.mapper.MapperWrapper; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import org.apache.log4j.Logger; import org.dom4j.*; import org.dom4j.io.DocumentResult; import org.dom4j.io.SAXReader; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.File; import java.io.StringReader; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.SocketAddress; import java.util.*; import java.util.concurrent.*; /** * User: yfdai * Date: 14-9-18 * Time: ?2:41 */ public class CtripHotelServiceImpl implements CtripHotelService { private static final Logger logger = Logger.getLogger(CtripHotelServiceImpl.class); private boolean serviceStopped = false; private final String allianceId; private final String sid; private final String secretKey; /** * hotelCacheChange,??); */ private final int intervalCacheChange; /** * ? */ private final int maxDaysOfHotelRate; private static final ExecutorService hotelDetailDaoExecutor = Executors.newFixedThreadPool(2); private static final ExecutorService hotelCacheChangeDaoExecutor = Executors.newFixedThreadPool(2); private static final ExecutorService hotelRatePlanDaoExecutor = Executors.newFixedThreadPool(2); private static final ExecutorService hotelCacheChangeDetailExecutor = Executors.newFixedThreadPool(2); public CtripHotelServiceImpl(String allianceId, String sid, String secretKey, int intervalCacheChange, int maxDaysOfHotelRate) { this.allianceId = allianceId; this.sid = sid; this.secretKey = secretKey; this.intervalCacheChange = intervalCacheChange; this.maxDaysOfHotelRate = maxDaysOfHotelRate; } // ?50 private final int MAX_HOTEL_DETAIL_QUEUE = 50; private final BlockingQueue<DocumentDto> hotelDetailQueue = new LinkedBlockingQueue<DocumentDto>( MAX_HOTEL_DETAIL_QUEUE); private final BlockingQueue<DocumentDto> hotelCacheChangeQueue = new LinkedBlockingQueue<DocumentDto>(100); private final BlockingQueue<HotelRatePlanRequestDto> ratePlanRequestQueue = new LinkedBlockingQueue<HotelRatePlanRequestDto>( 100); private final BlockingQueue<DocumentDto> ratePlanQueue = new LinkedBlockingQueue<DocumentDto>(20); private static final CacheManager cacheManager = CacheManager.getInstance(); private CityDao cityDao; private HotelDao hotelDao; /** * ??????? */ private int hotelCountPerRequestHotelDetail; private static Cache getCache() { Cache cache = cacheManager.getCache("openApiCache"); if (cache == null) { cacheManager.addCache("openApiCache"); cache = cacheManager.getCache("openApiCache"); } return cache; } private static String execApiRequest(String requestContent, String urlString, String paraName) { Proxy proxy = null; String proxyUsed = (String) PropertiesUtil.pps.get(AppConfig.PROXY_USED); if (proxyUsed.equalsIgnoreCase("1")) { String proxyHost = (String) PropertiesUtil.pps.get(AppConfig.PROXY_HOST); String proxyPort = (String) PropertiesUtil.pps.get(AppConfig.PROXY_PORT); int port = Integer.parseInt(proxyPort); SocketAddress address = new InetSocketAddress(proxyHost, port); proxy = new Proxy(Proxy.Type.HTTP, address); } return HttpAccessAdapter.SendRequestToUrl(requestContent, urlString, paraName, proxy); } private Element createRequestHeaderElement(Document document, String requestType) { Element returnElement = document.addElement("Request"); Element element = returnElement.addElement("Header"); element.addAttribute("AllianceID", this.allianceId); element.addAttribute("SID", this.sid); long timestamp = SignatureUtils.GetTimeStamp(); String signature = null; try { signature = SignatureUtils.CalculationSignature(timestamp + "", this.allianceId, this.secretKey, this.sid, requestType); } catch (Exception e) { logger.error(e.getMessage()); } element.addAttribute("TimeStamp", timestamp + ""); element.addAttribute("Signature", signature); element.addAttribute("RequestType", requestType); return returnElement; } private XStream createXStream() { XStream xstream = new XStream() { @Override protected MapperWrapper wrapMapper(MapperWrapper next) { return new MapperWrapper(next) { @Override public boolean shouldSerializeMember(Class definedIn, String fieldName) { //System.out.println("definedIn: " + definedIn.getCanonicalName() + ", Object: " + Object.class.getCanonicalName()); if (definedIn == Object.class) { return false; } // System.out.println(fieldName); return super.shouldSerializeMember(definedIn, fieldName); } }; } }; return xstream; } @Override public String importCityInfo(String filename) { SAXReader reader = new SAXReader(); File file = new File(filename); if (!file.exists()) return "not exist."; Document document;// ?XML try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); return "error"; } List flightDataList = document.selectNodes("//CityDetails/*"); List<City> cities = new ArrayList<City>(); String temp; for (Iterator it = flightDataList.iterator(); it.hasNext();) { Element fltElement = (Element) it.next(); City city = new City(); cities.add(city); city.setCityCode(fltElement.element("CityCode").getText()); city.setOpenApiId(Integer.parseInt(fltElement.element("City").getText())); city.setCityName(fltElement.element("CityName").getText()); city.setCityEnglishName(fltElement.elementText("CityEName").trim()); temp = fltElement.elementText("Country").trim(); if (temp.equalsIgnoreCase("1")) city.setCountryCode("CN"); else city.setCountryCode(temp); city.setProvinceId(Integer.parseInt(fltElement.elementText("Province"))); city.setAirport(fltElement.element("Airport").getText()); } int count = 0; for (City city : cities) { if (city.getCityCode() == null || city.getCityCode().trim().length() == 0) continue; if (cityDao.create(city) == 1) count++; } return "create " + count + " record(s)."; } @Override public String importDistrictInfo(String filename) { SAXReader reader = new SAXReader(); File file = new File(filename); if (!file.exists()) return "not exist."; Document document;// ?XML try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); return "error"; } List list = document.selectNodes("//LocationDetails/*"); List<District> districts = new ArrayList<District>(); for (Iterator it = list.iterator(); it.hasNext();) { Element element = (Element) it.next(); District district = new District(); districts.add(district); district.setName(element.element("LocationName").getText()); district.setEnglishName(element.element("LocationEName").getText()); district.setDistrictId(Integer.parseInt(element.element("Location").getText())); district.setCityId(Integer.parseInt(element.element("LocationCity").getText())); } int count = 0; for (District district : districts) { if (hotelDao.createDistrict(district) == 1) count++; } return "create " + count + " record(s)."; } @Override public String importZoneInfo(String filename) { SAXReader reader = new SAXReader(); File file = new File(filename); if (!file.exists()) return "not exist."; Document document;// ?XML try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); return "error"; } List list = document.selectNodes("//ZoneDetails/*"); List<Zone> zones = new ArrayList<Zone>(); int maxLength = 0; for (Iterator it = list.iterator(); it.hasNext();) { Element element = (Element) it.next(); Zone zone = new Zone(); zones.add(zone); zone.setZoneId(Integer.parseInt(element.element("Zone").getText())); zone.setCityId(Integer.parseInt(element.element("City").getText())); zone.setName(element.element("ZoneName").getText()); zone.setEnglishName(element.element("ZoneEName").getText()); zone.setDescription(element.element("ZoneDesc").getText()); if (zone.getDescription().length() > maxLength) maxLength = zone.getDescription().length(); zone.setMapUse(element.element("ZoneMapuse").getText()); zone.setMapRange(element.element("ZoneRange").getText()); zone.setMapPic(element.element("ZoneMapPic").getText()); } int count = 0; for (Zone zone : zones) { if (hotelDao.createZone(zone) == 1) count++; } System.out.println(maxLength); return "create " + count + " record(s)."; } /** * ?? * @param cityId ? * @return ?? */ @Override public String searchHotel(int cityId) { if (cityId <= 0) return "ER#CITYID IS " + cityId; //headerAPI? Cache cache = getCache(); String cacheKey = ConfigData.OTA_HotelSearch_Request; net.sf.ehcache.Element cacheElement = cache.get(cacheKey); if (cacheElement != null) { Element headerElement = (Element) cacheElement.getValue(); int accessCount = Integer.parseInt(headerElement.attributeValue("AccessCount")); int currentCount = Integer.parseInt(headerElement.attributeValue("CurrentCount")) + 1; logger.info("AccessCount=" + headerElement.attributeValue("AccessCount") + ", CurrentCount=" + headerElement.attributeValue("CurrentCount") + ", ResetTime=" + headerElement.attributeValue("ResetTime")); if (currentCount >= accessCount) { try { logger.info("Sleep for one minute."); Thread.sleep(60000); } catch (InterruptedException ex) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return "ER#Thread.sleep is interrupted."; } } } HotelRequestBody request = new HotelRequestBody(); request.createHotelRequestRQ(); request.getHotelRequestRQ().getCriteria().getCriterion().getHotelRef().setHotelCityCode(cityId); String xml; try { JAXBContext jc = JAXBContext.newInstance(HotelRequestBody.class); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.setProperty(Marshaller.JAXB_ENCODING, "utf-8"); m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); DocumentResult documentResult = new DocumentResult(); m.marshal(request, documentResult); org.dom4j.Document document = documentResult.getDocument(); org.dom4j.Element requestElement = document.getRootElement(); Element ele = requestElement.element("OTA_HotelSearchRQ"); ele.addNamespace("", "http://www.opentravel.org/OTA/2003/05"); org.dom4j.Document doc1 = DocumentHelper.createDocument(); org.dom4j.Element rootElement = createRequestHeaderElement(doc1, ConfigData.OTA_HotelSearch_Request); rootElement.add(requestElement); xml = doc1.asXML(); } catch (JAXBException ex) { logger.error(ex.getMessage()); return "ER"; } if (serviceStopped) return "ER#Service stopped."; String response = execApiRequest(xml, ConfigData.OTA_HotelSearch_Url, "requestXML"); //? SAXReader reader = new SAXReader(); Document document;// ?XML try { document = reader.read(new StringReader(response)); if (serviceStopped) return "ER#Service stopped."; response = processHotelSearchResponse(document); } catch (Exception ex) { logger.error(ex.getMessage()); return "ER"; } return response; } private String processHotelSearchResponse(Document document) { if (document == null) return "ER#Document is null."; Element rootElement = document.getRootElement(); Element headerElement = rootElement.element("Header"); if (!headerElement.attribute("ResultCode").getValue().equalsIgnoreCase("Success")) { logger.error(document.asXML()); return "ER#ResultCode is not Success."; } //header? getCache().put(new net.sf.ehcache.Element(ConfigData.OTA_HotelSearch_Request, headerElement)); List myNodes = document.selectNodes("/Response/HotelResponse/*"); Element eleOtaHotelSearchRS = (Element) myNodes.get(0); XStream xs = createXStream(); xs.alias("Response", HotelSearchResponse.class); xs.processAnnotations(HotelSearchResponse.class); Date date0 = DateUtil.getCurDateTime(); String xml = eleOtaHotelSearchRS.asXML(); HotelSearchResponse response = (HotelSearchResponse) xs.fromXML(xml); int spanMilliSeconds = DateUtil.getPastTime(date0); logger.info("xml -> object: " + spanMilliSeconds + "ms."); int total = response.getHotelInfos().size(); if (total == 0) { //logger.info(xml); if (response.getSuccess() != null) { logger.info("There is no hotel."); return "OK#0 hotel"; } } // return response; String rs; int saveCount = 0; int count = 0; for (HotelInfo hotelInfo : response.getHotelInfos()) { if (this.serviceStopped) break; cn.buk.hotel.entity.HotelInfo hotelInfo1 = ConvertUtil.convertHotelInfo(hotelInfo); int retCode = hotelDao.createHotelInfo(hotelInfo1); if (retCode == 1 || retCode == 2) { saveCount++; } count++; if (count % 100 == 0) { logger.info("Progress: " + count + " / " + total); } } if (saveCount > 0) rs = "OK#" + saveCount + " be saved"; else rs = "ER"; return rs; } private String processHotelDetailResponse(Document document) { if (document == null) return "ER#Document is null."; //????? Map uris = new HashMap(); uris.put("ns", "http://www.opentravel.org/OTA/2003/05"); XPath xpath = document.createXPath("//ns:HotelDescriptiveContents/*"); xpath.setNamespaceURIs(uris); List myNodes = xpath.selectNodes(document); String rs = "HAHA"; if (myNodes.size() == 0) { return "ER#There is nothing."; } logger.debug(Thread.currentThread().getName() + " is on processHotelDetailResponse."); XStream xs = createXStream(); xs.alias("HotelDescriptiveContent", HotelDescriptiveContent.class); xs.processAnnotations(HotelDescriptiveContent.class); String xml; cn.buk.hotel.entity.HotelInfo hotelInfo1; String hotelCode, hotelName; for (Iterator it = myNodes.iterator(); it.hasNext();) { if (serviceStopped) break; Element element = (Element) it.next(); xml = element.asXML(); HotelDescriptiveContent response = (HotelDescriptiveContent) xs.fromXML(xml); hotelCode = response.getHotelCode(); hotelName = response.getHotelName(); hotelInfo1 = hotelDao.getHotelDetailInfoByHotelCode(hotelCode); if (hotelInfo1 == null) { rs = "ER#No hotel is found with hotelCode(" + hotelCode + ")"; logger.warn(rs); return rs; } else { try { if (response.getHotelInfo() != null && response.getHotelInfo().getWhenBuilt() != null) hotelInfo1.setBuildDate(DateUtil.convertToDate(response.getHotelInfo().getWhenBuilt())); } catch (Exception e) { logger.error(xml); logger.error(e.getMessage()); return "ER#WhenBuild: ";// + response.getHotelInfo().getWhenBuilt(); } if (response.getHotelInfo() != null && response.getHotelInfo().getSegmentCategories() != null && response.getHotelInfo().getSegmentCategories().size() > 0) { int consumerLevel = Integer .parseInt(response.getHotelInfo().getSegmentCategories().get(0).getCode()); hotelInfo1.setConsumerLevel(consumerLevel); if (response.getHotelInfo().getSegmentCategories().size() > 1) { logger.warn(hotelCode + "," + hotelName + ": SegmentCategory\'s size is " + response.getHotelInfo().getSegmentCategories().size()); } } if (response.getHotelInfo() != null && response.getHotelInfo().getAddress().getZones() != null) { if (hotelInfo1.getHotelAddressZones() == null) hotelInfo1.setHotelAddressZones(new ArrayList<HotelAddressZone>()); for (cn.buk.api.dto.hotel.Zone zone : response.getHotelInfo().getAddress().getZones()) { if (zone.getZoneCode() > 0) { HotelAddressZone zone1 = new HotelAddressZone(); zone1.setHotelInfo(hotelInfo1); zone1.setZoneCode(zone.getZoneCode()); zone1.setZoneName(zone.getZoneName()); hotelInfo1.addAddressZone(zone1); } } } //SERVICE if (response.getHotelInfo() != null && response.getHotelInfo().getHotelInfoServices() != null) { if (hotelInfo1.getHotelServices() == null) hotelInfo1.setHotelServices(new ArrayList<HotelServiceInfo>()); for (HotelInfoService service : response.getHotelInfo().getHotelInfoServices()) { HotelServiceInfo info = new HotelServiceInfo(); info.setHotelInfo(hotelInfo1); info.setServiceCode(service.getCode()); info.setServiceId(service.getId()); info.setServiceDesc(service.getDescriptiveText()); hotelInfo1.addHotelService(info); } } //GuestRoom??? if (hotelInfo1.getGuestRooms() == null) hotelInfo1.setGuestRooms(new ArrayList<HotelGuestRoom>()); else hotelInfo1.getGuestRooms().clear(); if (response.getFacilityInfo() != null && response.getFacilityInfo().getGuestRooms() != null && response.getFacilityInfo().getGuestRooms().size() > 0) { for (GuestRoom guestRoom : response.getFacilityInfo().getGuestRooms()) { HotelGuestRoom info = new HotelGuestRoom(); info.setHotelInfo(hotelInfo1); //hotelInfo1.getGuestRooms().add(info); info.setRoomTypeName(guestRoom.getRoomTypeName()); RoomType roomType = guestRoom.getRoomType(); info.setRoomTypeCode(roomType.getRoomTypeCod()); info.setStandardOccupancy(roomType.getStandardOccupancy()); info.setSize(roomType.getSize()); info.setFloor(roomType.getFloor()); info.setInvBlockCode(roomType.getInvBlockCode()); info.setBedTypeCode(roomType.getBedTypeCode()); if (roomType.isNonSmoking()) info.setNonSmoking(1); else info.setNonSmoking(0); info.setHasWindow(roomType.getHasWindow()); info.setQuantity(roomType.getQuantity()); info.setRoomSize(roomType.getRoomSize()); if (guestRoom.getAmenities() != null) { for (Amenity amenity : guestRoom.getAmenities()) { HotelGuestRoomAmenity amenity1 = new HotelGuestRoomAmenity(); amenity1.setHotelGuestRoom(info); if (info.getHotelGuestRoomAmenities() == null) info.setHotelGuestRoomAmenities(new ArrayList<HotelGuestRoomAmenity>()); info.getHotelGuestRoomAmenities().add(amenity1); amenity1.setCode(amenity.getRoomAmenityCode()); amenity1.setDescription(amenity.getDescriptiveText()); } } hotelInfo1.addGuestRoom(info); } } //ref points begin if (response.getAreaInfo() != null && response.getAreaInfo().getRefPoints() != null) { if (hotelInfo1.getRefPoints() == null) hotelInfo1.setRefPoints(new ArrayList<HotelRefPoint>()); for (RefPoint point : response.getAreaInfo().getRefPoints()) { HotelRefPoint point1 = new HotelRefPoint(); point1.setHotelInfo(hotelInfo1); hotelInfo1.getRefPoints().add(point1); point1.setDistance(point.getDistance()); point1.setUnitOfMeasureCode(point.getUnitOfMeasureCode()); point1.setName(point.getName()); point1.setRefPointCategoryCode(Integer.parseInt(point.getRefPointCategoryCode())); point1.setRefPointName(point.getRefPointName()); point1.setLatitude(point.getLatitude()); point1.setLongitude(point.getLongitude()); point1.setDescription(point.getDescriptiveText()); } } //ref points end //MultimediaDescriptions begin if (response.getMultimediaDescriptions() != null) { if (hotelInfo1.getMedias() == null) hotelInfo1.setMedias(new ArrayList<HotelMultimediaInfo>()); for (MultimediaDescription md : response.getMultimediaDescriptions()) { if (md.getImageItems() != null) { for (ImageItem item : md.getImageItems()) { HotelMultimediaInfo info = new HotelMultimediaInfo(); info.setHotelInfo(hotelInfo1); hotelInfo1.getMedias().add(info); info.setMediaType("image"); info.setCategory(Integer.parseInt(item.getCategory())); info.setCaption(item.getImageDescription().getCaption()); info.setUrl(item.getImageFormat().getUrl()); } } if (md.getTextItems() != null) { for (TextItem item : md.getTextItems()) { HotelMultimediaInfo info = new HotelMultimediaInfo(); info.setHotelInfo(hotelInfo1); hotelInfo1.getMedias().add(info); info.setMediaType("text"); info.setCategory(Integer.parseInt(item.getCategory())); info.setUrl(item.getUrl()); info.setDescription(item.getDescription()); } } } } //save int retCode = hotelDao.updateHotelInfo(hotelInfo1); if (retCode == 1) { rs = "OK#Save OK"; //cache CacheHotel cacheHotel = hotelDao.getCacheHotel(hotelCode); if (cacheHotel == null) { cacheHotel = new CacheHotel(); cacheHotel.setHotelCode(hotelCode); hotelDao.createCacheHotel(cacheHotel); } else { cacheHotel.setCacheTime(DateUtil.getCurDateTime()); hotelDao.updateCacheHotel(cacheHotel); } } else { logger.info(xml); rs = "ER#Save Status is " + retCode + " for hotelCode[" + hotelCode + "]"; return rs; } } } //end for return rs; } private void executeSaveRatePlanDocument(final Document document, final int periodId, final List<String> hotelCodes) { //????? Map uris = new HashMap(); uris.put("ns", "http://www.opentravel.org/OTA/2003/05"); XPath xpath = document.createXPath("//ns:OTA_HotelRatePlanRS/*"); xpath.setNamespaceURIs(uris); List myNodes = xpath.selectNodes(document); if (myNodes.size() == 0) { logger.warn("myNodes.size() = 0, " + hotelCodes.toString()); return; } if (myNodes.size() == 1) { for (String hotelCode : hotelCodes) { if (periodId == 1) { logger.info("set [" + hotelCode + "]\'s rateplan status is -1."); hotelDao.setHotelRatePlanStatusByHotelCode(hotelCode, -1); hotelDao.setCacheRatePlanDone(hotelCode, periodId); } } logger.info( "myNodes.size() = 1, " + periodId + ", " + hotelCodes.size() + ", " + hotelCodes.toString()); return; } Date baseTime0 = DateUtil.getCurDateTime(); for (Iterator it = myNodes.iterator(); it.hasNext();) { if (serviceStopped) break; Element element = (Element) it.next(); if (!element.getName().equalsIgnoreCase("RatePlans")) continue; XStream xs = createXStream(); xs.alias("RatePlans", HotelRatePlans.class); xs.processAnnotations(HotelRatePlans.class); String xml = element.asXML(); HotelRatePlans response = null; try { response = (HotelRatePlans) xs.fromXML(xml); } catch (XStreamException ex) { //TODO ????? yfdai 2015-1-13 logger.error(ex.getMessage()); } if (response == null) break; String hotelCode = response.getHotelCode(); cn.buk.hotel.entity.HotelInfo hotelInfo1; if (response.getHotelRatePlans() == null || response.getHotelRatePlans().size() == 0) { if (periodId == 1) { logger.info("set [" + hotelCode + "]\'s rateplan status is -1."); hotelDao.setHotelRatePlanStatusByHotelCode(hotelCode, -1); } logger.info("OK#There is no rates for {" + hotelCode + "," + periodId + "}."); } else { cn.buk.hotel.entity.HotelRatePlan hotelRatePlan; hotelInfo1 = hotelDao.getHotelInfoByHotelCode(hotelCode); if (hotelInfo1 == null) { logger.warn("There is not hotel info for [" + hotelCode + "]"); continue; } //?RatePlan? List<cn.buk.hotel.entity.HotelRatePlan> ratePlans = new ArrayList<cn.buk.hotel.entity.HotelRatePlan>(); for (HotelRatePlan dtoRatePlan : response.getHotelRatePlans()) { //if (serviceStopped) break; try { hotelRatePlan = ConvertUtil.convertHotelRatePlan(dtoRatePlan); hotelRatePlan.setHotelInfo(hotelInfo1); ratePlans.add(hotelRatePlan); // int retCode; // Date timeBegin = DateUtil.getCurDateTime(); // retCode = hotelDao.createHotelRatePlan(hotelRatePlan); // int spans = DateUtil.getPastTime(timeBegin); // if (spans> 1000) logger.warn("CreateHotelRatePlan\'s time is " + Integer.toString(spans) + " ms."); // if (retCode != 1 && retCode != 2) { // logger.error(xml); // logger.error("save failed."); // return; // } } catch (Exception ex) { ex.printStackTrace(); logger.error(xml); logger.error(ex.getMessage()); return; } } // end for int retCode; Date timeBegin = DateUtil.getCurDateTime(); retCode = hotelDao.createHotelRatePlans(ratePlans); int spans = DateUtil.getPastTime(timeBegin); if (spans > 1000) logger.warn("CreateHotelRatePlans\'s time is " + Integer.toString(spans) + " ms."); if (retCode != 1 && retCode != 2) { logger.error(xml); logger.error("save failed."); return; } hotelDao.setHotelRatePlanStatusByHotelCode(hotelCode, 1); } //cache if (periodId > 0) hotelDao.setCacheRatePlanDone(hotelCode, periodId); } // end for int spanTotal = DateUtil.getPastTime(baseTime0); logger.debug(String.format("total time : %d ms", spanTotal)); } /** * ?HotelRatePlanResponse * @param document ?? * @return ?? */ private String processHotelRatePlanResponse(final Document document, final int periodId, final List<String> hotelCodes) { if (document == null) return "ER#Document is null."; Element rootElement = document.getRootElement(); Element headerElement = rootElement.element("Header"); if (!headerElement.attribute("ResultCode").getValue().equalsIgnoreCase("Success")) { //logger.error("ER#ResultCode is not Success."); logger.error(document.asXML()); return "ER#ResultCode is not Success."; } DocumentDto documentDto = new DocumentDto(); documentDto.setDocument(document); documentDto.setPeriodId(periodId); for (String hotelCode : hotelCodes) documentDto.getHotelCodes().add(hotelCode); try { logger.debug("Current ratePlanQueue\'s size: " + ratePlanQueue.size()); logger.debug("put hotelCodes\'s size is " + hotelCodes.size()); ratePlanQueue.put(documentDto); hotelRatePlanDaoExecutor.execute(new HotelRatePlanDaoThread()); } catch (InterruptedException e) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return "ER#RatePlanQueue.put is interrupted."; } return "OK#Document has been added to Queue."; } private String processHotelCacheChangeResponse(final Document document) { if (document == null) return "ER#Document is null."; Element rootElement = document.getRootElement(); Element headerElement = rootElement.element("Header"); if (!headerElement.attribute("ResultCode").getValue().equalsIgnoreCase("Success")) { logger.error(document.asXML()); return "ER#ResultCode is not Success."; } //header? getCache().put(new net.sf.ehcache.Element(ConfigData.OTA_HotelCacheChange_Request, headerElement)); DocumentDto documentDto = new DocumentDto(); documentDto.setDocument(document); try { hotelCacheChangeDaoExecutor.execute(new HotelCacheChangeDaoThread()); logger.debug("Current hotelCacheChangeQueue\'s size is " + hotelCacheChangeQueue.size()); hotelCacheChangeQueue.put(documentDto); } catch (InterruptedException e) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return "ER#HotelCacheChangeQueue.put is interrupted."; } return "OK#HotelCacheChange document has been added into queue."; } @Override public String importHotelSearchRS(String filename) { String rs; SAXReader reader = new SAXReader(); logger.info("filename: " + filename); File file = new File(filename); if (!file.exists()) return null; Document document;// ?XML try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); return "error"; } rs = processHotelSearchResponse(document); return rs; } @Override public synchronized String searchHotelDetail(List<String> hotelCodes, boolean returnXml) { if (hotelCodes == null || hotelCodes.size() == 0) return "ER#hotelcodes is null"; //headerAPI? net.sf.ehcache.Element cacheElement = getCache().get(ConfigData.OTA_HotelDetail_Request); if (cacheElement != null) { Element headerElement = (Element) cacheElement.getValue(); int accessCount = Integer.parseInt(headerElement.attributeValue("AccessCount")); int currentCount = Integer.parseInt(headerElement.attributeValue("CurrentCount")) + 1; logger.info(ConfigData.OTA_HotelDetail_Request + " AccessCount=" + headerElement.attributeValue("AccessCount") + ", CurrentCount=" + headerElement.attributeValue("CurrentCount") + ", ResetTime=" + headerElement.attributeValue("ResetTime")); if (currentCount >= accessCount) { try { logger.info("Sleep for one minute."); Thread.sleep(60000); } catch (InterruptedException ex) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return "ER#SearchHotelDetail thread.sleep is interrupted."; } } } if (this.serviceStopped) return "ER#Service stopped."; HotelRequestBody request = new HotelRequestBody(); request.createHotelDetailRequest(); for (String hotelCode : hotelCodes) { if (this.serviceStopped) return "ER#Service stopped."; HotelDescriptiveInfo hotelDescriptiveInfo = new HotelDescriptiveInfo(); hotelDescriptiveInfo.setHotelCode(hotelCode); cn.buk.hotel.entity.HotelInfo hotelInfo = hotelDao.getHotelDetailInfoByHotelCode(hotelCode); if (hotelInfo != null) { //if (hotelInfo.getGuestRooms().size() == 0) { hotelDescriptiveInfo.setHotelInfoFacilityInfo(new HotelInfoFacilityInfo()); hotelDescriptiveInfo.getHotelInfoFacilityInfo().setSendGuestRooms(true); //} if (hotelInfo.getRefPoints().size() == 0) { hotelDescriptiveInfo.setHotelInfoAreaInfo(new HotelInfoAreaInfo()); hotelDescriptiveInfo.getHotelInfoAreaInfo().setSendAttractions(true); hotelDescriptiveInfo.getHotelInfoAreaInfo().setSendRecreations(true); } if (hotelInfo.getMedias().size() == 0) { hotelDescriptiveInfo.setHotelInfoMultimedia(new HotelInfoMultimedia()); hotelDescriptiveInfo.getHotelInfoMultimedia().setSendData(true); } } request.getHotelDetailRequest().getHotelDescriptiveInfos().add(hotelDescriptiveInfo); } String requestXml; try { JAXBContext jc = JAXBContext.newInstance(HotelRequestBody.class); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.setProperty(Marshaller.JAXB_ENCODING, "utf-8"); m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); DocumentResult documentResult = new DocumentResult(); m.marshal(request, documentResult); org.dom4j.Document document = documentResult.getDocument(); org.dom4j.Element requestElement = document.getRootElement(); Element ele = requestElement.element("OTA_HotelDescriptiveInfoRQ"); ele.addNamespace("", "http://www.opentravel.org/OTA/2003/05"); org.dom4j.Document doc1 = DocumentHelper.createDocument(); if (this.serviceStopped) return "ER#Service stopped."; org.dom4j.Element rootElement = createRequestHeaderElement(doc1, ConfigData.OTA_HotelDetail_Request); rootElement.add(requestElement); requestXml = doc1.asXML(); } catch (JAXBException e) { e.printStackTrace(); return "ER#OTA_exception"; } Date date0 = DateUtil.getCurDateTime(); logger.debug(ConfigData.OTA_HotelDetail_Request + ": begin"); logger.debug(requestXml); if (this.serviceStopped) return "ER#Service stopped."; String response = execApiRequest(requestXml, ConfigData.OTA_HotelDetail_Url, "requestXML"); logger.debug(response); int apiElapsedTime = DateUtil.getPastTime(date0); logger.debug(ConfigData.OTA_HotelDetail_Request + ": end, " + apiElapsedTime + "ms"); if (returnXml) return response; //? String rs; SAXReader reader = new SAXReader(); Document document;// ?XML try { document = reader.read(new StringReader(response)); Element headerElement = document.getRootElement().element("Header"); //header? getCache().put(new net.sf.ehcache.Element(ConfigData.OTA_HotelDetail_Request, headerElement)); if (!headerElement.attribute("ResultCode").getValue().equalsIgnoreCase("Success")) { logger.error(requestXml); logger.error(document.asXML()); return "ER#ResultCode is not Success."; } DocumentDto documentDto = new DocumentDto(); documentDto.setDocument(document); if (hotelDetailQueue.size() == MAX_HOTEL_DETAIL_QUEUE) { logger.warn("hotelDetailQueue is full, thread will be blocked here."); } hotelDetailQueue.put(documentDto); hotelDetailDaoExecutor.execute(new HotelDetailDaoThread()); rs = "OK#save to the queue."; } catch (InterruptedException ex) { return "ER#Interrupt occured."; } catch (Exception ex) { logger.error(ex.getMessage()); return "ER#searchHotelDetail"; } return rs; } @Override public String searchHotelRatePlan(final List<String> hotelCodes, final int periodId, final boolean returnXml) { if (hotelCodes == null || hotelCodes.size() == 0) return "ER#hotelcodes is null or empty."; int minDay = (periodId - 1) * 28; int maxDay = periodId * 28; if (maxDay > 90) maxDay = 90; if (minDay >= this.maxDaysOfHotelRate) return "ER#Exceed the max day of rate!"; if (maxDay > this.maxDaysOfHotelRate) maxDay = this.maxDaysOfHotelRate; Date startDate = DateUtil.add(DateUtil.getCurDate(), minDay); Date endDate = DateUtil.add(DateUtil.getCurDate(), maxDay); String response = execSearchHotelRatePlan(hotelCodes, startDate, endDate); if (this.serviceStopped) return "ER#EXIT"; //? String rs; SAXReader reader = new SAXReader(); Document document;// ?XML try { document = reader.read(new StringReader(response)); } catch (DocumentException e) { logger.error(e.getMessage()); return "ER#xml->document"; } try { rs = processHotelRatePlanResponse(document, periodId, hotelCodes); } catch (Exception ex) { logger.error(ex.getMessage()); logger.debug(response); return "ER#processHotelRatePlanResponse"; } return rs; } @Override public String searchHotelRatePlan(final String hotelCode, Date startDate, Date endDate) { return searchHotelRatePlan(hotelCode, startDate, endDate, false); } @Override public String searchHotelRatePlan(final String hotelCode, Date startDate, Date endDate, final boolean returnXml) { List<String> hotelCodes = new ArrayList<String>(); hotelCodes.add(hotelCode); String response = execSearchHotelRatePlan(hotelCodes, startDate, endDate); if (returnXml) return response; //? String rs = "rs"; SAXReader reader = new SAXReader(); Document document;// ?XML try { document = reader.read(new StringReader(response)); } catch (DocumentException e) { logger.error(e.getMessage()); return "ER#xml->document"; } if (document == null) return "ER#Document is null."; Element rootElement = document.getRootElement(); Element headerElement = rootElement.element("Header"); if (!headerElement.attribute("ResultCode").getValue().equalsIgnoreCase("Success")) { //logger.error("ER#ResultCode is not Success."); logger.error(document.asXML()); return "ER#ResultCode is not Success."; } rs = processHotelRatePlanResponse(document, 0, hotelCodes); return rs; } private synchronized String doSearchHotelRatePlan(String requestXml) { logger.debug("doSearchHotelRatePlan begin..." + Thread.currentThread().getName()); //headerAPI? String cacheKey = ConfigData.OTA_HotelRatePlan_Request; net.sf.ehcache.Element cacheElement = getCache().get(cacheKey); if (cacheElement != null) { Element headerElement = (Element) cacheElement.getValue(); int accessCount = Integer.parseInt(headerElement.attributeValue("AccessCount")); int currentCount = Integer.parseInt(headerElement.attributeValue("CurrentCount")) + 1; logger.info(ConfigData.OTA_HotelRatePlan_Request + " AccessCount=" + headerElement.attributeValue("AccessCount") + ", CurrentCount=" + headerElement.attributeValue("CurrentCount") + ", ResetTime=" + headerElement.attributeValue("ResetTime")); if (currentCount >= accessCount) { try { logger.info("Sleep for one minute."); Thread.sleep(60000); } catch (InterruptedException ex) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return "ER#DoSearchHotelRatePlan thread.sleep is interrupted."; } } } if (this.serviceStopped) return "ER#Service is stopped."; Date date0 = DateUtil.getCurDateTime(); String response = execApiRequest(requestXml, ConfigData.OTA_HotelRatePlan_Url, "requestXML"); int apiElapsedTime = DateUtil.getPastTime(date0); if (apiElapsedTime > 1000) logger.debug(ConfigData.OTA_HotelRatePlan_Request + " API: " + apiElapsedTime + "ms"); //? try { SAXReader reader = new SAXReader(); Document document = reader.read(new StringReader(response)); Element rootElement = document.getRootElement(); Element headerElement = rootElement.element("Header"); if (headerElement.attribute("ResultCode").getValue().equalsIgnoreCase("Success")) { //header? logger.debug("put headerElement to cache by key " + ConfigData.OTA_HotelRatePlan_Request); getCache().put(new net.sf.ehcache.Element(ConfigData.OTA_HotelRatePlan_Request, headerElement)); } else { logger.error(response); logger.error("ResultCode is not Success."); } } catch (Exception e) { logger.error(e.getMessage()); } logger.debug("doSearchHotelRatePlan end..." + Thread.currentThread().getName()); return response; } private RatePlanRequest createRatePlanRequest(String hotelCode, Date startDate, Date endDate) { RatePlanHotelRef ratePlanHotelRef = new RatePlanHotelRef(); ratePlanHotelRef.setHotelCode(hotelCode); RatePlanCandidate ratePlanCandidate = new RatePlanCandidate(); ratePlanCandidate.getRatePlanHotelRefs().add(ratePlanHotelRef); DateRange ratePlanDateRange = new DateRange(); ratePlanDateRange.setStartDate(DateUtil.formatDate(startDate, "yyyy-MM-dd")); ratePlanDateRange.setEndDate(DateUtil.formatDate(endDate, "yyyy-MM-dd")); RatePlanRequest ratePlanRequest = new RatePlanRequest(); ratePlanRequest.getHotelRatePlanCandidates().add(ratePlanCandidate); ratePlanRequest.setDateRange(ratePlanDateRange); return ratePlanRequest; } private String execSearchHotelRatePlan(List<HotelRatePlanRequestDto> requestDtos) { HotelRequestBody request = new HotelRequestBody(); request.createHotelRatePlanRequest(); String hotelCode; Date startDate; Date endDate; for (HotelRatePlanRequestDto dto : requestDtos) { hotelCode = dto.getHotelCode(); startDate = dto.getStartDate(); endDate = dto.getEndDate(); RatePlanRequest ratePlanRequest = createRatePlanRequest(hotelCode, startDate, endDate); request.getHotelRatePlaneRequest().getRatePlanRequests().add(ratePlanRequest); } String xml; try { xml = createXml4HotelRequestBody(request, ConfigData.OTA_HotelRatePlan_Request); } catch (Exception e) { e.printStackTrace(); return "ER#request xml is wrong."; } logger.debug(xml); String response = doSearchHotelRatePlan(xml); logger.debug(response); return response; } private String createXml4HotelRequestBody(HotelRequestBody request, String requestType) throws JAXBException { JAXBContext jc = JAXBContext.newInstance(HotelRequestBody.class); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.setProperty(Marshaller.JAXB_ENCODING, "utf-8"); m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); DocumentResult documentResult = new DocumentResult(); m.marshal(request, documentResult); org.dom4j.Document document = documentResult.getDocument(); org.dom4j.Element requestElement = document.getRootElement(); org.dom4j.Document doc1 = DocumentHelper.createDocument(); org.dom4j.Element rootElement = createRequestHeaderElement(doc1, requestType); rootElement.add(requestElement); return doc1.asXML(); } private String execSearchHotelRatePlan(List<String> hotelCodes, Date startDate, Date endDate) { HotelRequestBody request = new HotelRequestBody(); request.createHotelRatePlanRequest(); for (String hotelCode : hotelCodes) { RatePlanRequest ratePlanRequest = createRatePlanRequest(hotelCode, startDate, endDate); request.getHotelRatePlaneRequest().getRatePlanRequests().add(ratePlanRequest); } String xml; try { xml = createXml4HotelRequestBody(request, ConfigData.OTA_HotelRatePlan_Request); } catch (Exception e) { e.printStackTrace(); return "ER#request xml is wrong."; } logger.debug(xml); String response = doSearchHotelRatePlan(xml); logger.debug(response); return response; } @Override public String searchHotelRatePlan(List<String> hotelCodes, int periodId) { return searchHotelRatePlan(hotelCodes, periodId, false); } @Override public String importHotelRatePlanResponse(String filename) { String rs; SAXReader reader = new SAXReader(); logger.info("filename: " + filename); File file = new File(filename); if (!file.exists()) return null; Document document;// ?XML try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); return "error"; } rs = processHotelRatePlanResponse(document, 1, new ArrayList<String>()); return rs; } private synchronized String searchHotelCacheChange(int cityId, Date fromTimeStamp) { //headerAPI? Cache cache = getCache(); String cacheKey = ConfigData.OTA_HotelCacheChange_Request; net.sf.ehcache.Element cacheElement = cache.get(cacheKey); if (cacheElement != null) { Element headerElement = (Element) cacheElement.getValue(); int accessCount = Integer.parseInt(headerElement.attributeValue("AccessCount")); int currentCount = Integer.parseInt(headerElement.attributeValue("CurrentCount")) + 1; logger.info("AccessCount=" + headerElement.attributeValue("AccessCount") + ", CurrentCount=" + headerElement.attributeValue("CurrentCount") + ", ResetTime=" + headerElement.attributeValue("ResetTime")); if (currentCount >= accessCount) { try { logger.info("Sleep for one minute."); Thread.sleep(60000); } catch (InterruptedException ex) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return "ER#SearchHotelCacheChange thread.sleep is interrupted."; } } } HotelRequestBody request = new HotelRequestBody(); request.createHotelCacheChangeRequest(); String cacheFromTimeStamp = DateUtil.formatDate(fromTimeStamp, "yyyy-MM-dd'T'HH:mm:ss"); request.getHotelCacheChangeRequest().getCacheSearchCriteria().setCacheFromTimestamp(cacheFromTimeStamp); request.getHotelCacheChangeRequest().getCacheSearchCriteria().getCacheSearchCriterion() .setHotelCityCode(cityId); //logger.info("OTA_HotelCacheChange: " + cacheFromTimeStamp + ", " + cityId); String xml; try { xml = createXml4HotelRequestBody(request, ConfigData.OTA_HotelCacheChange_Request); } catch (JAXBException e) { e.printStackTrace(); return "<xml>" + e.getMessage() + "</xml>"; } String paraName = "requestXML"; Date basetime = DateUtil.getCurDateTime(); String response = execApiRequest(xml, ConfigData.OTA_HotelCacheChange_url, paraName); int spantime = DateUtil.getPastTime(basetime); logger.info(ConfigData.OTA_HotelCacheChange_Request + ": api elapsed " + spantime + "ms"); return response; } @Override public String importHotelCacheChangeResponse(String filename) { String rs; SAXReader reader = new SAXReader(); logger.info("filename: " + filename); File file = new File(filename); if (!file.exists()) return null; Document document;// ?XML try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); return "error"; } rs = processHotelCacheChangeResponse(document); return rs; } /** * ? * ?7 * 1. ?id * 2. * @return */ @Override public String refreshAllHotelBasicInfo(String cityCode) { if (this.serviceStopped) return "ER#Service is stopped."; String rs = ""; List<City> cities = cityDao.getAllCity(); for (City city : cities) { if (this.serviceStopped) break; CacheCity cacheCity = hotelDao.getCacheCity(city.getOpenApiId()); if (cacheCity != null) { //?7 int spanDays = DateUtil.getPastDays(cacheCity.getCacheTime()); if (spanDays < 7) continue; } if (cityCode != null && !cityCode.equalsIgnoreCase("*") && !cityCode.equalsIgnoreCase(city.getCityCode())) continue; String status = searchHotel(city.getOpenApiId()); rs = status; if (status.substring(0, 2).equalsIgnoreCase("OK")) { if (cacheCity == null) { cacheCity = new CacheCity(); cacheCity.setCityId(city.getOpenApiId()); cacheCity.setCreateTime(DateUtil.getCurDateTime()); cacheCity.setCacheTime(DateUtil.getCurDateTime()); hotelDao.createCacheCity(cacheCity); } else { cacheCity.setCacheTime(DateUtil.getCurDateTime()); hotelDao.updateCacheCity(cacheCity); } //break; } else { // logger.warn("refreshAllHotelBasicInfoexit loop for (" + rs + ")."); break; } } return rs; } /** * ? * * @return */ @Override public String refreshAllHotelDetail(String cityCode) { String rs = "HAHA"; if (this.serviceStopped) return "ER#Service is stopped."; //hotelDetailDaoExecutor.execute(new HotelDetailDaoThread()); List<String> hotelCodes0 = hotelDao.getAllHotelCodes2(cityCode); int count = 0; List<String> hotelCodes = new ArrayList<String>(); int total = hotelCodes.size(); int count0 = 0; for (String hotelCode : hotelCodes0) { count0++; if (this.serviceStopped) break; CacheHotel cacheHotel = hotelDao.getCacheHotel(hotelCode); if (cacheHotel != null) { //?7 int spanDays = DateUtil.getPastDays(cacheHotel.getCacheTime()); if (spanDays < 7) { continue; } } hotelCodes.add(hotelCode); count++; if (count < hotelCountPerRequestHotelDetail && count0 < total) continue; String status = searchHotelDetail(hotelCodes, false); rs = status; if (status.substring(0, 2).equalsIgnoreCase("OK")) { count = 0; hotelCodes.clear(); } else { // logger.warn("refreshAllHotelDetailexit loop for (" + rs + ")."); break; } } return rs; } public int getMaxDaysOfHotelRate() { return maxDaysOfHotelRate; } public void setHotelCountPerRequestHotelDetail(int hotelCountPerRequestHotelDetail) { this.hotelCountPerRequestHotelDetail = hotelCountPerRequestHotelDetail; } private class HotelDetailDaoThread implements Runnable { //private volatile boolean stopRequested; private Thread runThread; @Override public void run() { runThread = Thread.currentThread(); //stopRequested = false; logger.info(runThread.getName() + "(HotelDetailDaoThread) is running..."); while (!hotelDetailQueue.isEmpty()) { if (serviceStopped) break; try { DocumentDto documentDto = hotelDetailQueue.take(); Document document = documentDto.getDocument(); processHotelDetailResponse(document); } catch (InterruptedException e) { logger.warn(Thread.currentThread().getName() + " is interrupted."); break; } catch (Exception ex) { ex.printStackTrace(); logger.error(ex.getMessage()); break; } } logger.info(runThread.getName() + "(HotelDetailDaoThread) exit."); } //public void stopRequest() { // stopRequested = true; //} } private class HotelRatePlanDaoThread implements Runnable { //private volatile boolean stopRequested; private Thread runThread; @Override public void run() { runThread = Thread.currentThread(); //stopRequested = false; logger.debug(runThread.getName() + "(HotelRatePlanDaoThread) is running..."); while (!ratePlanQueue.isEmpty()) { if (serviceStopped) break; try { DocumentDto documentDto = ratePlanQueue.poll(2, TimeUnit.SECONDS); if (documentDto == null) { Thread.sleep(50); continue; } Document document = documentDto.getDocument(); int periodId = documentDto.getPeriodId(); logger.debug(runThread.getName() + " is running on " + periodId); logger.debug("taken hotelCodes\'s size is " + documentDto.getHotelCodes().size()); executeSaveRatePlanDocument(document, periodId, documentDto.getHotelCodes()); } catch (InterruptedException e) { logger.warn(Thread.currentThread().getName() + " is interrupted."); break; } } logger.debug(runThread.getName() + "(HotelRatePlanDaoThread) exit."); } // public void stopRequest() { // stopRequested = true; // } } private class HotelCacheChangeDaoThread implements Runnable { //private volatile boolean stopRequested; private Thread runThread; @Override public void run() { runThread = Thread.currentThread(); //stopRequested = false; logger.debug(runThread.getName() + "(HotelCacheChangeDaoThread) is running..."); while (!hotelCacheChangeQueue.isEmpty()) { if (serviceStopped) break; try { DocumentDto documentDto = hotelCacheChangeQueue.poll(1, TimeUnit.SECONDS); if (documentDto == null) { Thread.sleep(50); continue; } Document document = documentDto.getDocument(); executeSaveHotelCacheChangeDocument(document); } catch (InterruptedException x) { logger.warn(Thread.currentThread().getName() + " is interrupted."); break; } catch (Exception ex) { logger.error(ex.getMessage()); } } logger.debug(runThread.getName() + "(HotelCacheChangeDaoThread) exit."); } // public void stopRequest() { // stopRequested = true; // } } /** * ?hotelCacheChange? */ private class HotelCacheChangeDetailThread implements Runnable { private Thread runThread; @Override public void run() { runThread = Thread.currentThread(); logger.debug(runThread.getName() + "(HotelCacheChangeDetailThread) is running..."); //?hotelCacheChange? List<HotelRatePlanRequestDto> requestDtos = new ArrayList<HotelRatePlanRequestDto>(); int count = ratePlanRequestQueue.drainTo(requestDtos, 10); if (serviceStopped) return; if (count > 0) { logger.debug("requestDtos\'s size is " + requestDtos.size()); String response = execSearchHotelRatePlan(requestDtos); try { SAXReader reader = new SAXReader(); Document document = reader.read(new StringReader(response)); if (document != null) { Element rootElement = document.getRootElement(); Element headerElement = rootElement.element("Header"); if (!headerElement.attribute("ResultCode").getValue().equalsIgnoreCase("Success")) { logger.error("ER#ResultCode is not Success."); logger.error(document.asXML()); } else { List<String> hotelCodes = new ArrayList<String>(); for (HotelRatePlanRequestDto requestDto : requestDtos) { hotelCodes.add(requestDto.getHotelCode()); } processHotelRatePlanResponse(document, 0, hotelCodes); } } } catch (DocumentException e) { logger.error(e.getMessage()); } } else { logger.debug("drainTo is 0"); } logger.debug(runThread.getName() + "(HotelCacheChangeDetailThread) exit."); } } private void executeSaveHotelCacheChangeDocument(Document document) { //????? Map uris = new HashMap(); uris.put("ns", "http://www.opentravel.org/OTA/2003/05"); XPath xpath = document.createXPath("//ns:OTA_HotelCacheChangeRS/*"); xpath.setNamespaceURIs(uris); List myNodes = xpath.selectNodes(document); List<CacheHotelCacheChange> hotelCacheChanges = new ArrayList<CacheHotelCacheChange>(); XStream xs = createXStream(); xs.alias("CacheChangeInfo", HotelCacheChangeInfo.class); xs.processAnnotations(HotelCacheChangeInfo.class); for (Iterator it = myNodes.iterator(); it.hasNext();) { Element element = (Element) it.next(); if (!element.getName().equalsIgnoreCase("CacheChangeInfo")) { continue; } //String xml = element.asXML(); HotelCacheChangeInfo hotelCacheChangeInfo = (HotelCacheChangeInfo) xs.fromXML(element.asXML()); CacheHotelCacheChange cacheHotelCacheChange = new CacheHotelCacheChange(); cacheHotelCacheChange.setHotelCode(hotelCacheChangeInfo.getHotelCode()); cacheHotelCacheChange.setRatePlanCode(hotelCacheChangeInfo.getOtherInfo().getRatePlanCode()); try { cacheHotelCacheChange .setStartDate(DateUtil.convertToDate(hotelCacheChangeInfo.getDateRange().getStartDate())); cacheHotelCacheChange .setEndDate(DateUtil.convertToDate(hotelCacheChangeInfo.getDateRange().getEndDate())); } catch (Exception ex) { logger.error(ex.getMessage()); continue; } hotelCacheChanges.add(cacheHotelCacheChange); } //end for hotelDao.createCacheHotelCacheChanges(hotelCacheChanges); } @Override public String refreshAllRatePlan(String cityCode, int ratePlanStatus) { String rs = ""; int count = 0; if (this.serviceStopped) return "ER#Service is stopped."; //hotelRatePlanDaoExecutor.execute(new HotelRatePlanDaoThread()); cn.buk.hotel.entity.HotelInfo hotelInfo; boolean bBreak = false; for (int periodId = 1; periodId <= 4; periodId++) { if (this.serviceStopped) break; int minDay = (periodId - 1) * 28; if (minDay >= this.maxDaysOfHotelRate) continue; List<String> hotelCodes1 = new ArrayList<String>(); Date baseTime = DateUtil.getCurDateTime(); List<String> hotelCodes = null; if (ratePlanStatus == 0) hotelCodes = hotelDao.getHotelCodes4RatePlan(periodId, cityCode); else hotelCodes = hotelDao.getHotelCodes4RatePlan(periodId, cityCode, ratePlanStatus); hotelCodes = hotelCodes != null ? hotelCodes : new ArrayList<String>(); int span = DateUtil.getPastMinutes(baseTime); if (span >= 5) { logger.error("hotelDao.getHotelCodes4RatePlan(periodId) " + span + ", ?"); break; } int total = hotelCodes.size(); int progress = 0; for (String hotelCode : hotelCodes) { if (this.serviceStopped) break; progress++; //header? //timeToLiveSecond is the time in seconds from the point of creation in the cache till it expires (regardless of how frequently it is accessed in that time) //timeToIdleSeconds is the time in seconds before an object in the cache expires if it is not accessed. //getCache().put(new net.sf.ehcache.Element(ConfigData.HOTEL_CODES_WAITING_FOR_RATE_PLAN, copyHotelCodes, false, 1200000, 1800000)); hotelInfo = hotelDao.getHotelInfoByHotelCode(hotelCode); if (hotelInfo == null || (hotelInfo.getRatePlanStatus() == -1 && ratePlanStatus == 0)) { logger.debug(hotelCode + " is null or rate plan status is -1."); continue; } CacheRatePlan cacheRatePlan = hotelDao.getCacheRatePlan(hotelCode, periodId); if (cacheRatePlan != null) { //?7 int spanDays; if (cacheRatePlan.getBeginTime() != null) spanDays = DateUtil.getPastDays(cacheRatePlan.getBeginTime()); else if (cacheRatePlan.getEndTime() != null) spanDays = DateUtil.getPastDays(DateUtil.getOnlyDate(cacheRatePlan.getEndTime())); else spanDays = 30; if (spanDays < 7 && progress < total) continue; } else { cacheRatePlan = new CacheRatePlan(); cacheRatePlan.setHotelCode(hotelCode); cacheRatePlan.setPeriodId(periodId); cacheRatePlan.setBeginTime(DateUtil.getCurDateTime()); hotelDao.createCacheRatePlan(cacheRatePlan); } hotelCodes1.add(hotelCode); count++; if (count < 10 && progress < total) continue; rs = searchHotelRatePlan(hotelCodes1, periodId); if (rs.substring(0, 2).equalsIgnoreCase("OK")) { count = 0; hotelCodes1.clear(); } else { logger.error("exit loop for (" + rs + ")."); bBreak = true; break; } logger.info("refreshAllRatePlan\'s progress: " + Integer.toString(progress) + "/" + Integer.toString(total) + ", " + Integer.toString(periodId)); } if (bBreak) break; } return rs; } /** * ?; * ? * cityCoded ??;???. * @param cityCode * @return */ @Override public String refreshAllHotelCacheChange(String cityCode) { //hotelCacheChangeDaoExecutor.execute( new HotelCacheChangeDaoThread()); if (this.serviceStopped) return "ER#Service is stopped."; List<City> cities = cityDao.getCityHotelGreaterThan100(); int max = cities.size(); int index = 0; Date timestamp1 = DateUtil.getCurDateTime(); timestamp1 = DateUtil.addMinutes(timestamp1, -intervalCacheChange); timestamp1 = DateUtil.getDateOnMinute(timestamp1); String cacheFromTimeStamp = DateUtil.formatDate(timestamp1, "yyyy-MM-dd'T'HH:mm:ss"); for (City city : cities) { if (this.serviceStopped) break; if (city.getOpenApiId() == 0) continue; if (!city.getCountryCode().equalsIgnoreCase("CN")) continue; if (cityCode != null && !cityCode.equalsIgnoreCase("*") && !cityCode.equalsIgnoreCase(city.getCityCode())) continue; index++; logger.debug("refreshHotelCacheChange\'s process: " + index + "/" + max); logger.info("OTA_HotelCacheChange: " + cacheFromTimeStamp + ", " + city.getOpenApiId() + ", " + index); String xml = searchHotelCacheChange(city.getOpenApiId(), timestamp1); if (xml.length() == 0) break; processHotelCacheChange(xml); } return "OK"; } @Override public String calculateSignature(String timestamp, String requestType) { try { return SignatureUtils.CalculationSignature(timestamp, this.allianceId, this.secretKey, this.sid, requestType); } catch (Exception e) { e.printStackTrace(); return ""; } } private class HotelRatePlanRequestDto { private String hotelCode; private Date startDate; private Date endDate; public String getHotelCode() { return hotelCode; } public void setHotelCode(String hotelCode) { this.hotelCode = hotelCode; } public Date getStartDate() { return startDate; } public void setStartDate(Date startDate) { this.startDate = startDate; } public Date getEndDate() { return endDate; } public void setEndDate(Date endDate) { this.endDate = endDate; } } @Override public void retrieveHotelCacheChangeDetail() { if (this.serviceStopped) return; String hotelCode0 = null; Date startDate0 = null, endDate0 = null; List<CacheHotelCacheChange> cacheChanges = hotelDao.getHotelCacheChanges(); int total = cacheChanges.size(); int count = 0; for (CacheHotelCacheChange cacheHotelCacheChange : cacheChanges) { if (this.serviceStopped) return; String hotelCode = cacheHotelCacheChange.getHotelCode(); Date startDate = cacheHotelCacheChange.getStartDate(); Date endDate = cacheHotelCacheChange.getEndDate(); count++; //???? if (hotelCode0 != null && hotelCode0.equalsIgnoreCase(hotelCode) && startDate0.getTime() == startDate.getTime() && endDate0.getTime() == endDate.getTime()) { logger.debug("HotelCacheChange\'s hotelCode is " + hotelCode + ", start is " + DateUtil.formatDate(startDate0, "yyyy-MM-dd") + ", end is " + DateUtil.formatDate(endDate0, "yyyy-MM-dd") + ", ignored."); continue; } hotelCode0 = hotelCode; startDate0 = startDate; endDate0 = endDate; int spans = DateUtil.getPastDays(startDate, DateUtil.getCurDate()); if (spans > 90) { logger.debug("HotelCacheChange\'s start date is " + DateUtil.formatDate(startDate, "yyyy-MM-dd") + ", " + Integer.toString(spans) + " > 90 days, ignored."); continue; } spans = DateUtil.getPastDays(endDate, DateUtil.getCurDate()); if (spans > 90) endDate = DateUtil.add(DateUtil.getCurDate(), 90); spans = DateUtil.getPastDays(endDate, startDate); if (spans > 28) { logger.warn("HotelCacheChange\'s start is " + DateUtil.formatDate(startDate, "yyyy-MM-dd") + ", end is " + DateUtil.formatDate(endDate, "yyyy-MM-dd") + ", split it."); for (int i = 1; i <= 5; i++) { Date startDate1 = DateUtil.add(startDate, (i - 1) * 28); Date endDate1 = DateUtil.add(startDate, i * 28); boolean b = DateUtil.getPastDays(endDate1, endDate) > 0; if (b) endDate1 = endDate; HotelRatePlanRequestDto dto = new HotelRatePlanRequestDto(); dto.setHotelCode(hotelCode); dto.setStartDate(startDate1); dto.setEndDate(endDate1); logger.warn("HotelCacheChange\'s hotelCode is " + hotelCode + ", start is " + DateUtil.formatDate(startDate1, "yyyy-MM-dd") + ", end is " + DateUtil.formatDate(endDate1, "yyyy-MM-dd") + "."); try { ratePlanRequestQueue.put(dto); } catch (InterruptedException e) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return; } if (b) break; } } else { HotelRatePlanRequestDto dto = new HotelRatePlanRequestDto(); dto.setHotelCode(hotelCode); dto.setStartDate(startDate); dto.setEndDate(endDate); try { ratePlanRequestQueue.put(dto); } catch (InterruptedException e) { logger.warn(Thread.currentThread().getName() + " is interrupted."); return; } } //if (count % 10 == 0 || count >= total) hotelCacheChangeDetailExecutor.execute(new HotelCacheChangeDetailThread()); if (count % 100 == 0) logger.info("retrieveHotelCacheChangeDetail\'s progress: " + Integer.toString(count) + "/" + Integer.toString(total)); } } @Override public void stopService() { this.serviceStopped = true; hotelDetailDaoExecutor.shutdown(); try { hotelDetailDaoExecutor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } hotelCacheChangeDaoExecutor.shutdown(); try { hotelCacheChangeDaoExecutor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } hotelRatePlanDaoExecutor.shutdown(); try { hotelRatePlanDaoExecutor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } hotelCacheChangeDetailExecutor.shutdown(); try { hotelCacheChangeDetailExecutor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } cacheManager.shutdown(); } /** * ?? * @param hotelCode * @param checkInDate * @param checkOutDate * @param ratePlanCode * @param roomQuantity * @param guestCount * @param lateArrivalTime * @return */ @Override public String checkHotelAvail(String hotelCode, Date checkInDate, Date checkOutDate, String ratePlanCode, int roomQuantity, int guestCount, Date lateArrivalTime, boolean returnXml) { HotelRequestBody request = new HotelRequestBody(); // if (checkInDate.getTime() < DateUtil.getCurDate().getTime()) checkInDate = DateUtil.getCurDate(); if (checkInDate.getTime() >= checkOutDate.getTime()) checkOutDate = DateUtil.add(checkInDate, 1); if (lateArrivalTime.getTime() <= DateUtil.getCurDateTime().getTime()) lateArrivalTime = DateUtil.addMinutes(DateUtil.getCurDateTime(), 5); request.createHotelAvailRequest(); HotelAvailRequestSegment hotelAvailRequestSegment = new HotelAvailRequestSegment(); request.getHotelAvailRequest().getHotelAvailRequestSegments().add(hotelAvailRequestSegment); HotelSearchCriterion criterion = hotelAvailRequestSegment.getHotelSearchCriteria().getCriterion(); criterion.getHotelRef().setHotelCode(hotelCode); criterion.getHotelStayDateRange().setStartDate(DateUtil.formatDate(checkInDate, "yyyy-MM-dd")); criterion.getHotelStayDateRange().setEndDate(DateUtil.formatDate(checkOutDate, "yyyy-MM-dd")); HotelRatePlanCandidate ratePlanCandidate = new HotelRatePlanCandidate(); criterion.getRatePlanCandidates().add(ratePlanCandidate); ratePlanCandidate.setRatePlanCode(ratePlanCode); RoomStayCandidate roomStayCandidate = new RoomStayCandidate(); criterion.getRoomStayCandidates().add(roomStayCandidate); roomStayCandidate.setQuantity(roomQuantity); roomStayCandidate.getRoomGuestCount().getGuestCount().setCount(guestCount); roomStayCandidate.getRoomGuestCount().setPerRoom(false); criterion.getHotelLateArrivalTime() .setLateArrivalTime(DateUtil.formatDate(lateArrivalTime, "yyyy-MM-dd'T'HH:mm:ss")); String xml; try { xml = createXml4HotelRequestBody(request, ConfigData.OTA_HotelAvail_Request); } catch (JAXBException ex) { ex.printStackTrace(); logger.error(ex.getMessage()); return "ER"; } logger.debug(xml); // return xml; if (serviceStopped) return "ER#Service stopped."; String response = execApiRequest(xml, ConfigData.OTA_HotelAvail_Url, "requestXML"); logger.debug(response); if (returnXml) return response; //? SAXReader reader = new SAXReader(); Document document;// ?XML try { document = reader.read(new StringReader(response)); if (serviceStopped) return "ER#Service stopped."; response = processHotelAvailResponse(document); } catch (Exception ex) { logger.error(ex.getMessage()); return "ER"; } return response; } @Override public HotelAvailResult checkHotelAvail(String hotelCode, Date checkInDate, Date checkOutDate, String ratePlanCode, int roomQuantity, int guestCount, Date lateArrivalTime) { String responseXml = checkHotelAvail(hotelCode, checkInDate, checkOutDate, ratePlanCode, roomQuantity, guestCount, lateArrivalTime, true); List<HotelAvailResponseRoomStay> roomStays = processHotelAvailResponse(responseXml); HotelAvailResult hotelAvailResult = new HotelAvailResult(); if (roomStays.size() > 0) { if (roomStays.get(0).isAvailable()) hotelAvailResult.setStatus("OK"); else hotelAvailResult.setStatus("ER"); } return hotelAvailResult; } @Override public String importHotelAvailResponse(String xml_file) { String rs; SAXReader reader = new SAXReader(); logger.info("filename: " + xml_file); File file = new File(xml_file); if (!file.exists()) return null; Document document;// ?XML try { document = reader.read(file); } catch (DocumentException e) { e.printStackTrace(); return "error"; } rs = processHotelAvailResponse(document); return rs; } private List<HotelAvailResponseRoomStay> processHotelAvailResponse(String responseXml) { List<HotelAvailResponseRoomStay> roomStays = new ArrayList<HotelAvailResponseRoomStay>(); //? SAXReader reader = new SAXReader(); Document document;// ?XML try { document = reader.read(new StringReader(responseXml)); //????? Map uris = new HashMap(); uris.put("ns", "http://www.opentravel.org/OTA/2003/05"); XPath xpath = document.createXPath("//ns:RoomStays/*"); xpath.setNamespaceURIs(uris); List myNodes = xpath.selectNodes(document); if (myNodes.size() == 0) { logger.warn("ER#There is nothing."); return roomStays; } XStream xs = createXStream(); xs.alias("RoomStay", HotelAvailResponseRoomStay.class); xs.processAnnotations(HotelAvailResponseRoomStay.class); String xml; for (Iterator it = myNodes.iterator(); it.hasNext();) { //if (serviceStopped) break; Element element = (Element) it.next(); xml = element.asXML(); HotelAvailResponseRoomStay roomStay = (HotelAvailResponseRoomStay) xs.fromXML(xml); roomStays.add(roomStay); } } catch (Exception ex) { logger.error(ex.getMessage()); } return roomStays; } private String processHotelAvailResponse(Document document) { if (document == null) return "ER#Document is null."; //????? Map uris = new HashMap(); uris.put("ns", "http://www.opentravel.org/OTA/2003/05"); XPath xpath = document.createXPath("//ns:RoomStays/*"); xpath.setNamespaceURIs(uris); List myNodes = xpath.selectNodes(document); String rs = "HAHA"; if (myNodes.size() == 0) { return "ER#There is nothing."; } logger.debug(Thread.currentThread().getName() + " is on processHotelAvailResponse."); XStream xs = createXStream(); xs.alias("RoomStay", HotelAvailResponseRoomStay.class); xs.processAnnotations(HotelAvailResponseRoomStay.class); String xml; for (Iterator it = myNodes.iterator(); it.hasNext();) { //if (serviceStopped) break; Element element = (Element) it.next(); xml = element.asXML(); HotelAvailResponseRoomStay response = (HotelAvailResponseRoomStay) xs.fromXML(xml); if (response.isAvailable()) System.out.println("available for booking"); else System.out.println("closed"); } //end for return rs; } private String processHotelCacheChange(String xml) { String retval; //? SAXReader reader = new SAXReader(); Document document;// ?XML try { document = reader.read(new StringReader(xml)); retval = processHotelCacheChangeResponse(document); } catch (Exception ex) { ex.printStackTrace(); return "ER"; } return retval; } public void setCityDao(CityDao cityDao) { this.cityDao = cityDao; } public void setHotelDao(HotelDao hotelDao) { this.hotelDao = hotelDao; } }