• Non ci sono risultati.

4 The Biim mobile mashup

N/A
N/A
Protected

Academic year: 2021

Condividi "4 The Biim mobile mashup"

Copied!
73
0
0

Testo completo

(1)

4 The Biim mobile mashup

The Biim mobile mashup is the production ready prototype developed to evaluate the ideas resulting from our studies. It fits into the existing Biim mobile mall project developed by OneOverZero GmbH and launched in May 2007.

We will start with a brief introduction to the Biim platform and technologies, followed by an architectural overview of the Biim mobile mushup system. Then we will present the prototype features and the customer needs they satisfy.

4.1 Mobile mall concept

The Biim mobile mall is a mobile commerce (or m-commerce) web based application. There are many definitions of mobile commerce. We will adopt the one proposed by Tiwari and Buse[26]: “Mobile

Commerce is any transaction, involving the transfer of ownership or rights to use goods and services, which is initiated and/or completed by using mobile access to computer-mediated networks with the help of an electronic device”.

Three observations emerge from the definition above. The definition considers the method of access as the primary criterion of mobility. What makes a transaction a mobile one is that at least one between

(2)

initiation or completion phase are performed using a mobile access by means of an electronic device. The character of the transaction may not involve money transfers.

Biim services are offered to two actors: buyer and seller. From this point of view it acts as a marketspace1. Sellers have a Biim space to sell their products. They put the products they want to sell in the mobile mall and can ask for integration services with their information system architecture. Other services include the delivery of special offers to final customers.

Biim is actually oriented on selling goods and services like perfumes, cinema or theatre tickets and other goods and services characterized by repeatedly buying habits or by satisfying needs emerging “on the fly”. Anyway, sellers are free to put on-line all the products they want to sell via mobile commerce.

While sellers pay for the service, buyers have granted free Biim access and registration. They can only interact with Biim via a mobile phone application written in Java. This means that only Java enabled mobile phone owners can access the Biim buyer services.

In the following we will consider only the buyers view of Biim and we will refer them as Biim users or users.

(3)

When the user accesses Biim for the first time it is asked to register to the service and to choose one of the supported languages2 that best fit its needs. After the registration process has been successfully completed, the Biim main screen is shown (see Figure 10).

The mobile mall shops are accessible in the “Channels” section, which includes other services like news feeds and weather forecasts. The user can set its favourite channels in the “Favorite” section, that acts as a collection of short cuts.

The “Profile” section allows the user to change its personal details, like home and work addresses, preferred payment method, name, etc. The “Options” section allows the user to set up options on the look and feel of the Biim application, the polling interval, auto login and information on the feature supported by the mobile phone3 it owns. Finally, the “Social” section groups messaging, microblogging and event planning functionalities.

2 Biim actually supports four languages: Italian, Deutsch, English and French.

3 Many features of J2ME are optional. Each mobile phone has its own set of supported features. The optional features are defined by some Java Specification Requests (JSRs). For example, Bluetooth services are defined in JSR-82, while Multi Media API (MMAPI) are

(4)

Before describing the details of the “Social” and “Channel” section functionalities we will cover in brief the most relevant details of the

Biim platform and the technologies used during development.

4.2 An architectural overview of the existing platform

The Biim platform has been developed using Java Enterprise Edition 5 platform (Java EE 5), Hibernate 3.0.x implementation of the Enterprise Java Bean 3 specification for object relational mapping, the Echo2 AJAX framework for web applications4 to provide administration services through a browser interface and the custom OneOverZero framework built on top of these technologies.

The system has been deployed on JBoss Application Server 4.0.4 GA bound to the Apache HTTP server by using the Tomcat connector technology. The PostgreSQL provides the relational DBMS services.

4 http://echo.nextapp.com/site/echo2

(5)

The OneOverZero framework consists of a layer of basic services, oozBase, and other topmost layers that offer project specific facilities. Biim has been developed on top of the oozBase framework and required new services to be developed in oozBase to support them. Figure 9 depicts the most important logical building blocks used for the Biim mobile mashup.

Figure 8 : T ec h nologies u sed in Bii m de velop m e n t (yello w boxes) a n d d e ploy m e n t.

(6)

The Messaging block is responsible of delivering messages. Recipients are not necessarily registered users and the messages may consists of text, images and any type of serializable content. Messages can be sent to multiple recipients at the same time and the service guarantees message delivery.

Tagging is self explanatory: it offers the capability of adding tags to

virtually any domain model entity. There can be textual tags or image tags. They are useful to classify the same entity under different

(7)

categories at the same time. They can be set by the users or by the system.

MobileUI Components encapsulate a set of classes that represents

elements of the MFDL5 markup. MFDL is a proprietary lightweight markup language developed by OneOverZero to describe the mobile user interface. It allows to provide a DOM6 of the mobile user interface, to define actions that alter the DOM itself or execute remote procedure calls. It also supports flow control and cycling constructs represented by means of special actions. MFDL is all that is needed to build up the mobile user interface.

The Web UI Generator component is responsible of generating the application's web interface. It has been developed on the Echo2 web framework. In brief, Echo2 is a platform to build up rich client applications on the web in Java. It provides the developer a component oriented and event driven API very similar to the Java Swing framework. The Web UI Generator analyse entities of the domain model and on the basis of this analysis it builds up the necessary UI components and aggregates them in a rich client page using Echo2 components.

(8)

The Geocoding component consists of a set of classes needed to access the Corbitconnect7 Mapservices web service, that provides geocoding8, mapping and routing services. It also contains classes that adapt the web service entities to domain model ones.

User Management component provides user representation and user

management services. It allows to set access permissions to application features, to manage the set of user identifiers in different authentication domains, to define user groups and user personal information. It also provides features to add and remove users.

Configurator provides application configuration services by means of

an xml configuration file.

Timers component contains classes and UI components that enrich the

timer services offered by the Java EE platform.

The Biim layer consists of the components that support the mobile mall and social functionalities. Many logic components covers both server side and client side features.

The News component takes care of news management. It allows to define new RSS news channels, to set channel parameters, like update interval, and to define channel containers that group RSS sources. It

7 http://www.corbitconnect.com/

8 the process of assigning geographic identifiers to map features and other data records, such as street addresses[28].

(9)

also allows to add news sources other than RSS feeds by means of a plug-in mechanism.

Mash-up Facilities allows access to third party web services and

adapts incoming and outgoing data to the Biim application data model.

Private Messaging handles one to one and one to many messaging

between Biim platform users or between a Biim user and unregistered users. All messages are grouped in conversations between the user and an interlocutor.

Microblogging is composed by a set of classes that handle interaction

between Twitter-like services and Biim messaging. These classes are also responsible of integrating micro blogging updates in Biim conversations.

Channel Management handles the Biim channels with respect to

geographic and linguistic context.

Shop Management handles the Biim shopping functionalities like

catalogues, purchasing and payment.

4.2.1 Mobile client and server interaction

It is important to understand how the biim mobile client works and how MFDL is used to create forms on the mobile device.

(10)

Having presented the system overall logical architecture we are now ready to present the details of our work.

4.3 The target user and the minimal required set of use

cases

The first thing to consider are the platform users. We have to define who they are and what services they are mainly interested in to start using the Biim mobile services.

The potential Biim user is an outlier which uses public transportation to go to its place of work and that have about 20 minutes of leisure time to fill in with something to do. This is a common situation for people employed in big cities that live in the outskirts. Many people spend this time reading news, weather forecasts or horoscope. So we may offer them these services as news channels providing news updates in near real time. The weather forecast can be tailored to the nearest city the user lives or works in. The same can be said for news even if we will offer national newspapers feeds too.

These information services will act on the Hedonic, Social and Utilitarian value according to the MDS adoption and usage model introduced in chapter 2 and the considerations done on mobile information services.

(11)

This covers the twenty minutes in the morning and maybe the twenty minutes in the late afternoon while the users go back home. Anyway, one of the most used features in mobile phones is messaging so we can provide it too. Instead of following the “medium is the message” paradigm literally, we can focus on the nature of message exchanges. Messaging usually occurs between two persons. We can provide a messaging service which groups all the received messages by interlocutor instead of grouping them on the message type they are. For example, if I want to send a message to Alice, I probably expect that Alice will reply to my message. If this happens it would be graceful if I can see all the conversation going on with Alice. It would be also good if I can send a picture to Alice too.

So we will provide textual and pictorial messaging functionality and we will group received and sent messages in conversations occurring between the user and its interlocutors. All the messages exchanged between the user and its interlocutor will be shown in chronological order. If some messages contain pictures, they will be shown too. The same model is applied if the user wants to send a message to many users at the same time. The same message will be reported in each user conversation.

(12)

According to the mashup style of the mobile application we assume that users may use web based communication services, being they microblogging or chat services. To apply this to our conversation messaging model means that messages sent by using these web based communication services have to be shown in the conversation occurring between user pairs assuming that service authentication data have been provided by users and that the web based service offers a way to retrieve sent messages.

What remains is the free time. If our users like to go out with friends or to organize events it would be good to offer some services that allow them to organize these events in a convenient way. Usually events are organized sending a lot of messages between the event organizer and the guests.

It would be fine if the event organizer would define the event and post it to all the guests, that each guest would decide if joining or not and that once all the guests have replied or the time expires the event organizer get notified of who joins and who does not. In some types of events, like cinema events or parties, the system could offer to the event organizer additional services, like the possibility to buy tickets or to propose a list of items to bring to the party.

At last we have to consider social entertainment services. An interesting example are polls: an user inserts a yes or no question and

(13)

submits it to other users. These, in turn, may reply yes or no to the question. Again, once all the guests have replied or the time expired, the poll initiator and the participants will receive the poll results. Even if it is a simple way of entertain people it is a successful one as services like Hot or not9 or the poll applications in Facebook have

demonstrated.

Another example of entertainment are video feeds like those offered by You Tube! We will offer them in a dedicated channel provided that the user mobile phone is able to support video streaming playback. All the mentioned services must provide a rapid interaction. The user must be able to access the desired service with the minimum number button presses possible and, possibly by using only two buttons or the directional pad.

9 Hot or not provides picures of women or men and the site visitor can give a vote to the

(14)

We can summarize what being said in the following use case diagram. A design constraint consists of news feeds being controlled by OneOverZero. In other words, the user is not allowed to add RSS feed sources directly but can only access predefined channels.

This constraint introduces the need of administration use cases. The Administrator will select and add new content to the platform by simply typing the remote URL from which the content is served. It will also be responsible of configuring correctly some news feeds parameters like refresh interval or number of news to serve.

Channels represent external information sources, like news, weather

forecasts, video collections and anything else the administrator considers to be informative for the user.

They are characterized by an information subject and a set of information items. The system has to allow the administrator to add

(15)

new information sources by means of an Uniform Resource Locator (URL), to define how many information items have to be considered in the remote source and how the incoming data must be processed to extract meaningful information.

While RSS feeds match exactly the channel model, this does not hold for other information source, like HTML pages. Hence the need of defining how to extract useful information from the incoming data. Depending on the channel information type different needs of information freshness arise. Some information is frequently updated while other is not. The Administrator should be able to define the time interval after which the information source must be asked for fresh content.

Channels have to be semantically aggregated using channel groups or

containers. Channel groups may be used to aggregate information in a

context dependent manner. The context may be the spoken language, the geographical location, the topic or any context the Administrator finds interesting to define. The application poses no constraint on channel group semantics.

The start and stop timers use case allows the administrator to start and stop all the timers currently registered in the system by means of a

(16)

simple web page front end that enlists them and shows the current activity status (started or stopped).

4.4 Domain model

Having defined the minimal set of use cases for Administrator and User actors we are ready to start to define the Biim mashup domain model.

4.4.1 Channels

All we have said above about channels may be described by the following class diagram:

We will represent a channel by means of the NewsChannel class to avoid confusion with the most general term of channel in the Biim platform, where the term is associated with many concepts, including

(17)

mobile shops. We have associated language and geographic context to each NewsChannel with language and location attributes, an URL to identify the remote source and descriptive information like name, description and an image to be shown when the user accesses the NewsChannel.

NewsItem represents an informative element in a NewsChannel. NewsItems exists until their NewsChannel exists.

The terminology used in NewsChannel and NewsItem is the same used in RSS for the channel and item elements.

ChannelContainer represents the concept of channel groups. Since there may exists overlapping semantics, the same NewsChannel instance may be associated with many ChannelContainer instances. The only thing which is relevant for a Channel container is a descriptive name and, more important, the aggregated NewsChannel instances.

The two remaining classes are ContentHandler and Category.

As we have seen above, NewsChannel have not to be limited in considering RSS only feeds. In this case we need something to understand or retrieve information hosted on the provided URL. The Content Handler interprets and extracts information from data available at the URL specified by the NewsChannel url field.

(18)

Category is about building up taxonomies of NewsItem instances if a taxonomy is provided by the NewsChannel the NewsItem belongs to.

4.4.2 Messaging

The messaging system has been designed to support all the Biim messaging functionalities but also to support messaging as a basic service available in the oozBase layer to be used as the basic messaging infrastructure for projects other than Biim.

With these targets in mind the domain model of the messaging system is shown in figure 13:

A Message may be viewed as a set of Content instances that a sender User wants to send to a set of recipient Users.

(19)

An User is an entity which may be identified by a set of known Address instances.

Users may be Registered system users or not and both are allowed, in theory, to send and receive messages. There is no structural constraint that impede unregistered system users to send or receive messages. However, RegisteredUsers are the only users that have an InBox and an OutBox that stores the messages the user sent or received respectively.

Messages may be delivered by using a Deliverer. The deliverer is responsible of delivering e message to its recipients using the provided recipient addresses. The Deliverer has to support another relevant feature: for recipients specified by means of an user identifier, the Deliverer may choose the best suitable address in the set of user addresses that best fits the message to be delivered. In this sense the user addresses represent the transport choices available to the Deliverer.

The selection strategy may be based on the content types and on the available addresses preserving the message information, though this is only an example an there are no specific requirements on the Deliverer behaviour. The important thing to notice is that this behaviour may be specified and changed easily in other projects.

(20)

Content represents a set of data of the same type which represent part of the overall message information. They may represent a text paragraph, an image, a video, a music and anything else that can be serialized in a bit stream. Each Content instance will have a type associated with it that can be used to correctly reconstruct the original information represented by each one.

It is assumed that the order into which contents are stored in the bearing Message is relevant and that a Content instance is meaningless if not associated with a Message instance.

4.4.3 Events

A social event may be thought as a subject of interaction between an issuer and a number of potential participants, or guests. The event initiator decides which it intends to invite and send an invitation to each one.

Each social event has a different evolution during the course of time depending on its type. The evolution can be described by means of a final state machine handling the social event state transition on the basis of the current state and an external event occurring at a given time.

According to what stated above we propose the following domain model for social events:

(21)

A SocialEvent is an event occuring at a given time, in a given place and is characterized by having a type. Each social event issuer must be a registered user. The state handling is performed by a final state machine (FSM in figure).

Each social event has a number of guests which may be registered or unregistered users. The only requirement is that it should be possible to identify them by means of an UserIdentifier.

Each guest will receive an invitation with an expiration date. Once the expiration date has come it is not possible to answer to the invitation. A number of event types exist. Each event type has to bound to a specific FSM.

(22)

4.5 Mobile mashup services and architecture

Having identified the main concepts to support the services we intend to serve through the Biim mashup application we have to identify the specific services offered to the final user and the implementation of the use cases.

4.5.1 News

The channels domain model has been mapped to the implementation classes shown in the following figure:

ChannelContainer, NewsChannel, NewsChannelItem and Category trace the channel container, news channel, news item and category

(23)

concepts described in the domain model. The YahooWeather and YahooWeatherChannelItem classes stores additional information provided by the Yahoo! Weather RSS feeds.

The <<ORM Persistable>> UML stereotype informs us that these classes are mapped to a relational database through the ORM layer implemented by Hibernate. The mapping is done by using the @Entity annotation provided by the EJB 3.0 specification. The following listing is an example of how this mapping is specified by the programmer: 65./** 66. * Represents a news channel. A news channel represents an RSS Feed. 67.  * NewsChannels can be logically composed using a {@link ChannelContainer}. 68. * Each NewsChannel is made of {@link NewsChannelItem}. 69. * For more details on rss refer to the <a href="http://www.rssboard.org/"> 70. * Rss Advisory Board</a>.   71.  * @see ChannelContainer 72. * @see NewsChannelItem 73. * @author vm 74. *  75. */ 76.@Entity 77. @AccessType("property") 78.@Table(name = NewsChannel.CLS_TABLENAME) 79.@Inheritance(strategy = InheritanceType.JOINED) 80.@DiscriminatorValue(NewsChannel.CLS_TABLENAME) 81. public class NewsChannel extends AttributeContainer implements  Comparable<NewsChannel> { 82.public static final String CLS_TABLENAME = "newschannel";

Listing 3: NewsChannel.java. Declaring a class as an ejb 3.0 Entity.

The @Entity annotation declares the NewsChannel class as an entity bean. The @AccessType annotation specifies if the entity data should be accessed by using getters (the property access type) or by accessing the field directly (the field access type). The @Table annotation

(24)

specifies that NewsChannel entity instances are stored in a newschannel table.

The @Inheritance annotation specifies the inheritance strategy to be used for an entity class hierarchy. It is specified only on the entity class that is the root of the entity class hierarchy. The @DiscriminatorValue specifies the value that discriminates the NewsChannel instances in the table or tables that will map the class hierarchy in the relational database.

News channels are about data from which we have to extract information. The object responsible for data extraction is the ContentHandler we have elicited in the Channels data model. The implementation class that maps the ContentHandler is the IDocumentHandler interface with its implementation classes:

(25)

The IDocumentHandler defines two methods: handleDocument and hasExtensions.

The first accepts a document url as parameter which is used to access the remote data source. It performs the necessary data extraction activities and returs a correctly initialized NewsChannel.

The second method is particulary meaningful for RSS sources since it allows to understand if the RSS document is supposed to support

extentions10. Tough the RSS parser is able to identify extensions in an RSS document, the hasExtensions method allows other Biim service modules to know if the channel has an extended vocabulary or not. This does not mean that the method is meaningful for RSS feeds only. Whenever we have a data source supporting vocabulary extension mechanisms, the hasExtensions method can be used to know if there are any.

The DummyDocumentHandler performs no operation. It is used with RSS feed news channels that are the default channel type in Biim. The IHtmlChannelParser defines an additional method to the IDocumentHandler interface that extracts the list of the nodes that are relevant with respect to the remote source information content. The idea is that when parsing an html document we expect to extract only

10 Since version 2.0 RSS supports an extension mechanism based on modules. Each module defines an own set of tags. For example, Yahoo weather feeds include the W3C geo vocabulary for representing spatial information and the yweather vocabulary provided by

(26)

the set of the nodes bringing information content ignoring the remaining document nodes. If the Html document is well structured chances are that it is possible to extract such information.

The YouTubeMobileChannelParser is one of the possible IHtmlChannelParser implementations. It extracts the entries provided in the You Tube mobile page, which is an XHTML document to be presented on mobile phone browsers, and stores them in a NewsChannel. Even if You Tube provides RSS video feeds, the video content data format is not suitable for mobile presentation. The You Tube mobile page provides videos in the 3GP11 format, for its wide adoption on 3G12 mobile phones, instead of the Adobe Flash Video (used by You Tube to provide video for standard users).

11 3GP is a simplified version of the MPEG-4 container format, designed to decrease storage and bandwidth requirements in order to accommodate mobile phones (expecially 3G mobile phones).

12 Third Generation mobile phones are mobile phones for third generation networks. These, in turn, are wide area cellular telephone networks which evolved to incorporate high-speed internet access and video telephony.

Figure 1 7 : MobileVie wCo m p oser interf ace a n d i m ple m e n t a tio n.

(27)

Now we are able to parse any document type, at least in theory. However, different information may require different presentation style for the Biim user: presenting incoming news from an online magazine is different from presenting weather forecasts. To take this into account we introduce the concept of MobileViewComposer: an object responsible of presenting information to the Biim user in a convenient way for a given NewsChannel.

The ImobileViewComposer interface defines a single method that represents the mobile view composition strategy. NewsFeedsComposer provides a composition strategy to be used to present news. The WeatherViewComposer is used to build up a presentation screen for weather forecasts while the YouTubeViewComposer is suitable for mobile video feeds.

Figure 1 8 : Map pin g vie w co m p oser a n d doc u m e n t h a n dler to a Ne wsC h a n n el.

(28)

The composeView method implementation in the concrete composers acts on channelCard which is modified as a side effect. The third parameter is an array of objects used to provide the necessary data to allow the concrete composer to perform the view composition.

Having the right view composer and document handler we can now map them to a specific NewsChannel using a mapping class that associates them.

The HandlersUrlMapping associates a NewsChannel with a document handler and a mobile view composer.

The handlerClassName and mobileViewComposerClassName fields store the class name of the IDocumentHandler and IMobileViewComposer concrete class names. These allow to load the correct classes at runtime using the Java reflection as shown in the diagram by the <<bind>> dependencies.

This is our solution to handle the source diversity. The proposed structure is flexible because it is easy to add now parsers and extractors or new view composers with ease by developing plug ins for new content types or to reuse existing ones, in which case only channel configuration is required.

(29)

News channels administration

To help the administrator with channels setup we have to provide a web interface for the administrator actor to set up the news channels for Biim. We can split the process in two steps:

● adding a NewsChannel;

● associating the added NewsChannel to an existing ChannelGroup or to a newly created one.

To add a new NewsChannel the administrator chooses the first menu item:

(30)

After the administrator has selected the first item it accesses the channels administration screen. Here it is able to add new channels or browse, update or delete existing ones. The feed administration screen is shown in figure 20.

Figure 2 0 : Feed a d mi nistratio n scree n. Labels in bold represe n t req uire d fields.

(31)

The labels in bold represent required information to be provided by the administrator. This sheds a light on how the document handler and mobile view composer mappings are specified: the administrator simply has to put the complete class name of the handler class.

It is also possible to define the refresh time interval. After the specified time (in the “Aggiorna ogni” field) a timer will trigger a periodical refresh action causing the latest feeds to replace the oldest existing ones.

The remaining fields are automatically extracted by the selected parser except for the languageCode field, which is selected from the administrator between the Biim platform supported language codes. The value set for the field will be the one considered in determining which feeds have to be presented to the Biim mobile user on the basis of the user language and the groups the feeds will be associated to. The feed administration screen is automatically generated by the oozBase framework by using meta information provided by layout annotations placed before the getter method declarations. To give an example on how this is accomplished we will present the code listing for the NewsChannel entity:

465./**

466.  * Gets the description of the news channel: <cite>"A phrase that  467.  * describes your channel, your channel's positioning statement"</cite> 468.  * @return the description of the news channel.

(32)

471. @VisualDescriptor(name=FLD_DESCRIPTION, editable=true, order=30, visible=true) 472. public String getDescription() {

473. return description; 474. }

Listing 4: NewsChannel.java. The @VisualDescriptor annotation with text fields.

The @VisualDescriptor name property defines the field label name. This value can be used to associate a translation to the field label itself. The editable and visible boolean properties specify if the field is editable or visible respectively, while order defines the ordinal field position in the form since fields are rendered in ascending order in the resulting web page.

The second step is to associate the feed to a new or existing group. This can be done by selecting the second menu item in the administration menu.

(33)

A new page is shown where the administrator can manage the existing groups or create a new one. For each channel group it can add one of the existing feeds and specify the name that identifies the group itself. The last administration function we are going to describe is about timers. When a new channel is added a timer is automatically started.

(34)

However, sometimes we want to have control on the timers currently running in the system.

We have developed a timer administration feature in the administration menu. Using the TimerService feature of the Java EE 5 framework the list of the existing timers is retrieved and is shown to the administrator.

It can decide which one to start or stop. Some timers may trigger child timers, as for the case of news channel timers. If the administrator

(35)

wants to start or stop all the registered timers a “start all” and “stop all” buttons are available too.

Stopped timers are shown in red while running ones are green. For each timer a start and stop buttons are provided.

Reading news on Biim mobi

We can now consider the Biim mobile user use cases for news feeds. When the user selects the Channels option in the Biim main screen (see figure 7) the user accesses the list of channels available according to its home geographic location and native language. Figure 23 shows a possible list of results for a Deutsch native speaker user.

The channels list contains all the existing channels. In the Biim application, a channel is any subclass of the AbstractChannel class. ChannelContainer is the example of channel we have seen so far, but

Figure 2 3 : List of ch a n n els for a De u tsch n a tive spe a k er user livin g in Z ü rich.

(36)

other channels do exist, like shop channels, which are represented by a Shop class. The “Import Parfumerie” entry is an example of a shop. We can see that the user can move back to the previous page (Zurück) or select the highlighted option (Wählen) by using only two buttons on the mobile phone keypad.

Choosing the entry highlighted in figure 23 the user accesses a news channel feed. The following figure shows the typical way news channels are rendered on a mobile client:

(37)

Figure 2 5 : N e ws re n deri n g

Figure 2 6 : Weat h er forecasts

The check signs inform the user that a news has been already read. By pushing again on the highlighted item in Figure 24 the user can read the news content and opt to read it in the mobile browser if the feature is supported by the device.

Figure 26 shows the typical rendering of a weather feed. The current weather conditions for the user home location are shown first, followed by the today and tomorrow forecasts.

The video feeds are rendered like news feeds. The only difference is that once the user has selected one of the available entries a video player will present the media content associated with the item instead of text screen.

(38)

ROME and the YahooWeather module

When we introduced ROME in chapter 3 we did not explain how ROME can be extended to handle RSS modules. We are going to show how we did it for the Yahoo weather RSS feed.

1. <?xml version="1.0" encoding="UTF­8" standalone="yes" ?> 2. <rss version="2.0" xmlns:yweather="http://weather.yahooapis.com/ns/rss/1.0" 3.  xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"> 4. <channel> 5.    <title>Yahoo! Weather ­ Sunnyvale, CA</title> 6.    <link>http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/ 7.    *http://xml.weather.yahoo.com/forecast/94089_f.html</link> 8.    <description>Yahoo! Weather for Sunnyvale, CA</description> 9.    <language>en­us</language> 10.   <lastBuildDate>Tue, 29 Nov 2005 3:56 pm PST</lastBuildDate> 11.    <ttl>60</ttl> 12.   <yweather:location city="Sunnyvale" region="CA" country="US"></yweather:location> 13.   <yweather:units temperature="F" distance="mi" pressure="in"  speed="mph"></yweather:units> 14.   <yweather:wind chill="57" direction="350" speed="7"></yweather:wind> 15.   <yweather:atmosphere humidity="93" visibility="1609" pressure="30.12"  rising="0"></yweather:atmosphere> 16.   <yweather:astronomy sunrise="7:02 am" sunset="4:51 pm"></yweather:astronomy> 17.    <image> 18.      <title>Yahoo! Weather</title> 19.      <width>142</width> 20.      <height>18</height> 21.       <link>http://weather.yahoo.com/</link> 22.      <url>http://us.i1.yimg.com/us.yimg.com/i/us/nws/th/main_142b.gif</url> 23.   </image> 24.   <item> 25.      <title>Conditions for Sunnyvale, CA at 3:56 pm PST</title> 26.      <geo:lat>37.39</geo:lat> 27.       <geo:long>­122.03</geo:long> 28.      <link>http://us.rd.yahoo.com/dailynews/rss/weather/ 29.      <span style="font­size: 0px"> </span>Sunnyvale__CA/* 30.      <span style="font­size: 0px"> </span>http://xml.weather.yahoo.com/<span  style="font­size: 0px"> </span>forecast/94089_f.html 31.       </link> 32.      <pubDate>Tue, 29 Nov 2005 3:56 pm PST</pubDate> 33.      <yweather:condition text="Mostly Cloudy" code="26" temp="57" date="Tue, 29 Nov  2005 3:56 34.      pm PST"></yweather:condition> 35.      <description><![CDATA[ 36. <img src="http://us.i1.yimg.com/us.yimg.com/i/us/we/52/26.gif" /><br /> 37.  <b>Current Conditions:</b><br /> 38. Mostly Cloudy, 57 F<p /> 39. <b>Forecast:</b><BR /> 40.  Tue ­ Mostly Cloudy. High: 62 Low: 45<br /> 41.   Wed ­ Mostly Cloudy. High: 60 Low: 52<br /> 42.  Thu ­ Rain. High: 61 Low: 46<br /> 43.<br />

(39)

44.<a  href="http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://xml.weather. yahoo.com/forecast/94089_f.html">Full Forecast at Yahoo! Weather</a><BR/> 45. (provided by The Weather Channel)<br/>]]> 46.      </description> 47.       <yweather:forecast day="Tue" date="29 Nov 2005" low="45" high="62" text="Mostly  Cloudy" 48.      code="27"></yweather:forecast> 49.      <yweather:forecast day="Wed" date="30 Nov 2005" low="52" high="60" text="Mostly  Cloudy" 50.      code="28"></yweather:forecast> 51.       <guid isPermaLink="false">94089_2005_11_29_15_56_PST</guid> 52.   </item> 53.</channel> 54.</rss>

Listing 5 : A sample yahoo weather RSS feed.

Rows 2 and 3 defines two RSS modules by providing their XML namespaces: yweather for Yahoo Weather and geo for the Basic Geo Vocabulary13.

The Geo Vocabulary is already supported by ROME, but no support is provided for Yahoo Weather. We have to implement the module parser by ourselves.

First we must start with the bean interface: YahooWeatherModule. YahooWeatherModule must extend the Module interface that defines a method, getUri(), which returns the URI that identifies the module. At row 2 we read that the URI is http://weather.yahooapis.com/ns/rss/1.0.

The yweather module defines seven elements:

(40)

yweather:units: units for various aspects of the forecast (row 13);

yweather:wind: forecast information about wind (row 14);

yweather:atmosphere: forecast information about current atmospheric pressure, humidity, and visibility (row 15);

yweather:astronomy: forecast information about current astronomical conditions (row 16);

yweather:condition: the current weather conditions (row 33);yweather:forecast: the weather forecast for a specific day. The

item element contains multiple forecast elements for today and tomorrow (rows 47 and 49).

This implies that the YahooWeatherModule bean interface will define seven properties: 1. /** 2.  *  3.  */ 4. package net.oneoverzero.biim.modules.rss.yahoo.weather; 5. 6. import java.util.List; 7. 8. import com.sun.syndication.feed.module.Module; 9. 10./** 11.  * Module decoding the Yahoo weather extension. 12. * This module is meant to work with Rome 0.9. 13. * look at <a href="http://developer.yahoo.com/weather/"> 14. * Yahoo weather page</a> for further details. 15. * @author vm 16. *

(41)

17.  */ 18.public interface YahooWeatherModule extends Module { 19. 20. public static final String URI = "http://xml.weather.yahoo.com/ns/rss/1.0"; 21. /** 22.  * Gets the forecast information about current  23.  * astronomical conditions. 24.  * @return the forecast information about current 25.  * astronomical conditions. 26.  */ 27. YWAstronomyForecast getAstronomyForecast(); 28. /** 29.  * Sets the forecast information about current  30.  * astronomical conditions. 31.  * @param astronomyForecast the forecast information  32.  * about current astronomical conditions. 33.  */ 34. void setAstronomyForecast(YWAstronomyForecast astronomyForecast); 35. /** 36.  * Gets the forecast information about current atmospheric pressure,  37.  * humidity, and visibility. 38.  * @return the forecast information about current atmospheric pressure. 39.  */ 40. YWAtmosphereForecast getAtmosphereForecast(); 41. /** 42.  * Sets the forecast information about current atmospheric pressure,  43.  * humidity, and visibility. 44.  * @param atmosphere the forecast information about current atmospheric pressure,  45.  * humidity, and visibility. 46.  */ 47. void setAtmosphereForecast(YWAtmosphereForecast atmosphere); 48. /** 49.  * Gets the location of this forecast. 50.  * @return the location of this forecast. 51.  */ 52. YWLocation getLocation(); 53. /** 54.  * Sets the location of this forecast. 55.  * @param yahooWeatherLocation the location of this forecast. 56.  */ 57. void setLocation(YWLocation yahooWeatherLocation); 58. /** 59.  * Gets the forecast information about wind. 60.  * @return forecast information about wind. 61.  */ 62. YWWindForecast getWindForecast(); 63. /** 64.  * Sets the forecast information about wind. 65.  * @param wind the forecast information about wind. 66.  */ 67. void setWindForecast(YWWindForecast wind); 68. /** 69.  * Gets the units for various aspects of the forecast. 70.  * Note that the default RSS feed uses Fahrenheit degree units  71.  * and English units for all other attributes  72.  * (miles, pounds per square inch, miles per hour). 

(42)

74.  * (using the u request parameter), all the units are in metric format  75.  * (Celsius, kilometers, millibars, kilometers per hour). 76.  * @return the units for the aforementioned aspects of the forecast. 77.  */ 78. YWUnits getUnits(); 79. /** 80.  * Gets the units for various aspects of the forecast. 81.  * Note that the default RSS feed uses Fahrenheit degree units  82.  * and English units for all other attributes  83.  * (miles, pounds per square inch, miles per hour).  84.  * If Celsius has been specified as the degree units for the feed  85.  * (using the u request parameter), all the units are in metric format  86.  * (Celsius, kilometers, millibars, kilometers per hour). 87.  * @param units the units for the aforementioned aspects of the forecast. 88.  */ 89. void setUnits(YWUnits units); 90. /** 91.  * Gets the current weather condition. 92.  * @return the current weather condition. 93.  */ 94. YWWeatherCondition getWeatherCondition(); 95. /** 96.  * Sets the current weather condition. 97.  * @param weatherCondition the current weather condition. 98.  */ 99. void setWeatherCondition(YWWeatherCondition weatherCondition); 100. /** 101.  * Gets the weather forecasts for today and two days in the  102.  * future. 103.  * @return the list of the weather forecasts for today and 104.  * two days in the future. 105.  */ 106. List<YWWeatherForecast> getWeatherForecasts(); 107. /** 108.  * Sets the weather forecasts for today and two days in the  109.  * future. 110.  * @param weatherForecasts the list of the weather forecasts for 111.  * today and two days in the future. 112.  */ 113. void setWeatherForecasts(List<YWWeatherForecast> weatherForecasts); 114.}

Listing 6: YahooWeatherModule.java. The Module interface.

Next we have to write the implementation, YahooWeatherModuleImpl, that must also extend ModuleImpl (the default implementation of the Module interface). ModuleImpl provides equals, hashCode, toString and clone support for the properties of the class given in the constructor. Also the URI of the

(43)

yweather module is indicated; it will be used by the Module.getUri() method. 1. /** 2.  *  3.  */ 4. package net.oneoverzero.biim.modules.rss.yahoo.weather; 5. 6. import java.util.ArrayList; 7. import java.util.Collections; 8. import java.util.List; 9. 10.import com.sun.syndication.feed.module.ModuleImpl; 11. 12./** 13. * A {@link net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule  YahooWeatherModule} 14. * implementation. 15. * @author vm 16. * 17.  */ 18.public class YahooWeatherModuleImpl extends ModuleImpl implements YahooWeatherModule  { 19. 20. private YWAstronomyForecast astronomyForecast; 21. private YWAtmosphereForecast atmosphereForecast; 22. private YWLocation location; 23. private YWUnits units; 24. private YWWeatherCondition weatherCondition; 25. private List<YWWeatherForecast> weatherForecasts; 26. private YWWindForecast windForecast; 27. 28. public YahooWeatherModuleImpl() { 29. super(YahooWeatherModule.class, YahooWeatherModule.URI); 30. weatherForecasts = new ArrayList<YWWeatherForecast>(); 31. } 32. 33. private static final long serialVersionUID = 1L; 34. 35. /* (non­Javadoc) 36.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#getAstronomyForecas t() 37.  */ 38. public YWAstronomyForecast getAstronomyForecast() { 39. return astronomyForecast; 40. } 41. 42. /* (non­Javadoc) 43.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#setAstronomyForecas t(net.oneoverzero.biim.modules.rss.yahoo.weather.YWAstronomyForecast) 44.  */ 45. public void setAstronomyForecast(YWAstronomyForecast astronomyForecast) {

(44)

46. this.astronomyForecast=astronomyForecast; 47. } 48. 49. /* (non­Javadoc) 50.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#getAtmosphereForeca st() 51.  */ 52. public YWAtmosphereForecast getAtmosphereForecast() { 53. return atmosphereForecast; 54. } 55. 56. /* (non­Javadoc) 57.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#setAtmosphereForeca st(net.oneoverzero.biim.modules.rss.yahoo.weather.YWAtmosphereForecast) 58.  */ 59. public void setAtmosphereForecast(YWAtmosphereForecast atmosphere) { 60. this.atmosphereForecast = atmosphere; 61. 62. } 63. 64. /* (non­Javadoc) 65.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#getLocation() 66.  */ 67. public YWLocation getLocation() { 68. return location; 69. } 70. 71. /* (non­Javadoc) 72.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#setLocation(net.one overzero.biim.modules.rss.yahoo.weather.YWLocation) 73.  */ 74. public void setLocation(YWLocation yahooWeatherLocation) { 75. location = yahooWeatherLocation; 76. } 77. 78. /* (non­Javadoc) 79.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#getWindForecast() 80.  */ 81. public YWWindForecast getWindForecast() { 82. return windForecast; 83. } 84. 85. /* (non­Javadoc) 86.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#setWindForecast(net .oneoverzero.biim.modules.rss.yahoo.weather.YWWindForecast) 87.  */ 88. public void setWindForecast(YWWindForecast wind) { 89. windForecast=wind; 90. } 91. 92. /* (non­Javadoc) 93.  * @see 

(45)

net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#getUnits() 94.  */ 95. public YWUnits getUnits() { 96. return units; 97. } 98. 99. /* (non­Javadoc) 100.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#setUnits(net.oneove rzero.biim.modules.rss.yahoo.weather.YWUnits) 101.  */ 102. public void setUnits(YWUnits units) { 103. this.units=units; 104. } 105. 106. /* (non­Javadoc) 107.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#getWeatherCondition () 108.  */ 109. public YWWeatherCondition getWeatherCondition() { 110. return weatherCondition; 111. } 112. 113. /* (non­Javadoc) 114.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#setWeatherCondition s(net.oneoverzero.biim.modules.rss.yahoo.weather.YWWeatherCondition) 115.  */ 116. public void setWeatherCondition(YWWeatherCondition weatherCondition) { 117. this.weatherCondition=weatherCondition; 118. } 119. 120. /* (non­Javadoc) 121.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#getWeatherForecasts () 122.  */ 123. public List<YWWeatherForecast> getWeatherForecasts() { 124. if(weatherForecasts==null) 125. return Collections.emptyList(); 126. return weatherForecasts; 127. } 128. 129. /* (non­Javadoc) 130.  * @see  net.oneoverzero.biim.modules.rss.yahoo.weather.YahooWeatherModule#setWeatherForecasts (java.util.List) 131.  */ 132. public void setWeatherForecasts(List<YWWeatherForecast> weatherForecasts) { 133. this.weatherForecasts=weatherForecasts; 134. } 135. 136. /* (non­Javadoc) 137.  * @see com.sun.syndication.feed.CopyFrom#getInterface() 138.  */ 139. public Class getInterface() {

(46)

141. } 142. 143. /* (non­Javadoc) 144.  * @see com.sun.syndication.feed.CopyFrom#copyFrom(java.lang.Object) 145.  */ 146. public void copyFrom(Object obj) { 147. if(obj instanceof YahooWeatherModule) { 148. YahooWeatherModule yahooModule = (YahooWeatherModule) obj; 149. setAstronomyForecast((YWAstronomyForecast)  yahooModule.getAstronomyForecast().clone()); 150. setAtmosphereForecast((YWAtmosphereForecast)  yahooModule.getAtmosphereForecast().clone()); 151. setLocation((YWLocation) yahooModule.getLocation().clone()); 152. setUnits((YWUnits) yahooModule.getUnits().clone()); 153. setWeatherCondition((YWWeatherCondition)  yahooModule.getWeatherCondition().clone()); 154. weatherForecasts.clear(); 155. for(YWWeatherForecast weatherForecast :  yahooModule.getWeatherForecasts()) { 156. weatherForecasts.add((YWWeatherForecast)  weatherForecast.clone()); 157. } 158. setWindForecast((YWWindForecast)  yahooModule.getWindForecast().clone()); 159. } 160. } 161. 162.}

Listing 7: YahooWeatherModuleImpl.java. The YahooWeather module implementation.

We can see the call to the ModuleImpl constructor at row 29.

The module properties are just Java Bean properties. The only catch is to follow ROME semantics for Collection properties: in the case of a null value for the collection, an empty collection must be returned. Also, following ROME semantics, all properties are by reference, including mutable ones.

The getInterface method (row 139) returns the bean interface of the implementation (this is necessary for collections containing subclasses such as a list of modules).

(47)

The copyFrom method (row 146) copies all the properties from the parameter object (which must be a YahooWeatherModule implementation) into the caller bean properties. The copyFrom method must do a deep copy.

The yweather module parser must implement the ModuleParser interface. This interface defines 2 methods, getNameSpaceURI, that returns the URI of the module and parse, which extracts the module elements from the given Element.

The feed parsers will invoke the module parser with a feed element or with an item element. The module parser must look for module elements in the children of the given element. That is what the YahooWeatherModuleParser parser is doing when looking for

forecast child element in the received element.

In the case of the forecast element it looks for all occurrences as the yweather module schema allows for more than one occurrence of the forecast element. A YahooWeatherModule bean is created and the found values are set into it.

If no YahooWeatherModule elements are found in the feed, the parse method returns null. This is to avoid having an empty instance of a module, not present in the feed, in the feed bean or in the item bean.

(48)

3.  */ 4. package net.oneoverzero.biim.modules.rss.yahoo.weather; 5. 6. import java.util.ArrayList; 7. import java.util.Collections; 8. import java.util.List; 9. 10.import  net.oneoverzero.biim.modules.rss.yahoo.weather.YWAtmosphereForecast.BarometricPressur eState; 11. import net.oneoverzero.biim.modules.rss.yahoo.weather.YWUnits.Distance; 12.import net.oneoverzero.biim.modules.rss.yahoo.weather.YWUnits.Pressure; 13.import net.oneoverzero.biim.modules.rss.yahoo.weather.YWUnits.Speed; 14.import net.oneoverzero.biim.modules.rss.yahoo.weather.YWUnits.Temperature; 15.import  net.oneoverzero.biim.modules.rss.yahoo.weather.YWWeatherCondition.ConditionCodes; 16. 17. import org.apache.commons.logging.Log; 18.import org.apache.commons.logging.LogFactory; 19.import org.jdom.Attribute; 20.import org.jdom.Element; 21. import org.jdom.Namespace; 22. 23.import com.sun.syndication.feed.module.Module; 24.import com.sun.syndication.io.ModuleParser; 25. 26./** 27.  * A Yahoo Weather rss feed parser implementation 28. * @author vm 29. * 30. */ 31. public class YahooWeatherModuleParser implements ModuleParser { 32. 33. private static final Namespace YAHOOWEATHER_NS = 34. Namespace.getNamespace("yweather",YahooWeatherModule.URI); 35. 36. private Log log = LogFactory.getLog(YahooWeatherModuleParser.class); 37. 38. private enum ElementNames { 39. location, units, wind, atmosphere, astronomy, condition, forecast; 40. } 41. 42. private enum LocationAttributesNames { 43. city, region, country; 44. } 45. 46. private enum UnitsAttributesNames { 47. temperature, distance, pressure, speed; 48. } 49. 50. private enum WindAttributesNames { 51. chill, direction, speed; 52. } 53. 54. private enum AtmosphereAttributesNames { 55. humidity, visibility, pressure, rising; 56. } 57.

(49)

58. private enum ConditionAttributesNames { 59. code, temp, date, text; 60. } 61. 62. private enum ForecastAttributesNames { 63. day, date, low, high, text, code; 64. } 65. /* (non­Javadoc) 66.  * @see com.sun.syndication.io.ModuleParser#getNamespaceUri() 67.  */ 68. public String getNamespaceUri() { 69. return YahooWeatherModule.URI; 70. } 71. 72. /* (non­Javadoc) 73.  * @see com.sun.syndication.io.ModuleParser#parse(org.jdom.Element) 74.  */ 75. public Module parse(Element docRoot) { 76. boolean yahooElementsFound = false; 77. YahooWeatherModule weatherModule = new YahooWeatherModuleImpl(); 78. 79. // parse location 80. YWLocation location = parseLocation(docRoot); 81. if(location != null) { 82. yahooElementsFound=true; 83. weatherModule.setLocation(location); 84. } 85. 86. // parse units 87. YWUnits units = parseUnits(docRoot); 88. if(units != null) { 89. yahooElementsFound=true; 90. weatherModule.setUnits(units); 91. } 92. 93. // parse wind 94. YWWindForecast wind = parseWind(docRoot); 95. if(wind != null) { 96. yahooElementsFound=true; 97. weatherModule.setWindForecast(wind); 98. } 99. 100. // parse atmosphere 101. YWAtmosphereForecast atmosphere = parseAtmosphere(docRoot); 102. if(atmosphere != null) { 103. yahooElementsFound=true; 104. weatherModule.setAtmosphereForecast(atmosphere); 105. } 106. 107. // parse condition 108. YWWeatherCondition condition = parseCondition(docRoot); 109. if(condition != null) { 110. yahooElementsFound=true; 111. weatherModule.setWeatherCondition(condition); 112. } 113. 114. // parse forecasts

(50)

116. if(forecasts.size()>0) 117. yahooElementsFound=true; 118. weatherModule.setWeatherForecasts(forecasts); 119. 120. return (yahooElementsFound)?weatherModule:null; 121. } 122. 123. private List<YWWeatherForecast> parseForecasts(Element docRoot) { 124.  if(docRoot == null) 125.  return Collections.emptyList(); 126.  @SuppressWarnings("unchecked") 127.  List<Element> elements =  docRoot.getChildren(ElementNames.forecast.name(), 128.  YAHOOWEATHER_NS); 129.  if(elements==null) 130.  return Collections.emptyList(); 131.  List<YWWeatherForecast> forecasts = new ArrayList<YWWeatherForecast>( 132.  elements.size()); 133.  for(Element e : elements) { 134.  YWWeatherForecast forecast = parseForecast(e); 135.  if(forecast!=null) 136.  forecasts.add(forecast); 137.  } 138.  return forecasts; 139. } 140. 141. private YWWeatherForecast parseForecast(Element forecastElement) { 142. if(forecastElement == null) 143. return null; 144. YWWeatherForecast forecast = new YWWeatherForecast(); 145. @SuppressWarnings("unchecked") 146. List<Attribute> forecastAttributes = forecastElement.getAttributes(); 147. for(Attribute forecastAttribute : forecastAttributes) { 148. String attributeValue = forecastAttribute.getValue(); 149. String attributeName = forecastAttribute.getName(); 150. if(attributeName.equals(ForecastAttributesNames.code.name())) { 151. try { 152. forecast.setCode(Integer.valueOf(attributeValue)); 153. } catch(NumberFormatException ex) { 154. log.error("Wrong format for  "+ForecastAttributesNames. 155. code.name()+". Invalid value  "+attributeValue+ 156. ". Skipping attribute parsing!",ex); 157. forecast.setCode(null); 158. } 159. } else  if(attributeName.equals(ForecastAttributesNames.date.name())) { 160. forecast.setDate(attributeValue); 161. } else  if(attributeName.equals(ForecastAttributesNames.day.name())) { 162. forecast.setDay(attributeValue); 163. } else  if(attributeName.equals(ForecastAttributesNames.high.name())) { 164. try { 165. forecast.setHigh(Integer.valueOf(attributeValue)); 166. } catch (NumberFormatException e) { 167. log.error("Wrong format for 

(51)

"+ForecastAttributesNames. 168. high.name()+". Invalid value  "+attributeValue+ 169. ". Skipping attribute parsing!",e); 170. forecast.setHigh(null); 171. } 172. } else  if(attributeName.equals(ForecastAttributesNames.low.name())) { 173. try { 174. forecast.setLow(Integer.valueOf(attributeValue)); 175. } catch (NumberFormatException e) { 176. log.error("Wrong format for  "+ForecastAttributesNames. 177. low.name()+". Invalid value  "+attributeValue+ 178. ". Skipping attribute parsing!",e); 179. forecast.setLow(null); 180. } 181. } else  if(attributeName.equals(ForecastAttributesNames.text.name())) { 182. forecast.setText(attributeValue); 183. } 184. } 185. return forecast; 186. } 187. 188. private YWWeatherCondition parseCondition(Element docRoot) { 189. if(docRoot == null) 190. return null; 191. Element e = docRoot.getChild(ElementNames.condition.name(), 192. YAHOOWEATHER_NS); 193. if(e != null) { 194. YWWeatherCondition weatherCondition = new YWWeatherCondition(); 195. @SuppressWarnings("unchecked") 196. List<Attribute> weatherAttributes = e.getAttributes(); 197. for(Attribute weatherAttribute : weatherAttributes) { 198. String attributeValue = weatherAttribute.getValue(); 199. String attributeName = weatherAttribute.getName(); 200. if(attributeName.equals(ConditionAttributesNames.code.name())) { 201. try { 202. weatherCondition.setCode(Integer.parseInt(attributeValue)); 203. } catch (NumberFormatException ex) { 204. log.error("Wrong format for  "+ConditionAttributesNames. 205. code.name()+". Invalid value  "+attributeValue+ 206. ". Skipping attribute  parsing!",ex); 207. weatherCondition.setCode( 208. ConditionCodes.NOT_AVAILABLE.getYahooCode()); 209. } 210. } else if(attributeName.equals( 211. ConditionAttributesNames.date.name())) { 212. weatherCondition.setDate(attributeValue);

(52)

214. ConditionAttributesNames.temp.name())) { 215. try { 216. weatherCondition.setTemp(Integer.parseInt(attributeValue)); 217. } catch(NumberFormatException ex) { 218. log.error("Wrong format for  "+ConditionAttributesNames. 219. temp.name()+". Invalid value  "+attributeValue+ 220. ". Skipping attribute  parsing!",ex); 221. weatherCondition.setTemp(null); 222. } 223. } else if(attributeName.equals( 224. ConditionAttributesNames.text.name())) { 225. weatherCondition.setText(attributeValue); 226. } 227. } 228. return weatherCondition; 229. } 230. return null; 231. } 232. 233. private YWAtmosphereForecast parseAtmosphere(Element docRoot) { 234. if(docRoot == null) 235. return null; 236. Element e = docRoot.getChild(ElementNames.atmosphere.name(), 237. YAHOOWEATHER_NS); 238. if(e != null) { 239. YWAtmosphereForecast atmosphereForecast = new  YWAtmosphereForecast(); 240. @SuppressWarnings("unchecked") 241. List<Attribute> atmosphereAttributes = e.getAttributes(); 242. for(Attribute atmosphereAttribute : atmosphereAttributes) { 243. String attributeValue = atmosphereAttribute.getValue(); 244. String attributeName = atmosphereAttribute.getName(); 245. if(attributeName.equals( 246. AtmosphereAttributesNames.humidity.name()))  { 247. try { 248. atmosphereForecast.setHumidity( 249. Integer.parseInt(attributeValue)); 250. } catch(NumberFormatException ex) { 251. log.error("Wrong format for  "+AtmosphereAttributesNames. 252. humidity.name()+". Invalid  value "+attributeValue+ 253. ". Skipping attribute  parsing!",ex); 254. atmosphereForecast.setHumidity(­1); 255. } 256. 257. } else if (attributeName.equals( 258. AtmosphereAttributesNames.pressure.name()))  { 259. try { 260. atmosphereForecast.setPressure(

(53)

261. Float.parseFloat(attributeValue)); 262. } catch(NumberFormatException ex) { 263. log.error("Wrong format for  "+AtmosphereAttributesNames. 264. pressure.name()+". Invalid  value "+attributeValue+ 265. ". Skipping attribute  parsing!",ex); 266. atmosphereForecast.setPressure(­1); 267. } 268. } else if(attributeName.equals( 269. AtmosphereAttributesNames.rising.name())) { 270. try { 271. atmosphereForecast.setRising(BarometricPressureState.valueof( 272. Integer.parseInt(attributeValue))); 273. } catch(NumberFormatException ex) { 274. log.error("Wrong format for  "+AtmosphereAttributesNames. 275. rising.name()+". Invalid  value "+attributeValue+ 276. ". Skipping attribute  parsing!",ex); 277. atmosphereForecast.setRising(null); 278. } 279. } else if(attributeName.equals( 280. AtmosphereAttributesNames.visibility.name())) { 281. try { 282. atmosphereForecast.setVisibility( 283. Math.round(Float.parseFloat((attributeValue)))); 284. } catch(NumberFormatException ex) { 285. log.error("Wrong format for  "+AtmosphereAttributesNames. 286. visibility.name()+". Invalid  value "+ 287. attributeValue+". Skipping  attribute parsing!",ex); 288. atmosphereForecast.setVisibility(­1); 289. } 290. } 291. } 292. return atmosphereForecast; 293. } 294. return null; 295. } 296. 297. private YWWindForecast parseWind(Element docRoot) { 298. if(docRoot == null) 299.  return null; 300. Element e = docRoot.getChild(ElementNames.wind.name(), 301. YAHOOWEATHER_NS); 302. if(e != null) { 303. YWWindForecast windForecast = new YWWindForecast();

(54)

305. List<Attribute> windAttributes = e.getAttributes(); 306. for(Attribute windAttribute : windAttributes) { 307. String attributeValue = windAttribute.getValue(); 308. String attributeName = windAttribute.getName(); 309. if(attributeName.equals( 310. WindAttributesNames.chill.name())) { 311. try { 312. windForecast.setChill(Integer.parseInt(attributeValue)); 313. } catch(NumberFormatException ex) { 314. log.error("Wrong format for  "+WindAttributesNames. 315. chill.name()+". Invalid value  "+attributeValue+ 316. ". Skipping attribute  parsing!",ex); 317. windForecast.setChill(­1); 318. } 319. } else if(attributeName.equals( 320. WindAttributesNames.direction.name())) { 321. try { 322. windForecast.setDirection(Integer.parseInt(attributeValue)); 323. } catch(NumberFormatException ex) { 324. log.error("Wrong format for  "+WindAttributesNames. 325. direction.name()+". Invalid  value "+attributeValue+ 326. ". Skipping attribute  parsing!",ex); 327. windForecast.setDirection(­1); 328. } 329. } else if(attributeName.equals( 330. WindAttributesNames.speed.name())) { 331. try { 332. windForecast.setSpeed(Math.round(Float.parseFloat((attributeValue)))); 333. }catch(NumberFormatException ex) { 334. log.error("Wrong format for  "+WindAttributesNames. 335. speed.name()+". Invalid value  "+attributeValue+ 336. ". Skipping attribute  parsing!",ex); 337. windForecast.setSpeed(­1); 338. } 339. } 340. } 341. return windForecast; 342. } 343. return null; 344. } 345. 346. private YWUnits parseUnits(Element docRoot) { 347. if(docRoot == null) 348. return null; 349. Element e = docRoot.getChild(ElementNames.units.name(), 350. YAHOOWEATHER_NS);

(55)

351. if(e != null) { 352. YWUnits units = new YWUnits(); 353. @SuppressWarnings("unchecked") 354. List<Attribute> unitsAttributes = e.getAttributes(); 355. for(Attribute unitsAttribute : unitsAttributes) { 356. String attributeValue = unitsAttribute.getValue(); 357. String attributeName = unitsAttribute.getName(); 358. if(attributeName.equals( 359. UnitsAttributesNames.temperature.name())) { 360. units.setTemperature(Temperature.valueOf(attributeValue.toLowerCase())); 361. } else if(attributeName.equals( 362. UnitsAttributesNames.speed.name())) { 363. units.setSpeed(Speed.valueOf(attributeValue.toLowerCase())); 364. } else if(attributeName.equals( 365. UnitsAttributesNames.pressure.name())) { 366. units.setPressure(Pressure.valueOf(attributeValue.toLowerCase())); 367. } else if(attributeName.equals( 368. UnitsAttributesNames.distance.name())) { 369. units.setDistance(Distance.valueOf(attributeValue.toLowerCase())); 370. } 371. } 372. return units; 373. } 374. return null; 375. } 376. 377. private YWLocation parseLocation(Element docRoot) { 378.  if(docRoot == null) 379.  return null; 380. Element e = docRoot.getChild(ElementNames.location.name(), 381. YAHOOWEATHER_NS); 382. if(e != null) { 383. YWLocation location = new YWLocation(); 384. @SuppressWarnings("unchecked") 385. List<Attribute> locationAttributes = e.getAttributes(); 386. for(Attribute locationAttribute : locationAttributes) { 387. String attributeValue = locationAttribute.getValue(); 388. String attributeName = locationAttribute.getName(); 389. if(attributeName.equals( 390. LocationAttributesNames.city.name())) { 391. location.setCity(attributeValue); 392. } else if(attributeName.equals( 393. LocationAttributesNames.country.name())) { 394. location.setCountry(attributeValue); 395. } else if(attributeName.equals( 396. LocationAttributesNames.region.name())) { 397. location.setRegion(attributeValue); 398. } 399. } 400. return location; 401. } 402. return null; 403. }

Figura

Figure 7 : Bii m  m a i n  scree n
Figure 8 : T ec h nologies u sed  in Bii m  de velop m e n t  (yello w  boxes)   a n d  d e ploy m e n t.
Figure 9 : Bii m  logical over vie w
Figure 1 0 : Bii m  u ser m i ni m al set of use cases
+7

Riferimenti

Documenti correlati

petals…sat on the back of the toilet…whenever we drop legislation into the bowl of Congress, democracy acts as an air freshener. In this case, the scatological humor comes from

This theory is based on the observation that in this patients, beyond to well known reduction in norepinephrine and serotonin contents, neurotrophins levels are

Then we have studied the abundance gradients along the Galactic disk produced by our best cosmological model and their dependence upon several parameters: a threshold in the surface

Essere liberi dalla paura e dal bisogno per essere capaci di esercitare la libertà in senso pieno è quindi agli occhi della Arendt una condizione

In un recente volume sulle guerre tra cristiani e musulmani, l’autore, ricordando le figure di due condottieri difensori della cristianità dall’islam, Giovanni

By using a loss of function approach in Xenopus embryos I demonstrated in vivo, for the first time, the capacity of serotonin, via 5-HT2B receptor, to act as a

If the ultimate end of representation using perspective – and all of the classic delineation derived from it – was founded on the attempt to (re)construct – or reproduce – space

This thesis has been developed in collaboration with Outokumpu Copper Superconductors Italy, a company that works in superconductors’ field.. Our thesis target was to apply