/* * Copyright 2000-2013 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.vaadin.data; import java.io.Serializable; import java.util.Collection; import java.util.List; import com.vaadin.data.util.filter.SimpleStringFilter; import com.vaadin.data.util.filter.UnsupportedFilterException; /** *
* A specialized set of identified Items. Basically the Container is a set of * {@link Item}s, but it imposes certain constraints on its contents. These * constraints state the following: *
* *
* The Container can be visualized as a representation of a relational database
* table. Each Item in the Container represents a row in the table, and all
* cells in a column (identified by a Property ID) have the same data type. Note
* that as with the cells in a database table, no Property in a Container may be
* empty, though they may contain null
values.
*
* Note that though uniquely identified, the Items in a Container are not * necessarily {@link Container.Ordered ordered} or {@link Container.Indexed * indexed}. *
* ** Containers can derive Item ID's from the item properties or use other, * container specific or user specified identifiers. *
* ** If a container is {@link Filterable filtered} or {@link Sortable sorted}, * most of the the methods of the container interface and its subinterfaces * (container size, {@link #containsId(Object)}, iteration and indices etc.) * relate to the filtered and sorted view, not to the full container contents. * See individual method javadoc for exceptions to this (adding and removing * items). *
* ** *
* ** The Container interface is split to several subinterfaces so that a class can * implement only the ones it needs. *
* * @author Vaadin Ltd * @since 3.0 */ public interface Container extends Serializable { /** * Gets the {@link Item} with the given Item ID from the Container. If the * Container does not contain the requested Item,null
is
* returned.
*
* Containers should not return Items that are filtered out.
*
* @param itemId
* ID of the {@link Item} to retrieve
* @return the {@link Item} with the given ID or null
if the
* Item is not found in the Container
*/
public Item getItem(Object itemId);
/**
* Gets the ID's of all Properties stored in the Container. The ID's cannot
* be modified through the returned collection.
*
* @return unmodifiable collection of Property IDs
*/
public Collection> getContainerPropertyIds();
/**
* Gets the ID's of all visible (after filtering and sorting) Items stored
* in the Container. The ID's cannot be modified through the returned
* collection.
*
* If the container is {@link Ordered}, the collection returned by this
* method should follow that order. If the container is {@link Sortable},
* the items should be in the sorted order.
*
* Calling this method for large lazy containers can be an expensive
* operation and should be avoided when practical.
*
* @return unmodifiable collection of Item IDs
*/
public Collection> getItemIds();
/**
* Gets the Property identified by the given itemId and propertyId from the
* Container. If the Container does not contain the item or it is filtered
* out, or the Container does not have the Property, null
is
* returned.
*
* @param itemId
* ID of the visible Item which contains the Property
* @param propertyId
* ID of the Property to retrieve
* @return Property with the given ID or null
*/
public Property getContainerProperty(Object itemId, Object propertyId);
/**
* Gets the data type of all Properties identified by the given Property ID.
*
* @param propertyId
* ID identifying the Properties
* @return data type of the Properties
*/
public Class> getType(Object propertyId);
/**
* Gets the number of visible Items in the Container.
*
* Filtering can hide items so that they will not be visible through the
* container API.
*
* @return number of Items in the Container
*/
public int size();
/**
* Tests if the Container contains the specified Item.
*
* Filtering can hide items so that they will not be visible through the
* container API, and this method should respect visibility of items (i.e.
* only indicate visible items as being in the container) if feasible for
* the container.
*
* @param itemId
* ID the of Item to be tested
* @return boolean indicating if the Container holds the specified Item
*/
public boolean containsId(Object itemId);
/**
* Creates a new Item with the given ID in the Container.
*
*
* The new Item is returned, and it is ready to have its Properties
* modified. Returns null
if the operation fails or the
* Container already contains a Item with the given ID.
*
* This functionality is optional. *
* * @param itemId * ID of the Item to be created * @return Created new Item, ornull
in case of a failure
* @throws UnsupportedOperationException
* if adding an item with an explicit item ID is not supported
* by the container
*/
public Item addItem(Object itemId) throws UnsupportedOperationException;
/**
* Creates a new Item into the Container, and assign it an automatic ID.
*
*
* The new ID is returned, or null
if the operation fails.
* After a successful call you can use the {@link #getItem(Object ItemId)
* getItem
}method to fetch the Item.
*
* This functionality is optional. *
* * @return ID of the newly created Item, ornull
in case of a
* failure
* @throws UnsupportedOperationException
* if adding an item without an explicit item ID is not
* supported by the container
*/
public Object addItem() throws UnsupportedOperationException;
/**
* Removes the Item identified by ItemId
from the Container.
*
* * Containers that support filtering should also allow removing an item that * is currently filtered out. *
* ** This functionality is optional. *
* * @param itemId * ID of the Item to remove * @returntrue
if the operation succeeded, false
* if not
* @throws UnsupportedOperationException
* if the container does not support removing individual items
*/
public boolean removeItem(Object itemId)
throws UnsupportedOperationException;
/**
* Adds a new Property to all Items in the Container. The Property ID, data
* type and default value of the new Property are given as parameters.
*
* This functionality is optional.
*
* @param propertyId
* ID of the Property
* @param type
* Data type of the new Property
* @param defaultValue
* The value all created Properties are initialized to
* @return true
if the operation succeeded, false
* if not
* @throws UnsupportedOperationException
* if the container does not support explicitly adding container
* properties
*/
public boolean addContainerProperty(Object propertyId, Class> type,
Object defaultValue) throws UnsupportedOperationException;
/**
* Removes a Property specified by the given Property ID from the Container.
* Note that the Property will be removed from all Items in the Container.
*
* This functionality is optional.
*
* @param propertyId
* ID of the Property to remove
* @return true
if the operation succeeded, false
* if not
* @throws UnsupportedOperationException
* if the container does not support removing container
* properties
*/
public boolean removeContainerProperty(Object propertyId)
throws UnsupportedOperationException;
/**
* Removes all Items from the Container.
*
* * Note that Property ID and type information is preserved. This * functionality is optional. *
* * @returntrue
if the operation succeeded, false
* if not
* @throws UnsupportedOperationException
* if the container does not support removing all items
*/
public boolean removeAllItems() throws UnsupportedOperationException;
/**
* Interface for Container classes whose {@link Item}s can be traversed in
* order.
*
* * If the container is filtered or sorted, the traversal applies to the * filtered and sorted view. *
*
* The addItemAfter()
methods should apply filters to the added
* item after inserting it, possibly hiding it immediately. If the container
* is being sorted, they may add items at the correct sorted position
* instead of the given position. See also {@link Filterable} and
* {@link Sortable} for more information.
*
itemId
. If the given Item is the last or not found in
* the Container, null
is returned.
*
* @param itemId
* ID of a visible Item in the Container
* @return ID of the next visible Item or null
*/
public Object nextItemId(Object itemId);
/**
* Gets the ID of the Item preceding the Item that corresponds to
* itemId
. If the given Item is the first or not found in
* the Container, null
is returned.
*
* @param itemId
* ID of a visible Item in the Container
* @return ID of the previous visible Item or null
*/
public Object prevItemId(Object itemId);
/**
* Gets the ID of the first Item in the Container.
*
* @return ID of the first visible Item in the Container
*/
public Object firstItemId();
/**
* Gets the ID of the last Item in the Container..
*
* @return ID of the last visible Item in the Container
*/
public Object lastItemId();
/**
* Tests if the Item corresponding to the given Item ID is the first
* Item in the Container.
*
* @param itemId
* ID of an Item in the Container
* @return true
if the Item is first visible item in the
* Container, false
if not
*/
public boolean isFirstId(Object itemId);
/**
* Tests if the Item corresponding to the given Item ID is the last Item
* in the Container.
*
* @return true
if the Item is last visible item in the
* Container, false
if not
*/
public boolean isLastId(Object itemId);
/**
* Adds a new item after the given item.
* * Adding an item after null item adds the item as first item of the * ordered container. *
* * @see Ordered Ordered: adding items in filtered or sorted containers * * @param previousItemId * Id of the visible item in ordered container after which to * insert the new item. * @return item id the the created new item or null if the operation * fails. * @throws UnsupportedOperationException * if the operation is not supported by the container */ public Object addItemAfter(Object previousItemId) throws UnsupportedOperationException; /** * Adds a new item after the given item. ** Adding an item after null item adds the item as first item of the * ordered container. *
* * @see Ordered Ordered: adding items in filtered or sorted containers * * @param previousItemId * Id of the visible item in ordered container after which to * insert the new item. * @param newItemId * Id of the new item to be added. * @return new item or null if the operation fails. * @throws UnsupportedOperationException * if the operation is not supported by the container */ public Item addItemAfter(Object previousItemId, Object newItemId) throws UnsupportedOperationException; } /** * Interface for Container classes whose {@link Item}s can be sorted. *
* When an {@link Ordered} or {@link Indexed} container is sorted, all
* relevant operations of these interfaces should only use the filtered and
* sorted contents and the filtered indices to the container. Indices or
* item identifiers in the public API refer to the visible view unless
* otherwise stated. However, the addItem*()
methods may add
* items that will be filtered out after addition or moved to another
* position based on sorting.
*
* How sorting is performed when a {@link Hierarchical} container implements * {@link Sortable} is implementation specific and should be documented in * the implementing class. However, the recommended approach is sorting the * roots and the sets of children of each item separately. *
** Depending on the container type, sorting a container may permanently * change the internal order of items in the container. *
*/ public interface Sortable extends Ordered { /** * Sort method. * * Sorts the container items. * * Sorting a container can irreversibly change the order of its items or * only change the order temporarily, depending on the container. * * @param propertyId * Array of container property IDs, whose values are used to * sort the items in container as primary, secondary, ... * sorting criterion. All of the item IDs must be in the * collection returned by * {@link #getSortableContainerPropertyIds()} * @param ascending * Array of sorting order flags corresponding to each * property ID used in sorting. If this array is shorter than * propertyId array, ascending order is assumed for items * where the order is not specified. Usetrue
to
* sort in ascending order, false
to use
* descending order.
*/
void sort(Object[] propertyId, boolean[] ascending);
/**
* Gets the container property IDs which can be used to sort the items.
*
* @return the IDs of the properties that can be used for sorting the
* container
*/
Collection> getSortableContainerPropertyIds();
}
/**
* Interface for Container classes whose {@link Item}s can be accessed by
* their position in the container.
*
* If the container is filtered or sorted, all indices refer to the filtered
* and sorted view. However, the addItemAt()
methods may add
* items that will be filtered out after addition or moved to another
* position based on sorting.
*
true
for the returned index: 0 <= index < size(), or
* index = -1 if there is no visible item with that id in the container.
*
* @param itemId
* ID of an Item in the Container
* @return index of the Item, or -1 if (the filtered and sorted view of)
* the Container does not include the Item
*/
public int indexOfId(Object itemId);
/**
* Get the item id for the item at the position given by
* index
. index
is outside the range of the container. (i.e.
* index < 0 || container.size()-1 < index
)
*
* @param index
* the index of the requested item id
* @return the item id of the item at the given index
*/
public Object getIdByIndex(int index);
/**
* Get numberOfItems
consecutive item ids from the
* container, starting with the item id at startIndex
. numberOfItems
item
* ids, but can contain less if the container has less items than
* required to fulfill the request. The returned list must hence contain
* all of the item ids from the range: startIndex
to
* max(startIndex + (numberOfItems-1), container.size()-1)
. numberOfItems
is < 0 startIndex
is outside the range of the container. (i.e.
* startIndex < 0 || container.size()-1 < startIndex
)
*
* @param startIndex
* the index for the first item which id to include
* @param numberOfItems
* the number of consecutive item ids to get from the given
* start index, must be >= 0
* @return List containing the requested item ids or empty list if
* numberOfItems
== 0; not null
*
* @since 7.0
*/
public List> getItemIds(int startIndex, int numberOfItems);
/**
* Adds a new item at given index (in the filtered view).
* * The indices of the item currently in the given position and all the * following items are incremented. *
** This method should apply filters to the added item after inserting * it, possibly hiding it immediately. If the container is being sorted, * the item may be added at the correct sorted position instead of the * given position. See {@link Indexed}, {@link Ordered}, * {@link Filterable} and {@link Sortable} for more information. *
* * @param index * Index (in the filtered and sorted view) to add the new * item. * @return item id of the created item or null if the operation fails. * @throws UnsupportedOperationException * if the operation is not supported by the container */ public Object addItemAt(int index) throws UnsupportedOperationException; /** * Adds a new item at given index (in the filtered view). ** The indexes of the item currently in the given position and all the * following items are incremented. *
** This method should apply filters to the added item after inserting * it, possibly hiding it immediately. If the container is being sorted, * the item may be added at the correct sorted position instead of the * given position. See {@link Indexed}, {@link Filterable} and * {@link Sortable} for more information. *
* * @param index * Index (in the filtered and sorted view) at which to add * the new item. * @param newItemId * Id of the new item to be added. * @return new {@link Item} or null if the operation fails. * @throws UnsupportedOperationException * if the operation is not supported by the container */ public Item addItemAt(int index, Object newItemId) throws UnsupportedOperationException; } /** *
* Interface for Container
classes whose Items can be arranged
* hierarchically. This means that the Items in the container belong in a
* tree-like structure, with the following quirks:
*
null
if the
* specified Item is a root element.
*/
public Object getParent(Object itemId);
/**
* Gets the IDs of all Items in the container that don't have a parent.
* Such items are called root
Items. The returned
* collection is unmodifiable.
*
* @return An unmodifiable {@link java.util.Collection collection}
* containing IDs of all root elements of the container
*/
public Collection> rootItemIds();
/**
*
* Sets the parent of an Item. The new parent item must exist and be
* able to have children. (
* {@link #areChildrenAllowed(Object)} == true
). It is
* also possible to detach a node from the hierarchy (and thus make it
* root) by setting the parent null
.
*
* This operation is optional. *
* * @param itemId * ID of the item to be set as the child of the Item * identified withnewParentId
* @param newParentId
* ID of the Item that's to be the new parent of the Item
* identified with itemId
* @return true
if the operation succeeded,
* false
if not
*/
public boolean setParent(Object itemId, Object newParentId)
throws UnsupportedOperationException;
/**
* Tests if the Item with given ID can have children.
*
* @param itemId
* ID of the Item in the container whose child capability is
* to be tested
* @return true
if the specified Item exists in the
* Container and it can have children, false
if
* it's not found from the container or it can't have children.
*/
public boolean areChildrenAllowed(Object itemId);
/**
*
* Sets the given Item's capability to have children. If the Item
* identified with itemId
already has children and
* {@link #areChildrenAllowed(Object)}
is false this method
* fails and false
is returned.
*
* The children must be first explicitly removed with * {@link #setParent(Object itemId, Object newParentId)}or * {@link com.vaadin.data.Container#removeItem(Object itemId)}. *
* *
* This operation is optional. If it is not implemented, the method
* always returns false
.
*
true
if the operation succeeded,
* false
if not
*/
public boolean setChildrenAllowed(Object itemId,
boolean areChildrenAllowed)
throws UnsupportedOperationException;
/**
* Tests if the Item specified with itemId
is a root Item.
* The hierarchical container can have more than one root and must have
* at least one unless it is empty. The {@link #getParent(Object itemId)}
* method always returns null
for root Items.
*
* @param itemId
* ID of the Item whose root status is to be tested
* @return true
if the specified Item is a root,
* false
if not
*/
public boolean isRoot(Object itemId);
/**
*
* Tests if the Item specified with itemId
has child Items
* or if it is a leaf. The {@link #getChildren(Object itemId)} method
* always returns null
for leaf Items.
*
* Note that being a leaf does not imply whether or not an Item is * allowed to have children. *
* . * * @param itemId * ID of the Item to be tested * @returntrue
if the specified Item has children,
* false
if not (is a leaf)
*/
public boolean hasChildren(Object itemId);
/**
*
* Removes the Item identified by ItemId
from the
* Container.
*
* Note that this does not remove any children the item might have. *
* * @param itemId * ID of the Item to remove * @returntrue
if the operation succeeded,
* false
if not
*/
@Override
public boolean removeItem(Object itemId)
throws UnsupportedOperationException;
}
/**
* Interface that is implemented by containers which allow reducing their
* visible contents based on a set of filters. This interface has been
* renamed from {@link Filterable}, and implementing the new
* {@link Filterable} instead of or in addition to {@link SimpleFilterable}
* is recommended. This interface might be removed in future Vaadin
* versions.
* * When a set of filters are set, only items that match all the filters are * included in the visible contents of the container. Still new items that * do not match filters can be added to the container. Multiple filters can * be added and the container remembers the state of the filters. When * multiple filters are added, all filters must match for an item to be * visible in the container. *
** When an {@link Ordered} or {@link Indexed} container is filtered, all * operations of these interfaces should only use the filtered contents and * the filtered indices to the container. *
** How filtering is performed when a {@link Hierarchical} container * implements {@link SimpleFilterable} is implementation specific and should * be documented in the implementing class. *
** Adding items (if supported) to a filtered {@link Ordered} or * {@link Indexed} container should insert them immediately after the * indicated visible item. The unfiltered position of items added at index * 0, at index {@link com.vaadin.data.Container#size()} or at an undefined * position is up to the implementation. *
** The functionality of SimpleFilterable can be implemented using the * {@link Filterable} API and {@link SimpleStringFilter}. *
* * @since 5.0 (renamed from Filterable to SimpleFilterable in 6.6) */ public interface SimpleFilterable extends Container, Serializable { /** * Add a filter for given property. * * The API {@link Filterable#addContainerFilter(Filter)} is recommended * instead of this method. A {@link SimpleStringFilter} can be used with * the new API to implement the old string filtering functionality. * * The filter accepts items for which toString() of the value of the * given property contains or starts with given filterString. Other * items are not visible in the container when filtered. * * If a container has multiple filters, only items accepted by all * filters are visible. * * @param propertyId * Property for which the filter is applied to. * @param filterString * String that must match the value of the property * @param ignoreCase * Determine if the casing can be ignored when comparing * strings. * @param onlyMatchPrefix * Only match prefixes; no other matches are included. */ public void addContainerFilter(Object propertyId, String filterString, boolean ignoreCase, boolean onlyMatchPrefix); /** * Remove all filters from all properties. */ public void removeAllContainerFilters(); /** * Remove all filters from the given property. * * @param propertyId * for which to remove filters */ public void removeContainerFilters(Object propertyId); } /** * Filter interface for container filtering. * * If a filter does not support in-memory filtering, * {@link #passesFilter(Item)} should throw * {@link UnsupportedOperationException}. * * Lazy containers must be able to map filters to their internal * representation (e.g. SQL or JPA 2.0 Criteria). * * An {@link UnsupportedFilterException} can be thrown by the container if a * particular filter is not supported by the container. * * An {@link Filter} should implement {@link #equals(Object)} and * {@link #hashCode()} correctly to avoid duplicate filter registrations * etc. * * @see Filterable * * @since 6.6 */ public interface Filter extends Serializable { /** * Check if an item passes the filter (in-memory filtering). * * @param itemId * identifier of the item being filtered; may be null when * the item is being added to the container * @param item * the item being filtered * @return true if the item is accepted by this filter * @throws UnsupportedOperationException * if the filter cannot be used for in-memory filtering */ public boolean passesFilter(Object itemId, Item item) throws UnsupportedOperationException; /** * Check if a change in the value of a property can affect the filtering * result. May always return true, at the cost of performance. * * If the filter cannot determine whether it may depend on the property * or not, should return true. * * @param propertyId * @return true if the filtering result may/does change based on changes * to the property identified by propertyId */ public boolean appliesToProperty(Object propertyId); } /** * Interface that is implemented by containers which allow reducing their * visible contents based on a set of filters. ** When a set of filters are set, only items that match all the filters are * included in the visible contents of the container. Still new items that * do not match filters can be added to the container. Multiple filters can * be added and the container remembers the state of the filters. When * multiple filters are added, all filters must match for an item to be * visible in the container. *
*
* When an {@link Ordered} or {@link Indexed} container is filtered, all
* operations of these interfaces should only use the filtered and sorted
* contents and the filtered indices to the container. Indices or item
* identifiers in the public API refer to the visible view unless otherwise
* stated. However, the addItem*()
methods may add items that
* will be filtered out after addition or moved to another position based on
* sorting.
*
* How filtering is performed when a {@link Hierarchical} container * implements {@link Filterable} is implementation specific and should be * documented in the implementing class. *
** Adding items (if supported) to a filtered {@link Ordered} or * {@link Indexed} container should insert them immediately after the * indicated visible item. However, the unfiltered position of items added * at index 0, at index {@link com.vaadin.data.Container#size()} or at an * undefined position is up to the implementation. *
* ** This API replaces the old Filterable interface, renamed to * {@link SimpleFilterable} in Vaadin 6.6. *
* * @since 6.6 */ public interface Filterable extends Container, Serializable { /** * Adds a filter for the container. * * If a container has multiple filters, only items accepted by all * filters are visible. * * @throws UnsupportedFilterException * if the filter is not supported by the container */ public void addContainerFilter(Filter filter) throws UnsupportedFilterException; /** * Removes a filter from the container. * * This requires that the equals() method considers the filters as * equivalent (same instance or properly implemented equals() method). */ public void removeContainerFilter(Filter filter); /** * Remove all active filters from the container. */ public void removeAllContainerFilters(); /** * Returns the filters which have been applied to the container * * @return A collection of filters which have been applied to the * container. An empty collection if no filters have been * applied. * @since 7.1 */ public Collection* Interface implemented by the editor classes supporting editing the * Container. Implementing this interface means that the Container serving * as the data source of the editor can be modified through it. *
*
* Note that not implementing the Container.Editor
interface
* does not restrict the class from editing the Container contents
* internally.
*
Event
object specifying the Container whose Item set has
* changed (items added, removed or reordered).
*
* A simple property value change is not an item set change.
*/
public interface ItemSetChangeEvent extends Serializable {
/**
* Gets the Property where the event occurred.
*
* @return source of the event
*/
public Container getContainer();
}
/**
* Container Item set change listener interface.
*
* An item set change refers to addition, removal or reordering of items in
* the container. A simple property value change is not an item set change.
*/
public interface ItemSetChangeListener extends Serializable {
/**
* Lets the listener know a Containers visible (filtered and/or sorted,
* if applicable) Item set has changed.
*
* @param event
* change event text
*/
public void containerItemSetChange(Container.ItemSetChangeEvent event);
}
/**
* The interface for adding and removing ItemSetChangeEvent
* listeners. By implementing this interface a class explicitly announces
* that it will generate a ItemSetChangeEvent
when its contents
* are modified.
*
* An item set change refers to addition, removal or reordering of items in
* the container. A simple property value change is not an item set change.
*
*
* Note: The general Java convention is not to explicitly declare that a
* class generates events, but to directly define the
* addListener
and removeListener
methods. That
* way the caller of these methods has no real way of finding out if the
* class really will send the events, or if it just defines the methods to
* be able to implement an interface.
*
Event
object specifying the Container whose Property set
* has changed.
*
* A property set change means the addition, removal or other structural
* changes to the properties of a container. Changes concerning the set of
* items in the container and their property values are not property set
* changes.
*/
public interface PropertySetChangeEvent extends Serializable {
/**
* Retrieves the Container whose contents have been modified.
*
* @return Source Container of the event.
*/
public Container getContainer();
}
/**
* The listener interface for receiving PropertySetChangeEvent
* objects.
*
* A property set change means the addition, removal or other structural
* change of the properties (supported property IDs) of a container. Changes
* concerning the set of items in the container and their property values
* are not property set changes.
*/
public interface PropertySetChangeListener extends Serializable {
/**
* Notifies this listener that the set of property IDs supported by the
* Container has changed.
*
* @param event
* Change event.
*/
public void containerPropertySetChange(
Container.PropertySetChangeEvent event);
}
/**
*
* The interface for adding and removing PropertySetChangeEvent
* listeners. By implementing this interface a class explicitly announces
* that it will generate a PropertySetChangeEvent
when the set
* of property IDs supported by the container is modified.
*
* A property set change means the addition, removal or other structural * changes to the properties of a container. Changes concerning the set of * items in the container and their property values are not property set * changes. *
* *
* Note that the general Java convention is not to explicitly declare that a
* class generates events, but to directly define the
* addListener
and removeListener
methods. That
* way the caller of these methods has no real way of finding out if the
* class really will send the events, or if it just defines the methods to
* be able to implement an interface.
*