7.4 JAXR Registry Model Overview


A JAXR client views the registry as a set of objects whose types are defined in the javax.xml.registry.infomodel package. The information model is based on the one defined by the ebXML registry/repository specification, with some minor differences. A JAXR provider for a particular registry is required to transparently map between the JAXR information model and the real model of the registry itself, so that JAXR clients are not dependent on the details of any particular registry. This section provides an overview of the JAXR registry information model. You'll see more detail when we look at the JAXR registry programming model later in this chapter.

Figure 7-6 shows a small part of the complete JAXR registry model, illustrating the elements that are of greatest importance to most JAXR clients. The first thing to note about this diagram is that it contains only Java interfaces. In fact, ignoring exceptions, the JAXR API contains only one class that is not an interface. The use of interfaces allows a JAXR provider to supply its own implementation classes for each element of the information model without exposing them to application code. From the client application's point of view, this has the effect that objects within the registry cannot be created directly ” instead, they are obtained from using factory methods of a class called BusinessLifeCycleManager , which will be described later in this chapter.

Figure 7-6. Organization- and Service- related registry objects

A business that submits information to the registry is represented by an Organization object. Associated with each Organization is a distinguished person called the primary contact, represented by a User object. User has several attributes, including two that are shown here: a name and a postal address. As we'll see later, the PostalAddress interface is particularly interesting because there is no commonly agreed way to represent a postal address within a registry, which leads to some complications for the application client. User objects also appear within the audit trail (not shown in the diagram) that is maintained by level 1 registries.

An organization usually enters itself into a registry in order to advertise its services. Each such service is represented by a Service object. In the JAXR information model, a Service object is bound to an organization and therefore organizations offering identical services cannot share the same registry entries for those services. Service is actually a simple container object that references one or more ServiceBinding s. A ServiceBinding contains the information that a client might need to use a service, including the URI at which the service can be reached, and, optionally , one or more SpecificationLink s that might provide technical information on how the service is to be invoked. In a properly constructed ServiceBinding , one of the SpecificationLink s would point to the WSDL definition for the service.

In the case of a UDDI registry, a WSDL definition for a service is referenced using its URI, whereas an ebXML registry might actually contain a copy of the definition itself. This illustrates an important difference between these two registry types: a UDDI registry is a pure registry and contains only metadata, whereas the ebXML registry is also a repository, allowing the storage of objects as well as metadata. In terms of the JAXR API, the repository functionality is modeled by the ExtrinsicObject interface, which is a level 1 feature described later in this chapter.

7.4.1 Information Model Interfaces

A class hierarchy diagram covering most of the interfaces that form the JAXR registry information model is shown in Figure 7-7. The complete set of interfaces, together with a brief description of their function, is listed in Table 7-1. More detailed descriptions will be found later in this chapter. The presence of a symbol in the "Level 0 methods" column indicates that the interface includes at least one method that can be used with a level 0 JAXR provider. If this column is empty, then the interface is (at least currently) of use only with a level 1 provider. When a symbol appears in both the "Level 0 methods" and "Level 1 methods" columns , then some functionality within the interface is useful only in conjunction with a level 1 provider.

Figure 7-7. Registry object class diagram
Table 7-1. Interfaces in the javax.xml.registry.infomodel package


Level 0 methods

Level 1 methods




Represents an association between two entities in the registry. An association has a type, which reflects the kind of relationship being described. An example of this is Replaces , which could be used to indicate that one service has been superseded by another. See Section later in this chapter for further information.



An entry in the audit trail for an object in the registry. Only level 1 registries provide auditing, which is described in Section, later in this chapter.



Represents a classification that can be applied to a registry object. Applying one or more classifications to an object can make it much easier for clients to locate businesses and services of interest. See Section 7.4.4, later in this chapter.


A scheme used to classify registry objects. See Section 7.4.4 later in this chapter for further information.



A facet of the JAXR registry model that maps onto several different features of the UDDI and ebXML registries. Concepts are typically used to represent nodes in a classification scheme or elements of an enumerated type.



Represents an email address associated with a User object. A User may have any number of email addresses.



The base interface for all objects within the registry. ExtensibleObject provides methods that allow arbitrary attributes to be added to a registry object without the need for an additional API. See Section 7.4.3 later in this chapter for a description of this interface.



A string value that may be attached to a registry object to provide additional identification information for that object. See Section 7.4.2 later in this chapter for further information.



Used to associate a link to additional information with a registry object. The most common use of an external link is to include a reference to the home page of the organization that submitted the registry object.



Represents stored data that is not of a type that the registry can handle directly, such as a document or an image file. ExtrinsicObject s can only be used with a level 1 registry provider. See Section later in this chapter for an example of the use of this facility.



U sed in the JAXR API where a string that may need to be localized is required. It contains a LocalizedString instance for each locale for which a representation of the string has been supplied.



Each object in the registry is assigned a unique identifier when it is created. The value of this identifier is held within the RegistryObject as a Key object. The key can be used to fetch the object at a later time, or to delete it. See Section 7.4.2 for further information.



A localized version of a string, together with its associated locale and character set. LocalizedString s are wrapped within InternationalString s.


Represents a business within the registry. See Section, later in this chapter.


Represents the name of a registry user. See Section, later in this chapter.



Represents the address of a user or (for a level 1 registry) an organization. Unfortunately, as described in Section 7.5.7, later in this chapter, this is not as simple a topic as you might expect.



A subinterface of RegistryObject from which a small number of objects in the registry information model are derived. See Section 7.4.2 later in this chapter for more information.


Defines the attributes and methods that form part of every object stored in the registry. See Section 7.4.2 later in this chapter for a more complete description.



A container class that allows registry objects to be grouped together. Holding a set of objects in a RegistryPackage makes it simple to get a list of them all at a later time, perhaps in order to remove them all. RegistryPackage s are supported only by level 1 providers.



Represents a service advertised by an organization. A Service contains one or more ServiceBindings .



Contains the information necessary for a client to invoke an instance of a service and may also refer, via SpecificationLink s, to technical information regarding the service. See Section later in this chapter for details.



Used to attach additional attributes to ExtensibleObject s as described in Section 7.4.3, later in this chapter.



Used to add a reference to a technical description to a ServiceBinding . The link may be a URI or, in the case of a level 1 registry, may refer to an ExtrinsicObject in the repository.


Represents a telephone number for a registry user. See Section later in this chapter.



A n interface implemented by other objects that contain a URI and that may optionally be requested to validate it. For example, when an ExternalLink is created, the registry may check that the URI that it contains points to an accessible object. The methods of URIValidator allow this validation to be turned on or off, as required.


Represents a user of the registry. References to User objects also appear in the audit trail maintained by level 1 registries. See Section and Section later in this chapter for further details.



An interface implemented by objects that might have associated version numbers . All RegistryEntry objects implement this interface.

7.4.2 RegistryObject and RegistryEntry

RegistryObject is the base interface from which almost all of the other interfaces that represent entities stored in the registry are derived. RegistryObject is itself derived from ExtensibleObject , a simple interface that makes it possible to add additional attributes to any object in the registry, as described later in Section 7.4.3. Only very simple objects that exist as part of other entities in the registry, such as PersonName , EMailAddress , and TelephoneNumber , are not derived from RegistryObject .

Every RegistryObject has a set of basic attributes, which are shown in the class diagram in Figure 7-8 and described in the following paragraphs.

Figure 7-8. Attributes of RegistryObjects

The name of the RegistryObject is of type InternationalString , reflecting the fact that it might need to be localized. This field typically contains the name of an Organization or the title of a Service . Registry searches can be performed based on the value of this attribute.


Like the name attribute, the description is also an InternationalString . It is intended to contain localized text that will help a potential client searching the registry to determine whether the corresponding Organization or Service is what he requires.


Each entry in the registry has a unique identifier that can be used to locate it without requiring a search based on the name or other criteria. The key is assigned by the registry when the entry is created and never changes. Both the ebXML and UDDI registries assign 128-bit DCE unique identifiers (UUIDs) to newly created objects, which the JAXR provider wraps in a Key object. UUIDs are formed using an algorithm that ensures that they are globally unique. [3] Some well-known registry objects have values that are published in their respective specifications. For example, the registry object that represents the NAICS classification scheme (which will be covered later in this chapter) has the UUID C0B9FE13-179F-413D-8A5B-5004DB8E5BB2. Since this is a universal identifier, it is valid and has the same meaning in all registries.

[3] The specification for the UUID generation algorithm is available for purchase or online viewing (following registration) at http://www.opengroup.org/ publications /catalog/c706.htm.

Object type

Identifies the type of the registry object. The values that may appear in this field are Concept s defined in a classification scheme called ObjectType , which will be described later in Section 7.4.4. This attribute is valid only for RegistryObject s in a level 1 registry.


Identifies the Organization that submitted this object to the registry.


A collection containing the associations between this object and other objects within the registry. Associations are discussed later in this chapter. Although this attribute is common to all RegistryObject s, there may be limitations on its applicability. In the case of the UDDI registry, for example, the JAXR provider allows associations to be made only between Organization s.

External links

A collection of ExternalLink objects containing links to information held outside the registry.

External identifiers

A collection of ExternalIdentifier objects. An ExternalIdentifier can be used to associate with a RegistryObject an identifier that is assigned by a recognized agency and that might be useful to registry clients. An example of this is the nine-digit Dun and Bradstreet D-U-N-S number (see http://www.dnb.com) that uniquely identifies a registered company. External identifiers are scoped by a classification scheme that acts as a namespace for the actual value. The D and B numbering scheme, for example, is represented by a classification scheme with a UUID value of 8609C81E-EE1F-4D5A-B202-3EB13AD01823.


A collection of Classification objects that apply to the RegistryObject . Unlike external identifiers that generally uniquely identify something, a classification applies to a class of organizations, services, or other entities that have a common trait, such as the business type or geographical location. A RegistryObject can have any number of associated classifications. See Section 7.4.4 later in this chapter for further information.

Auditable events

A collection of AuditableEvent objects that record operations performed on the RegistryObject that caused changes to its state. Auditing, described later in this chapter, is supported only by level 1 registries.


Slots are inherited from ExtensibleObject and are described in the next section.

Four interfaces in the JAXR information model ( Service , ClassificationScheme , ExtrinsicObject , and RegistryPackage ) are based on a derived interface of RegistryObject called RegistryEntry . RegistryEntry has the following additional attributes that are meaningful only when the object is stored in a level 1-compatible registry (such as an ebXML registry):

Version number

A RegistryEntry has three version-related attributes that can be managed using the methods of the Versionable interface, from which it is derived. The major and minor version numbers are both integers, the initial values for which are set by the registry when the object is first created. The values may be explicitly changed using the methods of the Versionable interface, and may also be changed by the registry if the RegistryEntry is modified in any way. There is also a user version, which is a string value that can be set and read by application code. It is intended to be the version of the object as seen by registry users and is not modified by the registry itself.


This attribute indicates whether the content of the RegistryEntry may change. The value RegistryEntry.STABILITY_STATIC means that the content will not change; RegistryEntry.STABILITY_DYNAMIC_COMPATIBLE implies that although the content might change, its new value will be backward-compatible with its previous value; and RegistryEntry.STABILITY_DYNAMIC indicates that the content may change in any way at any time.


The expiration attribute is a java.util.Date object that indicates the time up to which the value of the stability attribute is valid. If it has the value null , then the stability attribute is valid indefinitely. Otherwise, the stability of the entry is effectively RegistryEntry.STABILITY_DYNAMIC once the expiration time has passed.


This attribute corresponds to the state of the RegistryEntry within its overall life cycle. When initially created, the object has the state RegistryEntry.STATE_SUBMITTED . The state may then change to RegistryEntry.STATE_APPROVED , RegistryEntry.STATE_WITHDRAWN , or RegistryEntry.STATE_DEPRECATED . The JAXR API allows a client application to deprecate an object, but there is currently no provision for an object to be approved or withdrawn. Nevertheless, these states may be seen because they may be set in the registry by clients using more capable APIs.

7.4.3 ExtensibleObject and Slots

All RegistryObject s implement the ExtensibleObject interface, which allows arbitrary attributes to be added to any object in the registry without requiring a change to the registry API. Each such attribute is represented by a Slot , which has three properties:


The name property can be used to retrieve a given Slot from its associated ExtensibleObject . There cannot be more than one Slot with the same name attached to an ExtensibleObject . The JAXR specification does not describe what should happen if this rule is ignored. In the reference implementation for the UDDI registry, adding a Slot with the same name as an existing Slot causes the old instance to be replaced by the new one, whereas in the case of the ebXML registry, an exception is thrown when an attempt is made to store the RegistryObject .


A string that specifies the type of the Slot . There is no predefined set of valid types. This attribute has value null by default.


A collection of values associated with the Slot . Each value must be a unique String . Application use of Slots

A registry application can use a Slot to associate additional information with a RegistryObject . The ebXML registry model specification suggests that a submitting organization might use a Slot to mark all of its RegistryObject s with a copyright notice. Obviously, registry applications must have prior knowledge of the existence and meaning of specific Slot s in order to make use of them.

The mapping of the JAXR API to the UDDI registry model defined in the JAXR specification does not describe how Slot s should be stored in the registry, and, in fact, the reference implementation does not store them at all. Therefore, JAXR applications that need to work with a UDDI registry cannot, in general, create Slot s and expect them to be saved in the registry. One specific exception to this rule is the sortCode attribute of the UDDI equivalent of the JAXR PostalAddress object, which can be set by application code using a Slot , as described in Section 7.5.7, later in this chapter. Registry use of Slots

A registry implementation can attach Slot s to a RegistryObject to expose attributes available from the registry itself that are not mapped in the JAXR information model. There are several examples of this in the case of the UDDI registry:

  • The operator and authorizedName fields of the registry objects that represent JAXR Organizations and ClassificationSchemes are available in Slots , called Slot.OPERATOR_SLOT and Slot.AUTHORIZED_NAME_SLOT , respectively.

  • A slot is defined for use by the PostalAddress object when a mapping to the UDDI postal address scheme has not been defined. See Section 7.5.7 later in this chapter for details.

7.4.4 Classification of Registry Objects

All RegistryObject s have a name that can be used when searching the registry. You can, for example, locate the Organization object for Amazon.com by searching on the full name or by using a wildcard search with a wildcard such as %mazon% . However, when searching for potential business partners , it is more likely that you will know the type of company that you want to deal with, rather than individual company names . You might, for example, want to locate book publishers or book stores. In order to make this type of search possible, a submitting organization can apply one or more classifications to any of its registry entries. Classifications belong to classification schemes , [4] which categorize objects according to a specific criterion.

[4] The JAXR specification uses the terms "classification scheme" and "taxonomy" interchangeably. For the sake of clarity and consistency with the JAXR API (which calls the relevant interface ClassificationScheme ), I'll use only the term "classification scheme" in this chapter.

A registry can, in theory, support any number of different classification schemes, and the JAXR specification requires that it be possible to add user-defined schemes to a registry, a topic that is covered in Section 7.5.6, later in this chapter. It also requires that all registries support at least three standard classification schemes:

NAICS - the North American Industry Classification System

Classifies organizations according to the type of service that they provide. Examples of classifications from this scheme include "Book Publisher" and "Book, Periodical, and Music Stores." See http://www.ntis.gov/product/naics.htm for details.

ISO 3166

Classifies by geographical location. Organizations can categorize themselves according to location in order to allow potential clients to restrict their search to a specific country or group of countries . Typical classifications from these scheme are US and GB . See http://www.din.de/gremien/nas/nabd/iso3166ma for more information on this scheme.

UNSPSC - the Universal Standard Products and Services Classification

This scheme is intended to provide classifications that are applicable world-wide, unlike NAICS, which is, strictly speaking, biased toward the American marketplace . It is also broader in scope, including product types (such as "Leathers" or "Twill weave cotton fabrics ") as well as services. See http://eccma.org/unspsc for more information on this classification scheme.

You can inspect the classifications provided by these three schemes by starting the UDDI registry browser provided by the reference implementation (using the jaxr_browser.bat or jaxr_browser.sh script in the bin directory), selecting a registry in the Registry Location field, or entering the URL for a specific registry (such as http://localhost:8000/RegistryServer for the test registry server provided by the JWSDP and the reference implementation of the J2EE 1.4 platform) [5] , and then selecting Classifications in the Find by field. This results in the set of classifications supported by the registry being displayed in a tree control in the bottom left of the browser window. To see the classifications provided by a particular scheme, double-click on its name.

[5] Note that the registry browser was not included in the beta version of J2EE 1.4.

All three of the standard classification schemes are hierarchical. The NAICS scheme, for example, includes a top-level classification called Information , below which is another classification called Publishing Industries . Within this classification, there is Newspaper , Periodical , Book and Database Publishers , and within that, Book Publishers . Assuming that you have installed the test data for this chapter in the registry (as described in Section 7.3, earlier in this chapter), if you select Book Publishers and then press Search , an entry for O'Reilly & Associates is returned, as shown in Figure 7-9.

Figure 7-9. Searching the registry by classification

This search works because the Organization object representing O'Reilly & Associates in the registry has the Book Publishers classification from the NAICS classification scheme attached to it. It also has a geographical classification that indicates that it is based in the USA, as you can demonstrate by opening the classification scheme labeled iso-ch:3166:1999 , and drilling down through the classification level for North America to United States . Select this classification and press Search again. This time, you see entries for O'Reilly & Associates and Amazon.com. You can search on both criteria together by selecting Book Publishers , then holding the Ctrl key while selecting United States . This search looks for entries that have both selected classifications and therefore return just the single entry for O'Reilly & Associates. You'll see later in this chapter how to add classifications to a RegistryObject and how to search the registry given one or more classifications. External and internal classification schemes

As previously noted, classification schemes are hierarchical. Figure 7-10 shows a very small portion of the logical hierarchy tree that makes up the standard NAICS classification. The box at the top of the figure represents the classification scheme itself. In terms of the JAXR registry information model, this would be an instance of the javax.xml.registry.infomodel.ClassificationScheme interface. The nodes below this can all be used to categorize other entries in the registry. The relationship between these nodes reflects the granularity of the categorization so that, for example, a Book Publisher is a member of the set of Newspaper, Periodical, Book and Database publishers. Logically speaking, these nodes all represent elements of the classification scheme hierarchy and could therefore be used as possible classification values, but in the JAXR registry model, they would not be instances of the javax.xml.registry.infomodel.Classification interface. How these nodes map onto the JAXR information model depends on whether the classification scheme is internal or external.

Figure 7-10. A logical view of part of the NAICS classification scheme

A JAXR UDDI provider is required to provide the NAICS, ISO 3166, and UNSPSC schemes as internal classification schemes. In the case of an internal classification scheme, both the root ClassificationScheme object and the complete hierarchy of nodes that represent classification scheme elements are known and available within the provider implementation. The nodes themselves are instances of javax.xml.registry.infomodel.Concept , an interface that has several different uses within the JAXR API. A Concept is a RegistryObject that has the following attributes (among others):

  • A name (inherited from its parent interface, RegistryObject ).

  • A value, which is of type String .

  • A ClassificationScheme with which it is associated. Not all Concept s represent nodes in a classification scheme hierarchy; for those that do not, this attribute has the value null .

  • A list of child Concept s and a reference to a parent Concept . These attributes allow Concept s to be linked together in the hierarchical structure shown in Figure 7-10.

An internal classification scheme, then, is represented as a linked hierarchy of Concept s, rooted at a ClassificationScheme object. The actual Concept hierarchy for the part of the NAICS classification scheme illustrated in Figure 7-10 is shown in Figure 7-11, where all of the objects apart from the ClassificationScheme at the top of the diagram represent Concept s.

Figure 7-11. Part of the Concept hierarchy for the NAICS classification scheme

Notice that this diagram shows both the name and value attributes for each Concept . The name is used only for display purposes; it is the value attribute that determines which element of the classification scheme hierarchy the Concept represents. In the case of the NAICS classification scheme, the values are all numbers, where the number of digits is an indicator of the position of the value within the overall scheme. For example, the Information node has the value "51." The values associated with all of the nodes located below this point will start with "51," with an extra digit added for each additional level of nesting. Hence, the Concept representing Book Publishers has the value "51113" and is therefore three levels below the Information node, while the Concept for Newspaper Publishers, at the same level, has the value 51111. A complete list of the names and values for all of the Concept s in this classification scheme and the others that the JAXR provider is required to support can be found in the following files, which are in the jaxr-ri.jar file in the JAXR reference implementation:



ISO 3166:




An external classification scheme is one for which the element hierarchy is not known to the JAXR registry provider ” only the ClassificationScheme node itself is registered. It is obviously easier to create an external classification scheme because there is only one item to install in the registry provider, whereas an internal scheme might require many hundreds of Concept s to completely describe it. However, there are advantages to using an internal scheme:

  • Since the JAXR provider has a record of which Concept values exist within the classification scheme, it can check whether a proposed classification is actually valid before applying it to a registry object.

  • Application code can use the linkage between Concept nodes to browse the hierarchy of an internal classification scheme to discover (and perhaps offer to the user) valid classification values. In the case of an external scheme, the application must either know all legal values by some external means or trust the user to supply only correct values.

  • Using an internal scheme, it is possible to search the registry for objects that are members of groups of classifications. For example, it is possible to search for all registry objects that are categorized as Newspapers, Periodical, Book, and Database Publishers, or any category below that node in the Concept hierarchy (such as Book Publishers). See Section 7.5.2 later in this chapter for an example that shows how this is done.

It is tempting to think that the node hierarchy for an internal classification scheme is held within the registry itself. However, this is not necessarily the case. The UDDI registry information model, for example, does not provide any reasonable way to represent a hierarchy of Concept s and therefore cannot store an internal classification scheme. A JAXR provider is, however, required to provide a hierarchical view of an internal classification. The means by which this is achieved is implementation-dependent. The JAXR reference implementation achieves this by reading the classification files listed previously and creating a local version of the node hierarchy within the client application. The ebXML registry, by contrast, provides full support for internal classifications, which can, therefore, be stored in the registry itself. The difference between these two approaches becomes important if you want to create your own classification scheme. See Section 7.5.6 later in this chapter for further discussion on this topic.

In order to add a classification to a RegistryObject , you need an instance of a Classification object. As with classification schemes, there are two types of classification: internal and external.

An internal classification is created by referencing a Concept from the node hierarchy of an internal classification scheme. A Classification object for an internal classification representing Book Publisher in the NAICS classification scheme is shown in Figure 7-12.

Figure 7-12. An internal classification

An internal classification is very easy to create once you have the associated Concept . It is known to be valid since it refers to a node in the validated hierarchy of a classification scheme. Furthermore, given such a Classification object, application (or registry) code can obtain a reference to the underlying Concept and use it to navigate the hierarchy and create related Classification s, if necessary.

An external Classification object, by contrast, contains a reference to its parent ClassificationScheme and a name and value that correspond to those of the classification that it represents. An external classification, therefore, may or may not be valid, depending on whether the value part is populated with a legal classification value. External classifications must be used if the classification scheme itself is external, but may also be used in conjunction with an internal classification scheme. You can see examples of both cases in Section 7.5.2, later in this chapter. Concepts as enumerated types

Another use for Concept s and classification schemes is to provide a means of creating enumerated types that can then be used as arguments to JAXR API method calls. An enumeration is created by defining a ClassificationScheme and attaching a Concept that represents each possible value within the enumeration. There are several such enumerations defined by the JAXR specification that every JAXR provider must recognize. One such enumeration, called ObjectType , contains distinguished values for each type of RegistryObject , plus a few other commonly used object types. This enumeration actually consists of a ClassificationScheme called ObjectType and a set of Concepts , whose value fields are listed here:


















In order to use one of these values when making API calls, it is necessary to get a reference to the Concept that represents it. One way to do this involves using the findConceptByPath( ) method of the javax.xml.registry.BusinessQueryManager interface, which will be discussed in the next section. This method requires a path that specifies the required Concept . In the case of predefined enumerations, this path consists of the ClassificationScheme name (i.e., the enumeration name), followed by the value attribute of the Concept itself. Since the ClassificationScheme in this case is called ObjectType , the following code returns the Concept for the Service value of the enumeration, assuming that the variable bqm is an instance of BusinessQueryManager :

 Concept service = bqm.findConceptByPath("/ObjectType/Service"); 

As shown in Section 7.5.6, later in this chapter, it is possible to define your own enumerations.

The use of the ClassificationScheme name as the first part of the path is a special case that the JAXR specification provides for easy access to the Concept s of predefined enumerations. As you'll see in Section, later in this chapter, findConceptByPath( ) usually requires the unique ID of the ClassificationScheme to be supplied as the first component of the path rather than the scheme name.

At the time of this writing, the ebXML registry provider available from http://ebxmlrr. sourceforge .net does not support this special case. An alternative way to retrieve the Concept s for an enumerated type can be found in Section, later in this chapter.


Java Web Services in a Nutshell
Java Web Services in a Nutshell
ISBN: 0596003994
EAN: 2147483647
Year: 2003
Pages: 257
Authors: Kim Topley
Similar book on Amazon

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net