Formal concept analysis-based service classification to dynamically build efficient software component directories

Component directories index components by the services they offer thus enabling us to rapidly access them. Component directories are also the cornerstone of dynamic component assembly evolution when components fail or when new functionalities have to be added to meet new requirements. This work targets semi-automatic evolution processes. It states the theoretical basis of on-the-fly construction of component directories using formal concept analysis based on the syntactic description of the services that components require or provide. In these directories, components are more clearly organised and new abstract and highly reusable component external descriptions suggested. Moreover, this organisation speeds up both automatic component assembly and automatic component substitution.


Introduction
Component-based software engineering enables software applications to be built by assembling off-the-shelf components. To ease this process, components expose their external description: a component's set of required and provided interfaces corresponds to the syntactical description of the services the component provides to other components in its environment or requires from other components of its environment to execute itself. Previous work on automatic component assembly and dynamic component assembly evolution (Desnos et al. 2006(Desnos et al. , 2007(Desnos et al. , 2008 convinced us that an efficient component directory is needed. Indeed, searching in a directory for a component from a given repository that is compatible with, or substitutable for, a given component is a non-trivial task. Additionally, white-page-like directories, which represent the mostly used category of directories, are not suitable because they are not structured to enable the search for compatible or substitutable components. The idea of this paper is to propose mechanisms to semi-automatically index software components through a yellow-page-like component directory that supports efficient search for components that are compatible or substitutable to a given component. Our approach relies on formal concept analysis (FCA) that enables us to pre-calculate three categories of lattices: . Functionality signature lattices order functionality signatures in a way that naturally eases their search and can be used for required and provided functionality connection or for required or provided functionality substitution. This category of lattices serves as the basis for building interface lattices. . Interface lattices are more abstract than functionality signature lattices; they code information on functionality specialisation that has been modelled in functionality signature lattices. They order component interfaces -organise service descriptions -in a way that naturally eases their search and can be used for required and provided interface connection or for required or provided interface substitution. This category of lattices serves as the basis for building component type lattices. . Component type lattices are more abstract than interface lattices; they code the information on interface specialisation that has been modelled in interface lattices. They order component types in a way that naturally eases their search and can be used for component connection or component substitution.
These lattices provide the architect or developer with intelligible classifications for functionality signatures, interfaces, and component types. They enable us to separate the service compatibility calculus from the component search itself during the processes of assembly or component assembly evolution (component substitution).
Indeed, a component type lattice can be used as an index for the search of a compatible component (in order to build an assembly) or of a comparable component (in order to find a substitute). Furthermore, FCA creates new component external descriptions (new component types) that do not exist in the component repository but are more abstract and reusable than existing components. These new abstractions can be an opportunity for component developers to be guided during their engineering or re-engineering process. They can also enrich the repository.
The remainder of this paper is organised as follows. Section 2 shows an extension of object-oriented type theory to component types. Then, after recalling the basics of FCA and describing the example used in the paper, Section 3 shows how to build a lattice of functionality signatures and how to use it as a basis for component assembly or component substitution. Section 4 generalises these results to entire interfaces and shows how to use the resulting interface lattice. Section 5 goes one step further in proposing a methodology to build and interpret a component lattice. To finish, Section 6 compares our approach to related existing work and Section 7 concludes and presents future research directions.

Functionality signatures and interface syntactical compatibility
This section explains how the syntactical compatibility of component interfaces can be calculated from functionality signatures which define the syntactical type of interfaces. The syntactical compatibility of interfaces is used to check the validity of connection and substitution operations on component assemblies. It statically asserts a certain level of coherence in a component assembly that, before semantic analysis or execution, provides early error detection and correction.

Functionality signature compatibility in object-oriented programming
In strongly-typed object-oriented programming languages (Cardelli 1984), method signature overriding is allowed in subclasses but constrained by rules that enforce the substitutability of subclass instances towards superclass instances. Thus, a method signature in a subclass must have contravariant argument types and a covariant return type: argument types must be generalised and the return type must be specialised. Intuitively, a method implements a service provided by an object: when the method is called, assuming that sufficient information is received (as specified by argument types), a result of the defined return type is sent back. This corresponds to the concept of software contract, introduced by Meyer (1991) to reason about interactions between objects. Following the above rules, an instance of a class can replace an instance of one of its superclasses because it provides at least the same services, but is allowed to require less invocation information and to return a richer result.
These principles are also used to define relaxed matching schemes used to retrieve a class or a functionality from a repository (Zaremski and Wing 1995). A request is expressed as the signature of the functionality that is searched for. Any functionality, the signature of which specialises (overrides) the requested signature is returned as an approximate but still (type-) compatible answer.

Functionality signatures and component interface specification
An interface is a type that collects functionality signatures; it is used to qualify the collaborations a component can establish with other components. An interface is also a communication point through which a component exchanges service request and response messages with another component. Messages are sent and received along connections linking the interfaces of a component to compatible interfaces of other components (Szypersky et al. 2002). Comparing the syntactical types of two interfaces amounts to compare pairs of functionality signatures from both interfaces (Zaremski and Wing 1997). But in contrast with object models, a direction is added to the definition of interfaces in order to specify whether a component is a client (i.e. uses the interface to require a service) or a server (i.e. uses the interface to provide a service). Thus, two kinds of compatibilities can be verified between interfaces: connection compatibility between a client interface and a server interface or substitution compatibility between interfaces that have the same direction. The connection or substitution compatibility of two components can in turn be determined by verifying the connection or substitution compatibility of pairs of interfaces from both components.
In this paper, functionality signatures are defined by a name, a list of argument types and a return type. As in classical programming languages, names are used as the primary semantic element to match functionalities. Then, the types of the IN-parameters and OUT-parameters of homonymic functionalities are considered. For the sake of simplicity, only a single OUT-parameter (the functionality result) is used in this paper. But the same principles can be applied to any OUT-parameter when multiple OUT-parameters are used in a functionality signature. Figure 1 shows an example of different signatures for homonymic functionalities named create, associated with both required and provided component interfaces. The data type hierarchy used to define parameter types is presented in Figure 1(d).
The different cases of functionality signature specialisation are illustrated: argument type specialisation (cf. Figure 1(a)), result type specialisation (cf. Figure 1(b)), and argument addition into the IN-parameter set (cf. Figure 1(c)).
When associated with a provided interface, a functionality signature has the same semantics as in object-oriented programming: the argument types define what the server component requires to receive in order to execute its service and the return type defines what result it commits to provide. When associated with a required interface, a functionality signature specifies the service that is searched for by a client component: the argument types define the invocation information that the client component will send to a server component and the return type defines the type of the result it requires.

Functionality signature specialisation and provided interface substitution
Zaremski and Wing (1997) present functionality signature matching based on pre-and post-conditions. Consider a provided interface I 1 , which holds a functionality of signature S ¼ f ðX xÞ : Z. As informally stated above, its software contract corresponds to the following pre-condition and post-condition: To soundly substitute I 2 to I 1 in an assembly, the following predicate must hold: Substitution provided ðI 2 ; I 1 Þ ¼ S pre ðxÞ ) T pre ðxÞ^T post ðxÞ ) S post ðxÞ: This verifies that f in I 2 can execute the same invocations as f in I 1 ; second, it verifies that the results returned by f in I 2 can be used instead of the results returned by f in I 1 .
To be true, the predicate entails that: This respectively corresponds to a contravariant specialisation of the argument types and to a covariant specialisation of the result type between the two functionality signatures, as previously presented for object-oriented languages. A provided interface can be replaced by another provided interface with more specific functionality signatures, following the above specialisation rules.
For example (cf. Figure 1(a)), a provided interface holding the create(Information) signature can be substituted to a provided interface holding the create( PersonnalInformation) signature (contravariant specialisation of the argument type). Similarly (cf. Figure 1(b)), a provided interface holding the create():GoldCustomer signature can be substituted to a provided interface holding the create():SilverCustomer signature (covariant specialisation of the result type).

Functionality signature specialisation and required interface substitution
Let us now consider a required interface I 3 , which holds a functionality of signature S ¼ f ðX xÞ : Z. The pre-condition and post-condition corresponding to its software contract are the same as for a provided interface but, as discussed above, their semantics are converse. Indeed, x now represents the data the client component commits to send and f(x) the data the client expects to receive: To soundly substitute I 4 to I 3 in an assembly, the following predicate must hold: Substitution required ðI 4 ; I 3 Þ ¼ T pre ðxÞ ) S pre ðxÞ^S post ðxÞ ) T post ðxÞ: This firstly verifies that the client component holding I 4 will call f in the same way as the client component holding I 3 (to have the guarantee that the connected server component can execute all invocations); secondly, this verifies that the results received by I 3 will also satisfy the requirements of the client component holding I 4 .
To be true, the predicate entails that: This respectively corresponds to a covariant specialisation of the argument types and a contravariant specialisation of the result type between the two functionality signatures. Unsurprisingly, the specialisation rules for functionality signatures in required interfaces are the opposite of those that apply to provide interfaces. Here again, following the above rules, a required interface can be replaced by another required interface with more specific functionality signatures.
For example (cf. Figure 1(a)), a required interface holding the create(Child-Information) signature can be substituted to a required interface holding the create(PersonnalInformation) signature (covariant specialisation of the argument type). Similarly (cf. Figure 1(b)), a required interface holding the create():Customer signature can be substituted to a required interface holding the create():SilverCustomer signature (contravariant specialisation of the result type).

Functionality signature specialisation and interface connection
Finally, let us again consider the provided interface I 1 and the required interface I 4 . To soundly connect I 1 to I 4 , the following predicate must hold: This firstly verifies that any data sent by the client component holding I 4 can effectively be used by the server component holding I 1 to execute f; secondly, this verifies that the data sent by the server component holding I 1 corresponds to the result expected by the client component holding I 4 .
To be true, the predicate entails that: This corresponds to a contravariant specialisation of argument types and a covariant specialisation of the result type between the two functionality signatures. The functionality signatures associated with a required interface of the client component must be more generic than the functionality signature associated with the provided interface of the server component.
For example (cf. Figure 1(a)), a required interface holding the create(Perso-nalInformation) signature can be connected to a provided interface holding the create(Information) signature (contravariant specialisation of the argument type). Similarly (cf. Figure 1(b)), a required interface holding the create():Customer signature can be connected to a provided interface holding the create():Silver-Customer signature (covariant specialisation of the result type).

Functionality signature specialisation and parameter addition or suppression
A special case of parameter type generalisation is now considered. When a parameter type is generalised in a functionality signature, it conceptually means that the specification becomes less demanding on parameters. The objects of the Object type (root of the object type hierarchy) are the objects which contain the least data. We extend the generalisation principle by stating that void is the root type in our system and that it further generalises the Object type.
This way, a special case of parameter type generalisation is to set a parameter type to void. Any data, including no data, becomes suitable for this parameter. As this parameter is optional, it is possible to remove the parameter from the functionality signature. We therefore consider suppressing a parameter as a special case of parameter type generalisation.
Conversely, it is possible to add an extra parameter of type void to a functionality signature without changing its semantics (this additional parameter can always be ignored). The type of such a parameter can then be specialised in the process of functionality signature specialisation, thus becoming a parameter of a concrete type. We therefore consider parameter addition as a special case of parameter type specialisation.
For example (cf. Figure 1(c)), a provided interface holding the create(Information) signature can be substituted to a provided interface holding the create(Information,BankIdentity) signature, as the former signature is obtained by removing the second parameter of the latter signature (contravariant specialisation of the parameter type). Similarly, a required interface holding the create(Information,BankIdentity) signature can be substituted to a required interface holding the create(Information) signature, as the former signature is obtained by adding a second parameter to the latter signature (covariant specialisation of a virtual second parameter of type void).

Discussion
In Zaremski and Wing (1997), which proposes an extensive study and classification of functionality signature matching, the above predicates correspond to a kind of functionality signature matching called 'plug-in' matching. It is used to verify that the code of functionality can be plugged into some other code, to handle some expected behaviour, as specified by a syntactical signature. We have adapted this generic functionality signature matching principle to the specific concepts of component models, namely the syntactical coherence of interface connection and substitution.
Our formalisation shows that checking the coherence of these operations amounts to verifying the existence of specialisation relations between functionality signatures. Thus, we studied how to build specialisation hierarchies of functionality signatures, interfaces and component types. We intend to use these hierarchies as a practical, systematic and efficient means to set up and structure a component directory, where components are indexed by the type of services they provide and require, in other words, a trading service for component-based platforms (Iribarne et al. 2004).
The next sections describe how FCA-based approach to this problem can be used to build the necessary specialisation lattices. It is to be noticed that, at any step, a single lattice is sufficient to compare both required and provided elements for both substitution and connection. Indeed, as shown previously, only two specialisation rules are used, which are converse.

Lattice of functionality signatures
The substitutability rules presented in the previous section can be considered as the basis of a specialisation relationship among functionalities: a functionality that can substitute for another can be considered as its specialisation. Existing functionalities can thus be organised -classified -in a hierarchy based on their substitutability relationships. Furthermore, this section will show that FCA provides a finer-grained classification. After recalling the basics of FCA, we show how it can be used to build a lattice of functionality signatures and how the lattice can then be interpreted and used.

A survival kit for FCA
The classification we build is based on the partially ordered structure known as Galois connection-based lattice (Birkhoff 1940;Davey and Priestley 1991) or concept lattice (Wille 1982) which is induced by a context K, composed of a binary relation R over a pair of sets O (objects) and A (attributes; Table 1). A formal concept C is a pair of corresponding sets (E, I) such that: For example, ð{1; 2}; {b; c}Þ is a formal concept because objects 1 and 2 exactly share attributes b and c (and vice versa). On the contrary, ð{2}; {b; c}Þ is not a formal concept.
Furthermore, the set of all formal concepts C constitutes a lattice L when provided with the following specialisation order based on intent/extent inclusion: ðE 1 ; I 1 Þ # L ðE 2 ; I 2 Þ , E 1 # E 2 ðor equivalently I 2 # I 1 Þ: Figure 2 shows the Hasse diagram of # L .

Example of an online bookstore application
In the rest of this article, we will use, as an illustration, the example of an online bookstore application that targets both the adult and children audiences (cf. Figure 3(a) to see the Table 1 £ £ hierarchy of product types). Two categories of customers can interact with this application. Adults can save favorite book lists (as wish lists) through the application or shop for books following various protocols defined according to a client typology (cf. Figure 1(d)). Children can establish children book wish lists that constitute virtual orders that adults can offer them as soon as their parents obtain the SilverCustomer client category. For this online bookstore application, we have a component repository (cf. Figure 3(b)) in which we can see various components to manage orders (by adults or children) and various components to manage customer lists. These components each expose an interface list the types of which are enumerated in Figure 3(c).

Building the functionality signature lattice
We explain here the construction of the required functionality signature lattice. As provided functionality signatures are reversely ordered, the lattice we obtain can also be used to deal with them, when considered upside down. We illustrate our explanation considering the required functionality create(PI, BI,CCN):SC as it is described by Table 2. At first, for each create functionality whose signature is held by one of the interfaces of Figure 3, attributes are deduced from IN and OUT parameter types that explicitly appear in the signature. These attributes are marked using the £ symbol in Table 2: create(PI,BI,CCN):SC is thus described explicitly by attributes IN:PI, IN:BI, IN:CCN and OUT:SC. Then, we infer attributes (marked with â symbol in Table 2) when their types are compatible, regarding specialisation of signatures. Here are our inference rules: . IN parameters. As explained previously, if a required functionality sends a parameter of some type, it implicitly sends a parameter of any more general type. For example, the IN:I attribute is inferred when the IN:PI attribute is already present. . OUT parameters. If a required functionality expects to receive a return value of a type, any return value of a more specific type is also suitable. For example, the OUT:GC attribute is inferred when the OUT:SC attribute is already present. Figure 4 depicts the concept lattice corresponding to the binary relation shown in Figure 2, built with the GaLicia FCA tool (GaLicia 2002). Concepts are presented using reduced intents and extents (resp. denoted by Reduced I et Reduced E) for readability sake: an object (signature) that belongs to the reduced extent of a concept is inherited by all concepts that are above (down-to-up inheritance); similarly, a property (IN or OUT parameter type) that belongs to the reduced intent of a concept is inherited by all concepts that are below (up-to-down inheritance).

Using the functionality signature lattice
The functionality signature lattice can be used in various types of situations related to component connection or substitution. Let us consider the lattice of Figure 4 with the viewpoint of required functionalities. In this lattice, create(PI):GC is represented by concept C 3 while create(CI, BI):SC is represented by concept C 8 . Concept C 3 is more general than concept C 8 which can be interpreted as: concept C 8 can replace concept C 3 . In a component assembly, a connection to a required functionality corresponding to concept C 3 can be replaced by a connection to a required functionality corresponding to concept C 8 . In the general case, when there is a path between two concepts, the more specific (which has more properties) can replace the more general (which has a subset of properties) when the more general concept is connected (cf. Figure 5(a)). The same lattice can also be used to substitute a provided functionality when read upside down (cf. Figure 5(b)). This generalises as follows.
Property 3.1 (Functionality substitution). Let C father , C son be two concepts of the signature lattice of functionality f, such that C son # L f C father . Functionalities of C son can replace functionalities of C father when the functionalities are required. Opposite replacement applies when the functionalities are provided.
Both provided and required points of view can be combined to address component connection. Let us consider the create(PI,BI,CCN):GC signature (concept C 7 ). The corresponding required functionality can obviously connect to the provided  functionality that has the same signature (create(PI,BI,CCN):GC). Given the substitution rule, provided functionalities which are upper in the lattice, such as provided create(PI):GC (concept C 3 ), can be connected to required create (PI,BI,CCN):GC (cf. Figure 5(c)). Using the same rule in the symmetric way, required functionalities which are below in the lattice, such as required create (PI,BI,CCN):SC (concept C 10 ), can be connected to provided create(PI,BI, CCN):GC. By transitivity, we can deduce that required create(PI, BI,CCN):SC can be connected to provided create(PI):GC. This is expressed in the following connection rule that formalises how valid functionality connection can be deduced from the lattice.
Property 3.2 (Functionality connection rule). Let C, C father , C son be three concepts of the signature lattice of functionality f such that C son # L f C # L f C father , required functionalities of C son can be connected to provided functionalities of C father .

Interface lattice
Components are reusable software entities that are chosen off-the-shelf and fulfil high-level goals (database component, planning component, and so on). Interfaces play an important role to achieve these goals by grouping functionalities that have close semantics and may participate together in potential collaborations. Component assembly is based mainly on the connection of compatible interfaces in a higher abstraction level than simple functionalities.
Considering included functionalities, the interfaces can be provided with a specialisation order in a natural way. This 'natural' classification simply uses the inclusion relation between sets of functionalities in the interfaces and can equally benefit from FCA to look for factorisable functionalities (in our case remove(P) can be factored out).
Then, if we consider substitution or connection, we can improve our search and discover more pertinent abstractions when using the abstractions discovered in the functionality signature lattice. Lattices of the modify, add and remove functionalities of our example are built similarly to the lattice of the create functionality. Tables 3 and 4 detail the contexts, while Figures 6 and 7 show the corresponding lattices. As we have observed, these abstractions on the signatures are the concepts the extent of which has a set of signatures (the signatures covered by the concept) and the intent of which has a set of attributes describing the signature (IN and OUT parameters). For each concept, we can calculate a corresponding canonical signature. We show an example before giving the general definition. Figure 4 shows the concepts built using the binary relation described in Table 2. A concept the reduced extent of which has an original signature (e.g. concept C 9 ) exactly represents that signature (e.g. create(I,BI,Co):C). A concept the reduced extent of which is empty can be interpreted as a new signature that we can infer starting from the attributes inherited by the concept, and considering only the more specific ones. For example, concept C 6 of Figure 4 inherits attributes in:I, in:PI, in:BI, out:GC, out:SC. In case of required signatures, in:PI is more specific than in:I meanwhile out:SC is more specific than out:GC. Concept C 6 can be then interpreted as signature create(PI,BI):SC which we call the canonical signature of the concept. This enables us to build an interface description based on the set of original signatures completed by all the signatures created in the generalisation process (cf. Table 5).
Definition 4.1 (Canonical functionality signature of a concept). Let C be a concept in a signature lattice L f which describes functionality f and # Types , the specialisation partial order on parameter types. s(C), the canonical signature of C, is defined as follows: This exact description enables us to build more pertinent interface generalisations than those we obtained with the 'natural' classification of interfaces. It is used as follows to build interface descriptions within the new context R IntSigCar .
. The canonical signatures are used as attributes in the formal context. . When an interface I has a signature s in a functionality f in its original description, if we denote by C the concept such that s(CÞ ¼ s, we associate to the interface the attribute s and all the canonical signatures of the concepts that are upper of C in the lattice: R IntSigCar ¼{ðI; scÞj s belongs to the definition of I; sc ¼ s ðC father Þ; C father $ L f C with s ¼ sðCÞ}: For example, interface I1 holds the signature create(I,BI,Co):C. This signature is the canonical signature of concept C 9 in lattice L create . In Table 5, we associate I1 to create(I,BI,Co):C (marked with symbol £ ) and we equally associate to I1 the canonical signatures of all concepts of L create that are upper of C 9 . That results in the following signatures (marked with symbol^):create(I,BI):SC (concept C 5 ), create(I,BI):GC (concept C 2 ), and create(I):GC (concept C 1 ). From required functionality viewpoint, these signatures are generalisations of the original signature create(I,BI,Co):C (with the semantics of substitutability). The built lattice L I (cf. Figure 8) shows specialisation relations between interfaces. These relations show possible connections or substitutions which are deduced from the previously mentioned rules on functionality signatures that are extended to interfaces (repeatedly applied to all signatures that constitute these interfaces).
For example, the required interface I10 can be connected to provided interface I6. Still, required interface I10 (C 10 ) can replace required interface I6 (C 2 ). We see that a manual or automatic search of components is faster with this lattice that defines a search index. We thus avoid looking at all components in the repository since we only look for relevant branches. Let us imagine the case in our example where component SilverAdultOrder searches, logically, to be connected to component Silver AdultDB usually present in the system that is temporarily unavailable. The relation in the lattice, starting from the expected required interface I 9 (C 5 ), enables us to immediately find (just traversing the edge that goes from concept C 5 to concept C 2 , that possesses the I 6 interface) that component GoldDB could be used as a replacement. Temporarily the user will benefit of a higher service in replacement of a missing service.
In the lattice, we also find new interfaces, obtained using the existing interface generalisation. Starting from functionalities discovered in the first lattice, the technique can then infer a new interface, including at least this shared functionality. Here we see one of the main advantages of FCA-based techniques compared to simple calculation of signature comparison: new signatures appear, and thus we have new interfaces more abstract than existing ones. The following generalisation step is to use this lattice to build a component lattice. This latter lattice is more interesting for designers who can be guided when creating more general new components, as well as for assemblers who can consult an organised library rather than just a flat set of artefacts. Figure 7. Signature lattice L add for the add functionalities. The lattice L remove , isomorphic to L add , is not represented.

Lattice of component types
In this section, we first propose a solution to build the lattice of component types. The technique used to do so is the same as the one previously used for interfaces: the interface lattice helps enrich the description of the formal context that will be used to build the component type lattice. Then, the remainder of the section shows possible uses of this lattice.

Definition of the lattice of component types
Component types are described by their required and provided interfaces. This information can be organised by specialisation, but, similarly to that done with interfaces, component types can benefit from both the specialisation relationships between interfaces and the discovered interfaces obtained from the interface lattice. We thus get an enrichment of the description of components and a more precise classification, offering more abstractions.
The first phase of the building process entailed the introduction of the notion of a 'canonical interface' associated to an interface concept. This notion is similar to the canonical functionality signature corresponding to a signature concept that we defined above. Let us just mention that our analysis is still based on the case of required interfaces.
Definition 5.1 (Required canonical interface corresponding to an interface concept). Let C be a concept in the interface lattice L I . The corresponding canonical interface IðCÞ is defined as follows: . If Reduced EðCÞ $ {I}, then IðCÞ ¼ I. We can choose any interface in the reduced extent because they are all equivalent. . If Reduced EðCÞ ¼ B, then IðCÞ ¼ min # SigCar {s [ IntentðCÞ}. The canonical interface gathers more specialised signatures from the set of canonical signatures that forms the intent. The order # SigCar between canonical signatures is naturally inferred from the specialisation relationship between concepts of the lattice L f : s son # SigCar s father iff s son ¼ sðc son Þ, s father ¼ sðc father Þ and c son # L f c father .
Canonical interfaces found in the lattice are all the original interfaces (I1 to I6, I8 and I10, and a single interface corresponding to the {I7,I9} interface pair) to which new abstract interfaces are added by the classification process. These new abstract interfaces are described by their signature set (cf. Table 6).
We then set up a relation R CompCanInt between component types and canonical interfaces including their orientation (required or provided; cf. Table 7). The rows represent components, the columns interfaces. Interface identification (in column heads) combines the two interface orientations (noted req: and pro:) with each canonical interface name and is followed by their concept number in the interface lattice. For example, column 1 corresponds to the canonical required interface I1, associated to concept C 12 (as I1 is member of its reduced extent). Column 11 corresponds to the canonical required interface I12, associated to concept C 3 . Definition 5.2 (Component relation R CompCanInt ). Component types are the formal objects while canonical interfaces are the formal attributes. Let C be a component and I an interface, ðC; IÞ [ R CompCanInt iff one of the following properties is true: . I is declared by C, . I $ L I J and J is declared by C. Figure 9 shows lattice L C of component types. The following section will show how it can be used.

Usage of the lattice of component types
While interfaces represent parts of collaborations, component types introduce consistent units dedicated to the provision of a consistent set of services. As in the previous lattices, but at a higher level in the structure of software artefacts, the lattice of component types offers both a specialisation relation between component types and new abstract component types. This lattice has several applications in component assembly and software application re-engineering.

Emergence of new component types
The concepts in the lattice of component types can be interpreted as component types that we define as 'canonical component types' to remain coherent with the previous definitions. Some of these canonical component types correspond to the original components: they are associated with concepts the reduced extent of which contains an original component. When the reduced extent of a concept is empty, we explore the intent of the concept to build the corresponding canonical component type. Thus, we consider symmetrically the required and provided interfaces from the intent. In the case of required interfaces, we consider those that have the smallest (more specific) type as shown in the interface lattice. In the case of provided interfaces, we consider those that have the largest (more general) type. These rules are a transcription of the substitution rules for functionality signatures, extended to interfaces. In the case where an original component type appears in the reduced extent, the proposed construction finds an identical canonical component type. For example, concept C 15 of lattice L C has {pro:I5, pro:I6} as its canonical component type because I5 and I6 are the maximum of IntentðC 15 Þ (we do not make a distinction between required and provided interfaces because there are only provided interfaces in this intent). The reader will also notice that {pro:I5, pro:I6} is exactly the component type GDB that is found in the reduced extent of C 15 .

Substitution and connection
The specialisation relation we have built between concepts is tailored for substitution. Component substitution can be necessary in the event an entirely connected component fails. For example, let us suppose that an assembly is formed by component CO of type {req:I8, req:I4} entirely connected to component GDB of type {pro:I5, pro:I6}. Firstly, we can convince ourselves about the syntactical validity of the assembly that is ensured by two properties: required I8 specialises provided I6 and required I4 specialises provided I5 (as we generalise to interfaces the property described on Figure 5). Let us now imagine that component CO fails. Specialisation in the lattice enables us to efficiently find a potential replacement. Component PO of type {req:I10, req:I4} will be a good candidate. The assembly remains valid because required I10 specialises provided I6. The user will have access to a partial service because it is now only possible, among child books (ChildBook type), to ask for educational books (Educational-Book type), but the service may also perform better because it specialises about educational books.
Let us now analyse the connection problem. We note that two complementary components are not necessarily related to each other in the lattice: for example, there is no link between the components AO2 of type {req:I1, req:I7} (concept C 9 ) and CDB of complementary type {pro:I1, pro:I7} (concept C 3 ). Indeed req:I and pro:I are considered independent attributes. Given a component (e.g. AO2 of type {req:I1, req:I7}), it is nonetheless possible to find components that it can be connected to. A solution firstly consists in classifying the type of its complementary component (e.g. {pro:I1, pro:I7}) applying the inferences. In our example, we obtain {pro:I1, pro:I7, pro:I19}. In this case, the classification enables us to reach concept C 3 . C 3 and all smaller (more specific) concepts define, by the mean of their corresponding canonical component type, the types of components that can entirely connect to AO2.

Re-engineering and building generic architectures
We have previously described how the lattice discovers new component types. For example, concept C 5 of canonical type {req:I14,req:I6} has an empty extent. It indicates that the concept does not precisely correspond to an original component. However, it is an abstraction of all component types corresponding to lower (more specific) concepts. This canonical type, {req:I14,req:I6}, abstracts components relative to product orders in the example. It can be replaced by any of the more specific components. If a component of this canonical type participates in component architecture, this architecture will have the capability of being instantiated using an important variety of concrete components. The discovery of such new abstract components into the classification can be interpreted as reengineering the set of existing components, and can help the developer design more generic architectures.

Architecture abstraction
The component lattice shows both specialisation relationships among component types and newly discovered abstract component types. This can serve as the basis of whole architecture classification. This new objective is a little less direct to reach than the other generalisation steps we have described in the paper because, in an architecture, components are not only described by binary attributes but also by their interconnections. Several ideas can be explored to take into account these connections such as Relational Concept Analysis Huchard et al. (2007) or relations in Logical Information Systems Ferré et al. (2005).

Related work
Few of the related approaches use a syntactical type hierarchy to structure component indexes and help component search. Zaremski and Wing (1995) suggest such a mechanism but in the more general context of functionality signature matching. The functionality hierarchy lies on the partial order relationship defined by the signature-matching operator used, whether it is exact or relaxed. Module matching (component matching) is deduced from functionality matching: a component is comparable with another if each of its functionalities match a functionality of the other.
Existing yellow page-based service directories, also called service traders Iribarne et al. (2004), such as CORBA (trading object service OMG 2000), conform to the principles of the ODP standard (Information Technology Open Distributed Processing 1998). A component exports an advertisement into the component directory in order to be registered as the provider of some service. The service advertisement conforms to an existing service type that lists the properties and syntactical interfaces the components must have to provide the service. Service types can be ordered in a specialisation hierarchy that is static and manually built. As opposed to our approach, these models use statically defined service hierarchies Marvie et al. (2001). This kind of indexing and the corresponding directories are not adapted to dynamical, evolving and open environments.
Works based on FCA propose to semi-automatically index components (Lindig 1995) in order to be able to help the developer identify adequate components from all the components stored in a component repository. Component search lies on groups of names and keywords and on incremental queries that help focus the search, diminishing the number of potential results, as the search gets more precise. Fischer (1998) and Sigonneau and Ridoux (2004) both aim at building such browsable functionality directories. Concepts are used to handle the iterative selection of attributes that define the user request as a traversal of the concept hierarchy. Thus, in these approaches, concept hierarchies do not directly reflect specialisation relations between the syntactical types of functionality signatures. Fischer (1998) uses attributes which represent fragments of the formal specifications of functionalities (elementary pre-and post-conditions). Sigonneau and Ridoux (2004) use syntactical types of input and output parameters, along with covariant and contravariant specialisation rules. In the context of web service search, machinelearning techniques are used for service classification and annotation (Bruno et al. 2005;Corella and Castells 2006). Starting from textual documentation, services are automatically clustered using support vector machines or ontologies. FCA is then used in a second step to drive the matching between textual information and searched services.
As compared to these proposals, the originality of our work is to study directories of components described by sets of required and provided interfaces. Different specialisation relations are defined to take into account not only the parameter but also the functionality directions. Moreover, we propose an iterative process to build lattices of component types, which are composed of interfaces of both directions, which are in turn composed of functionalities. This iterative nature strongly differs from other works that use FCA which only build lattices of functionality types.

Conclusion and future work directions
In this article, we proposed to build component directories using FCA. The directory relies on the last built lattice that organises components in order to speed up their retrieval, for either assembly or substitution. This component lattice is built upon some related lattices: an interface lattice which itself uses a classification provided by a functionality signature lattice. Beyond its usefulness for component assembly or component substitution, this classification also discovers new abstractions (new functionality signatures, new interface types and new component types), providing developers with valuable information about highly reusable elements. The developer can use this information as a guide along the development process or as re-engineering information.
The work presented in this article raises new research issues. Firstly, we want to study how our system can be implemented and integrated into an IDE to assist the management of component-oriented applications. This task comprises four steps: . Extracting information about the component interfaces. We want to use the introspection capabilities of components to extract and dynamically maintain information on interfaces as the components enter or leave the system. . Encoding the information in formal contexts, taking into account the identified inference rules and the type hierarchy of the system. . Building lattices. Kuznetsov and Obiedkov 2002 present several incremental algorithms that enable new concepts to be added to an existing lattice. Several of these algorithms are implemented in GaLicia Valtchev et al. (2003). These algorithms could be used to calculate the different lattices and also maintain them dynamically as components enter or leave the system. . Using lattices. The obtained lattices can be used not only as a component index to ease search, but also as a way of visualising the content of component libraries using the graphical interface of GaLicia or a similar FCA tool like TOSCANA (Vogt and Wille 1994) or CONEXP (Yevtushenko 2000).
This will enable us to systematically experiment with our approach on large component repositories, considering various component or interface granularity and function signature complexity.
We also plan to study complementary features of components, interfaces and signatures, such as ports, protocols or exceptions. For instance, ports (Desnos et al. 2006(Desnos et al. , 2007 would enable specifications of the dynamic behaviour of components to be considered, providing more accurate component indexing and retrieval. Another extension is inspired by Web Services directories (Klusch 2008). Contrary to component directories, they mainly use semantic information (names, descriptions) in their search mechanism. We can experiment with these techniques to refine classification considering the name of the parameters in the functionality signatures. Conversely, it is interesting to analyse how our approach could be used to improve the calculation of syntactical compatibility in Web Services. Sylvain Vauttier has been a full time assistant professor at Ecole des Mines d'Alès since 2000. His research interests encompass component and agent-based software engineering techniques. His work, focused on behaviour composition mechanisms, is more recently applied on the autonomous construction and evolution of software deployed on ambiant intelligence environments.