PK  Doa,mimetypeapplication/epub+zipPK DiTunesMetadata.plistr artistName Oracle Corporation book-info cover-image-hash 48241178 cover-image-path OEBPS/dcommon/oracle-logo.jpg package-file-hash 209341855 publisher-unique-id E37535-01 unique-id 821487494 genre Oracle Documentation itemName Oracle® Communications Services Gatekeeper Platform Development Studio Developer's Guide, Release 5.1 releaseDate 2013-05-24T11:35:16Z year 2013 PK^W9wrPK DMETA-INF/container.xml PKYuPK DOEBPS/pds_triggeringedr.htm Aspects, Annotations, EDRs, Alarms, and CDRs

11 Aspects, Annotations, EDRs, Alarms, and CDRs

This chapter describes aspects and generation of EDRs, alarms, CDRs, and statistics in Oracle Communications Services Gatekeeper (Services Gatekeeper).

About Aspects and Annotations

Aspects allow developers to manage cross-cutting concerns in their code in a straightforward and coherent way. Aspects in Services Gatekeeper (pointcuts, advice, etc.) are written in the AspectJ 1.5.3 annotation style. There is already support for editing annotations in many modern IDEs, and aspects are simply set up as annotated classes.

How Aspects are Applied

All aspects are applied at build time by weaving the byte code of previously complied Java packages. Minimal reflection is used at runtime to make aspect-based decisions.

Different aspect types are applicable to different Services Gatekeeper modules. In general there are two categories of aspects:

  • Those restricted to the code for the traffic flow

  • Those that can be applied to other packages.


    Note:

    In this case, traffic flow is defined to include only plug-in implementations.

Traffic aspects are subdivided into two categories:

  • Those that are always applied

  • Those that are controlled using annotations.

Only statistics aspects are always applied because they are used to calculate usage costs. Traffic aspects are applied to north and south boundaries of a plug-in as well as to the internal processing of the plug-in.

Annotations are used to control the aspects that are not always applied for each plug-in. These annotations are defined as part of the functional areas that a given set of aspect implements. They allow the plug-in to communicate with the aspects as well as to customize their behavior.

Context Aspect

The Context aspect is woven at compile time, using PluginSouth as a marker.

While requests coming from the north interface have a valid context (with attributes like Service provider account ID, application Account ID, and so on) any events triggered by the network and entering a plug-in's south interface do not have a valid context.

The Context aspect solves this problem by rebuilding the context as soon as a south interface method is invoked: after this aspect is executed, a valid context will be available for any subsequent usages, such as the EDR aspect. All methods inside a class implementing the interface PluginSouth are woven by the Context aspect.

The Context aspect requires the following in order to correctly weave the south interface methods and be able to rebuild the context:

  • Each Plug-in must explicitly register its north and south interfaces.

  • Each south interface must implement the resolveAppInstanceGroupdId() and prepareRequestContext() methods of the PluginSouth interface.

  • North interfaces must implement PluginNorth and south interfaces must implement PluginSouth.

The following rules apply for methods in classes that implement PluginNorth:

  • The default behavior is that EDRs are triggered only for exceptions and callbacks to EJBs in the access tier (Service Callback EJB)

  • If a method is annotated with @NoEdr, no EDRs will be generated. It overrides the default behavior.

  • If a method is annotated with @EDR, 2 EDRs will be generated:

    • When entering the method

    • When exiting the method.

The following rule applies for methods in classes that implement PluginSouth:

  • Methods that perform requests to the network may have a parameter annotated with @MapperInfo in order to be able to rebuild the RequestContext when the response to the request arrives from the network. The annotated parameter must be used as a key to resolve the application instance ID using some plug-in specific lookup.

  • Methods must implement resolveAppInstanceGroupdId(ContextMapperInfo info) in PluginSouth and return the application instance ID that corresponds to the original request to the network.

The ways of doing this are plug-in-specific, but normally a network triggered request is tied to an application instance in a store that is managed by the plug-in. The store used for context mapping may be a local cache or a cluster wide store, depending on whether responses are known to always arrive on the same plug-in instance, or if they can arrive at a plug-in on another server in the cluster.

Example:

  1. An application sends a request to the network and an ID for this request is either supplied by the network or generated by the plug-in. At this point the originator of the requests, the application instance, is known since the request originated from an application.

  2. The plug-in puts the application instance ID and the ID for the request into a store.

  3. At a later stage, when a response to the original requests arrives at the plug-in, the method resolveAppInstanceGroupId() is called by aspects.

  4. In this method, the plug-in must perform a lookup in the store of the application instance related to that request and return the application instance ID to the aspect.

  5. The aspect authenticates the application instance with the container and puts the application instance ID in the RequestContext.

  6. The method in the plug-in receives the request from the network and the RequestContext contains the application instance ID.

In the example below the method deliver(...) is a request from the underlying network. The destinationAddress is annotated to be available to the aspect that handles network-triggered requests associated with this request, represented by constant C.

NotificationHandler handles the store for notifications and supplies all necessary parameters to the store.

Example 11-1 Application initiated request

protected static final String C = "destinationAddress";
@Edr
  public void deliver(String data,
                      @ContextKey(EdrConstants.FIELD_DESTINATION_ADDRESS)
                      @MapperInfo(C) String destinationAddress,
                      @ContextKey(EdrConstants.FIELD_ORIGINATING_ADDRESS) String originatingAddress,
                      String nwTransactionId)
    throws Exception {

    notificationHandler.deliver(data, destinationAddress, originatingAddress, nwTransactionId);

  }

When a network triggered event occurs, the aspect calls resolveApplicationInstanceGroup(...) in PluginSouth and the plug-in looks up the application instance using any argument available in ContextMapperInfo that can help the plug-in to resolve this ID from ContextMapperInfo, using info.getArgument(C). The application instance ID is returned to the aspect and the execution flow continues in the plug-in, with a RequestContext that contains the application instance ID, session ID and so on.

Example 11-2 Rebuilding RequestContext

protected static final String C = "destinationAddress";
public String resolveAppInstanceGroupdId(ContextMapperInfo info) {

    String destinationAddress = (String) info.getArgument(C);
    NotificationData notificationData = null;
    try {
      notificationData = StoreHelper.getInstance().getNotificationData(destinationAddress);
    } catch (StorageException e) {
       return null;
    }

    if (notificationData == null) {
      return null;
    }

    return notificationData.getAppInstanceGroupId();
  }

Below are the steps you have to take to make your plug-in compliant with the Context aspect:

  • Make sure to register all your PluginSouth objects before registering your plug-in in the Plug-in Manager.

  • Make sure to implement the resolveAppInstanceGroupdId() method for each PluginSouth instance.

  • Annotate each parameter in south object methods that you need to have when aspects call back the resolveAppInstanceGroupId() or the prepareRequestContext() methods. All the annotated parameters will be available in the ContextMapperInfo parameter. The aspects need to have them annotated to be able to store them into the ContextMapperInfo object.

EDR Generation

EDRs are generated in the two following ways:

  • automatically using aspects at given points in the traffic execution flow in a plug-in.

  • manually anywhere in the code using the EdrService.

EDRs should be generated at the plug-in boundaries (north and south), using the @Edr annotation to ensure that the boundaries are covered. Additional EDRs can be added elsewhere in the plug-in if needed: for example for CDRs.

For extensions, the EDR ID should be in the range 500 000 to 999 999.

EDRs are generated automatically by an aspect in the following locations in the plug-in:

  • Before and after any method annotated with @Edr

  • Before and after any callback to an EJB

  • After any exception is thrown


    Note:

    Note that aspects are not applied outside the plug-in.

Table 11-1 Manual annotation for EDRs

TriggerWhenModifiers restrictionsWhat is woven

method

before executing

public method only

only in methods annotated with @Edr

method

after executing

public method only

only in methods annotated with @Edr

method-call

before calling

any method

only for method call to a class implementing the PluginNorthCallback interface (EJB callback)

method-call

after calling

any method

only for method call to a class implementing the PluginNorthCallback interface (EJB callback)

exception

after throwing

any method

any exception thrown except in methods annotated with @NoEdr


The following values are always available in an EDR when it is generated from an aspect:

  • class name

  • method name

  • direction the request is going toward (south, north)

  • position (before, after)

  • interface (north, south, other, null)

  • source (method, exception)

Exception Scenarios

Exceptions are automatically woven by the aspect.

Some limitations apply:

  • The aspect will catch only exceptions that are thrown by a plug-in method.

  • The aspect will not catch an exception that is thrown by a library and caught by the plug-in.

  • If the same exception is re-thrown several times, the aspect will only trigger an EDR once, for the first instance of the exception.

Figure 11-1 illustrates typical scenarios when a library (or core service) throws an exception in the plug-in.

Figure 11-1 Exception scenarios

Description of Figure 11-1 follows

Scenario 1:

The plug-in method in Stage 2 simply catches the exception but does not re-throw it or throw another exception. Since it just consume the exception, the aspect will not trigger an EDR.

Scenario 2:

The plug-in method in Stage 2 lets the exception A propagate (or re-throws exception A).

In this case, the aspect triggers an EDR after the method in stage 2. Since the same exception A (the same exception instance object) is propagated (or re-thrown), only the first method triggers an EDR.

Scenario 3:

This scenario is almost identical to scenario 2 except that the method in stage 1 is not throwing the exception A but another exception, named B. In this case, because B is not the same instance as A, the aspect will trigger another EDR after the method in stage 1.

Adding Data to the RequestContext

In addition to the default values, an EDR also contains all the values put into the RequestContext using the putEdr() method.

Example 11-3 Adding values using RequestContext

...
RequestContext ctx = RequestContextManager.getCurrent();
// this value will be part of any EDRs generated in the current request
ctx.putEdr("address", "tel:1234"); 
// this value will NOT be part of any EDRs since ctx.put(...) is used
ctx.put("foo", "bar");
...

Note:

Common key names are defined in the class com.bea.wlcp.wlng.api.edr.EdrConstants.

Using translators

When a parameter is a more complex object, it is possible to specify a translator that will take care of extracting the relevant information from this parameter.

The annotation is @ContextTranslate.

For example, the following method declares:

  • The first (and only) parameter should be translated using the specified translator ACContextTranslator

  • The returned object should also be translated using the specified translator ACContextTranslator

Example 11-4 Using a translator

...
  @Edr
  public @ContextTranslate(ACContextTranslator.class) PlayTextMessageResponse playTextMessage(@ContextTranslate(ACContextTranslator.class) PlayTextMessage parameters) {
    ...
    return response;
  }
  ...

The Translator is a class implementing the ContextTranslator interface.

Example 11-5 Example Translator

  public class ACContextTranslator implements ContextTranslator {
    public void translate(Object param, ContextInfo info) {
      if(param instanceof PlayTextMessage) {
        PlayTextMessage msg = (PlayTextMessage) param;
        info.put("address", msg.getAddress().toString());
      } else if(param instanceof PlayTextMessageResponse) {
        PlayTextMessageResponse response = (PlayTextMessageResponse) param;
        info.put("correlator", response.getResult());
      } ...
    }
  }

The ContextTranslator class specified in the @ContextTranslate annotation is automatically instantiated by the aspect when needed. It is however possible to explicitly register it using the ContextTranslatorManager.

Example 11-6 Registering a Context Translator

ContextTranslatorManager.register(ACContextTranslator.class.getName(), new ACContextTranslator());

Table 11-2 is a summary of annotations to use.

Table 11-2 Annotations

NameTypeDescription

@ContextKey

Annotation

Specifies that an argument must be put into the current RequestContext under the name provided in this annotation

@ContextTranslate

Annotation

Same as @ContextKey but for complex argument that need to be translated using a translator (implementing the ContextTranslator interface).

ContextTranslator

Interface

Interface used by static translators to translate complex object.


Triggering an EDR Programmatically

Oracle Communications Services Gatekeeper triggers EDRs automatically in all plug-ins where aspects have been applied. It is also possible to trigger EDRs explicitly. In this case, you will have to manually create and trigger the EDR by following these steps:

  1. Create an EdrData object

  2. Trigger the EDR using the EdrService instance

Below is an example of triggering an EDR from inside a plug-in.

Example 11-7 Triggering an EDR Programmatically

public class SamplePlugin {
   // Get the EdrDataHelper like a logger
   private static final EdrDataHelper helper = EdrDataHelper.getHelper(SamplePlugin.class);

   public void doSomething() {
      ...
      // Create a new EdrData using the EdrDataHelper class to allow 
      // Services Gatekeeper to automatically populate some fields
      EdrData data = helper.createData();
      // Since we are creating the EdrData manually, 
      // we have to provide the mandatory fields.
      // Note that the EdrDataHelper will provide most of them
      data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
      data.setValue(EdrConstants.FIELD_METHOD_NAME, "doSomething");
      // Log the EDR
      EdrServiceFactory.getService().logEdr(data);
      ...
   }
}

EDR Content

Table 11-3 describes the content of an EDR. It shows which values are mandatory, who is responsible for providing these values, and other information.

Legends:

  • A: Automatically provided by Oracle Communications Services Gatekeeper

  • H: Provided if the EdrDataHelper createData API is used to create the EdrData (which is the recommended way)

  • M: Provided manually in the EdrData

  • X: Provided in the EDR descriptor.

  • C: Custom filter. Use the <attribute> element to specify a custom filter.


    Note:

    EDRs triggered by aspects will have all the mandatory fields provided by the aspect.

Table 11-3 EDR content

NameDescriptionFilter tag name

EdrId

To get the ID, use getIdentifier() in EdrConfigDescriptor.

This value is provided in the EDR descriptor.

Provider INSIDE plug-in: X

Provider OUTSIDE plug-in: X

Mandatory: Yes

C

ServiceName

The name (or type) of the service.

Fields in EdrConstants: FIELD_SERVICE_NAME

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: Yes

C

ServerName

The name of the Oracle Communications Services Gatekeeper server.

Fields in EdrConstants: FIELD_SERVER_NAME

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: H

Mandatory: Yes

C

Timestamp

The time at which the EDR was triggered (in ms since midnight, January 1, 1970 UTC)

Fields in EdrConstants: FIELD_TIMESTAMP

Provider INSIDE plug-in: A

Provider OUTSIDE plug-in: A

Mandatory: Yes

C

ContainerTransactionId

The WebLogic Server transaction ID, if available.

Fields in EdrConstants: FIELD_CONTAINER_TRANSACTION_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: H

Mandatory: No

C

Class

Name of the class that triggered the EDR.

Fields in EdrConstants: FIELD_CLASS_NAME

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: H

Mandatory: Yes

<class>

Method

Name of the method that triggered the EDR.

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: Yes

<name> inside <method> or <method> inside <exception>

Source

Indicates the type of source that triggered the EDR.

Fields in EdrConstants: FIELD_SOURCE

Values in EdrConstants: VALUE_SOURCE_METHOD, VALUE_SOURCE_EXCEPTION

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: Yes

<method> or <exception>

Direction

Direction of the request.

Fields in EdrConstants: FIELD_DIRECTION

Values in EdrConstants:VALUE_DIRECTION_SOUTH, VALUE_DIRECTION_NORTH

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<direction>

Position

Position of the EDR relative to the method that triggered the EDR.

Fields in EdrConstants: FIELD_POSITION

Values in EdrConstants: VALUE_POSITION_BEFORE, VALUE_POSITION_AFTER

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<position>

Interface

Interface where the EDR is triggered.

Fields in EdrConstants: FIELD_INTERFACE

Values in EdrConstants: VALUE_INTERFACE_NORTH, VALUE_INTERFACE_SOUTH, VALUE_INTERFACE_OTHER

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<interface>

State

Where the EDR was dispatched.

Fields in EdrConstants: FIELD_STATE

Values in EdrConstants: ENTER_AT, ENTER_NT, ENTER_NET, EXIT_AT, EXIT_NT, EXIT_NET

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<state>

Exception

Name of the exception that triggered the EDR.

Fields in EdrConstants: FIELD_EXCEPTION_NAME

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

<name> inside <exception>

SessionId

Session ID.

Fields in EdrConstants: FIELD_SESSION_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No

C

ServiceProviderId

Service provider account ID.

Fields in EdrConstants: FIELD_SP_ACCOUNT_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No

C

ApplicationId

Application account ID.

Fields in EdrConstants: FIELD_APP_ACCOUNT_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No

C

AppInstanceId

Application instance ID.

Fields in EdrConstants: FIELD_APP_INSTANCE_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No.

C

TransactionId

Transaction ID.

Fields in EdrConstants: FIELD_TRANSACTION_ID

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No.

C

Facade

Facade.

Fields in EdrConstants: FIELD_FACADE

Values in EdrConstants: VALUE_FACADE_REST, VALUE_FACADE_SOAP

Provider INSIDE plug-in: H

Provider OUTSIDE plug-in: M

Mandatory: No.

C

OrigAddress

The originating address with scheme included (for example “tel:1234”).

Fields in EdrConstants: FIELD_ORIGINATING_ADDRESS

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

C

DestAddress

The destination address(es) with scheme included (For example “tel:1234”). See "Using send lists".

Fields in EdrConstants: FIELD_DESTINATION_ADDRESS

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No

C

<custom>

Any additional information put into the current RequestContext using the putEdr() API will end up in the EDR.

Fields in EdrConstants: -

Provider INSIDE plug-in: -

Provider OUTSIDE plug-in: -

Mandatory: No

C

URL

URL.

Fields in EdrConstants: FIELD_URL

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No


WebAppName

Name of the current web application.

Fields in EdrConstants: FIELD_WEB_APP_NAME

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No


HttpMethod

HTTP request method. For example "POST", or "GET".

Fields in EdrConstants: FIELD_HTTP_METHOD

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No


RequestContext

Attributes in the request context map.

Fields in EdrConstants: FIELD_REQUEST_CONTEXT

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No


InterceptorChain

List of all the interceptors that are triggered.

Fields in EdrConstants: FIELD_INTERCEPTOR_CHAIN

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No


SubscriberId

Subscriber identifier (using route address)

Fields in EdrConstants: FIELD_SUBSCRIBER_ID

Provider INSIDE plug-in: M

Provider OUTSIDE plug-in: M

Mandatory: No



Using send lists

If more than one address needs to be stored in the DestAddress field, use the following pattern. Both patterns described below can be used.

Example 11-8 Pattern to store one single or multiple addresses in field destination directly on EdrData.

EdrData data = ...;
// If there is only one address
data.setValue(EdrConstants.FIELD_DESTINATION_ADDRESS, address);
// If there are multiple addresses
data.setValues(EdrConstants.FIELD_DESTINATION_ADDRESS, addresses);

If you are using the current RequestContext object, simply store a List of addresses. The EdrDataHelper will automatically take care of converting this to a List of Strings in the EdrData.

Example 11-9 Pattern to store one single or multiple addresses in field destination using RequestContext.

RequestContext ctx = RequestContextManager.getCurrent();
// If there is only one address
ctx.putEdr(EdrConstants.FIELD_DESTINATION_ADDRESS, address);
// If there are multiple addresses
URI[] addresses = ...;
ctx.putEdr(EdrConstants.FIELD_DESTINATION_ADDRESS, Arrays.asList(addresses));

RequestContext and EDR

Figure 11-2 shows how and where information for the EDR is added to the RequestContext and how it finally ends up in the additional info column of the alarm and CDR databases.

Figure 11-2 RequestContext and EDR

Description of Figure 11-2 follows

There are 3 ways of putting information in the RequestContext that will end up in the EDR (more precisely in the EdrData object):

  • Using the putEdr() API of the RequestContext

  • Using the @ContextKey or @ContextTranslate annotation. In the case of the @ContextTranslate annotation, the information that will end up in the RequestContext will be what is put into the ContextInfo object.

  • Any information put in the RequestContext parameter of the PluginSouth.prepareRequestContext() method.

When an EDR is created, the EdrDataHelper (which is the recommended way to create the EDR) will populate the EdrData with all the key/value pairs found in the RequestContext.

When the EdrService writes the alarm or CDR additional information content into the database, it will use all the EdrData key/value pairs EXCEPT a set of well-known keys that are either not relevant or already included in other columns of the database, see "Alarm content" and "CDR content".

Categorizing EDRs

Only one type of EDR exists: alarms and CDRs are subsets of this EDR type. In order to categorize the flow of EDRs as either pure EDRS, alarms or CDRs, the EDR service uses 3 descriptors:

  • The EDR descriptor contains descriptors that describe pure EDRs.

  • The alarm descriptor contains descriptors that describe EDRs that should be considered alarms.

  • The CDR descriptor contains descriptors that describe EDRs that should be considered CDRs.

These XML descriptors can be manipulated using the EDR Configuration Pane as described in Managing and Configuring EDRs, CDRs and Alarms in the System Administrator's Guide. File representations of these must be included in edrjmslistener.jar if you are using external EDR listeners.

The EDR descriptor

Each descriptor contains a list of EDR descriptors that define an EDR as a pure-EDR, as an alarm or as a CDR.

Table 11-4 EDR descriptors.

DescriptorDescriptorDescription

EDR

<edr...>

Defines which EDRs are pure EDRs

Alarm

<alarm...>

Defines which EDRs are alarms

CDR

<cdr...>

Defines which EDRs are CDRs


The descriptor is composed of two parts:

  • The <filter> element: this is the filter

  • The <data> element: this part is used to attach additional data with the EDR if it is matched by the <filter> part

Table 11-5 describes the elements allowed in the <filter> part:

Table 11-5 Elements allowed in <filter> part of an EDR descriptor.

SourceFilterMin occursMax occursDescription

<method>

N/A

0

unbounded

Filter EDR triggered by a method

<method>

<name>

0

unbounded

Name of the method that triggered the EDR

<method>

<class>

0

unbounded

Name of the class that triggered the EDR

<method>

<direction>

0

2

Direction of the request

<method>

<interface>

0

3

Interface where the EDR has been triggered

<method>

<position>

0

2

Position relative to the method that triggered the EDR

<exception>

N/A

0

unbounded

Filter EDR triggered by an exception

<exception>

<name>

0

unbounded

Name of the exception that triggered the EDR

<exception>

<class>

0

unbounded

Name of the class where the exception was thrown

<exception>

<method>

0

unbounded

Name of the method where the exception was thrown

<exception>

<direction>

0

2

Direction of the request

<exception>

<interface>

0

3

Interface where the EDR has been triggered

<exception>

<position>

0

2

Position relative to the method that triggered the EDR

<attribute>

N/A

0

unbounded

Filter EDR by looking at custom attribute

<attribute>

<key>

1

1

Name of the key

<attribute>

<value>

1

1

Value


Table 11-5 describes the values allowed for each element of the <filter> part:

Table 11-6 Values allowed in each element of the <filter> part.

SourceFilterAllowed valuesComment

<method>

<name>

“returntype nameofmethod([args])”

Method name. The arguments can be omitted with the parenthesis. See "Special characters" below.

<method>

<class>

“fullnameofclass”

Fully qualified class name. See "Special characters" below.

<method>

<direction>

“south”, “north”

N/A

<method>

<interface>

“north”, “south”, “other”

N/A

<method>

<position>

“before”, “after”

N/A

<exception>

<name>

“fullnameofexceptionclass”

Fully qualified exception class name. See "Special characters" below.

<exception>

<class>

“fullnameofclass”

Fully qualified class name where the exception was triggered. See "Special characters" below.

<exception>

<method>

“returntype nameofmethod([args])”

Method name. The arguments can be omitted with the parenthesis See "Special characters" below.

<exception>

<direction>

“south”, “north”

N/A

<exception>

<interface>

“north”, “south”, “other”

N/A

<exception>

<position>

“before”, “after”

N/A

<attribute>

<key>

“astring”

N/A

<attribute>

<value>

“astring”

N/A


Special characters

The filter uses special characters to indicate more precisely how to match certain values.

Using * at the end of a method, class or exception name matches all names that match the string specified prior to the * (that is, what the string starts with).


Note:

The use of any of these characters disables the caching of the filter containing them. To avoid a performance hit, using the other way of matching is strongly encouraged.

Table 11-7 Example filters

To match onUse the filter

All sendInfoRes methods with one argument of type int.

<method>

<name>void sendInfoRes(int)</name>

...



</method>

All methods starting with sendInfoRes regardless of the arguments.

<method>

<name>void sendInfoRes</name>

...

</method>

All methods starting with void sendInfo.

<method>

<name>void sendInfo*</name>

...

</method>

All class names beginning with com.bea.wlcp.wlng.plugin

<method>

<class>com.bea.wlcp.wlng.plugin*</class>

...

</method>


Values provided

The exact value in these fields depends on who triggered the EDR. If the aspect triggered the EDR, then the name of the method (with return type and parameters) or the fully qualified name of the class/exception is indicated. If the EDR is manually triggered from the code, it is up to the implementer to decide what name to use. Here are some examples of fully qualified method/class names as specified by the aspect:

Example methods:

SendSmsResponse sendSms(SendSms)
void receivedMobileOriginatedSMS(NotificationInfo, boolean, SmsMessageState, String, SmsNotificationRemote)
TpAppMultiPartyCallBack reportNotification(TpMultiPartyCallIdentifier, TpCallLegIdentifier[], TpCallNotificationInfo, int)

Example Class:

com.bea.wlcp.wlng.plugin.sms.smpp.SMPPManagedPluginImpl

Boolean semantic of the filters

Figure 11-3 shows briefly how the filter works:

  • The EdrConfigSource elements are the following: <method>, <exception> or <attribute>. They are combined using OR.

  • The filter elements of each EdrConfigSource are combined using AND. However, if the same filter is available more than once (e.g. multiple class names), it is combined with OR.

Figure 11-3 Filter mechanism

Description of Figure 11-3 follows

Example filters

Example 1: filter

Example 11-10 categorizes EDRs as pure EDRs with an id of 1000 when the following conditions are met:

  • The class where the method triggered the EDR is com.bea.wlcp.wlng.plugin.AudioCallPlugin or any subclass of it.

  • AND the request is southbound (direction = south)

  • AND the interface where the EDR was trigger is north

  • AND the EDR has been triggered after the method has been executed (position = after)

Example 11-10 Example 1: filter

<edr id="1000" description="...">
    <filter>
      <method>
        <class>com.bea.wlcp.wlng.plugin.AudioCallPlugin</class>
        <direction>south</direction>
        <interface>north</interface>
        <position>after</position>
      </method>      
    </filter>
  </edr>

Example 2: Alarm filter

Example 11-11 categorizes EDRs as alarms when the following conditions are met:

  • The exception is the com.bea.wlcp.wlng.plugin.PluginException class or a subclass of it.

  • OR the name of the exception starts with org.csapi.*. Since “'*” is used, the matching will not be performed using the class hierarchy but only using a pure string matching.

The alarms descriptor has a <alarm-group> element that is used to group alarms by service/source: this group id and each individual alarm id is used to generate the OID of SNMP traps.

Example 11-11 Example 2: filter

<alarm-group id="104" name="parlayX" description="Parlay X alarms">>
<alarm id="1000" severity="minor" description="Parlay X exception">
    <filter>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.PluginException</name>
        <name>org.csapi*</name>
      </exception>
    </filter>
  </alarm>
</alarm-group>

Example 3: Alarm filter

Example 11-12 categorizes EDRs as alarms when the following conditions are met:

  • The exception is the class com.bea.wlcp.wlng.plugin.PluginException or a subclass of it

  • OR the name of the exception starts with “org.csapi”. String matching in used.

  • AND the exception was triggered in a class whose name starts with com.bea.wlcp.wlng.plugin

  • AND the request is northbound (direction = north) when the exception was triggered

If the filter determines that the EDR is an alarm, the following attributes are available to the alarm listener. They are defined in the <data> part.

  • identifier = 123

  • source = wlng_nt1

Example 11-12 Example 3: filter

<alarm id="1000" severity="minor" description="Parlay X exception">
    <filter>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.PluginException</name>
        <name>org.csapi*</name>
        <class>com.bea.wlcp.wlng.plugin*</class>
        <direction>north</direction>
      </exception>
    </filter>
    <data>
      <attribute key="identifier" value="123"/>
      <attribute key="source" value="wlng_nt1"/>
    </data>
  </alarm>

Example 4: filter

Example 11-13 (for example purposes only) categorizes EDRs as pure EDRs with the id 1002 when the following conditions are met:

  • The name of the method that triggered the EDR starts with “void play” AND the class is com.bea.wlcp.wlng.plugin.AudioCallPluginNorth or a subclass of it AND the EDR was triggered after executing this method.

  • OR the name of the method that triggered the EDR is “String getMessageStatus” AND the class is 'com.bea.wlcp.wlng.plugin.AudioCallPluginNorth' or a subclass of it AND the EDR was triggered before executing this method.

  • OR the name of the exception that triggered the EDR starts with com.bea.wlcp.wlng.bar AND the exception was triggered in a plug-in north interface

  • OR the name of the exception that triggered the EDR starts with com.bea.wlcp.wlng.plugin.exceptionA AND the exception was triggered in a class whose name starts with com.bea.wlcp.wlng.plugin.classD AND the exception was triggered in a method whose name starts with void com.bea.wlcp.wlng.plugin.methodA AND the exception was triggered in a plug-in north interface

  • OR the EDR contains an attribute with key attribute_a and value value_a

  • OR the EDR contains an attribute with key attribute_b and value value_b

Example 11-13 Example 4: filter

<edr id="1002">
    <filter>
      <method>
        <name>void play*</name>
        <class>com.bea.wlcp.wlng.plugin.AudioCallPluginNorth</class>
        <position>after</position>
      </method>
      <method>
        <name>String getMessageStatus</name>
        <class>com.bea.wlcp.wlng.plugin.AudioCallPluginNorth</class>
        <position>before</position>
      </method>
      <exception>
        <name>com.bea.wlcp.wlng.bar*</name>
        <interface>north</interface>
      </exception>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.exceptionA</name>
        <class>com.bea.wlcp.wlng.plugin.classD</class>
        <method>void com.bea.wlcp.wlng.plugin.methodA</method>
        <interface>north</interface>
      </exception>
      <attribute key="attribute_a" value="value_a"/>
      <attribute key="attribute_b" value="value_b"/>
    </filter>
  </edr>

Example 5: filter with corresponding code for manually triggering a matching EDR

Example 11-14 shows a manually triggered EDR with its corresponding filter. The EDR is triggered using these lines.

Example 11-14 Example 5: Trigger the EDR

  // Declare the EdrDataHelper for each class 
  private static final EdrDataHelper helper = EdrDataHelper.getHelper(MyClass.class);

  public void myMethodName() {
    ...
    // Create a new EdrData. Use the EdrDataHelper class to allow Services Gatekeeper to automatically populate some fields
    EdrData data = helper.createData();
        
    // Because we are creating the EdrData manually, we have to provide the mandatory fields 
    data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
    data.setValue(EdrConstants.FIELD_METHOD_NAME, "myMethodName");
    data.setValue("myKey", "myValue");
  
    // Log the EDR
    EdrServiceFactory.getService().logEdr(data);
    ...
  }

This EDR can be filtered using Example 11-15 (note the various ways of identifying this EDR):

Example 11-15 Example: Filter 5

  <edr id="1003">
    <filter>
      <!-- Match both method name and class name -->
      <method>
        <name>myMethodName</name>
        <class>com.bea.wlcp.wlng.myClassName</class>
      </method>
      <!-- OR match only the method name (looser than matching also the class name) -->
      <method>
        <name>myMethodName</name>
      </method>
      <!-- OR match only the classname (looser than matching also the method name) -->
      <method>
        <class>com.bea.wlcp.wlng.myClassName</class>
      </method>
      <!-- OR match only the custom attribute -->
      <attribute key="myKey" value="myValue"/>
    </filter>
  </edr>

Checklist for EDR generation

Below is a list of steps to take to make your plug-in able to use aspect EDRs:

  • Make sure to register all your PluginNorth (and south) objects within the ManagedPlugin before registering in the PluginManager.

  • Annotate all the methods you want to be woven using the @Edr annotation.

  • Annotate the specific arguments you want to see in the EDR for each annotated methods. Use either @ContextKey or @ContextTranslate depending on the kind of argument.

  • Add to the EDR descriptor all the EDRs you are triggering, either manually or with the @Edr annotation. This is the only way to customize alarms and CDRs.

  • If external EDR listeners, CDR, and alarms are used, the edrjmslistener.jar file needs to be updated on all the listeners. Add the contents of the EDR descriptors to edr.xml, CDR descriptor to cdr.xml, and alarm descriptor to alarm.xml. The xml files reside in the edr directory in edrjmslistener.jar.

Frequently Asked Questions about EDRs and EDR filters

Question (Q): Is it possible to specify both exception and method name in the filter section?

Example 11-16 Example: method name and exception in a filter.

<filter>
      <method>
        <name>internalSendSms</name>
      </method>
      <exception>
        <name>com.bea.wlcp.wlng.plugin.sms.smpp.TooManyAddressesException</name>
      </exception>
    </filter>

Answer

Yes, make sure that the <method> element is before the <exception> element. Otherwise the XSD will complain.

Q: Is it possible to specify multiple method names?

Answer

Yes.

Q: In some places I have methods re-throwing an exception. Is it possible to have only one of the methods generate the EDR and map that EDR to an alarm?

Re-throwing an exception

myMethodA()throws MyException{
  myMethodB();
}

myMethodB()throws MyException{
  myMethodC();
}

myMethodC()throws MyException{
  ...
  //on error
 throw new MyException(“Exception text..”);
}

Answer

In this case, only the first exception will be caught by aspects. Or more precisely, they will all be caught by aspects but will only trigger an EDR for the first one, but not for the re-thrown ones (if they are the same, of course). So you don't need to use the @NoEdr annotation for myMethodA and myMethodB.

Q: Will aspects detect the following exception?

Example exception

    try{
      throw new ReceiverConnectionFailureException(message);
    }catch(ReceiverConnectionFailureException connfail){
      //EDR-ALARM-MAPPING
    }

Answer

This exception will not be detected by aspects. If you need to generate an EDR you will have to either manually create an EDR or call a method throwing an exception.

Q: Will EDRs for exceptions also work for private methods?

Answer

Yes, EDRs can work for any method.

Q: Will exceptions be disabled with the @NoEdr annotation?

Answer

Yes, with the @NoEdr annotation you will not get any EDRs, not even for exceptions.

Q: How can data from the current context be included in an alarm?

For example, can an alarm be generated in a request with more than 12 destination addresses? How can information about how many addresses were included in the request be added to the alarm

It is possible to specify some info in the alarm descriptor with something like

<data>
      <attribute key="source" value="thesource"/>
</data>

Can something be put in the RequestContext using the putEdr method and then get it into the alarm in some way?

Answer

Yes, add custom information by putting this information into the current RequestContext, as show below.

RequestContext ctx = RequestContextManager.getCurrent();
ctx.putEdr("address", "tel:1234"); 

This value is part of any EDRs generated in the current request.

The information will be available in the database in the additional_info column. Make sure you are putting in only relevant information.

Q: Is it possible to specify classname in the filtering section?

Answer

Yes, use the <class> element inside <method> or <exception> in the filter.

 <filter>
      <exception>
        <class>com.y.y.z.MyClass</class>
        <name>com.x.y.z.MyException</name>
      </exception>
</filter>

Alarm generation

An alarm is a subset of an EDR. To generate an alarm, generate an EDR, either using one generated in aspects or programmatically, and define the ID and the descriptor of the alarm in the alarm descriptor.

The alarm ID, severity, description and other kind of attributes are defined in the alarm descriptor, see "The EDR descriptor". For extensions, the alarm ID should be in the 500 000 to 999 999 range.


Note:

The alarm filter that provides the first match in the alarm descriptor is used for triggering the alarm.

There are two ways to trigger an alarm:

  • Use an existing EDR that is generated in the plug-in and add its descriptor to the alarm descriptor.

  • Programmatically trigger an EDR and add its descriptor in both the alarm descriptor file and the EDR descriptor. Make sure the ID of the alarm is unique and that the description is the same as in the EDR descriptor.T

Trigger an alarm programmatically

Trigger an EDR as described in "EDR Content". Then specify in the alarm descriptor the corresponding alarms.

Example 11-17 Example code to trigger an alarm

private static final EdrDataHelper helper = EdrDataHelper.getHelper(MyClass.class);
...
EdrData data = helper.createData();
data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
data.setValue(EdrConstants.FIELD_METHOD_NAME, "com.bea.wlcp.wlng.myMethod");
data.setValue("myAdditionalInformation", ...);
EdrServiceFactory.getService().logEdr(data);
...

The corresponding entry in the alarm descriptor that matches this EDR is shown below.

Example 11-18 Alarm descriptor

  <alarm id="2006"
         severity="major"
         description="Sample alarm">
    <filter>
      <method>
        <name>com.bea.wlcp.wlng.myMethod</name>
        <class>com.bea.wlcp.wlng.myClass</class>
      </method>
    </filter>
  </alarm>

Alarm content

Table 11-8 shows a list of the information provided in alarms.

Table 11-8 Alarm information for alarm listeners, also stored in DB

FieldComment

alarm_id

Unique ID for the alarm.

Automatically provided by the EdrService.

source

Service name emitting the alarm.

Automatically provided by the EdrService.

timestamp

Timestamp in milliseconds since midnight, January 1, 1970 UTC.

Automatically provided by the EdrService.

severity

Severity level.

Defined in the alarm. descriptor.

identifier

The alarm identifier.

Defined in the alarm descriptor.

The column in the database will always contain the identifier defined in the alarm descriptor.

alarm_info

The alarm information or description.

Defined in the alarm descriptor.

additional_info

Automatically provided by the EdrService.

Not valid for backwards compatible alarm listeners.

Each entry is formatted as:

key=value\n

Similar to the Java properties file.

All the custom key/value pairs found in the EdrData except these are present (EdrConstants if not specified):

  • FIELD_TIMESTAMP

  • FIELD_SERVICE_NAME

  • FIELD_CLASS_NAME

  • FIELD_METHOD_NAME

  • FIELD_SOURCE

  • FIELD_DIRECTION

  • FIELD_POSITION

  • FIELD_INTERFACE

  • FIELD_STATE

  • FIELD_EXCEPTION_NAME

  • FIELD_ORIGINATING_ADDRESS

  • FIELD_DESTINATION_ADDRESS

  • FIELD_CONTAINER_TRANSACTION_ID

  • FIELD_APP_INSTANCE_ID

  • FIELD_FACADE

  • FIELD_CORRELATOR

  • FIELD_SESSION_ID

  • FIELD_SERVER_NAME

  • FIELD_URL

  • FIELD_WEB_APP_NAME

  • FIELD_REQUEST_CONTEXT

  • FIELD_HTTP_METHOD

  • FIELD_INTERCEPTOR_CHAIN

  • FIELD_SUBSCRIBER_ID

  • ExternalInvocatorFactory.SERVICE_CORRELATION_ID

  • FIELD_BC_EDR_ID

  • FIELD_BC_EDR_ID_3

  • FIELD_BC_ALARM_IDENTIFIER

  • FIELD_BC_ALARM_INFO


CDR generation

A CDR is a subset of an EDR. To generate a CDR, generate an EDR and define the ID of the EDR in the CDR descriptor.

Triggering a CDR

There are two ways to trigger a CDR:

  • Use an existing EDR that is generated in the plug-in and add its description to the CDR descriptor.

  • Programmatically trigger an EDR and add its description to the CDR descriptor.

Trigger a CDR programmatically

If none of the existing EDRs is appropriate for a CDR, you can programmatically trigger an EDR that will become a CDR. See the section, "Triggering an EDR Programmatically" for information on how to create and trigger an EDR. Specify in the CDR descriptor the description necessary for this EDR to be considered a CDR.

Example 11-19 Example, triggering a CDR

private static final EdrDataHelper helper = EdrDataHelper.getHelper(MyClass.class);
...
EdrData data = helper .createData();
data.setValue(EdrConstants.FIELD_SOURCE, EdrConstants.VALUE_SOURCE_METHOD);
data.setValue(EdrConstants.FIELD_METHOD_NAME, "com.bea.wlcp.wlng.myEndOfRequestMethod");
// Fill the required fields for a CDR
data.setValue(EdrConstants.FIELD_CDR_START_OF_USAGE, ...);
...
EdrServiceFactory.getService().logEdr(data);
...

The description, in the CDR descriptor, that matches this EDR is shown in Example 11-20.

Example 11-20 Filter to match the EDR

<cdr>
    <filter>
      <method>
        <name>com.bea.wlcp.wlng.myEndOfRequestMethod</name>
        <class>com.bea.wlcp.wlng.myClass</class>
      </method>
    </filter>
</cdr>

CDR content

In addition to the EDR fields, there are specific fields used only for CDRs. They are listed in Table 11-5.

Table 11-9 Fields in EdrConstants specific for CDRs.

Field in EdrConstantsComment

FIELD_CDR_SESSION_ID

Session ID

FIELD_CDR_START_OF_USAGE

Start Time

FIELD_CDR_CONNECT_TIME

Connect Time

FIELD_CDR_END_OF_USAGE

End Time

FIELD_CDR_DURATION_OF_USAGE

Duration

FIELD_CDR_AMOUNT_OF_USAGE

Amount

FIELD_CDR_ORIGINATING_PARTY

Originating Party

FIELD_CDR_DESTINATION_PARTY

Same pattern applies as for send lists, see "Using send lists".

FIELD_CDR_CHARGING_INFO

Charging Information


The structure of the CDR content is aligned toward the 3GPP Charging Applications specifications. As a result the database schema has been changed to accommodate these ends and to facilitate future extensions.

Legends:

  • NU: Not used

  • NC: New column in DB

  • RC: Renamed column in DB

Table 11-10 Content in database

FieldCommentDB

transaction_id

Unique id for the CDR.

Provided automatically by the EDR service.

x

service_name

name of the service

Provided automatically by the EDR service.

x

service_provider

the service provider account ID

Provided automatically by the EDR service.

x

application_id

the application account ID (was user_id in 2.2)

RC

application_instance_grp_id

the application instance ID.

NC

container_transaction_id

id of the current user transaction

Provided automatically by the EDR service.

NC

server_name

name of the server that generated the CDR.

Provided automatically by the EDR service.

NC

timestamp

in ms since midnight, January 1, 1970 UTC

NC

service_correlation_id

Service Correlation ID.

Provided automatically by the EDR service.

NC

charging_session_id

Id that correlates requests that belong to one charging session as defined by the plug-in. Was 'session_id' in 2.2.

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

start_of_usage

The date and time the service capability module started to use services in the network (in ms since midnight, January 1, 1970 UTC)

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

connect_time

The date and time the destination party responded (in ms since midnight, January 1, 1970 UTC). Used for call control only.

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

end_of_usage

The date and time the service capability module stopped using services in the network (in ms since midnight, January 1, 1970 UTC).

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR

x

duration_of_usage

The total time the service capability module used the network services (in ms)

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR

x

amount_of_usage

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

originating_party

The originating party address with scheme included (e.g. “tel:1234”)

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

destination_party

the originating party address with scheme included (e.g. “tel:1234”). Additional addresses are stored in the additional_info field.

x

charging_info

The charging service code from the application.

Plug-in specific. Plug-in needs to put the value into the RequestContext of the request that will trigger the CDR.

x

additional_info

Additional information provided by the plug-in

x

revenue_share_percentage

Not used.

NU

party_to_charge

Not used.

NU

slee_instance

Not used.

NU

network_transaction_id

Not used.

NU

network_plugin_id

Not used.

NU

transaction_part_number

Not used.

NU

completion_status

Not used.

NU


Additional_info column

The EDR populates the additional_info column of the DB with all the custom key/value pairs found in the EdrData except the ones listed below.

Excluded keys (EdrConstants if not specified):

  • FIELD_SERVICE_NAME

  • FIELD_APP_INSTANCE_ID

  • FIELD_SP_ACCOUNT_ID

  • FIELD_CONTAINER_TRANSACTION_ID

  • FIELD_SERVER_NAME

  • FIELD_TIMESTAMP

  • ExternalInvocatorFactory.SERVICE_CORRELATION_ID

  • FIELD_CDR_SESSION_ID

  • FIELD_CDR_START_OF_USAGE

  • FIELD_CDR_CONNECT_TIME

  • FIELD_CDR_END_OF_USAGE

  • FIELD_CDR_DURATION_OF_USAGE

  • FIELD_CDR_AMOUNT_OF_USAGE

  • FIELD_CDR_ORIGINATING_PARTY

  • FIELD_CDR_DESTINATION_PARTY

  • FIELD_CDR_CHARGING_INFO

  • FIELD_CLASS_NAME

  • FIELD_METHOD_NAME

  • FIELD_SOURCE

  • FIELD_DIRECTION

  • FIELD_POSITION

  • FIELD_INTERFACE

  • FIELD_STATE

  • FIELD_EXCEPTION_NAME

  • FIELD_ORIGINATING_ADDRESS

  • FIELD_DESTINATION_ADDRESS

  • FIELD_CORRELATOR

  • FIELD_APP_ACCOUNT_ID

  • FIELD_SESSION_ID

  • FIELD_TRANSACTION_ID

  • FIELD_FACADE

  • FIELD_URL

  • FIELD_WEB_APP_NAME

  • FIELD_REQUEST_CONTEXT

  • FIELD_INTERCEPTOR_CHAIN

  • FIELD_SUBSCRIBER_ID

  • FIELD_BC_EDR_ID

  • FIELD_BC_EDR_ID_3

  • FIELD_BC_ALARM_IDENTIFIER

  • FIELD_BC_ALARM_INFO

Two keys not present in the EdrData are added to additional_info.

Table 11-11 Keys not present in EdrData, but added in additional_info

KeyDescription

destinationParty

If a send list is specified as the destination party, the first address will be written in the destination_party field of the DB and the remainder of the list will be written under this key name

oldInfo

Any backwards compatible additional info is available


The format of the additional_info field is formatted as:

key=value\n

similar to the Java properties file.

Out-of-the box (OOTB) CDR support

It is difficult to come up with a CDR generation scheme that fulfills the requirements of all customers. Oracle Communications Services Gatekeeper generates a default set of CDRs which can be customized by re-configuring the CDR descriptor.

The guiding principle for deciding when to generate CDRs is:

  • Generate a CDR when you are 100% sure that you have completely handled the service request

In other words, after the last method, in a potential sequence of method calls, returns.

For network-triggered requests this means that you should a trigger a CDR at the south interface after the method has returned back to the network. For application-triggered requests generate a CDR at the north interface after the method has returned to the Network Tier SLSB.

PKhSPK DOEBPS/pds_eclipswiz.htm Using the Eclipse Wizard

3 Using the Eclipse Wizard

This section describes how to use the Eclipse Wizard to generate various extensions for Oracle Communications Services Gatekeeper (Services Gatekeeper).

About the Eclipse Wizard

The Eclipse Wizard is an Eclipse plug-in that streamlines the creation of a variety of Services Gatekeeper extensions. The extension projects are created using wizards that customize the project depending on which type of extension is being developed. You can create the following extensions:

  • Communication Services

  • Interceptor Modules

  • OAuth2 Extension Handlers

  • Platform Test Environment Custom Modules

  • RESTful Communication Services

The Eclipse Wizard generates classes and Ant build files for both types of extensions, as well as a separate build file with Ant targets for packaging the extension for deployment.


Note:

The Communication Service Project(deprecated) wizard still exists for the sake of backwards compatibility. It is described in Using the Deprecated Communication Service Wizard, but its use is not recommended.

Configuring Eclipse

Before using Eclipse, you must configure it.

Prerequisites

  • Eclipse 4.0 or higher version must be installed.

  • OCSG version 5.1 or higher must be installed.

Basic configuration of Eclipse environment

To do the basic configuration of the Eclipse environment:

  1. Start Eclipse.

  2. Open the Preferences window, Window −> Preferences...

  3. In Java−>Installed JREs, make sure that the JRE used is the JRE installed with OCSG. This is installed in Middleware_Home/jdk_version/jre.

Configuring the Eclipse Wizard

To configure the Eclipse Wizard, do the following:

  1. Start Eclipse.

  2. Open the Preferences window, Window−>Preferences...

  3. In OCSG Platform Development Studio, configure the following:

    Middleware Home Directory The directory of the Oracle Communications Services Gatekeeper installation. This provides references to WebLogic Server APIs. In the default installation, this would be Middleware_Home.

    JDK Installation Directory The JDK installation directory for Oracle Communications Services Gatekeeper, for example Middleware_Home/jdk160_29b11.

    Logging Level The logging level of the Eclipse plug-in and the Ant tasks. Determines what level of detail to log by Eclipse. Select All for detailed logs, Standard for less detailed logs.

Generating a Communication Service Project

This section describes how to generate a communication service project.

A Communication Service project is based on a WSDL file and a set of attributes given when running the Communication Service Project wizard. Both RESTful and SOAP facades are generated from the provided WSDLs.

The WSDL defining the application-facing interface must adhere to the following:

  • The attribute name in <wsdl:service> must include the suffix Service.

  • The attribute name in <wsdl:port> must be the same as the name attribute in <wsdl:service>, excluding the suffix Service.

To generate a Communication Service project:

  1. In Eclipse, choose File then New Project.

    This opens the New Project window.

Table 3-1 Communication Service Wizard Tasks

In this window...Perform the following action...

Select a wizard

Make sure OCSG Platform Development Studio−>Communication Service Project is selected.

Click Next to proceed. You may cancel the wizard at any time by clicking Exit. You may go back to a previous window by clicking Previous.

Create a Communication Service

Enter a Project Name and choose a location for your project. Click Next to continue.

Define the Communication Service

Configure Service WSDL Files

For each WSDL file that includes the service definition to be implemented by the new Communication Service:

  1. Click the Add button Description of addel.png follows

  2. In the WSDL Configuration dialog, click the Add button adjacent the WSDL File text box, browse to the WSDL file, select it, and click OK.

  3. Choose to use either a custom REST configuration file by clicking the Add button adjacent the Use custom file text box, or have the wizard generate a configuration file by clicking the Generate button adjacent the Generate config file radio button.

    If you choose to have the wizard generate a rest-config.xml file for you, you should make any changes to the file before continuing.

  4. Click OK.

Define the Communication Service

Configure Callback WSDL Files

For each WSDL file that includes the callback service definition to be used by the new Communication Service in sending information to the service provider's application:

  1. Click the Add button. Description of addel.png follows

  2. In the WSDL Configuration dialog, click the Add button adjacent the WSDL File text box, browse to the WSDL file, select it, and click OK.

  3. Choose to use either a custom REST configuration file by clicking the Add button adjacent the Use custom file text box, or have the wizard generate a configuration file by clicking the Generate button adjacent the Generate config file radio button.

    If you choose to have the wizard generate a rest-config.xml file for you, you should make any changes to the file before continuing.

  4. Click OK.

Define the Communication Service

Communication Service Properties

Company: Set your company name, to be used in META-INF/MANIFEST.MF.

Version: Set the version, to be used in META-INF/MANIFEST.MF.

Identifier: Create an identifier to tie together a collection of Web Services. This identifier will be a part of the names of the generated war and jar files and the service type for the Communication Service:

communication_service_identifier.war and communication service identifier_callback.jar

Service Type: Set the service type. Used in EDRs, statistics, and others. For example: SmsServiceType, MultimediaMessagingServiceType.

Define the Communication Service

SOAP Properties tab

SOAP Class Package Name: The package name you wish to use for the SOAP communication service. Must adhere to standard Java naming conventions.

Web Services Context Path: The base HTTP path for the SOAP web service.

Handler File: A customized SOAP handler chain. If not provided, the default handler is used.

Define the Communication Service

REST Properties tab

RESTful Class Package Name: The package name you wish to use for the REST communication service. Must adhere to standard Java naming conventions.

RESTful Context Path: The base HTTP path for the RESTful web service.

RESTful Source Directory: A directory containing additional sources that will be compiled into war/APP-INF/classes. This directory is only used for the application tier.

RESTful Handler Chain: A customized RESTful handler chain. If not specified, the default handler chain will be used, including those for x-param, URL, session-id, authorizationHeader, and others.

JAXRS Application Class: An optional JAX-RS application class that defines resources and additional metadata. For more information, see chapter two in the JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.0 Final Release specification: http://download.oracle.com/otndocs/jcp/jaxrs-1.0-fr-eval-oth-JSpec/.

JAXRS Context Resolver Class: An optional JAX-RS class that provides context information to resource classes in addition to other providers. For more information, see chapter three of the JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.0 Final Release specification: http://download.oracle.com/otndocs/jcp/jaxrs-1.0-fr-eval-oth-JSpec/.

JAXRS Exception Mapper Classes: An optional JAX-RS class that maps Java exceptions to standard HTTP responses. For more information, see chapter five of the JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.0 Final Release specification: http://download.oracle.com/otndocs/jcp/jaxrs-1.0-fr-eval-oth-JSpec/.

Support Attachment: If checked the service will support attachments in both requests and responses.

Click Next to continue.

Define the plug-in information

For each plug-in to be created in the Communication Service project:

This opens a pop-up window with the following fields:

Protocol: An identifier for the network protocol the plug-in implements. Used as a part of the names of the generated jar file: communication_service_identifier._protocol.jar and the service name Plugin_communication_service_identifier._protocol

Schemes: Address schemes the plug-in can handle. Use a comma separated list if multiple schemes are supported. For example: tel or sip

Package Name: Package names to be used.

Company: Used in META-INF/MANIFEST.MF.

Version: Used in META-INF/MANIFEST.MF.

SOAP to SOAP: Select to this check-box to generate a plug-in for a SOAP to SOAP Communication Service.

REST to REST: Select to this check-box to generate a plug-in for a REST to REST Communication Service.

Click Finish to start the code generation for the plug_in(s).


Generating an Interceptor Module

This section describes how to generate an interceptor module project.

To generate an interceptor module project:

  1. In Eclipse, choose File −> New −> Other.

    This opens the Select a wizard window.

Table 3-2 Interceptor Module Wizard Tasks

In this window...Perform the following action...

Select a wizard

Make sure OCSG Platform Development Studio −> Interceptor Module is selected.

Click Next to proceed. You may cancel the wizard at any time by clicking Exit. You may go back to a previous window by clicking Back.

Generate Interceptor modules

  1. Enter a Project name for your project.

  2. Select either Use default location or click Browse to choose a new location for your project.

  3. In the Package Name text box, enter a package name.

  4. In the Application Lifecycle Listener text box, enter an optional lifecycle listener.

  5. Click the Add button to an interceptor: Description of addel.png follows

Add Interceptor

For each interceptor you want to configure, enter the following information:

  • Name: the name of the interceptor.

  • Index: the index of the interceptor.

  • Point: the point in Services Gatekeeper where the interceptor will intercept events. You can choose from:

    • MO North

    • MO South

    • MT North

    • MT South

Generate Interceptor modules

You can add additional interceptors by clicking the Add button and entering the required information in the Add Interceptor dialog.

Click Finish to start the code generation for the interceptor(s).


Generating an OAuth 2.0 Extension Handler

This section describes how to generate an OAuth 2.0 extension handler.

To generate an OAuth 2.0 extension handler project:

  1. In Eclipse, choose File −> New −> Other.

    This opens the Select a wizard window.

Table 3-3 OAuth 2.0 Extension Handler Wizard Tasks

In this window...Perform the following action...

Select a wizard

Make sure OCSG Platform Development Studio −> OAuth2 Extension Handlers is selected.

Click Next to proceed. You may cancel the wizard at any time by clicking Exit. You may go back to a previous window by clicking Back.

Generate OAuth2 Extended Handlers

  1. Enter a Project name for your project.

  2. Select either Use default location or click Browse to choose a new location for your project.

  3. In the Package Name text box, enter a package name.

  4. Click the Add button to a handler: Description of addel.png follows

Add Handler

For each handler you want to configure, enter the following information:

  • Handler Name: the name of the OAuth2 handler. Select Ext if you want to add more extensive customization for the handler.

  • Validator Name: the name of the validator for the OAuth2 handler.

  • ResponseType: the type of response the validator expects:

    • code

    • token

  • GrantType: the type of grant type the validator expects:

    • authorization_code

    • refresh_token

    • password

    • client_credentials

Click OK to add the new validator.

Generate Interceptor modules

You can add additional handlers by clicking the Add button and entering the required information in the Add Handler dialog.

Click Finish to start the code generation for the handler(s).


Generating a Platform Test Environment Custom Module

To generate a Platform Test Environment custom module project:

  1. In Eclipse, choose File −> New −> Other.

    This opens the Select a wizard window.

Table 3-4 Platform Test Environment Custom Module Wizard Tasks

In this window...Perform the following action...

Select a wizard

Make sure OCSG Platform Development Studio −> PTE Custom Module is selected.

Click Next to proceed. You may cancel the wizard at any time by clicking Exit. You may go back to a previous window by clicking Back.

Generate PTE modules

  1. Enter a Project name for your project.

  2. Select either Use default location or click Browse to choose a new location for your project.

  3. Choose one of the following options:

    • Use custom WSDL files: creates a PTE module based upon a WSDL file that you specify. Continue to Generate PTE modules / Use custom WSDL files below.

    • Use predefined WSDL files: creates a PTE module based upon a pre-existing Services Gatekeeper application interface. Continue to Generate PTE modules / Use predefined WSDL files below.

    • Use WADL: creates a PTE module based upon a WADL file that you provide. Generate PTE modules / Continue to Use WADL below.

    • Rest2Rest WADL: creates a PTE module based upon a Rest2Rest WADL file that you provide. Continue to Generate PTE modules / Rest2Rest WADL below.

Generate PTE modules / Use custom WSDL files

In Configure Service WSDL Files, for each WSDL file that includes a service definition to be implemented by the new PTE module:

  1. Click the Add button Description of addel.png follows

  2. In the WSDL Configuration dialog, click the Add button adjacent the WSDL File text box, browse to the WSDL file, select it, and click OK.

  3. Optionally, click the Add button to add one or more JAX-WS or JAXB binding files to your project.

  4. Click OK.

In Configure Callback WSDL Files, for each WSDL file that includes a callback service definition to be used by the new PTE module to return information to the service provider's application:

  1. Click the Add button. Description of addel.png follows

  2. In the WSDL Configuration dialog, click the Add button adjacent the WSDL File text box, browse to the WSDL file, select it, and click OK.

  3. Optionally, click the Add button to add one or more JAX-WS or JAXB binding files to your project.

  4. Click OK.

Use PTE modules / Use predefined WSDL files

Choose one of the following predefined communication services:

  • px30_audio_call

  • px21_call_notification

  • px30_call_notification

  • px21_multimedia_messaging

  • px21_presence

  • ews_push_message

  • px21_sms

  • ews_binary_sms

  • ews_subscriber_profile

  • px21_terminal_location

  • px21_third_party_call

  • px30_third_party_call

  • px30_payment

Continue to Settings below.

Generate PTE modules / Use WADL

In Configure Service WADL Files, for each WADL file that includes a service definition to be implemented by the new PTE module:

  1. Click the Add button Description of addel.png follows

  2. In the WADL Files Configuration dialog, click the Add button, browse to the WADL file, select it, and click OK.

  3. Click OK.

  4. Continue to Generate PTE modules / Settings.

Generate PTE modules / Use Rest2Rest WADL

In Configure Service WADL Files, for each WADL file that includes a service definition to be implemented by the new PTE module:

  1. Click the Add button Description of addel.png followsp;

  2. In the WADL Files Configuration dialog, click the Add button, browse to the WADL file, select it, and click OK.

  3. Click OK.

  4. Continue to Generate PTE modules / Settings.

Generate PTE modules / Settings

In Settings, enter the following information:

Name: a name for the PTE module.

Package Name: a Java package name that will contain the package classes.

Company: your company name, used in META-INF/MANIFEST.MF.

Version: the version, used in META-INF/MANIFEST.MF.

Click Finish to generate the PTE module handler.


Generating a RESTful Communication Service Project

Service providers may have existing third-party or proprietary applications or platforms that communicate using REST web services. Services Gatekeeper functionality can be integrated with existing applications that support REST interfaces by creating a RESTFul communication service.

Services Gatekeeper supports two types of RESTFul communication services. A REST to REST service exposes an existing REST API allowing communication between RESTFul interfaces. A REST Exposure or empty service is an application bound, network-facing service used when RESTFul requests are sent to a custom network implementation for translation and processing.

Services Gatekeeper mediates traffic between users and existing REST infrastructure allowing the application of service level agreements, policy enforcement, security, alarms and statistics for more control over communication services.

For more information on communication services, see Communication Service Guide.

The Eclipse RESTful Communication Service Project wizard generates REST communication services from Web Application Description Language (WADL) files representing RESTFul web application services. Services Gatekeeper then uses the generated service to handle RESTFul communications between two platforms.

The Eclipse wizard is used to create both REST2REST and REST Exposure services.

To generate a RESTful communication service project:

  1. In Eclipse, choose File −> New −> Other.

    This opens the Select a wizard window.

Table 3-5 RESTful Communication Service Project Wizard Tasks

In this window...Perform the following action...

Select a wizard

Make sure OCSG Platform Development Studio −> RESTFul Communication Service Project is selected.

Click Next to proceed. You may cancel the wizard at any time by clicking Exit. You may go back to a previous window by clicking Previous.

Create a RESTFul Communication Service

Enter a Project Name and choose a location for your project.

Click Next to continue.

Define the RESTFul Communication Service

For each WADL file that includes the service definition to be implemented by the new Communication Service:

Click the Add button

Description of addel.png follows

Browse to the WADL file, select it, and click OK. To select all WADL files in a directory use *.wadl

Define the RESTFul Communication Service

For each WADL file that includes the callback service definition to be used by the new Communication Service in sending information to the service provider's application:

Click the add button, browse to the WADL file, select it, and click OK.

RESTFul Communication Service Properties

Company: Set your company name, to be used in META-INF/MANIFEST.MF.

Version: Set the version, to be used in META-INF/MANIFEST.MF.

Identifier: Create an identifier to tie together a collection of Web Services. Will be a part of the names of the generated war and jar files and the service type for the Communication Service:

communication_service_identifier.war and communication service identifier_callback.jar

Service Type: Set the service type. Used in EDRs, statistics, etc. For example: Rest2RestXsi_Actions.

Java Class Package Name: Set the package names to be used. For example: oracle.ocsg.rest2rest

Web Services Context path: Set the context path for the Web Service.For example: /xsi_actions

Source Directory: A directory containing additional sources that will be compiled into war/APP-INF/classes. This directory is only used for the application tier.

RESTful Handler Chain: A customized RESTful handler chain. If not specified, the default handler chain will be used, including those for x-param, URL, session-id, authorizationHeader, and others.

JAXRS Application Class: An optional JAX-RS application class that defines resources and additional metadata. For more information, see chapter two in the JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.0 Final Release specification: http://download.oracle.com/otndocs/jcp/jaxrs-1.0-fr-eval-oth-JSpec/.

JAXRS Context Resolver Class: An optional JAX-RS class that provides context information to resource classes in addition to other providers. For more information, see chapter three of the JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.0 Final Release specification: http://download.oracle.com/otndocs/jcp/jaxrs-1.0-fr-eval-oth-JSpec/.

JAXRS Exception Mapper Classes: An optional JAX-RS class that maps Java exceptions to standard HTTP responses. For more information, see chapter five of the JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.0 Final Release specification: http://download.oracle.com/otndocs/jcp/jaxrs-1.0-fr-eval-oth-JSpec/.

Support Attachment: If checked the service will support attachments in both requests and responses.

REST to REST: Check this box to generate a Rest2Rest Communication Service.

Click Next to continue to the Define the plugin information window or Finish if you are ready to create the project.

Define the plugin information

A list of plug-ins defined for the project is displayed.

For each plug-in to be created in the project:

Click the add plug-in button:

Description of addplugin.png follows

This opens a pop-up window with the following fields:

Protocol: An identifier for the network protocol the plug-in implements. Used as a part of the names of the generated jar file: communication_service_identifier._protocol.jar and the service name Plugin_communication_service_identifier._protocol

Schemes: Address schemes the plug-in can handle. Use a comma separated list if multiple schemes are supported. For example: tel or sip

Package Name: Package names to be used.

Company: Used in META-INF/MANIFEST.MF.

Version: Used in META-INF/MANIFEST.MF.

Choose which Type of plug-in to generate:

REST: Select to this radio-button to generate a generic, protocol-neutral, RESTful plug-in.

SIP: select to this radio-button to generate a plug-in that connects to a SIP network using a SIP Servlet.

Click OK.

The plug-in definitions are added to the list of plug-ins.

Click Finish to create the project.


Communication Service Wizard-generated OAM Attributes

The Communication Service and RESTFul Communication Service wizards, generate the following OAM attributes in <Project_Name>/<Identifier>/plugins/protocol/src/<Plugin_Package_Name>.management/<Service_Type>MBean.java:

  • ServerUrl: The URL of the REST server

  • ProxyHost: The outbound HTTP proxy host

  • ProxyPort: The outbound HTTP proxy port

  • CallbackServerUrl: The URL of the REST callback server

  • CallbackProxyHost: The outbound HTTP proxy host of the mobile originating request

  • CallbackProxyPort: The outbound HTTP proxy port of the mobile originating request

  • CallbackUserName: The application instance name of the mobile originating request

  • CallbackUserPassword: The password for the application instance name of the mobile originating request


Note:

The values for ServerUrl and CallbackServerUrl are not pulled from the source WADL files and are, instead, set to http://xsp2.xdp.broadsoft.com. You must update those values manually after the project has been generated.

Adding and Removing Plug-ins

This section describes how to add plug-ins to and remove plug-ins from a communication service project.

Adding a Plug-in to a Services Gatekeeper Project

To add a plug-in to an existing Services Gatekeeper project:

  1. In the Eclipse package explorer, right-click the project for the Services Gatekeeper project, and choose Properties.

    This opens the Properties window for the Services Gatekeeper project.

Table 3-6 Add Plug-in Configuration Tasks

In this window...Perform the following action...

Plugin Configuration

A list of plug-ins defined for the project is displayed.

For each plug-in to be created in the project:

Click the add plug-in button:

Description of addplugin.png follows

This opens a pop-up window with the following fields:

Protocol: An identifier for the network protocol the plug-in implements. Used as a part of the names of the generated jar file: communication_service_identifier._protocol.jar and the service name Plugin_communication_service_identifier._protocol

Schemes: Address schemes the plug-in can handle. Use a comma separated list if multiple schemes are supported. For example: tel or sip

Package Name: Package names to be used.

Company: Used in META-INF/MANIFEST.MF.

Version: Used in META-INF/MANIFEST.MF.

Choose which Type of plug-in to generate:

SOAP: Select to this radio-button to generate a generic, protocol-neutral, plug-in.

SOAP to SOAP: Select to this radio-button to generate a plug-in for a SOAP to SOAP Communication Service.

SIP: select to this radio-button to generate a plug-in that connects to a SIP network using a SIP Servlet.

Click OK.

The plug-in definitions are added to the list of plug-ins.

Click Finish to start the code generation for the plug-in(s).


Removing a Plug-in from a Communication Service Project

To remove a a plug-in from an existing Communication Service project:

  1. In the Eclipse package explorer, right-click the project for the Communication Service project, and choose Properties.

    This opens the Properties Window for the Communication Service project.

    Table 3-7 Remove plug-in configuration task

    In this window...Perform the following action...

    Plugin Configuration

    A list of plug-ins defined for the Communication Service project is displayed.

    For each plug-in to be removed from the Communication Service project:

    1. Select the plug-in to be removed.

    2. Click the remove plug-in button:

      Description of removeplugin.png follows

      The plug-in definitions are removed from the list.

    3. Click Apply to remove the plug-in part(s) from the Communication Service project.

      Warning: This removes all parts of the project, including any manually edited or added files.

    4. Click Restore Defaults to restore the plug-in definition list.


  2. Click OK or Cancel to close the Properties window.

Using the Deprecated Communication Service Wizard

This section describes how to generate a communication service project using the deprecated communication service wizard.


Caution:

This wizard has been deprecated in favor of the wizard documented here Generating a Communication Service Project.

A Communication Service project is based on a WSDL file and a set of attributes given when running the Communication Service Project(deprecated) wizard.

The WSDL defining the application-facing interface must adhere to the following:

  • Attribute name in <wsdl:service> must include the suffix Service.

  • Attribute name in <wsdl:port> must be the same as the name attribute in <wsdl:service>, excluding the suffix Service.

To generate a Communication Service project:

  1. In Eclipse, choose File−>New Project.

    This opens the New Project window.

Table 3-8 Communication Service Wizard(deprecated) Tasks

In this window...Perform the following action...

Select Wizard

Make sure OCSG Platform Development Studio−>Communication Service Project(deprecated) is selected.

Click Next to proceed. You may cancel the wizard at any time by clicking Exit. You may go back to a previous window by clicking Previous.

Create a Communication Service

Enter a Project Name and choose a location for your project.

You can choose:

  1. To create an entirely new Communication Service

  2. To create a new Service Facade (application-facing interface) and the common parts of the Service Enabler layer for an existing plug-in

  3. To create a new network plug-in that uses the Service Facade and common parts of the Service Enabler of a currently existing Communication Service.

If you wish to do 3, check the check-box Use predefined communication service and from the drop-down list select the Service Facade for which you want to create a plug-in.

If you wish to do 1 or 2, leave the box unchecked.

Click Next to continue.

If you checked the Use predefined check box, the Define the Plug-in Information window is displayed. Go to Define the Plug-in Information instructions below.

If you did not check it, the Define the Communication Service is displayed.

Define the Communication Service / Configure Service WSDL Files

For each WSDL file that includes the service definition to be implemented by the new Communication Service:

Click the Add button

Description of addel.png follows

Browse to the WSDL file, select it, and click OK.

Define the Communication Service

Configure Callback WSDL Files

For each WSDL file that includes the callback service definition to be used by the new Communication Service in sending information to the service provider's application:

Click the add button, browse to the WSDL file, select it, and click OK.

Define the Communication Service

Communication Service Properties

Company: Set your company name, to be used in META-INF/MANIFEST.MF.

Version: Set the version, to be used in META-INF/MANIFEST.MF.

Identifier: Create an identifier to tie together a collection of Web Services. Will be a part of the names of the generated war and jar files and the service type for the Communication Service:

communication_service_identifier.war and communication service identifier_callback.jar

Service Type: Set the service type. Used in EDRs, statistics, etc. For example: SmsServiceType, MultimediaMessagingServiceType.

Java Class Package Name: Set the package names to be used. For example: com.mycompany.service

Web Services Context path: Set the context path for the Web Service.For example: myService

SOAP to SOAP: Check this box to generate a Service Facade that can be a part of a SOAP to SOAP Communication Service.

REST: Check this box to generate a RESTful Service Facade for the Communication Service.

Define the Plug-in information

For each plug-in to be created in the Communication Service project:

Click the add plug-in button

Description of addplugin.png follows

This opens a pop-up window with the following fields:

Protocol: An identifier for the network protocol the plug-in implements. Used as a part of the names of the generated jar file: communication_service_identifier._protocol.jar and the service name Plugin_communication_service_identifier._protocol

Schemes: Address schemes the plug-in can handle. Use a comma separated list if multiple schemes are supported. For example: tel: or sip:

Package Name: Package names to be used.

Company: Used in META-INF/MANIFEST.MF.

Version: Used in META-INF/MANIFEST.MF.

Choose which Type of plug-in to generate:

SOAP: Select to this radio-button to generate a generic, protocol-neutral, plug-in.

SOAP to SOAP: Select to this radio-button to generate a plug-in for a SOAP to SOAP Communication Service.

SIP: select to this radio-button to generate a plug-in that connects to a SIP network using a SIP Servlet.

Click OK.

The plug-in definitions are added to the list of plug-ins.

Click Finish to start the code generation for the plug_in(s).


PK}VfPK DOEBPS/cover.htm  Cover

Oracle Corporation

PK@t` PK DOEBPS/title.htm Oracle Communications Services Gatekeeper Platform Development Studio Developer's Guide, Release 5.1

Oracle® Communications Services Gatekeeper

Platform Development Studio Developer's Guide

Release 5.1

E37535-01

June 2013


Oracle Communications Services Gatekeeper Platform Development Studio Developer's Guide, Release 5.1

E37535-01

Copyright © 2007, 2013, Oracle and/or its affiliates. All rights reserved.

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

PKK PK DOEBPS/pds_ucp.htmu\ Using the UCP API

8 Using the UCP API

This chapter provides an overview of the Oracle Communications Services Gatekeeper (Services Gatekeeper) Universal Computer Protocol (UCP) API Java interface. It also contains some guidance on how to develop a customized UCP plug-in using the Services Gatekeeper Platform Development Studio and the UCP APIs.

UCP API Overview

The UCP protocol APIs enable platform developers to create custom UCP plug-ins without having to set up and manage connections from Services Gatekeeper to applications and SMSCs.

The UCP Protocol Server Service manages the low-level connectivity details, in conjunction with a configurable Connection Information Manager service, which stores mappings between plug-in instances and the hosts and ports and mappings between application instances and network node credentials.

Using the Protocol Server Service APIs, a plug-in obtains a connection to an application or SMSC and sends a protocol data unit (PDU) or acknowledgement on that connection. The APIs include classes for constructing UCP PDUs.

Figure 8-1 shows the UCP architecture.

Figure 8-1 UCP Architecture

Description of Figure 8-1 follows

A client-side connection is a connection between Services Gatekeeper and the SMSC, since Services Gatekeeper acts as client in this relationship. In the context of this architecture, a server-side connection is a connection between an application and Services Gatekeeper, since Services Gatekeeper acts as server in this relationship.

UCP Protocol Server Service

The UCP Protocol Server Service provides connection services on behalf of UCP plug-ins. It communicates with external applications and SMSCs using UCP over TCP/IP. This service:

  • Sends and receives UCP data from the socket.

  • Constructs the UCP PDU.

  • Associates the current PDU with the correct application instance.

  • Calls the plug-in.

All requests from a plug-in instance to the Protocol Server Service contain a plug-in instance ID. The Protocol Server Service performs connection and network credential mapping based on the configuration set up in the Connection Information Manager.

The UCP Protocol Service API defines the interface between the UCP Protocol Server Service and UCP plug-ins. See the oracle.ocsg.protocol.ucp and oracle.ocsg.protocol.ucp.pdu packages in Services Gatekeeper Java API Reference for documentation on this API.

The Protocol Server Service is a standard Services Gatekeeper WLS service. You can access it from the Administration console as UCPService under Container Services.

Connection Information Manager

The Connection Information Manager is a standard Services Gatekeeper service, which creates and stores connection and credential mappings that UCP plug-in instances need to connect to network elements and applications.

The UCP Protocol Service uses the Connection Information Manager to map plug-instance IDs to SMSC IP addresses and ports.

You can also optionally configure in the Connection Information Manager the local address and port to bind to when setting up a client-side connection to an SMSC. When Services Gatekeeper connects to the remote network node, it uses the specified local host IP address and port combination to bind the socket on the Services Gatekeeper side of the connection. The Protocol Service uses the specified port as a starting offset and increments the port number by one for each additional connection additional associated with the same plug-in instance ID. If the local host address is not configured, an ephemeral port is used.

You manage connection information settings from the Administration console. See ConnectInfoManager under Container Services, as shown in Figure 8-2. See the discussion of managing and configuring connection information in Services Gatekeeper System Administrator's Guide for information about specific operations.

Figure 8-2 UCP Protocol Server Service and Connection Information Manager in the Administration Console

Description of Figure 8-2 follows

PluginNorth

A plug-in implements the PluginNorth interface to perform the following tasks on behalf of application-initiated requests:

  • Send a mobile-terminated (MT) SMS message

  • Open a UCP session

  • Send an ACK to the SMSC

  • Send a NACK to the SMSC

You would extend and implement this interface to add a new application-facing UCP protocol plug-in.

PluginSouth

A plug-in implements the PluginSouth interface to perform the following tasks on behalf of network-triggered requests:

  • Deliver a mobile-originated (MO) SMS message

  • Deliver a message delivery notification associated with a previously-sent MT SMS

  • Send an ACK to the application

  • Send a NACK to the application

You would extend and implement this interface to add a new network-facing UCP protocol plug-in.

Additional Information You Will Need

In addition to the information in this chapter, developers should consult the following documents for information on how to build a UCP plug-in:

  • Services Gatekeeper Java API Reference

    Of special interest are the following packages, which include the interfaces and classes for the UCP Protocol Server Service:

    • oracle.ocsg.protocol.ucp

    • oracle.ocsg.protocol.ucp.pdu

    • oracle.ocsg.protocol.common

    The following packages include the plug-in interfaces and classes for the Native SMPP plug-in, which is part of the standard Services Gatekeeper Native UCP communication service. They can serve as a reference for developing customized north and south UCP plug-ins.

    • oracle.ocsg.plugin.nativefacade.ucp.north

    • oracle.ocsg.plugin.nativefacade.ucp.south

    In addition, you will need resources from various generic packages such as:

    • com.bea.wlcp.wlng.api.edr

    • com.bea.wlcp.wlng.api.management,

    • com.bea.wlcp.wlng.api.plugin

    • com.bea.wlcp.wlng.api.plugin.common

    • com.bea.wlcp.wlng.api.plugin.context

    • com.bea.wlcp.wlng.api.util

  • Services Gatekeeper Platform Development Studio Developer's Guide

    This guide explains how to use the Platform Development Studio to create a communication service or plug-in. See the following topics:

    • Understanding communication services

    • Using the Eclipse wizard

    • Description of a generated project

  • Services Gatekeeper Communication Service Guide

    See the Native UCP chapter. This chapter provides an overview of the Services Gatekeeper Native UCP communication service. It documents the attributes and operations provided to manage the UCP Protocol Server Service. The protocol server service is available for any UCP plug-in to access using the UCP Protocol Server Service APIs.

  • Services Gatekeeper System Administrator's Guide

    See the connection information chapter. The Connection Information Manager creates and stores connection and credential mappings used by UCP plug-ins.

Procedure for Creating a Customized UCP Plug-in

The following procedure outlines the basic steps to perform to add a custom UCP plug-in.

  1. Using the Services Gatekeeper SCE PDS Eclipse wizard, generate a customized network plug-in for the UCP communication service.

    You can also use this wizard to create a custom interceptor, if necessary.

    See the description of a generated project in Services Gatekeeper Platform Development Studio Developer's Guide.

  2. Create the service type for the customized plug-in by extending the ServiceType class.

    When the plug-in registers itself, an object of this type is passed to the Plug-in Manager.

  3. Implement the ManagedPluginService interface. This class activates, deactivates and initializes the plug-in service. It implements the PluginService, PluginServiceLifecycle and PluginInstanceFactory interfaces.

    See the discussions of communication services and generated projects in Services Gatekeeper Platform Development Studio Developer's Guide.

  4. Implement the ManagedPluginInstance interface.

    This class activates a plug-in instance that has been created with the Plug-in Manager, after which the plug-in should register its MBeans and prepare to accept traffic. The plug-in service that activates this plug-in instance must be in the ACTIVE (ADMIN) or ACTIVE (RUNNING) state when the activate method is called.

    This class also initializes and deactivates the plug-in instance and determines whether the plug-in instance is capable of servicing the current request.

    See the discussion of communication services in Services Gatekeeper Platform Development Studio Developer's Guide.

  5. If you are implementing an application-facing UCP module, extend and implement the PluginNorth interface: SubmitSm, openSession, ack and nack.

  6. If you are implementing a network-facing UCP module, extend and implement the PluginSouth interface: deliverSm, deliveryNotification, ack and nack.

  7. Create CDRs and EDRs to trace the message flow, if necessary.

  8. From the Administration console, configure the connection and credential mappings in the Connection Information Manager.

    See the discussion of managing and configuring connection information in System Administrator's Guide.

  9. Build the plug-in project and create the EAR package, which will be deployed to Services Gatekeeper.

  10. Use the Platform Test Environment (PTE) to test and debug the plug-in.

    See Services Gatekeeper Platform Test Environment Guide.

About the UCP Protocol Server Service Interfaces

The packages for the protocol server service are:

Using the UCP Protocol Server Service API, you can develop a custom UCP plug-in without having to implement the low-level connection functionality. The API provides a wrapper to bind, send, and receive messages and allows customization of PDUs.

oracle.ocsg.protocol.common

The oracle.ocsg.protocol.common.package provides four basic interfaces from which the UCP Protocol Server Service APIs are derived:

  • AbstractProtocolService

    This is the base class for the getProtocolServiceNorth and getProtocolServiceSouth methods. The UCPNetworkingServiceImpl class inherits from AbstractProtocolService to implement these methods.

  • ProtocolServiceProxyFactory

    Gets references to the getProtocolServiceNorth and getProtocolServiceSouth methods for use by the plug-in.

  • ProtocolServiceNorth

    This is the base interface for creating server-side connections.

  • ProtocolServiceSouth

    This is the base interface for creating client-side connections.

oracle.ocsg.protocol.ucp

The main protocol server service interfaces used by a UCP plug-in are:

  • UCPNetworkingService

    The UCPNetworkingService interface provides methods to add, remove, list and otherwise manage server-side and client-side connections. See the UCPNetworkingService interface in the oracle.ocsg.protocol.ucp package in the Services Gatekeeper Java API Reference for a list of the methods in this interface.

    In addition to accessing these methods programmatically, a System Administrator can also access most of the methods in the UCPNetworkingService interface as OAM operations from the UCPService pane of the Administration console.

    Figure 8-3 shows how to access the UCPService pane.

    Figure 8-3 Protocol Service Operations in Administration Console

    Description of Figure 8-3 follows

  • UCPNetworkingServiceClient

    This interface implements methods for sending PDUs, ACKs, and NACKs on a client-side connection. It extends the Services Gatekeeper oracle.ocsg.protocol.common.ProtocolServiceSouth interface.

    The plug-in uses this interface's sendPDUOnClientConnection method to send the plug-in instance ID and the PDU. The method returns a connection ID that identifies the connection to the SMSC on which the request was sent.

  • UCPNetworkingServiceServer

    This interface implements methods for sending PDUs, ACKs, and NACKs on a server-side connection. It extends the Services Gatekeeper oracle.ocsg.protocol.common.ProtocolServiceNorth interface.

  • The plug-in uses the sendPDUOnServerConnection method to send the connection ID and the PDU. The method returns a connection ID that identifies the connection to the application on which the request was sent.

oracle.ocsg.protocol.ucp.pdu

This package provides utility classes for building UCP PDUs for the supported UCP operations. This package provides classes for all of the supported UCP abstract data types (ADTs), as well as a generic UCP ADT, UCP constants, headers, and parameters

Connection Mapping

The Protocol Server Service uses mappings between application instances to network nodes configured in the Connection Information Manager to set up the connections that are used by the plug-ins.

At a minimum you need to configure the credential map, host address, and user password using these operations:

  • createOrUpdateCredentialMap

  • createOrUpdateRemoteHostAddress or createOrUpdateLocalHostAddress

  • createOrUpdateListenAddress

  • createOrUpdateUserPasswordCredentialEntry

There are various possible mapping logics; for example:

  • One connection to the SMSC for all Services Gatekeeper applications

  • One connection to the SMSC for a group of Services Gatekeeper applications

  • One connection to the SMSC for each Services Gatekeeper application

The simplest scenario is to configure a plug-in always to use the same application instance for all UCP requests. This requires only one connection to the SMSC. You would create the application instance in Services Gatekeeper and dedicate it to UCP southbound requests in the Connection Information Manager. Before making the call to the UCP Protocol Server Service, the plug-in can switch context to the UCP-dedicated application instance

Another scenario would configure the plug-in to use the current application instance to send requests through the service. This results in multiple connections to the SMSC, at least one per application instance. In this case, you must configure the Connection Information Manager with connection credentials and SMSC address and port mappings for all application instances.

There is no single correct solution. The mapping logic that you choose depends on the demands of your situation.

OAM Attributes Affecting UCP Network Connectivity

The UCPProtocol read-only attribute contains the UCP protocol string. This value is set to the listen address defined by the createOrUpdateListenAddress operation in the Connection Information Manager.

In the Administration console, you can configure two attributes that control how the Protocol Server Service handles reconnection attempts:

  • MaxReconnectAttempts: Specifies the maximum number of reconnection attempts permitted. Set to -1 for no maximum, 0 for no reconnection attempts, or a positive integer indicating the maximum number of reconnections to attempt.

  • TimeBetweenReconnectAttempts: Specifies the time in milliseconds between reconnection attempts.

Using the APIs

The first three examples in this section provide some guidance related to common tasks using the UCP APIs that would be performed by a custom application-facing UCP plug-in that implements and extends PluginNorth. The examples are based on a prototype for a ParlayX2.1 SMS plug-in. The last example is for a PluginSouth implementation processing a DELIVER_SM request.

The tasks include:

Sending a submitSm Request to the SMSC

When a plug-in receives a SUBMIT_SM request from an application, the PluginNorth implementing class processes the parameters in the request, constructs the PDU, and sends it to the SMSC using the UCPNetworkingServiceClient APIs.

The plug-in:

  1. Gets the UCP NetworkingService object. For example:

    UCPNetworkingService ucpService = PX21UCPPluginInstanceImpl.getUCPNetworkingService();
    
  2. Gets any outstanding standing SUBMIT_SM requests.

  3. Creates the submit PDU, using the classes in the oracle.ocsg.protocol.ucp.pdu package. See "Creating a UCP PDU".

  4. Gets the source connection ID.

  5. Gets the UCP NetworkingService protocol interface for sending data on a client connection. For example:

    UCPNetworkingServiceClient client = ucpService.getProtocolServiceSouth(UCPNetworkingServiceClient.class);
    
  6. Sends the PDU on the client connection, using the UCPNetworkingServiceClient sendPDUOnClientConnection method. For example:

    clientConnectionID = client.sendPDUOnClientConnection
    (
        px21UCPPluginInstanceImpl.getPluginInstanceId(),
        px21UCPPluginInstanceImpl.getSourceServerPort(),
        submitSMPDU,
        outstandingSubmitSMRequests,
        sourceConnectionID
    );
    

Creating a UCP PDU

To create a UCP PDU, you can use the classes in the oracle.ocsg.protocol.ucp.pdu package.

The following method creates the submitSM PDU used in "Sending a submitSm Request to the SMSC". It uses the using the UcpHeader, UcpParameter, GenericUcpAdt classes defined in the pdu package.

private UcpPDU createSubmitSMPDU(SendSms parameters) {
        UcpHeader ucpHeader = new UcpHeader();
        UcpParameter orParam = new UcpParameter("O");
        ucpHeader.setParameter(UcpHeader.PARAM_OR, orParam);
        UcpParameter otParam = new UcpParameter(UcpConstants.OT_SUBMIT_SHORT_MESSAGE);
        ucpHeader.setParameter(UcpHeader.PARAM_OT, otParam);
        UcpParameter trnParam = new UcpParameter("01");
        ucpHeader.setParameter(UcpHeader.PARAM_TRN, trnParam);
        UcpParameter lenParam = new UcpParameter("00000");
        ucpHeader.setParameter(UcpHeader.PARAM_LEN, lenParam);
 
        GenericUcpAdt data = new GenericUcpAdt(33);
 
        //ADC
        URI[] destAddresses = parameters.getAddresses();
        String uriStringDestAddress = destAddresses[0].toASCIIString();

        //Strip "tel:"
        String destAddressString = stripURIPrefix(uriStringDestAddress);
        UcpParameter adcParam = new UcpParameter(destAddressString);
        data.setParameter(Ucp50Adt.PARAM_ADC, adcParam);
 
        //OADC
        String senderName = parameters.getSenderName();
        UcpParameter oadcParam = new UcpParameter(senderName);
        data.setParameter(Ucp50Adt.PARAM_OADC, oadcParam);
 
        //NRQ and NT
        SimpleReference simpleRef = parameters.getReceiptRequest();
        String nrq = "";
        String nt = "";
        if(simpleRef != null){
            nrq = "0"; //0 == NADC not used
            nt = "7"; // 7 == all
        }
        UcpParameter nrqParam = new UcpParameter(nrq);
        data.setParameter(Ucp50Adt.PARAM_NRQ, nrqParam);
        UcpParameter ntParam = new UcpParameter(nt);
        data.setParameter(Ucp50Adt.PARAM_NT, ntParam);
 
        //If LRq is empty, the contents of LRAd and LPID are ignored
 
        //Message type 3 == "Alphanumeric message encoded into IRA characters."
        UcpParameter mtParam = new UcpParameter("3");
        data.setParameter(Ucp50Adt.PARAM_MT, mtParam);
 
        String message = parameters.getMessage();
        String iraEncodedMessage = iraEncodeMessage(message);
        UcpParameter msgParam = new UcpParameter(iraEncodedMessage);
        data.setParameter(Ucp50Adt.PARAM_MSG, msgParam);
 
        return new UcpPDU(ucpHeader, data);
    }

Sending an openSession Request to the SMSC

A connection from the UCP plug-in to the SMSC is implicitly established on receipt of the openSession request. Upon receiving the openSession request, the Protocol Server Service uses the current context as a key to determine the connection and credential mapping to use for the new connection that it is creating. The user and plug-in instance ID must therefore be configured in the Connection Information Manager before the openSession request is sent; otherwise the openSession request will fail.

The APIs do not provide a specific open session method.

To create a new session to the SMSC, create an openSession PDU using the pdu package and use the sendPDUOnClientConnection with a that openSessionPDU as the PDU parameter:

UCPNetworkingServiceClient client = ucpService.getProtocolServiceSouth(UCPNetworkingServiceClient.class);

String connectionID = client.sendPDUOnClientConnection
    (myUCPPluginInstanceImpl.getPluginInstanceId(),
     sourceServerPort, 
     openSessionPDU,
     outstandingOpenSessionRequests,
     sourceConnectionId);

A UCP plug-in uses the Protocol Server Service API after it receives an openSession PDU. The UCP Protocol Server Service creates a new socket connection for each session management operation of subtype openSession that is sent. The created connections are later used for sending SUBMIT_SM requests.

Sending a DeliverSm to an Application

When a plug-in receives a DELIVER_SM request from the SMSC, the PluginSouth implementing class processes the parameters in the request.

If the plug-in is communicating with a web services-based application, it typically analyzes the parameters in the request to find the correct application callback reference (URL) to which the mobile-originated SMS message should be sent and then sends it.

If the plug-in is communicating with a UCP-based application, it typically constructs a DELIVER_SM PDU, which it sends to the application-facing UCP NetworkingServerService APIs.

After notifying the application of the message, the plug-in should send an ACK or NACK to the SMSC to report whether the notification was successful.

The following process flow is for a plug-in communicating with a web services-based application:

  1. Gets the UCP NetworkingService object. For example:

    UCPNetworkingService ucpService = PX21UCPPluginInstanceImpl.getUCPNetworkingService();
    
  2. Processes the incoming deliverSM PDU to get the source and destination addresses. This implementation uses the UCP50Adt class to extract the data from the PDU:

    String destinationAddress = deliverSMPDU.getData().getParameter(Ucp50Adt.PARAM_ADC).getValueAsString();
    String originatingAddress = deliverSMPDU.getData().getParameter(Ucp50Adt.PARAM_OADC).getValueAsString();
    
  3. Gets the notification callback references.

  4. Implements support for using criteria and storing the mobile-originated message.

  5. Creates the deliverSM PDU.

  6. Send the deliverSM notification PDU. For example:

    boolean notificationOK = sendDeliverSMNotification(callbackRef, destinationAddress, originatingAddress, deliverSMPDU);
    
  7. Send ACK or NACK to the SMSC depending on the outcome of the notification. For example:

    if(notificationOK){
        sendAck(ucpService, connectionId, deliverSMPDU);
    }else{
        sendNack(ucpService, connectionId,deliverSMPDU, UcpConstants.ERROR_CODE_SYNTAX_ERROR);
                }
    
PKިuuPK DOEBPS/pds_pte_project.htmt Extending the ATE and the PTE

18 Extending the ATE and the PTE

The section describes how to generate and build Virtual Communication services, clients, and simulators for the Application Test Environment (ATE) and the Platform Test Environment (PTE) in Oracle Communications Services Gatekeeper (Services Gatekeeper).

Understanding ATE and PTE Extensions

Using the ATE you can create Virtual Communication Services, and interact with and extend to the network simulator. The ATE uses these extension points:

  • Virtual Communication Services

  • The network simulator part of the ATE

Using the PTE you can create client modules that act as applications, and simulator modules that acts as network elements and present results and statistics in the PTE user interface. The PTE uses these extension points:

  • Clients

  • Network protocol simulators

  • The network simulator part of the PTE

Figure 18-1 Extensions to the ATE and PTE

Description of Figure 18-1 follows

If you have extended Services Gatekeeper with a new communications service:

  • You can create a module that simulate this communication service and deploy it to the ATE. This provides application developers access to an application test environment that simulates the behavior of the communication service with which you have extended Services Gatekeeper.

  • You can use the PTE to test the communication service from an application perspective. You do this by creating create a module that acts as a client application to the new communication service and deploys it to the PTE.

  • You can use the PTE to test the communication service from a network perspective. You do this by creating a module that acts as a simulator to the new communication service and deploys it to the PTE.

The base for a Virtual Communication Service project, a client project, and a network protocol simulator project is one or more WSDL files defining the application-facing interfaces exposed by the ATE or used by the PTE.

You use Platform Development Studio Eclipse tools to generate source code, deployment descriptors, and build files for modules that use these extension points. The heart of this tool is an Eclipse wizard that guides you through the process of generating a project for these modules.

After the project has been generated, you add your implementation code to the generated source, and build it using the generated build file.

Your implementation can use a set of interfaces to interact with the statistics and presentation facilities provided by the ATE and the PTE. You can interact with the network simulator map and add new elements to the map. Refer to the JavaDoc for details about the interfaces.

Generating a Custom Module Project Using the Eclipse Wizard

See "Generating a Platform Test Environment Custom Module" for instructions on using the Eclipse wizard to create a custom PTE module.

Understanding the Generated Project

The Eclipse wizard generates:

  • A build file for the project: build.xml

  • A deployment descriptor: pte-extensions.xml

  • Depending on the type of project you generate, the project may also include:

    • Interface classes for a Virtual Communications Service.

    • Deployment class for a Virtual Communications Service.

    • Application client classes.

    • Network protocol simulator skeleton class.

The directory structure is described below:

<Eclipse_project>
+- build.xml
+- pte-extensions.xml
+- <Identifier given in Ecplise Wizard>
|  +- clients
|  +- simulators
|  +- vcs
|  |  +- <Identifier given in Eclipse Wizard>ModuleVCS.java
|  |  +- <Interface Name>Impl.java // One per interface
                                   // defined in the 
                                   // Service WSDL files.

Build File

A generated Apache Ant build file is created in the directory:

Eclipse_project/build.xml

Where Eclipse_project is the directory where the project was generated by the Eclipse Wizard.

The build file defines the following targets:

  • generate

    Generates source code.

  • compile

    Compiles the generated source code.

  • jar

    Packages the modules in JAR files.

  • clean

    Removes all generated artifacts.

  • dist

    Generates the source code, compiles it and generates JAR files to be deployed.

Deployment Descriptor

A deployment descriptor is created when the project is generated. The deployment descriptor file name is pte-extensions.xml. It is created in the Eclipse_project directory, where Eclipse_project is the directory where the project is generated by the Eclipse Wizard.

The deployment descriptor describes how the virtual Communication Service is deployed in the Application Test Environment.

The deployment descriptor is an XML file with the following structure:

<module>
   <data>
      <parameter>
      </parameter>
   </data>
</module>

The module element has these attributes:

  • name

    The name of the module given in the Name field in the Eclipse wizard. The suffix VCS is added for Virtual Communication Services. The suffix Simulator is added for simulators.

  • type

    The type of module. vcs for a Virtual Communications Service module, client for a client module, and sim for a simulator module.

  • class

    The fully qualified class name for the module. The first part of the package name is the name given in the Package name field in the Eclipse wizard. The name of the class is the name given in the Name field in the Eclipse wizard.

    For simulators, the last part of the package name is .simulators.. The class name has the suffix Simulator.

    For Virtual Communication Services, the last part of the package name is .vcs. The class name has the suffix VCS.

  • version

    The version of the module, given in the Version field in the Eclipse wizard.

  • depends

    The name of the module that this module depends on. In most cases, it is the Session module. Not used for Virtual Communications Services.

  • uiPanel

    Describes in which panel in the user interface of the ATE or the PTE the module presents it's user interface. For PTE clients is clients, for PTE simulators it is simulators, and for ATE Virtual Communication Services it is vcs.

  • uiTabs

    Describes in which tab in the GUI the module is presented. A comma-separated list describes the hierarchy.

The <data> element encapsulates zero or more parameter elements.

The <parameter> element describes fields in the user interface. It has the following attributes:

  • name

    The label of the parameter in the user interface. Mandatory.

  • class

    The class which defines the parameters in the user interface. Reflection is used to present the fields in the user interface. The parameters are presented as a hierarchy of description-only fields, and the parameters that have simple data types are presented with an input field. Optional.

  • default

    The default value for the input field.

  • occurs

    The number of occurrences of the parameter. Default value is 1.

Example 18-1 illustrates a deployment descriptor example for a client module.

Example 18-1 Example of a Client Module Deployment Descriptor

      <module name="SendSmsModule"
              type="client"
              class="my.company.sm.clients.SendSmsModule"
              version="1.0"
              depends="session"
              uiPanel="client"
              uiTabs="Other,ate_pte_sm,sendSms"
              >
 
        <data>
          <parameter name="Parameters"
                     class="my.company.sm.clients.SendSmsModuleData"
                     occurs="1">
 
            <parameter name="facade"/>
 
            <parameter name="url"
                       default="http://${at.host}:${at.port}/SendSmsModule"/>
 
            <parameter name="vcsUrl"
                       default="http://${localhost}:13444/jaxws/SendSmsModule"/>
 
            <parameter name="restUrl"
                       default="http://${at.host}:${at.port}/rest/SendSmsModule"/>
 
            <parameter name="restVcsUrl"
                       default="http://${localhost}:13444/rest/SendSmsModule"/>
 
          </parameter>
        </data>
      </module>

Example 18-2 illustrates a deployment descriptor example for a simulator module.

Example 18-2 Example of a Simulator Module Deployment Descriptor

      <module name="Ate_pte_smSimulator"
              type="sim"
              class="my.company.sm.simulators.Ate_pte_smSimulator"
              version="1.0"
              uiPanel="simulator"
              uiTabs="ate_pte_sm"
              >
 
        <data>
          <parameter name="Parameters"
                     class="parameterClassName"
                     occurs="1">
          </parameter>
          -->
        </data>
      </module>

Example 18-3 illustrates a deployment descriptor example for a Virtual Communication Service.

Example 18-3 Example of a Virtual Communications Service Module Deployment Descriptor

    <module name="Ate_pte_smVCS"
            type="vcs"
            class="my.company.sm.vcs.Ate_pte_smVCS"
            version="1.0"
            >
      </module>

Building and Deploying the Module

Run the Ant target dist to create a deployable module for the ATE or the PTE.

The deployable module is a JAR file named Name.jar, where Name is the name of module given in the Project Name field in the Eclipse wizard. The file is created in the dist sub-directory in the Eclipse project directory.

Deploying the module:

  • ATE: Copy the deployable module to SDK_Homelib/modules, where SDK_Home is the installation directory for the SDK.

  • PTE: Copy the deployable module to Service_Gatekeeper_Home/ocsg_pds_5.1/lib/modules, where Service_Gatekeeper_Home is the installation directory for Services Gatekeeper

Restart the ATE or PTE after deploying the new module.

Virtual Communication Service Module for the ATE

Skeletons of Java classes for a Virtual Communications Service for the ATE are created by the Eclipse Wizard. The classes are generated in the Project_home/src/Package_hierarchy/vcs directory.

The class Module_nameVCS deploys all the port implementations for the Virtual Communication Service. Module_name is given in the Eclipse Wizard.

The class implements the oracle.ocsg.pte.api.vcs.VCSModule interface.

The methods are:

  • getName()

    Returns the name of the module as a String. The name was given in the Name field in the Eclipse Wizard.

  • initialize(...)

    Initializes the module. If the module is exposing MBeans, register them here.

  • start(...)

    Deploys the module in the Web Services container. All generated implementation classes are deployed.

  • stop(...)

    Undeploys the module from the Web Services container.

A separate class is generated for each port defined in the WSDL that the project defines. The classes are named Port_nameImpl, where Port_name is defined in the WSDL.

Each of the implementation classes defines the web service using the annotation @WebService. Example 18-4 gives an example of the @WebService annotation.

Example 18-4 Example of an @WebService Annotation

@WebService(name = "SendSms", targetNamespace = "http://www.csapi.org/wsdl/parlayx/sms/send/v2_2/interface")

Each implementation class also defines a handler chain using the annotation @HandlerChain. This handler chain is necessary to leverage the security and SLA enforcement in the ATE and PTE. Example 18-5 illustrates the @HandlerChain annotation.

Example 18-5 Handler Chain Definition

@HandlerChain(file = "/vcs/VcsHandlerChains.xml")

Each method defined in the WSDL has a skeleton implementation. Each method is defined with the annotations:

  • @WebMethod

  • @WebResult

  • @RequestWrapper

  • @ResponseWrapper

Each method has an empty implementation where you add the custom code for the Virtual Communication Service.

Client Module for the PTE

Skeletons of Java classes for a client module for the Platform Test Environment are created by the Eclipse Wizard if the project was generated based on WSDL files.

The classes are generated in the Project_home/src/Package_hierarchy/clients directory.

For each method defined in the WDSL file the following classes are generated:

  • Method_NameModule

  • ResourceEndpoint

  • Method_NameModuleData

The class Method_NameModule deploys all the port implementations for the Virtual Communication Service. Method_Name is given in the WSDL file.

The class extends oracle.ocsg.pte.api.module.AbstractRestClientModule and implements oracle.ocsg.pte.api.module.CustomStatelessModule.

The following methods are defined:

  • execute(...)

  • prepare(...)

The method execute(...) is called when the Send button for the client method in the Platform Test Environment GUI is clicked or, once, at the beginning of a duration test. The skeleton for the method retrieves the data to use in the method call from the CustomModuleContext. This context is passed in as a parameter to execute(...). CustomModule is cast to the corresponding Method_NameModuleData object for the method.

The method prepare(...) fetches the URL from the field in the GUI and checks if the client shall use the SOAP interface or the RESTful interface by calling isRestFacade() on the CustomModuleContext. If the RESTful interface is used, the method getRestClient(...) defined by Method_NameModuleData object is fetched.

If the client shall use the SOAP facade, JAXWSServiceFactory is used to create the Web Service, a port is derived from the service and the local stub is set on the RequestContext.

The class ResourceEndpoint is instantiated if you are using the RESTful facade in the client. This class defines the methods:

  • getHttpMethod()

  • getResourceURI()

The method getHttpMethod shall return the HTTP request type as a String; POST or GET.

The method getresourceURI() shall return the URI to the RESTful method as a String.

The class Method_NameModule is used to hold the data about the request.

Simulator Module for the PTE

Skeletons of a Java classes for a simulator module for the Platform Test Environment are created by the Eclipse Wizard. The class is generated in the directory Project_home/src/Package_hierarchy/simulators.

The class is named Project_NameSimulator, where Project_Name is fetched from the Name field in the Eclipse Wizard.

The class implements the oracle.ocsg.pte.api.module.CustomStatefulModule interface. It defines the methods:

  • prepare(....)

  • start(...)

  • stop(...)

All the methods sends in the CustomModuleContext as a parameter.

When the prepare(...) method is called, you can set up anything that is necessary fro the simulator.

The start(...) method is called when the Start button in the GUI for the simulator is clicked.

The stop(...) method is called when the Stop button in the GUI for the simulator is clicked.

Virtual Communication Service Example

An example of a Virtual communication service is provided in the Middleware_Home/ocsg_pds_5.1/example/pte_vcs directory.

Client Module Example

An example of a client module is provided in the Middleware_Home/ocsg_pds_5.1/example/pte_module directory.

Simulator Module Example

An example of a simulator module is provided in the Middleware_Home/ocsg_pds_5.1/example/pte_module directory.

Stateless and Stateful Modules

A stateless module implements the oracle.ocsg.pte.api.module.CustomStatelessModule interface. This interface defines the methods prepare(...) and execute(...).

A stateful module implements the oracle.ocsg.pte.api.module.CustomStatefulModule interface. This interface defines the methods prepare(...), start(...), and stop(....

All these methods provide a oracle.ocsg.pte.api.module.CustomModuleContext as a parameter.

Presenting Results

You present results in the Platform Test Environment GUI by implementing the oracle.ocsg.pte.api.module.CustomResultsProvider<T> interface.

The results are presented in a table with columns and rows. Specify the name, or title, of each column by returning the names when java.lang.String[] getResultsColumns() is called.

When java.lang.Object getResultsContent(int column, T object) is called, return the value of the object in the column with index column. The index is the same as the position in the results from java.lang.String[] getResultsColumns().

The method java.util.Map<java.lang.String,java.lang.Object> getResultsDetails(T object) can be used to return additional result data than returned by getResultsContent(...). Return null if there are no additional details.

When java.util.List<T> getResultsObjects() is called, you return a list of objects to be presented. Each object is presented in its' own row.

When void clearResults() is called, clear all result objects.

Presenting Statistics

You present statistics in the Platform Test Environment GUI by implementing the oracle.ocsg.pte.api.module.CustomStatisticsProvider interface.

You clear the statistics when void clearStatistics() is called.

You return the statistics as a java.util.Map<java.lang.String,java.lang.String> when getStatistics() is called. Each key in the map represents a specific statistics counter and the value is the value of the statistic counter.

Interacting With the Network Simulator Map

The simulator module and the Virtual Communication Service can be used to interact with the network simulator map and elements in the map.

The oracle.ocsg.pte.api.network.Network interface is used for interacting with the network simulator map.

Use oracle.ocsg.pte.api.network.factory.NetworkFactory to get a handle to the network simulator map:

oracle.ocsg.pte.api.network network = NetworkFactory.getInstance().getNetwork();

Define a new network element by defining a class that extends the abstract class oracle.ocsg.pte.api.network.element.AbstractNetworkElement.

Create the network element using a class that implements the oracle.ocsg.pte.api.network.factory.NetworkElementFactory<T extends NetworkElement> interface. For example:

public class ExampleTruckFactory implements NetworkElementFactory<ExampleTruck>

Register the network element with the network simulator map:

NetworkFactory.getInstance().register(ExampleTruck.class, new ExampleTruckFactory());

Define the message that can be sent to and from a network element by defining a class that extends the abstract class oracle.ocsg.pte.api.network.message.AbstractNetworkMessage. Register the message, For example:

NetworkFactory.getInstance().register(ExampleMessage.class, new ExampleMessageFactory());

There are a set of classes that describes messages that already defined. The classes are defined in the package oracle.ocsg.pte.api.network.message. The messages include SMS, MMS, and MLP update messages.

To send a message to the network use sendMessage(NetworkSource source, NetworkMessage message) in the oracle.ocsg.pte.api.network.Network interface. For example:

final ExampleMessage msg = new ExampleMessage(null, address, data);

NetworkFactory.getInstance().getNetwork().sendMessage(this, msg);

The network element class receives a call to public boolean processMessage(NetworkMessage message defined in the oracle.ocsg.pte.api.network.element.NetworkElement interface. For example:

public boolean processMessage(NetworkMessage message) throws Exception {
    if(message instanceof SmsMessage) {
      final SmsMessage sms = (SmsMessage) message;
      if(AbstractNetworkMessage.isAddressesMatching(sms.getDestinationAddress(), getAddress())) {
        storeIncomingMessage(message);
        return true;
      }
    }
    return false;
  }

When the message is processed, the type of the message is checked and there is a check to see if the message is addressed to the network element by comparing the destination address in the message with the address of the element.

If you move around a network element on the map, the coordinates for it is updated. Use the methods public double getLatitude() and public double getLongitude() defined by the NetworkElement interface to get the location of the element.

PKtttPK DOEBPS/pds_smpp.htm Using the SMPP API

7 Using the SMPP API

This chapter provides an overview of the Oracle Communications Services Gatekeeper (Services Gatekeeper) Short Messaging Peer to Peer Protocol (SMPP) API Java interface. It also contains some guidance on how to develop a custom SMPP plug-in using the Services Gatekeeper Platform Development Studio and the SMPP APIs.

SMPP Overview

The Services Gatekeeper SMPP implementation depends on a core module, the SMPP Service, which provides connectivity services for SMPP plug-ins. The SMPP API defines the interfaces between the plug-ins and the SMPP Service.

Using this API, platform developers can create SMPP plug-ins without having to manage the low-level tasks of connecting from Services Gatekeeper to applications and to SMSCs.

Figure 7-1 illustrates the basic Services Gatekeeper SMPP architecture.

Figure 7-1 SMPP Architecture

Description of Figure 7-1 follows

SMPP Service Interfaces

The SMPP Service performs connection services on behalf of the standard SMPP plug-ins – Native SMPP and ParlayX 2.1 SMPP – as well as any custom SMPP plug-ins.

The SMPP Service handles the following tasks:

  • Receives SMPP data from the socket.

  • Constructs the SMPP protocol data unit (PDU).

  • Associates the current PDU with the correct application instance.

  • Invokes the plug-in.

  • Manages connections between Services Gatekeeper and applications.

  • Manages connections between Services Gatekeeper and Short Message Service Centers (SMSCs).

See the oracle.ocsg.protocol.smpp.service package in the Services Gatekeeper Java API Reference for documentation of the SMPP Services interfaces.

The SMPPServiceNorth interface processes requests received from an application-facing plug-in and sends them to the application.

The SMPPServiceSouth interface processes requests received from a network-facing plug-in and sends them to the SMSC.

The SMPP Service is a standard Services Gatekeeper WebLogic Server (WLS) service. You can access its Operations, Administration, and Maintenance (OAM) functions from the Administration console as SMPPService under Container Services.

Figure 7-2 shows the SMPP service menu in the Administration Console.

Figure 7-2 SMPP Service in the Administration Console

Description of Figure 7-2 follows

SMPPPluginSouth

The SMPPluginSouth interface processes network-triggered operations received from SMPPServiceSouth and sends them to SMPPServiceNorth. You would extend and implement this interface to add a new network-facing SMPP protocol.

SMPPPluginNorth

The SMPPluginNorth interface processes requests received from SMPPServiceNorth and sends them to SMPPServiceSouth. You would extend and implement this interface to add a new application-facing SMPP protocol.

Additional Information You will Need

In addition to the information in this chapter, developers should consult the following documents for information on how to build an SMPP plug-in:

  • Services Gatekeeper Java API Reference

    Of special interest are the following packages, which include the interfaces and classes for the SMPP service and plug-ins:

    • oracle.ocsg.protocol.smpp.service

    • oracle.ocsg.protocol.smpp.plugin

    • oracle.ocsg.protocol.smpp.event

    • oracle.ocsg.protocol.smpp.common

    • oracle.ocsg.protocol.common

    In addition, you will need resources from various generic packages such as:

    • com.bea.wlcp.wlng.api.edr

    • com.bea.wlcp.wlng.api.management

    • com.bea.wlcp.wlng.api.plugin

  • Services Gatekeeper Platform Development Studio Developer's Guide

    This guide explains how to use the Platform Development Studio to create a communication service or plug-in. See the following topics:

    • Understanding communication services

    • Using the Eclipse wizard

    • Description of a generated project

  • Services Gatekeeper Communication Service Guide

    See the Native SMPP chapter. This chapter provides an overview of the Services Gatekeeper Native SMPP communication service, which uses the SMPP Service. This chapter includes general information about how the SMPP Service handles connectivity and documents the configurable attributes and operations of the SMPP Service.

Procedure for Creating a Custom SMPP Plug-in

The most common task is to add a custom network-facing SMPP plug-in using the south interfaces. It is also possible to create a custom application-facing SMPP module using the north interfaces. The following procedures cover both scenarios.

The basic steps for creating a custom SMPP plug-in are as follows:

  1. Using the Services Gatekeeper SCE PDS Eclipse wizard, generate a customized network plug-in for the SMPP communication service.

    You can also use this wizard to create a custom interceptor, if necessary.

    See the description of a generated project in Platform Development Studio Developer's Guide.

  2. Create the service type for the customized plug-in by extending the ServiceType class.

    When the plug-in registers itself, an object of this type is passed to the Plug-in Manager.

  3. Implement the ManagedPluginService interface.

    This class activates, deactivates and initializes the plug-in service. It implements the PluginService, PluginServiceLifecycle and PluginInstanceFactory interfaces.

    See the discussions of communication services and generated projects in Services Gatekeeper Platform Development Studio Developer's Guide.

  4. Implement the ManagedPluginInstance interface.

    This class activates a plug-in instance that has been created with the Plug-in Manager, after which the plug-in should register its MBeans and prepare to accept traffic. The plug-in service that activates this plug-in instance must be in the ACTIVE (ADMIN) or ACTIVE (RUNNING) state when the activate method is called.

    This class also initializes and deactivates the plug-in instance, determines whether the plug-in instance is capable of servicing the current request, and sets up the session information cache.

    See the discussion of communication services in Services Gatekeeper Platform Development Studio Developer's Guide.

  5. Extend and implement the SMPPPluginMBean interface and register the MBean using the SMPP API.

  6. If you are implementing a network-facing SMPP module, extend and implement the SMPPPluginSouth interface to process network-triggered events received from SMPPServiceSouth. See the oracle.ocsg.protocol.smpp.plugin package in Services Gatekeeper Java API Reference for the list of methods in this interface. See also Using the SMPP APIs.

  7. Send the processed requests and responses to the application using the SMPPServiceNorth interface.

  8. If you are implementing an application-facing SMPP module, extend and implement the SMPPPluginNorth interface to process application-initiated events received from SMPPServiceNorth. See the oracle.ocsg.protocol.smpp.plugin package in Services Gatekeeper Java API Reference for the list of methods in this interface. See also Using the SMPP APIs.

  9. Send the processed requests and responses to the SMSC using the SMPPServiceSouth interface.

  10. Maintain a session information class to cache session values such as client and server connection IDs, source and destination addresses, whether a delivery notification is required, and so on.

  11. Create CDRs and EDRs to trace the message flow, if necessary.

    See the discussion of annotations, EDRs, alarms, and CDRs in Services Gatekeeper Platform Development Studio Developer's Guide.

  12. Build the plug-in project and create EAR package, which will be deployed to Services Gatekeeper.

    Make sure that the smpp_api.jar is in the build class path; for example:

    <path path="${target.dir}/protocol/modules/smpp_api/oracle.ocsg.protocol.smpp_api_5.1.0.0.jar"/>

  13. Use the Platform Test Environment (PTE) to test and debug the plug-in.

    See Services Gatekeeper Platform Test Environment Guide.

Configuration Settings Affecting SMPP Connections

The System Administrator can configure several attributes that control how the SMPP Service manages connections.

The System Administrator can also set some parameters on how the SMPP Service behaves on a per application basis, such as whether certain operations are allowed after sending a short message or whether network-triggered notification is enabled. These parameters are set using the addApplicationSpecificSettings operation.

These settings can affect how requests and responses should be processed before they are sent. The SMPP Service API provides methods for querying some of these settings. See "SMPPService" for more information.

For a complete list of the SMPP Service attributes and operations, see the reference material for the SMPP server service in the Native SMPP chapter in Services Gatekeeper Communication Service Guide.

About the SMPP Interfaces

The packages for developing an SMPP plug-in are:

oracle.ocsg.protocol.common

The oracle.ocsg.protocol.common package includes the ProtocolServiceProxyFactory interface, which is derived from the AbstractProtocolService class. This is the base class for the getProtocolServiceNorth and getProtocolServiceSouth methods.

The SMPP plug-in implementations use the getProtocolServiceNorth method to get a reference to the interface used to send PDUs to applications on server connections and the getProtocolServiceSouth method to get a reference to the interface used to send PDUs to SMSCs on client connections.

This package also includes the ProtocolServiceNorth and ProtocolServiceSouth interfaces from which the SMPPServiceNorth and SMPPServiceSouth interfaces are derived.

oracle.ocsg.protocol.smpp.service

The oracle.ocsg.protocol.smpp.service package includes the interfaces for the SMPP Service:

SMPPService

This interface provides methods for generic SMPP Service tasks. These include checking whether available or active client connections exist for a plug-in instance, registering the SMPP work manager, and registering the plug-in MBean object, which exposes configurable attributes and operations to the SMPP Service.

It provides methods for querying the following SMPP Service configuration settings:

  • ConnectionBasedRouting: an attribute in the SMPP service

  • LooseBinding: an attribute in the SMPP service

  • notificationEnabled: an application-specific setting in the SMPP Service

  • subsequentOperationsAllowed: an application-specific setting in the SMPP Service

For details about these settings, see s the reference material for the SMPP server service in the Native SMPP chapter in Communication Service Guide.

SMPPServiceNorth

The SMPPServiceNorth interface maintains a server connection pool that provides connections between Services Gatekeeper and applications. Services Gatekeeper is a server in this relationship.

When the application sends a successful BIND request to Services Gatekeeper, the plug-in obtains a server connection from the server connection pool and uses the implementation of the SMPPServiceNorth interface to send messages to the application.

The server connection:

  • Receives messages from the application.

  • Invokes the SMPPPluginNorth interface through a proxy.

  • Sends messages to the application.

  • Manages SMPP timers and windowing toward the application.

  • Stores transaction mapping information in cache.

This interface provides the following methods to send northbound requests and responses submitted by the plug-in: cancelSmResponse, dataSm, dataSmResponse, deliverSm, querySmResponse, replaceSmResponse, submitSmMultiResponse, submitSmResponse.

SMPPServiceSouth

The SMPPServiceSouth interface maintains a client connection pool that provides connections between Services Gatekeeper and Short Message Service Centers (SMSCs). Services Gatekeeper is a client in this relationship.

The service processes BIND and UNBIND requests from the plug-in and obtains client connections on which to perform SMPP operations toward the SMSC.

The client connection:

  • Receives messages from the SMSC.

  • Invokes the SMPPPluginSouth interface through a proxy.

  • Sends messages to the SMSC.

  • Manages SMPP timers and windowing toward the SMSC.

  • Stores transaction mapping information in cache.

This interface provides the following methods to send southbound requests and responses submitted by the plug-in: bind, cancelSm, dataSm, dataSmResponse, deliverSmResponse, querySm, replaceSm, submitSm, submitSmMulti, unbind.

oracle.ocsg.protocol.smpp.plugin

The oracle.ocsg.protocol.smpp.plug-in package defines the interfaces between the SMPP service and the SMPP plug-ins:

The plug-in developer extends and implements these interfaces for a custom plug-in.

SMPPPluginNorth

A plug-in extends and implements the SMPPluginNorth interface to process the following supported application-initiated operations:

  • BIND

  • CANCEL_SM

  • DATA_SM

  • DATA_SM_RESPONSE

  • DELIVER_SM_RESPONSE

  • QUERY_SM

  • REPLACE_SM

  • SUBMIT_SM

  • SUBMIT_SM_MULTI

The SMPPPluginNorth implementation uses the SMPPServiceSouth interface to send these operations to the SMSC.

SMPPPluginSouth

The plug-in extends and implements the SMPPluginSouth interface to process supported network-triggered operations, such as:

  • CANCEL_SM_RESPONSE

  • DATA_SM

  • DATA_SM_RESPONSE

  • DELIVER_SM

  • QUERY_SM_RESPONSE

  • REPLACE_SM_RESPONSE

  • SUBMIT_SM_MULTI_RESPONSE

  • SUBMIT_SM_RESPONSE

  • UNBIND

The SMPPPluginSouth implementation uses the SMPPServiceNorth interface to send these operations to the application.

SMPPPluginMBean

This interface defines the network-facing connection attributes of the plug-in. A custom plug-in extends and implements this interface to provide the facilities to manage and query the plug-in.

The SMPPPluginNorth and SMPPPluginSouth implementations use this interface to query values in the plug-in while processing requests and responses.

oracle.ocsg.protocol.smpp.common

This package provides the SMPPException class.

oracle.ocsg.protocol.smpp.event

This package provides classes for SMPP events.

Using the SMPP APIs

The basic procedure for processing and sending an incoming request or response through the SMPP Service is as follows:

  1. Get the SMPPService object.

  2. Process the fields in the incoming request or response.

    Depending on the particular request or response typical processing may involve setting various fields in the request or response. For a response, you may need to process event data from the original request.

    It may be necessary to query some SMPP Service configuration settings using the SMPPService methods. See "SMPPService" for more information.

  3. Get the SMPPService object's protocol interface for sending data.

    For sending data to the SMSC, you need the interface for SMPPServiceSouth to get a client-side connection. For sending data to the application, you need the interface for SMPPServiceNorth to get a server-side connection.

  4. Send the request or response using the methods provided by the SMPPServiceNorth or SMPPServiceSouth.

The following sections illustrate how the SMPP Server APIs and settings are used in processing some requests and responses. They focus on sample tasks involving the SMPP API. Logging, exception handling, session information management, alarm creation, and other tasks not using the SMPP APIs are not considered.

These are among the tasks performed in custom SMPPPluginNorth and SMPPPluginSouth implementations.

Processing a BIND Request from an Application

When the plug-in receives a BIND request from an application, the SMPPPluginNorth class processes the request and sends it to the SMSC.

The SMPPPluginNorth bind method:

  1. Gets the plug-in instance id and sets it in the request.

  2. Gets the SMPP Service object.

  3. Gets the service object's protocol interface for sending data on a client connection.

  4. Sends the request using the SMPPServiceSouth's bind method.

For example:

public BindResponse bind(Bind request) {
    BindResponse bindResp = null;

    // Set the plug-in instance id
    request.setPluginInstanceId(plugin.getPluginInstanceId());

    // Get the SMPP service object
    SMPPService smppService = plugin.getSMPPService();
    
    // Get the interface for sending data on a client-side connection
    SMPPServiceSouth serviceSouth = smppService.getProtocolServiceSouth(SMPPServiceSouth.class);
    // Send the request
      bindResp = serviceSouth.bind(request);

      return bindResp;
}

Processing a SUBMIT_SM Request from an Application

When a plug-in receives a SUBMIT_SM request from an application, the SMPPPluginNorth class processes the request and sends it to the SMSC.

The SMPPPluginNorth submitSm method:

  1. Gets the plug-in instance and application instance IDs and sets them in the request.

  2. Queries the SMPP Service's application-specific notificationEnabled setting and sets the registeredDelivery field in the request accordingly.

    if (request.getRegisteredDelivery() != 0 && !plugin.isNotificationAllowed(aigId)) {
          request.setRegisteredDelivery(0);
    }
    
  3. Gets the SMPP Service object.

    SMPPService smppService = plugin.getSMPPService();
    
  4. Gets the service object's protocol interface for sending data on a client connection.

    SMPPServiceSouth serviceSouth = smppService.getProtocolServiceSouth(SMPPServiceSouth.class)
    
  5. Process any extra parameters (xparams) in the request.

  6. Sends the request using the SMPPServiceSouth's submitSm method.

    serviceSouth.submitSm(request);
    

Processing a SUBMIT_SM Response from the SMSC

When a plug-in receives a SUBMIT_SM_RESPONSE from the SMSC, the SMPPPluginSouth class processes the response and sends it to the application.

The SMPPPluginSouth submitSmResponse method:

  1. Gets the SMPP Service object.

    SMPPService smppService = plugin.getSMPPService();
    
  2. Gets the plug-in message ID and sets it in the response.

  3. Gets and processes the request event data from the original request to which this is the response.

  4. Queries the SMPP Service and application-specific settings to determine whether a delivery receipt will be provided. For example, the following example checks the notificationEnabled and isSubsequentOperationsAllowed application-specific settings and the ConnectionBasedRouting SMPP Service attribute.

    boolean needDR = plugin.isNotificationAllowed(aigId) && originalRequest.getRegisteredDelivery() != 0 &&
            !plugin.isConnectionBasedRoutingEnabled();
          if (plugin.isSubsequentOperationsAllowed(aigId) || needDR) {
              // Set the session information accordingly . . . 
    }
    
  5. Gets the SMPP Service object's interface for sending data on a server-side connection.

    SMPPServiceNorth serviceNorth = smppService.getProtocolServiceNorth(SMPPServiceNorth.class);
    
  6. Sends the response on that connection using SMPPService North's submitSmResponse method.

    serviceNorth.submitSmResponse(response);
    

Processing a DELIVER_SM Request from the SMSC

A DELIVER_SM request from the SMSC can be a simple SMS message from the network, or it can be the SMSC sending a delivery receipt for a previously submitted SUBMIT_SM request.

When a plug-in receives a DELIVER_SM request from the SMSC, the SMPPPluginSouth deliverSm method first examines the isDeliveryReceipt field in the request to determine whether the request is for a delivery receipt or a network-triggered SMS message. For example:

public void deliverSm(final DeliverSm request)  {
    request.setPluginInstanceId(plugin.getPluginInstanceId());
    final boolean isDeliverReceipt = request.isDeliverReceipt();
 
    if (isDeliverReceipt) {
      deliverSmForDeliveryReceipt(request);
    } else {
      deliverSmForMO(request);
    }
  }

If the DELIVER_SM request is not for a delivery receipt, the processing is simple. The SMPPPluginSouth's method for processing the request:

  1. Gets the SMPP Service object.

  2. Gets the SMPP Service object's interface for sending data on a server-side connection.

    SMPPServiceNorth serviceNorth = smppService.getProtocolServiceNorth(SMPPServiceNorth.class);
    
  3. Sends the request using the SMPPServiceNorth's deliverSm method.

    serviceNorth.deliverSm(request)
    

If the request requires a delivery receipt, the SMPPPluginSouth method for processing the request performs some additional tasks before sending the request:

  1. Gets and sets the receipted message ID in the request.

    String msgId = createPluginMessageId(request.getReceiptedMessageId());
    request.setReceiptedMessageId(msgId);
    
  2. Using the plug-in's implementation of the SMPPPluginMBean, gets the response command status.

    failureCommandStatus = plugin.getManagement().getMySMPPPluginMBean().getDeliverSmRespCommandStatus();
    

    You would implement the getDeliverSmCommandStatus method in your SMPPPluginMBean class to get the outcome of the DELIVER_SM request. The status should indicate whether the application was reached.

  3. Uses the SMPPService isConnectionBasedRouting method to establish whether connection-based routing is enabled in the SMPP Service and processes the request accordingly.

    If connection-based routing is enabled, the operator can send a delivery receipt to a site other than the one through which the original message was submitted. See the discussion of connection-based routing in Services Gatekeeper Communication Service Guide for information about how connection-based routing works in combination with other configuration settings.

  4. Queries any additional relevant configuration settings for the plug-in using the custom management methods implemented by the plug-in in the SMPPPluginMBean and processes accordingly. For example, you may want to query whether to delete SMPP session information after the delivery receipt is received.

  5. Uses the SMPPService isSubsequentOperationsAllowed method to query whether subsequent operations are allowed for the application instance and sets the session information accordingly.

  6. Gets an SMPP Service object.

  7. Gets the SMPPService object's interface for sending data on a server-side connection.

  8. Sends the request using the SMPPServiceNorth's deliverSm method.

Processing a DELIVER_SM Response from an Application

A DELIVER_SM response from an application ca2n be the response for the receipt of an mobile-originated SMS message or of a delivery receipt.

The SMPPPluginNorth deliverSmReponse method gets the original request event associated with the response, determines whether the response if for a delivery receipt, and passes the request as well as the response to the method that will process and send the response.

public void deliverSmResponse(DeliverSmResponse response) {
    DeliverSm originalRequest = (DeliverSm)response.getRequestEvent();
    if (originalRequest != null && !originalRequest.isDeliverReceipt()) {
      deliverSmResponseForMO(response, originalRequest);
    } else {
      deliverSmResponseForDeliveryReceipt(response, originalRequest);
    }
 }

The appropriate deliverSmResponse method processes any information needed from the response and its associated request.

A method that processes a response for a mobile-originated SMS message may need to construct EDR data before sending the response to the SMSC using the SMPPServiceSouth deliverSmResponse method.

PKOL1<2PK DOEBPS/preface.htm Preface

Preface

This document describes the Oracle Communications Services Gatekeeper Platform Development Studio, a framework for creating and testing new extension Communication Services.

Audience

This book is intended for system integrators and field engineers who need to extend the out-of-the-box functionality of Oracle Communications Services Gatekeeper.

Documentation Accessibility

For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc.

Access to Oracle Support

Oracle customers have access to electronic support through My Oracle Support. For information, visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.

Related Documents

For more information, see the following documents in the Oracle Communications Services Gatekeeper set:

  • Oracle Communications Services Gatekeeper Accounts and SLAs Guide

  • Oracle Communications Services Gatekeeper Alarm Handling Guide

  • Oracle Communications Services Gatekeeper Application Developer's Guide

  • Oracle Communications Services Gatekeeper Communication Service Guide

  • Oracle Communications Services Gatekeeper Concepts Guide

  • Oracle Communications Services Gatekeeper Installation Guide

  • Oracle Communications Services Gatekeeper Java API Reference

  • Oracle Communications Services Gatekeeper Licensing Guide

  • Oracle Communications Services Gatekeeper OAM Java API Reference

  • Oracle Communications Services Gatekeeper OAuth Guide

  • Oracle Communications Services Gatekeeper Partner Relationship Management Guide

  • Oracle Communications Services Gatekeeper Platform Test Environment Guide

  • Oracle Communications Services Gatekeeper Release Notes

  • Oracle Communications Services Gatekeeper RESTful Application Developer's Guide

  • Oracle Communications Services Gatekeeper SDK User's Guide

  • Oracle Communications Services Gatekeeper Security Guide

  • Oracle Communications Services Gatekeeper Statement of Compliance

  • Oracle Communications Services Gatekeeper System Administrator's Guide

  • Oracle Communications Services Gatekeeper System Backup and Restore Guide

PK7lPK DOEBPS/img/removeplugin.pngAPNG  IHDRT<sRGBbKGD pHYs  tIME6(otEXtCommentCreated with GIMPWIDATHO#U?ә)BmABˆ5ߍolLLDDٍ&DLS m` P[:;3w| ,`s~O+rMA(duϿzkP&qՏD菆м:BU&ygFQ aZ@0T*1>>뺔J%^b(pBnUvd2gqRayy˲X__grr(ԭfv(E!VhF>'ϣ:jqmUEv O[iZ+++Ȳsssu˲hZB!677춤.1$`ttrL<΍FK4s|JDUUkkkX!'''z"{GBuBiD4BPiEA$qˍex<\Ų,,$IBmx^Y/]_鞰ׯfI&it:3B<?zCio).}G<n,F^Bfir$arzGqh/}Jrj_{o~ˉ0NjH G26$J:ir|7ᝏ>>=zu u޽{m(:$ ì>ׄ : ( (Cп&AU̚Pu֭wU7ndgg_vܻw0!!῎(jggT*R2x8q8dƲX,&IR"QfYV (JR+ q@"ԈqsMvڮ]BBBn߾s__=zhA5h`ҤI3gΌ>z͛v*Ɏ9 c>}-[͛{xxH$G:::;vO>EqH^g 2$77_ִۋ/<ҕH$xBHIIiڴb`)ʻw=zAaÆկ__TP(LLL|u߾}Fٯ*&TGmݺ|[ÿ r۷owׯ駟bqaa%K(ڳg $ٳg38xСC&MJJJZ`_0ק'OCt:LFZ((8j4Bb1x]("YeYABP(tf0BlDnРAfX0ޞaZ `k<2oǎ㸥KN4aÆ4Mr4 qRT  Vi:X ,dfYYS/(([7(Jo=zd2r/w`y F`(/ì Qnnn˖-駟6oޜҨQ'^o߾n|>ŋF1%%ɓ'E{ԩSiΜ9o߾:uj:uf͚֭[$|[%TavqeOOϤ0 xw^ѣG+VB8ɴxb__Ǐ;vl̙ M4M_$I9sppطo322&OlX|}}o߾7f de=ϪWNDgΜyӧ)*jȑZ5kdڵkץKhxu놢(دUVyzz>{lĈ]v3fMJ iѢ{С_~m۶f8 1ctu޼yO>Enݺ3ep,@ohe֭ۺu{Xr|YEQ$IA.\x֭֭[ BT*hh4-| XJ;AQT&2oyyy]v3gZNKK|rPPsss/^h8@dBB͛7ϝ;q\׮]#""?o<$Ϟ=>ŋ@6UVݺuܹsƍ߼y3wܞ={-^X$?~pׯoذh4۷O,GFFu-""K.׭[ 8̙3[nfw޷n ZvmRREQݺu8.111((hϞ=gΜ9y򤯯oFN:{חy Ϟ=Y?~LAѣ/bƍWСCv[hXڵk֡Cs:tH!HMbggסCAu _z/ڃ( H4͹B~~~cǎvZFI&;w~avv6E~xϞ=njsMP(}6aFrppP'OLNN&Iq~~~;wn۶hpرct<Y9998ST*:f̘3g.^8:tĉ.]z! |>W^cƌuVZZړ'Oz2ΝkҤرc b4cǎ]| <O\~=44tW^xutt:tСC}}}^ڬYð°Nj?zȑ^z͝;O>u'|j*___H}vBѦMG*P%]]]zbW0;wqʕ+(x<%TK(P(233bcҖ/_ᑟ3WWW>o,taD$effD"ZFqCqsJJJffѣG׬Y3`ooozh4eggx<{yy!Bt,>| ,Vj5kڴi>}R˲yNsqq'xxxTϟp 6}///aJ%0͚5+00h4N0r㼽%Z4iҪUNڮ] l޼M2 Ӱa={Y_~^^^7ndY$I߂jOºt0̚5kOq\[nʾo~3gθRz갰GGG #2x&Mj5dȐ>ŋ111^|q\.wwwg].{xxn0 (ʂٳgO8q߾}2Z#@5Ǎwu[R6a@4 _ح[#F:l ~qNDz,'ITؚL&R)0`T xEx<ZqR Y5A, aA$hKZbJ|h;@| (01 xF  X kQNq\"F0 ؎\|O-R>_1УT.# AXRK|U iZ,D44M aпeY@h8B4՛ Gz`u+;ARДl 9i]nOAA%3|83 c ,aK~1,\ U-u"-_)[o] ŗZS<'J,-ohU,>B*,3B@/-3ǰL0kBU :'|~M̙3]tuPE`mGd=/&TZ^ڵk/_ skd hxld&̚TIO;vm۾+[ZEy|*#$ %I^`*փ5!..tF$""Yfm0111??a776mtK*:::7A*Yf%o AV/]ԢE֭[, Fڃ*ad;vT*q?=ztN޾} X,h4`K0EVcׯ_?{/)ֺV3 A@uEQvvvZfͬYpqѣ| Oڵc||  E``3EQEJ$7n\z`09޾ T)nA6fW:uѣo߾=zh[bEvvvvv+RիW>̲ʕ+>},bq||ݻO:u1ټql>o=`ք 0 S*s?AD RT(!f<~ &0 # E"˲}ݰaÅ RSS BUk4MI&t<{{{0Z:{tP*EQt:09xNjin=`Y*v Ug`/Z]PP <ð%K,Zh„ 788X,$&&!C 2qべ>`ޭ 5!RxQ|t x㬃B AT]x]v  `ք ʂYl kC̼kJ25! `ք ʂY * fM ,5! `|?EaZP%IQ@5^Qͼl0nOQxxx  Ph0?^bC<I&</??_ KGGGLfXh֭M4XbŦM9x𠽽}pp0qmU.]ڱcGJt 6$Y|/_Y,蠠 Lv۷o#iӦk׮X%$$dĈTڿхŠSb;.]*_W^]lYU6me˖b,]tɒ%>1cFU`RxԬ `****s%@Ǿ}0 .J^۷o͛+Wn޼엃ða* {t}Ĉ PTأG޽{37gς`0|'NAXddd֭w^zQQYo߾M6¨ Yf(k9J  ج`Z ?VZuҥ2e3gTUHATM5o޼yf^sM 蟢(_~:t 1͕\b=://2o޺uk;t_n%[ÇdxNiE5[hq@Au{޽ӧ]ANWXX:o,[PP`2 D"A QF?9T*BPR>[l9i$ b!B.+f;EQ秤ܼyZP: @PzQQY3--t'\ QQQFFF6%--yAAA ,PTyyySNMHHXdF1 ZlٳgÇ vΝڒ$ rG˗Æ Xr% ޽{ӴƎab9~a֭[WPPPގL0СCe.*ʚ1117ooATg8qbϞ=Ç5k>]tizzG/H֭[Ѿ}N:x$[nm߾=>>ۻgϞ2l}ɱ~D"9ríc 5jh~~~1"$$۷owww/(88̙3...W\Yx6nXjX梢Z0A#N\zIIIf911ð.]8::$)(q z0l6FHԱcG;;/y&00P.[?BV3_?~ŋ)))`\|{{{VZ۷/>>"ggg9{ǽ:vX8^7 .qƥK J:t( ۷aX@uh(JRz5o|ѢE-ZhРT* 8^t:^իQF-_<==]R!?9rʕ+gϞrJtttE>~xjj1cPGCݻwCATG-\P.geeyyyM<AAu)%%%%%iooo0nϞ={9xvq7c >߸q_~%''ᅬHIIye Э[7_SRR 8A'8q"<<"wwwV;~-[N<9%%ŋௌqh{8vqj'8-qhk80mllly ~#$$L&AAMZ kBAP(\&AmAT0OQt? j۷7OQ _~YA ꈅ (k4A>ׄ CQ!@5I5EYsM]]lj$PH>P(x`R*z/B! \T46ХK˛9sڵk)wiڧO:f8{m^^^fjU]1 вeK@P q|>ŊO}T\3 hBBBaaY>ljE <⁠q^O?E"ʕ+nnn4M:@{E?{̆@P"^~=cƌ}ժUrĉC yH$ut}EY3::ŋ6 8qPAH$>i#8CQT&r$9h4AT*R#$I̟?_*"T*mCj e4ib0lA`(lpYd M bǎkzz@ utP1L 6۷h~)T իE0k~ o:11I&/^q}͛78RΝ; ,d,A-:tmڴ*sQ-kbY(ըQ&Mٮ`ud:qEQNNNǭ^Z&^(P$Ih4ف#$H$xRT*|Hь9rǎ:t ED4 ;&(J$ Hq\ 8JZl @H$ :p>ܲe.\P梢g}VU!Uw`x@3Fsee]\\<==90AnnnNNN^^^o߾iO?uqqj fիWܛ7oj4+Ja8O42 j*ʚ-xjǏ=Fڵ+ SN]bEnn@ ضmEQ999=zիWAAyXh4Gv0uY;eoA;w<ЦATШ6[(d@E{,˂YHU/Q4]u2bG~fLLLySWM N0zѼy kCk[YkY؀1vvvÆ ҽ{mZ+f!}juyȊfSWM,1n8<'m۶ڵNm`PU(uԨQW7o&b#Fh׮]k~U{`VMz,+VZ5aeGu&YjhhlܸiVX l q}ЂQ@P V5f3+onD4EQa8bqYm֬ɓA[Yۆ8A6?8l]8sttlժ } ejAUoڵoK/*ʑլ EQXz]3҆XC(JPT &z(j43f7ijuCdJJkL t:BC {PSL !bт'''Zoߞ9sٳ5T*`$J@ *}$"W(lڴ L~Obq-.aFQE"QFFѣG|H$J(;v,???669555::8nggg=7nxŋSSS@۔={lذ!;;;::رc2l La˲]Tq'R) ^xO;;?y߾},ٳEQBqIqqq_vrrT*={6k֬YfKD`h@P(F={qttH$,d2Pyfh |Ba-r ȶʚ":(D"=wT*̌>|x\\ܤIh>v옓SΝAqwD:uo7mrw|;;Xh4Quvv3fP(T(III#F5jZvZnnn-,Y2lذ'OA^z۶m[3gy…XTt҉'?~|ر<͛~mVVV /By֭[GGGwAAAVܹsvvE-Z$Ν;g0:1a L6˗7^r?;}p۷ooڴ͛7ϟ={ET*I2?ڵkWxxFYx1qgϞ8O>j:<<<==ԩSӧOصk=C}e2YBBݻAرc>}/$%%=~V;vɓE"ѫWF_cvҥϟw}ڵM4sθqPݵkWvvYb1w?bV]lYXXɓ''Lo߾ n\]]׮]ۦM3f|7on֬bXlA4MoD"ҥKmr hrPÇ;wnܸq;wYr۷oW\).\0a„d-Z㸫X,(*00pIIIj{tpppqq_͛jT*rʮ]|||RۿӧOT*+Wǟ~xF֮]ܽ{b{߾}=rww;w.A-[|ѣG}||֬Y&D&MpP(`A$P(;xӧOMF4Eϟ=z46ILL|I$xkcQ1p |'׮]xfСرc҂mֻw襤 L{njj޽{-˰a$ȑ#y7oz;,{6i$%%eܸq&_~Æ _~HHcϞ=}||<|r$-ZHKK 8}9 $vޝ9p{~7?ԩSe2 & ufdM$/_4qć;V$?Aǁ}FFFVV0, Hh2dȗ_~)SRRZ-0h4}{.0 lt6x& 5gΜ>ٳYYY@ }b8qN0Lpppƍ@a lyHW\h4_}UxxӧOBV-KW0 Im۶5kVzd2ٻw@ t:]VV^h4:4{dd)S0 STiZFQݻwZVT"U4arH$;w<{l~ݻg2{6lثW^zUPPN4bPVy$qo88n0_}||@lBFx/Əùs~5oޜ4 W5l2@CDj_ݾ}f͚ B̧pҤI8+> wb4wڵGݺuC=H$Yfȑ ,ppppssr_|1dȐnݺۻEjZmAAx䎎 z^w ,ݻw&ŋ;v숊rtt,{R={v^^͛PxΝ3f9sxt:8jCpfX,e/Pt:ˋeY"@3e=<<{"B4MJͭGe .tȑ# 0 srrSi|oooP_?(F;!4 @ t:\###.\^G5* 1ր;`pAQl O lwZ\T*AYU(#l(*O~TyfPM`k [,`FO%؁( )6-bW 4MzpMRޔX P6spp OAU0OQ֬&ӌTĭ5cIc,uV7ZiXUT;&XJw+F_<(vZAHv/~ +c,Zϗgvf]l6ϛ7\Qg%f]EV1eقkM)W)a0c\ 0[ 蟺t钻oEEѣM]]pgٔj?^3ն9\əe.**kV0uuÏ$YC00 #`|a@ *c-*ʚÇ`Jܹ:㱁^"A$ɄnݺUu+А'99~Nm?j.%HrʨQjhTMT y楤9 w/^صkWDDDueـ͛jFRyfkÆ 5(bɓ'߿?cƌ0`YK.mڴ)1mAEEEj믿.(kΛ7m۶UX(رc@@mð""11֭[ƍ>\L&0зgȐ!Á>H8T*٨)W˗R{#@ ۪n H=4MVzr4ѣՀE1 SwQWيD"ÊV5}||( ZaJn߾Z!AAP5U5.^ ***]v` 5R999aaaf{LBAuF)o^}fsyA@AuGeMX\EѧOd2Pl2bcc[nxOD:`7Azت;88xxx^TԆҥKϟ?¨l 7oK$… Ν۽{X,.Q=aVMHHul;udXlA]\\Ǐ\TT| U-cǎ۷ÇٳO>w4hPLLq/]7oެ[ƍ̚uH$zkJ: AP4{eI&UI0d4ƌhx<СC_ުU+јY* B^_&lZCk2@'%[GATY?6 t8O>XUTg"0 VlҴi:^T5###[nݽ{* (JQEQ((`3 cǎ4٫W/* #TJdf-* zdggkZAA\Q֜2eÇm ,aP(hljD"'a-JE5ETy`J?l6';vONNҥKA3 )ZgfUUHT 'O̘1QF,nٲ;vܹs-Z0 ѧOMnF[:zA%k+q(d2\.jazբE أ jE0k <Rd2Lf0 LuX,"q@h40ǵZm>}Y`A?S8b-JEYa~@QT$?zd2ߟuiʔ)q(1bNzu`` EQÇ djذa߾}9 ȢErrr.\Hkmڴ)s؟IaQqGw}SPP ȹsd|>AUeY>8tPJ\\ dMTzΝϟzɪU|||f-w7ߔ7OQ֌DURuGQTvcs4 IDAT7o~д]v+W,,,uhPKt陞^>|ѣU* &ĉEY, .0 CQR(ʦC*(k:;;WI05q:n˖-ڵM4qqqEOX,dǎ_5 ROPfA8!B4q`EqAP͕&JJeEEUȨ¨;Je۶m\b,hM z׮]'Nk}`qh4E4ml"A5o޼Y梢ɓ'[nQUQ}8xF#Ig_6E/᷺j$yŤ$X}~AHLNNfY6++k̙߿\.iֱ W^:uJT3L&Ǐ7{{jrd2YϞ=ׯ{+5&OOO9x3P }G-ebf67lЭ[7ww:H$7oi۶myYU=\\\sڌw\XfXM2X,~ի `4mG1fVݻjrPcLg/~5tFlٲzf͚Ta`87oyfAjA 0^ѣjg+6 >|HQT̀5k3XT!w߽'k6kݽ WPiZR,[ `ptʆPtEW0 05*N +l6þՍL&{5^A.8 Pou#8W,KQ .eYE4_(cY0JPqi>F!X 4M5x:[F7dz7"p*8A0 FnA ,Ap, &vzR"׼~|{(kt:  AFFEQ$IbAQT $Ik9 Q7 ðA BFcoo, H|>#"i"b1hBEIaacXgeYA!&33Jr$Idz-  ʱ^6;fiBR7czCB>r\"Q#K(I$J%JB!MH$IӴ5ּq;0J"\...Z?l6m6fdGJA C_8a...fSꦢ9iҤц8Ι3'++1::$Ii0^~ :8n0RSS/_'''_~]TX3998PHɓ{ݡC0T*MMM6mZrroӦϟ03 ߱c%K899t: XMKKsrrq&ʳ[`?sDDD֭oܸ5m4ww/^tڵe˖]v?rȝ;wիGQTzz:vvv۳gO###>SX F 6l;wU=z90wqqaY$I;;;ٌ㸛I O>mذ!qZ633S*3 #Hn޼9eʔ#2pѣGO[oJիWxx83^3bի֭ۿ+L&S6mlrFeee͙3'44499͛A''',wߝ;wnǎ?vtt1 o޼qvv&B!0.\ DDD?||'ԩÇv>$I__/^hN:ݻwƍYYY`, Էo_$899͝;_~}ي+իg0233BL&w?R}t\Jȑ#, ҥ˕+WƎp¤-Z?K.Ć}@&ՔGr @}tRFFFAARvիWqxǏ;Q#/^J} ={6aDzD׮]=<<=pt:ߎ;JJJlٲiӦ0Za@Z-p`h42Lh 7mtr1q߽{K "СCǰaî^*jmmm`

|8Xi?$Ill'nܸAa6*PX#oϯ`7|NPX,O%xG '6JQ(7o~WLu]h֭.]zO8ݕŁM\WÈX,>uӧ}t֭o...6mp/j666-ZPM6=3'EU*D"6m'O,H]]]Νk0rBPJ"sժUZw^fP(LOO?x L HIIŋt: &hZ ,6> ,99ڳgOfڶmxbyyy߾}?6 B)**:}ë֭[AAT*uwwOHHro޼M.]|}}5k )mLfmlld2Y@@@hh(Lr{ }ddNstt?c H$Ro^<<[ zq.-J) '\tteFkHtџ~iժUU"H<Bdgg'%%͚5cǎ%%%fm۶($ Եk׸NrrF,3L( +HpWT/Á=2RTRa!L 8BjtD"h4ШH$҅ ,Y" 5k6bHFಲ2) (r8_vmӦM$$|>L&)++6,,lٲeV(֬Ysܹ{Vr!8bӫXVVfzr/&kzU5JաwL_N8 EQhlc0ڵk$JК|!e`{kٲ%6~ӳL.U_WeU=Zu1Yib77$3e:E5V{/?vHѦ* ԩSKKK lLڟJI,kT* RTfiZ{{{XLFKiSӗSNl-c@QT"@lt\.7((6A=qSTjM3|KE W@d1,;:[6Z BZͯޚ0X[1屳7hg D˗}}PܼysS} UXXx&1c|B0 цa` ݵkלe2@R&ɬgg@<(iiq*_p8yyy;v?~M * JE㏟F$IPdeeosQ 绋Vvzԩ4KR L~5B[KKT8"hZlikkjiYpBvmmgkk۲eFhOxMZmggwTӧO8p`ld3=R4..,:T8dA jB&oP]fMAA  ɻX%?pqq/?,-Z C>PA{'g~`RA2Lfm߲( JMNNh4cƌt% Q֬Ex);,( Z˓h^d`P*k֬if{UjG@@@А9@ bs}VgT2CχOAQ?FP_Ԛ{(q0.`0 \rW*-d# @ח:tڵ!aZ#0RɩRkh4(!I@@@`0\.L&dPhkk 0--UއP NhFVh4$W/^\!¸O@@@@@P[I@@@@@شiӕ+W=TiU(D AcRXk-yA]b&O֜7oM]D@@@`yTD5I&z=azL]k:Tiwuuy,Y}XOit:fƌ=99X4aׯ__p͛.\d0'O@ tRkR:*tݻw|ryy'Ory=nݺ}vռysk+JPgܼyֶZ_P*a4 ł 9p@qqqrrrϞ= o߾aÆFK5%J+9ALGŋ-0`0⒒N:)64Ya05_+Q>h4 tV ;L&):NP)z^ѐH$&i5zBa4q7jEQ&ifw`0r8EQJE!g=9}*b1 L&+JA Lr\S( b] ) Ba8.F̜YI$NSTjM;؀Jh4=T* B)P IDATl Jd2`9E՚u6 ~lUhje ~52l00 iZ"5r`0PT (L&mP(Tk>|X׿Ç6 AI&5kѣGSN5sgϞE9s愇w%77wԩfrmk.99ð jժ_~/_5j`TF]^^>z7ot]FF͖-[bq||Yn޼I&I$H$N+//xNuܹsz}rr͛7k D<ѣG-ZDPN>m-YΝ;6mZd ڰa3g޽ӧO/_>|[[}OfN?~߾}w͜9̙3fN3fL&>}1cZju֭D3#!!AZa7oH$ӦMS(yyy5bl󳲲RRRu:W@QT&$$_j*GGܹs^(|J5k֬3fD+W$'')S 8`v=Lu cڵ JF2c$/233 ѣ_zU)7oFQ_~Cdԩ=zYYY"Zرcy_ Ƀk A]v,<k֬UVaּyshmFgϞڵ3s8Rtqq j:sΦ'Y-JR(`0(vډD"3+J5p@Xhb„ fNR*d2ypww7J&M`Qү_?PT*mmm͟T*F6EJFQ*zSd2FS(=zPThH$R9HxP(J///>lRPںYfP...GxӦM3s-X3 _},QS-&ILˤoF,͔RV%njӻwo3ijϊ+|x}:nzId2Y"޽[$62B bQ54ВH}ƍO...W -ӗjjBk ,ݻwOLL 5se22\mrrJ/@EZ_'NRmPUզͧ7"HcC4t;;;/\p:֔d3_w`p5Wg+xPp;E5ͿӇe:S1R:EkkSV]f`aEP;}6ʳ EQU;׬1b;m۶ׯ߾}͛vzq6m0 #A^^^qqq*ٳgsssJ$ˠjmmm) D[jՃnݚd2w" hl̜9޽{AOO:(  OHH|R.y@c4.]j0vZ˳^~}ĉZ7̩6@`EL$nD-n HVZUTTa֭[js"l.-bk Aݻwd2Кjz֬Y5Vy~-g~`0"U*[Zh4_ u=AǏs߾}; wP(ӦM Dd… 0 Gٱc󽼼&NH"VZU.t:}ҥZALVCBB7o|of\.zG,X0lذ޽{#hѢܵk~e/ +Q\"(al̘ZB}ך O` ۧ(7߀t޼yt:=888..n͚5YYYW\1cƍJ睜$IzzzLL̞={>}ӧXt6zhl׮]-]6} 6d=z8޽{+W߿?<<-444--mL&d޽{733gϞQQQ;v숎6ѩT^w#jk=tЃZ?|"C hfҚ4l0 +++{MN굿СCccc& %80׏;:s3gz[[F}gϞ={vΝJf#aѣ[jjz}iiiջt耀AB۷G}Ἴ=zǏ?yyr]vG޾}ӧO!FV&ر>>>DQF VJٺu G.Ϟ=L D")nڴivvvz@1K.dҥm<`STSj1U6j(Q=R êPUS W5I5\-gϞurr6A0B[T/R]xA׿.kU{dD#t'H^Zt@ @Q6::pfܹԐsk4xT/֬YӢEÇr8Y,ցBanOT,4iRAAWD"5kք:995Zc5 >H&qػw dm2̃EDD4BY"D"[ԭaP5zs+G׳lZT*J3V Zhu(bsYxqvyA:ޣjmllT lһwobO@P P TW"Y5F 8\t:--A]CH$:NMuXF#l_㯾*.._KX-[vvvPήvdrAAVU*ɓ' L&5ZV#EQr_|P(=z$1 jzdb H<3i*fvvH$I6* Ɖ'j5$)F{;w9 !v9Ng4z_VV0iSUB{1SFT*:uɓLhzWoT SRR M 777hh4. e $ VjOU& ˓B022yjlzH0m0gРAKb&4[=FQ*@4P8yd¿|3`ۣG@@Иꫯ,(X*9ƌd2%IuI$ԓj5Ǜ8q?ӧOzefS/uzzRk999YPAQr#f1Zv޼yWׯNMt:]CNRCé5CZ6]U aS0 cXT*(@:S G`0p7 8d2s8h4>dC"jjG4㸩t;:*, ?Z\n߾=dȐ3gΨTΝ;ST "e2ٹs缼O:u޽޽{hBIRBoݿwVVVǎ@X,6\.WhZ*d\;x`R S$ǏoժթS|}}CCCRB0Q*ZժU7VTT ^zu3g/}vAlNۺuW_}ji4Z>};vڵׯ_{{{)))h߾}tttFFݻw?~yf{{{DҧO+W7==}Ȑ!.]ڱcСCWZW6k믿~-+V6mIy76X,֡Crrr֯_?._~۷_駟;t萙-HN8a믿5keoom۶ &ڵkȑL&ҥK .Wޓ'Onzƍeee4 1,K./++#]tqvv޲e ÉȈp8ۻwohh޽{ =zm^z{nF3jԨx#d2yӦM~~~GY`ϔ)Sr;Zj㓖3.{1AlC~a }ԩ_xaX@@@```zzzE̚5ի˖-oY,9 H$KJJrww0`ѣ Ç__T 4mt(n۶cǎuss#d5VzQB-[VW^rĉ/_驩III4ʕ+K&MB!Xf͛yfs\{{{ooϟ޽񘘘nݺǏ\͛G6mTQQ㸭[f͚uyQҥK򋏏ϯzʕ]vjGGGPk.HSFn5666wqss˗/wtt_D" ǎ[QQvږ-[ٳ̙3?3Buww#GZhO?=|As禤`8 `E0[[[hG~3 H$jѢ`={}||9aÆLuaEccc;tc[[Geff~fpD"׏=* ae@dul߾NNNK.%H𡻻;`ڵkj]]]۶m{k׮;88%K899]b8p ..޽{vZ`AFFӡޟǖ-[^z%( "a֭ϟwqqbXӧO_fݻ>zjLf FiiT*e^^^֭D/_\|?|}''˗߻woϞ=999;v߯]?zz̐qjUvzJo0h4ڶmܺv횐p#G;vPi߾}ݾ}$))GP "JƎۼySN6ݻ%%%f^ĉ`CوBD ߿u .4F#) Ś1cz=wߕ\v~ʔ)qqqC ޴iS|||XX[]hRoyU*ɓ'-ZԢEN:իum۶߿˗/srr:i$2ckkӢE!Cܽ{D"͙3ѣG=bX:n&0Mxcƌf|~^^޽{8رc ߼y.00h4ٳ֭[w:#_7(4H(ZB[իڵkmmm:pK.;:::000""W^-[<~1c-Z4r~ݸqCR3UVFqONNn߾={ 7o|ϗJRENNNwܡP(UKo~Μ9o޼~رc_~+J>>22իW~P(l6;33G7nHOO ̩SvԩS#FxչsVZj)JxW\ԩSpp޽k׮]v 6K.]thm۶}`xb F۸qȑ#WX_DCo>//~W&MFСCD"2e@ hݼ j~FM|6- ?~K.}ի>"t:֭[߫kOQQ^g2|>q J'Z-0 sttZC*JPd؋2qh4 B+*J'O0'Jq& Jx H$TQQv4 nTC`X V1"88xرU(T*Qr8S(/_2 X,Z*غ.++b$VYVVfggGP4 xB@t) X۱l0i0 "H(ZTTT*l2`:77"ƕNS*|>وbE j[NF L4uѢEͲ[2${iT*X)rWWWV[VVh4%b}A{{oߪj*rZ-d2mll4Bh4l6/^D"4V8tvXt:X†%d2x8zJ lh4T*U0LhAMaSB8::J$DJT*uuuִiӄ7ol߾nlٲOL&Riddm@x,W^g&B'&&{զn޼}}C>Ѩj!T*e0 k0Lh뮮~xF\S8M7M x<1*f-[ƺT;;;Nfa67.u:xÃp5 %Y/`WGDTlx2...2 Qt- a4u:8@eV%Hx# EzP( ΂?(?SRR(ȑ####KKKMtX͘fxd2i4 ">IY@6(> &@$Aj4䟖S}ypG lz_U%j#F@v<"Lڟzi N1 I4IՉe!4 m-,(;@->hвjSwK Xya=ł8W 0<̈@ք]PR:t30H$:nG cƌiHUHvZݷ8L&S3`f($cbU@sFkH=^cFTjԕ|xݱP('O֬-eee ۗKbߞd~ ,(((8puX,BJ(Bjm޼b/00D|r6mԲejTΤh@JU@Q۷cǎ}ٳg!" w\ *+++//t:}Ŋ/_J8G3i*ךͳER}$iժUӦMG@P~y۷ڵ+..ѣǘ1c,F`YXӡʵ?" E:w,sssWH5`hzBԩSjLJ]h̘)P5ʬ0ChIIIffɓ'/]DP,-b4AiiiQQѹs&N鯵Z-cԩ{PLKK;sL]TγgNLL,++R3wTR$цhT(k׮=uTDDʕ+>9 Lڟ}dͺT*{{{ׯfೀaX,~& \jV0d5 A+ HPIS)f=J͙3N:}XbFݸqc׮]ǏOZq:aX8 Ԇ-(JBڎ?~Μ9\.|FH$D"Lv ^L@L3TjMXLL*{ׯ'7lP%/RUk@)ZhݻqFeiEQP(Am0ppPU(...[>p"|,  rҥKL&E$''ݻCZsΜ9+(FDDnzl6G@`m(h.]ԩS'*J,7 vՔRk޻wDj8t:6=}5kP(bI@`m(d2r92 jCiiiMi*&N'2|(*J2dɒs߿=1`4I$bX4h4B6 È@@PY|yMiJa|__߇d2VEg0Ju Fn4yF@P?~Mmd͝;w֭1bF#͆ F͍srrjҤ͛i4Gѷo_Lfi`00 $ --KB"( L\.1cVQEQBFtК Er߶mۮ]A[KEnnn(hSNTϲ@S<|0DBY!H˗\.1Lgɐ&jU۷Yf[~P֔JD`0(qڵˋB e/Fd2Y zBP(L!R ƦM>ٹDjF^?a„+W.Zh̙5sPEQ2<ҧON0h4~W&:R3p}!0]p?`kk[SE]tٳd2Y*/\ݽ1ά'쐐BaYѣGtRkѣNiFF3hРxfUC'AAQw„ ߝ;w"`0MZN_|977W.O<M4aXֶ!HJRTZZ aL&t0j ]hZmc36|Z*Z0(Gp9s̛7oٲe$Xn;F`۷ojjӧOCElmj 6mIIO?F!&zJRRR```DD*?vXJ` s\c>0V\icӧϤILz=]t i֬NJ^^^T*Pw֔Rk&$$FOXZlY\\ &I(͚5kҤ @LWE L&d )/z=2 5fTcA](d_~eEEŜ9sϟH FL&4`ǎ|>ߟBx`JD<:Rk={ӂ40 EddZNMM6mVP  R^^~QD+d29Nzz\h4bfggױcGdY hP(l6ۂ2 d2By<@ h$>*0q}*ݻw!'h4VTTĜ8qbΝ/^ :~ř3g|i DLOOo F#֭c<㢸>>3[f/]ػDX{]PAAPDذ."Xb56bJ|(QYܝrϽ;L&R )?c5#o߾k׮!IRնnz߾}5d2Ww[ 4'c(:vXBQTTTmrL֭[|T"CT9JW^EFF6hЀ`jP5 bI17#IR׷jjÆ 5mxA9x^_CӧVj.]YfTð>},]ӧM6f5u @ t*Yh4Bl[U 讉D" /`MVyߺ|U 7A*][+l*]2|wMe'.\xÉhqqqjj꯿zJ)Ei4RT(z ɄaɄsж | VFM&YRNC_L``2-5K.0P+epSL&`0`h40N3vm ^02a`{4*Ah! 8UmKjߧ"^f5a0|}}###cbbD"JoytӧOG=lذ+WLDd2FcAABP** Z=yd$>|8{l6T*t,d񹹹^d<O"t:&IdQQQaa!5@hѢ$!JLfNNRd0ӧOyǏ;uꔐ`0zT*Ɂ ~ymٲe˖-( `0z}ii) ---33eڴiO>-..S(4h4DǏ_x7nҘ[T*O:' O>o߾vvvݻw1cƦMlS߿oܸPx…ӧ8::n߾}„ ͛7DE?>!!a /"[i2e2D"aXӦM>}zqqqƍ/_٪U7oLlذs5h@&={رcOs=}MeZLFvZVԼy} 4#G888jՊoYɩo߾4`ĈzjԨ7&IBVǎL7͆ɓ't6jRi09x͛7ر BW2GQT.+e˖ٵo~}ٳg޽{={?d2Tjgggggӽ{5jѣG\r͛7~~~EEEo߾D"ADTbK$IٳgϘ1C&d2A:ާO˗xBH$//}ؘodtEEE[nJ ؼy3  jp@Nwޖ-[TZSN=w܄ SXXX럨Ν;s|F IDAT{dh@ &M8::~._\\\m`kksNFK=_&ٳ{d2x۟>}C da4hԩ㸟hٲT*uV&Me2ٳglllZn 9Nƍh4X|֭LArssO|u5J%J0=2dN2eӦM˖-0ob2ﳚD`0[\$ItK]$IZ@ d4uSd2jPy* [FRT* t:Л[>o2JP(T1VVV gNυnT*%^h4#͛2( ^r 0z޽{ug\nhhh\\\=m*שgϞϞ=[rR7U@y$z^0LVER&7f\\ܛ7o= |Bt:Mjj*{Adʔ)FQ$2[_qhFヒ$I2%%%++b-Y-N E]9\%rB޹X%Aӕe* _h!x̵Q=׻jAI-FM?Ȓ%K7o^O(>>رcl7Nstt1cƭ[opE  >(0(*JVZ':u >|R$UQTT7t3f秧XBP1ϣ9dofP Bpœ&M 5>R@$$Ųhd2 7o{ ++v1̥K>|0666&& BF;TOS ԯ_`,^>\x1IK^( bx*ٟ2nP  ۻCvk ./||._$IF}v.[ 0Yfn*{ :{L>}… v(>$ryDDDrr2ׯ?, 'd~5|1_E)<}(,5jӜ9sY򔔔Le˖A>ٷ`;9CCCCCC/^r%ѣ Ae@ڵkE$((%..}?ԣSl62 qHrvQT? `0[hz갰0.KjF;pb ^n:&]F3tАӧ'%%9::twRP1cƼoB׬A@:1>l6DT*e0 .,**1bɓ'Y,V-Lh4H[jըQ??;wڵ ^ WÆ Ws-gP|mll*DY͚I:nȐ!-ZHNN EQ@QTӑ$9k֬{?~ӦM/_p8-a4M&,+''G,_~G %\1ZP(h4F(> 7YM(k&Q$###b-[f$I>oee6MDw`0h46r֭e˖8qڄN֭KOO_vT* ܿ[ڷo1$I2̶m^z\? 7kׯQFjEe$P(׭[W&QLe2YsssmmmǏP(px"j޼y"& nsjQFIRJUkR٭[7 ömۆhTTT֭}}}N斐1+&̘1#,,SN\.RTܹs߷j;"(r!CYbŔ)S\]]?A{sNx1[xzz[{/_>qD{{Ç N:U",Xdɒ7ov޽W^2Z?ʁ2ڵQ("Fرh4B̏$IZbjeF ţFZvG)i8sNGGƍi?ܦM//n%ܶmۜ9s_b8q֭[0r yԩGݷo !!!"vH3>4Llܸ׷Cn*-ZٳFQ`8,Xm6___j^L&9rd~1߀]~h4NI$j"ᄇcvƍgϞ}d2>21&&͛VڼysllU 8t` `(>^رN]rP(ݨhBz}%q( Czȩذa$^~;v`Q?cvvˣZEkȊoUd2Ard2oa]SSL%?eVR(VZ%'':88PV@$j!<'Iqh4qL6 /BV/_?sܸ!Cܽ{T/>^E9::._<22]GA$iZ`0^~-sss9N :N/Nx뤨.F#N_jUJJʜ9sk o իW((At:NgX\.7''֖ Rh4Z~~P(1 PdB.AX,NWT_h4:88,X@0:uhZ&9| tJ@QTh4MΙ3'**.99~*dW^4iC/(ݖ*ð׷o^TVwsjeVs֭[PT` 2ee2Y? Nûp ל63 Hs[n)aÆmv111zݽcǎQQQAAAÇ ݴiF~Vh4ӝju@@N/))W*>,,,l֬Joj[AɓZRyȑ[n%''>$777<M6?D"IOO oYM>o-%T*Fn;@ k׮t:}͚5QQQ+))W?8bAwqPxoDٿDfkk´/;;{Æ III/^(55nݺ 4iҁW^aX\\{iiin &:/_|@lc/ [ Fe˖N7n\DDD{`0E-7 />MZ \NOB'I :U$Ix<^hB\.!J(JQx_O[~Vj¸}u8)6/>x`̘1^^^/_^zuHHHyRlР9sҥX nܸ;fffy󦠠 000))`0*h40R󇮮ݻwwx!k2Μ9uVa7Ih4Ǐ5jTu:X, kڴJ 8,,e˖h4n R9s߿UV$Izxx̚5 d` B.]tҕ+W/_[U;xC6RX,֞={7o~ƍ!CT??0A@5 &,ʕ+,Kф P_q6l6{߾}7ްaC߾}]]]h4R &_z5;;  ÂRVf9s&##A &x{{+ (HRj:tpҥ$IٰǿoSܶm[pp0e5- ޵kא!Cvޝr7m$s!}:rHJ]~Ǐ>}ZR?~ԨQ[l1cӧ߿Ox<͛7b1ɜ4i͛㏟~͛7oޜ2e رczz_BBFU/_[n7ϟ9s{Zj㸝]~~~f_| cPبQ#J6eʔ5mҥ#Gӽ{ح[h8Z@TUj C$F_tH$/..>|`` F{wE߼y3lذ+Vر#44漐8?z_~IJJ"⯿ZhQttFFeeeEW秥={$IHgƍ 6|7&BVi7n`ֿزeK˖-}}}ƍ˖ ի[RiTTԓ'O<<<ڵkd2 rI;;;BVƎT*gϞm<''4nܸAi';tL1 33fj0b0ϟ?77od2kkjYϟJYYYKhhɓ'|`~Iddǹ\nhh===s݃v!//v߾}{ \parrL&[hN߸q㯿T*:w`0~嗳gφ?~k׮ݲeKv0 q شiSttT*?;t5k <(Λ7e˖Rtٲe4-##+$$I&...ڵ۳g*WsXhQ˖-+5Ph"{{4Hx#G8~e˖jt:wwٳgϙ3 jY8yÍ7 ˗/3͛7?|0))sI`/ hd[`d^BԫF W͛4h H uAQT*6jraK.'O0aF),,l۶`t}Rd2cǎt2uν{j͸q4\.ر# ThFR3f fBdG+))1KJJ2aZM&Aƍ+y6۵kWnny/"ҭ[7[M ĬZJ"~:;;;<|بQ;w@ptttXXX d2tׯ_g0zs]tILLn߾}bbb~~dϟɹy͛9Ε+WpÇ #""qqqIHH:tS֭[g4g͚uEݸqcŊ}Aryvݷo 6\t)66—ݻd(Yh<77^zZ%55533Oru |Ç{MjBFiذƍbT*4ig&MHP EaH$*--III9998;;'''C$#F{u-/_^^JgIZSb1b ZRRR Aכzpܑ$ܨQ=zH$Bfrr?#H RJL#G9sfԩu=yB(,,8;w8880LjJ Yl۷7l0mڴtR 7{rrrF#,sѣK.7ׯ_}۴i!~ɉfÓ!rf߈RjV'dΜ9i2n񂃃v A v(̝;w޽(V{DiZG$`V/$.\`4gϞRpttot:T VvB?ow6L...ӌ ((W^$Y~} Pw6l3f8::2 ___ZU\t:sss OdrrrbX;v7o^NH ӧĉܹ{ngmmDĉ >|tǏoڴ)55N:󏛛hi9::8.\]]A"55U.zggg777 3Fߟ`@>Rrr 8w}?Sy{{O8uŊd2\ڵkj ROYoܻwI&}/^5kֈ?Z?)(»WLNի}}},u( Jt:ի. IDATAڵ ~9R&q\h&ݫr 2eJ߾}W>|xpp0Xtݾ{aZFhz~֬YbvС0я?(AǷm۶~+B1tT*AIzDFL&Fp?0L X,ps\ӿ( TEea`,d?a >OA@X53͆!|b50E:mg~ѽ{~p\\\=,ܪ6mT(S6ҥK-* 7f CLfΟ?WCEϞ=۽{7l6ŋbXgffB & J~WܭG-((x_ڲ '&µ^BFq\AX,ֆ X,a2YYY>>>r !C@YBh4$#|H5 pQr Nqjz„ 5$(d>!f,q>f&ɒjիWoݺǏoݺZ6L5YfY~  ʬU4ihQ|.:;vٲe5G$lX,aA@ |===!dtʔ)G盿s!`K"? EQJ>(.^bݽ{7##Xu֥i4{{dX3>ͳ"thx<޻[M4qvv`(&bM<955u…T^ybbb?`0\n׮]!sP-$Rs_} !IR"bGGxALѣGqJ B$000** 6h46T5qnWL%?eVe~t:++mO111L&|;9 HhhT*t˓j2_HH$$`0h4\.r׮] g#>>O$5o|Ν + $'M[ӤkeVS,8^2]v3g… q q"haa! ~z l2LS>*j^8!+V|̓_^_ȿAAA4ۻK.Fjժ|++$///heeecc_KQcQ՟\ʬfjjj۶mjl ŧiiiѐO!t:޽{p8 67k֬#Gnܸ1..NPϏ$IfCFF9}4ɼ#٩S.YDP@F ~ܷ(((XnݣGz=8q/((ի… ?^ERV0[[ی gcǎiӦÇp8=U꽠i@Vʬ&8(^F^Сógϊ޽[\\ܥK&_睐89sÇ CR;wd2?~\lA._sgvtt<{l^^^RRRO854B"c2F1b!\. hEo)j=)gΜqqqT(<d֬Y1cƵk /6 kʕ+Sժj. EZYF`IřL% ͭW994`tڵ,|гgϜd쓢%*jXwޔJgg~Ç( ?_,ŢhK,t uVRR2dȐnݺR&IRW ϼ5JBQ|Z8 ÄBV駟ڶm{W޿Z,IJRT:99ܹA6}+W0 H>>>fUSPʬ&ǣRp8ׯܹ?ϯdOU@z;B޽ȑ#t:MѸ?h4B7o[ɓ'$ٿPNK77iӦG b̘1aaaJiӦvvvb8,, cVt`gXܷoAի1 {+ *JZ ,HAQCXreӦM+LȤj &00P$k5-@īW!& \YvߦD/^\2 :uN?~Fnz͚5SL >FӾ}{$ݻG8NDDڵk'-sS@\7t̙I޴iO?e[)1PT4m}?լZ@'"I˫e˖;w.))?͛71 c0P69΢En߾ cǎb)~~~z^PH$TM EeytzqqÇ7oLѠ¶M&M$觡(*[hѮ];ArL&#b:3M&T*RYNAtOIIB4i뀀'I L*fP2(hgg͛/^`'''#BцP(poܸ14LeeeUE#qB_ʦh:$I{{{^痓l2.1>Ej9]G`sDTg6$I+++,F>̙f͚Aђ%K 3ORb<+}(j" eʬ&d`j?<vvv4J{>`0/_7hqqqFFF R666YYYBܸqnȐ! bUd2p~DDDy/hWPqJKKͪ4)))L&b EQVkooi39/E-cҥ۷Pj6nɂ۾}92@PNbJ,0tJh4__Yf͝;E~;v֬Y47nXjUUDUP;lѢE͛7 ̘u-A_ .E $11|-YM͢@,W]w&-&g3aa3Vj(ZRR2{sBh:h:p\/SX,ñL0E-٪rH4 J@GDVC_%Gj`.@#`@ )AraB0g@z[pvPae_>J`F@45g$IBOAT*OD_,a2*ĘQ\w 6qEAɜ>}յB2uFAEs%I288jP4> -[h~kҤɸqJ%-:.7m8LzF]ݻ' #""^|y֭t '](BNpR P(6mj>Rj`Pa+WL&J_S~BYkFflѣG]hx<^LL A0J3Dr6 SQq8HVT%%%v6lχ%[[M6\.711w;vVUTAx~P60Hq2 ǎS=NغTm`!!!Br)&a 8f߿߶m[o?\.ݺuٳgϝ;~;v9Ǚt:СC(r3g\pA3ȑ#A8qb̘1Ϯ]&MgϞgώ9M63fD.]R(FťyIII<Ν;{v:uj˖-͛ O4Z 0PՔLb۷AݻW^mԨQzz: l6{Gy%۱cohHܵkWͯ]6m4Fyϟ{{{4m466ڵkRtϟ?D 6|… :TZZO",Yٳgݻw˗/_z>wܞ={GEE]pA"DFF~*/ŻT"Sf5o|0 X}?sŊNNN6m)))fׯAPPӧOFcݺu6mtThJJJ=<<<:v+:?+Wlll' 8~ƍ.];wE(}D޽}ȑ={:tF]|ɓgϞE =zyO8vXvt:ʕ+%?FQV?yJ2''G.{xx?}t̘1gϖH$z~5k֒%K@l@@>z/_DQ`0 29sٳg0 x<Tz=,a ϣ'O~]e?.^sFSNf͚i47or\T{k׮?ٳgJ(JF`0tzaa'Olllptן3g^?qDz&Nx݃ J"q8ׯ>>>~~~ӦMsvvZVPd"^g;v qvv~D" t’Y͙3gR@իW{Aoڴ)&&&99yÆ l6Y,ϝ;~8phtrrbXiii)))oqAutdDRN:u4mlD"%IrÆ SXܬEEE(ڸqgϞ]6$$$**C$In߾}ӦMZnݺǎC͍ /0 tVÆ 5jTU pώ;-X^Ç#6a„UVիWѣGFٙ:99|GGG&qƍĺu6lʕ]vmܸmf7nXXXhmm}…#G.^xڴiEEE˗/wpph4)))cƌWdڽ{w.]ju\\ܴiM+WLIIS|q*A"pN7twhF-PRܡr`7AĽ{`ѣK & `0"^EM& &Th د_:uL0o޼ILL9s7xT pSZhQv yF#B0L(tY[[?:!!AәL&x~J%N5 (Azիϝ;Vqf!UV3Lx]Nd2~[,+++k&Yl\nhhh\\\=-5sm6$$Mesͬ,;;;777 6. IZd: ?f2 >& 1@C?ܵ-f2F#N0СCK,1Lfqm m4; t]y] Vn_B4$Tx?`5+Yo5L& *y@hӦMA&K`xg<Jે%8d0P"EUhѢmAAA'NHu`dm_?koŋCm^%2P F:MX߫ZfVg-R4<<$VUSPtܹk׮z~?Q1B-gRT eVf[Xۡs%St0Ŭiׄ:GJsu)j>[lP3Z`V7r12ZI,Y@°lE=rI%?լZ\ zY] #MZrǏ6Ϝ9S XlQ0˜ AIɄoe5BѩS 6(J;w,^Ef͂EK&ʣv HgٲeEEEYuP+&Pο,:00ۀaX۶m pw;b1 ^o^LRA"eNGQ9&I&2'Olܸb?Hb(j+ ڵ@Uj777+++ ծaĉW\ٯ_5Nr-P&Fa19Æ +..~Iݺu9WAtt0VX1`K5r@=/^?a„>yq7gjRPT(޹sT.Ϝ9S'kkT'͔uʻP@"E$ILx||O8a4G]RRh(D"1!!!|>nݺTWA%?eVsіjEhp_rVXq̙AuM*RN / jjz„ ZƍӧOwww_Ȍ⫆FyyynnnYYY&qZJFD̀DQT.CaT*,IAQEkCDoEe2ȑ#gΜs/^@unE5@bCCC.\HѠ\lllVV4((ʬfxxxJEu:]qqܹscbbΝ;rȢ"`0(Tǜ9sqVZUN%K8::]6##CQc)oJdwww 5恢Rtuu[?~agg9,Kf*PjLoR ǎ/IDAT{NG (*)ϟ?vvvjE&X[[wڕb%&&Ϟ=^z(r]p ٳgqww.9{L&񱱱!uvXj2ٳ>l&Q\z\.oڴ'/^sNHrT`7n>>J}c)`Xl6`PO|>`2YYY7MdMggZ@vtt(Y!L&s͚5+W,--WT[[[Z-Y,]OOO``Çq)"S =mN2 Ldukz:9S7M$fkrss,J jz`` mذA'cTCw@|'T*׃BLht{qc2'OlhhHKKKHH جWzxxaN\v Ce˖3bggN35oݺ-, ؾ}\ѣN8pMɓUUUX,=#ke [gڈWWW+J'6oԩ[[˗/+'NB<IKKh4)))gϞussill!744INNNJJ";{*++ϝ;Gϟ*KtttZZ!ĉaaabg]tɬ͛E"!$;;;$$$22Ҵ^fE !EEE˗/߷oi͊xxxTVV2LӆWss\./p8 5^/TkA2JӆRܳgف.^oP`oogϞv''ڬ:gyZZZz&&&>ddd<GEEbD7o4+2k0>io1h4矓qrrt/t^^^Q"Vrqq1 mmm>>>Eaz뎎!"+VXb!D,{yy)JLvZBD"fE\\\VZEioowssrjחkVLJ#bZ/\.H̊ӣ(rww7PGGY6/2 ӆhkkYbLj^O( ǏtO4 (;@GG[|`^ts&)RTRRo+O-%%{7zKZ ݲeC"##CBB/_\; chB֯_ΝsΝ9s<7dM(PXWWf͚켼rHqqqkkkQQQWWzccΝ;GFF8dM(2,::%:::%%dMGn߾?BbECքbүܽ{СC666֍ 3s֭8L6ʍ7!;v^P`*ځ<[yyS ݰagpZsv VXXf'>22V-ϬXn&BT c-bxllQLa4Rd2"jL,x7.dMVK/P(̶NgMR)M_QT8[LP(&5 0sȚ` bX(WTTB>&gv̙̜9EQEH-(ZAEQsQ+(x.jEQE(⹨TEQ<(VPQE\ *(ZAEQsQ+(x.@qC&Od nORx h]?F Za>t5m˗oǎgΜ1[7x!l.111 0[####$$$ T/l)<W-GC D0ǣz9@-mQEq0޾GCK6rblɈw;sEcAŝo`_|ōnܸʕ+PؘGEE?W[*7If@2Dz a97'n[0EY` &Ɔ RSSLK/}…B v̙1clݺL2tR…ٸ|rP%fOqEaÆժUF;wO-D`khHL"0,6iڛtadG j֬"[I@_5ڵk7tP4vyKHbk_2iѢŮ] 6" ICb>$g\b! =l'Ef:ʅ8E.GӥυH&XPq[0c[>pۨڽ{w|z:rHDDĀ{taŊC y>vX~>A{~-SzevW}Q|I*ǏGwb_>8Xt0ҰĉVBaK;e՟%ذav͚5͚57o)ׯO\gA2s x 믹 \w}\Gݺuc9lr…2}tNq"<97mڔH!DFݨQ#2(iI89s{=2>>!W^yo9uIam, fѸHB={-[U{'YfavڰaC3f`9w۶mQQQ'O\xq*U8ԧO%Kl .hօû?6* $iiiQƹs*VHpCնm[ WFX0I) /!c',88n\L_d%(_|xxS![|9QHaaE~w3{gyxx]ُ?8""u̙x~9Szq:S\Iad@)w/b-/Qvm@3'W +(uHt^T\K#G>3p;m4.6.n5zo޽c7oތE@T… ۷ܹsݺuɿo߾fQqEPrYJ֭[Mxyk׮/-w:';%<-7r3eξLC<1'a&=6n"K矆T\722r֭Dirޱc#"$fvH8KMNGv2Te<RX\UIOٷ7ƕ6[Uid#ۄصk: 4YŊl߾8d wϞ=Vl4o޼hѢҠ-=zF~q0;vdxꩧ6n(gIcP"9q0'$>?/Ssʍ\oi3mРUJd>SĐLsN2 g9P(\ԆIKȈ+HR9u;vxp6_Zզu-,@d 2bU2SW頤j޷0;3YbzN_l{:= )3Lf3H *dk5%`5B:GTQ.),'r\HT"9jBQ՜khUf5S%8|y'XwXBPs *'k.j|rqqqV8_c, I _VNEcAEQGR1_vjժ366vΝ!!!?8|˫\r ݺuСC||>u6jEQOR|AcK,֗+s]tzj J(AbI@\駟}֭3VTZAEQsԩ٬Y2 _Mݻ7QcmÔrn| g(HRSScbb=b=zX^zoP9yh,(=V2[ HLLӧO``aFܹst!ook&L }zzٳgd^~M6ժU8}k^QĉǍVBCCccc]SYe}kKÀl :^vmȐ!w˗ z-GIFV>35(f׮]k6[ %{r\d5zC_f|QQQkʔ)Dɯ Tp). "du+4\KJJɓ'M8R9G(#6nZ&Z1[ZAEQ QR(UEQ<(VPQE\ *ٿ|4h6wEqAtv8[Ξ=ϟ߶mLcѣ.(.ZAEq0K.}衇(fr;vlE#(&--p6l޽B)= *yw~u۷ok֬iҤB)=j|˖-ldlEv*fˢ( 炊_"""l?(Rbhf+Vk׮5[EQr &P̜9lE1#zhޜ9s&))l)Em *(ZAEQsQ+(x.jEQE(⹨UlGV܏ࠠ Pn"(:D+]oVnKV*Ue˖ .mHLLl߾}HHiׯiv,YrW\)XIcҐm…V^\@k׮ϟcǎ)))GY={*TG9ۮ]CzUP|e˖"˗Io_h&M R?~_Ur""߃ʘD -[֓+1cH++n߾aԩj=ʕZ9s.`>}ƍD5jPϟۿQգIԈvJgOFIC&T"GGGKn*̙3T:T JJJJoժ!!b7N 1 6nhTzթtJHG"/{H\X1:i䓶9?]t۷X8^x!99yl/Z\>>>C*Tĉ g} =(|\\dnϭԕwy/_n C+Xڵk_ViӦMbIr444?kd{SN_|3fd}GVݻܕ5f9+ΨVpDθ(;`l9 FHW5k sF- H_lQFܹLufd۰aC"&Ww¾*Rr(III[~GǞolB [bE```|%uE1˗;#[Vpɒ%fE Xx1I&'NLMMe>t0u RRRƍ';͖NQ<Pgdk /_⛆uqL# <|S[y裏=XC+wr4:¨x͚5ۼyóoZ&|֭[f)25jԈ IuSȟ?իUF%]BBB,YyeuRڴi \fM^Y#WAѺuk6L쓊klٲE9s&"""WE }7mԤI\.BXo&$$w̚5… )]!tFNeUp%d2700p…SLҥߥNs":422Cf*Hpxc's;w6Q Is/hzA췢(}+nݺ`#|~l)쓘ȯ@g+'}|.{6 <2$x͙s_n)2˃HظvZs[<ΤYH^vMdˋ Sf\KF5և@άbJIK\rQZR([']Fbd{e*E ֯_l)1o5 CEMСD 3gĐ`FNŢVВvh 65?P٤2Af"@ٲe˰aøīzq/L&|ɼy݄8h]|| M_U˖-Cc̙3)S;vg1$޺u(QͮiAGa-hߏ~QX|ZAxM͋yIE(UG̐Ղ +%ͱv9)$ {9: ]o߾ErB<8Lj+?ڷo;JgÕaP -]L|mO,8b֜9s>3ZҜZ+WĢS4MΥW`MKfY;E P־U.}t=]h|-GP|rml^OJ7CGIWRQLG΄\X c55j`ViLl1F]6!:ڎCH/˩jՊ%CbGcE-VcL!dp;) a"gaqu8[m۶1TEp쿊ǧ[;})jҤ ZØBAI2ͿGuv pnG 2ЧhCŋ'%%J'fY-1eCjՐbɄX61q* Euj~XA#(z*ئu]8x+:ƽQɋ⬐?%8Ѷ^^m “;-W$Oy;ԢE 0NBD>Yrv*m蜈*Xa=y>/uIm=gJ/ \;<[sD]mf|ܶbmd܃Tq&a}U<Y,۹YOzܱ~oQ!Bpٖ$g}ÇӲFd#!ܨZ7&LS<}+8gΜ䖤YފUŭ[{luold5*R`` CN^5BBB,[:f 愇3E=۶GVTɬꥦVX]v 21W\jmئM~\|p®LȝRs?ޘO?%+VڷN-8hD{3[r8?~ȏ+/){#^;Vpڴi}1*fQ|b☘ }sRyQ~E{ؿ}(ҥK}+xyxyy{}ʭ@*THWQ\'}۾4hBkՒJJJ2'NtF`FF(Bdd3oY1h,(.ˍV!`o>XՒ<5[ EQnH-}+Xvm-YZWQ\'P>l ȷo,W!88X}\\|O4 *a?\vAf͘1#((H5a蓊%EQ |nA؇ͫ\/r ^:--mժUAS2UBQ%{ywD[lߚ9r/N:͛7`w,l?ݛl?ˬ(qFgdk߼͘1Vt8/ӧSn]Ӧ=ztJk5z9ⲠXpĈn ¬Y;Q~ӧ]haÆjEQ\jڷ۷o뮻.M<9$$$55}gΜ!).\l'*3h gdk 2dŋ7L\\\^._L,H1orrX`BBZAF5[ EQnȨQNl[A???xl|d .9h,(.˳>lcQ+(b:ǎsF A#?/꧆ݛWz{{k,(.K˖-;M6 GrJppق(NDf7eu=___:?^<'3LbUIξ2ee7#`222}Fȑ#T2b"5ؿ#drZAO ߸#v\\ܲe{-[R ɡLwHYY $''yyy>bv=4pjR*\jI%QD'c;KlY;ECׯ!hvFͰ"T 7j "@9LrZ*TIKKَYՍZP.g#-Ƚ{{~k~Zj1/_z-p~%J([lUV9zpBXXaP12wɡ:z-#v&L`TR$>}/^(h?v)D*'>>DRKRl:O?ź?_^Mi4:qС欍N\ѣ|饗ڶmƍlYc0F4}hhhS~[V"TҡCj֬Itw}7B桥ދ-!(ɓ')T@(nŊΝMNjԔ̶S-fRT`ƍ"*+o^gd_QR7n#wFuQTΝqq4im+_< (}ԩl0fΜYt2e\"}[hQ.V\?$;x O.hR*|Μ94|G&E;v졇m|ź ώ;pl[odɒgΜ!2}_}֭FGBcSiPtի6me_ŊRҥK/^8 '֭[ޒݢE{,WO?c* 2< IQjUX"-ժUM$҅RRvFٳ֥] cGrF,/$h1b|P^=}W:7z QǏǰS7rH%ø[n.F)Ə49~q{ɍ8|7,ַ`*xYvɐ;F{7BQK:uC͸q¹й4 >۽{7M/+tҥVZL ֭[0׿&6e˖lc/ŎJeEqc#̷oNHǏ˖-Xo#1c,XeMA[0P % ~"{wU4UJqMW_}gF qڵkNQ4Qφӱ=/co߾dWܰaLϡ!m&RZ5.ՋA+035K G}%`܃q6rchwgdk?8CkG=/ۻw/cXB[3C˄$3:>|z&M 3e'n)J6K#x͛1'O O 'l$WE0h!)W\yꩧЕGyJKbG _Yf111M!Di ɜ'gC(.n7> AUF׮]0rH{oN,ևU X|9UGdfHLEr:B^/rOT nw}00`IsyR x5l0::$_Q .`0\%ɍɨPn!q1NcO?̕_̖ .4nӨ5k֠9U%u]kf#(_u„ 6m:qıc}Ya@fr2!0o޼#G 8wdJ%֔),VEu]цCEZJg͚G@ v VJXF AiΝ;Ҿ'(IJZS$88:vX\ChXvru4)%4:AXL6ж<4BtQDؘo<j\rE, UIX$n&1!# 0Yp! iݸq#9H4M0>/gϞA0hhZm׮]\hBzReӦ=$h7n#歷ޚ:uógU|:՘ju۠tpr oݺ<L\M|lo Od qh"Qv%$ʕ+o il6缛Ee&mn&dU<κ5d+sC?Qzs4+m':!!&=G`@曍5vlIiep첅N2pyVZaA?9m97ڈ vyWQ,nh0D{hFyp#(D(#K(ߣG$ybGZy̙M.p|}}7mDtgP2ISWmE Q~hٲeۛ?X/bbbnL+@Wڵ+?55nI_pxⱱ/::m8V(I`y3yxɲˆСC+W-pS-?l_5Wh#Ocذa־]D Q/޶mɓZp׮]T3>k7%E})6o Ag0<|xtt 9{l!8&[$41a=Wܿ4'xK 6l@ŋ8qBPp޽{N :R#WȖbCKnC 6cǎʣhѢݻws ԩSZ9.sN};.߷~CMۗJC |HUXwyxؔ3Ϝ?1xO>h j@y1fΝ&XAUTR@@\Z5bP*ك4|%HFrbRt %tYuPGFH̹\Iz$= ۰aC21zdE~'&MȲeуfС#x^ƌC1\V _N4IjdɒFN\rCI_ Õrيw+箻5k Z9.sȊNwFY[F2pV\9w\uIINN& 0ݤQFM:l :гg:f 8 &ngKh.4eQ&m0dT;vnݺg}ְapI裏A=8ܼy|_l rb7neh. 04S!ŻNcB'M$3s~pgyDGGc+n(A%ުUN:塗/վ}ݻϊ)"ŋ͖%L١Ceqn*S~~Y0DR%mwYXkG-בPe˖co Z16DԫtWpq0pm>(P 66XDZɓ+V2=AtdI8}Ƞי-5,?zr]|05[Yиw ݾW^Dl(Qbƌl;/)O{&Ĉ=zꫯ؎W^YܹsǏotU+fKD)B";VM#%&&\rٲetڵkׯ]v;v(S|"NQdӦM{ߔXУ΅gݺuk֬M?4ȽEqM,YlǂQQQf  D)))   B[Ӹx<Ă4i76O|௼)[Vo>00lQscbbP|hڵk)yܡCwܹ߿;Y4QtF`M@8˖-3f ZliӦ^xݻ{q(رc炕+W̷цK~7oQf˥8 b>$$D[Rr) o3ocvMmxÇ_aB;qմ{b} ܧOh5Yj3;vVN)P+L8q֬YݺuXu1qqqy9>>>4Y@@ق܌cǾXhQ%ʞ:|{yy]hyur.]8[V.'2l߾sΌܜ0FFF]+ ;-666)))}6 !]! J*TG_!|Г͸ErlU͙3ǽf(>s3 :㫆G?007999>>^>mb??+϶eB*TH&ddd↳۪jm  3}N.įd/sooycv:/󭌏vImHДvjj*Zg4. 2-c\]i4mgrLf b>_b?'r`Е+W\ac}D0ۆ1ғJ$o3ii5pd:Zi/c: 99g+[8;o4RL/:s*3=-( \dz\t~,n:1A͛7G5jf _{ݸqc9%Yb8ԳgO~CBBfϞ͘'٧Ob0… HIο_QdɢEwd3z%JHCׯPYTTLɣ"##[jsTm+pǕ+W*1eWR^z\+DB ̚5ϝ;wYiӦa#+V8pչɓ۶m"[0m |̘1:t믿hnݺk׮}Gf͚Q-4ȑ#iGPq 'L:uTVj9mۆzmݺ5Yɓ'xbC ٲe {HEQ^4 bzsNif}GPlt=Ig`AO>|8I4h >$۷oСtBz]bWZY=T͛LYAlP.uafꐲ/[geI&/^lڴĉ4kǎ?>b MS\~[NoZh)Vh߾=B`ѣ_ꊝ6m"[9J+,s!~Dx9)Zt o&v4ǤIH|]wQObz#nљ3g&$$43G-+횆B<L5ڇJ'~FUBZxh%b(TXMl$8iy:2tI%``0*PN)QU(@^?SF2A rŃ "ͻヒ:f<+-(/>a$rd+VDQ.Y?>"x>IְaCLF~SO=5ʧcFk5ڵ_y,Љ'! .Dk5r 19B`F,4 h .Hg;,)cSNżp*UDbt6m<(V0+KOrEīZ*ʚG5kr APD-dNOv PL*駟Ff*wy'G/F)#uHJv4&6pw8 F ,޽{^(d{ҥ ȐO_|Jcѻロqh d:TR<5JҥKR4BЃheb$pPiM/_[_2y=¥ih|GVxє#"rH:#+OؠQh2L4E2=3Ь"<Fò."?b<!_.Mv"9X!|.GINŵbbb\pB$2e E!!]j$P tO^砀X#,qA.(2&mAb2pR4Mr#Z\F%tyu@T2iH /Tg4=#%tU/: L( -x$_~/`TyfmH5kիkժ7o\0q&:^ ˰D&4xX F$ŋ_}&D6ㄑO`޵k ): P[\BfGuƌx:5j߫W`X~Ȇ0K2/Xz&Φb ƍʑzg Z¿a?a4{PT)a2߁ CBǠqك";uAwXdoYhCtkYo Hg =6O""4iF7$Ab%bC=F h  3TP Ѷr (2_ N H Ec$`daJ[Pj*"bĉ''dbX\ X?C*EVrWsϝ#ޢ]ZlIЀsN8FT&gɵdhSNhO&45>)شJ֭w^42GEEN0uh[c nUZp9B֦a#6}]NQ:ܼy3QBL)t9z! q PKVnaP$=쮻"cPׯQFڵk-i𚔌j{YJ+J،3#'7c-ICPxD%O5!=zhq۷[N|)G˗/Ou`pq EfE N6j\ ógwY6]Xwнniг1?o3*=(.D2V_^e" DIol˧VA t%駟èW̪(_yX(אG򉴤ʗ by8(R|v4 ڠ$Qy>*%gԡq1_Uo(Zd(5/7hL7mJ˃IOMd"-+.GЫW/bH !3 QJj*Rl?eIl'Խ{wN6?3ޚp@zTp, '45jRRpSZG_rJMMfL@nc4qݬE-PW_}C%*hܸ~*s^2 afСC### ]1Fc J47$ʍڪtv}L!Yb>7_,l7CȤo2@pMLٶm[bMk;زؐѱqFO4oMʹiL`T#7nطĘ- jeo[)Z87ъ%P?¾,W+,`oWB -*S$G[7$ϓ۰0֜EwEdR(3g+|N֕0aԩSss.3gtFmѣG+UhnQVr8}' ʭ'UP={1sXA7oNxx޽{?#w䄉'=znũ'$$\hEޓ>|]` 6m~fSqc{)B'W+`/_n:;byl:s1a&D3gΜ7o^׮] ϟ?o|DP(.]ZfMgk *n|'==]# $55qƭZڶmۀ"""4Lfdi'< -3 ZnA0f_QڳDgΜXU-Vw… -WPPѣGۋ/o޼pa͚5-@xھ!vq/R6m|}}~iڔl}+x%,Zs4p}}ի>>>QQQ hԨѶm̖T3kVYqcP~~~hRO&+8xKb'Nwކ o~׮]f%ٳgQō;yu<ۅ^Oj*'!`.]*nƴiӜ;k׮mҤN4>%4qpp'4ted-{ۑ(|ϊڎbʍpƇ- z8 -D k…/]M^hوX-5j3 lR}d.s_GMŕyga?c ]GTqc&.PF18p3oGV]M;OvWL۷o7D_^@];e] l!C;w+ imŕԩ3o;&C,XX .h,f ?lU c|G"kkT&X -طiiiwDmws?~w&%%\UVԩS.bK(Q`AOVbE~ݸY XX1qb 6mT0ō~zxxxׁؿ~-X%K?oVW\Qc35ꩤC XbEٮ\rN~M۷IIIĂN\nݥK,TƏoFƱ9syQ":=7$$D#1Bb+W+V,444222..뉉 Qkɒ%Eղq!z%zcYl[(x9]vP;v|;v>6CH̗ʯGǟ8 ٳlٲGĄٰZ0./k(&a|sѢE-[򛢊 B EDH]N5kVZ&N6YLI D?c_k֬ ӧ\ZJ a OF\Z h:dZ1UVfdklƏ_~bŊY-E0~w7nܵkr? BZ)YU^pa6 ԩSg֮]{ԩD)Q!_nq] o7o6#[ϩ+hG  3K6+Vnf&&&~geʔ!"9r,őTH\aȍkϛ#N9c+wa$]v͛2uKOO~⤤*U˗ʕ+X>Rv/^A'4Cs0;v/+wpϜ9sw| a7..)9'000((s"+mMοr+3Hc8H̶1͹U6GD8vqa(a"R??tloLLܲ$E_=&+Y5SAվO"DdM 6lݻ… Q;w1 jJvܹ~hKpn̯ߟkݺu"瓘xH)))_|)tV%J@z}`I[l9}4Ģ+V?| F\dd)S0lgϖڐF·f_9bOSІ5-:cƌӧS)8={vǎԓ4"i|ҬVKW5?[Yfyؼ,!v;w.+pP_KrkPa:uu[x1pĈ*jtV߄$꯾ yҥ}Hf___R8p;s :СCŋgS &!&&&ƔVNQ#?8?d$M:uѢE5k.27n\vmp[lbD +VѶʔ))); Rڵ+Bc` 9{/hVR~GF>}:c K>C,_ʕK=C.\@C=z(9IN3AczAo~5<tRUj5{l? )g]wA$pa\}^t8&)gc+;~Q8i$\HƤl͐KOOuD\Q͛7߿Ȟ>v#ŷaÆnݺ?(cǎ5jbE^rKXvؑI&Ν#:Yr AONi "%C^PlQ b;v`x_2ь 5]va 7mڄ_LG4 $+/c"g~Ϟ=K{-X8Q\֭[1$ ۶m2 ?.ܒ8Y͛7GP%.QߘQԄxi F2-[?FۡזT\cv֬YN:͘1o3#`&ND9V^!99ҠAG}էO-+""^{B[47{1l̙3wnݺuBB‰'< Ăt].P?""" ;gy wEZ+X`A|OzAM<@ȑ#+Wp'?iC`vX~[Ν;?:HaqOn})N#$$ܹs#߱c"7'c–Nt.]*|VÆ Ç/[˛)oFV0&&üKEQ܅׬Y߿^z6mۡ1b35ǎKX… .]ڬY׏3Fⵌ7Όl jku<*}7oތe6\CkiѢǂ aOw(nM 錌ϟ_V%oPTLZ nڴɛɒ.:x!9c0y ><bcccQV TCԯ_ߌl{e+`3N慄 0`W^;vѣÓΝkIȇ'7EQqUX?&qƊ+LԈVP&wDte}EQ\ \BB=J͛QVzGT>V?(ڵkիW߶m[PPPbb,YK/;wNz$&}k ֬YkWEڶm!$k޼yxx~`D:#ٰa[)S\xWE/iiiB6>WEQ357|WOEQgҠA35lX}OZ W2bR4bl~īȓ'O^muuKKKgbl}}}3(P 88p%JAAAVKQ B09mڴi ;wܖ-[x '''[]/EQVZfdklBhhhҥ-Zի?~+*ɍk׮:_z511Q?B#b'ZJIIɗ/9 t>ylܸьlΙ3;E벋ӧ;}tL`Bn޼9ZnݺVW[EqqqX&M .ĉUcfdk FEE9T_?P1AAA+Dϟ^0uY}|n߾$$$w}7+> @4={FŹ̙3׭[G X^~@)Bv^tb\js8a$* b~4UX:WJ| /=z4))@@*&]r<񆆆;vvڗ/_fwҥs]r r).U`ANODV_|EnRRR*TPZ;nP+(nbgauu ".](ZhaFVL2,[o͙3gĚqUDaݬYݻ]_5S5kڵp&%KLѹsgϾnW_P9^lȽF ٷoD KAdx"+t.2dȐ>}/_… )jժ*UJLLZ+@n߾}e| mVQ :wuxV\r}kMGlқD4 T;:h+Vt+RSS<^xwQzuqpqqqq(@Wɍ$$u:c޾s?~=zL2Ɓҡlmw؝UљG +N B ءCǏ]vֽo-[6%%%gb fΜ9f̘{キK.[n9h5k~2J j<]mwa͛7wxV0&&9 {sOK2%?xDR&#jML'ʒ1Rymw)迪mκM& `TFRRg9FjBJfܽ r$5o9p *x-J[AgϞ7nP.!k,+C*qyldJ B,YdY%O ҎfF!Sy UW:Pq햮á Ο??gҏMVzuFJJ;[cSǎ:tҥK6mʀ2e -P`A::= #0$"##;v8|p=[z3'+m۶;_}հa:ԯ_')RD̹s}.]/d.K2 0)r:W:f̘5jtЁ|˗/OȊjժuUBreD%ESsi Eu~/Xxqrw}7n8P#F ?-E4bϞ ֭[qro9kWt%Ä *UTfMohgѣ׬YS[~r/ޱcUЫi8=~̙3^2dH|0?c!֮]駟Jի8[iY*]^=&Md2$BQA#5BK6(ݝ;w^pAnf"ԤM64R<^2E&^$br c+Hu:vܹ?ѧO~}}fϞ]lY _jժݗݠA#v8k,FB!`˖-Bv WX#U:uиd`,1$~={ƍ{1 6DDDу˖-+S̒%K(|իWSh:h ¢EPR(Zr\u@׼;$޿ZFEC0D/׮]/7|_y,"|7nf$ÌQDNA Y#ZȓCK3/|'[l|w̙3SXΐ) /i/Vk٦#͛ӫLjgNhѢfŘ;v,G}뭷 Q) POxy,Ќ c\3nݺK.8KEOū DWF#`<`^6lH&t}TR*:#`(tXJ!krW_}ȖMoݺ5 *fԍeb|5'@,Xn7903)ݩS'@oM6TaXx♌ Mc5k֌~ g[i׮i?8|peZA=dӂ5ufF.}.--/K/..aڹF~Wa͛ǹy)Aa/ izFiѢ#@SHF;bl(6@wBd/ b$b(1H_}]Sׂ A+Vo>l-NŒ/ŵS,ܜ9sN6hYF oٳdjئ/Z2Mt&e ,a_# EH.5r[I8@_dPb z7''>60*U %(MYD&d,FPR(5z?aG˗/9šƤ:bժUsɊhCY&>f(~! r 8`A%'B5naiGqAsԩ;~쵱(J"o(Z֬]0K{ t'|f'B'z5BZ`>C;a88Lr?bIGb_>8lsYAn5k1b!9N^*V[0dX0oȓrq>`I[/D[St!&t G TUzN߾}!ji?ᐆmyrlvy9_[A:}XXXVppq藄V .k?2h , .9ݻXJPT0\6) Spjժ%r&<#11Q|$ztkY4@vZt+=I<6J>{キdt4qAMɹ Z/^={jE>|HqȐ!ԙ0sF0ZmCÆ C'Cr@Y#.9}9  &lBYK *"ۤI bPN'8y.' $# i> ,,GbR&5kh^{]Y? Z CgҤI\./u"4{'ua'0mڴ={:<Diouʔ){;oL˵(W4DAJlWfmpJ R጗AR[6S^(Qp!2QEz5/.h/ [߂}|;i&)T~.cAfd FA dV-4bDJl!Q%2UQvɓ( p95Jgx ҡt?#Pz|G' Ħ@Vjذó5g͚J2;^qdZ_ee؆4Յ n37/ǫLn\\\d޽{ ;<~8*T8qggu\o8mhfܐk6ّ$p &rdvDIpX4fhHFw:}_y"zMCPfdk C-)""AVrVCMylcu]ƟX]!ulC WTEb T… B03a35sEKj('-(]vbQu˗lAAAkjJV[9;q˼Swչsqƕ.]ڙ} Vc{իWA9ֻ5*/rF|d%kY\'Ը>V0݆$7YkW\FRؐyV\}yv&ΤIٳΝ;`)8;v{kx%IIIfСCyXXՕR< c+8}t~bWQ\ Ȃ>=z{VK}<|˥(eG+(͛[`>iZ}35ǎӻg#/s^I z!PŊԩs+qxvLVvEq W}]ڛiѢǂAEQE0`.]]EQE ˖-3#[c+(ߌV?iQEqYFaFVgϞj+ŕׯ[t/\{^64Tgԩfdkl{V_(8c+_@UEQ`>{(򪵟iiir-lǂ3YB86mZB䐠7n8~W_}q{t@@@jj:|fsDDD``ɓ'3 \Qr@tt[~AWR4r>}^|EQF9sm۶ϟjsOHHȥKm۶-Z`zATrɎT-|r޼y|}ѢE/^)V矧Nٳgׯ@4USܛlР)#v >~Ν?0J|)9 ))_?>;sM\~===)́ ˺\p{]iiӦ%K ߿|@/+BbbovZr \bcDd˖-}(&$$"V^7|cF:A@QVSNY]`[4uF/(IQ]vU6 J,(a N4!%zY}Ɋr J,)E!<ZAEqY:1suDG_Ugٲefdk|3**kW(wb .ZHT<(.NV N<پ谢x* *cwD͛Wh رzb%~˗/˗WI& i~B Y&%%͛y}']vx~+[,E|ozz:tR||}GժUKMM]z5ɓBCCR7Ҋ+VV-H?}vQyT\rj ÇS+P5j*UJoZm޼… 699 Wḯpaɒ%8PhQḚpJ,?Xc|UVݻ t*M3\={8"B?P$"ٹsgll@ujϜ9C"m۶WЋ)ҰaCڒ:UT]:.հjÆ vWXK5(WP"iBVjpDjIcŋ8{5VۿG>C*ڵ#\cR=Gjp? +hxׯ_GpPoxEN *(ދZAEQ{Q+(A*wVPQ|KQoC*'Ou?&&&>}bŊVHQ'wDo'--qիWOOO ]x5Ry- EٴiS:ud[Gx *Oڵ=zuQũh,(_ZE6tvbׯ7SSSo޼iu] (P/ݺu;~[|PϯgϞmڴ"h,EӦM'NX\9>e޼yeU{ vJJ!!!W\"h,Q &0u.D] 2:;F1 *׏ݚt(nZAEQ{Q+x'OL/]@:]Xdy@REnWP'_|: gO ʷN B'W:@tA:ÂcoTx U\h6$P^bU7rn`A-ojwbՔG(` c@LD H6NGMXfM#T}~!ҷVvT,?>^fA_ݵTJQUɰbL&92td Ys:TNMBC=C+F(``Ąֆ` X3L#e~,vֈ1O 2RX6T}K1 bx  ;<]4D L];^M`Q0 0@1᯵'U']ik )[O ܂\9ݿ4Ϻ6]\ "^v}wTaC>1 U/Qw-#{؁zN.74 Z%goyhO]@y]`4}2 H= && Y&,ɀ0ܵa|j%Hs3%zO+NP Q̇u2 9d ddI4q^lGق Vi/Hx2zQ0 F(X@.Wsbo 7V7zq(`d@G(`!h^*U5`Q0 (`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@1~y4F(`!Ug4F(`!tJh(Q0 F(C(`Q0d@Vۣ`Q0 F2:H> F(` @Q0 F(`bh(Q0 F(C˟AQ0 F(`bh(Q0 F(C(`Q0d@w4F(`!h= F(` @,F{ۣ`Q0 FP`Q0 ѫDF(`!htn{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 izw1#~=,\M8 F($] )WaF>]`MRCZ D@ 0 ]Gdxv` ̈́õ8 F( \ 2\^*}? ą4l]7($ p#hPQ0  _ *l+\E}#4Nq1Ҙ9b6C+F뎂Į˂HhUd[a^W'5\?{,΃ @P{!걄$I,\ !a44{60 v\x1F 4`Fc8ǿ~v0PSЃqQ0 FE ;ֲ^aE7wii}Iz16P"p(p-m b_¨s6K _ΕNًssOKoa!FX(~KҮf[jImKPzД%E;QO3 mDoҋ#q(/A }>X V!X#iɏRE-/e"23n3h Wݠsb=$ `'Jh_aQ@ T!ށ֩ZM#*"mPw.nPQbu; R' T ^Ԅ17ᠪǿ:<:q3 i`@ѤuM *i;{w=-x»^tGo>\΃tIS@=Ttj1BȰ ^A4AH\jJiKiT vQ4Q0 F h4H(]<`!tv /I$ VuCLD,Gtxyi\ UұtG0h/؝i($!c,Fɶ@kmxR;W eȋtRAmh<0H`Q@. F`of2,=4hԌQ0 F2t Xd GhԌQ0 F4{ۣ`Q0 F4z(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4Xs` Q0 F(p@!U ~=,׻`%Cg`Q0 2 Zg_v aѾ(`DArQ׊]EncUa}X\]sdy$D΃2a\7v\XTp={lzPr +W4Z,8\91:> F( =E4dWG'h+P/l>x5Q[!6窨klynA5 ;Ui(D}f`{  H*S@LpA6,-QmQ|2#frkϮÂ"QEq9 Q0 F( ]AXА9; kͶUږTc"XZ^ɋaa]SJhmPHU@*`Tz؇ՙB5 F(`G 2-hRȫ`]s6kʢ]ěB vj*VcIt ]rم}Evl<~}:`Q@_WN$lt,"ըqdp݉m h;i6 #Ov Ҥ=Ȃ>7TRS;P)dx}Q0 FpDj =kgz!ŐyY>v \PhT2̀*J6꫔ѡc3<`Q0@ Z iAtc`Q0 A`Q0 Fq F`Q0 j{Q0 F(2 hRmImt܊~7z R\STSaG(` =@4S`'̾x#di+cs[BBNYJ~ h`! .D\zC8yG.*oy;tL *`Ǧ\E=`,pڳD &JzQ0 F(p@F| _3vi⿨h~#N9X 9m8-jh&%a.|, y!6 F(`@ѱVMA*$\];Wt`?Z-2 h~#96 r |LrU|w[Fm+;y(`4`+Au>Fu6Wt@XBFp怪n(H+<"Vvo$Xܳ2 F(v t>F+:y957 _t pǡaczۊ=(`D `e8F+ \PVko "| zC{@ܶB~Q0 F(H@Q0 F(C)i`Q0 F4ZmQ0 F(Ch= F(` @:>`Q0@Ѧچ-GF. 3jU#` AvW.F(& h.*bq3x"3LR@O&l2zu(U3 Q0  {xhBC[ \cy=Lj8W kBnrQP^ԁ,6bӂfVy׽.>ѱm^"fjB8CK6'oP$oJ龄M听"*Y\I;l[:4q{$~qXv /Iu]G:! r1M3jAW~FWAOʀzn)܌yuFL {Y5pygIt+"9ڋ;8QD3*Q_$x 9ɛ$@˻j8 Q0  Z$Wyx`uXǠ6|ƜnDܫA΍"<7Sx{YHt0V"5*ɋDZ\2w8 Q0 q4^A~r =E\YnƼ5Zz/ ւu_[LL5 UtȦaV@|ªku(׷ ڻjDz! Q0 k `Ud^C^ 頁WQC;.|1JM͘Ww Kj#i0eu(I&h~ 6Ϣ\r8nU ]B.`]5Ժ΅(C ÈG^u8%VCCxl; F(42R'7B@6gSG; F( F/`Q0 3G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 Nzwq8=d@ŸZRbzqiix4ߍ?x9`0@/  hRm3y*#ۋ FL [=HB9U/ܧ#1?Qsu]Akēe&@"rMCEhs{PQ^PZ QZF`&j^?Πi):@vAv l X''` ,<Đ@PO`[Ӄ 5a,}F#EݮcBcc ٙe\SͳҰ`? A1C^a8ƺhNMR؋;Qx Ocӷxޅ?9^4_*W[-R{J2PC(y۔BT8X6_?o&5 yu\eO, R__O ;+aW%_l@> ƫ0\&|QcGZuR)@+ZBm8.FPC\| eU40 ߉pkbx$vd{lyHD`kA~G S#ݏn&(&V%8jF(#9a-c UX|a)$wx"~ oڎT Nڸ !*=a ) 8i .'10A5L*v*FMDqU5 K]Cߡ`1"8ᦓp$v@A{@C6=ՇTsj hj܌4؂j&HRd7w%P GaLQLJLK Lv#=D's@#W4(T͞ _?>Vk0 KtF ZHk10`ĥA5Hd b1:BDnOo4p]2~yk&h:j,ĊwX+D_C=P}QT}X<R%D9ي;5X#}`P`V *0f ~B36~t3qF1*1QUÌ>,AM~# h5’8x <^o2V[4p%>#=#BDɫ}sA54Hd J^lb B AF~,[RkL̓5$vӍn#'a 4=MeIFx;ql,KG(Vzv1Q0 (4`Q0 (`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Cа_.fݯi.88cQ0 F(@çVb;<^+nbԯaE]{{]EGS(`4lvUTWv\x ϙϹ+>9Py.;&MwD͒Q0 F(r@å~zrGXTJ+ |>;UX^#0 '屣\=S=jD}U@Ů]~|<0GM ؀]u 4-v%@c`Q0 (Bꅻ *ǻjVε-g3{vU:Cj*c*LzvR(djգ&t{e*MVcZd_sf/Bz{n\5obdb?@3<#t|r@ jyduvA)d50@A<7x\T kd%iZ]:'G( tvI2 HN98`PhpSG[<]謹"XRTag1gdb1wü]Q@Q0 Ft 5Dar4F( h= F(X+JREe쬰ڝ5 F9 FQ0 F .G(lQ@`!?ciI ?~Gg4l@ |uZ5KG( :/!^/VF bdbFQ@!QmUeL:^ 2 F(`P W@. > tV GL辐}gԂ!J]+FV۝"Q0 @ne!~vMaQ0 H4mhO 'O f:[r_+FvvAfHWvD&kE/o ւSd/`=t9t6j{r@ U!#!dXr8>d>xTiiwQ` G!/֔]; F9 @]u9G ~K R}] 5D d|Q@"D0 F@ j[)a, 2r.o$ 2 n{Yv&R$JMv`Q0 4$!w@A#UqPyY(+FA棁v" cVn`L`Q0 F@ 1Ά߯ F8lFvى$صσU$ g9,Qr%h< F `DJ&й0J=F(]~Q0 HĈgٳg)!G 45^e; FI GwOҹmQG( iu(ya@V Q0 F(G{`Q0 j{1 Fh^`G{`Q0 j{1 Fh^`G{`Q0 j{1 Fh^`G{`Q0 j{1 Fh^`G{`Q0 j{`z(9JG( U"t v^0 Fhl@Q0 F(`G(`!hLb9Wi~nBa5:xD(`Ph=L9b;<^+nbkm *s4W@%0ӳ& `Q@{@,A0 F(44Zm @Űj u C n:h׫9xbAӱ'a1M G޹YQ{U%I >11 F(h mŬSA z<ҷCL kx] 1G5ivLz+x56` GA:(k:`#ψz6ü֍'Xpưg[x#bQ0 h=`v x3dV J($YЪ.p *UGuhPAApvqe\A?Fk4H1.oNc :l;1 F(h*ыF(`Ph= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch= F(` @`Լe4sۣ`Q@@8/æ]oQ0 F@VóF+z6闌 ]{/bkQ0 Foe 8..37>@ыG/`h=`b޷2lk2$A5(qAs^=z(n F큪i}6˰q߮ -WqjmBۣ`Q@%@޷0.{6UIZzvaыG(@޷2lk&ipQkP?z(`h=@m ۵-5tܠ6AoQ0 F@VVomt4F(@E($mVۣ`G( h(Q0  A`ht p`M۔ceQ0 Fq F ^\MeҨM۔GTt`L@,A0l𠋫#_\ͨ1UAi[mAAKϮ3hZأ`@7v5Έl@׻QoP{q5v^&zMaFQ0 Fj{:خ:8qV$@5' j_&vMۨa{|(`0(`Q0d@Vۣ`Q0 F4z)P`h= F(` @(`Q0d@Vۃm=Խlzc7^j|hޭuT*it6g_A:lSnh |Ah62ıЃOf)uڽi9$t(},_>z^( h=pme Y r&{Nڽ{Xn&:=oٷF6 sT̙ztR@I#%T6u` @ڴoX`&n'8sH o\=oNAZ6OTam;ְڣׁQ0@VۃmLU(u99KM9t{8 [jPX6Umw:Q0  j{۞:\Ii 7vC")BZIF(4ZmPmW}$$h9u6$NK{CGȍݐ g@jH=Z{:Q0 j{m߷ A2l1]#N=͡#nH nasv7 nnI|hm!s6 |A#mQ@*(sPv}=}I-sF-jmKG(Cŝ@c:ֳ'$^X> F(Ch=X.iFjm(&лӝد7^!q$^X> F(C}t ub1 F4 Mɉ7 F(Cŝ`p: ۳'0? F(Ch= Yh0Q0 -AQ0 F(`G(`!hۣ`Q0 j{վDWq޺MMKG(`h=Bҭۣ`Q0 j{HwQcawK#Ƽ&nBWkQ0 F(t4Zm@!jo$|_̀ b,6-wu#ݺ j @mrU69د`Q@'@_V qY) )]ڢȘڑDAǃ_G7!i$f'i͙9]5 F( F{Ƽ:XE8n݆ wc3KG(`P h$olU~tUlh4JN.@QpF(`h=˪ ^ aaYnFqe&CqMWbQ0 F(4Zmze͂B̓  j o.~m(`:o`vQ0 Fs(mQ0 F(Ch= F(` @(`Q0d@Vۣ`Q0 F4ZmQ0 F(Ch=lҽ"T<[;A~u cb@}Q@j{0HMT@g9؄@:MM Z%X!h=#PB=nt3 ?z> F(EmƀtN ۹@;yL;>Ws0`4@v_l9az}P]9U ;S/޽{!I3K'0(rߑ7 #lw#";'r `ϙ2>'`L:m`3=LqϠ|bK ,A瘂Ēk`6hב lwc 5pY3]{;fdg;7"nvY{ 013`h@3q 6R]`QQ$ $;E"Q%`#w WAvn  4 Lcf;HyF 6[@'ڣ`@W 6֊ .{O06hVx]cIׇcp.&f;lI'{`u9 (`sq5k1:r{~ ]pco2]gJ]{ €<ۡk0 Tk:`a h @:m`FA!c4QA3Ω\ z7h` Gx99z86n+Haa3(M&CCo8@ wڣ`@u \ٻt(:W`3Lx{h&dc66ga@Mv86pV A2د3'vH n|azM3u`oۅ]=IA{3iQ0Q0 H4]ߤRٜQ@a=|e4F" 20B6ZϾUj3 (g`D$+hk4F(@`h`Q0 ѹQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`G(`!h`Q0 j{Q0 F(2 FQ0 F(`'JdIENDB`PK8JJPK DOEBPS/img/states.pngiTPNG  IHDRX44 pHYs   IDATxy\LmfZ=$*BFNcOd}[QǒH E"JҾMLO3G;s9=|$I@(BE:GPS[[o>??GWX`CCC;ׯ_wwwk,--߿! T̞=ʕ+<Ԍٳ' P00y[nJ.]"##Az"Lii)a':QQQӂ2+++!0"{GD }}KKK$0"?s… I`D$666kyΆ ޾}˽'!!];/~;vlDDSWW.gNOO |@5aCMM-'''*****JRRrÆ yyyr+Wt-;; >}hkk3 QQQ9&>>/_TQQɡ+++2oݻ?$$$ﯧgddD0III{쉌2dX,Bh޽7ncܶ_.00ѱΜ䴴D11+V8;;A#B4c wwWrӧ/VjjjjjjÇ$$$>|^h<<|hddP/_]eȑ߿UWWi 6{gkggX#222<<<ϟ_^7)) ߁qѾ~jaaf͚e˖Aa碨HSS͛cǎr]bիWS|)Smɵ BHTT4>>ŋ+agaʕ>>> L~~CCC_XXHC'/_˃4h3`Ђ ѣǑ#GO0n:kk={(3w\%%%OOO0X,ѣz)?~ШQ#B!GOO`xyy9::(}(PWWTTThwwZooovr ǃPA ?SP__Bee?E($;ZZZE(<|]II ;ݺu9PH9lii)`L&trBg  0 RWW9riii ׯ_?}}} deewUXXRE(xx'''K. qر޽{/XѲKSS +P!NnnT̟?ťُ把 6!:(B@aٲ 0rH___Y]]G!QPPreeeImi &@ K.=z(ȁ~?@@g <<޽{sAaKXCee:d/^ܹݻ 3P\\ܖ3[Flc_<$&&BFp̙.] E( 0 55,ƍ9$I0vUZZ @ @pႅ_TNN]N;|p2)S01zh |TUU-YDKKkʕ8|;}$ #B߿+>{ѣG'N455h{UUUlׯ޽{'O.g^bʕ+srrBC(MA;++ӧOȏ^^^655UTTg$Ir׮]111 8{AxW111Ђ0/_pGs\\\{]%22+¸ʾ}*++ݻO>]vaǓ^[[{ϟ?ʕo޼ٲeUVZեK Ĝ9s͛7ZZZ***466>T^jB v۷'NȽᤥ{.)))--(77WMMmŊ֠Av$cǎQm޼YTTt۶m555vt:]FF&11q۶mRRRV)--qk׮͘1`嶶! pBZZ].#F4]ӧ'OwyE6 SAdyyyuu=&FSPP4iܹs-qғ'OB/K I{ժݽmٲyj)))__ߍ7*((dff"~cƌ8qf/Xgɡh4m$jjj999bbbfffݣ4MLL,,,LOO@E8pرc9NHHրYYِkvZGDDܹs}qtt 3fL``p4(w## . : 5kBH]]]RR'ҥӧO /D߾}tpЩSphV_`t !4cƌk׮᝼'33s޼y/^/lԴ ss333MMM!)!BIIɫWΞ=F[g2e Ixϕ+WFB8 Bb58C[0i4ZDDBg5fffk֬i|I?}zrr2BH[[ݻ-‘Nlv[.]^^ommݣGjgۃ+Ô)SL|rBHEE"~ vLLLHHH^/^۷Duu5VTTTTTTXXXPPCee%Q5kݻ+<Dl` @˗/{WUTTRRRFU]]]ZZ^8qӧkjj`2!)))999PZZqPPB.//ӳ׭b<Ǐxw :377?@톿###'OۧOj{, PYYٲe˶l"!!!!!q]jFKQQQAAHTTGUUUگ^622;t?Yl٠Aυ]8~ϯ_.V}||qųk?VUUԔoڴN3gfuuuUUUUUUuuu8#uƍ-[ <8+++555 _qԩ 6L2VAvvnݺuΝ8޳ͪnvޭݿ?Bgm8}V' hhh:ujҥVRPP䔚@䔐0gΜ˗/CS2Bw׮]Q!_PSS3dȐwvf-9tP~~ nܸ]oQUUni Ppuu3gI:7k~Schm b| PӧOSRRvt1Q__"''wSSS?PYY9p@/ b"9Pڵk]\\-֫W/!HUXRR"##l1X@۷z555XXX((I&5[011!K~2>;E$$$ ё^ԩSJJJNNNVZb/Sŋ۷ Ёw@f͚U suuuss]t$...;;-Peeeemm @$$$@Z<[yyyK_]v (++I%%%]\\[Qѣ?dddژzc"'88XGGuq5edd.\rJ @DVk߿5j`3taaa-94ūW@@ ..^[[ rnݺ"x"44,&Lz*EEEcM-pS;J/1˗/ Cp8 y(ByΝ;|r/hhhഈ Ch)&܀"vرvZ/Dt9­[OBYYYC$B:q bjܹshDEEY,^xrsssP@TVVpE#==t \(͒գGAs!T?]1ʙ/.((mP&77UU՜Ёos ޹Fx񢒒R^|mAAܸq^]]ݙ3g:ԾWWQQիs U2(r: CCôVG,,,lv'5nTD47KNN4/MÛħOjjj(H rrr`ypss۷o_X,ggg tuu+**/_,] ;;=˗/i4Z~uIa͛666K,A%&&l++ӧ޼y$ɱcۏ7>I,,,lP!888_trr>}ӭrss\񖖖ԅ999xnnn[YY%&&6(lW_pϛ(hee---[n^zejj{ [[ۓ'O ^~}ԨQW?'+<իW$Ijii}ד'O&I˗+::Aoذ$w͜9$&~N:G\=55-\^^.//oqqq9z(O6h&P||~H&\nn.5 1[˗/o߾uvvǬ-))1bʭ[xbccsi_k!UUU 8[ BGJ2 !))ImP!}k׮qē*** I[ڝRJM$qӧOoܸPzzIV^M"994&iiixsN? x6 >yْA5̷%&&&6[811ɓ'j/*lҥKA;w.''gРAA_t !i&ʀpРA999ׯ_ݘ1cF8p IJD M6!N8DXCv|rF~{?p~c:N%"_p={ pt:BڢebbltU_TUUyعs#GY}BII S<|={ýgرԊQCq{V_]Ѓͭ#""ںu#GVZof)**b0}0̤$ SKK d"$%%#""񬀖.۷ݻTWW㝕T5_~֭۷oBÇp S4k,WWצl 4/^XTT4|POXtΝ;JKK ܹsmmmABffk˗/NNN،cƌa08ƍw܉G8Zڵk9r1c:t-Z7݋ھ}ƍWZ|rhѢu!СC#'y5jݻwmll:(jjj\]] (Ÿ |+bO4IFFNcG{'3/ٓ{J(<ؠABNNNT{M4չ!dddlvRRV23I=qک=seE+M1c ۷oZZ5qp~n޽{(4P'( @KK^„< (cڴi~~~i;9c9PZZot"...޸$p8૪pooܹ>>>њ;)SYճ"""~$IN2Z71b9s̶mZ ={+NgQQQAAAgϞm [[ۼ<6M IDAT---fgggbbR\\,..PTT^033300p͚5SNe0/u(NB/_lQۚOOϭ[vܜoIII0`@hhhnZT|ˎ;ثW[n5k#:::7oaX?~>.eggwիyyy8˗/s4:СCd犊0#(Žd„ /_n"655 ?n///Pttw9|p+&''wޝr>J__'6RUU4fK󣢢$$$(?͙31C%I-qm¨1c5"(ŽdŊ8q_~;v`XUUU > abbyfOO@"98p1~fƌs9}ӧ555MLL***uRyn?|9|}6EEEOe^TTTرcϟVęL&;11ybŊ'NTTTTVV D쒒33ڐ^۷o+W~94mԨQx;==ҥK7oޤS122{.wd%hі'OF{n„ gϞ%I ŋ,+''GFFr|(BYvmhhׯ_-'q;]!qF{{{ ?T=QQѠ8.'pss@B\=bw_WW5PExyy_b޽1P߿7[۷oϞ=sqq9߿֭[II BHUU555!++?ywJ\X[[?믿󭬬̈́4TS={ A7]J82kddKX:ԿӧOϟ??''GCC!bھxmGC&TQQYTTdll\\\\]]=l0999))6*L:5==̙Ԏ`,/qM3gδo]"qqqnxklxUUUb6Trvv~@:-...H#|uڵo߾ƍ!n"V^~=K4B^^^BBPBBBRRRJJA CBBBUU{] ĽgѢEԞKKK4/B֭[f:w1tqqq1c8۷Ԁ"ړ'OΝ;WWWE:IIIȑ#GѿN!:N9$")))22MrrssItrrzI[n} '?C'OM65;*V?M/_&ߕŋXwwfs G4hwOP@m۶!C,_<::TUUmbRDDFq/M2OpOPuuux0B(+++//X_r8RڻwoFt:ڿ?۷oYYYL&sxһLVVbtBP|ʌ3N<9z޽{/^ۻZSSb Bׯ_p8 짥۷{nIIׯ_#544DDDǑ"hS%M`06nH?ݠf+++O$%%Ld2whղ޽{M8W)))Đ$ya l c2مU!HBM:uUZZpPSb3@X)..}6s}ioh4YYܸ9sRիW^Q{3 @RR244 I'&&~ /޽ݻwCCCv޽k.))7o~ѣ_]>%IRNNϣ;/PXXwxxիW.] -3w޽"m6|555AJJJZbō7xo߾Ǐ_p!>dddL8hݾ}@_x񢳳se͛W\\L)W^98804A^pAZZr8 | ^󓖖\xqӏVUU=z);vlϞ=ӧϹs眝edd1Iz̎;" XXX:uRajԼpǏ pB؞W띝[nQG"99!C<}TCC`X:C-$ህ sέg0xOZZکSZk,--, :|¢EUttt={v-uuz!444>>ֶEܽ{&fBu;v<{O> ]|944ϏJ SSRRf3P(ꪪ*C.//qguuuMdRRR:vػwN>ŋ?|7̙3rHoH777AS|ģGN>X BUUOP}%=yK9}F +._ rhcbCtF6mgg,I[ˡ?CFFȁ*$ .]Ժ0qdivvv ^Xn E/#!NzC|}}Ν tZNzyP@y͋/?t1:+?w!Gϟ@0QPPi[T0U/(ŽgK,i6D=}&[VVlTnӧO{ vUSSQw@- >>>++k̙͖444| 7R~'!oٲzб wh<Y[[[ .NKK+--?~6l9s& />|5t!֭[FFF]vm]K. :T[[-0gΜ?c̘1AҵkW*"(ByΟ?ڢ*7otww_~ %zaeee||ON81qD+ف%suֵTn߾A__wJJJ<ѡCڵ***kpBs !B?~(,,iQ-]]۷o^~L TRRrڵm۶m˖- hAFFF=w#WUU}UZZ{lDuUppRQQ!Iiaзo{I~򥕕UtttxxxcED@JNp8{%*++1cƌٳg7Ln|d~aҥQQQ<]:ӧOϛ7,Kȑ#Gb3D$-,,FI1cttt H244ѱĽBRR$Icc㰰0ccc$CBB,,,?޻wC:::r522(**"I _W=VVV^ފO>m{a ܦaaagɒ% ^ѣGuu5A8v؄ h4OnnNRRAX;"-[FŋP|$IGG;wRRR Ϛ5k<8v '9, lْ7tП߿'O@;z&{ڑxb ͱ.:ucBӦM֭BhرTfrmm!C,ZݻwtuuqG6JHH30"&1&LxM=zǏ:ŋ &xa׮]{7n~]7޽{T!d>@QQO>uҥRLLLEEWҥ 0%KSK>A"())={RFmmmѱ733iw؁7x rFn===k׮۷o*a^E4il֘T'DGG/\N8LMM94͏?xIPQQѯ_? B?sfΜl2&>:uuu /27ٳ 6<~sx̙3]D7nܸqt:}&%%ݼys֭yyyiii-WPy>|Xn… ϟo߾m]*___Y*))idd6leocQ6 GG7n5o.URRmllݻG:~ʕ+B!!!#F◗իǏoiim۶˗#˹ cǎX!ڵ ٳ_hwtUU &q@ 4ﹽX,tddܹs)E]&::֭[[nUVVVVVÙ1>|?~ZwѬ,III*ƧO_<0`40lذbyyHIIM>zݟ>}?7 $I>{W [-,,p<${)SHLHHh`iBEHrppV\ӜP$pf;ӹ⍀ggg|իW4ӯ6޿7#6(;\vm'N^f rLLEII IIIIF q--aÆ$)..ZHHȔ)Sihh6uRRRJeaagddo޸{DFFBJ`۶m[n|MMɓ[T8y򤩩)ʓ'OlmmqqD(""c/988h4QQQlWRTTx Ewh46mׯ_KJJf̘]ի/:uiӦ߿_DD ׋4PzcWv  x$++KSSNy {SN 41!!aчy&B>}ӣP5_޷oNrrr5k BHKKÇUV}ݻw[nxⅮnxxxAAŋGDdzz:օP2e<#۷o2d͛+**FLLlҥݻwౖۖ@t6]__*&N?~5j=zT\\Ӡ/_~zEEń}qR\!DETWWXU„3gxt{b⴦ֶÇT)++ I?g̘GEEZ_~۷oȠv^^^3f6666'OTVVШؿ֭[---Bܾ}{~~~FFƝ;wB/_3gu|jI`׮]Q\i۶mUUU7n3Bhٛ7o ՀDqq1vm~#%%%++{ϟC[ly䉢".=tPqqqߛ-vڵ=zPcxDmm-h¬ժU! SN nQjl CQ[[+**xO6~:ecFW>xٳ-|(((P3~˗޽/;|ԩLLL|||ZC3Ο?OhѢ#Gx!33 fjB w54hp ><;;{Ϟ=gφ2|}}㏪*B\ 5B!DzzzTfi444{qС;w\|ZPȘ8qbLLS```'ŋ322(i-F]]M]p6Ǐvf!DDD Ø1cŋ],W\@_ӫW͛7 i4p88Fӵ?GUVVVWWc111:/))i;v\%3g\~}aqqqtttAA?&I666jjjS]]J\\ܴi~6yy/_>|pƍX]˿x$)++KӹY,ֻw\\\ollbB6lXti޽NPhh()u+Zf͕+W֮]{A"ĠA꒒7,X@AAaԨQ|ɗ$]veffFFFhUȮ444SRRJKKKKKvmj l6ѣG|05x{{Y٠iii:::!jES.T-IIIjFgiZ]QLL"V̼BЀpצY~M]?ѻRq9Nt%%%tzZZZrrUٳg_r$q$%%kjjZd2ZWWgnngϞG&$$}=!!!EEESLy&*CC<{pHqqqIII TUUsrrlv񋒒0ܺu) @詫FL19s,--Ν #B8p ވڲe/1YR???n-  mmm%%XYYٖph4LeeǏ:C{!}ȑ#={Auy2]d2;jjjʨ”+RkRIIIP/..H5p`jYYݻwޗ.]:tPbbK:W'ЩغuZ~||+W.(B&77ɩ1cƝ;w=QQaÆ=zHNN͛7QQQ֭+))?~WX,^;ą߿Z=Æ {}xx8`ٯ_ݻǍsuaUUﯿ:tڵk`ǎ˖-c0fffRRRTHuqvvnE P@Ӊ(򥥥<ڡtǏ!!C̚5+$$dر0ZDDDIIϢ6lؿ?UQQ'|B(""ѣG99988)SO~ڵ֙͞={ٺ/^ GHOO޴i; (B~ .|捁Ax7kz򥖖2_ZZsHII;w!6K33gƅL&{n^^ʇ F-`,G۷X oBO:ݻ;wܲe w*C$'""9ׯ_gʢ9EOLL woDյ饾S[[{=ssfs!))?n8^N>k֬X$Phشi#Ç-++suu}t:]MM͛oWA."999ƍ0`x4DGG3 p`4OE"|@)//0`qrrrLSj4`>O8;;>|l!!!999 :## |p8Gio,>y CR_d3 K0aB~~>!$11PVRZZϟUib[[ۈ-[ZVNMLOxأGⓀ ]T ᡡiDB_Bz}ll,tܼy3!RT* Y?{+t޽k:bYvРA*lz8::vZ>}6o4 TݻgP(ܺu}PP˲jzԨQ  ;eggBy<ޒ%K䔗ߟX0 ˥f3 3j(5bBHFF)))ӦMrPBP(x似"jaSS9iaڴi->>>>&&fذalhh^q㆛GII o555577D۰a4/@~JJi!!!! 5jTKK\.7ȑ#Zd111 7oljj4d={g=={|a{G) Tz94eKKK׮] X{IẌ́]`0xyy ƒ;g>4 .˲v1cư,{Q(s@ {ƥK"̦a:RU\\<}tS9SE{~UJ/B%-ffy|(ˡ Bn߾#F7772cc!C(ʑ#GBNg# ]4<x;EddÇ-7+hZ777,[^^PYYPYYiڋeGUWWkZ3}{uuu{Z{ݻ5mGm;yjpu? +SZ$D".ca$ Nob m6az}dd?o ch'OLQ*pO]3MJJڵkWAAѣ͛vǏC~Ag}% E"D:J4ų;vl{G( B*=zXa\p.A~iEIǢ"Xm޼a;Je}`0t %10VCWBDXJJJL&dBxj4t׮]֟1 ,@xDDD`>kؿ?d yJd&;֬Y3j(V lK S(vvvNa?)Cmii6l@ 'O 5 phʔ)Æ kll9sСCaPJMP z…ٳg;88Я@PCq;M1`R9vX _֬Yvg@V_r2vAX7nu/))ݻw{aeAfNNN =zB4͝;w pݏ?n PVVֽ{///ڝRWWP(\\\ ?Hh4w޵g˘jzrMN!aP[[[(LۈD"DC )Sl޼Y$999|̆h{^f,XT'L?)))d=gΜ ~~~Ϭ`~IEx)Sdffv;o* FZ  }bbccD+VB>VBHnݠj*'X?DtttkkC e٥ؿO8^Pg __޽_g:t4֭[ !/6k\__^g֬Y{y3&0bxΜ9YYYqwwwuu:u*׉S#T*( ̟??88="͝EK&C. ;wI 9IDAT%ITTԔ)Sd2م RSS;foo?c ??tRRR ommttxc t>"#ׯ_z(BnݺdɒzѣnJJJ"/22gϞ zw}F#02ٳB3f <drE-mmm###@M]/] )8{DDDjj*˥U*UEEFjzyB Ccc !7oG|#Ftss:uꋽEEEiiiT +-]f͋z1&+**dѢE6m2dj4kZ[[[[[~-)))66-]t„ zs"x |$AE#'''00`0_9EIx<ށԉf{Y999 @XF1|!L hBK.͞=߻wN`⥥6l u`LNN)40-zBHBB† H$`r666",jgW\ "Mcgg߾;!!!yyy#jΝ,* Fp~TSNApVP(ۋZV(Z>Zp'RZ?zS3uuuUɓ'O>}5 APX~͚5k>CT *r:Nt:xh4ۗ3U*ljQQQQQQpT*iG(9slNyBGBHff;s}ᮧ ~/a.KKK˂ zy>}ѣGiiiuiZ/ x!_~eccŋϞ={_/ݻwݻgZG!bcǎm \Ya[V5 2* 4Jrfa VΥtj*$@40)i;[.]AWz6y:X,b RO?Ay_5˲xAE< "̙3})--=p@BB޽{%==.222!)))#G bb޹sgΜ9=8@KZHOO .JT-+;#4z# 曐һwo@,,BP(ӥ)wM(9rE)PxM7jZNkƍ׫Wo&88|R3YVGEE=zQ:V]]!O>IHH[ *B䗆Pqc+W[hll|won}ccٳwxAE2 4={h=k.77wĉj?~e W*ݻfx-W\9~xqquuݴiS'Oz}dd$]/TM6M6Q_SA}m۷Ǐ< FR8zhAE"Nja]vBz}ttttttkkJ޽;˲eY]TTDiiiaYrS(J[[|:D/Ɏ?n,j MAP"fذa?! YRRү_?ބ,6ixkJEctХ---xrBiwhƌwAF_bcYYj]]]<]]]MC1 ӭ[7BQ[[A.fxٳg~~>bu!ÁŖh|waCaYr길7xcʕxAE<#'OܹsgϞ=mwYjueeeqq{ + *ByQ*yyymcpwMlllÇAT ҅@gA! "DAT AAP" *BAAE  ^hğIENDB`PKP;ưiiPK DOEBPS/img/exampleopjavadoc.png .PNG  IHDR@sRGBbKGD pHYs  tIME:tEXtCommentCreated with GIMPW ,IDATxHNϭR"(I[SXDK=4ЃG/襇{ i>Ѫ"(nhvg6}v~a2;?;{?M4M,پॸK.:U7/"P/(dB,ndq͇ݢj8he痫ZGm> ("".=vz͇W6^0\4OXѺ*m7En eµ o֢y/=vZp2dס}_%f\dŇ+:Ϯsa{Y;M-kPP%sm+|n{Qvu1+ ٺ!,|.! %џ,d@B,Y@! Y d! B, d@,Y! B d@B,Y@m 7n~f]Їad4>k1NiG~z[ d^DDF|oϿ:~߻4& ʼ>Bi`{WC~S\ey Bv+ѽ=J}޻,M*ݪygשhP0?] О;6~h(L]4}QB~ dW~:[,@Uվ'r%: ӯMBpTBv^Ԥ"\WC@_NjOlӪ[4={,[7ݠpUEE]W. ,Ԋ-;jMiݾw }p?8i*1^Ujռ_𔟾Mߧ6 y !U0h,٭ڶUV})6 da#aT 9WJJ+ʢ+}˦juŀeciAYw. bPɲ]v΅ּ!@>O?F!UP4|{?"j.M&Ff6dZvרu-[ի:nhe\@O+ꃶh:}6ٶ~eqx a[C dYcJf_X|'5m_)T+>BMy:k_"\bY4M8{lFD={VK =@,Y! B d@B,Y@Cv? &i>k*Y@! Y! B d@B,YSU3$Ir۸gqm$IlT%g6!6q}mnU5+ٲ7c6-_W5eYUUg-ۦoκRβJYWedz,fӶzLKޕN%Oz3;lE|M٦]lkreXgO[S.S֝Va7|37.e}~_n[Czl[unC U۬OxX/[6uMwdUZQԽ肚7ˢSe)Ulo^TlxQ-E2QՕM7}|gBV@;B, d@i msMlߦ5y׵~u5]>zǽͱ{ouF!6-sʎߐ8:q_Cj LܗbuU,Ahm[UdM"՝~ꪻ]69~zޱk\`m+hu.uΐlf}tq_o]կ[Ҥ4=Yۮ in]tWuu_1j}*l2kˬeں5o(]MnJW}5i:ϣshwvJzsˮ;պm\|mof?>&N>I4dsom~vaEvJWC:.u!ʾ@Wq@~ʭ͇&EwvC#d󧲺dH~Pt.smvG{eq_o~翧6u^mmU(ud*Ħݶ,O4M{1UU_\ӮA([gݟ(隰8M/:Ф,keplmoi5&M*^6}K.A; :Nh5P%jOhzA- ,Y@! Y d! B,p[޸q#0z>܅ &H/<t1lSu [4 drkۓ? Y/! 0=<$H#ݪq!K!DmVY aiDrPI֌Yz5Sd?Nl@[NgU`D&[4 d5d'q5fD$ǿ{񗏾X,=Lir2p#9[>xDO[_n@қ,܎ȼeOٯǵOcOn[~<ą-?~s2 ly?q!K!;DDiFf!U61O#MgW޼7y=.>z_\yzܜN 珈 ݳ`_ dIv[[7$,N1'Ϗ*ޚڇqk͖ڇmh}IO^L&O1x2^GB|"_+֌Pҟ:L[5B^8mB^da鶍 d`8]L/xUl=?q,Y@! Y d! B6b_PIENDB`PKef PK DOEBPS/img/addplugin.png;PNG  IHDRT<sRGBbKGD pHYs  tIME7tEXtCommentCreated with GIMPWIDATHMOcUܾ PJ wH Ռƍ,iʍO` C4jLI Dv m;/x9dSYwN_O<89)!2Ŀ\@IpHW=@p>~@;]w_\!П:Tk&{{U \)!xIeOt|"pP$ X@>gnn8^΋淽dYR((|>RT O\FJmۤi۹Cah4J L:b'▖XEѠmƟ44M4H$&ccclmm100Ra&J)*V@ MӐR"<ݷ,˅8X˲4 mx_YAix~%.1yv]H$0Mߏ(+HQv^~̋IvsEtlVV~d}}MFGIRVUKHIWk}n'.j,/!BRus1R =/dT"0;;ikdJHV|{xueU~6.j^.VYY(J__z/oHI qzT|qힶʶ6q=*uѰyi+H-}:u:Vw.f25yߓZ!י&:5LmCc|N#l4Y~r69ɑUCXjFubZa҉BwjJtycFE֥˴޹p98#[k_?[%  ;M 6mmi:jAL4u~jMgުK3*+G95M,+6μd?[%:Rdc ڜ:2cX:>zr MwC3-e2UNc?]̞?Wm鳲A<:2>dten R5U㭜"*$!etWX(.XmsE,\BmCf{ _x)Kd[yât=ɺ;cʑlXQ |6!avv@?4/q3V`cV )1~]^IcW\=7К`#L\NPc>0ӴW2i"{/E]wʼnQ Uuï{]s/1!\5Uh;utͥbXty(1U:DkD5=Ekń硊(t:Je2"d$d2L&HW\qE\!?yw'Nl~Ʌ 2!Zy̡ȯY;K! `C؈`6@tk[n-_qD-􌪨XO[2k%]H<_"jږ|{{cBtUxD-jV[Ut:Tk$J]/y@I6Q~t ]@5t 5(4_M/Q|~wX2 ϣEjb|>szc[kc|i--&H1ZaSbϪ` %{ 5M$AP8ŪQ[LOAg: miFxJ޷y="ߣib@T<Vub꾕E&8k8ώ*ݐt*XiU^+?T{jRLHjiXVڬ"n2M;ic|T3H@Wrݺu~+왺JOk7,X;?]٦z8d2!K=>Z]{9QwN&NĄ7Û]jkSzjWGWUQ1a◹BopïK7S"J綦{Y]!:y#8ֳ A"mС㽽oeEd5_LݎAz ]@5t ]t͞2)+(KPv ?T8yXզ+UUAA#+Qӊ.LU=:93S9pBrfjg,2cАG15@׊!bKZz5l4sUzk#Tcp k6ש^M?(Sc.o)sHTymET*u֭S?444L<0#¨djjjr61?~0>PUUe|glss3k c l&`ݰ.q~B<5"yIlkV(\NEŪ:n\j&`9MmY{W>-MV[JM[mM5vԖ4풠!(r 1jkk{zz5+很qA e6 l=l+Qd4o'uvۓf6{DBy/MC=yde[;tuz 9Lc\~,xW+gUW5.GsÌ]]]~aCwHD:˫w5h8RgՅ}gϞOھǏޫ(**6>w.72)@ Ptmi6'Culqiڶmy9jUAl6{̙'|m#F.^?6L&˗+䇊=x(|OOoo\)ӯd;zmkgm|4s y;Om3G-_pwbZLcJ`yo. "gF5. ښmȋ( m]B3mI7߲͘] 7̛?gN>=J96>ĸk3.jbC7\x k51mjb|mO3tuu}mJqD-/m+nit:]:SL&>%ZHmw|K/"4wM˗ݿrܹsK fkaٳmHЏaΎd2YrW0Zr55W1zjy?ٿ?yX,M| [M->>]f|l@ { еf~}-2=ֶf@ ]t-Zr[gwl?_?{a |Ot _ XW K\>3/D@ 5(!^euN|?uQӵS&mi^P ʩ%-*~?5pǺ{45نԀ?x_UUUCL<χԂ(jZOj5uXWm9u6}ys~( e{j봦7-֚+&O9;8x~>4:V׬f7ϜY?7ܾ}D"|5H]ӹt9[nyW?p)g ,e>Z15 `ƚ4M@ x.m"~(kkk`O&ոAr5t ]@5@5t oϔԟߔ4N٬(ǎd2]]]jzDz ]3y+V;;;}s],\&h>L&=*~MxID_εJt?i8\כ݈W'U2X,v}5/U=NEGk%chԾt&Gc8{]2)D6]մF*̷%_j-n;e 6Jg TkbI32)sRMȄ/$[tQ{)ڹ:5az4.oy7֬59l:VfU=3VntW"׬i;j+\SkδHDeK3juwwX7Er+|Wż Fx嚞N!js[/ Ѽnq+KP$oji:]$GD_G.Gu_Ĉ8_=W漱թt˙ʤܜRNcu9 ڲ)~z`GD:{5ɓ/ʹs:5 Zx'}l{fTEͫ/ֆAh}aF э5(mPmޯN[f8g;uutکP [q{[q7z Ű;ѵpuÌ=>%St{a) 좹RZъMR߿رcdrԩxzϷ<{v٭G.~t}?^oS ZqNOOϴ'4cƅwܾ[ӦOORVފFE+wxHW`Ic.|Vxy3`b :jZs'曮}Ϝ9fK_Esmwm4eunk/c=yy^m{?pzݿj]fↁ@fWW׬Yd^SUUuqSꪯ/re--___#F[(-!r(7xcyxg޽׷̙ExM8믇C5q3[.?ByLkkQԩS5\]t ]@5t 5%;Й@ =p ](tոqκg,^ 3f/niU@)ctpeĹCMjb ;CxVV]]@¬kX`‚6^#lgɵȈ ]SFy*7L@MLm!KpJnɴ뮇kze k׼Դ+Լ;ow\Q oХ25mA5|@ktu{_u&.xS˲׿}C=_5ՂWMVez;7 d:iDžm6ka`K[zmj@ma>ru?]wEYUrZ^~:tP' Q %?ԩgjLL*f*— ,_c߸5m>\뚗/&#[O(XAset~(ᶂ[lCc.dG8^D ] -mjmFߍeV2 )r/3ܬjMCCp[VZt-BH<5!n3L#ML&kPBX۬jD %.&h! Zɇ*ǎ 7'|R /t 5(*ZZ~ G/0յ_t 5p_nW$־k0\3TGt)W1EA{ m]NP@ $.m"~(kkk8BHRn:CCCɓ׃"yQL&icǫ8 Y܌Zљlka30{ {- =oadX5(ʻ{W;v ]56kƍ/}ٳ]vٔ)SZf-zW٬PEE_ى2̕W^yԩsY;vkkk9`bQS3t[]Nz{{MwoEMwݚ5kIt TرcGMM͎;t+W듩a``>&PZ&… fϜ9#_È#zzzIt t-J9RsRsYxZeeeRq/uYB^07Tz`;v YꁽP,X5H('8Cyq.@)UQSeڴi$_r%:27Ң+H,O&8qb&a̘1~(@P__o5EQ+**Gu= j@0hhhwE ,x`~(~(L&3k֬_ӧE=z~Z]]ىt:NEI&d{t _t ]@5t 5/ IDATt Ay%kDX˛l?v ">&?oԫGU6@ HJ or]5P 7^PF+ɀ6 x$kkkkk0oIENDB`PK ! !PK DOEBPS/img/ate_pte_ext.gif1GIF89ap,  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiiqqquuuyyy}}}wH*\ȰÇ#JLxÃŋ3jȱǏ C^1ɓ(S\ɲ˗0cA͛8sAϟ@ Jт*-آҧPJJhҪC[81֯`Ê*Y-P۷phv.ʴk˷_uBVÈ!a9KLk {>/{&l1ӨSGݙ47T˞M5f֠ͻwgەqM8bm'+g%Oν썕k`ûB+V΂A Tx:H$h B6 فa 6ƒf߄U蠆 _^Ws*4:#_3֨o7@ʖ ^IDG)ӏA6 Zt-$@D TC pCK -NYtp@y]Ĥt6ݚĹC$@3P Е  $$$ g@.J Y穆!g;D9Pa0% {W"-ؐ{Qv8l$*i*d*V;@\++ IK-2JRz nc}+NɬU@Kze\P@/, b` ]Kg0lšjњk% 3p)P 3ZfLSN/A +\ap(GMp T+зzE¬$ò2,&t [9Km J#dxSe,( l6Ȅ;-]):s#9 Zi!y>Մjn, iCI*drӢ׮ioom d2hGߒsA/3 w/rq 䧏/LyhG-+`x*z L^Z0cqAhp`X>Bۉ,$,N0o,Ċ _(Ve4D lSDq*bT:)*Ll(JIT\$ pH2hLF6.Yʣ>  QbF:򑐌$'IJZ (G̮}TSr2[ejZ)DRzD - [ cIbp-}<Q4I@d&Z@nz2O쀝dЀ2o)A(t'JъZͨF7юNt(F(MJO+=`JӚڴirp LS:EM捧4A`nu,QXXͪV]P[ V1h BDVn^@IZ+׾[ةڀ%hE\p ,RYzVE|8ːЊ6}%i6+lc֨Hs[֪V!- 7]qw\6wW-t)޲M%vrXMz#Jo|Kߐn5~7'=o_ ̄ύn b\kp? O*`h!W,%ZT7 &nHGAFwar@KCw`UJ8`z@ xKߖ59OYSX.kpAȺz& X>C;֡,Ej}i`3GZ^'Cœ_ X_T*4Բb~#by}+)uPVIkfd9 \$.]/Bη~6)Amgw'"&1fOc`-UVuo}`j ˮus=^o;҇~\!f{߻hQ2wxћyk,{؟#ؚ"ϼRp@b#I%U{($1dκ'{/2AƺT'?t|_J dk 42߾Qr*]-ܔ<~F~vF6w(Vflb,XxD!Y~i.7~ 1q(R.~gy_:a0&dURDqzAWdU75h65q/jfQ!NbQ5Q9%9x6 yyoAc'RHTH'nvxx.0=Xq8s8Epxo+AqeMEA-3@/ևщ$(Py_ׂlxx @eoh/h8W8+K$)@Q{ϱ!`(hwwhz}vÍ1!}E1.]F(o8/n*nf*(r$&*C$)R(HW*YA}1(,'r'.̒2+:s)%gZ1*,X+6,&jxё񑥵`"ų&2(xja02y/qc,p1"k7X"(bX a 1!O3[2:CPhg 70i( |)%W2JYn \ 3ė3`WY 6a6/&6ѕW1F#69t R{Ea&"~$ÙI WBly:&4~7h(3/^%3hwٖ9X&!2*I($QUy:&"6(9,:#2Y0ܩ2Ey.)|h)(Q/eco:- q_G/Gi qə\ykɑ/'2x5G`(-I,qr<i-cr%3\w:ءI22&R)r%& Q7%f 'eh5-Qo.h ZU+Ւ.S.`&ps)؟:9ZȸTB296)"R;B}V% Pcnhnb`}j610:4,6kZaKa$ ~򹆩zfB#)78cChֈr kE⠱ ȣA3i,G2"|99 %,@ni"~ժ:-:D{fc<.3z-Uph%5*"цpBe~6()Z9W6PDjes+/y(+`,Dy}%;ƨwlD30( '`.] -zط|}V. V (3YjA|n6htYNZjZakIID[fr,J)d'UK}*';͉ʌ{`ϲ*idlr1cC-6^fyEGIPjk CjJR8)f_˂Z;Zb)# Q9ѵ AgTYPz46.ʠ -26kgfb'.7}ɯתć~(z<0&60 dzB^a4&2ce;-r<*B > Rs XrZzzl†$@*(2̓1cG/B+â:W `1 =c#^e`(Kx:/WayC{i.a;:1[-DĭDS<8ډY'~IskwJ2l|G h^UF!utl뽬X1èxc`<)9ex)8Yx7`Q)o Ŝ\Ş$:oJi_sʶb4"RƼȜk!&˛|ci)_)׹̷8|)8(&C(sSˏ99 utjX :G$-h.*y$3#khZhQ,13$CfdrI‹Lqi++K+kü4ǫӰ+hŒ6m8;M3==lڵjrFӪI]@rDQa!fFQm;\)mq<-pa} 9C+k}`10/bû␼8B;g|;70-z*ƻmd٪{um.\*20 Ӫچ٫&(މ$N&ލ5V8:<>zZ4^سƬEރgXs )CmKѣ5KS8Qne'NYn柌WqM|~^Q e_.I4po`S M烎5⚾<`N# R+U갾A?"}\".\nr-^*7žv^ g%oq슗ΞC>~2nd'NOE^G^~v#M _ t^/I $ "?$_I#7*,.02?4_68:<>4>D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_0?o`%P%??_|&h\*HTV. Dq `U1+`OuB1KʿO'G4SQfrQҿ/N#OD%rQ[/or&,R2@^a0@ 9D B-^ĘQF=~RH%MDу*jE6`@b4C t1M9`2 ^ptU ~VX`W|YV̋ i\32ҝ&́H\dJv .h#^k**`vVfΝ=<3GI$vA$m-\>H`/ֻY;EW @as¾{f{+a'(~2U.S8ZZǟ_~0R )滨4x`(0莄^A.*29@6*j:qpx@`@+aB=k J++!<t Z2K-K/3L1l@cI4*R(:l!w/3=ZNl:E$CFwη0a`*PBr2'55OMT9U$Qm3pH/ykV|tZ 6(βf5EÕR֪Î;脝A`W/*ZmR]5ݔTUn@-XځPm"`s*܋ l)ы֓(hRgܵ4 $W8[px\4\<s 3=e9#v[Ud^M!rK5&9z(Z{Dd*/ *z=3dDgsjTqlЌz*LX`[&z6+=JUU(6 sKp.wIp ? m]nӾ @u YkELgea껣v-+T}'~Giw,៧#za|7{Uӧ|G귟nG槿T`@!0}5@jA EAHbt}'B;5L 8L 8!poS6r)1?Ė I"H+ˊ]nDTAcոF6эoc8G:9?1&> PGBҐD$"P<2qx{bG$ҐX0H1d(;Kb`>v0GED!bJ\ҕ_Z/ F@1.cz&&0LdR3g/-d^s#'g^TgasHf %;A>M:|3LIʉMOt]c SZ5$'xFR$=gt!i/yTAOej 7!BɢNCH&NA&d|+1kiLz$\j]Twb$BVjzUgEI!ˤE XQقOz] Zu#} ED XQM^,a.Vͭ2^\6}6{P8w3ֵ% f-7[,ץQxiwIn^ߋU!4IcBYwFfK:c}ez|+O^R+ x@b3#K zhelPL35 0(dv*! CP0 0#pךUndxCA0Ð&8R `{3.,bjȞ4Үd"BP@ &S%\QV@omZ&I7}g ZD0<_K7ӥ rFR?8 X atk}v&iG1=lbسC6YlR_9nGheڧfvj.k嚑Y/7& xZު9Wp[[wac-M~/xx5;}sԨU~VDL%\@Moe"O XSh'^:^slY @&HJ?|8 To =%nga- rȟMUv.߽={Xtso? ;o| w%>UyS{Ss]+軾z}dy~OWx^< +w6m._=OvW׍vWB|o_ZL 0 0ш(1+9` AX8V?S;` 3K X?[ۻh A(ܺ `ЋX 'h”\!./ B"$A1ܷ4s‡  ӑ Á7 o /bPCQGidy9,|FtGHIJKtĄ ,C[;H)S,TLXH8`1P;ê{fD F\tENA\<**`D$Ƒ2F#dEDdht-wi*ar!eF(qG*GCFXB~d x|pGBᑷ l$ =y Gpa S;( Y*0d ` Hך Hd DȐPwJ9 1L!XAD 'a,ZJ˸#N 8=-E˾K9$-=L#̼l9L0pŤ?+lPH#>ͬ+<&́(dD;r,=PT`ʘԿ K7Q0wVVl1WO9lbWxJt蠍łd(xWW']T(Xׯ )n@ׁ` i+.݊%iO|XЀ ˜XXXu* ]`٧ @լm>m H eFL $l[!Oͣ ?(gF xz Bꪌh$ B8x\ʋUcS#V x]sA%$2]][ߵW>mU͈ɥ0y^:@8NX(^^ܑ.^pR2 eұX_ r.&P 8\ L  <̎ }9 ְ]h0u v=LLnQ !7{Ex$o}FR )u_ aAT0 /y2@`_ҁy.! [(4FD a̮݉> }4ځ MT4R:7RCoS*VSڿ`ДCd8 "ڪb-I᧥ xY4>GNd阉 ' k\<S u^e^%~l9:ȥ èR`\(% Ϯ.S2ƈڒ``l@J(cl>L@ٳYm>(QqkÊbF8y)I1](h WR]`dbhn, C[+ RMɐ+5d0 > = sP,ǡw5\>of <j |3ԈjE=`Nl]$ 8_3r ӌ6ȅؘoJ/7TV 2' HjZgƁ c%csq)7!1)>[tY|hWM@9D)?r4 yf-i@(t{ aJnF!Bn~uXv ? RO0p W s: 5ocddYH. |r=V js_Gt` i *vS7jT_Z&)RHȘp튷x0C>R?ϕ >,h „ 2lp *ZxC"׳o=ӧx` K7nrEF^ZW : ޗuca7 b$ Dn%x/p")"-"18#1j]HPI8ӇcۈC*=eYTCYؑ"V%GM\N5FBѕ5gِ׽)DIR9'Gi%bgcAz(*(:hdjdn!ign >i`z***dPLp+++ Na~viuPCJ;-}rj;X"˗ˊBn{. `Fئݪg% 0/ <0|0 ,,x,Z;gk1FkJ)gf2%H/+d3gmތa;era}Am=3vJ 5lNS}aRaVsYZ.Xy]6Ji$=7u}7y7ߚa"=8.Bu)@A98K>9[~9u^",x桋>4:뭻U>;ƀz;ڮ;c-> dC+<;#\@|* lЉF_^jY@mܙ6j7o6O;d߇W),@G))tճ^3*1w sgMQeUscąG[uf5ǪU k|FО:V!ܤZSio᠝o]8 4Rgob?W5}RL:m skyNԜ֨9e\? :ۡδUy޹͙Ug>ÐX8zQ*G:{pg\QǨmֿ:pE!3 3@D :D3@D :DУ;w =M3DOŘ\:zPg "uH"Rg"!$f;ׯzfLfG9uK֗{* WSV9Mqΐ: sYsjBm7{t^6u~^F@:ά3P儷ͩt!u/+ /o''Y,GlV%1Eʒ| ;~Ӹ7}&}9IsτIJc!VuSi.p "uH"Rg "uH"Rg "uhu^.}ǡGЍ9qe&cuNo9T5gE0 o^~ѽGU|CbZU2彽-%&7PD9s3ȱֹ wO 0:mBLꜞH{kd9n Έ 0a :螛+lN䯆ʯ#@oB|a ]xGnmGwhyv3PpgfRgAI7vNǴ|nPg6rơׯ_O>^xqAU睝D<塇0 .ܸqѣG|̙+W =(P^zdٍlk׮ݺu+>'dyD3ʦ&!uɔ&!u^?8(:?:WٞٝSz[HkQ'/ =_>e!uH"Rg "uTdU.fcGrs~hWA&agkiWa-'os, 0Mpg=(<;ζ)|yʒ47^?1mۑ'3믿~G|IF3I ?>>N$oeE=?RgXǕ+W '7*oe_믿NW>S7nx׺:#ΰ/vNAG!W^ywe{z>Q){՗4~?| ;Iq}l|L.ll%iOenY۩RE^M/|u>W10X&w~r#uuF!\ifrT3ctunTynA:U׹s=uuW +OCg(. j\:$"&($KU+k>=.rcs  (ꬅ*3+3ٴY4 \p +f{U[X'bJLBVƺʯV>r17LO^HΟΟ~}+Ӆ=;ɍά}ws k=ʴԫnpauf6sخ&@:S-;xźUg¾@%uf|=m-}W= mٝSz[0b_>e!u{f9uH"Rg "u'ΝHCn}ü~!7L:D3@D #z[_}?(AaĒ4O :Oۯy]T}C:Synۻo0uH"Rgfa\w;%{e I3Be˻v4g-?HYɨ3Brg;.VvO;5Mntw?Oc0B始pairsΜNr۴5n5XܠPʗuAٚl}) w~9&K@ B˓D: +f[3.-H /_bm?ѼjlxEL]T'lj 4(`)uY5/ WT_/Ƥ0Fcs*rs@כ2c1:w΢t#j~}Ca5tku.[߭8>>΁O&t\J7lu.d΋_+w3gwv/78ietu>5΅; CΛLMQe&O"Rg "uH"Rg 꼳3w%Oy! ݻٍC_|<<?$/61&40ƒ3{fx% {-`ީ< ˫3r6Ϗ8MGe-]n.wLL5`M>vR]+&GL7n Ok#G>~Ȗद6S3@;RRӍ%6jF궍8Efa*ُgmcs%׶;u^w=n8jq rY[Gdk}Y=F@[?7嘋WnJ~Ǘ:˹B6| x@cR'R/uylRoc)G)Q$Ta %#VZͭ#K`'oir49%v̎ZxAYO .Nj2!̝}V HsVhz/d,JGtJXJ?q"wW(q-X@#< ڞ?T=f WrTI,[x㍇a!;?jqMkB݂ǹGwFyϛFs3fӚ,MѝQ@gi x x@ fAFX<<  ^#OY',`k b0 51Aa}@@̂ x> x x@ fAFX<<  ^#OY',`k @ )~KU@M#qFf7#כ_v>C4[ x x@ fAFX<<  ^#Oz#;!'h!(.FyD\^jzcJӻW!XH}?}d}w3{gl̀0%+x!aaxq?qXz>%Lr }a^: M7:k6dzt;%\zl4~%gs)y~c/zs?my,Nkў==zwe%JSxih^rיO'^h{6)=sO=Gxts)}[n?xr3G{vJv\ٸ -D?D?öǞ3=Gc7ƒ'Vh2Z^˝k<\ek<<}f@X<<}f@X<<}f@X<<}f@X<<}f@X<<}f@X<躮.FA_ LKqϱa!T>?kI_^mn40ƒxfPt&Fx(9cN=UqՙHy#1NQkKFm>nv0㮸-i>'hyϨf3+KKc9b6<7KW (>Z[LYK"tx6\@G^gi#7@*͍>jMlm4z?t&##5ٖ<~[FxlG$_Fu#'^sOE`1Ȕ&P@@*,M4<"D<?믫@}{tbw_ ^#뺮pV̎<ӘNgLkִ<zGwFy}cqw̑iMp&(`giݪwɀQęb.6ό/5ZˬR];sם?9>6#q[ 1O}}ѵn _D 6}{CsFp7u4vOT^w:3 ^5[Zc[=sݥgjvW)/dOZ ;!;#3G%c@@31 x xTi@<<*4pL xwڿxj;ٶ7뺯{"?^^|܎"{xf`7@jϙo//+燐>s;zo[#mmx}~wL< wL^y{߯ re 2\r@. 2re 2\r@.e 2re 2\r@.e 2re@R2ϝ;8WAAANN2re1˦zcUgj--I#إ[wh4$W(JW9}5+[(& zYW06"ٸ +.AL,,z1tF!9 ϩ_]]tWpHnP/'ep)-cKov t azSwwTە^ś8Hȯ_0d(2.--;v,Cຒ8,]ze]E HΓkk|púu ~཯>$?lo?Ç].eڹs}?C%6pe&5֠3"qea6->n2L3/љ,ݜw=/}ԼD~[6]QiB ~%atN9weBY]KVчY`A6vA9,XI4MmZ;3=jJB ӾɗHhKطFcԬ0((bN5uhVw>ͪz͖ 2{AH|eeSE,x[5aݮHnG0jVC\U?-+A󪇢u"W9zd C 8_W__K1IzW|r+ y@@.cde 2r9%\.>ls0 }*'OqDn{a§w2g:lCpo]hdC(z#Gn7r`}}SSӵ˳VeH~~G+*^Brz>ϟ5>:Ke8מ={ۛ `@re 2\r@.c\p882( 2 H srrԝby@.~!7UD:ւ7xTKU1#ajʱSfzTq]Y˱(vߟ`ZWDL /3ms9q^DUű] e,Xn~.uW0]!<*G-XvC [ZE ~<2eZ0,..Vݱhɭ J_***UM\v-#P/)%رc;ư\/:.ʮmYغ.Dxd7^*lZr=)ش`~yd.--=q!@ڢO5%z!<ׯ%Ĩ4ZCm !v~mZ46 M1>hɒ% e ]eɻ)glfF5DJ^ naӪ1*̵?X%:^zw'L HJ[?0ե}_HJSd.-UAwŬ@ѽF{ |\0Ⱥhjz#uz͖"HpY$׬ѳ-D⺺tšg,[ԮzY|!픸6~x[5akofJDp8JfзGJoà<=ݵ`~VSScMEe\Z8s_"}W.5{[7o6Jsy:X1Q(8Qe(ʠކodT@PPe(tttqޝ7zR{WɘqUdFs_mmmM[FWX^I͓-M&~o$MMWloN:]bx㍌-@.ôuuO/ZPS/two]։\umSzʮF7Fg[_p`P{"k0~˵_j|R7t?1s\UU `؁X?|]ÆO?|ݭK䓥?@ ޴y´) eEQ.7ߜeee@.)7}{nIz{Z>>182r=RrIі}IVF2@/gm/+7$i+x챱c:-8@.Ù|>]1}"5\e(@`̙71s^ؿc{`v\ ' B?5ˮ "5x.˹ori~ᜮ;X'=kfwr(2R] Ɲ뽡bCw-ӧN=|ºWnu4[B%+VK/_?4=]> 6(JGGǭO{{?ww[l)**J!e.wih4vb(?Ƹ)tγ޽P&/glXGDXw~S<{zn[[Z n,Tg{G_3rcI=kΚ373@J+eFuº͍}AW|;ZĮ]38ej4`uڷ|ҙX Y`08z3-ν\41tL\qƁ&p>re P(82e2re 22 @.e 2rv)** @.)\.W8fr@. oqQE0{}n; Bɓ'Z9|?q?f=pjh/7CѣG/]4s|UVY[[tY0?j~#ˤJ8...=Cĉ|lMST#kS2Z*:`fF%/'SY5&$er9ʋrGŋd˵s)k׮dDى;%6;Tw)M ܢ)c%Xz9)LG.++FvHI$ xjt#(U3PU]GAltqZ-;EY^N˞/hlo,)f8zThf[(*IAz٨`rfa^)bX "3E^]J26*-lY{ԦvFM!r͒4 hwY^;/_>K|UèHJfMњ7aTˬhͱJ,↑O\vt@S;ngm^o8.)))//qd0*&TM)X_>ЮW}@ݢ`8Dz Uډuwܽi'.^|O?z`WK<2$?_Qݸy ^JӷGA &VWi eEQ-ڰqqU3@.#u:::UU8iF7M1mUU|>S'Ω%M?%xvAU%Z wyٮumzٕW f;׿n]xΌTa`; qfKF;3$ד2?r9m{#/m(EWXJSe`'2BDiW;j2s h0,$ѽ8/$3J[[(%%%EEEwtpY_0̓|W<vݒoQ \1|DYjfHn:n`)&/.(q/Y֍֙1_V{⊜)SL2+,(({2++KT eEQ&ϙ7y2r EMnISFmTӵ'DٴٟF;{Vف=X,YP/% ͝;رcPHb: GXt=u^y͵Wrԩ-K߻lYMMMzY|ѳWK cz9J q7-[{˼]P$$Tv̝zΜ9sw" Zn(K;::T`5y~LW,T]]2J}{~4i2bSreFR%=S/1̤™>(JEEE|I`0zCPggq|y ܓXC9nykoʔ)z};>r >SənѣG˃͛ ;[aIPOw6[0@.'$|鑜?//?{ll"G477;d羾߹Ayy>ϴ8>G2Q.C o矿ۿztߵNܒPV3>g @ַuy>Fss ٳnݺ@ }i}3gNj| 6w\]HG(rUW駟FrgٝMMM//Gy'{[/w`/~Tly]xᅒ3v?|ҡn]ݝMx`'Ky/ x1rH k>4?Sr9}utt\gϞ3dȐo{P&A.go= ^7lذ˗o(GBΚ)ny #;r`{2 /0x=EKZ[[igq]|_KţMw 555~q݊?{e~)S}Y'N )C_~9KԴi7eL+].WgggZ(zH{V\[[݋eWVV3X^22D˜b9\U[OpٸH/ T&O\YYy-M;nȏU?2YgܽlYss3C= O*9[m_uMꁨ Ca_;hcZ~>hVu2$s45^8 ?:wNn`H~ކac*+C6GD2ɥl4L*L-]DU;{ RE@%c*y0v9&/U~92;͠hL&ci2 jv 2l.-Tymmm7M4~}͓*oϷݬ[Z~v_̿]՞]OFg44/w#{yf{{fcgVL}a4zq[ۂ7ڢFkAT̒ evj͂|8Sq6}0{\ԮL.тสC=Wb=qҸDBM]6Z'Z5 f1c$}b߰˼]|,]qdu{zWX{}SL rɜcΦ}Vlo6|޾rÆuxy1\lQ8^\Ww;<0(//n{{#l3ȋ- E6ʊ̨[`)C(p7jڲ4}k-qys_ьgKCY̱f޼\&X*͒߉{^zU&@A#cB!bvs Hv˲wR~s 1PϧNWСC'13#6|x8NNx.d*t~q@f uKR{ *}OmhoNfYw%.bԗ0Ǩ"?Ũ!h2ߓZeA۝>K^vA_ooR5/|+эuTw1ZV@[< YJ6B\۰n]݂gL;}T2}i7T.l7 v ݉r523`veyep?c欹U^aj{OU+v<رcM3I?h%F  } Hŝ~e8K(z?sٲ}j3-- Y\]E}"wikL[>҃~=얺ʼnwo\jˇݶ}F%|<*%e8T;g퉴# ׌|ElQo7geӍ IdZG3ǀYn7m(w F,-4e> uIDATdm7 \v2fmCYs0}F { t͂2 $ } |In7^X9gfOD/577oڶ[v벥KVړdW^ W^}Q g`r asr?%C.Q|_ gt/M~Hn[D^FJemBw"rIID&Т2\r@. \@.e 2\r@.@4>_>Ä 8߀ WF~;j0,..ñ].WgggQQ,>2MQQQmmjbmm- eP/;dX2଒bˠ^vPL eY%32A젒{ޟgrYFy_|qYYҥKCeP/ݻW^}'|r„ < A.HMMѣGϝ;g4~衇-Z rr=Suuu]]].7< A. x<`0XVV eVrW.g~H'{)..޳gj/˿o+裏8`\l+̙J_ky7I@2cC8e+,,L~=χ~/r%/Y2IWWW]Vg>v_nFS rٳ;;;<Ϙ1cͭbA.IIȔ-xAAW/#y<So>aȐ! .|GL@rB#F|JJJN2P8|>/3, Vr@. \@.e 2\r@. \@.e 2\rH2\h:Zsr_؍6 rH]R!!@6L PP3@ ؔ*X؉H6/Sp@.e 2re@`.H&IENDB`PK$$PK DOEBPS/img/pat_ucp_arch.gif3GIF89aop,o      $ $$ $  ( ( $$$ $ $0$$$(0 (0(((4$$,,(,,$00$0<$0@000(44(4@040444,880844844880<48880<<4<40@08<84@40@@<<<0@P<@<8D<@@@$U<8HH@HDKNسkWc Ë],7J˅˟Ot(}VzVA΃F(Vh8< (v`(U "]0hc杘⎳hU7Y(Gy<6U #Ը 26*IGBeF)HVL:_PR%ԐLJeFq yb:(`mNp@El !UVZ !H(w'Ini !n)!㢸2XHB9$ B؍xn{ڈ̜`tC$@郄j`ըTh˱ ->H gG*c b9UiJP  Kʛo/.[0⒣1>X VlR_' Kڂ/o7n2! * ·lQ8;"$1#+0,JX"Sl2!z :tC:萩"WEՀõW9[̳$P 5~ij29w68: 8UnHY#yveJk1Wzf;G 4[“CX8nuWofH[K=۷̦wZŗi5I3lK2x [󝺋jњi&}y}bޢREQ!(]/O[c+>pO?qz#kd\ؗgUYCdx Yza\I!A gS{}H}}fH&UǀЕzGtv~wGgYG~]U~d%cVaz*(},Xx.H{xeUՄ[XbbW5;yxd )+Xp$1v 6s7yGyI&]{T0sz&|Ly^>hwu({w&bjgjNRv@z%H^eIc(f?UOHE`UʄX#^Vڥ(^xƢ-jjfMI^XNEYy`Ug{PL饟IjctITfKOckPiy^~zꠀ+cIU빩&UkثځA (UgS8Cɬ("߹#nmp :ɭn8jJ#ꪛٮzD;rjM(_.W#J("YQ z|I | ː{Ň Dۙ6V;wJXV;^x^h[ f;R˩<]`Y(Ixt bz: !;])ZbY$1 OɓgW#{X)Uz'H^p湾Ưgu_VNU Yj .jH&VNjs)!LVj+j#X) Jc$[\M|{[zBh׫aYP7 ,%ǜX^F`&_\e|Suש(l$?xdXN(j%L[LYV_Wl݋.,:}u[!ܕyHYwy&l$1|VqfW_ (2jbahȥ|\ej+x8V9`P;`ijj@II&6)U؀HOe읉b~絽*eE+ȅ#c=IMq|)kų1VʑbP5`[3q^Yʪ!ʸFi'x19ת('Vs嶄~;_qz{ ʌLnSG\|؜ڼuƀ. <\|| C0\| @} =B = =m@ ߰ "=$]&m \,m`6} <8|}D]F}H)@m Q=PPN}6S]X B+d]fmK-_ Q`` \l}n rMx}a+c}ք]؆tR` Vؒ}Z؍ؓ]с(m؞hjW- Mړlڨ YhU5vW^jJ٠ ҈ 6 m ѩMx=ܱp琮#AW)H=]%PR l}Z}m=ϛ-&e&<9byaGcFe&v`M`@=l~ρm^!\[ZX=qaOUu%%If-%Pl? DnJn-!P\TWWu/s5G>G Q=`=oZs>$b8h%Vw*M(Ef\M!l(-ڀ`m%`x-՟n=[c8UeXe8zםkK>!榞Ϙ>Ѭ]gV5|Ku_d[b[xWYgt)!% @m^_ .$.z0 z.~ o SH !`  _%1V! ѮY` z l 9ˠM] Y!p:>BOI}ϥ0t0 !ҕpl MP pW 7߰ !Y7! V7p{_ }?brӌ]@@.Mrϛvxy:pʿ/Oh%Ϭ |^Oht4ˏy70Ə7[e ص+o7v1Qd̆1QF=~RdHa``J-](Gk0m:=}TP??@4:xbWd8!B 6m׍l&ՠo چJx^ 1Iꨲ`+en,ѣDC5 ?(Ndʕ-_ƜYR:Jrt׷~d T 6Y4ЭRjļ!gCNa_6 Fzd&)^x͟G?^JfA>I7Bq" 뵆 aگՄpe0' s@)#2$Ѱ4rDt *|*ŢbF9 #fJ !NaFF.pEBҚ%2HrG.T;=,)0zAaşP@`PƟѳ($PC L8!3\ќ=S͌p1DH)mIΞAFbuqu.E>YuuQqa JeC;"U,f$MAȅXuBH! Ǝ$nK☩Ā(lwc*Ǩ18pzZ.7 %[2@+ Q/9IC,φf@.]-kEs%6I`u@LPfa;%*9Or"Ԅ$ld3?$_9}n$0' y/dH3s|c`#=5 DݑeBDrl35On\Q%*#=(9#ڃ a5=%b%pi-N$4SF 2'\bRPٙpF;͔'Pŵuqhd'&s̱JD%!0V խW=ΌXabF+_WVXpMc f`~M9Ԅ%a>ͨdjY (i#כv#JÌ6GSb\*)ZrmoQֶ1in3Z2`e/Ese`+׃LM{.YBOBF%KC%V+FqV|Fe>J"x%Y!rgܲC^7U ͠ЌzQuhpܨp[ρ^JP^\SFA̽BV7NT ҅ HLn$D EKlZf! Uve 6~x_0`ln8vpPࢷ5MR֙_o٧ClY W+D4"ф,"AgK6ںFQX{:ȪoK\;Щ#[r#\%d"RDVwl`zwBRt }=V`GVdp=)`(D;ڙ*\hsѮɮO>q^zu'_`Bzb \H(MlbS츑 Du~4ztj#5oÊ&fu8!pxݻT"vujFI ũmC5TAAljW .ǛG+g!)nH$a F *'an 1GI"l5sd>4TXL ш3͂T`Ō Ť#hijki\̨7S=88,B Cl&D99H:*d?8b|YŒ5RGi/ED\D[D\AHkHt7T<[\ċTT@`G"k-i+s t,BfBAPA={Gۈȏ,E6ɏ\ćԈʥ<Ŧ>4I`#SˉɗIR (0»ɏytLǼ4N\b"›;J葃o0(̼r dJ ̪!HTSdL(Fxì#,KC TM I EHd,TR2TEƪ=1Dx4F+NŨJGȤ>JRR042+I+ÐL$ ^F}YlK`ŗ?Io A;L ˾ύ` E(Ԉ!0;PɌ;ϏPйE+Dl=L9p E.yjO|ʙ7R:P>0K֌E-ѻ20Gx`1bsRV`8[00^1 =Qm!e'"UI!CEup7=Q1]ÃQ.RJ/1E&2AKsr3FI:(#>`RvPTyґLTst鲡9U0C{ۖ8.TSTNTas@UQ`4< 3HQhX LEZ}[kR-RVou)ɕ2@bSf%YhM#i!{鯯m ;,{.sUUVum-vwm!xu9Cyj]؊؋،؍؎؏XYpPBXRX!M@YYU:rٜٙٚٛٝٞth*9ـIYDڤգMEUکZ=a^0b'ڮڟڱrgگE۪ \p۷A۹ۺۻۼ[}Fdp2M%tddmb C(F`AIӵ/W.MN._H>C>H~a[va4(`V^Wc YZ&3]SP-5~h.h]}(._cFrbfbxbn6p3v.Zxp.`\sdet^>_q.`rhX!hme^hsnyh֝h{h~4&N~6v]NUa~bFicӕ^`U6e.g>Vaipva%_^e=-j9g i%oVbj"j9Va~b.e]"f Pvمjba~9F6lNHjoNIR>]>ln~-ƀ^pgͮݻ.Ҽ&&]MbFNg,nH^ b7N!gk"a fn.Q^[~mF-`l.(f>Z8c].n-ndkS{l~nמblDln.doFhVF放nn"a枃'dS`90 ?] /݂'`4f('&5~;VGxb4o__'駖KqE` r8r"i/$_p^Ҏ_'r]r4i,/_#T$3 s1^2U3?M0Ys6^7V8ss;?^<=>/?%t HIJKLtL POuQ'Rt8SWUgVWTwuS? ([\FgI`a'b7cGdGvGpfwv7givjlmwkvj*CPr7sWvVu,҄w9-e{qw'yx'zwwWw9x/x=x'x|xOcnxx y7y~?,/w/K' ?`W+ ^( W]' \& Z/ W%7{U{`Tr{/͹ߣWZ #/KgFX0c!y{yR{<}Џ }? |W%݆H}֧}rC}ٯyկ'#~W'?~y_ ]}~''5WO u,h „ P(H0'Rh"ƌ7r#Ȑ(a :(z(w 0͝$(JZNi~:i*x):*z*~j2wA:+qbMrZ+ *:,{kakv,۪Z-2:+v{nf{,Ί;nN.[++M;b.i /*390~$k)s:/Iq|]p0x*6!{'搳uXg77Alq9OExzg52V&q ,' zjq?!y,,7 #^&(NR`6$X,4hs)"9fiL[zib0Z<+g5/rOx77N*o0.!Nj8&_o)>>===:::888777444222111///---+++)))'''%%%"""!!! !,XH*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟VB0(h& @.v(`~ D,(P8 8<@h#H4ZL6$ha+X#OfeEX";hfߔ.es ~&b('>9QA$6ebKNEJ$ xT~@G4ĦJ,駠*ꨤjH A0P')F 뮼nzkD-!`*J$ä~C b+2t+䖻m~V`hARn/1@`r۰% |8PZIeKLoTK 1tH%<|p Y }19@"A3KAHW@lsK,6F:upQ'5Z|yrdsQLHd}vޯJ$T" 2u_A7@3HAH['7C03?P/& Øn6 5821I5Kv>Ś};A̒ғk}B^@^+E#D#LGh_2̴b7=?/AE8 ^Җf +~ =|-8X6m BnAkcҁqNB`P泲.2 a,Cv5]lُp!WH(`m?m@dt!p#x)`CeHF8Dx@,B͋@1 fh@PpЄ(\( !}}0J`at =9JTp8|{GKH@(X)h# !,6@P$@@D(@@ <2 1 p`hCW)`% ij Ю@zP 30B4˓7?@S F $Q3>7PBF0L 1'watL `jb-`* A, D v5 E 8E< W!})PPD! @ ,vUYT JN$ȕ(RKsl`,dtY@,vha@9/p sXWK@=Fu?O@fta 897bp}&ҁ 24v `Rc@G <Qu=gc0 C@\o,̓M o{w#fBGp,is'|{qI)&؃>D&z1>)b;%]Tkt7]="a]wEĂ&}#}cL33,?cH)Wp0u#:B#kb(='+'a('J /x'9&DEVT"S "4Ӆ6b<'$p`l*zW&Ak 6osggE2,i,*k49B&9c|%jS#|D q+Ax]TCLcO1S 49W+9[:%sb+Vq;jE76!= k;nF[H˹Tst[K;[3)3Cڷ'm?{;x2;E[@kg;kT[QQ(˵K_1蓢3 Q3û3x+?zk˼kŸ[R۾;ni({'荈W ˿ 93;kܻ{I,s5Y5R{29IV^G9H#Y#XBwh?/L 1!o{pv۽$%_92i!M#XK!.a aƠƸuZo8\y %%" 3Yd]R,##>lij3!Vܼl-[06:uo{2\9W{~@P`$"BFv^K&c9Vי,.e( AWGc}cM8ʷA%m[>Bu9". UNdBd5` O0{C M!h0r⬝#>& jDpv`Ei1OЮGΘ60!&M%lq[U\BgtA˜RV`WDv'-Px8 Ԗ> npmB1#N5B'`de_-<*0s`OfMH,pwӼM3,xBAT)"*s]MpF(.-`w1 $6"b1O|U8I+M{NSsHS,l^rR*5] D,&1 2x`0Yq/OPi}Ѹz@/5n5<ut5ֈ'XB]yV$işO0N I=<.C4 'zQI@"]_N,Dr^]ֽBkz_9]+i` @?x `A%NXѢD'/&$(?~44(@#BaAbL 1Çs%1>cEIF̙ P( &z&ׁP\8=@A^[8,@#?%Dh: %9B#LSc [bÇ"0Wsp"1=2ѓH.Q.BRP&BBJFfYP0B (P:p=F+ ᐑ $w@M0g<6=:A83*XZ#3A>1 wy97i29=n PKVLx  2×(j5¾>~ c9 SӣF- +?KbWI̸P-"2/ 6JKKKY̷ q&@ Y{JDR84 A!rr. z/q*蓌D8 1G߫9x'8w j;2!bC(x[ ȁܦ>I065΢3*^ 3)ϳP',&1 ?(ǘƉ<"E 8Ѓ~[0t>9 a#p&/Ȳ"H:Q"";O,MQ; P1DKI #P3R("fD}RLbBGZ1Pˁ)p8B-c26="%Q˔za@ -ʆs@MO2" ܼ:hMP-L-X*/@X*/: TS U+0HUgRLR =)3`ŏ8I74Ax>!hT k"`R4W7Ih&x+P 63Z ͐*Э ;` ;զ| 89@Q->t4BU)97 sUo*+IY]  #I( ]!ӸQс@SN%B@`%#X( 1 57PKɊGQV>}ϸ p˘aѓMӕmjYYo| ק ŝK\7luʗ(Eaul;:@m]fx')5 (R:κ _K6##7[@&9xR-h-d<-\ l<ۨs]uI2qف ._0ܺ`ޭ B/X?2 (*-abl;@ : ,= IMZJ=>iU?ddM-6PaZ,)b{k?bi`m}T` ̬> b<B)),X6  40]eN ޽d'%dD ]9TO W|t  )=▜ќ,$XX)v{㷥c|$mé@&es:1dDc5 S idQ]h}ȼ@▏1JKI$Wx&^.yUk&lvbT fJ4Q蠋VOOE*eQQnhhbĢ fi4FFN"yU ?fA`fD e狰W.i@TTy.'nP~~|]jDŽZ6\XYSfrkӓZ[\.2j4}"dU\=kul4ѼR ӻhKdTHB,-NunK29= F28+Q2; ; 5@:{Bw Hb:K7U U φ:kWD n @Je0UΖj>tlHHD HOޤ `^?ɼ "(+&'++,hU3@/*X,r0*/+5pӵ%s0*r+VfGa*-,)h*p,=Eu9 &)(s7벷1& t9wr,+>q޼5&?()ps, +qD,*)w'ؑt90hF8ws+#e(X( XPfqX uG i 0crivG"h q'8u/  PY[Zm/ yu'/x00Bqv~x'vH(P`wgwy~+egvӆ60J';0!fHhf4PmpP"@X@bB_LʼngE4H )1m(Pn͔`̀,K)/ $o'0H/UFl1HˏRed؊(0#75RoȠ-^]ޖ,nf)&R <`-)".tT|f 8xg R2Жqh} 1{ `*<a(P!r#H5h#A 9>(`@. rt$Ju:2$РB-j(ҤJ2ْ#MxC@-"`+vf:*\gE"nm [ 먈 A+^2ӭW(gƆ&ci K tO= E S6W}.Pr֮XBΚktE5y`jqq%9(Ot뵇eP(_+k`%))Pѩa&@._|):bL mt"QB Vr1i!i!IGMap&Ć\?3uH@@m7EDrC}9@ ${y灀>: 驛灠.)~;zW}辻|+5`ZB9e~P3YI2X>ʴ9Va}8`p))G? % In(?ܴ Bsxz)ߪ /I~CWxCAPN|"~Ҕ098]RDQI|BXPPĆ(kI cOuН'8d랔Ϯ& ̀+jqA8jj-sʩ9j{~ 41@Vu5b7ebp2 azA ]bk^@ (Vi"؜M h$'Yj9*cI qqA*zݽo,p}9069TqYWݨn8(?sK)=Y#?ˏC1s ϊ3u=syVA Vs^:.@W\$1\=QdgZu=K ?< B!nKt&#s~}D{< t CT"~G^ļGޛZ #%\Hrp]H9Qnz97m0˾#U{B_@b}P9LvtȔL=荀AqXAt@h9G,]  ^r xG`ژVGd@j ~^!t D`BEH@A@"@TTABn@ZAXt 0Q Za !Bag|șDaU0AD@tA@T@@ q L0%'b\((R  edd5 _0"A(x @ @=A`@n4nG4BJq9ʡ!7ڡ7 +Z+P@|Ax Ѐ@A nL( h:B#{%!)>)F$*N$rMbA@L@y D`Ȋ 8@A@ QAvBG)6%eE}DAAc ^55>X6^^%%Raj%'e=OPbc))BIjpRt[ bYch^^U)V & G%He4dPzPY0dj2sVĞsB[~ag6g2fh>_m2=@TI'QqlKp"dbXlZxxϭX@@xd~~ly\,JXAq(h@N8k>aۄRcZ!NA ֩&.钦 @2^` T~)~i xx 6qG]]hX`$@\ݝ}aُ]xO tMIJ3 (Y (uS!vrSj:gH|ivfrF }lc~~#q * hm"WtZr9*mJ]kӹfP0 )y).j_rBPƆ࢞Ek5+Rvk r&'Vؽ&löOtbMOTVĖd H @WY׎^V*],e),߄PD, B^_W8 @ @A*,g)g!ln,tlVTyz"DV U 瞸͊_΂m%-ܑ-LK`LeA@XI8T@P l ݙDen!n.mf @8LA8@P@ (@L 4@ @ EX L.«ʫ>. S A'@AA,AAtbTBhꐴ.nBQ~!چEElk0LX@@HhAXP  'zS^OzpB^` K &*@bzvb@@llt%@ b W D:YBؔRYk7XScSƥb@W ̙Hv$lOβ9UaxbKޔNMfxnQPkK'c('e"Y[) <^  JԪ\,|.e&κ1P2StIE|@J ZOu6VCTOP-]P({:Cqg;OӇI$H4OOt1KS1nbTFo8$L!*F xNRlQQURWRknU_EGpݑ8A<"wpKVs5bVWE78\޷*xgLtQ8Cf8'8V{x: ŀj7܂w_Nlu-f⢫iKl+7vkۊy @tږg9zo777lo+2qvo|~G㵎ӥ+[` I0磏b:I@z3s+w9O8O9zz{LPv'1?ysbBL9K7ḅ+y?!0? o:B;ջi{発+z;lG1p7k<5y9ss\|+;yzZ/+Rķv|k<<1{gfƼwϼ  NO1Ȅޔ֮,ԖJə|I |l/<=| ؛*wEE M%  `@(Â(`@ R(`c `!@J+YtfL3iք M@J>94іA(eGgSScrlTiEc”0QHk(8  x"#,Ԙ2AEM 44e)W,ϱ@Z\5%VLB-*u%ϠNիbWy6PթK04V[]zbm15@R=#-Kz)[$lag;a/@9!x B(*GD@"`"!%ʠ&P,9M JKI2J"ΡŻlN^j<<=2R 9R8 r%(|A%vr )(Ž*:%r9P"%p<4m둥Ȣ` `+L Hdp48,//<! & !QVt̬ԄV[ST( u:U 8P20#YHI<2hFk$ʜeG-V")PIP "`")jPRI.(,anU*WaͩL#P& HBM-,3? bU)XUIc":,H %8꠼H.sa"q׭}ؘ.! 18A>d2 @fΪfqu'9%~ gEC00( з08 *$#ȀJA솻.kpÎo p55`ƈvCˡŠSo'1 )C9` Z%=: \RHىݧשwhE!(Gp Y@b DoTh!%V'I\-1C*ǐ~ΐT9Ù+L) xU *qU5Pꉣf?A';휸)Wi]4&"(LX O$+cYgJG+ 0?1g*p IO @!a %bЂH\[J. Z")oDcֳ8@C (-x>.)* XDi%hқ!II%8 Ub#LOTP! 4PJiSD\XmM c\T/aKTb x0'lB $( LAj XrPp؁`@R%0 Na $0%m~8LGXB|RTbg;?!]~"iR)CؐZ6LTr`t-"@T18bҡ1 d`@$-$,xi@ +@9@Dj5Q⁜ pm<ƒӲ \Q" l$y9kVÑ t5jID ,?&,GqHEUqK[ `i5 -|#Up\j4:&=ͪH%80f)PDFq{s[[|mHo5- AXRo̵d-ÝGl%idmm&lD*Bi[2q=T%=O$Kʦۭus/JXむ -yo\B7 !`'")Cu2I2aH}J! f1X!&ޔ02KFzwۗ ZBx*lGNB;.FO&\^)J%Df,{0eI% `&@vr(YbG] ה&(V|X&%~&^$:&:* h@P&0 `!,d@:d-Wb'|"cb |-^B )Aj ڥY , oRk"B>NDjn J@%JPaJCRMWO:b00N% %8 ll`.kiХ ^ R IP%0TqXZlB+2Z^(bfn1 c Q t 14e*:8*&VJ K|ќQS;b!DN"[p[)p&t%t^s*>` WK( 8h# i*"s" #`.6H2Mlر!%b#u3} %vN%\jȉ-J`H- :6%v):n4elB)D !`e1ss3P%p+w`1o3kb;(43'l1!<.87Z#Ж&Pll$TPJ"oo#F-.N(3;4QebOih)m~8"E!/ojLŮR^bJ^ O! 1(#;&)~C!v7e]G<#c$"v1PJ0zFM !HhxGHw(sZ#u5rQ7&P#J/!x7i+\"2fNT:#@- m BqCޢr&B-6+'<63h y :"uK!*o08I(޷rgZbSb}WG|cUzW18 JEz>,Wlqj T2bob"vѶ#Wsb> w-b1*o#fw8WMBm(-(WvIiQ jYb ‹kz$\#8ɂ @KɧR-f~ɢw8i2b1VJkؐoX%DvNgRBL  02! ^8BCN9b5 j% Z@DJL `~&2j$si$$@ Qu)]PZJ b@ ~1D{` >@j  j &rD9r-j&gXd%dJ-$QJGBw%.sU,6`H0$%9FN•\iXcm&Zѐ$Z|Q闥yD>G`P<FB`&vRiz&Y$R`dR$2'K &zjaQzK9p)E@z =zhHQhJP%N@D)%j=ڮib*9 8BAi5gc稳]:Cgc= b4;U>p=ؙ('emuW)8-`dR:&\y[U Xe"&S8b]ڀB-- T`% @Uⅼele$b7`1&i°}{|Qr @H*%R]f.z,?;qB/ @:%t \ȍY(m(Dn oi!v[H/vUeBQu Ӽi.TAgX{l9Qz*$(26/Y&:f)(dI.+l2;bx,ķ~WO3#fK=}_^abΨvz!>Ul߫"4q`(n<.`9@< 6Tĥ-/D0 I9CPCo,tC[UP*=r 5\Y^}n!Dl pBLN:GcNWP_E XDa@g rg{٥VEei_`1 G PG:(C]8zxq8eG 6DԜԝP>%#Wy@Q| 6 逜ijGO䙧LO%%YZ#_m)P PDWLȒHEs\e֜x]%]PXeF'UDB4@jRTqqP1PE"6Qslf6K U[AP;VLuAN N^%RWyލ(A&h1Pʜlm8QuC1z[y$A=,&w1:@)4:1j'@js Гr(e</UnfeEn/ANaF%߲?尖K, ߴFW:̥5t!d-Ӻ2 {b @TdN1BJiF pIe!;[K jOI%KIp~r:g5L~6p4Zg@4p"m7/py^ W, q)2-& 14? g DN` * \0$B d24.P8@k6)TLc88K#QLtC3sJQf+]v7-szފg9 Q=㪅A*b&wPE9iZlu8k^YH@m> fئ;sa# Op dDv)=cA$A3tJ1wLI,Xޥ`%`6\fBtA%6D @."}zDhl$ ȳ b0`hr .xa `H 0`PЀ$!%H/z]-@Wp0|AG*dBJRtpĚU1la jByXOT#bBb+ <DS( F5I Qkp E6@`ENv2ه|`@0,x`$I d@`: wrt@w4%搂(T@Y;]$oI* \ _m7\gVUʳyi"ݕdfBx-05<_{(-G”&] T/}JQЁu!d YgijN'R`\gN ΋ 2Ce1 ^w,򉚩]AX 6q[ixCr \n0O0K*FFȪVuz#P}Hekći @U*'wx 1eI|@#\@h|f\AcirK!ؙZvg{]A8|:/cd%[;"@r#UJSb&݉17-9VDmDu3ZxTk krv: s@B4%tTNp[B#MDmt{ymrۄib%A`N7wNby; mW'0nLIAx]h @0/  @X8 x ˭I"vN9]Vo{tհ|sxDDcjwϐv)qPTj*?dy}aaБ2?lϾ>P g|bg mP2.gTO*Pt%Y"~P3.WPqa}VF']-Ҁ/x%hP}04ݧg5k-edp8`:abP:mQ%s1%Ub%!x8%_hl xF޷g% g[膏D*rL"azcE((|h~GHLaX>!M,$;w8Z!pS7'47p<,@YX7Cx7zkӊu" j?؆HY6(:N=r;0'x@X9Gy0DE\D%]⨐6AaRցH(HauΨď81cF ؐqQDg/Jg/5 6*`U;17'7Y':P+ ђCPqv!X'T`pxIR6#"w{6*7qQv"H;1PpT@/LpGH*m;<)?>j@CzV—}Ii/`Qt't?`U%@}@L@9G5Q6+8IkvhhAiZq .cyiVA #.T_P*nO@qP'`a#̙BJNBgT089!}̻a7"˿h@y˘>ɬoUĎqEi<|tlLY,(<ιxFq8 I[% I|~O5glܜ b|c\|-  !%0) rk R(Аlҷ),}wdupE0{ dEY]Ho7c]0@ԖuJNҔ,fd- [G` `Sryr>Q4(*"qs O *{{svI2NA@&QPQPVP qh-jM5x'֩'l ڡ}wbo0@q}0\s6e0W 9@pE ٽxgٛEaԝ]lnd21puI0G"?Zw1 3;hǁZY;Խ=}Ƭ OGrDAԳ!:gy9MQz=C^p]K;sI:7xDt̺Dr ;T [C3 }J3VAgzMd*tw/z3'l."Z%qPp`N1-6'5\r3>3QrsrqXރJ&7:oBAJ=H(t'㸣LpoCAD!<3νC =\C Ŗ>\*$X-C\-7S.g?Mc:S.>\|д%FU(9Py|sĪd :K h.>l@d@0-Q*S"b=CF/4H@)<]nB x~xN/{y W*yzru}G)Uz W,NOdw04W{z@u7jtxGfOVG1v@90sdxܑm?4{"S3?a5_8@ Px, ވزY+|nק?L5!Gr =YϹ% Mh|ݯmC.81 s1KSWqן*å/Ew2KD@``DP2TQD-BthѢC+Rȅ:f$P]@<Ѐ5męS,0aǐD#݉4&o$aF;VĨcNWR怕-_ 0ZmHUs*^LsBq÷l܊kaQ$M4_ƜY~qB,V(gL|s1'ǖV-kڵmTq<3տC:~-lƝ?n[Mh}GjZS5"g{9͟GszEM?05ǗfC/@\{o@D;ϵ2/иS:5<ī0CWdmC:C> DPB-G?&S?=ܚ7Q;FDG+D3!E*RF/JLO?Z36;2G9F1%@6u2u~ s<.D+(OtٝnΝ993sg!`0 F[a``0 B `p `0 F A!RSkD &d2~\^"\6bsZI @<|H4(d0sWC704&Elg> :7/GV`i=O]hH\!W `yQu+YڤOZ<խXbn7Cj 'o,';S[-j|&<@TH*H2|MysXG@/Y#A$A u2X(Ǥ A &L&(&ɽ5e(% K)oNE,&p={,&-x H㋟_Lb~Js!u«{*7l. e@…~@qHV@Vb4u0OD?[&O\зs\d2)d1A(Ee"Jf(ɬdHv/)*b|QAPyb*+X$K Եk L`Sl&&7!1fãM3`@C`DpbA_\)EC AE $ ԡ .y|1__&RColbYn6!0#!8}%|#)w)ok[yS7`.0W$fA|C` |>)ckײEc#XL 8lR'db]\Cm& 4S.H!0@gM7UoV^D uIvAߚ 苸|<>7,\ @ה`|q]շ.(1_ B`L&1zV/@H;uLJ7g.\]f'Ӱv\\xd^lKSu+W0A&n/s<;'XFIyڶAzR \z.@QIV˸=r#P"x}pkM]43Aƃ*s={g%JM!zNnq/^Kz#:!c ?iBiVڶgN!a#-:}FBTtDD)9ܱ};7ӈvmri9$c=nܶ 1`;OUѸQ[N/:ߥ1ef?x\௙7I޾O|u5ւ%kę ˰]V-7Ys @^ѝ. ZUqIܳ}KSy3/ʉN% Ыt^%Hr9/bԲs5lXAK@h))/"֯ڼKdG36ciQ{д߽zֲ}^=ioS&>u g_(޲nMTtװF::B=^|5hĤKXןxA\=~Qꖧ\]073=yܙS޼I1Yk v54v,8[a–{\-/7﯏"8:fMM xB`ЭmضK__o.Q1l-lttuZ'./?#8$ҕ;!aޮ=GcH6hdTLW}ܹ#{;3Xi'p(vLl|m< ܽѳ0tAsjZho/KrA][7EEmni#tF];{&J;x̌KzF>spw""_vB073x%h))k< `mPu^>H >`TLվ ;[_%Jw_״Yˀ_RRRp*dD\T69@ MMoCV_^;99 57j۔Լ5.ތssulbFY#d$*(T&E(qQ|Hϔf~HXqV,ޣeFiަ뤷`VMkTӣ'κz}ztc_Hrb,o#JL&XIIqq1@OS=۵޶~YJ{Z}_5~h{t/(p]+:]>֚PȓɤRT2.PAJ$%.srʓjmk23?{ PԮM^=:_PՑ-Qֶg-kO]]L&p9*|& R!tuCFFÛM OO[A3 R!7l ffƷO/_iWMYY5o2BrKJJ*.?9ߵIq͚4afj:w2ڱe5x魫gp9v_bؼ -u+8qժsm](.5pD]NeʳGN&tUEw׉oC#H7eX pn.:6n#Jjpmk`GNY=7vˆVu<ߟ ђ=WA O,>f¾ۃ}W˦ԉĖu+`0nǡA7΍9E&2`z?Xbp'.YZX7lha+ | }zݼfxt7pMw^ 0(¢T&;wkhCqA^'իOt;\)N_l H&$(@  (d\@U6P(AV 2X@08*@P*PȁA|^va!wRi}c=A __ XLؠR2_"+I *H^*9(*  ` `+\)2A$6mTQ@2A!Yee ZV,d@ (Z܏R`@._ۓ~B&{uUhua^=>.L*$SS(| d%* _L_$+5zE,H& $ bWqR(LTJP-K/&JP*/`3aL;wto_FRWK&;׉mA ܷ:b }"ފ"~k"[z\ooHj1#ʿEJKۿ jp `0V]SA0 V R};X⏓$IO@/.R*_Y>A&+?3Ic &CJRR]`0-H>,RIq_\* 8LJ ̟d1@ʢ=M@/IT -Qdߥ 8"ǟKOTBs[&-[Ҡ{ HJwp *Ņj@}I.s$L6{;i @U @ *W\&@I]$ @*Qʾ1 GWN[g0 X?Big&!EaTE7߷Bl"R!o:BI˟s:uhR*.K%AlEd6ߏ !< Bj9Hc`l">YZ=G0ljӻ{'R $Fl*^.LYy>v6o,x߹TN !U%!$)\rrxx/r)qk'ϲo+f $F\FtSS"*غ~9]_"PRV.~):}UP^ߊ2)BڶDS/WAq uj!$S"TҰ3]Z&,N""/\P4mY5i;)TR͟9qƌaaYY꣑W4us;!tS_Ef&~ҋS=dۅЁ;6p[͢\NiR*4_qAlinW JOxZ~Nj-5g pG2T R|8߾ auZ\Pğ]* S*l؍.3I2_ؿ}f̄?:z܅)/wM,&!t7[ L`iױ'z0g k"=0e-F͚2@uZ++-k^&dT*BokJynee  LLtIa~BM?rY~+|g,,,-jղh ``/[ۚ::`hoia~1KKscЛW'l^|0jײ0ءCZeK-,wn <b\5V.M[[zaT-L_DFwo׶ucwTf}Bq#Μ^.eBUPRAW$,߸x=1&yfL.NT ؟)SGOK+S0quqn۴|J?QkVV#Y$8 /'f.^Z89-, son\8AƛxKK-Z)!BV[8L&iiazpk5zƆ0t ͛ձe]Xϭa]]O_F榉/[?=}=K+ FlZt٪͎u[jjk[?vM }},-gN Jک#0H~;tBԸGgOЖ5K<௯gjbPp 365jղmެ)8ׯXWtA4715u|$CC33O0ja:lkZװ٢ysGl MkWYXo^@tU++ޟ? tqwaL9qFVDsfZXܻ@mf%'_=ǩb-,ڴn VccS3@o*}Nk_!t쑥gy_I__ǡ# 8"iFft{F ʋתPw/:!j徏Y c&{Bz&)ZG*y|R)0FNn.EAw$PzC5Ţ9Ӂg* Hz 5ܥ@( f| w~3ս3p F M^#@ݺ 2?7cO IDATAL"ғtLRtPCOZ ͖dp'\Oc/#DaAdfeX@_[oԜ<8x$ :{] rr!'68CM@i .'oWx󶽲RYX)'DNv.T +nhhЯNj (O0TZ(.p(#f/%[gϋWZ6w<4(3IOeSY+k֭IGX>0iaR lNii:|rӞ$e_='ːBa~2z쑄WV!^@HXTB@|\0 %H).*˙Ave ,Ke+Jq726omyɾUY@V P(*m20TvC9E2iwA ?tHNu ~TnQ'c 8WO)O *z<}}Sf!2 /P!FC)2ɁOK /; @A~Mk$QOԱiً t+AQYkKX*g̫2も./[9J< @ BlW[`̾Y:e?vedeOGҏ() bWゾׯZ2{w]YP j:Yb eXt˭dٱޭ+'v >磧er~3*E,'%Gk4-F B(Pҹ} |* z`i73uJѹtIqUإGnٲ MݾT&F%} yzϙL`q?UB# ~ߊZlrm:0:BRvOd2ׯ#rp]t ~ ^jz0E~(]`6r,pLT4E_\ϱ6- pm֦??YLг'{CFd)6E)U2a.7770˄o bSM);I2 '߳l6E/d`԰2W?*PŦ(Mdص2L@QEQ cw6:swn`ϝ:]EQ**nvDᨫ RRKDQMĿSSKWz$I]#B`,ԹZOZТP,W ԭ` MrA\L\XZ]ڿeag`0 F{`08b0 !`08b0 !`08b0 !`08b0 !`08b0 !`08b0 !`08b0 !`08b0 !`08b0 !`08b0 !`08b0 !`08b0 >05V$Ir<=B`0Z$w~ʪT*,,zU`0hs͡8]$Lx`r Ml@bsϞ=-`PQ*=bЍ[Jr,#˱`0 Bɡ(p m[y W :v`0ZN"**iv=]$J7Q: h=BB F$Ir_> i_A`c0 F*J:w}`X PgOp#go F5v{a;`05an߾ud޽l6h-L ;9+dԩ׿zjȐ!͛7f`0xD<羾&0 B-eԩ|9 @4nܸcǎ3f 2|k׮ELe`08j)~~~xe)@xxx? `4'8!BK  s~ƍ8051WvJ\ 圯‚#'/=^\,aQ*]O%%H$$IG :~͡~b&vfutt P(,۱ZV"jp,x%%%tg drUC\TLnD@ $!TT$.o;`2rH԰m:֩_@(?X>K$"$̛@P|%6nN+ҥt. )D" w#Gn:__Rb0P\Nh`ugN'N3r+'2rPGXVWApU7 Ar&MEDDTJDb! L窕J%` H5bB 6^YeILL.|%SZR$FR)U]K$˛Ç{衫O-D&V LF< ^NA*J?Z54cG\;??ߎB H$ŒbTV ]7 $E"ظvϬ96_i!RdRZ d0>R)bx\ᅋ_FH9lLZRUm_?vR)Ŧ4*ڦͻtrܹV\$="$cc4-]hb~\!gs?]\&z_4k',< Tm<\QTZikn"zcxJ..Wа{v?t]WmrEm `~O!h+P0ԫwX}&-[j3~8,|k!o`F^>=ua ,_*uߧh@ P]8g*i=61õKgja|kCz&`Ya|\TN^!8կנdP$8Vyzjٲ% 6yV{E tMӨ[Mۇe6Iy=E6K!#3ZjCF>)tLII޽{Ϟ=?޽֮ўM5U GGh[[nݱcG<"f"##]]]@Ri|y葛V=#B $6mhCq ļyEgٳBzZdW,q]mStIII!FFF 6ԒN4)??BѪU+upp(,ghY,VN!ZRٜ1chCM=*Lddߍ`0xD+۵k[Pd2lqq |7o|oH8qKDQQQ͚5ö 2$<<\U@!;,YBFΝ;7nlذՓSW(T V۷0BCAhjp ^W\\ 2L6䅅i"""<<< -FںuU{'N6Uj Eic 5^kEEEtՖ={T* F!!#s-S۷[#U.9P;_;MB- X K;bS UufW\ь|}کGj7o6me˖ݻwcQՔ SL={*Ԫ`JAA_UswwDXjfexD@hhhͫn=zI9 w=B'r8SV#Fh۶h:S\\'!!pMG>h~͛7(=I&U  <[nĢ`0xD/^d˗/Z:v22 Tax捚&77^zj(Fcݻc]1լYS=|𔔔LpG8b~&/Sɓ'{]XX3Ѕ tBwbcc{I'1bSLvחW^oFݾ}{Сt޽{׫W/:s̡<~k׮;wWy(޽{FGG!Μ9Aɓ'}SJ[.w̙3ׯ_9r$BhŊ'"֬YcX,ի׌341113f̠=~xOOϼ<1۷o2)wwwzTGwׯ]__ߋ/Z[[#6lF/ +..655E988@zz׭[B.\8x`֭[۷oӰaϟW^!ԢEw6ӧYf\\cyBmڴINNxUnnݺ%Jƍua )|!4uq!hsںun-RSS_xAE7(>AoРA;vЋq `5/^G9q&M 8`hh(BBBYPGG;w &u3uU7):t0eʔÇWLfΜ9tP'''P``<7edd̚5аqƟ<44^C`2у >}z?2t)Sh!k.CCCSSӠ~=7o@iiرcE"р>Sӹssb_z)))'Ng,:>|prr?~<=1`P8Ν;<{}ڵbܹsƍ]3%p8@ۡCTZ^=WW7nh>B̯ <] KjժUVU PY%bp fB1ucܹ/Vò[[[cܾ}vV*333|W1 SX8~L ))f͚jUx{{{1(0̯Ob~?tlܸq ԤTw%B߰aCHH61o5){DDf;v>|8*axDJ4mڔWQ(ӦMk߾=6*޽{ա۷oǺ#BL$11q֬YgΜQ໘ b0: FDDnϞ=2)ߋۺ˗/NJ#BLGP 2$667͛7=U gPggg`E!jd2]\\(H?o(33GAP9roz߾}q#Brӧƍ 111X b0CG5k$$$9;;RӧOcZJp,|1D"ݻw~EͷoN?s/bW!^FEE7 {S!44T__Ay1X}\ղ̫W\W^~X8bsm]tر, oX`p `\b 233:fL*Rl6u"99zBe!FYbEHHȨQ aU{є)S߿\żw;w;v Bsukkk;;;R1ݻcbb~,abb.9G:t:R/pBXyf,s B F|D"߿e_hƍT IDATQQQ2`p `ԑӧ֢k׮cƌ޽;VhbժUW}}}g͚E!-n޼yݻwWUn߾]RRҥKj6a8+WX[[c9@|/gϞuqq̛4iuV77<==kQep `4ؾ}WRǏ߹s'3F1ZMzʣRW^ 4i9e|6%""d>x,J'LsV{Sa5klٲJ0111X )Sy3EQ6665jPl۶m5֪"&Mb2U*7n1=B oA,YdXfF1;޾}%\~L&Ú3'VG&!'',-,$T.iJKKH ܶoPA&b$fhdL&W(+#s@mJs3a„;Br‚ q `0w;lպmz T@p //B>O$Ů?HW['N_M^2s+#sRc o7J$B iddpܼ|=ލ`0{{ѣGGGG+aAkpV, u4:gi9 Bm)̿i0Lf9s♥IIffa|H$C -  GK K RN -EŧOY:| ,^,8 -b|D$Kr$]IH>Od~J -9lk')6Y!|>)!:$s!WB{F,,|6zq._\~=&&F__s#a9sˈZB Rh H=)4&P H pM6iBKRO ЀB)%PwVmuvk =RhB -I10w848&ԤG -wHTC҉MI*h܀|+Zp'U xd0H)4!6aeQFu%˱0vlZ^Y1#j8:FݬI+"QpMI>)$$O`U(æ)4ԲQÇ=PtXѣGKԬ~Es3DݻtdsWQD3&O;ИBsRK/@/^ܲu32;/_4䑽IoS/\Ɔi>M>B ,8g]8+{Kϸ}-T*=8WQ[kZEC P1XxXiDm:ac]g8};䟙lf^ߞ]o_=s6EQV.*((l=1)ֶQ5ǦmZ߻y3.)N5O0:}Rv _9o`eGDvI,\f뺥KWn0d,cX r"ރ9?ݼ%)ttu\{0mh#/[_PXVb$>kQzf{W?@q E#MMLF D$ I1zqvFPBAIًwRi>o٥'2zQ}5q_.*(DlݣZŽpkjڪZGqVq!*nN\8A I.oOT  !ܽ>I^eūGϟW|{NHf@+1:oCFl{?']Q2TP(Wuc{pw?qRIT>ʚ>~|蜿q^k8|o^ Kg)g/LK$ b?ޖw^bv&I,-DR"-H RYYD6Ȃ(HETDHADr""D* 7v^Sỷ\=jשm_+~[y\EdITH$#%YD쥙HGdx1/, DHb(uDr"FrF]BuQj֯ŒY2&oe?W ]҄Bꈲ2L8XȰao2J+xxTDOd$bd,8JID$*Q d4w/xyϻ1^bxRiDrW 3J;C ·4DR"X.J$"b:(8H؛3f8RYܫҘHw^=/jPr/*TYɫ^T* ^C=mA[o1H +HrBռ\e\Ϋ Z+3 Hχr)D;6kަeʐvԨ$H$L&[t!rc#9>صm)xWtQyRbiCq$SmOIn(Bxsʞ}=SӈG"𰧤$$FGD’ ƈЧѤP.)>!5)I_XH aa*Ojظx"m"ZS߶NDvIcbHeF*{)q1$Qiݴ[vDe#Srrm: h@o8ˈpRې!2<"&2TR)OGd,%1>TvHKMd 4.O9Q"޵g-D{NM F HRؑB,9>:jRXEGƓځT< %"{LԼICɅGD.&&v99iaOzRۍ1)6>>&H*idZLR؅''IVMLK '@M RX''dځTe"##Hm+]%RR_Т{ă+֖Hx"ڼ#55m]m)[wB?b\xŵwf͘x-wC5iC6 ~5gsZE1a, [)d5iJ*֨V5"*[xfq#kl,9kIgݳtAH0Gjmm͏K&Nރ}M'A'[umӲi*U~ZpWUJEVkvLRKZ]JիVYOx CD3T}1=z=;pwܷjo_!))yC <}Q//'1Z[3ƪml:s19zS_ԴmQJi6oݼZ'ז:W?fNs?|{7ckIϞ= :cnZtGOt:}U ޒuzp c :wufS' 816t`_Dx;{l[=":{]wϮ5WYZE{J5r27oX|>m½kgO۸v?XQcG 6d֨V1C]&c[=X>1Ƙѭ.uj$\l2 1 X^jx6-zZ#mzT_:zt{j"DDi,/16{Ƅ/g͹|rJJe@ޝ^DbɼM1m2cJǪ4V[֜=8Ě1|>n:DV1^8FDu]hR1V'bʱ;o\<~?cM˦1_LƖ+ڵv1VSNRh?ewІ1֬ICX czve;jhռ cL\[Ǚֹ˛X6թ]ʪcFnu|}8~Bכ=3B8Hȩc5kVԡmhXKOǍ8Vǩƒ_GDh>~JD{ 8￿cA]>ܥCo;t6puw_2SϘ~ߣם T(ݚupcDĹS_|lK'[4i\cnp"򀈎|D]g))oS`0hָGU*;ԩ]Ӧ'Qs vKeN56ڶ~]*֫X\%_Co\ 42$u;vdJjzv׮VϘYJ.ujl9UW:D=2 d_./= mۨDauQƫ8;ڪզ@-Zp!ι{Swjz _ŭQKim[hm֨͵nmmm q9*#(8sn7K|ܼ&-4혓۪EVmwv[6 BD!wVѭa kh>l㏜j7iPʭ}:K~ujTt԰vܜ+ua7`@Х 9߯X]N#<+,,t\ѣGvXfNh{'A}ӯ˱#m>l&dKV^}ءTרQl~\koˋXkIIIo o'?_o{ǍJ9WP*ČfEMj_[\JP,%["xksc떯_dMDA^Μ6| hbRV[T~c2PE"@P(B!E"@P(B!E"@P(B!E"I[{^)HR"/וR#gVϭy4ߞy8E YYDzIHAfCLF3" /v D0$ c EãW3sr23LY̌geVH.W(9bkYӛP?%<"Re-"" +|׮0uJPk\4=;CR.ʪ|VVYYϒ Vkڼܼ-U3q͍ /+͛7߭[?>)~{!7Ęeiٙr{ep.=z{m\좔H%emʤ2ʄ )g_dLԭwgMu*H$ O R g0ⱺUfB%"gp64RiA +H#!#ǧ 귶nfM2XYyxLAnGNԼn}Ɯ8u?piQ:}Œ56ʖm{i .@D(B7UVE!.>rJEPzu)`6>}P7l؀ƦM^sNh߾ r(i8FY͍Df#:::;;9U>|?Gfcܹ>>>Eo"4'UTE% 3B!]v9aÆm޼9U1p Ņc!̀kRRr0SNݳgr@@1$&& `sssCI1BQF `4\.G(B]f3339UV={94)"0'Ǐ-S 07oh4EŰe˖J*!g988 cP!YZ-r0~~~G(B(K"wޫW"cfeԩ666<իVZȡ!j5 `VN:FHHHrr2r@@1 2$..9e˖!!C۶m-,,ypuu\2r(i8F!%s lقPP !`aaP(CI1BEfUVl,Zȡa(@丹YXXW+fkk( FʤYYYK~~nRtʔ)SN}oW Pl)))eʔsGr\"N3)&x'"^/nBwرcQf8kkk"R*r 95L&3V{1+_<<|ǎ3tE`nżf#!!!''9x88nҥoxu|ߞ>k֬i 6i֭҄+ڦMb-\{eݺu/MEӷo< 6di4W$nݺ5##>>Eܽ{wY|}}'33S9886n(v7۷ӧ.]tΝpբK߿#G/$k׮m۶-&&m#m۶WCGQNN8/}۷xABBn(B(>}ٵkW޽觟~ѣM>]& 2 IDAT tܹ*==8} RRR) N״iSN'.pʔ)2L\ٳܹ^GM6]zu̙^^^{=}e233'OLDz϶lْ `D4jԨO>,,,z8GdDFFXBoܸqׯ8qs6l@DǏy~ƌD4pC={[ubPL-[|oWU~~~&Mbۋw*2ƚ6m4iҝ;w ݻZmcV_ucliii?~\0ċO2Ç+W{L&&&wu̘15h )))%%f̘1{e˖K{e˒ċÆ ۳gŋZzun֮];}޽{רQk׮s 1bD||8Zjnݺv:w\??̲eˊcq6o3gΙ3gx3go>qdkkkĂqW$͚5QFE Wɓ' roݺu۷_$X4ܹ#0|@̙sС\Z$ !C֬YYJ͉hÆ 'N 3B߾wz֭ Xtt4c,==]<=!!ƍ9coߎe x"aaaw)ZrPP۷ş>|U4Whd3 Í7yբ됕CG!$$'>xh!E|رO>D<1**JǏܾ}EdS >}TՊ~||V]vw\./ɓk׮ 7Y̡hoݺӢEMOOOJJŒD#-""3((\+Wʤ4߿9::߿_ؽ7oVTNIIСCCx ¿{7-(5}W(Bs&^iժr(ix _jf@|K `Fs5` E<|vB(BRA/(Q8F`n(?"PP!0lذM6!!@ 1Bscf/ŌEńcf/(~(@:YYYȡ! DaŊxC=UV##BV#j!YqttZ`P*UVdkkkkk8@D[lqpp(_|ѧl޼=_"%" =:|pN>KBJʖ-{q#V6lٹs  4H,Txwi۶Ν;… K,Yn݄ kЦM'OTZ666ׯ_"C(gϞm߾=??޼yuMNNޱcGRRҨQN<٧O۷;::.X:h4ӧqqqq !)2dȺu낂jL&3FQ,?"2 {K.M6t:R,,,4jP.?|0..nl-ׯ`]vc,X0c "Rj,?++^|yE&''QAAT*t׮]suu'<[ZZ&$$ŋ/_}ԩSǏiי|PBnݺ5n_zG1n8NRrssA:?||||O>ݹsgZW_TPA񌌌˗h믿nѢr<++ښ?~,SRRA>}zll,q1P,AAA]ÝČ7ԩSf))):t yoFLptt矑]v+WTX\\\鯽{^z5R*i8F`n4i{n`[|6M&|LH ;]f+229}ݾ}9v`|}}CIîQ34f̘u"S7`5k"!ȑ#@vK.#Sw͗?qPׯ#SjժǏ#![6m LWƍWJ%K 30sL!gϞ!3m'ODnʔ)۷oG(B(6\L]2ej5r(i8F`<uf(B(mgf`С6mB(B(["89:0 . 3k.!iܸqW\A믿E(B(,`ꢢRSSCI1B3a|Xx r@@ 3x7k ?Fn˖-Evر(`Ν;#PҰk ͜9aÆԍ;9z@;]iѢEԝ;w.<<9u,\!-[?9ut!03g S7n8!g"SP::uLܹs}||^ZFZjȡ!yCnɒ%3BxMEPzYXX S7lذ͛7#!@)c!cfLݻf(B(>:u*&(B+==}p<ݽ{!5kh4"Q~}`lll;] !+W1#t}`ꂃ^ǯL݌3^ǧ~L]&M;ciҤI !#So߾k׮!]!^zժU 9uر!A!wFÇI IJJB(Bx1`Җ-[vQ"q\۶mI_~ʕCI1BuE`f͚0#LZnn.c 9u0ưWM0a˖-EYJ94 BJ\94///!1qr0i#Gܺu+r@Rh4"ct`Ҽe2r^SٲeIC 4j! 9r9u0n߾LZXXسgϐCI1BqӧI[` r@kԩB0iQ5qD`Ҷo~u"۸q#r0i'Owr(i5 `8[t)r0iիWG(BxMgF&{Qyf`҂^ӷ-F&(]%:vW'aεLqޟ/vc(BxSeL7tݦ]p=zvttt4/=5?@$"rJՆʩiw`_M6V+S܊6j/EDFvDd2L.R90ER3v(B(qĉ C@"R /xwx8|^!'H[(RԚɳ[RI2+"ol8ImM&bDYBNR1]H8Hm9p'&|q^-f :?-HbiM@d c?E$E7B wf1Œz$)klI^kذHRx>d*M9"/J𚲼ƒWyWy%Tjs$㸸!'NKJ ^*e2^*r^5^cEMfI-Լ oiexp㸊D^c[ZZūUƒhxJ9R7H/BxW\rRizҳ߭ Yy^cCr$I9^*d9STR߾yILԼ *^& ҒPK "qJQND?5eHa槵''qUJk~qkHUXj5/ 95e/׿p5VƚXM J%/*%U70KK^楥zR"x`9qR3YyyҎlAt͞;%?LJ;b'#v7\?/+5Ht(1%f"퓰pJ3O?vȏpoT^:sw/)l5][1Θ)ϡC>$ {z%%YYyDR}}{v;u}TȤ:ae7T=͈&DD0 Z 4qOv?q{wq;pܩs$/GdUűb^AOHeM*+7HjsɳǏߺryQݺv$]~''nܺ-8yҎ|>}aڳoac8쟝FJ#BN_Х+*e(Bx,,_͜4$觟۔+V(_M ´ ";qfvR`z ܶsߙs ꞽcb"SqFɳ_2cnGpyꌹZӪC/"3N_61νi~z+u|@E˟E3g/bb>w= v1HEjݱ=[:{RVZ{] 8dd"Z/Bp1ܹ|KADt؛w#b> ;&}6}~6vҗ'N;qFJ̃&8p}P޻%b oٲ嫜rUcXCv,cLTƅݚ9vZ͚1)69W3 MsiQJ]Etk]ڶuTvb(cl͏m]Ӎ&d=.NS~>qDqi eRԩfժv1t.k2!jE*ZHB۴(Sƺs-Dq3-mAw>uZ[5!~ys1=&4xp]/Ãr0 vaOC1c/GlGJ3yHXAv⓿Fhzt(XM\ڳ팱jUO>1&dNJ۰\&nW<|Dw7399}nX*j+9>^cb++H۷lJ?|?ϡJW ={tҩӈ|>i=B{Zrٝ !sQ< uY\] *-R!""3((=gk?.{YS+y'"$$1f0H4/>ԶSWcn'͵(tfm{L7rjT%f$22h$ p'!"pKI&#bD{NweNOqD^'!##$Rb 7<_LNDd43LFD1Ɉ'^пxr[}m* S;,1Q8HxdI.^/bxy)VALz_tzҧ!yBS%Ҿʉ\\"0W(Dk,K۶+r oo*"] y\|BVRh|Bb𪎕=KL=ں̨ѥv\J׆JVൻ'*Ex;IoĩF"tŒ(}p۵EB4E[w-7]v-(,ԥB҃TNK0R6j/xMIDATg@"!E"@P(B!E"@P(B!E"@P(B!E"@)"(9r̮-ʥm2ƘnB)#ޔB.ۧtn~A05`q\iZYA_M>(=q\~~~NNN\\)N %%`JhdFVE.V>zVK3#3 2ɕ7$1)Q*ۭ\!G[ Ho><e? 8x >NQBwU^0       B>o><XsuQpk{)7;(,V%%ڿ9fueMc8܌, U6tMW!;Jz2#~MHlV,'4in/*kӲ_`-Z@ rl3.:+Jmb7_Md{[h0Gt-&یNU};K?+.٥t*4SGuFNav#W![/LRqzq:~im MJwU-{۫V_Ag,D݃z{)faiyӷot,NҏșEM-r2PteMUvҥkK[8N)$VE㏿vln"o`E! ͞zvSJ .f;y i'M{ kk|祛p]1A_M"rV51&H ˒7y4%o 5ți\W{Z'ix'o=f)uf)\z͞EZ2+_} !Ꜿ}۵w@NverE ,:~ŭs8AosTT^2ÕLJӀ6&)F>\jo:~ ,] tiӇ+hmglV$]n:@Cv}}5¬s8Aٴwz˲fN {ն654MhpICƧuk`".?U]{8}Mqr EWLʴO =AI\uq0h`R7ӃsewmvUu65`NI }ҷ鲪ܾ88٣:}OTx,"Z253mֹui`\6*|s8A:_7+۪ܹ!$CB47LːA߾-py wӬp'xٽ*|l60漴{8yÇvip,`!A*&iyL2x'5вlJ(XDթ|Ѥ o o o o o o o o o o o o o o oYzwt}¿[Yκ,`k3r;ls_? 'm 0W2f^ 0W5"o?&u#|Va`^XelӵXz-Vv" D}tf3 \΁q>B< ڙ#3LvN#*϶'W~x;5 p݃z 0rǔ4lL }yuv'Ki~`Q1dEܾEԮ?$o٘MGN΁vtmG>?FYtg΢7\lWcxYs$NgJ"o o o o oź{||,݊U}xx.#oچMdc o o o o o o o o5b37vّ757ixA%ok"Cmc#y-{1 5y,ӳgJФ0K]۷޽{}}fj`e&ny^NИ65ZW駧/^~tC#o`tЫWw˲MMK8F߭LR?S"4]VgJqX9< :Y ϟ?/񷨩/os !͔8]g?nVj9lӚwP:V096qat       !(bٔĮŶt+j 3IENDB`PK%MMHPK DOEBPS/img/methodeval.pngIePNG  IHDR@1 pHYs+ IDATx|T՝2Yg]&Z"C]4D_ʏb@ Ny Z$ P`y~H-DڥQXú[j!`i펯T2D|%ӝ^3gq~/_3swܹ___ 0`0roJh@t6:Y:[m{Fr*S Z(JwIk~O~#!vuC,2v2}BƗZ*[ڡH'٧٬%90d(ݚ0Y%u"  I+9/R6jx Kԉ>Q7<Վo_ާ&*h$NI}ܔ /^S0GB}xHo[闫 9"%ݧa.d|sZOc75 MTgbIꪏ/L3RҼ9Mq1+~)X"/I-KZ!Ы^"YɆ4jdKFZJC^W")t֙uKz a-N[5Z$n47Z}nƎAkOZiٵ'jo[(rbdsJ+հS76;YNM3!1p2Tr:$65gnG1qve֚yV}Ě773Rt$lJӬ/Q@IQsE"/{DMLY͓aP"k5kxС[DO Z'IǙlLl_S܅UNL2TfT'JZh[SMp}A:L)SKA=egðH2Jui~'3I ,s߅Ϻ4CSI7Wһ5vɣ R10}n4EwoHIoT| ˗pfZD1 A&d}n1{6pav,đFAՉ1<*DIvMJw?2ג>t%S` FNdxگl9Puc:F\ݠDgp2gH^蕫Z"g!I*Y'U'O4S  @ ̟蟋(K'+ 0 Ed\Hi܀) yKql2h"hNi!>k8W%=K)CϋLhL̎<fIJNsFJgd܀IgΔLHŀ0$I pG}qҌr>7`_/ Q?IL42|S1Y)bBK>R&7ɓ(i])]RX8K (ƄLh -MvJk;we:)&LuLŧ) L&fDat!2-k2%u#+U4֖T(ͤ*VK_fLhɄ9Flw])[Ap`ɭp[qpME3| -Q*"%gO:Z\!0  g!I6z%c0 e۳?34{Do7kO5,i*PI,bx!+YE)3Vxvd`fOs1[ң4̟,hV$%d0#;&9d!O%3ӣԔSV3ӣi*,f`Хy5hgz 遜>M%X `&al40T2ehv!M>'ya:IO:dc*f_e>J.DqCyMS)؃ف̎i* l ` A@QR0`0`0`0`0@j`0 Ma z~S(Lh?{GWZ1W{ sSC|x`ʕ= 20X,6rkvn%2+kŒo%TAW@A#6G>z9ɗԢTnc ^`#x6 i4V) RxH:_YѧSCzG7| @&0Y[ZEө Wyi݈! T.D 0 0XqرQnsS^z VQQy 6VTTP ~G~HUу*_| `燛77-[zpcGӴl7ox<GIAQs 7= )H'B͛I@CF6mH=g×钓|NȽ@10 0 0 0`0Hm`[[[ ?jjj% p%!? p,C|+To$)++b(_T8.?Ⱦ>c ?Y8,W5>/hW_o8`vؕv&?5IWaL ,{2IC\ !̱,P]婞rJU's :f%( tF&S_6\pek G=8$ޭ̮$M9,Bd,'a_ ϧYi#g]`*t̖kUf'uH$a_nh@fso ?d$r d/?yd `p}s3badZ?χOpX,6+V&t3W[[^ŭn@0_H8|b:z)2uS~+CP&z@X{F1\.^|ɒT70 -A`jgz{?oҐ Qb{wcϿ ^ **Zּo[n-z,' E"IՓ zMw[LP4mooooo%0KYSvB>vƜ9v"  %%%>oڴiӦM|%%%)I6tʣ0mظqK+)S==Mx͸Ս(ÍŲiӦ;v>Ӽt>|׮]T pX,ӽ^𠢢wG?ni+1.:%%%oF #ND;tnCw-?,cN5Jf<СCT{0‘Π!1 Æ;&cǎ1F8-^bCb~ܹwӧ%w2dȐ'ORd`3E/EQ.2dŦ_A& 7o^YYٶmK  /"P0h^ W喍f-J̬ 6P(R;s u8=b^tQ6-)bӧOy 2.?\~X,F푁PZZ֞=v);G|/y`zMUϝ;sI zw^:5gz{3z 4۷̙;wngg֭[of/>s~@fucc݂Ξf0a͛=UZZ_2i$$sιC6zP(4ڻ*w{,SUUUTr&VB$;v̽>o$0護v?yw۲ýs-/ܩo[=ܽ+}駧ONu](4^{uX[(!-kVu%zМ9s֮]{p>SD/20@رu5K-l~gM`ۿ|DMvQ\\?+صk=0Xc+oP( N$ (p3glٲA]G~?#үg*rY020I>Jt'.L|y1IFD2\cˡWIpe$ Y|HAE z97" s9㣚f:D3g5$z9'޻woeeeb7L$7Iu8a +1E"̰P  ^Jg!C" :`-φ555~Ru"HYYY,S/x<Ƌ߁]p4  ~ pdFKH@82 #%`0 FQ7<πw0[QQQUUŇ#G]jW\1b칃/pYVR3=CXrBhB$ &VVwͿ~p`PQRض770yVCm ζlh ,*\M}g>`pp8|]eU^[ZZJsq۵_@=U `pߖSns%a08XwwC0`0`7OX>Jo,/'\GIɽ>fmKnk<aGd` R>Uf[i67ۧand$+%lTWI_5["fmVVVm6.F"9Pg Wjv.ާ MK߃zhTJz柆Em۶566fPh &©2+Cb74@_D/K}PJ*CefE2'sxy.D @I}EJ.&VPl!~FE20Y'3|U NFYXGٮ0/20Y/s,MI@W$tJxm H;::`d`p9[\FMRgh9NKO)rӅ$4l] "ok}Zre׻k׮H$oڴ)q" l;Ӵ׌cH `p+P(@ԻwQSSm۶FFBw9u='gpj<4ы G)ӧ ܹs;;;nJBJڳgW77eX=u֞=D/0… %W׿m a xݭ>zz2q3k}[{`hȋ w_x0kbc`HI{{{{Fq?vK̜9JR B" /E"+`ϙ36 ÷qMsj+ob?lKEEKC0EQ:::Mvر>0z'^ȄX,6+Vn}惷jk+"!dp:CRM IDAT2dȐ!C⭀?p x^ڹsQ uxg^ L{>~jomyH,A,Lh>vG~az ,! 0 .DN0lkkK!GMM~w`pH$RVV =Ogg~rQӞ.D @ KH@82 #%a_d` ~m`0 ѨNvg; N@"yUV}u#+ƞ;a%%n8ӟ:+W| ࢦ=X,6rkvnp'UW:E֞=08w!]01z U=& R /*mz }b 0 0ʍױX>sLz($ {cB5gJ`pu7%,$P:MQ@Mt4G_%Ilڰ4G4pI`ń,N4fEx x?I{W5Ŗ)@l ;1Bfg*HiԤ9iDf[R0KR>kqB$'.p:X?@.D0I3ӌQ3?jt2{ЮW)@H0MOfaaV!a0V%I{0 2Y{BWaBKۧSlӺC{QӞ.D 0 0XqرQnsS^z VQQy 6VTTP ~G~HUу*_| `燛77-[zpcGӴl7ox<GIAQs 7= )H'B͛Jx`Ƚh4iӦ_Ds>|ȑ.9Yw @܋ $  @Eׯ_on:Jܿ䏥>eYs#X^KюnS*ze&zY lhhQSSӕq4['}xKD0V0aX;~bUW"HYYY,S/x<>F! <їM\Yn5%V_W;IPǤjU+ >/h@ LP&>GMJgxiVHդE*$ d`9֧^jߏ%M>grG? iy9% #23K$3[Ir9S=e0|U1+﹉$ d`Gz>2R=;Q"_0W:/&a_ߘ0G7nÇ `d` # M}E_[L< Ȉ;vΟ͏>soظr 6`PQ(gz{fonOU;\qQS Dщ}C-k^^ **Zz'G"t8 5-5COM%5P+.yw_yKyRuu0𗅅 OwO?;e^rU̎;[nY/Tډ'/7{|G?sK B"`Fy3s՛(i`Dz%c }z10gtWIUa6~,ӹ$4CbIYC t!&U3s5n?hp0|2v%qRb6T7QSߔ,<), z1$  fY{V\`զ+yiOUƖA/1`08%Ɛ g!lSEQ #+f#+*7xc?z|gF"@͓)ydMSV(/D"o|7|Y}ןkyyRZ\6^t!ps.5k̉W_bEuu3ڑeͪ='kiaQ k^2{%>'ݳa1 w^M g8K"؉peʰf'nBnlټ =ՕCY>kѣ^ڹ#ד>BxS{6\YPˏOu.ibd%X0{5^mnzV 0+[4m `9Ww)dz$+Y @Myʟ鏙Cb z .>q%Ғ'5({kgz{ۖ5:{ _2/cʒIp<^0 d1 1{.DE7o9 -6Eb.i2=_Ϭޒv-yaJͤ^hB3GIy6]{[- 1EG\Hټ<%)J_z3OJ%^37;սIi;7viH1 ?IEN&cЋ 0>p4pHA/`|`SS^Ӥ4Cb z@f`~6lܸu>eXr}T> 0>pTK L# 666< 0>pb[hb|& `pTa{$ 0`0`0` `ip`0֖gCCCON|`pH$RVV =Ogg~xў]p4  ~ pdFeVFfeO[F%'0/20e3imڰqo}_t`DFeS"74ۏ]`g`͓9rdܸq& ,{YLB{H/s,V 9Z B\T8 M}Ћ.=3$ e+$醚1ɅA\|,h <~5ɚ]\H)\Ҏ;jh榟zV{IcLj|B41KڅteAO"E)>|l٭7qxT7LZE[TWww_KYus--;s- t"%WK* :fMQaq&=z+dʾÖ5OD/EQXY>p8OrFG4YV%efd YP(tS~w꼻V:e~êLioo3 9` gMImd+_AֹlG`ːlN9&29f"4~B纆+/YQ%.XJ*ы T?%ꐘGCd`Y%RgI02bf@f+ɂt\}_a+V\l$A/(O<%fyH. {Y8OGAڱcc-kZZɩ5nƒK-ߙ HuK,_B" A/1Y`Ǐ6%kkk|BDaذqۗ6VRCY[hV76RohO tXlQ]'{a 77u--^'!BEIՓXzM(eʤjĀH,;=yPoII,>}[, þU[[rgp=}ŝƋByݭ>M`LoW|[{ z0odb'諾a-7f /pQH:::fyLlnզ+yiO%KE{gc^0'Qhlc ٖ^@gt!"dC[fyHA/'~l@7F~NCb_M~}jk+݆03QCbf$;ۻnQGƄ>݉?-Ls޾{c W-_d̙d` CZ̰krc8;nS[yKl8 IRR<Ÿn}惷jk+3 T\bIp'ĮLP`yİ=_U@ @ p"\' %ٿw`pH$RVV =Ogg'S8=q=:>/h@7&8, #"$ ~ pdF@LO8Q[[2l07xOpb=|oj.lj=ak\w[6o&q?B*xjkO6nHm oLD~٠"j%.߷wО ߍCrAEE7zL0*@>kJyy(@uww_0z@ @ fxK'ŏu,%dS0m۶m۶Ȩ7 Bԍ dy ˜& dWex;olHYfL~ ^R csd@"_oٹxf{0`4m~B B7)k O'zN6R,;vl:JW_-4K4H~C=}jUUDE/ !A=+)a 0R(JQ %sέ_Y_o|%DIzGIT~0Fsܺukii-G\Ʒ2LlNutf:Ad d`pj誯-8|KJ}A e23,[|y0x/ٴS.^?v*tK0>psX,jlmmsUUUP1zF  k lhhQSSӕw`}L"HYYO% fa  zd`|c2~q pdF񍉯KH@82 #O9rȸq>LI$k:::f~[]|q8N2Qo3@[~޵k׌9sG߹7lܘ%iⵔ=NLs'Vع:{!CE95/ʞ7^b!Z9̬phOG"F>Bk]Xlw;xH=%:lbee4͇J@cYf$ UVObeNwԅ߽P(̀8 ]m Q1-܅޾{c,.^|ɒ3gJ}Q 2.z]aݓO>O 6-~E~H \QP^=BKQAEE˚jH  D,z%:::g) N߰)U m` ̱aƭ۷/mZ?$:Ӵ׌[Hs *ӺX,ӽ^𠢢t{sSя^޹%[ ^/A{S y<Y^4kYwB!OL}S3zrwh6\O@WojkK.I6z^'/|T;rQ^K&TOO&qw+> =o`Սu 7U{o󉮮jo0~ܸKNw1%z$>$V:NsW{_}g/dЋKy.DXk-kVuA/dyw|3>>~Yߨa Y89S9O,1 zU.՛q!1K0pEuu%%g{N>"6G)`ͥ;v<䓿/䫚%zSuwC %[5S9 ȯ%XBr߁`  7qu`[[[ ?jjj~?8?p;Ǐ`D"eeeXLtvv22.D @KH@82 #O%a_\ ~m`0 ѨNvg; N;G]jW\1b칃/pI5VR3=áG>f<,<$f4٤f9 , lK,!1MJ/  YhŃ^bS6\SN}\օ_"KuHM1,']\ q@^bJ \QP z;$h?ڠXbHz% 'w;GɗmظqK+)!N[4iup.՛X,ӽ^]݆ۛ~Ks BEIՓXzM(eʤjĀH8DqsgV+$M>ߧsx P nQIطjkK.|v,{yܢ M|wk륃_Xp's:ۻ֞7^ ƺ=v7jo0~t!ttt̾ΩP=M+W<~J`@F>$ƠBDqHA/d[Cb zy.D2Cb z0 Cb_M~}jk+݆@> .>$6o.Y>kF!3k>޾}D/ キ'.=p_x%KfΜIu0 9NѼA}g[***(X,6+V&t3W[[y>, ]<K;w=*>$zg^@8@|H윢"0p8?emj\M(~i0Ua48;M5jv0 3qRmy iP* 7W=鉶%ͷlïf{Hl*9~?~40;Pџxbg3]I `LA/֬C1PҴI`pb4j\֪Qg}ꋭ䮏Z-눷Jz4L )!uahMܾ?(a /SpD&M00/8ws}f"e)8 G \,.Dv'/YN tJ.st7bd`@F!/,NH=X8䘍: KZ~fRSޖNl'}ed$Dt!` `QmeN2TTBZ@GL~ W7An{.0 hߠ\JL.X}J%e`AW]`KPfzH2ө r ] =&vJ%ea,f#l.XGI*YQIKt4GưD˨n24S~>=eTz<) dJzaHneؑY>J"zGC+'0m>Ff-gЄBE" U 'Ο)s{&FI?TJ;Ϫe8RڡDbN%_{'H 17 tх @ ?Ei{=ػIENDB`PK)IIPK DOEBPS/img/interceptor.jpgJFIF``CCX"   c   !1x"WXY2579RVq 6AQ#8%&Barv')3wy$(CIs ?)@)@)@)@)@)@)@)@)@)@+DD@DDGDD|@1P|Ҽm˄B@D-@7Y}#˃hRRRRRRRRRRRnD뭴n.Gp!ץp[hkʁJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJR_p  !@@|B!W(2Cuշz7- ğ7jV˲:VnCI9e# s\a9!5 6QQ~)W~VBw\7kƿ}:ҷG_xz~VBwV(">JHN}[ ޯ=Z4{+t}!;Q8I+P[G;Ȯ/mww+k:DD{lRLW#(ōE m%d%&ɭ )pXb76yclo)ef\Yqm^D.ew(w<I! v]xr]D-n0Q?RsZLrE#Ͻ4Q [F.@۝/:6֋گNGOM$7sזAikM4 Hp<=]򍷓o95z֍!)l!&%&F3]2~CJ"4iN/My][J7 heݍuxnC1ļfx S|l@ Sfn~; +mMXZ ZAcȍ ?0v3{RN7,P|ϘѬar0c7˓(w 3n aMVBwO>JHN}ѥ][ ޯ=?{+t}!;Fw{n'ztWPf*M}$•tx$nVعtM>g;~ C~p4%'V)uİ*Q&:?JVyrWrJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRrmM+H|d/Hh$YB즓' -I[+6g ǔko Fע_Ԡ|%w^R{+y\O&5+ka=!l`d&nfYÉs&[ ys*̡a;U(0bJXR8GfעBpvđ=D~Kn22j=ǚŐv4΋ӭXJ܄|qqK= .qJ D4ɪG8̨/Dǒ)T rQ$YՋذJ s=*bXS_؉eᛑq#) 8_Wc2H?-VmljH՘Y捷\:ٷOD#^FmFf4&ljj{w$"pXSiA7_LS1$v0JSANϒbƣ%DX05I*I){+yY{0@gӺۉ}ƚꍰ&ԧpZ\p-E% )zM*z<mx}yniaER83lHI":߹Ս$#[Hy!1EV`2+&'w.բ -%h}k.Ym^7uhՀ!ۭ=z@נx#1cVn\v .x[ٸ2Kn6 6euۗ-lmhfѾmpZ-Gpu ?ARYmon@{V^h^t[rنm͠7[h t>W;%pץ pe !@)@)@)@)@)@)@)Ao y\=F{7vnw@<}Tvmr{]шB#߲&bRe['Y'&^7('%մiVWͺ,c^` yfqBinՌD@UhkRlk(]r1S._vv4@,A߷鞜춡KO#g4t|})-Obv|'ngj>nCK+Ta؈ ՌԦʹAa4E$c^RLqfVTZ[4]@$n|*y×dY6"ʐ, :qA{]$T0aMIć)GgzN J eVIP,K`t3g޲݊HZLVH y ʰEYɐL1%j2W#(BPHdT l{s2k Jl! \ L1cJaJ ۲ H$nAA4Uum#ю49Ȍ+.I]6@ʿvK2 ?nItlV2#06U7;$-wX^Pu[IAw*gœ]y|+jryFQu?.whf2pώF@g=Orl؈ZrGv#.ռ"|P"aEIE}am4]dyn +`Á`#S&\; Q[a؉Ť"X̀tMx\JgkE1E>U,P<x1ǔױH0 D,uWY][%AVES b+ 2ح/M҂vڀ-EBW1EdPm PəokVhn+c|&+pef ߊ{9EqAN8νv9Hz#_ D [6ݼlהȖT0%-J*\$;ް]K `]qiRXJ%GT$i\el js+:id mS*B?Ҭ JhqJ' @fbFe>w[^21:]3ahєhl cP=tfdM͟y"'MZiE4Vn wfVʢE-3Wɔ.Kצ'ǙɌu>:͓x /mvbȺV9ke(=`AvZ*÷v͈^6=(s^vgS{YboYrDl\̢g;kU'vژz-;/sWbν;HQ*,#JH|ix@sRÆX)RiA9+6A- "T.D} pKIƅqi C2 p$(B泙AK}r+ls$[Pbjl˺00tɒȸˠj쫉g2 4A&Q(%sT(:%,&#X~"x9nZM*i>:lYOq#̐l. hE1(*ʰlFmqyױU{/}h:-re͠Vrv}(̲`Il@'gLwɪ VʸۈFˀ-gd'K-tr9[Dt8XnI(Mfmw׈tnvIRXqBMK8vŃ*:(.)("cE7AO^LVzPMQmͭA gblL:*eKU ~$DQd6Cċ%\ ܊?9յ9eʐ JrŤ2&Rn.jE-YP"x$7>'&#㷥Ep jIkq6p# BMIl'{=xrM|vqLI.}I4b(b~dΤįlrQ85ΐvCn|Ix۹,gCdJ3fC"&&Iiy4Wwy*VĜE-2 0wN6&(}.=ʦĩp!af&Onu] 1Huc[3!c<抖O(E=J*\; ذ]7 `]rSHY*eXT:is\bip$eRm/*^2ߊw9)nem@SV_s5Z8(@+2Qeyl),ff:Z'V r.hBA-&"h L+}Xq7VAi[1]0 WD۸Xp @6mΦ']nDIBKW b--xˁ~Za 1LRtv`ܣh u-Pqv>s~v ޵ig$b^e6,ۉ}*KW"r|+]"zlI3gN6ћ Gٖ]1 B}n/zzH;}pIfcቢX6w` ^k+obAHmc"Yq|^(d5ULc[&02rmD.[A,I;NTƎI؍*՝3-K΅g@9HHl{5ٕ15_SvnҹBѺ"". `uue [hq?'Nt;m-r6vKd ={!nN'zzlnQ%\;܏.kHy?fg%,4Relɬ;uJ3#o`JI[ll+hO62‘tUsèo(\ߍ猸/ϺiQ!1ML4XF89m"iۧW=K̡mսӥ/rY[8 ٶ@kuwA!G=kk`(iE(#%I8%d%inKo9 +B70_#3*Q#;H!L!ܜ֋\|n>bwGDYe4|c n9bu*'.$,C3tIND]ѶZuϒ=n9vFo}nn(u2^ پ~@فDFK=n- uhm~;lv@0^.ePpgTS͚ Ͱn൶vmd ~vTTd}5!˺3ǎn91JX4n=78f+\e{1͌+-(lmDzz,+^:zͣ8TZ~±>FP+{^npm￳2 ܃- 0݄. ߗd-m<@=v[u'nG%ҔRRRRRRv"i14Q䘮I-i#sU[k7dgJsiLWWߚj^0hJ28clE$MGu cxZkŰ!,# &dTTz7cpFKiizU 5Mvaȸd449T,E=Pɫl9p{W~?u;_:AO_H,l S58yD*@ 19:c-ѿ-q5竎JNg0$i1'=B2vI]SdΚMG륰RqVC{!#UT IhK?H?֝ ~Z-;wc雳x0`}ևQΣ6tzcitdW\"oXvc(CuE©d3BĶi%2 +# `'{W~?u;_:AOemňLz\Y([R[(>Ms:2*xn)pRUK?͕eUj}uH?֭ZPE] ~Zwڿxt]jեUj}u睪脅g_a?뵣gG^ [}"6@ Ļ\*eYսw&3E˘]QYzb$x`I]5@pH?֣.*~]>ӿätV("{W~?u;_:AOj҂*~]>ӿätV("{W~?u;_:AOj҂*~]>ӿätV("{W~?uY hs%$ f6_:$W&k,0lJ{ۘ7>+ɛAj:xw\%IE2vNtlXp1ŋQQF]Gs#ys &3d(Ld7R E.\zv:=tk8cozҷGWNRKQo#+wd(4N얳8}A[ӿätV("{W~?u;_:AOj҂*~]>ӿätV("{W~?u;_:AOj҂*~]>ӿätV("{W~?u;_:AOj҂*~]>vlIe$YR|3r uC=6LL(i`B;%urr6;z95 SP#Eny[(- {]{@w@h0 6A |Ҕ R R R R R R R R R R Rf~@׏=VJ*qEqVzI SFjcT2mtY=S6gˎKw[yzUZ7Ym=zZ=.C4g &O&-SBGS{{z i- RvɄ:0ѕ)5u]v&cEou͟Wͭ;'"'8 -o;vRr6r #-™6d8IB(?gq"d b [p^7^ [mwg`[obqm ^<};!xW-[3wg͏P%^uRS$P|뱮"7>1%0Nx%,F:&sH8TfK%d'nLuUqj*bvFݏIINi?Kn yí.%xVcͺp_>:۠zDdsMȵqLuu[p]( w#@- -/ Q:\= C;B!Gz n^>d~lq-k&Do㭽$jt9 ),om䄬ȑ)kK$1m;@x`I!ФHf̻14Fid],)dG[_IJV7UӕX>OuѲmCdk|/hdC!_Sn˔:^Kn߲h=4#0}f$ln*#,.9:( EiEΆs|g܊u-aZ6o=Z{Jz_Pԃ.ЫAdMIq=:Ěa?̯\KMk7يгvm:w@lnm_H_\"7]x\=;]:`@XmUfJiyGws.4g_Jɻ#),BoHv\vcT$sg7y_m+ErLjA $M5[2#b a% 5cD4ؽU^ZĹցOq>k Қ H ta"Sd.SegZn6?*.?{_R`p\7]ݮn#o[%pnɐ:p7=Y>ɃMP=zxרDFJܻIM*d˧Yk*ZAjV TtCyN\;#-٬$Nz!{F66Yq\sZu\nM).dt%MXKM>ZyXOAv|-DSM7nr}v7'LåFb]E R6:^9txr@j82JTlu&,KKC 2d6gAxu oL/+ ǒ!Bۮﻨ:]p" " .^7bţuhz!ӭ=F7kʼoKg̖UrsA8vf;;b}v.:xmטά2${`ݤ-pݲsGj x|TU#vIdˊA+"9#UU" -^8rIyG\`sxK2xmޯg?ͧBm݅A\Yo]m\@(@pyRRRRRŏ9ݛŚ˃$2a&<KF񈇊OP8ܽ-6eqƪ>IYk\P:e7=CMR|~[J)J)J)J)J)J)J)JEny[*Ѩ~0M;zkeJRJRJRJRJRJRJRJRJRJRJRJR,o磪9UiYߐ5GUsҪӠRvi YrcHf>"y=0Z~fa5sM$KQ C&S133%˔Bmo.Yp]}hnV]ӳ}և1nFΣ5fr3[Qi+$ɭ_>՗h`k0dY+Qw"IeKO0U3q5,/gMP!F,Yf4zPdrz~㜩Ӎ;YX$Äb.8Xs7e5]#O"Bi :I)M5I̘RK:DɓwP̞dmז#gF-Li6j.4e7x2E]rg3VȦJHψ:#½O?,xC{@~YTd5( &45( tJ,t FBN˕G#vGcLqAI?j872[2#ػp Yutu0  ^'F}½O?,xC{@~YO  >5P@>.>}dk<+\|$׏:AWI呯huw+^\f>H.LnȀ#.l}98 0lle|n 1aÃp+/}nY9B{)f7#m"L1O_4fi"^c*UZ_VD܂Yǔd[kR5]5vURB:o0d}1'`eoi^J L2(Er6d:&"Fʮ7^]Nι|+7[+)'3*q|fN&-B/ :&0_ʼn^.BK)CocI6܂؍dOnn9&׫M`"ڢbEܬc &(7:F|(!}nb `LuQUKaaG=p7 OKhRLWww`cc=×Ûr52}1mDg[#ۄ{]ķ6Q{hH:XƮ9#ɀ r&`KK2&o"(IKl.ULjr_-G_۽[?w[@no o  >5.>}dk_Ԡ|+\|$׏:xWI呯huRqq#^>^'F}J½O?,xC{@~YW(   >5C.D@m#?Pzpٺ;5y^^4u>|ݷ>eiTy:KDD`|@Nz[u5%DHN%ԊyK3Le&3euqq#^>^'F}J½O?,xC{@~YW(   >5.>}dk_Ԡ|+\|$׏:xWI呯huRqq#^>^'F}JV͒EЃYob/'@ ;/ zuueݢ#mpvnZ"0tנu 9`˓}Y{l묋uu[u]mֈ )JEny[*Ѩ~0M;zkeJRJRJRJRJRJRJRJRJRJRJRJR,o磪9UiYߐ5GUsҪӠRŦztTlR?j~?wz%LCo7rJP;,eIJ\FMSVs ¡Yp?ZaLFJ|EI³}K#ՏsdSyMql\ˍY3"seOśChz|j4>9$d',LXwz$b4, }ߢ {~䝓xRP&\&\駒#qF)B[Xok'[(ΝqA;@Ǯk %8\ʆĽf6SMR܌r*2cR9( TBb&W91ĥmunx)OdZdƐIqH e'* }.(./ϪlEK1Y9fs~8'gAսh4 %,!Pi-h0zԤ9ӎ7Jܖ'fq/qyc1_L/Âe0{97WJtɆ i1cnX8 =̋ԖpSVyr5oFkzq&(]p>6F2̀O5m#Hf-9HbI2s_R YukH5knjkm5S|i,rx> ㌨U@&tiS늆1ې[F,L^2/~l0N{δ SEYLF=I-,b &0 W&6a(1@*+4k#sIua/ke{ܧUWKmǮll$̯1)h!1*q(5q5sy.}# D˵AxN?%[TUZ:Krœ'!sAMNِa>T<^>/U.YX%4L 䋁b 8D?H^\2^7ޫ?A URUf*oW[q}i*MXn7aKJ'BZ wbZu jFf򼧾sDv^ɬ+kӕeYosE Ԓr#)JKSn̵umuMYrŗ.L5 P^nTm%oLӆ)y"7:2u7'Wi'\&zKO#u^**Fo2i[`h_u=gP]mqI/h.$o5߂|#l>-]a#xXZ\&2Wb3\r=ie3I i)r;=l?7Vo8ۆ~eyj^4g̨bcE}y9r tC[V lg72#m/Y (2Q/M=9.-Eu)\t^FN[H^k\O^.'fc&RHZt.1cg/knử=Hhb?ʊ 6ϸ ΂tvzkDW6D'D͎h&<+)q8ďA)ik2D!%UUs~Οs[K{oB'kv;w6DDb^3?50sq2($hͮWqA[ʐ xm'|~R=Z)؏|~R=Z)؏򢬵asa[hm{kh.F-p(F́m!me})@)@)@ 哳㻹z =|+Δx?5uqQRL`Tke5sHw3c W2n]JM IUHUK%-716K.^4[,>?RTsX_.w'[qkNmB?&\ ^^^1:C)7٪Pc[e-_]2cX'fi[ a)-q ,'=#-{3<˲j;Ma;mLq$])SiG !e0rV4ٱ@Lj6pE}y-b6==@:h "bdSH6LҐmhKn 91C34Z!o&eb-INMLN,Woɼ]T%Inncy_Yjɳm^Jb >^54M1"y}y)&g_RiR8`#ϜɄm&c#s_O!Nh^3gbn<_m9ov[(1>q'L~I:ZZtk{]M} *ɧe%%4{4j왯q |eGͽ76QHY*}]#&m6:;\- ~.HNK}3^XSںPdF_zZc>T qT˭NKبje\:ҲsDS r2jb*v2)I>za%Ė){퍜FO:漷 '3v9GIHV\gRx4X,: Jc.[YزO,EN^G^q3&Wl^BzUm* ք`ntFY;:jL٪PaZ>zJ$Os 8[әW$eUW˯&k ghNj ya9tӖ$ZGbwV8;;;P. S88O,Gվ!/)ąѱLC5֗Y <]Q9wݶ>!-2z\DxO69M'c0F3zڙKҠDW'2WYnn{ Ur]"I@҃#[%{N'KڢIad"<1rXn-6:&oRm2iQRs-Y"|TU3 xm-9DZRqr x[^KFŅtL6ܼލ!lMR嵋ouՐޱT҉pcیIX2lXL4A%a(44fbHSHIxO䬾 mIde}-zx0ʼnZ@smzPb_c3Tth`R ąHφN[']ۅmXT'"AjILMFκ2HJ}+leFimmn!a5]aa'ƒب+s.Mp0ishm ~r-y(ܿZY'rr5h7NO)aeɖ!0rrS~Z.wdz[$e[wAN J  W,vDO^}Ph +?,\Z|%\|.->?YzA4qiqoJxXJe%ҳŧU/])b*嗮hJ  W,vDO^}Ph +?,\Z|%\|.->?YzA5um!@^.->?Yz_.n.Jt-6ٹ:u-@F@ Pw2!m#bpcG/ˮNJF`}:IX;ǧ#{Gٴ0e-dM]K7TZGt%'?0u\-_Sy:yzrl{]ke}efĦZm y3͖mIc#n 1Yaׄ2# )g0Fp$%J\Oa>&~2jغ!lti&˕gg%J$isk<_,?YzO  W,vDVxXJe%<,\Z|%\|@iYb*嗮hqiqoJ gO^}Wۃ.gX$`/q6|_n/D[fFKK~O <:צy2jYQeёLas&Kv98ny'\HEEAČ76RXcgˈr1vnvGrIp/˖'X`tVZvnGx)v5n (A{_N0 IA^iWd NyAl19 ]38z<>{KAeWT4lm[N,wʆNOe"O@H# A{ (jj-5,cNJJqf;FaBBu@: gO^}SŧU/](4.->?YzO  W,vDVxXJe%<,\Z|%\|@iYb*嗮hqiqoJY?E%`s@/䷎Y#m`9[dj4a8g;#4¢ڱ©iĎP;2ϚݠRT]?&睎}=5PZ4(((((((((((("z:VE^Z;4+"iPXKLW'E<ͅSH( GIωg|[ G}#p:ϔ|?=D|thRgS?wRgקg@z^ӠuWMňuހN=t]C7D.P{C?KPݞ5ӧn˭h/m6u X]ӳv=:i^Z6A}oO(_hP:Ի]ljC~,GN6=4]GN=#P>A<Sqd=D8CNzt:䠿{C?KP(qEŨqB@CNu@@|Ou]ljv.65@ - }|\Z"":uD|hRgS?w^,vmhӽuw]:PPmk]h/^;pC 7[<[|9CUqPcxГf˛"{s͇LIj?_C9f|lņɚx-xemc7F '79ǔ zLPo-A¥?lzNr[/;7E 'qfȞ2t=wf+\n&јKE3L-j6Bb"F:S2g9 %؍?>yNKmv;vod"Kr(DY -QTF%%V&f1ye0.uC5 +GPbJC RK0eI7bwE0h l aYf^mjq3%(QY_aDz1jzRv)&\ >s_/2LI"-z\ѺJ[z͒5y)+QfM7I .-j Gҍ^o4.|K.ł642 .L-8p +{ 68d\x+3&P.%ph'hRgS?w(x =ku#oYh_g:}ץֻ]hB:|҂]ljv.65@ - }<<[|9 ?wԻ(x5sg4Pmk]h/hRgT ?λCŷ#w9C?Gnm]P/o_@G:s^xLysa̸xǓLwcdtY}]e]m4S7sjɩ$!m/$_"z75W s.8.+iB S1 gFCw 6ڽK^s/Zk#L'dd=LZ]Ne?Ue!3(X;̘}acu]ljv.65@ - }<<[|9 ?wԻ(x5sg4Pmk]h/hRgT ?λCŷ#w9C?KP qGŭ[Ɓ !Z !#0Wςo_@G:sA}v.65;C?_u - }~^g<ڸ-  @n nhpێ{VwA=z^yD:h]!GWHz4uJnN Wo9[k "j $&,y<|gşۺ R UQv`v: FYߐ5GUsҪӨu kǞ|U@)AL<#隬 F[b=f6g_nu >:p MY-yɻ h3"a]RnCO#eKKqef8beTKi)~*= B307h3X>ƵO%ǚc1(}r;KJ.SY!i=7jŕTm.L ʜMSJ/m΍GM#4 .]oŇ]/3e¯bXȠjs8u;j_Q2lN9G$v3>Gusk>>=&\:ulkm] FOPrz)/kTL~=L8) [u!Ve \o#{IJm޶g^=D\c4Uinۭ4% #;mQYe]UGb𧦥'2||/ɜax׭hb{7X"f^eKmH-˕e1sR-p)2:9Z%k$Fj'O3 UC'rnEwM5䮩',#EдEZFaBP$Ôbiu|  *Nj~A}8䝳<@fXVюأ { AR&&leOۏ,|-`L6竇C dS?wBcx`^Dss)x}9ұەY[akSSfCfO\ Kq̝4sL98mx8ZIv+>'J VJhmƨܐYKNt Q>0˭,6mqhuA?7j|vl%*bȌqM;e|"Hʒ:dmS^ǻXypk2S Qmڭ`]q]թXH/[k=D8ћ=mf5vFp4_LnLw9v#ߒ.l@m8邦1dWf裁v+',m@p8\I,iyn޼RəQ}Wy,s' `E\#&a8A#F,Ed=tWZѻ' VjHҜ8mAl]e[bϱn$˘Mj'VgDSiZ%Ԙј9Ңe ,-4cb p?^Y,ʹq4U3XM@Pm6!nNpc9ukyQȾ0^Ń)m2,HFN]KrUM0 !CɦTwԕ C[e[d֝;E![Z|^mjFBk Bv+M(w0ڮLnrbj^J "`>P ?p- uqi3e PLP+f˄1en$.cm/aw ~6~lw@Yx]wu8wfqN9SնAPEּ҇O6(rohc9 ˗ k3#2Kf&twyL@%)A@ڕ<*DT1ls:dKI(R5I 5 'aUs¢X2 knmmvv!d-oj!n6u'{91R؍GhеM' 6s[%5sV˪3Ʉ)WkIZK&b4rkɬqvD_Cf]0r,b[ƖZՅVع"#'GƷo]MB y0ARi*HI8'GzbŻAR,  4/'[҄a]xYՓ=r7ܙpfrdHڕI&DdGMީF#mK4\_=H'R9ub|whD1˰@%i^=h&! .FH\;a-ET#^#viGq{:N&2TctEx\.rjmϛė a/YQ1qZ "ܳ޸w% ͇E-Uv`U_g#qȅ=mvXo&)Uk3zwesdb(Y ̲lx\KZE3nA,"!س=.LB_~8he%+ʽxZb3aP''4wu3S#sC% LK]foËnCgQv*gJۓ6o\8322!I1Lҏ$nolüGS cԇ7sMR$vEUaU[G4bs+1KYKebn92Rt_żmV93@ņ$Ԗ珞JGmz|:gݙMe蜎녒r;,&HwHK.JN71_Թ4H8Sf7d ;~&Yv&ZoOYtR;Enk1g+(d-vns&|Ǎ._޲α-l{֙+ω\Y"d"x^dՕ5p ce8~oD64YézX[ &Gr"YI(`FwaMl#eyl" 6#Iڿ0)˒GQ90W"NIɣ;'gtAhҔRRRRRRRRRRR7[yzUZun xo("i]3U~|sjJE4t҅S1RIc\8T,$dKqp|V#y-WJ w7.>9RטW%l̆N_1픭9ۋgS7SɧKH,/$we\El-= ~z%; Ӯk/ 9. B)Auz ]2K$@r`Q]`n0zYٷk^wo6 v>NPFBiA }cV[$mfdȤY%le|\_-*$Yepq0]LRS3zdޗw/quf؇xkYW^AQⴲ2iWnQ0Pc6[3r)|e/jl~\w!oTph{8~o3Hg&<8-YnLhC ta.\m)(?M$UɈJ 1"}L{kdInE7#q'_K1e]>Wg",V1 ? M#*x/M ` ]_;(!wQӽQW0Pvmu]ws.&N\j7MOaQ~N7!Qt=PsqA 皊ZD3c}%ZIoۚ+8_: 2^ R2~z6y˳y\mfܱwc ys]ܙ/ mb. ,vں1-MB^ؒFWSȰi%*?dgs*2 ˎscKƸhT/o`+)vvFȔe.Wj;ܭi-byٮֺRAy k3J0lmx֍u =C^"!^WIN;L>-'_:iAz 0~>Cl4uSVWIN@! =fyOV(1+V7l 4q3LG(NʫQj6oݒKRQR!Pŏ)쀿).ۚmN!xi3~Ԫ?G_u_>CtDz@H6HX.eW\l@t/d;N'@Ĝ˄]n6q&"_řaGa5DŽar."K[g ט!ȥW$Ǐ 6Xc uJRՐCCE~YοjU>Cl4uS2LsjAJqJSdzC$_YW) L{I'm2n5y6h^tKKm0]f@eqnPѲѷ ^uzPF;L>-'_:z 0~եU>Cl4uSz_^'nwIڈm!-+THh4HKԢj2OpQ*HrMe-n&lZJP0+攠RY?E%`s@?9dyn_FRT]?&睎}=5PZ4(((((((((((("z:VE^`JJ;0ugZepg(Q%t#h Nv>G=a!EeAG{3 18E/%ͥ%B-MvfVFRԔNc;K&#C#{+jo#ЉvI5S(6#=nk$OȰ|h^B%zR$[nbIy.Q0i/D_$ c 6 *ǃ:q_;i׫X";Fqtƌ"3n#'ccSBl/1خu~k-pdˋ_&cEs,gAȦ́[ii6]E .;&{XH{Zl'*!@)@)A!lڙ_4ʊzw6!GEAq%*8Z%)AA1[h)@NR7foݳnMrv bi{7&Fqn' 6Ҽn"xTUrJx>Ug6/Cv<7ٖ̘͏.,V&,}ْr[}˃][_PzݍCa V&AHXtrWbatfC%0f f6mTT$L#;^Q*Aȝ 6>[̔k1Ȏt\V6F}Ҩs2L-e^[Ɣ%5ssf2ꪝJkOVZ"k]EbV>,pٲ|l&A7?ψKk$MHRiSӱ3u]#3bPkJo`+}i`Qq,*Ѡ6]J";ŖYׯbm}N!JRJRJRJR?9dyn_FZQG9JRQv`v:ʴj.ߟs@>AhҔRRRRRRRRRRR7[yzUZun xo("i]3U!p?ZaLf@h+zPJvv):q/l9kd$5}<ӣlqIn(CK8W2jܿz(17/b8?䶬W[;9fqY"\p6ql9eQ"eU8m /_NSD]r6Feu#7e¶j5DJv%8HPojd;6;ՙY q@zs\Ie= f5dJJJ(Ĝdq9 ,㋐׶و+\6.ayM}S㵭\jf1k5RqF]"w0PYG:f4X>:gDMh%7/Uqn#64 mGL,C&YCmN\(rXWb4 Z>ÉVh9=yڌ3(T[KV~'@~?n#濣x󓍹dgR"ٵÝzA@!Gs}%zyl|;s^ǜ볛HSG9z4l߀RWg@u qDʓKAm㙱I4wa }@AJXCɳY>9pj?U]3P2⌲2-N}ɰ9a,}9eVSݪXq_zߪ[#ПabL֨*G1z6̘+b:KAB$Q)Rϓ5ܸK\Bvbe+kZތ"ix]\<ܘU&lj 6T: 5#H /LL,G;+%/Lo8+lxћݻ5!붋{7r#z]'Be̦ʔJ$#;7QDtC*% 攥,Cr푌sgZd͟L5 †jc]QO_`1Etl2hQT!i*a=VB4p2e4ىE?*>C[J}Xq] R R R R R'rr5hg,ג0 9ՠt R UQv`v: FYߐ5GUsҪӨu kǞ|U@)AL<#隬 F[b=f7CAJRJRJRJR?/b8?䶴-3č&8⇎LSCo4#r 8ՄWjYk%I-KNa@ CHKCpEP r&M\U Od]re2\($)sZbֆD2QDfQY;T;!k*xۿN7Q1D1e\Tqb/@W:nM}7&LbS%2gA4фDl ]HMvGp\Ƀ.%d TڃqsXӉ]5u$YI5>pgEՇeveq9F}qۈhI]Hƚ[)T+MP.7ݏpo%VoT+ۿʔBҝ<׃LAr:\qrW7ޣ@ʞJRJRJRJRJR?9dyn_FZQG9JRQv`v:ʴj.ߟs@>AhҔRRRRRRRRRRR7[yzUZun xo("i]3U!p?ZaLf@hTLFS &ŅQlm"yH3Φu#iOY 5l f紸J8œ2TWUli(z1vFoЌV)}袢յYį\Go([=6М+kOas,lU[/ܣ&+Rs*юk]Jg 6ZIQҜh{c +쯫97[wLZ=uZ=<@|a_mb u!m#Өhd"|% ;!,2FNn="]ȝxYy7M.v>YɹhD3}[ǵ(uCzuӯjޞ_^:o^<}+]no?/>xiK-jk0m!=a9be:ԙ՛m bZ]L}+6`(SS^4uG\Xӑ]osےbdazXnk1f "Z>yx4uQڢ64H0n9v~$t%FTQ)c`\Xd-hʎXNLNEa^߱gIL _y[1<:!1lW4btcωMAه1.GI7:cgX-seM@uRx%gk !i*7MڀiKtKK.!SJD$?e [7PB.}T˭4sY`qUmI`pCx%*w#EaǛ,k1 Y}oPˏ5)E]~;moD 2mY~Knv+*Hx`'zEg$*18̅I)rȪRQƵ5A=JP)JP)JP)JP)JP)JPg,ג0 9ՠu~^J<7/#V)JP*.ߟs@>VEny[(-R R R R R R R R R R R Rf~@׏=VJNz:V_-0Џkjq ~5nL<#隬 )J)J)J)JwwMĵܣȴnxKo)Frԏ#hYde}wvΕ(w:|=k|9K]||w%ڎ(FJHͳr@W[TFk(f3‹y!]'v(֜ωר4oEn7g=w/jD"YXWUU1 ii895]{ oe>Ȇ>8JOZOޛBfJ-"ԛ*݅DCvx'=3Y~]2zĆĜH> gEK!Ů)"Gf*)w+AaSIY@kԽ1}S@kԽ1}Pw rxnv@^>6{WvmZ/@ ==rMںk@kԽ1}S@kԽ1}Pw/o==rMںk@kԽ1}S@kԽ1}Pw t˶{`n6[}} FKmL. g`/n7[s} N&J`c"IER9ɖVfd*N\ KJ͎'/Lg<o'/Lg<ol] *f.ߵBR';"ZaljhSAO"vzp(X NᏳKk#Lr{HV>q2ɦFk"\i_d$!\d$r|YD|tR*x 5Tq#`bS'?שzc9|VIqTkRQEàcq ΤGXԦOIDt)X_+Jʜ%5JȽ%zϰ܋iq#yǻ>G)`&'"o^BcDZ%-v5YQDP CYߦȷ~Z8_*øf16"  ɓƤa`|2e%r}(&]䏜ihZɲlx^?6Q\eͦڥ*G 0AhҔRRRRRRRRRRR7[yzUZun xo("i]3U!p?ZaLf@hiݝX2c"wUfȠGmpnu Ve<.3TEgnLt[SdL^Q(vR͏d4%9HJR MqvL6lw[PYxc"xjZWy4{)JWSP_Tʫk{8ϊylo\ƞ;IHT7an2M&mMGksA7_zM )r-PC7 9"CQK&q(_4(^ls;oP81Ѻ BXd`4<@i#ZkٓЏHjb:+HeLT(gy{ [Y#JXrۉǒ;pu8>(Hnº |=l Qs?ϓxhP=/%椦lSE)U!ȼZқ$g#7o$)F w/"N?JƼ_6aMA4we뒣b9iLh˺J}Na){B I$R#zP#ZMLvoDdiElWkVq.=.'A{:Ȥ!S[4IoLE ;#M~ݝH~Sc0ުr**k󲮫T.,dPgu%9P}F=ng:Bsl$cI v>`R"4Feuč'ifD/2*Z-聠Vp&\v.^̔U8TPH)Jn54rMxXtvrKۆɌx帹px+5?7:兹 =.⇒D-m1KzCڼ.ж⑄G]1m?͊S/n#YR(mG:rڄӻNr疵.LNrOq M9uS:҉Ժ)qOjVEny[(-R R R R R R R R R R R Rf~@׏=VJNz:V_-0Џkjq ~5nL<#隬 )J)J+睎5!){YѴ=/N׋惺Â׌" cC MeE<͟$+׏sM9VxJ}|}i+׏sM9VxJ}|}i+׏sM9-wB(DTt- q/rvzL+ϒ6'*K_iMDѻ5E+>C'W[;sXY!ȎNt]n|Ҷ>PޱN4y8}-r$x1LS ErNfrfu^qZ귷E6#BZ#93oMI4cnҟ֩]v0`2$Sm L4dSg~6Noo#{F_ B(jNmܣ:Uduq+yBq񝹲arSfǹ P:){g :hm9x”M+ʌs.yjc 5;!%-#{^P>U2$א'NHAML8,$Y6{ zt\PoSFUu TsUrBr;]e[:cz~F|]@/jVsKgj F%x8v6ד˫!9Zζ֣7ijeїP$.yȒI<~$ڎĊd9*}5)#br j__y1y ̍Xu㷁_v_oqO[ WI?$r"\܌ kS6Y>G q[~sohZj<6+9\Y r âلr;S%=6Ҁ5("ƉsgY6:;|_Ip$8+e##јt۱bHlfNQ5ZMO{+ȱ,unv\#7ChLa8Y[a%fQ*mez2*|2>Tz7RL"ӔZdY2_ D6q&lod{.!ݚa||6-{RhD?9 I` 0n\JC8-5g Tx{QָZᚰAmHt410{qI) tE n-UGKJu;,s_\Rgq;,s_\RgJRJRJRJRJRJR?9dyn_FZQG9JRQv`v:ʴj.ߟs@>AhҔRnzvhz@w W"m}D,~0dCG^tYߐ5GUsҪӨu kǞ|U@)AL<#隬 F[b=f7CAJRJR?7c?䲣NMu]õˢ-$SHrž}ԅ„POdx‘*S5,6+k]JJ R8a/q;/?KK+vٱ6a\RJ\|2P2TYQ]Q&(kԛ,)1!֪Q5Y͙_d@ǫ`Ku_g6pu +1i ?9dPW,i8 "fu創&۔t(ePGmo?6na5Iw!o]Ig]z|bM^D3"8!f{[ּ-({?0V/%VTy'DQM?'AiŌ̚tpv'>y.:NT[i>)k9q+re,lLΫܭo~v8a__k1e1WL ?%3Z ].5vƌ\r8Ldؒ9%ETǖs0 c~{o>tan6۴VixNd`n6+!El *[6q{"nIe-7DpltacpS=a~vzD7CZQ#'>LoWKhM*H6{[/Kffd4nAKB-uʹ)޶"J[?3 amXo|UgEuE NۯSvfI-YSp1$ &{\ILD]1>4XMgrl[LX"JWQ^V1KW#o+Y㗣D:3%^jR kLWH}tN:$`ńbEQ.0-+hÔXR)⤾xKTsI+N<9+Fq9Vtj6X虛'plL7͸Ј,D0c14%f9y ˗!{L #3iǘ%H'(4~r-y(ܿZY'rr5h7zɂ&UU+cdi"/beX]@1fN|j7K'%nH@ѓKE&KR}s{x>}ūUo,nCG QzNG٩ s1ln=>'Tfq$$fńd&4GFb+籽 Ilی4oW[ߨA;}⣧h7n> 696aHrjWTR޹|zH:׊(R=}mAr,NXq7mܚli{uaxdopɏ>2u:Y=PA͂$)ƞǐQm$i"Lik)tXϝAx-F@%BBĞi?*y}G.;xŏCքD tTõ&:#G|:EhGlc34-9Nή(Yyy!?%Ed|FУԹdq1Nz1J}S6KeЦFjFQd44H&Kxj[h鬥O*$g-?5߮G/rAu2h3E#e9$X]~(? E.FRwų5#钾'~D{Ÿ$bGdݍE<@_f<$qcf!|fL\kYR%|dTn$vƥb踛5NQt cx!`E ]ێ>yi|;['HwS8p_/8{q)ӝ݉Y8b#=}}M~?[tB1>ۭj"s :btɄ8G*E1v7m&υ>dxd LƃL4j;,NwtUR2#"d zOu-$ L̍%E&en6RAw2!٩}jSV,*>LJN!h]B{:{1E+Ⱥ1Dk9tI s H TvCJɎ> 񃫦Pt=PSU>&RÍU*Hs]홇dnǪ;%0 툞ڳā4*û5jNjm Rw7 ǎ'6ksa [ё[UĎ'NcmH$J\u1Dc*dWERn(.7 nkIA(p`BEO2AEaưvRRRR7[yzUZun xo("i]3U!p?ZaLf@hj /2B@Ǔ9{!\m?"{-`D4O[.UA ܶw3YM~&@w)A% 8uvnYo$Ŋ1'!j}go?H)@_g_Jh l ;Mtj\dyЈz1d]=c2_&L*ǻd6!|r894ݚT]@_g_?h l ;iQw ~m}~/MRѥE߀4I~Si6yJ F~&@w)O?H(-T]@_g_?h l ;k 5ٴ}=G<]sqLbz*KZ.oZYA6FrYK$Q6R) F/?H*-c&b=܍mk[%y,%u gH"Ql‡{Cn{/QZ)Yv?MDV6WKK0r}gg!Ua4R6'cyYGy`,5ɏag|.h3[IQ[zԼ 6:&D$wLx7c1xAVZJ fǎR*?H)@_g_g^ŝͽzZ=z^pyD0_ysyMRU CaUGV+g#YDoS7h:ue]Ue}dq*8w;jNs`Ň#eYqdSNd{P鑍Hg{2K.n#)9__߰Qg(L˲&r=0HhTaDžy%Ȍ~҃ס\ƚ׌❔Է-Dnc0km#rd=~CҲqC,62rsȪ쿌m^9%( v=cX'Ɔ7N|ّufT~m5̩,=5}Aʼj8.cGy@EtsE³Rȳ7ʚVGn@+ MR:֖fw!%6cu(rS&u=,Gs%fJ]0K[wq=p_ԠRRRRRRR7[yzUZu ohq`!;c6.dYߒ .&GQ U!%GJHdžP(ןsO1祢=#hu<]x^}?Wy;߯D)_sSj}uH?ָ^}?Wy;߯D)_sSj}uH?ָ^}?Wy;߯D)_sSj}uH?ָ^}?Wy;߯D)_sSj}uH?ָ^}?Wy;߯D)_sSj}uͪzu]:uQuu+k#ieȾ$u%Iy}yş'hhij+ $SHpy.[\rYep|H6eMIѣ:NēXV9s:# J7'gd뢲idh~OwEE}"+GMQ^Έ?=?kzw`ӷT}DxUv_UL/7JLpiz9;TpT~!v%kI]Zg  b|%w^Rk(Xo7"&e}^^6w¿t‹+R'PJAy˗X'lݱ)7.4sätN{W~?uqo Fע<%w^RätN{W~?uqo Fע<%w^RätN{W~?uqo Fע<%w^RätN{W~?uqo Fע<%w^RätN{W~?uqo Fע<%w^RätN{W~?uqo Fע<%w^RätN{W~?uqo Fע<%w^RätN{W~?uqo Fע<%w^R9&vg+i K-5ֹ̈́Btx;q+Ŏ"ˇ3Io45FMRRĞ\BimHư(ןsO<^}?W@>y;߯D)_sxJ5~}(/ꋷWkϹz'JWBlnGbE1]G ?K%vqȔb$܈Zp?Zk0ڨmqyMeFH$E4s@#:נpvgQ=׆+Y@-}ep[hݎ̘nޢ@2m"ɍ˅v/qy,muw'8Zץ`\:ZUFja,잛i-c>!4IelRr7e[,$eQ.xe]=jQl'͹,뭴DFΝkp@D.6]m֏K!:>Oq:ձ AY]YqTqbOb}IRBF:ns h.G qu` ~\atv{A@|]oӠ|B?X[uvxc2 Wp6 n,ϊ~n\ݛ\=+G[pM;c,ieѓ^*RܥǪ, 39r~ /v64بep;n6s i+\x_Y_Zd*s61#n'B |! n7YO;+K;y$d"Z =6u)LyZDdn?#Rzg6t0xp}`6:m F ǔ.wee![p Gg9BfmǪ hP_&͖`’;T0%p9&hIVucGYOE~wcn$N@ɸ~+8%Gn=̲Nmq:Xp@'1ƯNJ2{Lum]p|c:=?Xo<: c&vkI8ȋ4Y[߮$"6]Nt݉ΦuM'NTPȮk;2Ǧ--6e, c[ f5HMt̍D0u Rr|b$jE,F0-xYno=l. Z >!_ufOJ${th#A(ϔ"0@nskU3H%je*#xiLV+!5Wf\͟d+kO!otۥ(y%}9q8=@%y]:m]G*s)z=ϴ]ٴ}#BhwLf1 Ltvcٷ׭[mݠ {p - Q5>Yg%Ma׉-@}L@cgwc6nISKTIF{>Z ˰"MLr/4DĜThSnc \^2vecg Ggڷl?D-.l^}p,쀅|#ӥ[C8N!gHsHzhyҦ2 bEI+exbXˮYt%sl{[_#(Z[LTя5BAbl6h tbB4a!I9eChFAzF}}. ǂ݈%:penHIޔr>TvaTÕ?6Msk Mq NfUkQ=h =.[,ۊV3dRMY7rKbfb+"TPnlЖByef3MR$HBOg ancp8ґE4g:23[JOR)YwzC{H1v&ڽVhl2[)lq7HD,aH Ēћ ewzzL 'z2\2Vt@TZ-{#ILrj0j,WZ/G;eܵ̾]eRw\Vd* Jn}S`}SI̼1g8[7"3˞یtsi5YCZ{YU&xQV#H^YI?|rOkhfYbܭɌc<,,Z%%Kg!h0 {]@@B;Vx7Ydo pې,ۀ3bg߃$M%;$~M:<.Q@5gխV3Md\d3n_McR;!|Z޷[c2&T&fBhlH}fCEM2n|y< mÛNֈ_lpt@@>.-n=^"^{An;=s#+Ĭ]H_L`GZcr%-e,,QYmaXVĀjܧ*(NZæC/`0xdX$jv -4NsUYnf.<&ӁUM8|8s-#(260[UUQMbP'6D,Dr]zknzmhD- ت [{ӱIҁwkiH9~@c.p#*(tRk&\ai'0+ˈٳ{$ݜ- qg#u=zK:A Ȉo 7]hh^6fp{[Z7h@: e0f]K3Is :^,]NT',H"dR]sNQ8d,q7fKAIĺ[`Uj$Q$$^=.s6.qMC "%)m}څ?Qo`;^PkuQ c\=v{@q^[D/-lm osROfp6 LN3%V=œ/~uH']eU#ܼrb~B]IAHp ӆsdR&b|:HJk\Q}-2NW$]{ت#dC:Z/=nO([hPp7u }khwKDn@g"!mhs=c.W A:N~.a\ mtF8de$xJfgk9O:Q%ܒMmH Ϝk'-MgxW7̹)0Pjez4yl!2h5ɕyy-3@qר[ud@.ŒJz:u荃-A=DFm %ҝ6] ԭeotks_dqs!n3,0h8Π&2-jMlh2$mѕ\&5#@\" ]+4GBꪘR1 %VXpŹͶ[uÈpL7u.DnJN% ̤ay6#$Y9A YkIE3I&-l1۱b˾M!24/=m'܍YrK(#eLE*^oBD”i9;:V2e؞P0fhKѕcn6MUv&YHjP 9D1e}PyBc.w)'RsaC+wc>^=_r=l(sI"%Xq&#$+/h̥Kt>qU.i *,A'b,i AY*idXMqD&F.*Hg. f\7c˱!o]m.{#h >)no>c:U]c[Nv\SkYxˬE+E3/1􆨆 Fn%bsE#&%:xaJGNON.`"@| 8hdbc1`ŇɟuGKa zvc>3;qm0e2#it$`9}cGmE&W_^\.lz"쇌@ - ~оѶ#h@@@@:gɶis J$Q )4Tj~ܜHn<z)ಌn4V֝ʑ€Sv8(.n-zs"t܎4CY1Jd$ȶ51eB*]CTjغi (HPu>vҲș&zYKۺUȍTU4^e!Ș 8Jk*=2kPrֺ0K (\Mi( 7n "g6(xU&;nuvtp.7J]o,k54E ۝=HXs෧;ITmqYqb6$# j41Mȃ1HU>C*&ڑzΉ#SbmG1[ ;C"la:hIHH4t` 1~L:"DGcdC.U,.Ҭw/Wۙw;N'#v8wڒꢂGiJ)J)J)J)J)J)J)J)J)J)JeQXk;(k.j*ʡ* (cG7du_lحLq/dž<8r1K .|nH,Æݗ-nO3:YFvcs$d'Kz=. e-џ\冎 D~$4f0j2evCF)RbȌuo:ؓQϢ9P8G_KLX1#B1s!`lP|{X] ݤ^d],xQ@$t=VKa\,όov?H3%U5s`Ik„aiN)8m4ë5ʲί"\`m BfWC7aߖ稦@ۮQ7-Mi{&7@&.=HbYM-2ft<Ÿ q{]ʘu$rRd-h]2Ԝ2ᦴ|n.:,]Q̯3mxBh) j+G&x )w[WH0cZb2h d`!#F23|BGr ZKTOVш*bśK,| G?a"AInNL-T {@t\쭚{a+&Im(UWL`Q).*ֱGZv'PnBWm95&.=AlWtGXa}WLUU݂v$ݰE"H=)P+6AQHI$tCqUEu1dluA>!{DCm%yw}c ogv{6[o@:ZӯO'^:lo?-S]J-SNlo?Ԡlo?5ڛg"Aq2c]% 0m>75r ehJ]paL]C҃{D>屿SC[mOEvu(:ǼC[mOEybLY16d},+V˂nB.D.G@kAQ]m˚1zw~p-gˮAu=p]nc tgƷ}j)J)J)J)J)J)J)J)JrV1A/v,lˇkK3yc.-2Z^gvGiA-3 dWK$t6ךJlIfngH3Gg%ͲdYQSb8$T, PɌY* 8qË1ÆqbŊqŊ qǎޖǎ , ,ж @>P)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP)JP|7D|> :UjrqKY-[]j cjfwwqn P};r$KG/jm9cߓ1+4@=;N:c-='KP!hvmB;|dn+An^oN>'h6hvut*PïgOѸn9,kZ',/uɗs+ ri}rYՙ-;xcB-mm z!h5[u=e 6u p_m@oG_\vnN% uGw Yh[кPgP#mN7j<-^/숏kt}r!=[[y+^]C|;eг/odoBA׿yCmA, @9,kDG8(ޢ6Z7u7}.Q0i恏[lrW,;![ױen렔{r;IV;r;IV_Ԡ{r;IV;r;IV_Ԡ{r;IV;r;IV_Ԡ{r;IV;r;IV_Ԡ{r;IV;r;IV_Ԡ{r;IVy[$r7Z`}QmC6hYf8iJ)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)J)JPK'_.VGPK DOEBPS/img/edr_exceptions.pnggPNG  IHDR[xŢ_IDATx?PW?`1s J ^UPŮbW"p;[+;S٩lܹ&IenL;9(QdCVgW:nj@.HD$"D"DH"@$ ID$"D"8J\9opJ=Wͳ5oV"3ݻs,-lQa(333/_)He]dj3ZrnMy\5ndY\d61ᖶm4-#'VTjinloucʖ%/ȵ5o'͡[H_(>AEuٳ-ϊQetZjmc?#B}Wĕ- 7o?8DS4&mzcz祷h}g䛷L[=& \-$H EӼ :_c;͛I6Ej~XcXk\"RxW)i9eҼi1-[́mtt*(ڔr̭@:n$/c4zNStkOclz/W+2jo1mhȬj-tݚk+k2[ Rjm[Nڧ6c{1[v[mxΛbT *ZPw8m8%UHii$4:D"DH"@$ ID$"D"QDta=[EJb;Xe{. +M7Anr=@!tNFxR)еX? %5N 'OdlHjZ#i#̚ZJ;b鐈֒2XwGH"@$ ID$"Dq<ϫj*D'O{nsssyy9u- C"K!"@ 7ǫB;==4r1e5 nDV;;;!3?W^]] I+`05]\\̢ _Y㱴YP\q^?)!*t׷XHD +333K(F..$"ZiѣF b&^v-mIE' N PH!eIDB i# ID$"D"DH"@$ ID$"@U\D(/_a͛n)Uq) t $"@UյoǏ+JF"P ?|T"@$ @Z{D#YZ rN"ï%ʳg+%>qߚwYxq=T)WK?=Lg;0cX$"0:@'F0-瀔VY%"0/4Vft>Gl?ym"D"Dr||~ϧ.$%Pj! _x/%1PF=_7oTE%&hmmmeeeii)u!9"hR*E"@$ ID$"D"DH"@$ÇGGG_ݻwR 7nY^^N]QzBpR#޾}֭[JL"ZS Ē>eΝ;?I]KJ͛7%"@^lmU*ɗK gggj5u-HD c,<:J]WY(ў׮fͧ.$"_אB@&b~M߯L]b@VWF..-9&; (:d%>kPID$"06GGGqŋ 낾HD` B޻wo޾}ryݒTB~LJv{_}ID`$u) x d P:5ms ʚۼkL7}D$"D"DH"@$ ID$"D"D̅ 40D=&z E vc߶1Ӳڧ6WdWC{aC M OވmnPվ3u"󋋋 II"P9<<\ZZJ]EbÇwwwSWD(ˋ IL"ǏC.'=PF/^XZZVVVR v/"_$"D"DH"@$ ID$"D/..\ݻD(/_ϧwM]N.HD2ڸt~~EE"YZ}K$"0)l:hW_}ssskII" YYjvv6ǏK~T"YjdYReee͛`'OZڵd.,,^\\̖D2{kX sssggg%>-LV?W}Fή_O]BID K_Ғ3ks@X.&& ID`<...^~}ttݻG-_JZK"c#.-,,.-- ${Mp||7lll9'x~3I(j恬Bװ8 kZP(Dtvvfwއ2Q/{o1Ϳ6'Y-3vfjHDij: #t[N۷o'yiK#)Y^+kks&>Fǐ|@mG )br4[).Hݻo,$Qjt=Z-SRDܬP.:ss5Ioй wOOHDJ,N*++eҍ_tw3aθ(F6mεOjMTN!mll spp5ɘj)$}DT/2oɓ'ܹ}nnn%t!$"0~akkY 9"!mll/GzkkkWÓBƍǽ\ZZߟLU0d~~Ç[[[[ 9i80IUȼnooݻwGGGᯮ~kkkssskID`/BX}.3:>Q4/S+D}^{ 2bUtqU(Ǐ4O?QIWqR;5pªhhYY#bSlKvJ}#f,t =7=;K]J1Wuk_NzcS=jHRk9c1DJ͓'YxzJ4_6A]xoB&SCcLN~GeP0m%9} F"fe>w]CSArmߖƵՍHĬ[V67+[[?T\3lW?sйfgg{t'&U4JRy6P9e!+ڜ!ST"KC$bW:m><˸zHjDiT%DzHĉh"mnnlc]޵52.m!a31> &9bc|Ua=Bdzͷ}xhۜ E j]\vFl>?rkkk?ׯM0Ҫu?TH$"/twݻw]4n'ɚDd>߇Ե/*ܡotzqtP:=+u<^D"N/=^/?[q{k ۧhe/SI"0o#L H|aWA,L%8=|un>dWI| jdC+,x 2y#ɘj)$}DW{7QDt=qS@"@$ ID$"D"DH"WU$IDhqq1uID*?M]Eb^x(Jɓ'ABғeϟ}vmmիWPRw-$"@.!w$"D"DH"@$Rlϧ.^i#ID$"D"DH"@$ ID$"Dqx\J]}9u DݻwSWD>|H]&wrrJGZŭIđnccc{{;uDIxOrpp(O`HQ}9b!}ӧ8q㱻vԵ;99~^zD!Cq߇0v?;׭[Ž %,a/=vvvveee{{͛7[Z}Nn.//WհsPL]I"fիWxnn. _Î}pp &ݧO®v' 12$we ;j=&+faaa/UC;~S.K(`~~>u{^c<$)?Ksbqq1zrrӻw.--ņ.KիFa1Y@Rjgggmm-CIDJ~ʨ/}5juqq1u@z[]]m@(-H}eفD:DH"@$ ID$"D"DH"@$ ID$"D"DH"@$*/5bQc- ;~Ǐ?~E Y ?~Ǐ?~ъ"ZǏ?~ǏWd X%d +8Z"Ǐ?裏>裏> +V^8`A\0a„  bE &LhAVxM@ DPB >QD-^ F W<P0A1^ceeE 1bĈ#F1bq/#F#F1bĈ#FWXcBV k,h „ 2lPV>|Ç>|Ç^ ^8`A&TaCpСC:t @ <0… :|Ѡ+#FЊ#>\1bĈWD1bĈYY1bDDъ ` VA\c Zъ#>\@X`eE V p@fX]05++"F1bD( 5VXY+ 0PZV p  !++#Fb%bĈZ1b+"Fኈ#F!++#F萕#Z Ɗ5Yxk @ +Xv k,hp+x͊"AV`  D+V"FpEBV`  @pEĈ#F tX9d!++#Fb%bĈZ1bć+"Fኈ#F!++#F萕#Z` WD+#F|"bĈ1bĈ1bĈYY1+ X@k+f@V +Vt "b%bĈWD1#F($XA .dH 2baÆ 6$hJÆ 6aÆ 6,aÆ 6l ++ 6lذ!AVV6lЊ 6lؐ+ 6lڊ 6lذ 6lذaC4lذaÆYYiذaÆ 6lذaÆ 6lpኆ 6lذa 6lؐ!++ 6lذaÆ 6lذaÆ 6lذ 6lذaÆ 6lذ!CVV6lذaÆ 6lذaÆ 6lذak+6lذaÆ 6lذaC4lذaÆ 6lذaÆ аakZ A+hJЈV 4hРX 5VtZ4hРA"bŢ+kp@ TъA +A#Z4hРA"b%hD+V 4hPV8 + ҊA +  "5X@` +X +Y @ +X@`Y @ X 4hРAZҐ tX@kVt VXq Y еk t5+V H+ H*\ȰÇ#JHŋ3jHъ5Z‘#G9rȑ#G9b#GVpȑ#G9rȑ#GXQ+9rȑ#G9rȑA+V8rh G9rȑ#G9rV9rȑ#G9rȑ#G Zaő#G9rȑ#G9rѠV dJ X1!+0G9rȑ#G9rh +@ + $@@8!Vpȑ#G9rȑ#Gdk,h „ 2l!Ĉ'Rh"ƌ7r1V?~Ǐ?~LjVX}Ǐ?~Ǐ#ZaǏ?~Ǐ?~hǏ?~Ǐ?~1V?~Ǐ?~LjVX}Ǐ?~Ǐ#ZaǏ?~Ǐ?~hǏ?~Ǐ?~1V?~Ǐ?~dž8P k,h „ 2l!Ĉ'Rh"ƌ7rq!+ \ <0… :|1ĉ+Z1ƍ;zt?~Ǐ?~G|Ǐ?~ǏZb+Y hʊ+xM@ DPB >QD-^ĘQF-Z#QD-^ĘQFW@@Њ+\ 0 Z"p;vرcǎ;vرFV+A+XJ@W cǎ;vرcǎ9Z! @-Zaªcǎ;vرcǎ1(  @YXJb+uرcǎ;vر@ t<hEWtthŊ@;vرcǎ;v1b:*\c+uܸUA+ұcǎ;vرc@+u"bk5V^8`AZ"B"4+W&p "Lp!ÆB(q"Ŋ/b "FW<` +0R bE 1bĈ#F1bĈ`0bda@Xah0bĈ#F1bĈ@+a8qF+"F1bĈ#F1V F#ƃ#F1bĈ#F`#Ƃ+8P k,h „ 2l谠V>|Ç>|Ç2 Ƞ>|B+5 4xaB 6tV B"D!B"D  p $XA .dP` XqСC:th +V:tСC:tСC pVX&p "Lp!ÆСC:tPa $k,h „ 2l!āVD1C+V"FpEĈ#>\1bĈ#"de%bĈ1bD+V"Fѡ+#F|"bĈ1bĈ1bĈYY1+kV @V@hVDhJĈP@ k r @+ 0 @+5+jE @k#F!++ p @ VhAYhVVh@XVt-Vde5 4xaBV(4 @AX@`Y"(5kj@bEB *4`@Z ` +d+\ B +V p- X]pB *TPB YY9(5kj@ 5X 5Ȋ5\ B +V$deEB ^bEB *TP+ *TP *TPBW(TPB *T *TPB(TP!Ȋ$XA .dHЊ 6lxmEÆ 6lXpEÆ 6lذAVV6lذaC4lؐ+ `aÆXiذaÆV4lذaÆW4lذaÆ deaÆ 6$JÆ Z0!  t  `E.baÆ ^[ѰaÆ \ѰaÆ 6lh 6lؐ ++ 6dhJÆ 6lHЊ 6lxmEÆ 6lXpEÆ 6lذAVV6lذaC4lؐ+ 6lذ!A+V6lذ 6lذa 6lذaÆ $XA .dH 2baÆ 6$hJÆ 6aÆ 6,aÆ 6l ++ 6lذ!AVV6lЊ 6lؐ+ 6lڊ 6lذ 6lذaC4lذaÆYYiذaÆ 6lذaÆ 6lpኆ 6lذaÆ 6lؐ!++ 6lذaÆ 6lذaÆ 6lذ 6lذaÆ 6lذ!CVV6lذaÆ 6lذaÆ 6lذak+6lذaÆ 6lذaC4lذaÆ 6lذaÆ 6lذaÆhk,h „ 2l!Ĉ'de"E)RH"E)R<"E)RHCVV(RH"E)RH"Ń+(RH"E):de"E)RH"EPʊDz"Ex$h ׬: E)RH"Ń Z)Š@+ hE +*h +`u-0 (h +  յ@8+ PA Z9PH"E)RH"EWPH"EQDE k,h „ 2l!Ĉ'Rh1bĈ#FYY#F1bĈ1bĈ#FYY#F1bĈ1bĈ#FYY#F1bĈ1bĈ#FYY#F1bĈ1bĈ#FYY#F1bĈ1bĈ#FYY#F1bĈ1bĈ#FYY#F1bĈD+k,h „ 2l!Ĉ!@@ H*\ȰÇ#JHŋ P k,h „ 2l!Ĉ'@@$XA .dC%NXŃ#F1bh1bĈ#F1bjF1bĈ@V0bĈ#F##F萕1bĈQ!++1bĈqኅX!B @V+V d@r 5VB*@ +0:de VA+ ՊYh@(pV d@ª "#FX+00kV he bA h @׮YV\v 5+k׮vV]pڵkv+V׮vk\fX](X` de5X`eE \"A+ +((@hX]0`u @AVXY ` kb%@(($XA .dÅ+ &"D!BxmDYYH D!BbAVV B"D"D!BpDYY"D!B!B"ā+ B"D!.\AVV B"D!*de"D!Bq !B"D W@h!B"D YY"D!B"D!B!de"D!BBVV B"D"D!BpDYY"D!B!B"ā+ B"D h!V&p "J„ &L0a„ &L0ak$L0a„ &L0a„W$L0a„ &L0a„ &"a„ 0a„ &L0a„ &L++ &L0a„ &L0a &L0a„ &L0a„ H0aB$L0a„ &L0a„ & k,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҤJ2m)ԨRRj*֬Zrf WH*\Ȑ + H*\ȰÇ#JHŋ3jHъ5Z‘#G9rȑ#G9b#GVpȑ#G9rȑ#GX (Њ9rȑ#G9rѠ+ dŊ#kVpȑ#G9rȑ#GXj\c@ V $@+Vd+\cj+9rȑ#G9rȑA+V$"@@\(@\`@Xȑ#G9rȑ#G Z"Vh@j+`um]@k5 $h k,h „ 2l!Ĉ'Rh"ƌ7Rb#GVpȑ#G9rȑ#GXQ+9rȑ#G9rȑA+V8rh G9rȑ#G9rhЊ5Z‘#G9rȑ#G9b!+Y`uUB!Z‘#G9rȑ#G9b!r H f@׬Z VV`%  @ Vpȑ#G9rȑ#GXa  `EV`5YV&p V&p "Lp!ÆB(q"Ŋ/b̨q#E+V`E + @Ȋ5Xt- Ȋ5YYh@Vhh G9rȑ#G9rhЊhb#G9rȑ#G9r4h G`ъ9rȑ#G9rѠ+9jb#G9rȑ#G9r4h GXȑ#G9rȑ#G Z‘F+V8rȑ#G9rȑ#GVpъ9rȑ#G9rѠ+9jb#G9rȑ#G9rd@V&p "Lp!CV&p "Lp!ÆB(q"Ŋ/b̨q#E+8`A&T!AV^8`A&TaC!F8bE1fԸcGVXyѣG=zѣG= ʣG=zѣG=zQV=zѣG=zѣGѣG=zѣG=zhUA0DŽ+\cEA+ ՊYhG=zѣG=zDhU@+ Z V]@ rՊ@ZJA+X dee *@+ѣG=zѣG׬Bh@  @] P  Pk "ڊ  <0… :|1ĉ+Z1ƍ"j@``Y +  A++Z"A @VVVd@` V t9rȑ#G9r +9rȑ#G9rȑ#Gȑ#G9rȑ#G9rh +9rȑ#G9rȑ#Gȑ#G9rȑ#G9rh +9rȑ#G9rȑ#Gȑ#G9rȑ#G9rh +9rȑ#G9rȑ#Gȑ#G9rGqGqd@VX&p "Lp!ÆB(q"Ŋ/b̨q#ǎ#ZaǏ?~Ǐ?~hǏ?~Ǐ?~1V?~Ǐ?~LjVX}Ǐ?~Ǐ#ZaǏ?~Ǐ?~hǏ?~Ǐ?~1V?~Ǐ?~LjVX}Ǐ?~Ǐ#ZaǏ?~Ǐ?~hǏ?~Ǐ?~1V?~Ǐ?~džVX`Ŋ+>~Ǐ?~Ǐ 8 $XA .dC%NXE5nB+ <0… :|1ĉ+Z1ƍ;zl@V^8`A&TaC!F8bE1fԸcG Ǐ?~Ǐ?~ }Ǐ?~ǏǏ?~Ǐ?~ ?~Ǐ?~CVZ(0+V H*\ȰÇ#JHŋ3jȱkXa+Ǐ?~Ǐ-ʊ?~?~+W p rڊVv+ H*\ȰÇ#JHŋ3jȱcBVX%V QD-^ĘQF`BX++ѣG=zѣGp `kV vm 8 +$XA .dC%NXE5n1رcǎ;vرcǎ-@;vرcǎ;vرc5رcǎ;vرcǎ)Z Q#++;vرcǎ;vرDV+* +W 5VZaձcǎ;vرcǎ;F"$5Jǎ;vرcǎ;vqE\c ZqEǎ;vرcǎ;vq@յ@X]c5V+qEǎ;vرcǎ;vqk,h „ xM@ DPB >QD-^ĘQFȑ;vرcǎ;v1"++9Zaձcǎ;vرcǎ;J\ё㊎;vرcǎ;vؑ⊎Wtرcǎ;vرcǎYi@thJǎ;vرcǎ;vhJ Zʵ@+`a +;vرcǎ;vر#FVV  k@ tرcǎ;vرcǎW4dX@ ++\B` VWرcǎ;vرcǎ;b5 48xM@ DPB >QD-^ĘQ@ȊFVT+VXhƍ7nܸqƍ7bd V6Vdյ@+6"\a +++mܸqƍ7nܸqƉ 0`cD++XFV+8dee7nܸqƍ7n@AlljVVX +XYdee7nܸqƍ7nܘ0P Vj`@ZY c ++VX`Ŋ+Xa +++lܸqƍ7nܸqƂ! !V6\qV6ndH` Ɗk,h „ 2l!Ĉ'Rh"FVVpEƌ׬1cBV h%cƌ3f̘1cƌZa%#3Jƌ d2f̘1cƌ3f̘12N\1B++d!2f̘1cƌ3f̘ V2^\ъ@+*PƆVVXaQb@Y"@2f̘1cƌ3f̘Q2f VW de%cD++U 2f̘1cƌ3f̘ +3\@AV h1 +2f̘1cƌ3f̘1cD++Xë $XpEA(X` ,XP` VX&p "Lp!ÆB(q"Ŋ/b̈ +5*\1B+5  +5jԨQF5jlhe+ШQc@+ҨQF5jԨQFVXѨ1 5J J 5jԨQF5ZBƊ+4jx1Њ4jԨQF5jؐՊ@5b\QFXHF5jԨQFШQ5jx0Њ4jԨQF5jjE 5^ &p "Lp!ÆZ"Ç>|Ç>|ÇxÇ 8k,h „ 2la+=|Ç>|Ç>VzÇ  P$XA .dÁV"D!B"D!B\ xM@ DPB :tСCX` V8tСC:tСC2 &p "Lp!ÆX C:tСCV@@ H*\ȰÇ#JHb $k,h „ 2lx :tСC p H*\ȰÇ#JH1"+ \ak,h „ 2l+:tСC W p AV^8`A&TaC!   4xaB k,h „ B@ DPB^8`A&TaCY d,h „ 2$ k,h „XQPB *hŊB *ThpB *TP *TPB *deEB *TP ++ *T+ *TPBXQPB PPB *BB *TPB(TPB  deEB ^bEa`Er(4hŊB *ThpBX@@X @ *TxmB *TPB YYA+(+X(BB YYQPB ]+ H@4h  be@+V 4hРA 4 AX0 dJ  0hРAW&p "Lp!Æ @V de@YኇCV<0@V@VhVXy(Њ>4B!X!5YBA\ck\c@ @X5VPÇ>|Xb@+d Apkr]cZ +X !++>4hC ` +- + 0AYÇW( + 0AxMk^ k+` k+ A+^8`A&TaCYYQ@ +VX@` 8`@\ T@BVV>|hЊ+@ V]kVT 5+X +`+>|hpA+V׬\c+h@V@ +][!@+׬ tm +5 4xaB 6tXV`umY VX`++80 @kVB +VY@V x$XA ZPB *T(Њ *T *TP+*TPB *TʊB *TP@VV*TP5+V*TPB ZPB \PB *T8pB *TPB YYQPB *ʊB *fŊB *TP@+V*TPB+*TPB PPB *TP!++ *TPBYYQPB׬XQPB *hŊB *ThpB *TP *TPB *deEB *TP ++ *T@+V^8`A,$h| ++>4hÃ*5Vh@V X]0+>|hpÇ>DÇ>|X>|xbÇbÇ xÇW<|Ç ÇCV<|ÃV<|>|ኇ>|aAVV>|AVV>|hЊ>|xЊ>4Ç"\Ç>,Ç>< ZÇZÇW<|C5 4xaB 6tX>|xbÇbÇ xÇW<|Ç ÇCV<|ÃV<|>|ኇ>|aAVV>|AVV>|hЊ>|xЊ>4Ç"\Ç>,Ç><Ç ZÇZÇW<|C+>|ÇYYyÇYYyA+8`A&T!A^8`A&T,h ‚&L k,h „ 2l +WH 0a„&p "Lp!ÆB(q"ŊWXhѢE-JdeŢE-ZhѢE-^[aѢE-Z(-ZhѢE-ZxmE-ZhѢDVV,ZhѢE-Zh-ZhѢEYYhѢE-ZhѢEVXhѢE-JdeŢE-ZhѢE-^[aѢE-Z(-ZhѢE-ZxmE-ZhѢDVV,ZhѢE-Zh-ZhѢEYYhѢE-ZhѢEVXhѢE-JdeŢE-ZhѢE-^ $XA .dC%N$ E)RH"E)RxpE)RH"EPH"E)RŇV  ++WPHQ!D D+ `` (de!++)RH"E jX1p A+p +Z@׬X@@@VH VW@ ׬@Z $ \ D\+PkkX! Vx-^ce5 4xaB 6tbDd@\vk׮]@X`@Vx5 x @ @p $Hp $XA  v5׮]5Yb5k(ڵk^8@ $(^@k(ڵk^8YYxM@ DPB >QC`% \@ `@+"  d+@Z J ('&VY V+ 5V+"X hX)\+`5X!  d+@2qĉ'N8qB8Q YA\1qĂ4q5V b5qCVY <0… :|1ĉ+ZpF1bĈ@VV0bĈ#F1bxqF1b@VV0bĈ#F1bxqF1bĈ@VV0bĈ#F1bxqF1bĈ@VV0bĈ#F1bxqF1bĈ@VV0bĈ#F1bxqF1bĈ@VV0bĈ#F1bxqF1bĈ@VV0bĈ#F1bxqF1bĈ@VV0bĈ#F1bxqF1bĈ@VV0bĈ#F1bxqF1bĈ@VV0bĈFaFat@+^8`A&TaC!F8 ++)RH"E)RH)RH"EB"E)RH"E)\A"E)RH!++)RH"E)RH)RH"EB"E)RH"E)\A"E)RH!++)RH"E)RH@h5 4xaB 6tbD8P` $XA .dC%NXŁ8k,h „ 2l!Ĉ#Z@ H*\ȰÇ#JHŋW P` $XA .dC%J@@V H*\ȰÇ#JHŋY 1bĈ@`#F1bĈ#FF1bĈ `Ĉ#F1bĈ"V0bĈ#FY#F1bĈ#F#F1bF1bĈcDV$XA .d!C 2,5 4xH*\pC 2dXk,h „ 2l!B"D ++!B"D"D!B8pD!B"ą+ B4 D!B"D@"D!\p` db V]b ][15W&p \X1 Y][qZ H+\b!+VX @V@+\c`@ +0 ` +`55   h"D p +Ȋ@ bE k ] pEX  @ 05   8 D!B Wꚕk`e+80ЊVXvڊ׮bV 40е]"0еY r͊@Z!յk׬\v͊@+V vڵYhe@׬ tm +$xmE ,Xp ++Wꚕk`e +80еrڊ׮bVdj`k+fE`k+hŊ@v5V]fڵk+@vڵYhe@׬ tm + de5 4xaB 6tp Y "D!B(pDYYx@!B"DYY"D!B"D!B!de"D!BBVV B"D"D!BpDYY"D!B!B"ā+ B"D!.\AVV B"D!*de"D!Bq !B"D W@h!B"D YY"D!B"D!B!de"D!BBVV B"D" " Z H0a„ &L0a„ &L++ &L0a„ &L0a &L0a„ &L0a„ H0aB$L0a„ &L0a„ &J„ &L0a„ &LXpE„ &L0a„ &L0aB+&LP ++ &L0a„ &L0a„ 0a„ &L0a„ \0a„ &L0a„ &LP &J„ &L0a„ &L0ak$L0a„ &L0a„W$L0a„ &L0a„ &"a ++ H*\ȰÇ#^ceED%JXpD%J(Q% deED%J(Q!++%J(QĂ+$J(QD(Q ++%J(QD YY(QD%\!QD%JpDYY(QD%JTʊD%J( %J(Qą+$JʊD%J(QBVV$J(QDWH(QD%.\!Q@VV$J(QD"QD%J, 4xaB 6tbD^8`A d 4xaB 6tbā H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx ;;PKTTPK D"OEBPS/img/pat_ucp_containersrv.gif] GIF89awܛ'HP[bw}!+W_r|ԟܛrwrԟ±|r|w2vr|w›2r2±rrr2vr2r2·כwԕrrrrrr8;8;8;8;8;8;8;t8;r8;prwԛ㘛rwrw•223rݛr㕺rԱ8w8v8u8s8r8rwr™rrvurڛrpsp88888rrԛ8utꕰ9;8qs8۰ȕ˭8ԛưrժ˘گݲخլȗ8Ô8̙8ƕ8’8rrvuڰrݳtխpׯrԛ̘‘ϛʗǕœԵԳv8s8ܺț|ԵԼܛ|꼯ԟv;8u;8r;8p;8o;8;8;8;8rrrԛ瀀!,wH*\ȰÇ#JHŋ3jȱǏ CIɓ"o\ɲ˗0cʜI͛8sɳϚ( JѣH*]ʴӧNIJիXjʵׯ`ÊKٮϪ]˶۷p%ݻx˷߿ LÈ&ǐ#KL˘3k̹ϠCc&ӨS.}հc˞M۸sm:)x Gtw>Ǔ'1/gҽ>V7韴\owGϿjq>!& :(0LH "8_}|2}%0:ҝɱ xH܉cԈHC#"Lz d8N ?:)c0d(_Gv7c(hjI>)av~+"$s~(Ki䊾p AD 1t)6 ;~!ҍs`JE" FJbƤn dk묶jj"fzl:[鱳Jꦮºi:ykm,+*RZiJjӂT IzJo0?||/@HOL!? T|1;U01+{q3Fǯq! MEKɽ|+p7 4?T,qr Mr1&̈nc|*7'Ol4'x7NJ̲vl62+2c,3^Gs>=+-K.$,d\5eK,9m:;?Isθ?lw⵻:A4 +NDr'hyh PKЃohc/ "Oo|(.=Q/89z[_$ 5~ً 4_!A /<<ЄT𥏅8") O#H?DX=(D?+4NL:ҹB0vHG L?AhVt# .P1cm pd0[b?1.  +2o,x%ґ$#sFP񌔴$(.f1^ddO5pҍ4c-5YKZydINL2f:Ќ4iiZ̦6 w\4f1IrL:׉n~d~'@JЂTBІ:D'JъZͨF7юzP HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMjPa h*aéa*Vբ0 +Tf&4`!_ +-D֮%l0j zu ZW J *.*26b$z,-f9lUk $keQKیUdY: (Tvmm[ 1FոO%tKZͮvAw;[X x^pcJP[[nH{2uB/mt7/NA(APB{ #e "`&E8j pa9;  -g\S3>D:PA1r s8H!K$cy r;b,EKfNy6=G| vyX  0<pys,iXEC.27e)35Na\;2{mgyZFnkZ+jkLjYl.8Ϝ+zDŽMln >iz@wδxkL_C&<t7hue:[.1xikF2E?O7Xۄ\Vz܇iv6aȪ7N}[w_\sc¦lC_p_Um8A HTg&uFnuր7X_707oxol)Gb~``q*ewc$b%rW&kw+7a-gqUնesFsxtfCwfuIfuu[VSxu||guրXVvt}WicsVfvw'ffv7xegHG|sw~\VyG[wu'hxfVoxf恬{vgejiħ_{XƇd||-!}Iq{CV`7ykm|6kv5Džy6EJ ŀAx؈n٘S8s*B(l8a^Gvfvg_Uh$opH`ք6/v7~{@u#wq+vrSra)6pюWd&'oNJFd6uؒ^(AV!ɍh8q_Beeftwvwyw 7g5ugy'YɈh)9ct~\{inMxtYȑrG{a5dq0mU~/'8{8(in.9]X Axz:Id)y@_љ*^6yq/בI=Xr#)7qrf5(y7i9^Z(UdM7|[XXcioᖔqwxȇ啡^p{x{ٟe:j: bzTz+; ";;PZjdK*бѰ6{wPZkꊱ%k+[K?kD˲! L[AkZD RK0UI ;[|  !;{兮{I*[KB y+ lJGӪo:`j ۲Uګ#pڱjzKKG0^yEկAئAŹzmz]{D+ۻ8Š;z xfnW !DZn#؛[;d7" Ik>(yky'օ eWHXwaX ȒFmffY Kxyh  :}h(wZx˗ycg'F8yH&(,T+02Lni9Jķ  =+ޛȃ2"d Ƀ+ w0)UXxOǞ+VGȮg mla\D9XwǕweq(Ԙ uԜɏ6Ȅ'Ɔ(w9rlH=.x_YG|G)^0_`׌0(a8 pέ'aqgmΨc7nvR(eAt˷{bt2V3px6hz6}cdx]-zCp6Z}l}pʪouHw 98յlcVMژ-żgot1n%xM'P ,w8nn%ت,䇰G-~W٢+w|3*1, q3G -^=[hTB-<ǑApLt9haCj5=&F~O2yʊ}!HN@.\mnIܧ]M۵hlH<̡~ENn(A͚GFHa"{ZndHe^%AQ^o+yR͛ۤculyy͜ƍʽg^aܛƍ#-YoMÌ{5k:}%ȻtXgԬΔw ؞ʌՏ^.8ဆ~w6ׯN兘`,pWoY\[_adHin>O@rTL{ p6-6O%ocg,)8]'xwܔOz}'SXBycFoHi}7ZYdN;e 6[.xx mdɼsOgoφѱ6vCh3 rN PS. , @P!? 0 B+(HGQ`A#=4XK1eΤYM9uI_ϟ7m$ؒ %J@E!jiԊCM L*פP{e[9ksCn-HrվTG+>x&SV[e̗ʭb2>T šn=sQ#/o-.O^ǹ>}p@ )4pAtA#0.B 3 5;IDK4DST._ Ɲd\F̀iE,G q4]gI\ҟ\"/:*)LCʹ( " +)<4H(:g+`N>J i8)6 NF]Q(L22L+Ё2KN kTЌrҼ ⛥J/41$#uQTQM"= 1ҰG܆SﶂrSbDT8ֲ)H#0DM*)/ٕhn%|[FM>8}]k:S5Vxa~0a#b+^b3ae&q5QUiȎ|dY('{cm%%RCTŒ2JmJ$0Ҩ>s\n3jt7 ٸJDS򄎣(פHQFe85*5W1*Hf<]ȝVL,Q:-ÜrUqL_dуfNsC&.Bei㠏Q>66ZlpNMZLISrK[^{]}~?wߗ.~ ?~$` 59]6'.*p19ʜQ.3s H ΄D`y '`>kRPW/h/BRl"z@ߤ{GaxHDY+ERR͍%u{[Ḵe{LeE^''iUnv{"6xU/-TSӈ{B><VTm?8NWC,+ ch`s I25Ud7;C H9s@%)M#5,YOs`jIu"#Ȋ#5\Ѻ=d][AҕLgN l3CK.C 7D`Nt8SdY8Y1w3bg=M+YK@xO=YzI-$eh{)LXcWЄxm9(Ƭa9=B %\G1n·\T(OaL*9]3V%a0L*vO&И6+8VIL9T%tb K _S K]]}^W)$Pzq=\zWǮy5^z#U] "GT䰉˄il*0D"'d@X"Ve+BRV4EY?=@0g f-MT.٬,@ T6dOÆC0AeZG"ekvon 6}fAGcLq+ D"Я8 \ mbaےWe\|]XRxӕ BX—r``q]bX0lVv50L+7H#;b  Hpd(GY 1fdڊU.jJٳhӪ]˶۷Z]}XzAnÎ-ػo}v_} kX2wku3IWǀʥ-}1h԰cˮ&V6>ͻ߱]NS[a JN>A} )tZgx>}FI:v#?{DLg_M y h~_7`[Etv^{gt:>]y*~!2 'NG#wG 1tQ$6 ;~!Eҍs0IE"P bF2ƑI> 4fn)jΩe"x6gTy~ޙgY&bd:fm)*a"dFZeR*T| Z떎IJj#,?|ⅰ|/@rưK$,;U0-zl+Ffɴlv+ڋ憽}+p7ΊK/?ckVl_ڋVs *1\-2B}kKl$k_0k4!5;?nlri5G +NDr'hyh 㥈.S.o83. 䦣"Ѻ?d Sx ǟ.xxGy;k=3zуBB#!O@C?a+la@3@rPK (A`(CGH~P Q8 np  1C R/Wh7D%`{(A p}QExF щiD#B(v> IB268"F:p(H=汒̤&7Nz|$1yIPL*WR򕰌,gHW̥.M 0IbL2f:Ќ4ɑjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz %'3@0 $ yT #}iHgQfp,([M ժlbԜ>(ְ66Ac 2 z+Ig`UΚTMjWֺlgKjAhmw ŭn"\krcJPx\nr,@YBss! qSJPܞ"HnfInсNx_$ؗo`uo +l%A o0Cu{3 ׺ͭ{w29<(A6yxtIc59w3IVXw[]W+M\$TKwu'f!v wtnhִ Vy z*ygctƈ@؂$hc$菙p7y8aq@De||( 7\QsYuQwyyٗF~Q؋dx4u[YM9VWyɘi7ڥ䴗 mV\wЗo h(popcwFgY\:H2Wb'z;HˈIxl2'k:D:@N|YEK0#ĤTGlP4 1Ӱ#`Mk`MaʥQ4TrjWM7d*Pp4 &1 ,pi: q: %F XiZbJ^Pک#pi* _ P~QjPJPKRګb:o*@ڬ.[J`a* 4 P^  ``1୤!֊:ڮ^Jua&0Jꥳ c _jڰ_ZQzZ *;PKKtZK pj=%:*!<; oʴ 0AMxʧ Pq 㺰 B +p:(*;+ dUks\:\*kQ#pj~ GZj;}UZM+eyM;XTrP9ջ h씣_ht\놾ĻNfll_恱Yp;]ugg=8*vYsfiW'uIYM?rw9fuixYI;XWaXeWvuq[4$O&|*\)¼H.,P-ì@i{˛F6ټɡ~fdêtyJt2i"8١8XeF{N((phh_òhly*7fY3xf蛒/9klj6V^YɄz=ܢmZ$m۲ la߸uNH X\{Wnmbʍ{})e\\8}|a^3]~r2\櫙l{ΧH>@>iᧀɝme]0^7t'|ENOyGF>)-YOUѕMY.O~n>Pn5>ػ9&`k)4OVLϥUF8ufT-matgVݾȩhn iwh@ .IMR֏vPfb힓^_pgw6鉕wfk~wsu*ѿ_ti_ٔ $Xp?PLnA%xB \FA$YI)Udʗg`" jܩs̚7[%ZQI􇰩ӦPx˂s ر0ĬJdY TFD R9ILVnM&\d:%u `Nqňre8NXMWhN㈙JkرQƜm\;1'H掬3pVbWaC䲵o. YCnQr->fV- L0z s,,R0S{P5$ps:LjR@ pE[4+%103K$ľΣo:>rFwÂ&2E(ܨJ,L)K0[214L4TsM6,M6㔓08NDqMXo7z!lu2֐>.}8?d99Y'+ӪxɍvĜXA# "=8@+ YB3a "C>9yC x0ZY&vŭ_ZgJC ~!Gؽm#  S-F{LJGF^\cƅ k@#w%9/¢Hv9k=k[XEI#鳬Kv2$I\x h$/.YZR`YBqY_)[8Şh}$U/zEd`tzNdiHZR+eiXum%r[C[j?f(Nn&™SnqU&#>]r?=Hy:XE(yg-mUZ;P)z 4캞R+hY ѶМ7įa]ńWu" j (2QD$b hX0uG>ڍTł@$,04ĞmU-TZm^[;vEmo}[W%nq[WensCN#t+d @vU`p7OHuK\׹ͩA)q@XCdW.{V8D;xvkn8T@ Wu,2(w!p[ !&yAGcL+\l )ǐűhBCoK]GYFJsq_ww8v|G8,c,׻rKx. 2b;BH#f; n&qlYW |-\<΢܀;PKSu PK DOEBPS/img/pat_smpp_arch.gif_GIF89aTvp,Tv$$ $ $$$ $ $$$$$(< ((( 0(P$$<00444 488@8 4<04<4<<$L4$$00a,,<<<@@,@@8@DDDDDP@@u44<04408HLLHP@LLLPP0HPHaLL@@@@YY]@HDHD>ʵׯPCHbΪٳhӪ]˶DNKݻx˷߿jLۗo^̸ǀ/r˘3k hCMz/9"-nsװc&$ոsޝ97 ^Wվ_|tyKN:Lʛk߾8RعWS|ӫ_ӭD{!¾ih؜9upVM`(樣uP㏍@e=i$`+DLFJGF XXEaMvee̐t5Ab9~_Y )4ytV@硈~4(]H `HNEBcnxi^\>2iXRD*`b@;C IGƮixيb+` Klc";j"x*|j@%\+U`e@vW;׽u˗εi[겋׻3]U1ů^ ,^ee.(idž+j04g[DpE_K^+Pd *-zav6nĺ!a(m mf{-cᲊmWYb V+RfY'ig= u]ZebϬ cNxWz[xSWw5 ԻN݋ XL|&95ˀ1^o'Z(VY#a {,ٰ0xCoWܖH!A,bo,αL|k(IᱏHfА FKOLe ;QO$J+gY>@\o,_`392"|!fgl΀~I>B>7'pe]hC/N'o<@.N6B Xә DR{ ulՠ˪vlZs$:xb-@ћy@ANvA|т,ЎMn{NvrPvKLP;ntOp8%?7kÕ[ .ohƸG1Ihg)|Bxӓs@OGEhv>h0R8TXVxXZ\؅^`hudXX8fjl؆npr8tXZX eajЇ~8XxL舒Xx؉@ {(H؊8Xx}`` 8XxȘʸ،XwX8xؘڸ؍hHkIHxL؄\w;Ȏ掺Hfg`6fXk&:IiChSא)u@3F|y%7ב/@-j8A(9f*f6!7d9`pf')zOY,w @n12 -Д:] Ff9^ ѕni!DIu),F @2I,!V.)$0aɓY撉#w) 0ْ"l;% !U2Еi" ƙ :Е-Y%ЛGJYh `ٛaAe:r.!^搔0$ٕ ba}٘ӝ pYٶ< ٟ`9-ٟj )pY %29*Y٠-7Q铤*:0JY'B!&P(:0y` AKْLꤥ$@Yd4ٛ PK73JKiɦY\*r^lLwzy%[}:ScA2ZeJzT֨!({J{ZvGFʩ{:*tF9fpbڪ*%bHlɶ$)JjKv` :Zzؚںڭu::z蚮꺮ڮ: p1گ;[{A k ۰;[{˰@ ;$+[{(,۲.00; 3!p<۳>@B;D[F{ELL۴GNR;T[V{XZ\۵G{J3a ꬻb+dmaêŶ5ۏxe˫g |}Kbck2!Ǫ[{분+k|0qJe/fkK˷;cT-q{oº!Ẑ{9 dѻ6@{j {W{ӼA3k `ϛѽgg#K^ߛѾ[{KF{|ҿ@'L΋)L! .! d&Y뻰{+-A d %"\­K!a—2$+ ;4\6 8l9:<9-̼E,Sĵ@Bl_:Q\Ue4)h\!jř[g|bŌYs ]<dME>G( z|pWIN =T>Mp]B gn} TmpѢ m Pptu>w~"y s2>^~> !5lkL Sn%ݒ`Xn^ 0֝\誎NNi~p.$>^q빾.2>|~~Ǝ]0 l %}&@Y~Pn&HHPY2ѱ` $7^\n+Om . _.z~ˠĞKp0n. Ѽ@".-垐7SN`[00JOtd-獐B >_] K.]$>MN-~-~{}J\g0DO/Ց/\Mix2`ex #B@]0 KԮM~5M }y@n)&LpA@RbĘQF=QH%MDR-]S̙\Y"Ct4ETtYU^ÇAXQ X^rҤ QP-$(BǹuGJ $@XF+`ur7xwb y_J,ĵͶ>D}|yu%}J)`L췙jN[ \J?/#_* j/JK$*P$`, jІ1Z >X~euڲ “b~2"OZn X4 {PdfVQI @{1%ab9Mэ1ƒ؛)=TI >яd 9HBҐ$HF6ҏtd$ ي;Q{"7FNʦTG.RB&A!TJVҕe,e9KZҖe.uKA$2N3-PRƋu^tI,LjVӚf6_i1ٛI @;M3 f69OzӞ/δ#h@:PԠEhBP6ԡjP&W;X/xӣiHsOo37za ԥ/iLe:SԦ7iNuӚaKK{AjQ)vQDԩO5Iڦo^X1Uvի_kX:VլgEkZZV k5Z,Ƭ;%Uկ꒪ƫ^%pElbX6PA:X՝[t&;Wפ0_6V9cUZֶڐȁG+4*ͽַhT*umr\vb@\]gj4#!.pmvq\׼煫O'N˭uw]r׾՝p]W)Eo<୒#Uk{[B]ͶG,~%p YPGWMdYpnت*u?CsrM(+@ʿMh@j: :*=/U3V{!Mk"(=1_C85܉n>9c>C7i46aS>>t>8>a>>'s rܰo؂Iۀت ܪHʂHۀ WCp|=D`CzxzC*CA$DZ"=8 !-m8k[1_[8V81;\ H=D:X9\>C%>H{*() -4-p؂0TA1Z,6_;d8;c42Ab#^Y7r--ot-7qL"J|؁>hDqw|GGz H|,X6*>@ć؁؀D lWC7C4M**aB0SvlwTKBJ=RD K CLT|խzBt|FGU+&e)} ԛ իM Ub2;+SD,G,8ObEC;O<@Z+qM膷*|ѮK`Ňxl3ćnpTrKdZEiSTxTRjKVX-; R +[hXr:LGC,K7XWRYB*KY+"@Ydx٭ٮ*YzˮY;ämKIJf=Lͨج}QV(Ѷ<ij* 5P./ڻ}P}'U+mh+HU-;YeۈbҰzثVɵ'm -4][ ܳ,0I7j3RrVVʕlܳ\ [XA1[^fAi;z]u^ܔ\5^ZMޤ:^iE_5]ۙ ^^ * (tX}+;%[mݙݴ__e]XL`Yމm~`U f5 ^``6֊(=auP]ԪU̫F wa(aUe_ۉ刊Mbji{_Ê_jԭbb n}ᇔ&><=>?@A&B6CFDVd>X++c{b(" (mcЋ+!~R0SFTVUfVvWXYZ[6b}:[.ap L}d|`a̢.3rfgNz.b&\bcJf"gg%N^sFtVufv8hxyz{|gڂv>Oef/炆qb`v臆b pMvYx PQ6薎 y h&b6biÁiQ%*nie[^騮vч<&h9i^i*&rNO&hkW1kIX&v!ۮl{)ktlnN>)N-A.nfI^d>H̶llі"m ֆj]jږf#Fmgmh}<"GҮjI~&^=V()Yoflv^^^&WJ-lo&o]&gXȅ'c Ohj @vq;`jJ`9Pn/p(Nw]7rD`'oq/ep G^ώ>+bN o'/?vn#9q0wOqkPrJ;/5l783wkrr(rAkCpDm@mFfvm:tЦM ter&ru5ɹq G_PXR' H\/ (/j2W_'kdOOgmgshvok GttmoWp7yxyz{x ~wx'~79funjvY$%/][@'w/g-ЄB?y-~qPW`xpy7r {0GWgz߂+Nzh_hyzAZzuIٞ&2#-?n ?{O U XE{zuJ_w{4'|YGz5N`/GoʯtM\O)7}G}(v}џ _"_}/V?ǧn_i]07O~ SU 8gK4/=[G-|oO`,h „ "2!E 9gb]EjaI$J7ly̘2gҬi&Μ:w'РBJJ P#ҨR UjFӟK2  bִmC5Z&KWF;-l0Ċ3yT*SP!Cju&پ|0X 'VԬnACtЍnwMۻl78Sn)UYunb%B'Xշ'\$6Ӷ7y׳o=M<1aB}(ɓZf[;w_5VY܉E`'ЁifIIh|j!B' 86H5 &Z"j-.hCHald~Ymy$~x"J(Sfh#B @=H#-J]EH`AcI&-ydLQ6e@ւ2"g3bjy_f&m:(> ' h̹(Bq3 [r֡d&m hjKA1 4"P)ue[nFl*`JR!:حjfp h $0٩٩͒l̪k楨b-jحqdL͹nu~bw0ª;|UX{1uk? iÁ*\\1˼XJ@ l(L$ oE`Z<3M{Thp!'C;\Yk=@N$XAXAYp} ,dA5E|K%m ~ t^[.8ftOl9A2h9Œ6= ~3DU'D{l3 fh9`ĪU6jpM`^=h jŠM. '9;D/1nwiy$2/ɴ LKPҖ\&X=5~pdEꦿ=# mJR;$D 41O$-`ʹ"Nh_ YJ\g+%0uapY=`%؂)a'J7OoU2nŢY :B~ !3̈Zn CIOh?ӣg詖wL)VïKq-UK7NsK=3YNqVԨQ JuLT'*b--0Ճ%GJNsz%J" s;ibSM0 4 V- @?¬5H+G*qC@B"b!^H4$xIPʍ s+ lWC#8 !'Qκ9beU\Wi_ &HhB L &M0Mܙ7AC[yЉUr\nMLҎԴU_Fp"dgn\$@wX0M*]dx1"IRRW{J,g9MdLZ(9&007\g1e X!h0ᘔ{37b!${ti" ?&>W:*%2Pl^Lom Ubgu +M~2g8Dɒ  x57L_6zV0AD=L}fVxS%]Eon벍c䪻O$iuV8 3/cnOk9q>p{@&Hxmo!A3/*P6Cgvs܌;Q^qXjKr9!htodiQ7Ȭ9a|#7ů#|X`0qxz)n8&Q UIi,úȎ7UFy]fs* MsKdk\z]G'zd;pn{#׿<>݃Ӛpإ87=dzn8uaZ0ܬ!8@{h(h[Gp數)7aMţXA?u [~˲*|2] j{V.ِZLA]"ْq]非YIWiYH]YIV@0C_3N Qi TύRzكeU@ Ql' +  Be|\ 5儭= '^Z]yq1]٦)- 5U:x/Q*=P_BlPy_Ao99:,U'ύ!HKaKlȬIaD6`Zita"=]31E@ikADb&7SThR,bi7+Q:TA,a,%p|Q[w%`48J#ڂWwi#쵙bA"R PߥYT,JxQaNq>n[ P"BAdK$a=,%GbY0#T_'}S"jyesń'wMNXXy5>ZL$B5"ڡ%w奁-]NFE4@#B#YM_Q}Mi@D!T)@0@W@ eL)֩ڨNd[[/Fj|$4#P]UbjX T؀Jffv*zʒ橈 VjJid $e&E(q!\)Gݲh:kk)(U%fNnkR@Aʝ 1~*Jj껝L$*뽊k+Hk/, ,,v]|˷+AlUNbl0j,rlǮ(kR#E"a+̺꣪k`&tҩʒk6m-"ѢRfʰ-V$vBR-Ѳh*2-,m(LB)B~NilP H>퍪áiߢzD:llfϾKX̭'g&gj>&(<†ꦭնnjr)ܪ <.zziG)JP /ۮhֆið~.vEVdl*'jlxDvHlvn| D.-Ưro*"LB/ i6 p//*0ul/Uo4.oƾo2p80 ) $`XpppbT6KprE.0?1gզBll1Ņ#KpˢS/ۯt1;w{x112qcpb;nopv$?%o%.D,Dz,2-ײ-r42/߲.0r/31s-o,B4A/2:1ar0Pq^0t738839wH@9s9Dq:3<dz:;$7@)5J@_D \@4B ( $X^k??o&4@ `4GwíC4S.5D16V+{􌤀 L4J83$rJKfE[t@4m\@ Qt ltD?4qsO*{E_8P5Vc(N)S?uDu guKtZK 6,5Iqq55E4 kZB7^5,tC{\G]oY5`{D[/CcGf\tI_oub#^qJ?,hvVt\WC4akFggWrhKv xjvK Uv\45JǶO6+vcܴn7G\ssat6qqud_;wL up#ub4jww{ oc6yp[yCJi6{;HxN6OӤ7r5et77{x4׷f4~+b2vdρ[GxsA{wk7DksNd_Rxn77p۷y07v[x߸g6H`/g8z)j6xu6uu3y;96evynxxPG6{Cvyg9}yopq^xKv[c93Y9kZ K6+: Cyd/vy>#y綔[z77T^uc/{̌z7v:\wyi#xy'8g?ld`g{c s>wy;459vRSx[cxǻ{Z\;`KʸoK̃7l d^AЂ}En JtQ uu"$ 7MP a\Bޥ9c U=1wʆ1DzC :z"LeN@܊6t9xهP9kGr e^!_ '8r STR)HҐ""L}$3̎! \،`-Xc x̥2$`@=mn+w"tp]xK֧`8xiD)C.DT ObPQ(zA^)} PSUh~꬘MOȡuhEQ+5!+ֈhCgD2@ Y4MAZMJCB53{5@X;jAkXю6ON+Ků\k6A?K*iqVmej95nd˘:)u\#{w&Kkir\(Jl玷FY]ZW^vuv+Re%}$ }uKk$| 0$/N .#K`o;J}9)^3丐d߮}M{99E`U0xLbAZһb26l9Х&k`ࠇpakYϚֵqk]׽90!׵GC}c&ʠ&նmKvI|QZ 38nuvoyϛo}Fu\07 wI̕M|01qoAr%7Q.U6,asC'>$$Aӿ[tE VN43wӡ>F8@Ry]|$?7v,'zӣv<Q2fh%rǞw}eWz뛎ٶEf`c],tOO߿mgiA4 zѻf p՝.w@ -{ٓ=陗|!Ga (H0z$&q_yg}<#P ]ݜ}ۧ+DlP`?}*i޷?%~'Jد 0ܯàh .@| Ft H-pIPMp;tE@2i@q&!@ ܲLoKs#$ (W#a`>uht4?B4u$@AqP@@1*-r!;R7i41)R,;7DRiD*N74*´~MpFϓKl6*֎G_p=Q)H)p* 'PRt;"s,<ִ&NLt"+R- @/k&TAi52ɓ!e4$6Єo2 `d>KP0u%`1'uԴ2Jx1l9?u!\#BcKLr[2a0T ߕ;N =Nu]nX'=/>;O`Pi H(RhGHuR)Nհ:Q**bVC# <+tJB%huRb@9g *TUiv+m w6#s$H^֨,v5=oY& N)$R">ζ1Q5 ] wpkwqqqvo9l P!ps9w hKn)\sOJ`pY 0xa-aFW5Nmyw}Y$[oe_bu_7httx7@K5Ru#l7{Ǯyy{oeolu|g{{}pzOWR}Է_}7u ~  j7//~I| x}N)=1M)΃A.aMx n~ Ѕu`Ud8+7W#~w8/O臃_95X7zUx5pb[ToW]XτxmX6؎)Lx۸Y/q!!9%y)-195qً9Xu"ve7Uy,VaYZ9׍,8q9(A@9x[闬٘9x58w gԊyK8s+` sԙřٜe 99Yɞ 95Ǡ:|yyh*9IysD̡9}=Jťڛ:syY2ڢ1ym:qJ٤ŨG{!I_g:x4)ڧ_eZZ_ZO:xڔy ٯX ;{!;@-1);9=9[SE{imZoY{zZ)Wi׵O{ R[}۶yU1{)9ڹ󓻱1PڻOscx9{U{Wz xzoW ;:{o-< R)|/aNA NQk8x=H]qث5\s<#x|}|xo\ȕ\충4|ɩwyۦ[| |ݺ:˿<՜|<||\Ӽ\ŧ9GW|] Ѝ9K|]=!%}q[<59==]A=ԕ|ԡQU}]}w_=cݍg osw} {}=S]q{}4ك<ٽGWۭءVܻıɝHӽ/ܟxݩ}ٽ=*} ށ8G={gaxA\Mo!‡:a9=A>E~IMK P]I^Yimq>u~y}O>A>~陾{` z 걾駾곾>~ɾB>>~r ?!?# $1?-_=A?EIMQ?/ɓ-rcE{i_m_u??:} ^ki?ȉ? Χ ??̷?|1ǟ\ <0… :\l+Z\(Nō;z2ȑ$K 6رY%״ײ} 7܇f_}vn޻|[߱-<8B3Q1[R#O97oӬ[+K*ٴk۾;ݼ{ 61̂?|ɛ;=ԫ[7.0,˛?>ۻ?`H`mFKj!k?NHaZ, $^mbZ] Srb.d/"\5Έca([>I$G1bX$H7dN:yOr$Z9eYFyUI֕@zI\Icf9ZXfvmyWz` Jhh.h> fQF^VPi~ jJj*jNZiފkkO$;,ĎZ.l* I>b\~Nm )ֵ~ .iZ[m枻ؕ.;ؕ;Ƽދ[koվ~ p+E0p>%OLIooryq"#2\%'r.382?3%2\1\9 1FF \C}tA?}0%L-O\RO=FPo/S!Lu.ʹJn{Z[=o Ex .H%Ā>mYψ?~|%9ۉsCJ袏Nz馟zꪯz뮛nC쐰M^{|F"|/|?}OO\/}TT|c}O> 1\TDQOOߏϴ> p,>9 }r J~' jP d`\.p G0[@P& g¯.L u0&? SGl&:qL"E*jPDIF.KDaЌhlXF7ʑ]<zXZ/9$(r~6XGqyppz##O}\8h` d;52k lFq1D$E> QёCRuKFť$S**URUs"!T uD[CQ]ۇ𣏕jզp,D  r8ՌJdIjĈd+GVҴi/$ؤvuYzqr`Gob$~e=*n al6iHQjwp}_zb՞uZ%wq|K'VW$%`p\3 };Β#=)?ջN{&*"_>0 ,|ؚ; .*Zzq*%Pq /M9pOq$9T3ĭaARuAY]0NٶtFqS`"rApH<2X֣BpT5`_ { ?*h# >Y{V-Dۑƈᣓ ͓C7z'DBZ(+N{: G=hPwDԨ`MVQaiXַ 7^#պ^$v%hf71YXvE9;vum7={|{]o(Z+|IcH|/k|?r&O|=;PKV`_PK DOEBPS/img/addel.png PNG  IHDRT<sRGBbKGD pHYs  tIMEY<tEXtCommentCreated with GIMPWfIDATH=KA@~H"&'[,,ց+,DP*,BH^sir^r-ĭv9fwVTU1J)cⰛ;60>0HĪ[Sv(ڍPL*9Z{j)@+CQ]"z yC\6R* ._invCy5H-ab$Ѱ5K7ac]0AED@E9e*);X'Qlm }9{~[uYZa3y:^/n4:?﯀[jHqY8HO-~™XR,d_wчMIENDB`PKw&h PK DOEBPS/img/layer_highlevel.pngZPNG  IHDRXRw6p pHYs+ IDATxw|g.rwPzH"HQJhA>HDD E C 1 I @co?wtR0y?co3}71FPUA B B<5klܸ.ZG lxxٳg!ݺu۷o߫ 0P=*S+WJz:2 *CUYCrrM,ĉcbb*1jBSWH8Nw5j>>ɑ_R"nC?,X,Z.FBw4Wc())yl|>ۛv)ɄlˋkM]V =~ROU4 6_~=EV䣍t@R@t:+P($ƽ!DҢ՛.1fnl;$9NY vZxxxv._LBN<0̰ad2٢EB L8Q&}[nxbо}D"0j!tqD0LvB~)B!`x ajԨCMBWVV7;wPm􌏏DwEIҌ ???B۷oGBa>} BmڴAm2 #HΝ;G^R]td.@q.= #铞,ȣq*T~~~D۾k@'MDNI$9sZ#~7x'}";BhNKK ̝;sdeer@n:T~j7o$J˗`„ |>_ |7܏Lՠgr99X,k׮!RSSI XՒ"b詨7ҟqxx8 ٰaÔ)S6W޽;7 6Zjasrr|}}wK^=!TN;w|||0"gz91n۶- 9rdRRfԨQ[nqb &`C%d2}w~Gs۶m~! ===""cѣq:7lp…~~~zt:___rܤI Ёy:6m HII!U\ڴi3p@>߷o_UN:;\>` U)wh_~eΞ=[^ZV 8У'\=nHNvΝˍϏ6p@^oJ@.O`>:N,kЯ]ɴf2aXD"ٳbiӉtܹQF../___:ODt:KJJx<ĉI%{K8BW^wqѣj GJJJr9TJσ7oN;$ikd]aZ=<<tҵkWę;Cdp`4ܰah]ذa' !in֫WSr8~D"9&O\^=PHHHnn.Q~~~]tA5jԨw^^^.;P2婐dZ .]0̑#GHR0 B&Ocja̙3ӦM#$0ӧO>;`0rU.]Ӊ t. ARIj5QPF'ˑ960 ˲ݻw;ٺu+=7Ȓ%K_NBT25*((xĈ>>>?Nwڵc"N'Rtf b>JonԨ1*HPƍg̘AΘ1Lyuuj5x`qwy jժ J4.[hQXXjUXL&V.>|ԩSߧG}6B_u n6)~)ShA=y!~!`8ycY#RSSIӧ_E,K8q>'O&zԩ .@/lZ^!STTO?֪U+::͛uկ_?22UV111D,NժUԫWVZ]tx"#I&!!!-[LIIIJJBc-CCC E_|E1SNݺuAN:^LjCCC֭'Æ 0d'+Wb8oT^APUȂgǎbg7o ]!oҤ~i!]v_c֭KϟE2c|ܹhn~:rUM(Jqjj*qA/$'$d͚5.ς` ˖-"fٳ'quS#F͛7o׮]OI&*wE޽ZjfȐ!6l MtҾ}{!>>!dۏ;V^=X,&h)K7n4lؐ:Q'|BDR;ӡC.Sx jNMMU*dQv|>;/իzawO>v=))iěxknnL&ţ@9ܹsb/.dPOrc,o߾]RRBw]~9sRiF޽uԩSTV{ʕ7xҥKe*ڵk Bnn.5E><<<|}}Hu%smBDqƍPPn5k"D"d2MAcN!#3z}I z%%%nݒJ!!!ܫBժUkӦ͍7 hHRxs?{}ѐ:u;vlݺu.Ti`ǎOnHƍoݺW^@@ƸG,H(SB!޽;m̷lrʕ ܺu+!!!$O8A9qҦMٳgk׮&Mڵ8q/'NZbeΝ bn"F__rrrGC<Ӌ=)5SPYYh:%* | B B  i@8RIN@xZ* cr9wy!8N5y@ fNC!d2MbpJRb2 /Bw*[k`0L\Zh2B-@hZ8]+7ʔr[,2 H\.JP^!I9/|9-$MC-@+Wd2t:2:/#W1:NB"U! ]&BaL&BEˣM&ӿEB>oZJ%@xIT*տ-.<fT* B8ZmZ fT 5MII kUx`9kc-Bg`ZZmPA 8N^OVV"x<E * R-Df2 e -BWL&ZFYۅ t:o ѨhD_ y<YVRN';!BiZN'*YS :(}B4v,- $¿L<b%"P @8VkX!#U5 cTPRqwVdez[ <7) X BIIR$JPdܹ6et:d6\.ɪ`ϯVZYle>t* TZMC1 B+N?lIQ5V]C @yS[`(k⁦B<LPn #,?NPu0((2COG yPi;L!, J}n%J!& B Pxd4hPQwVNRPP`۫W)޼y$g4[h1=zk׮/znZRԩS5k֬^N{E'NS,r/"/ U#JJJ,P(H$,k<+׬YAo[n!!!#?+PDDDnB'N ~:9;dȐ젠k׮!ù}}1L۷oO0!#xw}L2cCPPPHHȪUBs%)"vܹi&bS^SD,"tyDgϞM@zjYYYzBmۖޭh '?=ZZjժi4rr]l_bERRRIIVFP(///Da07l PF Xcǎ?>00߿? `۶m4^O$䭷"U0 `𨨨/nذwc2w{"z}PLDwڵ.] :E]T*ɓ' Ƙ_8qD|||tt4ƸZj OJJJIȟ:djS\\18qbll,8 xӿkqhѢѣGqqq@V+V|駗.]y&#DG' VZNNyշzիkcۤIׯ߸q#((pN̔JeaaZt:>}ĉ;w޻w/ iݺZhÇ述`ӧO#BCCSRRO.$^nݺuN:;wֱc{ŒWPPPXFB_Mxe={xyyyyy7!$ &KHΝP(JɓIC`07NO>l_}_Ev`0fƍ,YhٳgoŋsssC/#F0 ${ȍ>{ԆҪU  abq=B>4Ldr__߸իW/\V^h4SPԬYğt%-[$iii?sϞ=B55kfmҤ 7DwۢEŋ5juJ LJ q=N:ݹsΝ;>>>?# ѣGJJݻwkժ5k,OΝ===bP(ԩBH t֍aLdO*v!ԫWǏ?|PP5k˫K.+""7""kرW6 SNܹ3B(..իׯVU*ULL\.o֬Yݺu m6R5bbFdVZY&uafY׫jQF|>VTǎ#>>>m۶%}!HTfM"y[no>V{Q>/ZoFzhN駟n޼d2 :o߾nٲEь;6**agv](jժZj ;;o߾|>iӦnӦ ۸u)ʙ3gY{n>}B^^^ڵNpf!Wlk˜9swNFLm6 d`8B(`aadZKW' X98D!!!!!. IDAT!@6~ԩPy0!!aȐ!PR?~@RnE(C>UQ-!#7o޼xnw:bZu:];u:RT"T>zB2x`qڵKJJ 7^Q)Wn!ߖ,Y2ydN P~;wf͚@3e +u`<"u@Tl6B!|-{S~Rӟn7 Vh4\ȍ7h@˜˗/WV<~xfΟ?OCBCC{aÆ g^^^rH$dM6zk޼9aӴiӨ/}#G3v؏??رF@HIJرc{[n!ئMm۞9sk~'Ѹq2]vcƌ!?[P^B40..!o۷oo׮oA#۶mۦM(W$JlgΜ?ݻ-Z4j(q`` BhժUj(o߾ݻ7!!9sG;|'sҥ'С۷o^F'?~\.r] ͛oܸ) ?bŊܳ|>… &ז#F̚5|U&S:4s?!f͚ѣGשSgΜ9d,0??[n^R w܉ZdIvvvdd$N:ǏWcaԩJNN޽{7Bt֪U !$J DbꫯvehT7o{FF% {=N{OIr;0 ؾhT*JBI8D6m^۶m۶mےc^e @(JB^…zH۷ݻBm))).P6绿kԨQfMڵkù|Dt-[򙕕uΝ0ϧˏH$|>?>>P5j+Wԥ,7aq@!BF֭K^Rfqǹ?nDEE͘13.BpP xϏ^p8B!9>uBn:DhJ$ܺukb*1vZB͛7E,Bn"!䫫f͚V|'=IYPRfʔ) 6\jQVZu!33w%;wh4VZ~}vBǏ˓d.K)|_~b´# xbׯ%$$FDܹ_жjŋ۶m3SL1 իWWTFqܸqV0`@ttM7n~V.oڴIխ[tMG*4_~رt\NZt2Nqq1BH"lݺCOfOBЋ _޻woa vi͚5jzڴi.K,VZ믿x<9k,P||ѣZhA&̘1v®])B Ivd2Zp P'MpB *XZ|;w7nL&{c_\\ܱcGrmV:v옏OaaL&{RrgΜ4i҄ WXg5jƍoܸ{dٳg0 77Iwu24oޜ|߸qcu'SO x0kcJlܸ1== nݚF)u+Jҟiݻ!&&毿Bba>ٳQQQlܹߺu !믿rǃ]Ο?ۗ(OP@U ,d.]z̙]vA\_| رctc;NIFӓEL&T K|LIj PJE - eC0 pprv;Q^OFYvٳgij@.}Ads B "hBTB-B "@}r@ t eH$ ^7ʩ'n[޽{tS1&<^mBPA͚5P1B8r`HDw?afR+X,UܷH$2d4*@>#e6B(zA>kv<kxNGqqq:D9@K,L!r… BP XVJ]_*v//{g'g_K.}Æ 8pkaVbtR@T.\0WgǏܹs6m|M B+WZܹsʔ)UjvvW_}UvtӓnJ# 2?&?ssskԨ|rtѣGB$e@hVf|X,rH$Bx<>O1 {H$\3r 5åƊbTrHPг2 fddi7* Gуz/!6}qpf,7 ċ ߶n׷|T*X^O{u:=>m6R,PTTDWS3ZM"4^:Nӹ9zlVTl6S\3r4 jijkM&F&CAz- w:JR.hʎFnq;bF2IeGˋ[3KѦ.6}fz=7hЀQu B=w1nڴiӸ6Rt˲>,n:"##B,~zqbb"˲bIرcceM&``Y611cni&ɴdɒXV{֭mۺK$۷Lŋt˗/>ɓ=CbY%^-Z4qD۷5kb| >sիWYpx޼yI̘1cʲ,s;u9s`ϝ;Wzu ޺u cM|h'1a[X={,oVIMMϘ1o!~YMKK#ݓ3gd:p@llm2>cw^zuy/]d2F9ol߾L&;rxʕ,33eYh_.lڴ|߰,K}޼ySL߸qaÆ!w'y#v-LF%cǎAQǏvЁ)/^tt4  !!]~}rOH$*C#+B4}h`0߿?B| $8@0_|E{=˹.Z믿&#G$}D/Z[ny !Lyxehӣu:= P:BڽKaXGX̜9o!L4( ;v]Zܜb|mrqM!ah4t:-/rHKK{ȮܦGܿ{lC*,,fl]<==}||""" ωdj޼K$ J=QVzk׮ ,@Qɓ'CBݺu#zk(RK{d{1cF˖-nY@Ǔ;ϙ3zwΝK{"!/^Nv#_><͛7?{b`&&&%~|#cu7n4m!ԧOm۶m۶QDDDՋDsoAZ6wpJKvv61믹@x%"##1Æ #[oI$BT!$U*իW<P7~IĆR( ޽{O1:?%)) ֮]t Br|IXr%9'z{{P TY70aӧl6X,}vtt4B(**jժUN[.cZԍ5*22rnݺ?~ZvժUYYY-[ܽ{X,6 ,(,,tIYYYXTΞ=N:ULPlْ-!̛7o޼y<poȑI׿ԵkI&!ƎU#FP#F@,t:wލ"կ_?պm67 \!֭7n\TTB?fv0@@.]̙3v*ƃ B 1B@@Hb)Iv}ݺu* 2i& Hrt BPT,V򡔅!t5ȋcn?BHfkٲb X*^L :cǎW^x!p8J#*p=a```JJ dP6BVc^r T:Hٓm۶kܹs?MڵkkԨWe/w1z@%DR1 C߿ODxxx/>xnwP( EY,f͚}gܭ[֨Q#77W(2 h"!Zd2ǓH$ϟ_| '{Fɓ|@ =._jKȚ5k*NF^zܹuS\⶟6o|i).]zʕ_!t…k׮W\iժիk]v]t%aÆ%''_tܹsݻuǎݺu;wܙ3g.]bf6߽{wAMڴ}KkSŷ"LLLl߾N;:> &P[n};ox9s&0bdS|>ѢEӦMCVA6K֭WNBD"]7oieeey{{/]T,߃^d Ì3H$?~ɓlrmT*UAA˅VuС_|sf 6+ wU>}222ȱ˜HR0j$rq&3eٳIttIB_}7aQFϚ5%pĉ.puօ޼y*PxwAc6JSʗ_~Oqnٸvڹs'$c"51ƿ۹s^c[֒ j5.IGbzKI|8'>>i4 B(((^z$ål6h۷oOR(EF2]j޹s|}}j5BebZ]䖄Gnl6O>"nh4>LA1vE*AAA!Pxҩh|>ݻ`Ϟ==zٳݻi}:00P6nܘ Zmzz:6w[2񏆋__cǎCȑ#k׮={2 !!!BXFxxxEPd2@y[FFF%@K7]jU3ԩS/ !Wbɉ~ 0L/UP(Mm*qD"LtL#|1rxx u!jUT<t?vc}h32!!!!!@% !TfA>UB  xl}:NLt:!YFAJ`` dBK 吷!;Vh4?B>f B B 0mڴ;z>eYELL{IIIm۶,kU*˲wo޼>,1駟X߿]v. رc+V=cɲ1\ZRRrܹ}LiӦ7d2ԯ_žzG5LSN?~`8y1c^16m{ ,?eׯc'Nwa/w-Z}6x-=ze{aի1GaY֬Y1>pD"qE~zqRR˲j=qbb"$4L,&&&b{it:˲ׯ_Oʮ022^"8pgZ,9rczj$1w˲G/Zh۷oh>88w'N_~ec,XĴi0W^eYҥK̙1pB͚5]6lx ԩS͛1NIIaY6##{?#ɓ,fffbGb c }vhO{=erJɴu;w&iƍ]twÇcccIv:K..<oϞ=)E̲16lpOb|e<1^|1c0w w;y$xҥcǎ,{ig}1u˲gΜ9}tRsc_|cLBlB*jjjHHƸujcL2oɍܹs䘼1ƤVc% 6bbbc̄effwJ T,@ ;*JD"JF!g2f3}?:Βl۵Z-1S*2L$cP%%%%"4yk+U,{a|}} i]b_;$_Ԭh4kzn'Gp&A J%w\,JFcqq\./((p:ժUX,* !Aۂ!XL̂'J*')7z'jÃiV5㖝l6L0&O&egz^Wehz}pp0͕d>>>fh[,P1͕H$5k\Z=ڤmBLJ9NB.$ڻ(gvub[E(!Xi,hU` QR5ECјECkTmG>11! x!6TB M^[;"e}|f\3 #m6'c+in8EQ_A]E/]СC_|9g׮]LG}oܻwڵkVd.| l߾].#gnݺw1eC{ɉ˗z~粲ؕ߿<=кu6o, ]Z^w,%ɦ`(VuѨiUR0nѨZ-VuM\NX,UUG|)d#inb])~~ڹs9g^kk'|?;ɓEEE2.`朦@ z{{W\믿ƾa޽g.WZ%OI?nGz`0x L\xQӴkz$2h4j5 )cr2S/^WӴu)'r͚5>09stww֎gφaMΝkinn~͝-((8x5k,Y65{lchvΜ9SWW hlE0ŋ;w4 j6o޼{N;4/~7KJJ";;{ΝwuWKK{bŊ5n^RWWO97nlmm1\t9uwtM#ϟ?I~?SU3f|K,9py΢Lz ߱)]mYv<LH$288an7^uv&#gb[bŁ憆W^y #Ѽ^oWW:mjZ/!֣GVVVksbZK.}wcԩS;vpB\Pr nTUΦRnnn ϡ׻zjsS AΞ=ohv1rrݚ> L#GC R!p80 UUm6f\.˕={9k$m۶P(dZEN4ł-''7;zƿ·v^ꦦ&'&sQ)H[nʢZv}ر;3R`m޼:8>:~?'c0IDÔ B`2 #RLq(AAAA8)1V\)={PUBtvv\0yޞxbk|<Ux2b̛7Oa۽^VE=A&@ o8_roFqk;v옜hmmqfᎎ=---ro5[i} !t]?_M1ANo1#G}r?|UUصBʊ!q>F˖-;m˗/B=쳛6m/--5k!srr6n /444PO=al6[yyyAAlnٲ|8@O g͚Ȑeee555O<FB4dfz<#'䜪۷]J+|_}BQm۶QdܲeϧiZqqyxYNSNȓ1B7lg.)w`jj*EF[[oBB*!(OuWU !dѣG 2HD B0ܴi(j.jv]=n`\lhFl9sÇu]7SP0A, cȽi!Ė-[4MD"-2_4MӴ/$v=9&{ŗF2fΜ9hѢ>(vH&}!EQVZ6b,s蕚={6bEѼrssO8qnذ!l6U|Zf~~3gߴ>3A>f0p8̈́6-;ڮu[[o}'HdĽ[ BKO躞2[3N<KZv!0Iر:`u}…!A8mEEQv0&V$X,mᚦn.D džF!!!!!!!!!!!!!!!!!!!!!!!7aDQ0Z]u] Lv)))nbs_멩!b\.,)   pprQU5;;:[R}K-&(Bp8k P%555Rg 6V?NR]v9P(D-&Cjdnq4H*P(77:\e;[q4Mo LIIp#BJ0DсEQ⛅hpn* !UU: PU5'A@y޸gր ,KO ! V5 R4A`0(u=A_ӴP( n B= tܦ(ŋ}>_"Bx<RA,E koOTe̙q?d7O3pqR^Gar:=$y  !RSSIAaRs82 w$LAyi Wؐ]/xRRRt]ϫ3SrB{XmN,4S0==ۖIUU-{J/(;lqX]]IENDB`PKoxZZPK DOEBPS/pds_policy.htm 0 Using Request Context Parameters in SLAs

17 Using Request Context Parameters in SLAs

For most installations of Oracle Communications Services Gatekeeper, you can use generic data specified in service provider and application-level SLAs to choose the correct behavior of a plug-in.

Using RequestContext Parameters Defined in Service Level Agreements

It is possible to use generic data specified in service provider and application-level SLAs in a plug-in. This is useful when the data used by a plug-in should be different depending on which service provider or application that the request originates. For example, this can be used for information about parameters that corresponds to a certain group of applications. For instance a certain group might get the priority on their SMS set to LOW because they pay less. The priority might be a parameter that is sent down to the network which handles this.

In an SLA, a <contextAttribute> is defined as a name/value pair, where the name is defined in the <attributeName> and the value is specified in <attributeValue>.

A plug-in can retrieve the value specified in <attributeValue> using the name specified in <attributeName>. The value is retrieved using the RequestContext for the request:

String attributeValue = (String)RequestContextManager.getCurrent().get("<attributeName>");

For example, the value associated with the contextAttribute with the attributeName com.bea.wlcp.wlng.plugin.sms.testName1 is retrieved using:

String value1 = (String)RequestContextManager.getCurrent().get("com.bea.wlcp.wlng.plugin.sms.testName1");
PK!H PK DOEBPS/pds_intro.htm1 Overview of the Platform Development Studio

1 Overview of the Platform Development Studio

Oracle Communications Services Gatekeeper provides substantial functionality right out of the box. But because all networks are different, matching the particular requirements and capabilities of some networks sometimes means that Oracle Communications Services Gatekeeper must be extended or that certain aspects of it must be closely integrated with existing network functionality.The Platform Development Studio is designed to ease this process by providing tools for creating new communication services, for customizing existing communication services, and for integrating a Services Gatekeeper installation with external systems.

Creating New Communication Services

Networks change. Existing functionality is parsed in new ways to support new features. New nodes with new or modified abilities are added. Because of Oracle Communications Services Gatekeeper's highly modular design, exposing these new features to partners is a straightforward proposition. The extension portion of the Platform Development Studio provides an environment in which much of the mechanics of creating extensions is taken care of, allowing extension developers to focus on only those parts of the system that correspond directly to their specific needs. This aspect consists of three main parts

The Eclipse Wizard

At the core of the extension portion of the Platform Development Studio is an Eclipse plug-in that creates projects based on the responses that the developer makes to an Eclipse Wizard. The developer supplies some basic naming information and the location of a Web Services Description Language (WSDL) for each application facing interface that the Communication Service is meant to support, and the Wizard generates either a complete Communication Service project, or a network plug-in only project. For more information on setting up the Eclipse Plug-in and running the Wizard, see "Using the Eclipse Wizard" To see an example of a generated project, see "Description of a Generated Project" To get an understanding of the Oracle Communications Services Gatekeeper features with which your Communication Service will interact, see "Using Request Context Parameters in SLAs" "Container Services""Aspects, Annotations, EDRs, Alarms, and CDRs" and "Making Communication Services Manageable"

Example Communication Service

To give you a concrete sense of the task of generating a new Communication Service, the Platform Development Studio contains an entire example Communication Service, which is buildable and runnable. Based on a very simple Web Service interface and an equally simple model of an underlying network protocol, this Communication Service demonstrates the entire range of tasks that you will encounter in creating your own Communication Service. For more information, see "Communication Service Example"

As an example a network protocol plug-in that uses the SIP Servlet container is provided in "Service Enabler Example with SIP plug-in"

The Platform Test Environment

To simplify the testing of your Communication Service, the Platform Development Studio includes the Platform Test Environment, which provides an extensible suite of tools for testing Communication Services and the Unit Test Framework, which supplies an abstract base class, WlngBaseTestCase, which includes mechanisms for connecting to the Platform Test Environment. As well, there is a complete set of sample tools created to interact with the example Communication Service. For more information, see Platform Test Environment, a separate document in this set.

Integration and Customization

New Communication Services are not the only aspect of Oracle Communications Services Gatekeeper that can handled using the Platform Development Studio. To help integrate Oracle Communications Services Gatekeeper into the installation environment, three other aspects of customization are supported:

Service Interceptors

Service interceptors provide Oracle Communications Services Gatekeeper with a mechanism for intercepting and manipulating a request as it flows through any arbitrary Communication Service. They offer an easy way to modify the request flow, simplify routing mechanisms for plug-ins, and centralize policy and SLA enforcement. Out of the box, Oracle Communications Services Gatekeeper uses these modules as part of its internal functioning, but operators can also choose to create new interceptors, or to rearrange the order in which the interceptors are used, in order to customize their functionality. "Service Interceptors" describes the request flow through interceptors, lists the standard interceptors and explains how to rearrange interceptors or to create new custom versions.

Subscriber-centric Policy

Out of the box the Oracle Communications Services Gatekeeper administration model allows operators to manage application service provider access to the network at increasingly granular levels of control. Using the Platform Development Studio, operators can extend that model to encompass their subscribers, giving the operator the ability to offer those subscribers a highly personalized experience while protecting their privacy and keeping their subscriber data safe within the operator's domain.

Operators create a Subscriber SLA, based on a provided schema, which describes sets of service classes. The service classes define access relationships with the services of particular Service Provider and Application Groups, along with default rates and quotas. Profile providers created by the operator or integrator using the provided Profile Provider SPI then associate those service classes with subscriber URIs, forming subscriber contracts. These contracts are used to evaluate requests and to generate subscriber budgets, which are used by the normal request traffic policy evaluation flow. A single subscriber can be covered by multiple subscriber contracts, based on that individual subscriber's desires. "Subscriber-centric Policy" covers the process for setting this up.

Integration with External Systems

Finally, the Platform Development Studio provides mechanisms to support the integration of Oracle Communications Services Gatekeeper with external network systems, including:

Additional integration points, not covered in the PDS, are provided by:

Tips for Creating Extensions

This section contains tips to consider when you are creating extensions to Oracle Communications Services Gatekeeper:

  • When creating the management interface, consider if the management operations and attributes should be cluster-wide or local.

  • Make sure to follow the plug-in naming convention: Plugin_web service interface part_network protocol.

  • Make sure to implement customMatch of the PluginInstance (or ManagedPluginInstance) to be sure that requests end up in the correct plug-in. This is important when there are multiple plug-ins for the same communication service.

  • Create exception types that are very specific to various error scenarios. This will allow fine grain control of the alarms that are generated.

  • Have a clean separation between the north and the south side of the plug-in.

  • Make sure to return all north interfaces (callback included) and souths interfaces when implementing the getNorthInterfaces() and getSouthInterfaces() of PluginInstance.

  • Make sure to implement the resolveAppInstanceGroupdId() method for each PluginSouth instance (if applicable).

  • Annotate each parameter in the south object methods that you need to have when aspect calls back the resolveAppInstanceGroupId() or the prepareRequestContext() methods.

  • Consider what additional EDR fields you need to add. Annotate all the methods you want to be woven using the @Edr annotation.

  • Annotate the specific arguments you want to see in the EDR for each annotated methods. Use either @ContextKey or @ContextTranslate depending on the kind of argument.

  • Add all the EDRs you are triggering to the EDR descriptor.

PKGY11PK DOEBPS/pds_customavp.htmEh Customizing Diameter AVPs

14 Customizing Diameter AVPs

This section describes how to customize Diameter AVPs (Attribute-Value Pairs) in Oracle Communications Services Gatekeeper (Services Gatekeeper) for:

  • Parlay X 3.0 Payment Diameter communication service

  • Credit Control Interceptor

  • CDR Diameter listener

Introduction

You can customize the Diameter AVPs that Services Gatekeeper sends to the network. You can add or modify the AVPs.

A set of standard AVPs are sent using Diameter, and you can add additional AVPs and modify them using configuration. Applications can also provide custom AVPs as tunnelled parameters, and they can receive returned AVPs using tunneled parameters.

Configuring Customized AVPs for Parlay X 3.0 Payment/Diameter

The Parlay X 3.0 Payment/Diameter communication service translates Parlay X requests or requests over the RESTful interfaces to Diameter calls. You can add and modify the Diameter AVPs that are sent in the Diameter request using a custom global SLA or a custom service provider SLA. See Managing Accounts and SLAs Guide, another document in this set. Use the SLA type payment_diameter_avp when loading the SLA.

The custom SLA has the following structure:

<tns:paymentConfig>

<tns:avpAttributeDefinitions>

<avp:avpAttribute></avp:avpAttribute>

...

</tns:avpAttributeDefinitions>

<tns:avpTemplate>

<avp:avpValue/>

...

</tns:avpTemplate>

</tns:paymentConfig>

The paymentConfig element contains one instance of avpAttributeDefinitions and a sequence of avtTemplate. It has no attributes.

The avpAttribute element specifies the AVP attribute to use and defines its characteristics. One or more avpAttribute elements can be defined under avpAttributeDefinitions. The avpAttribute element has the following attributes:

  • code Required. Defines the AVP attribute code.

  • vendorId Required. Defines the Vendor ID for the AVP.

  • name Required. Symbolic name to use when referring to the AVP attribute definition in the avpValue element.

  • type Required. Type is String. Defines the data type of the AVP. Possible values are:

    • INTEGER32

    • INTEGER64

    • FLOAT32

    • FLOAT64

    • STRING

    • ADDRESS

    • GROUPED

    • BYTES

    If the type is GROUPED, the AVP attribute is a grouped attribute and a sequence of avpAttribute elements can be added as siblings to a avpAttribute.

  • flag default is 64. Use the following values:

    • FLAG_NONE = 0x0 (0)

    • FLAG_VENDOR_SPECIFIC = 0x80 (128)

    • FLAG_MANDATORY =0x40 (64)

    • FLAG_END_TO_END_ENCRYPTION = 0x20 (32)

    You can combine these flags by adding their values together.

The value parts of the AVPs are defined as sequence of avpValue elements. The avpValue is a sibling to the avpTemplate element.

The avpTemplate element defines the optional paramName attribute. If a ParamName is not specified, the template that has the same name as the calling operation is used.

The avpValue element defines the value of an AVP. It has two attributes:

  • avpName Required. Type is String. Points to the avpAttribute the value corresponds to.

  • defaultValue Optional. Type is String. Defines the value of the AVP. When it is a grouped AVP (type is set to GROUPED) the value must be null, otherwise it must have a value.

Example 14-1 illustrates a custom AVP definition for Payment. It defines three AVP attributes and shows how to set the values for these.

Example 14-1 Custom AVP definition for Payment

<?xml version="1.0" encoding="UTF-8"?>
<tns:paymentConfig xmlns:avp="http://ocsg.oracle/diameterAvp/xml" xmlns:tns="http://ocsg.oracle/plugin/payment/diameter/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <tns:avpAttributeDefinitions>
    <avp:avpAttribute code="3001" vendorId="111" name="test-avp-1" type="String" flag="0"></avp:avpAttribute>
    <avp:avpAttribute code="3002" vendorId="111" name="test-avp-2" type="Grouped" flag="0">
            <avp:avpAttribute code="3003" vendorId="111" name="test-avp-3" type="Integer32" flag="0"></avp:avpAttribute>
    </avp:avpAttribute>
  </tns:avpAttributeDefinitions>
  
  <!-- default template -->
  <tns:avpTemplate>
    <avp:avpValue avpName="test-avp-1" defaultValue="hello world."/>
    <avp:avpValue avpName="test-avp-2">
      <avp:avpValue avpName="test-avp-3" defaultValue="2"/>    
    </avp:avpValue>
  </tns:avpTemplate>
  
  <!-- custom  template -->
  <tns:avpTemplate ParameterName="template1">
    <avp:avpValue avpName="test-avp-1" defaultValue="hello template 1"/>
    <avp:avpValue avpName="test-avp-2">
      <avp:avpValue avpName="test-avp-3" defaultValue="20"/>    
    </avp:avpValue>
  </tns:avpTemplate>
  
</tns:paymentConfig>

Configuring Customized AVPs for Credit Control Interceptor

The Credit Control Interceptor sends Diameter requests based on the content of a request from an application. For each request, you can specify one or more AVPs to send in the request.

You specify the AVPs in an custom global SLA or custom service provider SLA. See Accounts and SLAs Guide, another document in this set. Use the SLA type credit_control when loading the SLA. For information about Credit Control Interceptor and SLAs, see System Administrator's Guide, another document in this set.

The AVPs are defined in the avpAttributeDefinitions elements in the credit control SLA. Define this as a sibling to the CCInterceptions element.

The SLA has the following structure:

<CCInterceptions>

<avpAttributeDefinitions>

<avpAttribute></avp:avpAttribute>

...

</avpAttributeDefinitions>

<CCInterception>

<SubscriptionId>...</SubscriptionId>

<OCSGChargeDescription>...</OCSGChargeDescription>

<ServiceContextId>...</ServiceContextId>

<Amount>...</Amount>

<Currency>...</Currency>

<ServiceIdentifier>...</ServiceIdentifier>

<CallingPartyAddress>...</CallingPartyAddress>

<CalledPartyAddress>...</CalledPartyAddress>

<AsynchronousCommit></AsynchronousCommit>

<customizedAvpValues>...</customizedAvpValues>

</CCInterception>

<CCInterception>

...

</CCInterception>

</CCInterceptions>

The CCInterceptions element contains a sequence of CCInterception and avpAttributeDefinitions elements. It has no attributes.

The CCInterception element defines the data to set in an AVP and it specifies which method and interface the request that the AVPs are valid for.

It has the following attributes:

  • interfaceName Required. Type is String. The Java representation of the Parlay X interface name. For example, com.bea.wlcp.wlng.px21.plugin.SendSmsPlugin.

  • methodName Required. Type is String. The method name. For example, sendSms.

  • pluginId Optional. Type is String. The Id of the plug-in instance the AVP is defined for and serves as a default definition. If it is not present, it is valid for all plug-in instances. If it is present, it overrides the default AVP definition.

The avpAttribute element is identical to the avpAttribute element for the Payment plug-in, see "Configuring Customized AVPs for Parlay X 3.0 Payment/Diameter".

Configuring Customized AVPs for CDR Diameter Listener

The CDR Diameter listener converts CDRs emitted by Services Gatekeeper to Diameter Requests.

The mapping from a CDR to Diameter AVPs is defined in the XML file mapping.xml. The file is located in the EAR files cdr_to_diameter-single.ear and cdr_to_diameter.ear, in the APP-INF\classes directory.

You can define two types of AVPs; dynamic and static.

Dynamic AVPs take fields in the CDR and defines which AVP it is mapped to. The Static AVPs define static values.

The XML file has the following structure:

<mappings>

<mapping/>

...

<mapping/>

</mappings>

The mappings element contains a sequence of mapping. It has no attributes

The mapping element has the following attributes:

  • edr Optional. Type is String. Defines the EDR ID to convert.

  • avp Required. Type is String. Defines the AVP attribute name part, for example Called-Party-Address.

  • avpType Required. Type is String. Defines the data type of the AVP. Possible values are:

    • INTEGER32

    • INTEGER64

    • FLOAT32

    • FLOAT64

    • STRING

    • ADDRESS

    • GROUPED

    • BYTES

  • vendorId Optional. Type is int. Defines the vendor-ID included in the Diameter request. For example, Oracle's vendor-ID is 111.

  • mandatory Optional. Type is Boolean. Defines if the AVP is mandatory or not.

  • vendorSpecific Optional. Type is Boolean. Specifies if the AVP is specific for the vendor or if it is a standard AVP.

  • endToEndEncryption Optional.Type is Boolean. Specifies if end-to-end encryption shall be used for the request.

  • avpCode Required. Type is int. Specifies the numeric value for the AVP attribute part.

  • mapper Optional. Type is String. Specifies the class that performs the mapping. Use the fully qualified class name, including he package name.

  • avpValue Optional. Type is String. Specifies the value-part of the AVP.

The following rules apply:

  • If the specified edr attribute exists, the value in the EDR is forwarded in the Diameter ACR (account request).

  • f the value in the EDR is an array, all entries are sent as comma-separated values.

  • If there is no EDR attribute that matches edr, the value set in avpValue is used.

To define a dynamic EDR to AVP mapping for the time stamp, use the following XML:

<mapping edr="Timestamp" avp="Event-Timestamp" mandatory="true" avpCode="55" avpType="INTEGER32" mapper="com.bea.wlcp.wlng.cdrdiameter.xmlmapper.avpmapper.TimeStampAVPMapper"/>

To define a static AVP, use the following XML:

<mapping edr="CustomizedAVP1" avp="Ocsg-Customized-1" mandatory="false" avpCode="3001" vendorId="111" avpType="STRING" avpValue="test"/>

How Applications Can Customize AVPs Dynamically

Applications can define customized AVPs to be sent in the Diameter requests. Applications use tunneled parameters (x parameters) that define the AVPs to be added. The AVPs need to be configured in the SLAs using the same key name as used in the tunneled parameter.

Set the value for the key in the tunneled parameter to the value of the paramName attribute in the SLA to use a configured AVP.

When you use the SOAP interfaces, the values should be encoded in the SOAP header as follows:

<soapenv:Header>

...

<xparams>

<param key="template1" value="10" />

...

</xparams>

</soapenv:Header>

When you use the Restful interfaces, the values should be encoded in the HTTP header as follows:

X-Plugin-Param-Keys:template1,template2

X-Plugin-Param-Values:10,10

The key and the value for the tunnelled parameters are ordered so the first occurrence in X-Plugin-Param-Keys is for the first occurrence of X-Plugin-Param-Values, and so on.

AVPs are also forwarded in the responses to requests from the SOAP and RESTful interfaces for requests to the Payment communication service.

When you use the SOAP interfaces, the AVPs are returned in the SOAP header in a tunneled parameter with the attribute key set to AVP_LIST and the attribute value set to an XML encoded string representing the AVP. An example is:

<param key="AVP_LIST" value="AVP_list_in_XML" />

When you use the RESTful interfaces, the AVPs are returned in the HTTP response header in an tunneled parameter with the attribute X-Plugin-Param-Keys set to AVP_LIST and the attribute X-Plugin-Param-Values set to an XML encoded string representing the AVP. An example is:

X-Plugin-Param-Keys:AVP_LIST

X-Plugin-Param-Values:AVP_list_in_XML

Below is an example AVP list expressed in XML:

<Avp-List>

<Session-Id>;1280993750;3</Session-Id>

<Origin-Host>ocag.oracle.com</Origin-Host>

<Origin-Realm>oracle.com</Origin-Realm>

<Result-Code>2001</Result-Code>

<CC-Request-Type>4</CC-Request-Type>

<CC-Request-Number>0</CC-Request-Number>

</Avp-List>

When the XML is returned in a SOAP header, values are escaped. For example the < character is converted to &lt;.

When the XML is returned in the HTTP header, all <CR> (carriage return) and <LF> (line feed) characters are removed.

PKHEEPK D OEBPS/toc.ncxl Oracle® Communications Services Gatekeeper Platform Development Studio Developer's Guide, Release 5.1 Cover Title and Copyright Information Contents Preface 1 Overview of the Platform Development Studio 2 Understanding Communication Services 3 Using the Eclipse Wizard 4 Service Enabler Example with SIP plug-in 5 Description of a Generated Project 6 Communication Service Example 7 Using the SMPP API 8 Using the UCP API 9 Container Services 10 Service Interceptors 11 Aspects, Annotations, EDRs, Alarms, and CDRs 12 Subscriber-centric Policy 13 Custom Service Level Agreements 14 Customizing Diameter AVPs 15 Creating an EDR Listener and Generating SNMP MIBs 16 Making Communication Services Manageable 17 Using Request Context Parameters in SLAs 18 Extending the ATE and the PTE Copyright PK qlPK DOEBPS/pds_edrlistener.htmEs Creating an EDR Listener and Generating SNMP MIBs

15 Creating an EDR Listener and Generating SNMP MIBs

This chapter describes how to create an external event data record (EDR) listener in Oracle Communications Services Gatekeeper (Services Gatekeeper).

Overview of External EDR listeners

External EDR listeners are Java Message Service (JMS) topic subscribers.

The diagram below illustrates three different ways of listening for EDRs as a JMS listener.

Figure 15-1 Flow for external EDR, alarm, and CDR listeners

Description of Figure 15-1 follows

EDRs are published externally using a JMS topic. This makes it possible to implement language-independent listeners anywhere on the network in a standard way. It is possible to implement an EDR listener in several ways:

  • Alternative 1: Using a pure JMS listener. Implement the javax.jms.MessageListener interface. It is up to the implementation class to implement any filtering mechanism needed.

  • Alternative 2: Using a subclass of JMSListener with no filter specified. In that case, the JMSListener class will use a tag, if available in the EDR, to filter the EDR into a specific category: EDR, alarm or CDR.

  • Alternative 3: Using a subclass of JMSListener with a specified filter. This filter is used to perform the filtering. If a default filter is used to perform the same filtering as Oracle Communications Services Gatekeeper, all classes used in the xml configuration files must be present in the current class loader. Otherwise, some EDRs will not be correctly filtered.

Example using a pure JMS listener

Example 15-1 Using a pure JMS listener

public class ClientJMSListener implements MessageListener {
  public void onMessage(Message msg) {
    // Extract the EdrData object or array
    if(o instanceof EdrData[]) {
      for(EdrData edr : (EdrData[])o) {
        //do something with each EDR
      }
    } 
  }
}

Example using JMSListener utility with no filter

Example 15-2 Using a subclass of JMSListener with no filter specified

public class SampleEdrJMSListener extends JMSListener {
  public SampleEdrJMSListener(String url) throws Exception {
    // Register in the JMS topic. No filter is specified so 
    // the "tag" filtering mechanism will be used.
    register(url);
  }
  @Override
  public void onEdr(EdrData edr, ConfigDescriptor descriptor) {
    // The "tag" mechanism will filter the stream of EDRs according
    // to the internal filtering. To know which type of EDR is 
    // actually provided in this method, we have to determine the 
    // instance of the ConfigDescriptor as follow:
    if(descriptor instanceof EdrConfigDescriptor) {
      // do something with this EDR
    } else if(descriptor instanceof AlarmConfigDescriptor) {
      // do something with this alarm
    } else if(descriptor instanceof CdrConfigDescriptor) {
      // do something with this CDR
    }
  }
}

Using JMSListener utility with a filter

Example 15-3 Using a subclass of JMSListener with a specified filter

public class SampleEdrJMSListener extends JMSListener {

  public SampleEdrJMSListener(String url) throws Exception {
    // Register in the JMS topic. Use the default alarm filter. 
    // Note that in this case all classes needed by the alarm.xml file 
    // must be in the current class loader in order for the filtering 
    // to work correctly.
    register(url, EdrFilterFactory.createDefaultFilterForAlarm());
  }
  @Override
  public void onEdr(EdrData edr, ConfigDescriptor descriptor) {
    // Only AlarmConfigDescriptor should be received here. 
    // Just check before casting.
    if(descriptor instanceof AlarmConfigDescriptor) {
      ... do something with this alarm
    }
  }
}

Note:

When using the JMSListener class, make sure that any modification to an EDR, CDR. or alarms descriptor in Oracle Communications Services Gatekeeper is also updated in the edrjmslistener.jar file.


Description of EDR listener utility

The EDR listener utility contains a set of classes to use when creating an external JMS listener using the JMSListener.

The helper classes are found in:

Middleware_Home/ocsg_pds_5.1/lib/wlng/edrjmslistener.jar.

Class JMSListener

Table 15-1 JMSListener

MethodDescription

public void register(String url)

Registers the JMS listener to the EDR topic using no filter. The filtering will be done using the tagging mechanism. The parameter url specifies the URL of a Network Tier server.

public void register(String url, EdrFilter filter)

Registers the JMS listener to the EDR topic using the specified filter.

public void onEdr(EdrData edr, ConfigDescriptor descriptor)

Method that the subclass can override to get notified each time an EDR is received.

The descriptor will be a subclass of ConfigDescriptor that will identify the type of EDR: either EdrConfigDescriptor, AlarmConfigDescriptor or CdrConfigDescriptor.


Class EdrFilterFactory

Table 15-2 EdrFilterFactory

MethodDescription

public static EdrFilter createDefaultFilterForEdr()

Creates the default filter using in Oracle Communications Services Gatekeeper to filter the EDRs using the edr.xml file embedded in the edrjmslistener.jar file.

public static EdrFilter createDefaultFilterForAlarm()

Creates the default filter using in Oracle Communications Services Gatekeeper to filter the alarms using the alarm.xml file embedded in the edrjmslistener.jar file.

public static EdrFilter createDefaultFilterForCdr()

Creates the default filter using in Oracle Communications Services Gatekeeper to filter the CDRs using the cdr.xml file embedded in the edrjmslistener.jar file.


Class EdrData

This class contains all the values that an EDR (alarm and CDR) have.

Table 15-3 EdrData

MethodDescription

public String getValue(String key)

Gets the value associated with the specified key.

public List<String> getValues(String key)

Gets the values associated with the specified key.


Class ConfigDescriptor

This class is the parent class of EdrConfigDescriptor, AlarmConfigDescriptor and CdrConfigDescriptor.

Class EdrConfigDescriptor

This class contains the data that is specified in the descriptors in the edr.xml configuration file: the identifier and the description.

Table 15-4 EdrConfigDescriptor

MethodDescription

public long getIdentifier()

Returns the identifier of the EDR.

public String getDescription()

Returns the description of the EDR.


Class AlarmConfigDescriptor

This class contains the data that is specified in the descriptors in the alarm.xml configuration file: the identifier, the severity and the description.

Table 15-5 AlarmConfigDescriptor

MethodDescription

public long getIdentifier()

Returns the identifier of the alarm.

public String getSeverity()

Returns the severity of the alarm.

public String getDescription()

Returns the description of the alarm.


Class CdrConfigDescriptor

This class identifies a CDR. This descriptor does not contain any additional data.

Updating EDR configuration files

If you are using external EDR listeners, and the alarm, CDR, or EDR descriptors have been updated in Oracle Communications Services Gatekeeper, the corresponding files need to be updated in edrjmslistener.jar. Update the corresponding xml file with the updated entries in the edr directory in edrjmslistener.jar.

Generating SNMP MIBs

Alarms can be forwarded as SNMP traps, see Managing and Configuring the SNMP service in System Administrator's Guide.

The MIB file that corresponds to the alarms can be generated using the Apache Ant task mibgenerator defined in com.bea.wlcp.wlng.ant.MIBGeneratorTask.

The Ant task is packaged in Middleware_Home/ocsg_pds_5.1/wlng/lib/ant-mib-generator.jar.

There is an example build file that uses the an task in Middleware_Home/ocsg_pds_5.1/integration.

When the alarms descriptor is changed, a new MIB should be generated and distributed to the SNMP clients. Copy the contents of the alarm descriptor and paste it into an xml file. Use this xml file when generating the MIB file.

PKAƑEEPK DOEBPS/pds_subpolicy.htmEL Subscriber-centric Policy

12 Subscriber-centric Policy

Making subscriber personalization easy and offering superior subscriber data protection is key to growing and maintaining a loyal subscriber base. The Oracle Communications Services Gatekeeper (Services Gatekeeper) Platform Development Studio offers a straightforward way to extend the power of Services Gatekeeper's flexible policy-based control to the operator's subscriber base.

There is an example Profile Provider in Middleware_Home/ocsg_pds_5.1/example.

Service Classes and the Subscriber SLA

The first step in adding subscriber-centric policy to Services Gatekeeper is to create a Subscriber SLA. This is an XML file based on the sub_sla_file.xsd schema.

The schema file can be found in the wlng.jar file located in the Middleware_Home/ocsg_pds_5.1/lib/wlng directory.

The SLA is used to define classes of service in the context of existing Service Provider and Application Groups.(For more information on Service Provider and Application Groups, see “Managing Application Service Providers” in Concepts Guide, a separate document in this set. These service classes can then be associated with subscribers, based on their preferences and permissions, defining individualized relationships between subscribers and Service Provider and Application Group functionality.

The <reference> element

The <reference> element specifies the operator's already-established Application and Service Provider Groups that are to be associated with this service class. There are two reference types that define the groups: the ApplicationGroupReference and the ServiceProviderGroupReference. In addition there are two additional reference types, the ServiceReference and the MethodReference that indicate specific service interfaces and methods, respectively, covered by those groups. In the Example 12-1 snippet, the service class news_subscription is defined. Evaluation of matches in the class occurs using the following rules:

  • If no reference type is specified, everything of that type is a match

  • Two or more entries of the same reference type creates an OR relationship

  • The default relationship is AND

So, in the case of Example 12-1, the class covers any request that matches:

  • Any of the service interfaces of the silver_app_group

    (No ServiceReference type is specified, so everything is a match)

  • OR the gold_app_group

    (Two ApplicationGroupReference entries creates an OR)

    • AND the SendSMS service interface of the gold_app_group

      (The default relationship)

    • AND the content_sp_group

      (The default relationship)

    • AND the SendSMS service interface of the content_sp_group

      (The default relationship)

    • AND either the sendSms OR the getSmsDeliveryStatus methods

      (Two MethodReference entries creates an OR)

Example 12-1 The <reference> element

<ServiceClass name="news_subscription">
        <references>
            <ApplicationGroupReference id="silver_app_group"/> 
            <ApplicationGroupReference id="gold_app_group"> 
                <ServiceReference serviceInterface="com.bea.wlcp.wlng.px21.plugin.SendSmsPlugin"/>
            </ApplicationGroupReference>
            <ServiceProviderGroupReference id="content_sp_group">
                <ServiceReference serviceInterface="com.bea.wlcp.wlng.px21.plugin.SendSmsPlugin">
                    <MethodReference methodName="sendSms" />
                    <MethodReference methodName="getSmsDeliveryStatus" />
                </ServiceReference>
            </ServiceProviderGroupReference>
        </references>

Use of the empty <references/> element matches everything.

The <restriction> element

In addition to the <reference> element, service classes may have a <restriction> element. This element is used to attach default rates and quotas that are used to create budgets for the classes. These rates and quotas can be replaced in specific contracts.


Note:

The XSD requires you either to specify a rate/quota restriction or to use the <restrictAllType/> element.

Example 12-2 The <restriction> element

<restriction>
            <rate>
              <reqLimit>5</reqLimit>
              <timePeriod>1000</timePeriod>
            </rate>
            <quota>
              <qtaLimit>600</qtaLimit>
              <days>3</days>
              <limitExceedOK>true</limitExceedOK>
            </quota>
</restriction>

These elements function exactly as they do in the other SLAs in Oracle Communications Services Gatekeeper. For more information on these elements, see the Contract structure section of the “Defining Service Provider Group and Application Group SLAs” chapter of Managing Accounts and SLAs, a separate document in this set. If the <limitExceedOK> element is set to true, the request is allowed even when quota has been exceeded, but an alarm (Alarm id 200000) is fired.

There is also a <restrictAllType/> element. This element, as its name implies, denies access to all requests.

Managing the Subscriber SLA

There are three management methods in the Service Level Agreement MBean for managing a Subscriber SLA. They are covered in detail in the “Managing SLAs” chapter of Managing Accounts and SLAs, a separate document in this set. The methods allow you to load a Subscriber SLA as a string, to load a Subscriber SLA from a URL, and to retrieve a loaded Subscriber SLA.

The Profile Provider SPI and Subscriber Contracts

Once the Subscriber SLA is established, the various service classes it defines must be associated with individual subscribers. The combination of a subscriber (identified by URI) and a service class is called a subscriber contract. A subscriber (a URI) can have multiple subscriber contracts associated with it.

The subscriber contract object contains a URI designating the subscriber and the service class type with which it is associated. It also contains an expiration time, represented as a java.util.Date.

The subscriber contract constructor will throw an exception if the URI, service class type, and expiration time are not specified.

The subscriber contract may also replace the default rate and/or quota settings in the service class, or set this subscriber to RestrictAll, that is, to deny access for all requests.

The operator or integrator is responsible for creating the mechanism, a Profile Provider, that supplies these subscriber contracts.


Note:

All class files related to creating Profile Providers are in the com.bea.wlcp.wlng.spi.subscriberdata package, and can be found in the wlng.jar file in the Middleware_Home/ocsg_pds_5.1/lib/wlng directory. The JavaDoc for the files can be found in the Middleware_Home/ocsg_pds_5.1/doc/javadoc directory. An example implementation can be found in the Middleware_Home/ocsg_pds_5.1/example/profile_providers/src directory. This sample implementation assumes the use of a properties file to assign subscriber URIs to particular service classes. An example properties file, exampleSubscriberContractMappingFile.properties, can be found in the Middleware_Home/ocsg_pds_5.1/example/profile_providers/resource directory.

The Profile Provider must implement the Profile Provider SPI. The SPI defines three methods;

  • init: Oracle Communications Services Gatekeeper initializes the Profile Provider by passing in a list of the service classes that are defined in the Subscriber SLA and a list of any previously defined subscriber contracts. The Provider returns a list of updated subscriber contracts.

  • contractExpired: Oracle Communications Services Gatekeeper sends the Provider a list of service classes and a list of expired contracts. The Provider returns an updated list of contracts for those that have expired. The Provider can remove or add contracts to the returned list.

  • serviceClassesUpdated: Whenever the Subscriber SLA is updated, and the service classes are thus modified, Oracle Communications Services Gatekeeper sends the Provider a list of the updated service classes and a list of all current contracts. The Provider returns an updated list of contracts. The Provider can make any necessary updates to the subscriber contracts.

The Profile Provider implementation must have a public constructor with no parameters or a static method which returns ProfileProvider.

Deploying the Custom Profile Provider

Once the ProfileProviderImpl has been created, the JAR file containing it must be added to the app-inf/lib directory in the profile_providers.ear file, which can be found in the Middleware_Home/ocsg_5.1/applications directory. You must also modify the app-inf/classes/ProfileProviders.prop file, adding a line containing the package and implementation file name of each of your providers (multiple providers are possible). For example:

com.mycompany.mypackage.MyProfileProviderImpl

Once the EAR file is modified, it can be deployed in the normal manner. For more information on deploying EAR files in Oracle Communications Services Gatekeeper, see the “Deployment model for Communication Services and Container Services” chapter in the System Administrator's Guide, a separate document in this set.

Subscriber Policy Enforcement

Once the providers.ear is deployed, the singleton SubscriberProfileService initializes the Profile Provider(s) and receives the relevant subscriber contracts. It uses the Budget Service to create budgets for the contracts, based on the specified rates and quotas, and also creates and schedules a timer based on the expiration times in the contracts. Both the Subscriber SLA and the subscriber contracts are persisted using the Storage Service.


Note:

For more information on budgets in Oracle Communications Services Gatekeeper, see the “Managing and Configuring Budgets” chapter in the System Administrator's Guide, a separate document in this set.

When a request from an application arrives at Oracle Communications Services Gatekeeper, it passes through the Interceptor Stack for policy evaluation. The EnforceSubscriberBudget interceptor manages policy enforcement for subscriber contracts. The process within the interceptor has two phases:

Do Relevant Subscriber Contracts Exist

The first thing the interceptor must determine is whether one or more contracts exist that are relevant to the particular request that is being evaluated. The interceptor iterates through all the target URIs in the application request, and evaluates whether or not there are contracts in effect that it should enforce.

  • If there are no contracts at all associated with a particular URI, the request is simply passed on to the next interceptor in the sequence.

  • If there are contracts associated with a particular URI, a set of evaluations must be carried out. The figures below show the decision flow for the evaluations. All three sections must evaluate to true for there to be an enforceable contract.


    Note:

    The XML snippets correspond to the relevant sections of Example 12-1.

    • Is there an ApplicationGroupReference and is it relevant? See Figure 12-1.

Figure 12-1 Application Group Reference Evaluation

Description of Figure 12-1 follows


Note:

The evaluation for methodExists is covered in Figure 12-3.

  • Is there a ServiceProviderGroupReference and is it relevant? See Figure 12-2.

Figure 12-2 Service Provider Group Reference Evaluation

Description of Figure 12-2 follows


Note:

The evaluation for methodExists is covered in Figure 12-3.

  • Is there a Service Reference (and possibly a MethodReference) and are they relevant? See Figure 12-3.

Figure 12-3 Service and Method Reference Evaluation

Description of Figure 12-3 follows

Is There Adequate Budget for the Contracts?

Once the interceptor determines that an enforceable contract exists, it first determines whether the contract includes a <restriction> element set to <restrictAll/>. If so, the request is immediately denied, and processing on the request ceases.

If the <restriction> element is not set to <restrictAll/>, the decision flow is identical to the other budget evaluations that take place in Services Gatekeeper.

If there are no relevant contracts, or there are relevant contracts and there is adequate budget to cover them, budgets are adjusted as necessary and the request passes on to the next interceptor. If there are relevant contracts and there is not adequate budget to cover them, the request is denied.

PK0WGJLELPK DOEBPS/content.opf5 Oracle® Communications Services Gatekeeper Platform Development Studio Developer's Guide, Release 5.1 en-US E37535-01 Oracle Corporation Oracle Corporation Oracle® Communications Services Gatekeeper Platform Development Studio Developer's Guide, Release 5.1 2013-05-24T11:35:16Z Oracle® Communications Services Gatekeeper Platform Development Studio Developer's Guide, Release 5.1 PK6PK DOEBPS/pds_oam.htmX= Making Communication Services Manageable

16 Making Communication Services Manageable

Once you have created your extension Communication Service, any OAM functions that you have designed - read/write attributes and/or operations - must be exposed in a way that allows them to be accessed and manipulated, either through the Oracle Communications Services Gatekeeper Administration Console extension, or through other management tools. The following chapter provides a description of the mechanism that Oracle Communications Services Gatekeeper uses to accomplish this.

Overview

Oracle Communications Services Gatekeeper uses the Java Management Extensions (JMX) 1.2 standard, as it is implemented in JDK 1.6. The JMX model consists of three layers, Instrumentation, Agent, and Distributed Services. As a Communication Service developer, you work in the Instrumentation layer. You create managed beans (MBeans) that expose your Communication Service management functionality as a management interface. These MBeans are then registered with the Agent, the Runtime MBean Server in the WebLogic Server instance, which makes the functionality available to the Distributed Services layer, management tools like the Oracle Communications Services Gatekeeper Administration Console. Finally, because configuration information needs to be persisted, you store the values you set using Oracle Communications Services Gatekeeper's Configuration Store, which provides a write-through database cache. In addition to persisting the configuration information, the cache also provides cluster-wide access to the data, updating a cluster-wide store whenever there is a change in globally relevant configuration data.

For more information on the JMX model in general in relation to WebLogic Server, see Oracle Fusion Middleware Developing Manageable Applications With JMX for Oracle WebLogic Server at:

http://download.oracle.com/docs/cd/E15523_01/web.1111/e13729/toc.htm

Create Standard JMX MBeans

Creating standard MBeans is a three step process.

  1. Create an MBean Interface

  2. Implement the MBean

  3. Register the MBean with the Runtime MBean Server

Configuration settings should be persisted, see "Use the Configuration Store to Persist Values".

Create an MBean Interface

The first thing you need to do is to create an interface file that describes getter and setter methods for each class attribute that is to be exposed through JMX (getter only for read-only attributes; setter only for write-only) and a wrapper operation for each class method to be exposed. The attribute names should be the case-sensitive names that you wish to see displayed in the UI of the Console extension.

  • For each read-write attribute define a get and set method that follows this naming pattern: getattribute_name, setattribute_name where attribute_name is a case-sensitive name that you want to expose to JMX clients.

  • For each read-only attribute define only an is or a get method. For each write-only attribute, define only a set method.

  • The JavaDoc will be rendered in the console as a description of an attribute or operation. It will render exactly as in the JavaDoc. For example:

    /**
       * Connects to the simulator
       * @throws ManagementException An exception if the connection failed
       */
      public void connect() throws ManagementException;
    

    Will render as:

    Description of exampleopjavadoc.png follows

  • Any internal operation or attribute should be annotated with @Internal annotation. This attribute or method will not be shown in the console. Example:

    @Internal
    public String resetStatistics();
    
  • Indicate optional parameters for the operation by using the @OptionalParam annotation. In the JavaDoc for the operation, explicitly specify which parameters are optional. Example:

    /**
        * Gets the alarms matching the specified criteria from the database
        * @param Identifier EDR Identifier
        * @Param Source server name (optional)
        * @Param Severity 0 - Critical, 1- Major, 2 -Minor
        * @Param maxEntries max number of entries
        */
        AlarmData[] getAlarms(long identifier, 
                              @OptionalParam('source')String source,
                              int severity, 
                              int maxEntries) throws ManagementException;
    

The interface should be named ServiceNameMBean.java. The interface for the example Communication Service provided with the Platform Development Studio is named ExampleMBean.java.

Implement the MBean

Once you have defined the interface, it must be implemented.

You must name your class ServiceNameMBeanImpl.java, based on the interface name. The implementation must extend WLNGMBeanDelegate. This class takes care of setting up notifications and MBean descriptions and all MBean implementation classes must extend it. All MBean implementations must also be public, non-abstract classes and have at least one public constructor. The MBean implementation for the example Communication Service provided with the Platform Development Studio is named ExampleMBeanImpl.java.

  • The MBean implementation must be a public, non abstract class

  • The MBean must have at least one public constructor

  • The MBean must implement its corresponding MBean interface and extend WLNGMBeanDelegate

Register the MBean with the Runtime MBean Server

The MBean must be registered with the Runtime MBean Server in the local WebLogic Server instance. Oracle Communications Services Gatekeeper provides a proxy class for MBean registration:

com.bea.wlcp.wlng.api.management.MBeanManager

The MBean implementation is registered using an ObjectName, and a DisplayName:

registerMBean(Object mBeanImpl, ObjectName objectName, String displayName)

Construct the ObjectName using:

constructObjectName(String type, String instanceName, HashMap properties)

There should be no spaces in the InstanceName or Type. Object names are case-sensitive

If the MBean is a regular MBean, use the conventions as illustrated in Table 16-1.

Table 16-1 MBean ObjectName

The ObjectName convention for extensionsDescription

type

Fully qualified MBean Name.

MBeanObj.class.getName()

instanceName

Unique name that identifies the instance of the MBean. For example, it can be obtained from serviceContext.getName()

The unique name of the MBean. If this is a plug-in that potentially is used on the same server with multiple plug-in instances this should be unique per plug-in instance. It is recommended to use managedPlugin.getId().

properties

HashMap that contains objectName key and value pairs ObjectNameConstants class has set of constants that can be used as keys.

Null for non-hierarchical MBeans.


Example

com.bea.wlcp.wlng:AppName= wlng_nt_sms_px21#5.1,InstanceName= Plugin_px21_short_messaging_smpp, Type=com.bea.wlcp.wlng.plugin.sms.smpp.management.SmsMBean

If the MBean is an MBean that should be the child of a regular MBean, use the conventions as illustrated in Table 16-2.

Table 16-2 MBean ObjectName with hierarchy

The ObjectName convention for extensionsDescription

type

Fully qualified MBean Name of the parent MBean.

Parent MBeanObj.class.getName()

instanceName

Unique name that identifies the instance of the parent MBean.

properties.key=ObjectNameConstants.LEVEL1_INSTANCE_NAME

properties.value is a unique name that identifies the instance of the MBean

properties.key=ObjectNameConstants.LEVEL1_TYPE

Fully qualified MBean Name: MBeanObj.class.getName()

properties.key=ObjectNameConstants.LEVEL2_INSTANCE_NAME

properties.value is a unique name that identifies the instance of the MBean

properties.key=ObjectNameConstants.LEVEL2_TYPE

Fully qualified MBean Name: MBeanObj.class.getName()


Example

A child MBean, for example HeartBeatConfiguration, can register with the same Level1InstanceName for all instances of the Plug-in (since it is a child, its MBean name depends on the parent's instance:

com.bea.wlcp.wlng:AppName= wlng_nt_sms_px21#5.1,InstanceName= Plugin_px21_short_messaging_smpp, Type=com.bea.wlcp.wlng.plugin.sms.smpp.management.SmsMBean,Level1InstanceName=HeartBeatManager,Level1Type=com.bea.wlcp.wlng.heartbeat.management.HeartbeatMBean

com.bea.wlcp.wlng:AppName= wlng_nt_multimedia_messaging_px21#5.1,InstanceName Plugin_px21_multimedia_messaging_mm7, Type= com.bea.wlcp.wlng.plugin.multimediamessaging.mm7.management.MessagingManagementMBean,Level1InstanceName=HeartBeatManager,Level1Type=com.bea.wlcp.wlng.heartbeat.management.HeartbeatMBean

Use the Configuration Store to Persist Values

The Oracle Communications Services Gatekeeper Configuration Store API provides a cluster-aware write-through database cache. Parameters stored in the Configuration Store are both cached in memory and written to the database. The store works in two modes: Local and Global. Values stored in the Local store are of interest only to a single server instance, whereas values stored in the Global store are of interest to all servers cluster-wide. Updates to a value in the Global store update all cluster nodes. The example Communication Service provides a handler class, ConfigurationStoreHandler, that gives an example of both usages of the Configuration Store API.


Note:

The configuration store supports only Boolean, Integer, Long, and String values.

PKiıQ]=X=PK DOEBPS/dcommon/oracle-logo.jpgeSJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222'7" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE!KEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEzE7V%ȣOΏ9??:a"\fSrğjAsKJ:nOzO=}E1-I)3(QEQEQEQEQEQEQE֝Hza<["2"pO#f8M[RL(,?g93QSZ uy"lx4h`O!LŏʨXZvq& c՚]+: ǵ@+J]tQ]~[[eϸ (]6A&>ܫ~+כzmZ^(<57KsHf妬Ϧmnẁ&F!:-`b\/(tF*Bֳ ~V{WxxfCnMvF=;5_,6%S>}cQQjsOO5=)Ot [W9 /{^tyNg#ЄGsֿ1-4ooTZ?K Gc+oyڙoNuh^iSo5{\ܹ3Yos}$.nQ-~n,-zr~-|K4R"8a{]^;I<ȤL5"EԤP7_j>OoK;*U.at*K[fym3ii^#wcC'IIkIp$󿉵|CtĈpW¹l{9>⪦׺*ͯj.LfGߍԁw] |WW18>w.ӯ! VӃ :#1~ +މ=;5c__b@W@ +^]ևՃ7 n&g2I8Lw7uҭ$"&"b eZ":8)D'%{}5{; w]iu;_dLʳ4R-,2H6>½HLKܹR ~foZKZ࿷1[oZ7׫Z7R¢?«'y?A}C_iG5s_~^ J5?œ tp]X/c'r%eܺA|4ծ-Ե+ْe1M38Ǯ `|Kյ OVڅu;"d56, X5kYR<̭CiطXԮ];Oy)OcWj֩}=܅s۸QZ*<~%뺃ȶp f~Bðzb\ݳzW*y{=[ C/Ak oXCkt_s}{'y?AmCjޓ{ WRV7r. g~Q"7&͹+c<=,dJ1V߁=T)TR՜*N4 ^Bڥ%B+=@fE5ka}ędܤFH^i1k\Sgdk> ֤aOM\_\T)8靠㡮3ģR: jj,pk/K!t,=ϯZ6(((((((49 xn_kLk&f9sK`zx{{y8H 8b4>ÇНE|7v(z/]k7IxM}8!ycZRQ pKVr(RPEr?^}'ðh{x+ՀLW154cK@Ng C)rr9+c:׹b Жf*s^ fKS7^} *{zq_@8# pF~ [VPe(nw0MW=3#kȵz晨cy PpG#W:%drMh]3HH<\]ԁ|_W HHҡb}P>k {ZErxMX@8C&qskLۙOnO^sCk7ql2XCw5VG.S~H8=(s1~cV5z %v|U2QF=NoW]ո?<`~׮}=ӬfԵ,=;"~Iy7K#g{ñJ?5$y` zz@-~m7mG宝Gٱ>G&K#]؃y1$$t>wqjstX.b̐{Wej)Dxfc:8)=$y|L`xV8ߙ~E)HkwW$J0uʟk>6Sgp~;4֌W+חc"=|ř9bc5> *rg {~cj1rnI#G|8v4wĿhFb><^ pJLm[Dl1;Vx5IZ:1*p)إ1ZbAK(1ׅ|S&5{^ KG^5r>;X׻K^? s fk^8O/"J)3K]N)iL?5!ƾq:G_=X- i,vi2N3 |03Qas ! 7}kZU781M,->e;@Qz T(GK(ah(((((((Y[×j2F}o־oYYq $+]%$ v^rϭ`nax,ZEuWSܽ,g%~"MrsrY~Ҿ"Fت;8{ѰxYEfP^;WPwqbB:c?zp<7;SBfZ)dϛ; 7s^>}⍱x?Bix^#hf,*P9S{w[]GF?1Z_nG~]kk)9Sc5Ո<<6J-ϛ}xUi>ux#ţc'{ᛲq?Oo?x&mѱ'#^t)ϲbb0 F«kIVmVsv@}kҡ!ˍUTtxO̧]ORb|2yԵk܊{sPIc_?ħ:Ig)=Z~' "\M2VSSMyLsl⺿U~"C7\hz_ Rs$~? TAi<lO*>U}+'f>7_K N s8g1^CeКÿE ;{+Y\ O5|Y{/o+ LVcO;7Zx-Ek&dpzbӱ+TaB0gNy׭ 3^c T\$⫫?F33?t._Q~Nln:U/Ceb1-im WʸQM+VpafR3d׫é|Aү-q*I P7:y&]hX^Fbtpܩ?|Wu󭏤ʫxJ3ߴm"(uqA}j.+?S wV ~ [B&<^U?rϜ_OH\'.;|.%pw/ZZG'1j(#0UT` Wzw}>_*9m>󑓀F?EL3"zpubzΕ$+0܉&3zڶ+jyr1QE ( ( ( ( ( ( ( (UIdC0EZm+]Y6^![ ԯsmܶ捆?+me+ZE29)B[;я*wGxsK7;5w)}gH~.Ɣx?X\ߚ}A@tQ(:ͧ|Iq(CT?v[sKG+*רqҍck <#Ljα5݈`8cXP6T5i.K!xX*p&ќZǓϘ7 *oƽ:wlຈ:Q5yIEA/2*2jAҐe}k%K$N9R2?7ýKMV!{W9\PA+c4w` Wx=Ze\X{}yXI Ү!aOÎ{]Qx)#D@9E:*NJ}b|Z>_k7:d$z >&Vv󃏽WlR:RqJfGإd9Tm(ҝEtO}1O[xxEYt8,3v bFF )ǙrPNE8=O#V*Cc𹾾&l&cmCh<.P{ʦ&ۣY+Gxs~k5$> ӥPquŽўZt~Tl>Q.g> %k#ú:Kn'&{[yWQGqF}AЅ׮/}<;VYZa$wQg!$;_ $NKS}“_{MY|w7G!"\JtRy+贾d|o/;5jz_6fHwk<ѰJ#]kAȎ J =YNu%dxRwwbEQEQEQEQEQEQEQEQEQE'fLQZ(1F)hQ@X1KEQE-Q@ 1KE3h=iPb(((1GjZ(-ʹRPbR@ 1KE7`bڒyS0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( g\==oNYdp+@jhs2X".]q8mQ\V_ Ehl%d24O@@^2QҬudKhCrnWS0H9Ey?H@2pX9[RFѯKEQK2@IԡtkRdX/m㸍d0WP3k|]1U@dPRY"Pp2H8;DzD<?;ۿb1@}gYywx4r@c ~5ChڥY[q"b gW_5h^Wwgy@\+#nܜ]*ǃ|M^->Y:+F8\i::΍c[w Fp}M\3Լg!?G9Qk$hڱ@D($P1׃jx%`]f;KXbv pé#pLx^JfbKXYPCaݎ6?G4me#ֵO IU¾/P0qJ+/x]/S?t9绗̗â4)%܈ Q`_?|#[gkpAtzŠp̨ \n{f4)Ro.SzXu SU֯ľ#[jZ}.ӂw?,zWax×,z4ʺDp9SuW0nGƄfs-1V0Ě]Զ>lr3S򮆻_eq#T58m]>$W'j41=r O\ıv˧QŒLѶK3!Cc I9f&MCX{{} g9NN7d  GĖzg]hk_; vI<`¶+ֵ}OKXo{K[28\VV$(wdG=1cjx>%ՠt]K{XeR7p'#H@L_.M.wiދ=>ƶrpT D +#ƺDŽ /~%xĨ v@$΢Fe.71@(('O5"v?:&$7䩗NWC}vz'?fڍpP.'ː,I1@  !y$($spxG?yN*O/vq3n͹,95_4/sΙuwfH9V c}n:uD}JrRt J(~-g÷qZ|vy((U;'smGykA]B,-_H6/,0=A=w(}G;p}3z隱^?"S#jgDIm .[ 9׍(ƺDŽ /~%xĨ v@$΢Fe.71@+-[cA}gkdͽLlJ*ph(QյOK^}`2ďx:=B ( ( ( ( ( ( ( ( (8xo]D~-5وCis=B4  Vn!A Xj>ֵkk D%;ƒ5  3xUG͊(3񇁼KO&?hėlQKiro;aAFLđY:kՊ!t%9 6 oD㼰L $0? @& o3^F]}wgo9ǽؚ)ywmݝ{U{=2K--cFI?Լ-x7݄V{CM<RE kc&/o}:Sv#]EgvgdH$F Uj:"w|Ai{q7nnH28>՟'ĺoa6 c:y.m& dc`GnW(;д|WM-'U8w$u<j:'%6OۼAw{oon px8>Q@o[YoK lj5y|Ԗ0#9'|Tz5D<hG<3dZ)ɅX :2}2Msڞ:lsq.0@DT1b'\t?^hV6Sm7TB$8giG (*彂8| : =pAH$]BRW%G$dqMs7.?bCn1L]z5D<hG<3dZ)ɅX :2OxĺL#c\G|u̷w*NýFu)PQMZeKOU#3ګ&co'Vْ81$p2NH]gvgdH$F U{Don#'-yźC0Pzq;QEp-3Q/XV+Ŧb,&@I_ڥxP?k7"}%FL>\FA (|!^=&obÑ[[;ǒJ&L IV޳xsCXMc { E1.@zEW#>"ȷhjiW L@ [/S>G:ۺy^3ͷcPټI5$:m$ǰo/X =xsGuww-ح!|H N~(_&m6}O -!q"_XW}wO7ǙZ yᵷX$/$0UE$xs@W|2 G~KOE]@ALg[HQ(W"8ם+#MI䵵߱`\vsXmooq{ْHhռ r8=*E5pzg}حy$cUXŤ$IThN紑7ҹdU;`95k3Yc]Gk(SCjGb ڕkY xgcL/R&lg88< d>|Lō'EDC۞ d9O6M;~& *X^W3;GrH9F@(G YYsi$Vl*VPpx%( _D? 1>}yK`~ҷQl@8댮;!+{x++Ď; :(@pjxJï:?eC3ƶ>Wm-_W$M6GG@: 5~~6`X=5&Tڧg׮P|Mi#TaikhFS. ,6:co ܯѮm ؔR97d2zW7/=mFKiE՜$ i-/"xޝ*?vߋu +Nq̍Hv6XcJp@ -^M%GۀyPBԒNyGKwEo}c/{o?)"Kqi `"[ ~mG>g19&.w ')"ɹcF$Hxg'զIơ$绻 I;GRx;+Ѿ)'_RN{D9!I*C1$aG'һ (D;vIukaXCoH+9ך+sS^:eۙwtlgh/)'M$Ѯ"Q c9H`89?.q@Bզ^"{;i-f!gÜ 0qY·N{ ^ V2gi z`0cѼ?x g-ԌV岪BF9'kcsmo,q!}A;U,@ V:v]& gG۳1s]:yh[]igF}6'2pHش4cQխ_j^WjpNgy>A?|os6q ?›?W7>|뼿߳88͊9x.W/#Iv#I락yli~4oecjfTX cZ{C:;wEuk{e%eX$R`E'_[YwwW[ ˴e98\)h<7qٷ?Í.5 l|Cwq$Nx I&D9b˱@< N@x7n1N $a@|>^H.#[ r0c^[:6]K Ĉtt F88YYQ{G@%$y$#e ē]o.8T<5 B{ Iy$Fp ggK8./vg*N-ϡ@ sF>i]YAwɈ0du7d Hĺ jvibhR]As'hVۿx% etm?IԴӑRL p2 *džx>x46;4C02I8><1}ooᨼ6*2\GpM#@ B`˶3ޕyMүྺ`yʟ, qګ? </=$$YlrǓ]&Xz][Gmgn":(dII4OS?j1 VP_)%#rLX Gy,#_4 i PaF.vK%_qƻu<R9m'8%32qֆ#Z-vRX,z xt.}G;p}3z)̕c]]& gOyNvo8Ͻr< 77uu+3qؒ2I@ hӤk$fO5ː9rOElPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPPK@eePK DOEBPS/dcommon/cpyr.htmD Oracle Legal Notices

Oracle Legal Notices

Copyright Notice

Copyright © 1994-2014, Oracle and/or its affiliates. All rights reserved.

Trademark Notice

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

License Restrictions Warranty/Consequential Damages Disclaimer

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

Warranty Disclaimer

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

Restricted Rights Notice

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

Hazardous Applications Notice

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Third-Party Content, Products, and Services Disclaimer

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

Alpha and Beta Draft Documentation Notice

If this document is in preproduction status:

This documentation is in preproduction status and is intended for demonstration and preliminary use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of this documentation.

Oracle Logo

PK0hPK DOEBPS/dcommon/oracle.gifJGIF87aiyDT2F'G;Q_oKTC[ 3-Bq{ttsoGc4I)GvmLZ).1)!ꑈ53=Z]'yuLG*)g^!8C?-6(29K"Ĩ0Яl;U+K9^u2,@@ (\Ȱ Ë $P`lj 8x I$4H *(@͉0dа8tA  DсSP v"TUH PhP"Y1bxDǕ̧_=$I /& .)+ 60D)bB~=0#'& *D+l1MG CL1&+D`.1qVG ( "D2QL,p.;u. |r$p+5qBNl<TzB"\9e0u )@D,¹ 2@C~KU 'L6a9 /;<`P!D#Tal6XTYhn[p]݅ 7}B a&AƮe{EɲƮiEp#G}D#xTIzGFǂEc^q}) Y# (tۮNeGL*@/%UB:&k0{ &SdDnBQ^("@q #` @1B4i@ aNȅ@[\B >e007V[N(vpyFe Gb/&|aHZj@""~ӎ)t ? $ EQ.սJ$C,l]A `8A o B C?8cyA @Nz|`:`~7-G|yQ AqA6OzPbZ`>~#8=./edGA2nrBYR@ W h'j4p'!k 00 MT RNF6̙ m` (7%ꑀ;PKl-OJPK DOEBPS/dcommon/doccd_epub.jsM /* Copyright 2006, 2012, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2012.3.17 */ function addLoadEvent(func) { var oldOnload = window.onload; if (typeof(window.onload) != "function") window.onload = func; else window.onload = function() { oldOnload(); func(); } } function compactLists() { var lists = []; var ul = document.getElementsByTagName("ul"); for (var i = 0; i < ul.length; i++) lists.push(ul[i]); var ol = document.getElementsByTagName("ol"); for (var i = 0; i < ol.length; i++) lists.push(ol[i]); for (var i = 0; i < lists.length; i++) { var collapsible = true, c = []; var li = lists[i].getElementsByTagName("li"); for (var j = 0; j < li.length; j++) { var p = li[j].getElementsByTagName("p"); if (p.length > 1) collapsible = false; for (var k = 0; k < p.length; k++) { if ( getTextContent(p[k]).split(" ").length > 12 ) collapsible = false; c.push(p[k]); } } if (collapsible) { for (var j = 0; j < c.length; j++) { c[j].style.margin = "0"; } } } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(compactLists); function processIndex() { try { if (!/\/index.htm(?:|#.*)$/.test(window.location.href)) return false; } catch(e) {} var shortcut = []; lastPrefix = ""; var dd = document.getElementsByTagName("dd"); for (var i = 0; i < dd.length; i++) { if (dd[i].className != 'l1ix') continue; var prefix = getTextContent(dd[i]).substring(0, 2).toUpperCase(); if (!prefix.match(/^([A-Z0-9]{2})/)) continue; if (prefix == lastPrefix) continue; dd[i].id = prefix; var s = document.createElement("a"); s.href = "#" + prefix; s.appendChild(document.createTextNode(prefix)); shortcut.push(s); lastPrefix = prefix; } var h2 = document.getElementsByTagName("h2"); for (var i = 0; i < h2.length; i++) { var nav = document.createElement("div"); nav.style.position = "relative"; nav.style.top = "-1.5ex"; nav.style.left = "1.5em"; nav.style.width = "90%"; while (shortcut[0] && shortcut[0].toString().charAt(shortcut[0].toString().length - 2) == getTextContent(h2[i])) { nav.appendChild(shortcut.shift()); nav.appendChild(document.createTextNode("\u00A0 ")); } h2[i].parentNode.insertBefore(nav, h2[i].nextSibling); } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(processIndex); PKo"nR M PK DOEBPS/dcommon/blafdoc.cssc@charset "utf-8"; /* Copyright 2002, 2011, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2011.10.7 */ body { font-family: Tahoma, sans-serif; /* line-height: 125%; */ color: black; background-color: white; font-size: small; } * html body { /* http://www.info.com.ph/~etan/w3pantheon/style/modifiedsbmh.html */ font-size: x-small; /* for IE5.x/win */ f\ont-size: small; /* for other IE versions */ } h1 { font-size: 165%; font-weight: bold; border-bottom: 1px solid #ddd; width: 100%; text-align: left; } h2 { font-size: 152%; font-weight: bold; text-align: left; } h3 { font-size: 139%; font-weight: bold; text-align: left; } h4 { font-size: 126%; font-weight: bold; text-align: left; } h5 { font-size: 113%; font-weight: bold; display: inline; text-align: left; } h6 { font-size: 100%; font-weight: bold; font-style: italic; display: inline; text-align: left; } a:link { color: #039; background: inherit; } a:visited { color: #72007C; background: inherit; } a:hover { text-decoration: underline; } a img, img[usemap] { border-style: none; } code, pre, samp, tt { font-family: monospace; font-size: 110%; } caption { text-align: center; font-weight: bold; width: auto; } dt { font-weight: bold; } table { font-size: small; /* for ICEBrowser */ } td { vertical-align: top; } th { font-weight: bold; text-align: left; vertical-align: bottom; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } li { text-align: left; } dd { text-align: left; } td p:first-child, td pre:first-child { margin-top: 0px; margin-bottom: 0px; } table.table-border { border-collapse: collapse; border-top: 1px solid #ccc; border-left: 1px solid #ccc; } table.table-border th { padding: 0.5ex 0.25em; color: black; background-color: #f7f7ea; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.table-border td { padding: 0.5ex 0.25em; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } span.gui-object, span.gui-object-action { font-weight: bold; } span.gui-object-title { } p.horizontal-rule { width: 100%; border: solid #cc9; border-width: 0px 0px 1px 0px; margin-bottom: 4ex; } div.zz-skip-header { display: none; } td.zz-nav-header-cell { text-align: left; font-size: 95%; width: 99%; color: black; background: inherit; font-weight: normal; vertical-align: top; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-header-link { font-size: 95%; } td.zz-nav-button-cell { white-space: nowrap; text-align: center; width: 1%; vertical-align: top; padding-left: 4px; padding-right: 4px; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-button-link { font-size: 90%; } div.zz-nav-footer-menu { width: 100%; text-align: center; margin-top: 2ex; margin-bottom: 4ex; } p.zz-legal-notice, a.zz-legal-notice-link { font-size: 85%; /* display: none; */ /* Uncomment to hide legal notice */ } /*************************************/ /* Begin DARB Formats */ /*************************************/ .bold, .codeinlinebold, .syntaxinlinebold, .term, .glossterm, .seghead, .glossaryterm, .keyword, .msg, .msgexplankw, .msgactionkw, .notep1, .xreftitlebold { font-weight: bold; } .italic, .codeinlineitalic, .syntaxinlineitalic, .variable, .xreftitleitalic { font-style: italic; } .bolditalic, .codeinlineboldital, .syntaxinlineboldital, .titleinfigure, .titleinexample, .titleintable, .titleinequation, .xreftitleboldital { font-weight: bold; font-style: italic; } .itemizedlisttitle, .orderedlisttitle, .segmentedlisttitle, .variablelisttitle { font-weight: bold; } .bridgehead, .titleinrefsubsect3 { font-weight: bold; } .titleinrefsubsect { font-size: 126%; font-weight: bold; } .titleinrefsubsect2 { font-size: 113%; font-weight: bold; } .subhead1 { display: block; font-size: 139%; font-weight: bold; } .subhead2 { display: block; font-weight: bold; } .subhead3 { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .betadraft, .alphabetanotice, .revenuerecognitionnotice { color: #e00; background: inherit; } .betadraftsubtitle { text-align: center; font-weight: bold; color: #e00; background: inherit; } .comment { color: #080; background: inherit; font-weight: bold; } .copyrightlogo { text-align: center; font-size: 85%; } .tocsubheader { list-style-type: none; } table.icons td { padding-left: 6px; padding-right: 6px; } .l1ix dd, dd dl.l2ix, dd dl.l3ix { margin-top: 0ex; margin-bottom: 0ex; } div.infoboxnote, div.infoboxnotewarn, div.infoboxnotealso { margin-top: 4ex; margin-right: 10%; margin-left: 10%; margin-bottom: 4ex; padding: 0.25em; border-top: 1pt solid gray; border-bottom: 1pt solid gray; } p.notep1 { margin-top: 0px; margin-bottom: 0px; } .tahiti-highlight-example { background: #ff9; text-decoration: inherit; } .tahiti-highlight-search { background: #9cf; text-decoration: inherit; } .tahiti-sidebar-heading { font-size: 110%; margin-bottom: 0px; padding-bottom: 0px; } /*************************************/ /* End DARB Formats */ /*************************************/ @media all { /* * * { line-height: 120%; } */ dd { margin-bottom: 2ex; } dl:first-child { margin-top: 2ex; } } @media print { body { font-size: 11pt; padding: 0px !important; } a:link, a:visited { color: black; background: inherit; } code, pre, samp, tt { font-size: 10pt; } #nav, #search_this_book, #comment_form, #comment_announcement, #flipNav, .noprint { display: none !important; } body#left-nav-present { overflow: visible !important; } } PKT' hcPK D OEBPS/toc.htm Oracle Communications Services Gatekeeper Platform Development Studio Developer's Guide , Release 5.1

Contents

Preface

1 Overview of the Platform Development Studio

2 Understanding Communication Services

3 Using the Eclipse Wizard

4 Service Enabler Example with SIP plug-in

5 Description of a Generated Project

6 Communication Service Example

7 Using the SMPP API

8 Using the UCP API

9 Container Services

10 Service Interceptors

11 Aspects, Annotations, EDRs, Alarms, and CDRs

12 Subscriber-centric Policy

13 Custom Service Level Agreements

14 Customizing Diameter AVPs

15 Creating an EDR Listener and Generating SNMP MIBs

16 Making Communication Services Manageable

17 Using Request Context Parameters in SLAs

18 Extending the ATE and the PTE

PKPK DOEBPS/pds_esexample.htm Communication Service Example

6 Communication Service Example

This section describes the example Communication Service in the Oracle Communications Services Gatekeeper (Services Gatekeeper) Platform Development Studio.

Overview

The Communication service example demonstrates the following:

  • Structure and execution workflow in a Communication Service.

  • Parameter validation

  • Hitless upgrade

  • Retry

  • Simple TCP/IP protocol-based simulator

  • Testability with the PTE

The example is based on an end-to-end Communication Service, with a set of simple interfaces

  • SendData, which defines the operation sendData used to send data to a given address.

  • NotificationManager, which defines these operations:

    • startEventNotification, which starts a subscription for network-triggered events.

    • stopEventNotification, which ends the subscription for network-triggered events.

  • Notification, which defines the operation:

    • notifyDataReception, used to notify the application on a network-triggered event.

The SendData and NotificationManager interfaces are used by an application and implemented by the Communication Service.

The Notification interface is used by the Communication Service and implemented by an application.

The Communication Service to network node interface is a simple TCP/IP based interface that defines the two commands:

  • sendDataToNetwork, that sends data to the network node.

  • receiveData, that is used by the network node to send data to a receiver - in this case the network protocol plug-in.

Figure 6-1 illustrates the flow for these operations.

Figure 6-1 Overview of example Communication Service

Description of Figure 6-1 follows

The flow marked A* is for sendData, the flow marked B* is for startNotification and stopNotification, and the flow marked C* is for notifyDataReception.

The modules marked with 1 are automatically generated based on the WSDL files that define the application-facing interface and code generation templates provided by the Platform Development Studio. The modules marked with 2 are skeletons generated at build time.

High-level Flow for sendData (Flow A)

  1. A1: An application invokes the Web Service SendData, with the operation sendData.

  2. A2: The request is passed on the EJB for the interface, which passes it on to the network protocol plug-in. The diagram is simplified, but at this stage the Plug-in Manager is invoked and makes a routing decision to route to the appropriate plug-in.

  3. A3: The Plug-in Manager invokes the sendData method in the class SendDataPluginNorth. It will always invoke a class named PluginNorth, that has a prefix that is the same as the Java representation of the Web Service interface.

  4. A4: The request is passed on to class SendDataPluginToNetworkAdapter that performs the protocol translation according to the network-interface.

  5. A5: The request is passed to SendDataPluginSouth.

  6. A6: The request is handed off to the network node.

High-level Flow for startNotification and stopNotification (Flow B)

The initial steps (B1-B3) are similar to flow A*. Instead of translating the request to a command on the network node, NotificationManagerNorth uses the StoreHelper to either store a new or remove a previously registered subscription for notifications. The data stored, the NotificationData, is used in network-triggered requests to resolve which application started the notification and the destination to which to send it. In the example the notification is started on an address, so the address is stored together with information to which endpoint the application wants the notification to be sent.

High-level flow for notifyDataReception (Flow C)

  1. C1: The network protocol plug-in receives the network-triggered command receiveData on NetworkToNotificationPluginAdapter.

  2. C2: SendDataPluginSouth can be used to add additional information to the request before passing in on.

  3. C3: NetworkToNotificationPluginAdapter performs the protocol translation.

  4. C4: StoreHelper is used to examine if the request matches any stored NotificationData. If so, the information in NotificationData is retrieved. This information includes which application instance that the request resolves to and on which endpoint this application wants to be notified about the network triggered event.

  5. C5: NotificationCallbackFactory is used to get a hold of an active NotificationCallback EJB to pass on the request to.

  6. C6: The request is passed on to the NotificationCallback EJB.

  7. C7: The request is passed on to an application.

Interfaces

The example Communication Service translates between an application-facing interface, defined in WSDL, see "Web Service Interface Definition" and a network interface, TCP/IP based, see "Network Interface Definition".

Web Service Interface Definition

This is the application-facing interface for the example Communication Service.

Interface: SendData

This interface is a simple interface containing operations for sending data.

Operation: sendData

Send data to the network.

Input message: sendDataMessage

Table 6-1 sendDataMessage parts

Part namePart typeOptionalDescription

data

xsd:string

N

The data to be sent to the target device

address

xsd:anyURI

N

Address of the target device.

Example:

tel:4154011234


Output message: sendDataResponse

Table 6-2 sendDataResponse parts

Part namePart typeOptionalDescription

none

N/A

N/A

N/A


Interface: NotificationManager

The Notification Manager Web Service is a simple interface containing operations for managing subscriptions to network triggered events.

Operation: startEventNotification

Start the subscription of event notification from the network.

Input message: startEventNotificationRequest

Table 6-3 startEventNotificationRequest parts

Part namePart typeOptionalDescription

correlator

xsd:string

N

Service unique identifier provided to set up this notification.

endPoint

xsd:string

N

Endpoint address. Endpoint of the application to receive notifications.

Example:

http://www.hostname.com/NotificationService/services/Notification

address

xsd:anyURI

N

Service activation number.

Example:

tel:4154567890


Output message: invokeMessageResponse

Table 6-4 invokeMessageResponse parts

Part namePart typeOptionalDescription

none

N/A

N/A

N/A


Operation: stopEventNotification

Stop the subscription of event notification from the network.

Input message: stopEventNotificationRequest

Table 6-5 stopEventNotificationRequest parts

Part namePart typeOptionalDescription

correlator

xsd:string

N

Service unique identifier provided to set up this notification.


Output message: stopEventNotificationResponse

Table 6-6 stopEventNotificationResponse parts

Part namePart typeOptionalDescription

none

N/A

N/A

N/A


Interface: NotificationListener

The NotificationListener interface defines the methods that the Communication Service invokes on a Web Service that is implemented by an application.

Operation: notifyDataReception

Method used for receiving a notification.

Input message: notifyDataReceptionRequest

Table 6-7 notifyDataReceptionRequest parts

Part namePart typeOptionalDescription

correlator

xsd:string

N

Service unique identifier provided to set up this notification.

originatingAddress

xsd:anyURI

N

Address of the device where the data originated.

Example:

tel:4153083412

data

xsd:string

N/A

Data sent by the originating device.


Output message: notifyDataReceptionResponse

Table 6-8 notifyDataReceptionResponse

Part namePart typeOptionalDescription

none

N/A

N/A

N/A


Network Interface Definition

This is the network-facing interface for the example Communication Service.

sendDataToNetwork

Send data from the Communication Service to the network node.

Table 6-9 sendDataToNetwork arguments

ArgumentTypeDescription

fromAddress

String

The address from which the request is sent.

toAddress

String

The address to which the request shall be sent.

data

String

The data to send.


receiveData

Send data from the network node to the Communication Service.

Table 6-10 receiveData arguments

ArgumentTypeDescription

fromAddress

String

The address from which the request is sent.

toAddress

String

The address to which the request shall be sent.

data

String

The data to send.


Directory Structure

Below is a description of the directory structure for the example Communication Service.

communication_service
+- build.properties
+- common.xml
+- build.xml
+- example
| +- common
| | +- build.xml
| | +- dist
| | | +- request_factory_skel
| | | +- tmp
| | | +- example.war
| | | +- example_callback.jar
| | | +- example_callback_client.jar
| | | +- example_service.jar
| | | +- resources
| | | | +- enabler
| | | | + facade
| | | +- src
| | | | +- com/<package name>Plugin
| | | | | +- ExceptionType.java
| | | | | +- NotificationManagerPluginFactory.java
| | | | | +- SendDataPluginFactory.java
| | | | | +- handlerconfig.xml
| | | | | +- weblogic.xml
| | +- wsdl
| +- dist
| | +- com.acompany.plugin.example.netex.store_4.1.jar
| | +- example_enabler.ear
| | +- example_facade.ear
| +- plugins
| | +- nextex
| | | +- build.xml
| | | +- dist
| | | | +- example_netex_plugin.jar
| | | | +- com.acompany.plugin.example.nextex.store_4.1.0.0.jar
| | | +- build
| | | +- config
| | | | +- edr
| | | | | +- alarm.xml
| | | | | +- cdr.xml
| | | | | +- edr.xml
| | | | | +- alarm.xml
| | | | +- instance_factory
| | | | | +- instancemap
| | | +- dist
| | | | +- com.acompany.plugin.example.netex.store_4.1.jar
| | | | +- example_netex_plugin.jar
| | | +- src/com/acompany/plugin/example/netex/
| | | |           +- context
| | | |           +- management
| | | |           +- notification
| | | |           +- notificationmanager
| | | |           +- senddata
| | | |           +- store
| | | +- storage
| | | | +- wlng-cachestore-config-extensions.xml

Directories for WSDL

Below is a list of WSDL files that define the application-facing interface and the Java representation of these in the plug-in.

Application-initiated traffic

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common/wsdl/service

example_common_faults.wsdl
example_common_types.xsd
example_data_send_interface.wsdl
example_data_send_service.wsdl
example_notification_manager_interface.wsdl
example_notification_manager_service.wsdl

Network-triggered traffic

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common/wsdl/callback

example_notification_interface.wsdl
example_notification_service.wsdl

Directories for Java Source

Below is a list of Java source directories for the "Communication Service Common" and the "Plug-in".

Communication Service Common

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common/src

com.acompany.example.plugin.ExceptionType
com.acompany.example.plugin.NotificationManagerPluginFactory
com.acompany.example.plugin.SendDataPluginFactory

Plug-in

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/plugins/netex/src

com.acompany.plugin.example.netex.context.ContextTranslatorImpl
com.acompany.plugin.example.netex.management.ConfigurationStoreHandler
com.acompany.plugin.example.netex.management.ExampleMBean
com.acompany.plugin.example.netex.management.ExampleMBeanImpl
com.acompany.plugin.example.netex.management.Management
com.acompany.plugin.example.netex.notification.north.NotificationHandlerNorth
com.acompany.plugin.example.netex.notification.south.NetworkToNotificationPluginAdapter
com.acompany.plugin.example.netex.notification.south.NetworkToNotificationPluginAdapterImpl
com.acompany.plugin.example.netex.notificationmanager.north.NotificationManagerPluginNorth
com.acompany.plugin.example.netex.senddata.north.SendDataPluginNorth
com.acompany.plugin.example.netex.senddata.south.SendDataPluginSouth
com.acompany.plugin.example.netex.senddata.south.SendDataPluginToNetworkAdapter
com.acompany.plugin.example.netex.senddata.south.SendDataPluginToNetworkAdapterImpl
com.acompany.plugin.example.netex.store.FilterImpl
com.acompany.plugin.example.netex.store.NotificationData
com.acompany.plugin.example.netex.store.StoreHelper
com.acompany.plugin.example.netex.ExamplePluginInstance
com.acompany.plugin.example.netex.ExamplePluginService

Directories for resources

Only the Communication Service common components have associated resources. The resources are XML files that serve as deployment descriptors for the network tier and access tier EAR files.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common/resources/at/META-INF

Contains deployment descriptors for the access tier EAR file. These must be present in the META-INF directory of the EAR. See "Enterprise Application Deployment Descriptor Elements" in Oracle Fusion Middleware Developing Applications for Oracle WebLogic Server at:

http://download.oracle.com/docs/cd/E15523_01/web.1111/e13706/app_xml.htm

for a description of the enterprise application deployment descriptor elements.

application.xml
weblogic-application.xml

The code generation creates these files, and the build script takes care of the packaging.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common/resources/nt/META-INF

Contains deployment descriptors for the network tier EAR file. These must be present in the META-INF directory of the EAR. See "Enterprise Application Deployment Descriptor Elements" in Oracle Fusion Middleware Developing Applications for Oracle WebLogic Server at:

http://download.oracle.com/docs/cd/E15523_01/web.1111/e13706/app_xml.htm

for a description of the enterprise application deployment descriptor elements.

application.xml
weblogic-application.xml
weblogic-extension.xml

The code generation creates these files, and the build script takes care of the packaging.

Directories for Configuration of Plug-in

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/plugins/netex/config/edr

Sample entries to add in the EDR, CDR, and Alarm filters.

alarm.xml
cdr.xml
edr.xml

These serves as examples. Add the contents of these to the EDR configuration file. Use the EDR Configuration Pane as described in Managing and Configuring EDRs, CDRs and Alarms in the System Administrator's Guide.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/plugins/netex/instance_factory

Sample instance map for mapping of classes, interfaces, and abstract classes.

When using com.bea.wlcp.wlng.api.util.InstanceFactory to retrieve instances for a given interface, class, or abstract class, this mapping is referenced. The mapping can be overridden. See the Javadoc for InstanceFactory for details.

instancemap

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/plugins/netex/storage

Sample store configuration file. Defines how the Storage service is used by the plug-in, store type, table names, query definitions, and get and set methods. See "StoreHelper", "FilterImpl", and "NotificationData".

wlng-cachestore-config-extensions.xml

Directories for Build and Configuration of Builds

Middleware_Home/ocsg_pds_5.1/example/communication_service/

build.properties

Defines the installation directory for Oracle Communications Services Gatekeeper and for the Platform Development Studio.

common.xml

Defines properties, class paths, task definitions, and macros for the build.

build.xml

Main build file to build the Communication Service. This build file also contains targets for packaging deployable artifacts into the access and network tier.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common

build.xml

Build file for the common parts of the Communication Service.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/plugins/netex

build.xml

Build file for the plug-in.

Directories for Classes, JAR, and EAR Files

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/dist

Deployment artefacts for the Communication Service.

example_facade.ear

The part of the Communication Service that is deployed in the access tier.

example_enabler.ear

The part of the Communications Service that is deployed in the network tier.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common/dist

JAR and WAR files for the common parts of the Communication Service.

example_callback_client.jar
example_callback.jar
example_service.jar
example.war

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/common/dist/request_factory_skel

Auto generated source for skeleton classes extending com.bea.wlcp.wlng.api.plugin.RequestFactory.

One class is generated per Service WSDL, that is per interface that defines application-initiated operations.

The classes are named PreFixPluginFactory, where PreFix is picked up from the WSDL binding in the WSDL file.

In the subdirectory that corresponds to the package name, the following classes are generated:

NotificationManagerPluginFactory.java
SendDataPluginFactory.java

These are generated as skeletons, but in the example they are adapted to the specific use cases.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/plugins/netex/dist

Contains individual JAR files comprises the plug-in.

com.acompany.plugin.example.netex.store_4.1.jar

Includes the schema file for the store used by the plug-in, packaged together with the classes for which instances are stored. This file must be put in Domain_Home/config/store_schema on each server in the network tier. The server needs to be restarted if any changes have been done to the store schema or the classes referred to in the store schema.

example_netex_plugin.jar

The JAR for the plug-in.

Middleware_Home/ocsg_pds_5.1/example/communication_service/example/plugins/netex/dist/mbean_generationdir

Output directory for the MBean that has been processed by the javadoc2annotation Apache Ant task.

Classes

Below is a description of the classes and the methods defined in these classes:

Communication Service Common

This section describes the Communication Service Common classes.

ExceptionType

Class.

Enumeration for exception types:

Defines:

  • SERVICE_ERROR

  • POLICY_ERROR

NotificationManagerPluginFactory

Class.

Extends RequestFactory.

Helper class that is used by the service EJB for two purposes:

  • Creating routing information requested by the Plug-in Manager when routing the method call to a plug-in.

  • Converting Exceptions, thrown either by the Plug-in Manager or by the plug-in, to Exceptions that are supported by the application-facing interface.


    Note:

    This class needs to remain in this package and the class name must not be changed.

public void validateRequest(Method method, Object... args)

Validates the request to make sure that mandatory parameters are present. Operates on a Java representation of the Web Service call.

public RequestInfo createRequestInfo(Class<? extends Plugin> type, Method method, Object... args)

Used by the service EJB to extract routing data from the method call. The routing data is then given to the Plug-in Manager. This method returns the routing data in a RequestInfo object.

Returns a:

  • AddressRequestInfo if the request contains an actual address that can be routed to a specific plug-in.

  • CorrelatorRequestInfo if the request contains an correlator that relates to an operation that relates to states (to start or to stop something). Most often it is the starting and stopping of notifications that use a correlator.

public Throwable convertEx(Method method, Throwable e)

Called by the service EJB in order to convert Exceptions thrown by the Plug-in Manager and the Plug-in to Exceptions defined by the called method.

private Throwable convertEx(Method method, PluginException e)

Converts a PluginException to an Exception that can be thrown by the method called by the application.

Plug-in Layer

This section describes the Plug-in Layer classes.

ContextTranslatorImpl

Class.

Implements interface com.bea.wlcp.wlng.api.plugin.context.ContextTranslator.

Responsible for setting any non-simple parameter into the RequestContext.

public void translate(Object param, ContextInfo info)

Puts the member variables of a complex data type into the ContextInfo.

Checks the interface type.

Gets the simple data types provided in the parameter param.

Puts each of the parameters into the ContextInfo object.

These parameters are provided in each subsequent EDR that is emitted in the request.

ExamplePluginService

Package: com.acompany.plugin.example.netex

Implements ManagedPluginService.

Initial point for the network protocol plug-in.

Defines the life-cycle for a plug-in service.

Also holds the data that is specific for the plug-in instance.

This class manages the life-cycle for the plug-in service, including implementing the necessary interfaces that make the plug-in deployable in Oracle Communications Services Gatekeeper. It is also responsible for registering the north interfaces with the Plug-in Manager. At startup time it uses the InstanceFactory to create one instance of each plug-in service and at activation time it registers these with the Plug-in Manager. The InstanceFactory uses an instancemap to find out which class it should instantiate for each plug-in interface implementation. The instance map is found under the resource directory. It also has

public boolean isRunning()

Checks to see if the plug-in service is in running state.

public String[] getSupportedSchemes()

Returns a list of address schemes the plug-in supports.

public void init(String id, PluginPool pool)

Initializes the plug-in service with its ID and a reference to its plug-in pool.

public void doStarted()

When entering state Started, the plug-in instantiates a TimerManager.

public void doStopped()

No action.

public void doActivated()

No action.

public void doDeactivated()

No action.

public void handleSuspending(CompletionBarrier barrier)

The plug-in service does not handle graceful shutdown: it propagates the request to public void handleForceSuspending().

public void handleForceSuspending()

When the plug-in is being forcefully suspended, the plug-in service iterates through all plug-in instances and calls public void handleSuspending() on each.

public boolean isActive()

While there is a connection to the network node and the plug-in is in state ACTIVE/RUNNING this method must return true, in all other cases false. This method is invoked by the Plug-in Manager during route selection.

public ServiceType getServiceType()

Returns the type of the service. Used by the Plug-in Manager to route requests to a plug-in instance that can manage the type of request. The ServiceType is auto-generated based on the WSDL that defines the application-facing interfaces.

public String getNetworkProtocol()

Returns a descriptive name of the network protocol being used.

createInstance(String)

Creates a new plug-in instance.

ExamplePluginInstance

Package: com.acompany.plugin.example.netex.

Implements ManagedPluginInstance

Defines the life-cycle for a plug-in instance/

This class manages the life-cycle for the plug-in instance including implementing the necessary interfaces that make the plug-in an instance in Oracle Communications Services Gatekeeper.

It is also responsible for instantiating classes that implement the traffic interfaces and for initializing stores to use and MBeans.

public String getId()

Returns the plug-in instance ID.

public void activate()

private void rethrowServiceDeploymentException(Exception e)

Re-throws a ServiceDeploymentException if any other exception is encountered. The exception is wrapped in a ServiceDeploymentException.

public ConfigurationStoreHandler getConfigurationStore()

Returns a handle to the ConfigurationStore used by the plug-in instance. The ConfigurationStore was initiated in public void activate().

public NetworkProxy getNetworkProxy()

Returns handle to the NetworkProxy. The NetworkProxy was initiated in public void activate().

public void connect()

Connects to the network using NetworkProxy.

ConnectTimerTask

Inner class of ExamplePluginService.

Extends java.util.TimerTask.

It has one method, run(), that tries to connect to the network node, if not connected. This class is instantiated and scheduled as a java.util.Timer in public void handleResuming().

ConfigurationStoreHandler

Handles storage of configuration data using the StorageService.

A set of default settings are defined as static final variables. These are used to populate the ConfigurationStore with default values the first time the plug-in is deployed.

Takes the plug-in ID as a parameter. The plug-in ID is the key in the ConfigurationStore.

Uses ConfigurationStoreFactory to get a handle to the ConfigurationStoreService and gets the local ConfigurationStore that handles configuration data for the plug-in instance.

The plug-in only deals with configuration data that is unique for the instance in a specific server, so the store is fetched as outlined in Example 6-1.

Example 6-1 Get a server-specific (local) ConfigurationStore

ConfigurationStoreFactory factory = ConfigurationStoreFactory.getInstance();
localConfigStore = factory.getStore(pluginId, LOCAL_STORE, ConfigurationStore.STORE_TYPE_LOCAL);

If the plug-in uses a ConfigurationStore that is shared between the plug-in instances in the cluster, it must fetch that one as well, as outlined in Example 6-2

Example 6-2 Get a cluster-wide (shared) ConfigurationStore

ConfigurationStoreFactory factory = ConfigurationStoreFactory.getInstance();
sharedConfigStore = factory.getStore(pluginId, SHARED_STORE, ConfigurationStore.ConfigurationStore.STORE_TYPE_SHARED);

After the ConfigurationStore is fetched, it is initialized with default values for the available configuration settings. These default values can be changed later on, using the MBeans, see "ExampleMBean".

public void setLocalInteger(String key, Integer value),

public Integer getLocalInteger(String key),

public void setLocalString(String key, String value), and

public String getLocalString(String key)

The methods above are used to set and get data to and from the ConfigurationStore. One set/get pair must be implemented per data type in the ConfigurationStore. It is only necessary to implement set/get methods for the data types actually used by the plug-in.

In the set methods, the parameter name/key is provided as the first parameter and the actual value is provided in the second parameter.

In the get methods, the parameter name/key is provided as the parameter and the actual value is returned.

ExampleMBean

Interface.

Management interface for the example simulator.

It defines the following methods:

  • public void setNetworkPort(int port) throws ManagementException;

  • public int getNetworkPort() throws ManagementException;

  • public void connect() throws ManagementException;

  • public void disconnect() throws ManagementException;

  • public boolean connected();

Implemented by ExampleMBeanImpl.

All MBean methods should throw com.bea.wlcp.wlng.api.management.ManagementException or a subclass thereof if the management operation fails.

Management

Class.

Handles registration of the "ExampleMBean" in the MBean Server.

NotificationHandlerNorth

NotificationHandlerNorth()

Constructor.

Empty.

public void deliver(String data, String destinationAddress, String originatingAddress)

Delivers data originating from the network node to the application.

NetworkToNotificationPluginAdapterImpl calls this method upon a network triggered request.

The actual delivery is not done directly to the application. Instead it is done via the service callback client EJB which forwards the request to the service callback EJB. Both of these are generated during the build process.

First, the "NotificationData" associated with the destination address is fetched.

NotificationCallback, which is a generated class, is fetched using "private NotificationCallback getNotificationCallback()".

NotifyDataReception, a generated class that is a Java representation of the operation defined in the callback WDSL is instantiated.

The correlator associated with the "NotificationData" is set on NotifyDataReception.

The data (payload) in the network triggered request is set on NotifyDataReception.

The originating address in the network-triggered request is converted to a URI and set on NotifyDataReception.

The endpoint associated with NotificationData is fetched.

A remote call is done to the method notifyDataReception on the Callback EJB in the access tier. The endpoint and NotifyDataReception are supplied as parameters.

private NotificationCallback getNotificationCallback()

Helper method to get the object representing the Callback EJB.

If the object is already retrieved it is returned, otherwise the NotificationCallbackFactory is used to get a new object. This is the preferred pattern.

Using the CallBackFactory ensures high-availability between the network tier and the access tier for network triggered requests.

The Callback is generated during the build process when the access tier is generated. Three files are generated per callback WSDL. The names are based on the interface name defined in the WSDL. The interface in the WSDL is Notification, so:

  • the factory is named NotificationCallbackFactory.

  • the implementation class is named NotificationCallbackImpl

  • an interface is named is named NotificationCallback.

The classes are completely based on the WSDL file for the callback interface. The factory is used to retrieve the implementation class that implements the interface.

private NotificationData getNotificationData(String destinationAddress)

Helper method to fetch the NotificationData from the StoreHelper. The NotificationData is retrieved based on the key destination address.

NetworkToNotificationPluginAdapter

Interface

extends PluginSouth, NetworkCallback

Defines the interface between "NetworkToNotificationPluginAdapter" and the network node.

public void setNotificationHandler(NotificationHandlerNorth notificationHandlerNorth)

Sets the NotificationHandler.

NetworkToNotificationPluginAdapterImpl

Class.

Implements "NetworkToNotificationPluginAdapter".

public void setNotificationHandler(NotificationHandlerNorth notificationHandlerNorth)

Sets "NotificationHandlerNorth" in the class.

public String resolveAppInstanceGroupdId(ContextMapperInfo info)

From interface com.bea.wlcp.wlng.api.plugin.PluginSouth

Gives the plug-in an opportunity to add additional values to the RequestContext before the network-triggered requests is passed on to public void receiveData(@ContextKey(EdrConst ants.FIELD_ORIGINATING_ADDRESS) String fromAddress, @ContextKey(EdrConstants.FIELD_DESTINATION_ADDRESS) @MapperInfo(C) String toAddress, String data).

This method is called only once per network-triggered request. It is invoked after resolveAppInstanceGroupId(ContextMapperInfo), when the RequestContext for the current request has been rebuilt.

The default implementation is supposed to be empty.

RequestContext contains the fully rebuilt RequestContext.

ContextMapperInfo contains the annotated parameters in public void receiveData(@ContextKey(EdrConst ants.FIELD_ORIGINATING_ADDRESS) String fromAddress, @ContextKey(EdrConstants.FIELD_DESTINATION_ADDRESS) @MapperInfo(C) String toAddress, String data).

public void receiveData(@ContextKey(EdrConst ants.FIELD_ORIGINATING_ADDRESS) String fromAddress, @ContextKey(EdrConstants.FIELD_DESTINATION_ADDRESS) @MapperInfo(C) String toAddress, String data)

From NetworkCallback.

The network node invokes this method when a network-triggered events occurs.

The parameter:

  • fromAddress is the address representing the originator of the request

  • toAddress is the address representing the destination of the request.

  • data contains the payload of the request.

The method is annotated with @Edr, so the method is woven with annotation EDR.

fromAddress and toAddress are annotated with @ContextKey, which means that they will be put it the current RequestContext under the key specified by the string in the argument of the annotation. As illustrated in Example 6-3, they are put in the RequestContext under the keys EdrConstants.FIELD_ORIGINATING_ADDRESS and EdrConstants.FIELD_DESTINATION_ADDRESS, respectively. These keys ensure that the values will be available in all subsequent EDRs emitted during this request.

toAddress is also annotated with @MapperInfo, which means that the value should be registered in ContextMapperInfo under the key specified by the string in the argument of the annotation. In Example 6-3, the key is C.

Example 6-3 Annotation of network-triggered method

...
@Edr
public void receiveData(
   @ContextKey(EdrConstants.FIELD_ORIGINATING_ADDRESS)
   String fromAddress,
   @ContextKey(EdrConstants.FIELD_DESTINATION_ADDRESS) 
   @MapperInfo(C)
   String toAddress,
  String data) {
...

NotificationManagerPluginNorth

Class.

Implements NotificationManagerPlugin.

public StartEventNotificationResponse startEventNotification(@ContextTranslate(ContextTranslatorImpl.class) StartEventNotification parameters)

Starts a subscription for notifications on network-triggered requests.

The method is a Java representation of the application-facing operation startEventNotification, defined in the WSDL that was used as input for the code generation.

As illustrated in Example 6-4, the method is annotated with @EDR, and the parameter is put in the RequestContext using the annotation @ContextTranslate, since the parameter is a complex data type that requires traversal in order to resolve the simple data types. When using this annotation, the class is provided as an ID.

Example 6-4 Annotations for startEventNotification

...
@Edr
public StartEventNotificationResponse startEventNotification(
@ContextTranslate(ContextTranslatorImpl.class) StartEventNotification parameters)
throws ServiceException {
...

In the operation, these parameters are included:

<xsd:element name="correlator" type="xsd:string"/>
<xsd:element name="endPoint" type="xsd:string"/>
<xsd:element name="address" type="xsd:anyURI"/>

The values of correlator and endPoint are put in NotificationData.

The application instance ID for the originator of the request, the application that uses the Web Services interface, is 5Vʩresolved from the RequestContextManager and put in NotificationData.

Using StoreHelper, NotificationData is put in the StorageService.

public StopEventNotificationResponse stopEventNotification(@ContextTranslate(ContextTranslatorImpl.class) StopEventNotification parameters)stopEventNotification(StopEventNotification)

Ends a previously started subscription for notifications on network-triggered requests.

The method is a Java representation of the application-facing operation stoptEventNotification, defined in the WSDL that was used as input for the code generation.

The method is annotated in a similar manner to public StartEventNotificationResponse startEventNotification(@ContextTranslate(ContextTranslatorImpl.class) StartEventNotification parameters).

Using StoreHelper, NotificationData corresponding to the correlator provided in the requests is removed from the StorageService.

SendDataPluginNorth

Class.

Implements SendDataPlugin.

public void setPluginToNetworkAdapter(SendDataPluginToNetworkAdapter adapter)

Sets SendDataPluginToNetworkAdapter to be used for application-initiated requests.

public SendDataResponse sendData(@ContextTranslate(ContextTranslatorImpl.class) SendData parameters)

Sends data to the network

The method is a Java representation of the application-facing operation sendData, defined in the WSDL that was used as input for the code generation.

The method is annotated in a similar manner to public StartEventNotificationResponse startEventNotification(@ContextTranslate(ContextTranslatorImpl.class) StartEventNotification parameters).

Passes on the request to SendDataPluginToNetworkAdapter.

If there is a need to retry the request, this method re-throws a PluginRetryException, so the request can be retried by the service interceptors.

SendDataPluginSouth

Class.

implements PluginSouth.

public SendDataPluginSouth()

Constructor.

Empty.

public void send(NetworkProxy proxy, String address, String data)

Sends data to the network node.

Passes on the request to sendDataToNetwork using the NetworkProxy.

The method is annotated with @Edr.

public String resolveAppInstanceGroupdId(ContextMapperInfo info)

Empty implementation that returns null. This method has meaning, and is used, only in network-triggered requests.

The application instance ID is already known in the RequestContext, since the class only handles application-initiated requests.

public void prepareRequestContext(RequestContext ctx, ContextMapperInfo info))

From interface com.bea.wlcp.wlng.api.plugin.PluginSouth

Gives the plug-in an opportunity to add additional values to the RequestContext before the application-initiated requests is passed on to public void send(NetworkProxy proxy, String address, String data).

Empty in this example. Normally all data about the request should be known at this point, so no additional data needs to be set.

SendDataPluginToNetworkAdapter

Interface.

Defines the interface between the plug-in and the network node for application-initiated requests.

SendDataPluginToNetworkAdapterImpl

Class.

public SendDataPluginToNetworkAdapterImpl()

Constructor.

Instantiates SendDataPluginSouth.

public void setNetworkProxy(NetworkProxy networkProxy)

Sets the NetworkProxy object. This is a remote object in the network node.

public void send(String address, String data)

Hands off the request to the network node using SendDataPluginSouth.

FilterImpl

Class.

Implements interface com.bea.wlcp.wlng.api.storage.filter.Filter.

This is the query filter used for the named store NotificationData.

Evaluates whether an entry in the named store NotificationData matches the filter. The filter is defined in XML, see "Store configuration".

public boolean matches(Object value)

Must be invoked after public void setParameters(Serializable... parameters).

Returns true if the value provided in Object matches parameters[0], as set in public void setParameters(Serializable... parameters).

public void setParameters(Serializable... parameters)

Sets the query parameters for the filter.

The parameters are ordered as provided to the StoreQuery and it is the responsibility of the implementation to handle them in this order.

NotificationData

Class.

Implements Serializable

The data structure representing a notification. The notification is registered and de-registered by applications using the application-facing Web Services interfaces and represents a subscription for network-triggered events. The NotificationData is used for:

  • Matching a network-triggered event with a subscription started by an application. The match is usually based on the destination address in the requests from the network.

  • Resolving information on which application instance created the subscription, and the endpoint on which the application expects to be notified of the event.

NotificationData is stored using the storage service, normally using the invalidating cache storage provider for cluster-wide access and high performance.

Each of the attributes to be stored must have a corresponding set method and get method.

The class must be serializable.

public NotificationData()

Constructor.

Empty.

StoreHelper

Class.

Singleton.

Helper class for storing NotificationData using the StorageService.

public static StoreHelper getInstance()

Returns the single instance of StoreHelper.

public void addNotificationData(URI address, NotificationData notificationData)

Stores the NotificationData using the Storage Service.

The named store is retrieved using private Store<String, NotificationData> getStore() .

The NotificationData is put into the named store. The address is the key and the object is the value.

The named store is released. This should always be done in a finally{...} block.

public void removeNotificationData(String correlator)

Removes NotificationData using the StorageService.

The named store is retrieved using private Store<String, NotificationData> getStore() .

A Set of matching entries are returned using private Set<Map.Entry<String, NotificationData>> getEntries(String correlator, Store<String, NotificationData> store).

If there are matching entries, all are removed using private void removeEntries(Set<Map.Entry<String, NotificationData>> set, Store<String, NotificationData> store).

The named store is released. This should always be done in a finally{...} block.

public NotificationData getNotificationData(String destinationAddress)

Gets NotificationData using the StorageService

The named store is retrieved using private Store<String, NotificationData> getStore() .

The NotificationData that is keyed on destinationAddress is fetched from the store.

The named store is released. This should always be done in a finally{...} block.

private Store<String, NotificationData> getStore()

Gets a named stored from com.bea.wlcp.wlng.api.storage.StoreFactory.

private Set<Map.Entry<String, NotificationData>> getEntries(String correlator, Store<String, NotificationData> store)

Gets a java.util.Set of entries of NotificationData from a named store using the StorageService. The query being used is a named query, com.bea.wlcp.wlng.plugin.example.netex.Query, defined in wlng-cachestore-config-extensions.xml.

private void removeEntries(Set<Map.Entry<String, NotificationData>> set, Store<String, NotificationData> store)

Removes a java.util.Set of entries of NotificationData using the StorageService. The NotificationData is removed from a named store.

ExamplePluginInstance

Class.

Implements com.bea.wlcp.wlng.api.plugin.ManagedPluginInstance.

Defines the life-cycle for a plug-in instance.

Also holds the data that is specific to the plug-in instance.

public ExamplePluginInstance(String id, ExamplePluginService parent)

Constructor.

The id is the plug-in instance ID, and the parent is the Plug-in service the of which the plug-in is an instance.

public String getId()

The plug-in instance returns the ID that it was instantiated with.

public void activate()

Called when the plug-in instance is activated, so the plug-in:

  • Instantiates the traffic interfaces.

  • Registers the traffic interfaces with the Plug-in Manager.

  • Register callbacks between the interfaces.

  • Initiates the Store.

  • Instantiates and registers the MBean interface.

If the plug-in service is in state ACTIVE (RUNNING), public void handleResuming() is called.

public void handleResuming()

Connects to the network node.

If the connection fails, a timer is triggered to retry the connection setup.

public void deactivate()

Called when the plug-in instance is deactivated.

If the plug-in service is in state ACTIVE (RUNNING), public void handleSuspending() is called.

The call-back is unregistered from the network node.

The MBean is unregistered.

public void handleSuspending()

If existing, the timer associated with connection setup is cancelled.

The plug-in disconnects from the network node.

public List<PluginInterfaceHolder> getNorthInterfaces()/ public List<PluginInterfaceHolder> getSouthInterfaces()

Returns a list of the interfaces.

public boolean isConnected()

Returns true if there is a connection to the network node, that is if the plug-in instance is ready to accept traffic.

public int customMatch(RequestInfo requestInfo)

Checks the operation that is about to be invoked on the plug-in instance by introspection of the RequestInfo associated with request.

If the operation is StopEventNotification and the correlator provided is cached using the Storage service, the request must be sent to all instances of the plug-in, since the request depends on an earlier request (startNotification). MATCH_REQUIRED is returned.

If the operation is any other than StopEventNotification, the request is unrelated to any previous operation and any plug-in instance can be used. MATCH_OPTIONAL is returned.

private void rethrowDeploymentException(Exception e)

Re-throws a DeploymentException given another exception. The exception is wrapped in a DeploymentException.

public ConfigurationStoreHandler getConfigurationStore()

Gets the ConfigurationStoreHandler.

ExamplePluginService

Class.

Implements com.bea.wlcp.wlng.api.plugin.ManagedPluginService.

Defines the life-cycle for a plug-in service.

Also holds the data that is specific for the plug-in instance.

public ExamplePluginService()

Constructor.

Empty.

public TimerManager getTimerManager()

Gets a handle to the TimerManager.

public boolean isRunning()

Checks if the plug-in service is in RUNNING state.

public String[] getSupportedSchemes()

Returns an array of supported address schemes.

public void init(String id, PluginPool pool)

Initializes the plug-in service with the ID and a reference to the plug-in pool.

The PluginPool holds all plug-in instances.

public void doStarted()

Instantiates a TimerManager to be used.

public void doStopped()/public void doActivated()/public void doDeactivated()

Empty implementation. Nothing to do here.

public void handleResuming()

Iterates over all plug-in instances using the PluginInstancePool and calls public void handleResuming() on ExamplePluginInstance

public void handleSuspending(CompletionBarrier barrier)

The nature of the example network protocol is that is does not have connections to maintain. Because it is possible to treat this event as in public void handleForceSuspending () the request is passed on to that method.

public void handleForceSuspending ()

When the plug-in service is being forcefully suspended, the plug-in instances are disconnected from the network node immediately, without waiting for any in-flight requests to complete.

This is done by iterating over the PluginInstancePool and calling public void handleSuspending() on ExamplePluginInstance

public ServiceType getServiceType()

Returns the service type, com.acompany.example.servicetype.ExampleServiceType.type. The type is automatically generated when the service EJB is generated.

public String getNetworkProtocol()

Returns the network protocol. A string used for informational purposes.

public ManagedPluginInstance createInstance(String pluginInstanceId)

Creates a new instance of the plug-in service. The ID for the new plug-in is supplied together with the object that created the instance (this).

Store configuration

The store configuration file wlng-cachestore-config-extensions.xml defines:

  • Which data to store

  • The get and set methods to retrieve and store the data

  • The database table structure use to store the data

  • Queries to perform on the store

Example 6-5 shows the store configuration file for the example Communication Service.

The configuration file defines:

  • The store type ID: since the store type ID is prefixed with wlng.db.wt (wlng.db.wt.es_example), the store is a write-through cache.

  • The table to be used: es_example

  • The identifier for the store is a combination of the type of the key column (java.lang.String) and the type of the value column (com.acompany.plugin.example.netex.store.NotificationData). These are used when the store is retrieved from the StoreFactory, see "private Store<String, NotificationData> getStore() "

  • The key column: address

  • The value columns for the key:

    • correlator

    • endpoint

    • appinstance

  • The get and set methods for the value columns.

  • The query to use when doing lookups in the store.

The configuration file, together with any non-complex data types must be packaged into a JAR and put in the directory Domain_Home/config/store_schema so it can be accessed by the storage service.

Example 6-5 Store configuration for the example Communication Service

<?xml version="1.0" encoding="UTF-8"?>
<store-config xmlns="http://www.bea.com/ns/wlng/30"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://www.bea.com/ns/wlng/30 wlng-cachestore-config.xsd">

  <db_table name="es_example">
    <key_column name="address" data_type="VARCHAR(100)"/>
    <value_column name="correlator" data_type="VARCHAR(100)">
      <methods>
        <get_method name="getCorrelator"/>
        <set_method name="setCorrelator"/>
      </methods>
    </value_column>
    <value_column name="endpoint" data_type="VARCHAR(255)">
      <methods>
        <get_method name="getEndPoint"/>
        <set_method name="setEndPoint"/>
      </methods>
    </value_column>
    <value_column name="appinstance" data_type="VARCHAR(100)">
      <methods>
        <get_method name="getApplicationInstance"/>
        <set_method name="setApplicationInstance"/>
      </methods>
    </value_column>
  </db_table>

  <store type_id="wlng.db.wt.es_example" db_table_name="es_example">
    <identifier>
      <classes key-class="java.lang.String" value-class="com.acompany.plugin.example.netex.store.NotificationData"/>
    </identifier>
    <index>
      <get_method name="address"/>
    </index>
  </store>

  <query name="com.bea.wlcp.wlng.plugin.example.netex.Query">
    <sql><![CDATA[SELECT * FROM es_example WHERE correlator LIKE ?]]></sql>
  </query>

</store-config>

SLA Example

Below is an example SLA for the example Communication Service. There are examples of service provider group and application group SLAs in: Middleware_Home/ocsg_pds_5.1/pte/resource/sla.

Example 6-6 Example SLA for the example Communication Service

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Sla xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" applicationGroupID="default_app_group" xsi:noNamespaceSchemaLocation="app_sla_file.xsd">
    <serviceContract>
        <startDate>2008-04-17</startDate>
        <endDate>2099-04-17</endDate>
        <scs>com.acompany.example.plugin.SendDataPlugin</scs>
        <contract/>
    </serviceContract>
    <serviceContract>
        <startDate>2008-04-17</startDate>
        <endDate>2099-04-17</endDate>
        <scs>com.acompany.example.plugin.NotificationManagerPlugin</scs>
        <contract/>
    </serviceContract>
    <serviceContract>
        <startDate>2008-04-17</startDate>
        <endDate>2099-04-17</endDate>
        <scs>com.acompany.example.callback.NotificationCallback</scs>
        <contract/>
    </serviceContract>
</Sla>
PKLDV5VPK DOEBPS/pds_interceptors.htm Service Interceptors

10 Service Interceptors

This chapter provides a high-level overview of service interceptors (interceptors) and describes both the standard interceptors that ship with Oracle Communications Services Gatekeeper (Services Gatekeeper) and the process of developing your own custom interceptors and deploying them in Services Gatekeeper.

About Service Interceptors in Services Gatekeeper

Service interceptors provide a mechanism to intercept and manipulate a request flowing through any arbitrary communication service in Services Gatekeeper. (See "Understanding Communication Services" for a description of communication services.) Additionally, service interceptors supply an easy way to modify the flow for a request and simplify the routing mechanism for plug-ins associated with a request.

Often, interceptors may make a decision to permit, deny, or stay neutral to a particular request. Some typical use cases for service interceptors are to:

  • Deny a request if the user does not subscribe to a particular service in the application layer.

  • Deny a request if the personal identification number is not valid.

  • Verify that a request's parameters are valid.

  • Perform argument manipulation (such as aliasing).

Service Interceptors in Services Gatekeeper

Each interceptor in Services Gatekeeper is identified by the class name of the entry point of the interceptor, that is, the class that implements the Service Provider Interface (SPI) Interceptor.

For example, the EnforceBlacklistedMethodFromSLA interceptor is identified by com.bea.wlcp.wlng.interceptor.EnforceBlacklistedMethodFromSLA. (See the entry for EnforceBlacklistedMethodFromSLA in Example 10-1.)

A set of standard interceptors are provided with Services Gatekeeper. Some interceptors are required, while others provide extra functionality. In addition, Services Gatekeeper enables you to develop and deploy custom interceptors. The invocation order of the interceptors currently active in Services Gatekeeper is defined in an XML-based configuration file, described later in this chapter.

Request Flow

Figure 10-1 illustrates where interceptors are triggered, both for application-initiated and network-triggered requests.

Figure 10-1 Interceptors and Request Flow

Description of Figure 10-1 follows

Application-initiated requests proceed south in the following order:

  1. The requests starts in the web service (access tier).

  2. The web services converts the request to the Service EJB in the network tier.

  3. The Service EJB sends the request to the plug-in manager.

  4. The plug-in manager sends it to the interceptor stack.

  5. From the interceptor stack the request is sent do the network protocol plug-in.

  6. The network protocol sends the request to the network node.

Network triggered requests proceed north in the following order:

  1. The request starts in the network tier.

  2. From the network tier, the request goes to the network protocol plug-in.

  3. From the network plug-in it goes to the interceptor stack.

  4. From the interceptor stack it goes to the service callback client.

  5. From the service callback client it goes to the service callback EJB (access tier).

  6. Finally the request arrives at the application.

Plug-in Manager

As Figure 10-1 shows, the Plug-in Manager is responsible for calling the first interceptor in the chain of interceptors as defined in the interceptor configuration file, described later in this chapter.

For application-initiated requests, the Plug-in Manager is called automatically by the service Enterprise Java Beans (EJB) for the application-facing interface. For network-triggered requests, the Plug-in Manager is called by an Aspect that is woven prior to calling the service callback EJB for the application-facing interface. For more information on Aspect, see "About Aspects and Annotations".

The interceptor chain is invoked at the point-cut that is a Java representation of the application-facing interface. Some application-initiated requests are not necessarily propagated to the network, and some network-triggered requests are not necessarily forwarded to the service callback client.

Request Context Data Used to Handle Request Flow

Interceptors in Services Gatekeeper have access to context data associated with each request and use that data to arrive at the appropriate decisions to forward, return or abort the request.

The actual data that is available to an interceptor depends on the context of the request. In general, the application-facing interface defines the data that is available. This data includes the following:

  • The RequestContext for the request, including:

    • Service provider account ID

    • Application account ID

    • Application User ID

    • Transaction ID

    • Session ID

    • A Java Map containing arbitrary request-specific data

    For information on RequestContext, see "Interface: RequestContext".

  • The type of plug-in targeted by the request for (application-initiated requests)

  • The type of object targeted by the request (network-triggered requests)

  • The method targeted by the request

  • The arguments that will be used in the method targeted by the request

  • The set of RequestInfo available to the request, including:

    • method name

    • arguments to the method

    • plug-in type

    For information on RequestInfo, see "Class: RequestInfo".

  • A list of plug-ins that matches the specified RequestInfo

  • The interception point that indicates whether the request is network-triggered or application-initiated.

Example 10-6 shows the method used to retrieve data located in RequestContext.

Data Available for Modification

Custom interceptors that you develop can be designed to access and modify certain elements of the data in RequestContext.

Interceptors can set the following data in a request:

  • In the RequestContext:

    • Session ID

    • Transaction ID

  • A list of plug-ins that matches the specified RequestInfo. For information on RequestInfo, see "Class: RequestInfo".

  • Arguments to the method targeted by the request

Specifying a Destination for the Request

Each interceptor is responsible for deciding whether to proceed with the request flow (by forwarding the request down the chain of interceptors) or to break the flow. The interceptor may break the request flow in one of two ways, either by returning the request or by aborting it.

Figure 10-2 Decisions and the Interceptor Chain

Description of Figure 10-2 follows

Decision to Proceed with the Request Flow

The decision to proceed with the request flow translates to continuing down the invocation chain by calling the next interceptor in the chain.

The request is passed on to the next interceptor in the chain and ultimately to the network protocol plug-in or to the application. When the request is returned from either one of these points in the flow, the return path traverses the interceptors that were used in the calling path. Doing so makes it possible for interceptors to manipulate the request on its return path and ultimately return it to the originator of the request, the application or the network node.

Decision to Return the Request

The decision to return a request may be arrived at because the needs of the request may have been fulfilled and, therefore, there maybe no need to call the plug-in or the application. The remaining and final step is simply to return the request.

In such a scenario, the request is rolled back through the previous interceptors using a regular return statement. Doing so makes it possible for the previous interceptors to manipulate the request in the rollback path which ends with the originator of the request, the application or the network node.

Decision to Abort the Request

The decision to abort a request is arrived at when there is a violation. For example, a parameter in the request is out of bounds, or certain usage policies have been violated by this request. Such events lead to a PluginDenyException being thrown.

When the decision is made to abort a request, the interceptor breaks the chain for that request. The request is rolled back through each interceptor's exception catch-block rather than being returned in a regular mode.

  • For application-initiated requests, the exception is reported back to the application. It is possible to reuse the exception catalogue to map the exception thrown by the interceptor to an exception defined by the application-facing interface. For such a scenario, interceptors should use com.bea.wlcp.wlng.api.plugin.DenyPluginException.

  • For network-triggered requests, it is the responsibility of the plug-in to act on the thrown exception.

Invoking Next Service Interceptor to Handle the Request

Each interceptor is responsible for calling the next interceptor in the chain. This means that:

  • For an application-initiated request, the interceptors can change and add request-specific data. This data is then propagated to the next interceptor and ultimately to the network protocol plug-in. When the request returns from the plug-in, the data can be changed as the request returns through the invocation chain.

  • For network-triggered request, the interceptors can change and add request-specific data. This data is then propagated to the next interceptor and ultimately to the application. When the request returns from the application, the data can be changed as the request returns through the invocation chain.

This is useful for aliasing of data, where the interceptor anonymizes request data such as telephone numbers so that an application is not aware of the actual telephone number of the subscriber.

Last Service Interceptor in the Chain

For application-initiated requests, the last interceptor in the chain is responsible for calling the plug-in. The standard interceptor InvokePlugin performs this function. In Example 10-1, the example interceptor configuration file lists InvokePlugIn as the last entry for the tag called <position name="MT_NORTH">.

For network-triggered requests, the last interceptor in the chain is responsible for calling the callback service EJB, which calls the application. The standard interceptor InvokeApplication does this. In Example 10-2, the example interceptor configuration file lists InvokeApplication as the last entry for the tag called <position name="MO_NORTH">.

Standard Interceptors

Standard interceptors are service interceptors that are provided by Services Gatekeeper.

The standard interceptors in Services Gatekeeper can be:

  • Enabled: The interceptors that are enabled in Services Gatekeeper are listed in the config.xml interface configuration file provided with the installation. See "Config.xml File".

  • Disabled: A few interceptors are not yet enabled in the default set of interceptors enabled in Services Gatekeeper. If necessary, you can enable these interceptors by updating config.xml. See the steps in "Updating the Config.xml File".

  • Internal: Any interceptor with a $ in its name is internal to Services Gatekeeper. Such an interceptor should not be used, changed or deleted.

Standard Interceptors in Services Gatekeeper

Table 10-1 provides a description of the standard interceptors that are available in Services Gatekeeper and lists any dependencies enforced by Services Gatekeeper.

Table 10-1 Standard Interceptors Provided by Services Gatekeeper

InterceptorDescriptionDependency Enforced

CheckMethodParametersFromSLA

Enabled at installation time.

Checks and enforces the specifications in the service provider group and application group SLAs with respect to the request parameters.

Is related to the SLA <parameterName> and <parameterValue> elements in <methodParameters>.

See the discussion on service provider groups and service level agreements in Accounts and SLA Guide.

CheckMethodParametersFromSLA must be invoked AFTER invoking:

  • FindAndValidateSLAContract

CreatePluginList

Enabled at installation time.

Creates a list of plug-ins that are capable of handling the given request.

Populates the RequestInfo object.

See "Class: RequestInfo".

CreatePluginList must be invoked BEFORE you invoke:

  • EnforceNodeBudget

  • EnforceSubscriberBudget

  • FilterPluginListUsingCustomMatch

  • RemoveInactivePlugin

  • RemoveInvalidRoute

  • RemoveOptional

  • RetryPlugin

  • RoundRobinPluginList

CreatePolicyData

Enabled at installation time.

Creates the policy request data object needed by other interceptors.

CreatePolicyData must be invoked BEFORE you invoke:

  • CheckMethodParametersFromSLA

  • RemoveInvalidRoute

EnforceApplicationState

Enabled at installation time.

Enforces the application state. Verifies that the application with which the request is related has established a session with Services Gatekeeper.

None

EnforceBlacklistedMethodFromSLA

Enabled at installation time.

Enforces the method blacklist as specified in the service provider group and application group SLAs.

Is related to the SLA <blacklistedMethod> element in the <methodAccess> element.

See the discussion on service provider groups and service level agreements in Accounts and SLA Guide.

EnforceBlacklistedMethodFromSLA must be invoked AFTER you invoke FindAndValidateSLAContract.

EnforceComposedBudget$1

Internal. Do not use.

Not Applicable

EnforceComposedBudget$GetAppSLA

Internal. Do not use.

Not Applicable

EnforceComposedBudget$GetGeoAppSLA

Internal. Do not use.

Not Applicable

EnforceComposedBudget$GetGeoSpSLA

Internal. Do not use.

Not Applicable

EnforceComposedBudget$GetSLA

Internal. Do not use.

Not Applicable

EnforceComposedBudget$GetSpSLA

Internal. Do not use.

Not Applicable

EnforceComposedBudget

Enabled at installation time.

Enforces all settings on composed service contract in both southbound and northbound traffic.

A Composed Service contract supports services implemented through the composition of OCSG communication services (for example, SMS+Terminal Location+....).

Foe more on Composed Services, see Accounts and SLA Guide.

None

EnforceNodeBudget

Enabled at installation time.

Enforces budgets related to the global and service provider node SLAs.

EnforceNodeBudget must be invoked AFTER you invoke CreatePluginList.

EnforceSpAppBudget

Enabled at installation time.

Enforces the budget defined in the service provider group SLA and application group SLA. Is related to the SLA <rate> element in <methodRestrictions>.

See the discussion on service provider groups and service level agreements in Accounts and SLA Guide.

EnforceSpAppBudget must be invoked BEFORE you invoke EnforceNodeBudget.

EnforceSubscriberBudget

Enabled at installation time.

Enforces budgets related to the Subscriber SLAs.

EnforceSubscriberBudget must be invoked AFTER you invoke CreatePluginList.

FilterPluginListUsingCustomMatch

Enabled at installation time.

Invokes the custom match method of each plug-in the current plug-in list. The custom match method either removes the plug-in from the current plug-in list or marks it as required.

FilterPluginListUsingCustomMatch must be invoked AFTER you invoke CreatePluginList.

FindAndValidateSLAContract

Enabled at installation time.

Enforces the existence of application level and service provider level SLAs for the given request. It also verifies that the dates given in the SLA are current.

See the discussion on service provider groups and service level agreements in Accounts and SLA Guide.

FindAndValidateSLAContract must be invoked BEFORE you invoke InjectValuesInRequestContextFromSLA.

InjectValuesInRequestContextFromSLA

Enabled at installation time.

Adds any optional request context attribute as specified in the service provider group and application group SLAs.

Is related to the SLA <attributeName>, <attributeValue>, and <contextAttribute> elements in <requestContext>.

See the discussion on service provider groups and service level agreements in Accounts and SLA Guide.

InjectValuesInRequestContextFromSLA must be invoked BEFORE you invoke:

  • FindAndValidateSLAContract

  • ResultFilter

InjectXParametersFromRequestContext

Enabled at installation time.

Takes tunnelled parameters from the RequestContext and puts them in the the SOAP header of either a request to an application or a response to a request from an application.

None

InvokeApplication

Enabled at installation time.

Invokes the Application via the service callback EJB. This should be the last interceptor for an network-triggered (mobile originated) request.

None

InvokeNetworkNode

Enabled at installation time.

Invokes the Network Node via the service callback EJB. This is the only interceptor for an network-triggered (mobile terminated) request.

None

InvokePlugin

Enabled at installation time.

Invokes the plug-in(s). This should be the last interceptor for an application-initiated (mobile terminated) request.

InvokePlugin must be invoked AFTER you invoke CreatePluginList.

InvokeServiceCorrelation

Enabled at installation time.

Invokes the service correlation feature.

See "Service Correlation".

None

NativeSMPPAddressRouting

Not enabled, by default

If enabled, ensures that, for networks having multiple SMSCs, SMS messages sent to the same address will be sent through the same plug-in instance.

If NativeSMPPAddressRouting is enabled, it must be invoked BEFORE you invoke RoundRobinPluginList

NativeUCPAddressRouting

Not enabled, by default

If enabled, ensures that messages sent to the same address are sent to the same SMSC.

If NativeUCPAddressRouting is enabled, it must be invoked BEFORE you invoke RoundRobinPluginList

RemoveInactivePlugin

Enabled at installation time.

Removes any plug-in that is not active from the current plug-in list.

RemoveInactivePlugin must be invoked AFTER you invoke CreatePluginList.

RemoveInvalidRoute

Enabled at installation time.

Enforces the plug-in routing logic.

RemoveInvalidRoute must be invoked AFTER you invoke:

  • CreatePluginList

  • CreatePolicyData

RemoveOptional

Enabled at installation time.

Removes any plug-in that is marked as optional if there is a at least one marked as required in the current plug-in list.

RemoveOptional must be invoked AFTER you invoke CreatePluginList.

ResultFilter

Enabled at installation time.

Applies result filters as specified in the service provider group and application group SLAs.

Relates to the SLA <resultRestriction> element.

See the discussion on service provider groups and service level agreements in Accounts and SLA Guide.

ResultFilter must be invoked AFTER you invoke InjectValuesInRequestContextFromSLA.

RetryPlugin

Enabled at installation time.

Performs retries of request. See "Retry Functionality for plug-ins".

RetryPlugin must be invoked AFTER you invoke CreatePluginList.

RoundRobinPluginList

Enabled at installation time.

Performs a round-robin of the list of available plug-ins. This is not a strict round-robin, but a function of the number of plug-ins that match the request and the number of destination or target addresses in the request. If these parameters are consistent, a true round-robin is performed.

RoundRobinPluginList must be invoked AFTER you invoke CreatePluginList.

ValidateRequestUsingRequestFactory

Enabled at installation time.

Validates the request using the RequestFactory corresponding to the type of plug-in the request is intended for. For a description of RequestFactory, see "Class: RequestFactory".

None


Location

All the standard interceptors can be found packaged in Middleware_Home/ocsg_5.1/applications/interceptors.ear. (See Table 10-3.)

Retry Functionality for plug-ins

When a RetryPluginExeption exception is thrown during the handling of a request, a retry is attempted among the plug-ins that were chosen based on the data provided in the request. Retries are performed among the plug-ins in the same Services Gatekeeper instance only.

When a plug-in throws a RetryPluginExeption, the RetryPlugin interceptor is triggered. The RetryPlugin interceptor captures the RetryPluginExeption, removes the plug-in that threw the exception from the list of chosen plug-ins, and calls the next interceptor in the chain.

The different decision scenarios are described below in Table 10-2.

Table 10-2 Retry Plug-in Interceptor Scenarios

Objects with which the RequestInfo objects in the RequestContext are associatedAction(s) Taken by RetryPlugin interceptor

PluginHolder objects that are marked as optional

Remove the failed RequestInfo from RequestContext and invoke the next interceptor in the chain.

PluginHolder objects that are marked as required

Treat the request itself as failed. No retry is performed, and an exception is thrown.


Note that the Subscriber Profile/LDAPv3 is the only (standard) plug-in that throws the RetryPluginException.

Custom plug-ins can use the infrastructure for retries as provided by the RetryPlugin interceptor. This exception should be thrown if the communication with the underlying network node fails, or if an unexpected error is reported back from the plug-in.

Interceptors.ear File

The interceptors.ear file is located at Middleware_Home/ocsg_5.1/applications.

File Contents

Table 10-3 describes the contents of the top-level of the multi-level folder in the interceptors.ear file.

Table 10-3 Contents of interceptor.ear File

Folder Name/File NameContent

APP-INF

A multi-level folder which contains information about the applications.

  • classes: A multi-level folder where the sub-folder /APP-INF/classes/com/bea/wlcp/wlng/interceptor contains the standard interceptor classes.

  • config.xml: Interceptor configuration file. See "Config.xml File".

  • config.xsd: Schema for config.xml.

dummy.war

Empty WAR file. Present in order to deploy the interceptors.

Do not remove or change this file.

META-INF

This folder contains the following files:

  • application.xml: Deployment descriptor.

  • MANIFEST.MF: Manifest file for the interceptor infrastructure.

  • weblogic-application.xml: WebLogic extensions to application.xml.

Do not edit or remove the contents of META-INF.

WEB-INF

For internal use.

Do not edit or remove its contents.


Maintaining Interceptor Data