import java.lang.* ;
class Main {
public static void main
( String [ ] argv
) { SandwichMaker< Cheese> sandwich = new CheeseSandwichMaker( ) ;
sandwich.make ( new Cheese( "Camembert" , "Normandy, France" ) ) ;
sandwich.make ( new Cheese( "Cheddar" , "Somerset, England" ) ) ;
}
}
abstract class SandwichMaker< S extends Spread> {
public void make( S spread) {
toastBread( ) ;
addSpread( spread) ;
enjoy( ) ;
}
protected void toastBread( ) {
System .
out .
println ( "...toasting bread" ) ; }
protected abstract void addSpread( S spread) ;
protected void enjoy( ) {
System .
out .
println ( "this is yummy!" ) ; }
}
class CheeseSandwichMaker extends SandwichMaker< Cheese> {
@Override
protected void addSpread( Cheese cheese) {
System .
out .
println ( "... adding " + cheese.
name + " cheese from " + cheese.
origin ) ; }
}
interface Spread { }
class Cheese implements Spread {
this .name = name;
this .origin = origin;
}
}
aW1wb3J0IGphdmEubGFuZy4qOwoKY2xhc3MgTWFpbiB7CglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmd2KSB7CgkgICAgU2FuZHdpY2hNYWtlcjxDaGVlc2U+IHNhbmR3aWNoID0gbmV3IENoZWVzZVNhbmR3aWNoTWFrZXIoKTsKCSAgICBzYW5kd2ljaC5tYWtlKG5ldyBDaGVlc2UoIkNhbWVtYmVydCIsICJOb3JtYW5keSwgRnJhbmNlIikpOwoJICAgIHNhbmR3aWNoLm1ha2UobmV3IENoZWVzZSgiQ2hlZGRhciIsICJTb21lcnNldCwgRW5nbGFuZCIpKTsKCX0gCn0JCgkKCmFic3RyYWN0IGNsYXNzIFNhbmR3aWNoTWFrZXI8UyBleHRlbmRzIFNwcmVhZD4gewogICAgcHVibGljIHZvaWQgbWFrZShTIHNwcmVhZCkgewogICAgICAgIHRvYXN0QnJlYWQoKTsKICAgICAgICBhZGRTcHJlYWQoc3ByZWFkKTsKICAgICAgICBlbmpveSgpOwogICAgfQoKICAgIHByb3RlY3RlZCB2b2lkIHRvYXN0QnJlYWQoKSB7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCIuLi50b2FzdGluZyBicmVhZCIpOwogICAgfQoKICAgIHByb3RlY3RlZCBhYnN0cmFjdCB2b2lkIGFkZFNwcmVhZChTIHNwcmVhZCk7CgogICAgcHJvdGVjdGVkIHZvaWQgZW5qb3koKSB7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJ0aGlzIGlzIHl1bW15ISIpOwogICAgfQp9CgpjbGFzcyBDaGVlc2VTYW5kd2ljaE1ha2VyIGV4dGVuZHMgU2FuZHdpY2hNYWtlcjxDaGVlc2U+IHsKICAgIEBPdmVycmlkZQogICAgcHJvdGVjdGVkIHZvaWQgYWRkU3ByZWFkKENoZWVzZSBjaGVlc2UpIHsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIi4uLiBhZGRpbmcgIiArIGNoZWVzZS5uYW1lICsgIiBjaGVlc2UgZnJvbSAiICsgY2hlZXNlLm9yaWdpbik7CiAgICB9Cn0KCmludGVyZmFjZSBTcHJlYWQge30KY2xhc3MgQ2hlZXNlIGltcGxlbWVudHMgU3ByZWFkIHsKICAgIHB1YmxpYyBmaW5hbCBTdHJpbmcgbmFtZTsKICAgIHB1YmxpYyBmaW5hbCBTdHJpbmcgb3JpZ2luOwoKICAgIHB1YmxpYyBDaGVlc2UoU3RyaW5nIG5hbWUsIFN0cmluZyBvcmlnaW4pIHsKICAgICAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgICAgIHRoaXMub3JpZ2luID0gb3JpZ2luOwogICAgfQp9