@@ -0,0 +1,178 @@
package PageGuest;

import com.teamdev.jxbrowser.chromium.dom.DOMDocument;

/**
* Created by Andras on 27/07/2017.
*/
public class AirbnbDotComStatus
{
public enum Status {
EMPTY,
STARTING,
START_PAGE_LOADED,
FILLING_THE_FORM,
FORM_IS_FILLED,
SEARCHING,
RESULT_PAGE_LOADED,
PARSING_THE_RESULTS,
PARSING_HAS_FINISHED,
NEXT_PAGE_LOADING,
NEXT_PAGE_LOADED,
THE_SEARCHING_READY,

OPENING_A_HOTEL_PAGE,
HOTEL_PAGE_LOADED,
PARSING_A_HOTEL_PAGE,
HOTEL_PAGE_IS_PARSED,

APPLYING_A_FILTER,
FILTERED_PAGE_LOADED,

DONE
}

private Status mStatus;
Status getStatus() { return mStatus; }

public AirbnbDotComStatus()
{
mStatus = Status.EMPTY;
}

public void starting( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case EMPTY:
case THE_SEARCHING_READY: mStatus = Status.STARTING; break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void mainFrameLoaded( AirbnbDotComPageGuest guest, DOMDocument aDocument )
{
switch( mStatus )
{
case STARTING: mStatus = Status.START_PAGE_LOADED; guest.FillTheForm( aDocument ); break;
case SEARCHING: mStatus = Status.RESULT_PAGE_LOADED; guest.ApplyFilter( aDocument ); break;
case APPLYING_A_FILTER: mStatus = Status.FILTERED_PAGE_LOADED; guest.ApplyFilter( aDocument ); break;
case NEXT_PAGE_LOADING: mStatus = Status.NEXT_PAGE_LOADED; guest.ParseTheResult( aDocument ); break;
case OPENING_A_HOTEL_PAGE: mStatus = Status.HOTEL_PAGE_LOADED; guest.ParseAHotelPage( aDocument ); break;
//case THE_SEARCHING_READY: break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void fillingTheForm( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case START_PAGE_LOADED: mStatus = Status.FILLING_THE_FORM; break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void formIsFilled( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case FILLING_THE_FORM: mStatus = Status.FORM_IS_FILLED; break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void searching( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case FORM_IS_FILLED: mStatus = Status.SEARCHING; break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void parsingTheResult( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case RESULT_PAGE_LOADED: mStatus = Status.PARSING_THE_RESULTS; break;
case NEXT_PAGE_LOADED: mStatus = Status.PARSING_THE_RESULTS; break;
case FILTERED_PAGE_LOADED: mStatus = Status.PARSING_THE_RESULTS; break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void parsingFinished( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case PARSING_THE_RESULTS:
mStatus = Status.PARSING_HAS_FINISHED;
if( guest.pageNext())
{
mStatus = Status.NEXT_PAGE_LOADING;
}
else
{
if( guest.openTheNextHotel())
{
mStatus = Status.OPENING_A_HOTEL_PAGE;
}
else
{
mStatus = Status.THE_SEARCHING_READY;
guest.printTheMatches();
guest.startANewSearch();
}
}
break;
case PARSING_A_HOTEL_PAGE:
mStatus = Status.HOTEL_PAGE_IS_PARSED;
if( guest.openTheNextHotel())
{
mStatus = Status.OPENING_A_HOTEL_PAGE;
}
else
{
mStatus = Status.THE_SEARCHING_READY;
guest.printTheMatches();
guest.startANewSearch();
}
break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void parsingAHotelPage( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case HOTEL_PAGE_LOADED: mStatus = Status.PARSING_A_HOTEL_PAGE; break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}

public void Done( AirbnbDotComPageGuest guest )
{
mStatus = Status.DONE;
}

public void ApplyAFilter( AirbnbDotComPageGuest guest )
{
switch( mStatus )
{
case RESULT_PAGE_LOADED: mStatus = Status.APPLYING_A_FILTER; break;
case FILTERED_PAGE_LOADED: mStatus = Status.APPLYING_A_FILTER; break;
default:
throw new RuntimeException( "Illegal status: " + mStatus );
}
}
}
@@ -42,7 +42,6 @@ public class BookingDotComPageGuest extends WebPageGuest implements Runnable
private BrowserView mBrowserView = null;
private JTabbedPane mTabbedPane = null;

private boolean mThreadStopped = true;
private DOMDocument mDOMDocument;
private BookingDotComStatus mStatus = new BookingDotComStatus();

@@ -63,6 +62,9 @@ public class BookingDotComPageGuest extends WebPageGuest implements Runnable
private static final int HIGH_PRICE_FLAT_COUNT = 5;
private int mMatchedAccomodationCounter = 0;

// blocktoggle #RD17925503
DOMElement mRoomMetaBlock;

enum MyFilterIds
{
checkin_no_till_limit,
@@ -263,6 +265,7 @@ public void startANewSearch()
mResultSorted = false;
mHigherPriceCounter = HIGH_PRICE_FLAT_COUNT;
mMatchedAccomodationCounter = 0;
mRoomMetaBlock = null;
mBrowser.loadURL( getURL());
}

@@ -808,30 +811,58 @@ boolean testCheckinPolicy( String checkinPolicy )
return false;
}

private String getRoomSize( String roomMetaId )
private void getMetablock( String roomMetaId )
{
String roomSize = "";
if( roomMetaId != null )
{
// cutting the starting #
roomMetaId = roomMetaId.substring( 1 );

// blocktoggle #RD17925503
DOMElement lRoomMetaBlock = mDOMDocument.findElement( By.id( "blocktoggle" + roomMetaId ));
if( lRoomMetaBlock != null )
mRoomMetaBlock = mDOMDocument.findElement( By.id( "blocktoggle" + roomMetaId ));
}
}

private String getRoomSize()
{
String roomSize = "";
if( mRoomMetaBlock != null )
{
DOMElement lRoomInfo = mRoomMetaBlock.findElement( By.className( "info" ));
if( lRoomInfo != null )
{
roomSize = lRoomInfo.getInnerText()
.replaceAll( "\n", "" )
.replace( "Room size:", "" )
.replace( "Apartment size:", "" )
.trim();
}
}
return roomSize;
}

private boolean testSharedBathroom()
{
if( mRoomMetaBlock != null )
{
DOMElement lDOMFacilities = mRoomMetaBlock.findElement( By.className( "js_hp_rt_lightbox_facilities" ));
if( lDOMFacilities != null )
{
DOMElement lRoomInfo = lRoomMetaBlock.findElement( By.className( "info" ));
if( lRoomInfo != null )
boolean sharedBathroom = lDOMFacilities.getInnerText().contains( "Shared Bathroom" );
boolean expectedPrivateBathroom = false;
for( int i = 0; mFilters != null && i < mFilters.length; ++i )
{
roomSize = lRoomInfo.getInnerText()
.replaceAll( "\n", "" )
.replace( "Room size:", "" )
.replace( "Apartment size:", "" )
.trim();
if( mFilters[i].equals( "private_bathroom" ))
{
expectedPrivateBathroom = true;
break;
}
}
if( expectedPrivateBathroom && sharedBathroom )
return false;
}
}
return roomSize;
return true;
}

boolean testRoomSize( String roomSize )
@@ -940,9 +971,13 @@ private void ParseAHotelPage_S( AccomodationData_RESULT lAccomodation )
{
lRoomResult.mName = lRoomName.getAttribute( "data-room-name-en" );
lRoomResult.mRoomHook = lRoomName.getAttribute( "href" );
lRoomResult.mRoomSize = getRoomSize( lRoomResult.mRoomHook );
getMetablock( lRoomResult.mRoomHook );
lRoomResult.mRoomSize = getRoomSize();
if( !testRoomSize( lRoomResult.mRoomSize ))
continue;
if( !testSharedBathroom())
continue;

}
}
else
@@ -1,6 +1,9 @@
package PageGuest;

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.dom.By;
import com.teamdev.jxbrowser.chromium.dom.DOMDocument;
import com.teamdev.jxbrowser.chromium.dom.DOMElement;

import java.awt.*;
import java.awt.event.InputEvent;
@@ -228,7 +231,7 @@ private void javaScriptSetFocus( Browser aBrowser, String aXPath )
aBrowser.executeJavaScript( String.format( mGetElementByXPathPattern + ".focus();", aXPath ));
}

private void javaScriptSubmit( Browser aBrowser, String aXPath )
public void javaScriptSubmit( Browser aBrowser, String aXPath )
{
aBrowser.executeJavaScript( String.format( mGetElementByXPathPattern + ".submit();", aXPath ));
}
@@ -243,4 +246,17 @@ private void javaScriptClick( Browser aBrowser, String aXPath )
{
aBrowser.executeJavaScript( String.format( mGetElementByXPathPattern + ".click();", aXPath ));
}

public static DOMElement findElementByAttrib( DOMDocument aDOMDocument, String tagName, String attribName, String attribValue )
{
java.util.List<DOMElement> tags = aDOMDocument.findElements( By.tagName( tagName));

for( DOMElement element : tags )
{
String value = element.getAttribute( attribName );
if( value != null && value.equals( attribValue ))
return element;
}
return null;
}
}
@@ -194,11 +194,10 @@ public void FillTheForm( TravelData_INPUT aTravelDataInput ) throws URISyntaxExc
for( int i = 0; i < lInterval; i++ )
{
FillTheForm( aTravelDataInput, lYear, lMonth, lDay, lResultList );
if( ++lMonth == 13 )
{
lMonth = 1;
lYear++;
}
lDate = lDate.plusMonths( 1 );
lYear = lDate.getYear();
lMonth = lDate.getMonthValue();
lDay = lDate.getDayOfMonth();
Sleep( 1000 * Integer.parseInt( lSleep ));
}

@@ -279,6 +278,11 @@ private void ParseFlights( JSONArray aFlights, boolean aOutbound, ArrayList<Trav
for( int lTripIndex = 0; lTripIndex < aFlights.length(); lTripIndex++ )
{
JSONObject lJSONTrip = aFlights.getJSONObject( lTripIndex );

String lpriceType = lJSONTrip.getString( "priceType" );
if( lpriceType.equals( "soldOut" ))
continue;

//lTripClone.mDepartureDatetime = lJSONTrip.getString( "departureDate" );
String lDepartureStation = lJSONTrip.getString( "departureStation" );
String lArrivalStation = lJSONTrip.getString( "arrivalStation" );
@@ -46,6 +46,11 @@ else if( arg.equals( "-booking.com" ))
BookingDotComApp.Run();
break;
}
else if( arg.equals( "-airbnb.com" ))
{
AirbnbDotComApp.Run();
break;
}
else if( arg.equals( "-dbagent" ))
{
DBAgentApp.Run();
@@ -37,6 +37,10 @@ else if( PageType.equalsIgnoreCase( "booking.com" ))
{
return new BookingDotComPageGuest();
}
else if( PageType.equalsIgnoreCase( "airbnb.com" ))
{
return new AirbnbDotComPageGuest();
}
return null;
}
}