/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.sling.jcr.resource.internal.helper.jcr;

import java.io.Closeable;
import java.io.IOException;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference;

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.external.URIProvider;
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.api.JcrResourceConstants;
import org.apache.sling.jcr.resource.internal.JcrListenerBaseConfig;
import org.apache.sling.jcr.resource.internal.JcrModifiableValueMap;
import org.apache.sling.jcr.resource.internal.JcrResourceListener;
import org.apache.sling.jcr.resource.internal.NodeUtil;
import org.apache.sling.spi.resource.provider.ObserverConfiguration;
import org.apache.sling.spi.resource.provider.ProviderContext;
import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
import org.apache.sling.spi.resource.provider.ResolveContext;
import org.apache.sling.spi.resource.provider.ResourceContext;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(name="org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderFactory",
           service = ResourceProvider.class,
           property = {
                   ResourceProvider.PROPERTY_NAME + "=JCR",
                   ResourceProvider.PROPERTY_ROOT + "=/",
                   ResourceProvider.PROPERTY_MODIFIABLE + ":Boolean=true",
                   ResourceProvider.PROPERTY_ADAPTABLE + ":Boolean=true",
                   ResourceProvider.PROPERTY_ATTRIBUTABLE + ":Boolean=true",
                   ResourceProvider.PROPERTY_REFRESHABLE + ":Boolean=true",
                   ResourceProvider.PROPERTY_AUTHENTICATE + "=" + ResourceProvider.AUTHENTICATE_REQUIRED,
                   Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
           })
@Designate(ocd = JcrResourceProvider.Config.class)
public class JcrResourceProvider extends ResourceProvider<JcrProviderState> {

    /** Logger */
    private final Logger logger = LoggerFactory.getLogger(JcrResourceProvider.class);

    private static final String REPOSITORY_REFERENCE_NAME = "repository";

    private static final Set<String> IGNORED_PROPERTIES = new HashSet<>();
    static {
        IGNORED_PROPERTIES.add(JcrConstants.JCR_MIXINTYPES);
        IGNORED_PROPERTIES.add(JcrConstants.JCR_PRIMARYTYPE);
        IGNORED_PROPERTIES.add(JcrConstants.JCR_CREATED);
        IGNORED_PROPERTIES.add("jcr:createdBy");
    }

    @ObjectClassDefinition(name = "Apache Sling JCR Resource Provider", description = "Provides Sling resources based on the Java Content Repository")
    public @interface Config {

        @AttributeDefinition(name = "Enable Query Limit", description = "If set to true, the JcrResourceProvider will support parsing query start and limits from comments in the queries and set a default limit for all other queries using the findResources methods")
        boolean enable_query_limit() default false;

        @AttributeDefinition(name = "Default Query Limit", description = "The default query limit for queries using the findResources methods")
        long default_query_limit() default 10000L;
    }
  
    @Reference(name = REPOSITORY_REFERENCE_NAME, service = SlingRepository.class)
    private ServiceReference<SlingRepository> repositoryReference;

    /** The JCR listener base configuration. */
    private volatile JcrListenerBaseConfig listenerConfig;

    /** The JCR observation listeners. */
    private final Map<ObserverConfiguration, Closeable> listeners = new HashMap<>();

    /**
     * Map of bound URIProviders sorted by service ranking in descending order (highest ranking first).
     * Key = service reference, value = service implementation
     */
    private final SortedMap<ServiceReference<URIProvider>, URIProvider> providers = Collections.synchronizedSortedMap(new TreeMap<>(Collections.reverseOrder()));

    private volatile SlingRepository repository;

    private volatile JcrProviderStateFactory stateFactory;

    private Config config;
  
    private final AtomicReference<DynamicClassLoaderManager> classLoaderManagerReference = new AtomicReference<>();

    private AtomicReference<URIProvider[]> uriProviderReference = new AtomicReference<>();

    @Activate
    protected void activate(final ComponentContext context, final Config config) throws RepositoryException {
        SlingRepository repository = context.locateService(REPOSITORY_REFERENCE_NAME,
                this.repositoryReference);
        if (repository == null) {
            // concurrent unregistration of SlingRepository service
            // don't care, this component is going to be deactivated
            // so we just stop working
            logger.warn("activate: Activation failed because SlingRepository may have been unregistered concurrently");
            return;
        }

        this.config = config;

        this.repository = repository;

        this.stateFactory = new JcrProviderStateFactory(repositoryReference, repository,
                classLoaderManagerReference, uriProviderReference);
    }

    @Deactivate
    protected void deactivate() {
        this.stateFactory = null;
    }

    @Reference(name = "dynamicClassLoaderManager",
            service = DynamicClassLoaderManager.class,
            cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
    protected void bindDynamicClassLoaderManager(final DynamicClassLoaderManager dynamicClassLoaderManager) {
        this.classLoaderManagerReference.set(dynamicClassLoaderManager);
    }

    protected void unbindDynamicClassLoaderManager(final DynamicClassLoaderManager dynamicClassLoaderManager) {
        this.classLoaderManagerReference.compareAndSet(dynamicClassLoaderManager, null);
    }

    @Reference(
            name = "uriprovider",
            service = URIProvider.class,
            cardinality = ReferenceCardinality.MULTIPLE,
            policy = ReferencePolicy.DYNAMIC,
            bind = "bindUriProvider",
            unbind = "unbindUriProvider"
    )
    private void bindUriProvider(ServiceReference<URIProvider> srUriProvider, URIProvider uriProvider) {
        providers.put(srUriProvider, uriProvider);
        updateURIProviders();
    }

    private void unbindUriProvider(ServiceReference<URIProvider> srUriProvider) {
        providers.remove(srUriProvider);
        updateURIProviders();
    }

    private void updateURIProviders() {
        URIProvider[] ups = providers.values().toArray(new URIProvider[providers.size()]);
        this.uriProviderReference.set(ups);
    }

    @Override
    public void start(final ProviderContext ctx) {
        super.start(ctx);
        this.registerListeners();
    }

    @Override
    public void stop() {
        this.unregisterListeners();
        super.stop();
    }

    @Override
    public void update(final long changeSet) {
        super.update(changeSet);
        this.updateListeners();
    }

    @SuppressWarnings("unused")
    private void bindRepository(final ServiceReference<SlingRepository> ref) {
        this.repositoryReference = ref;
        this.repository = null;
    }

    @SuppressWarnings("unused")
    private void unbindRepository(final ServiceReference<SlingRepository> ref) {
        if (this.repositoryReference == ref) {
            this.repositoryReference = null;
            this.repository = null;
        }
    }

    /**
     * Register all observation listeners.
     */
    private void registerListeners() {
        if ( this.repository != null ) {
            logger.debug("Registering resource listeners...");
            try {
                this.listenerConfig = new JcrListenerBaseConfig(this.getProviderContext().getObservationReporter(),
                    this.repository);
                for(final ObserverConfiguration config : this.getProviderContext().getObservationReporter().getObserverConfigurations()) {
                    logger.debug("Registering listener for {}", config.getPaths());
                    final Closeable listener = new JcrResourceListener(this.listenerConfig,
                            config);
                    this.listeners.put(config, listener);
                }
            } catch (final RepositoryException e) {
                throw new SlingException("Can't create the JCR event listener.", e);
            }
            logger.debug("Registered resource listeners");
        }
    }

    /**
     * Unregister all observation listeners.
     */
    private void unregisterListeners() {
        logger.debug("Unregistering resource listeners...");
        for(final Closeable c : this.listeners.values()) {
            try {
                logger.debug("Removing listener for {}", ((JcrResourceListener)c).getConfig().getPaths());
                c.close();
            } catch (final IOException e) {
                // ignore this as the method above does not throw it
            }
        }
        this.listeners.clear();
        if ( this.listenerConfig != null ) {
            try {
                this.listenerConfig.close();
            } catch (final IOException e) {
                // ignore this as the method above does not throw it
            }
            this.listenerConfig = null;
        }
        logger.debug("Unregistered resource listeners");
    }

    /**
     * Update observation listeners.
     */
    private void updateListeners() {
        if ( this.listenerConfig == null ) {
            this.unregisterListeners();
            this.registerListeners();
        } else {
            logger.debug("Updating resource listeners...");
            final Map<ObserverConfiguration, Closeable> oldMap = new HashMap<>(this.listeners);
            this.listeners.clear();
            try {
                for(final ObserverConfiguration config : this.getProviderContext().getObservationReporter().getObserverConfigurations()) {
                    // check if such a listener already exists
                    Closeable listener = oldMap.remove(config);
                    if ( listener == null ) {
                        logger.debug("Registering listener for {}", config.getPaths());
                        listener = new JcrResourceListener(this.listenerConfig, config);
                    } else {
                        logger.debug("Updating listener for {}", config.getPaths());
                        ((JcrResourceListener)listener).update(config);
                    }
                    this.listeners.put(config, listener);
                }
            } catch (final RepositoryException e) {
                throw new SlingException("Can't create the JCR event listener.", e);
            }
            for(final Closeable c : oldMap.values()) {
                try {
                    logger.debug("Removing listener for {}", ((JcrResourceListener)c).getConfig().getPaths());
                    c.close();
                } catch (final IOException e) {
                    // ignore this as the method above does not throw it
                }
            }
            logger.debug("Updated resource listeners");
        }
    }

    /**
     * Create a new ResourceResolver wrapping a Session object. Carries map of
     * authentication info in order to create a new resolver as needed.
     */
    @Override
    @NotNull public JcrProviderState authenticate(final @NotNull Map<String, Object> authenticationInfo)
    throws LoginException {
        return stateFactory.createProviderState(authenticationInfo);
    }

    @Override
    public void logout(final @NotNull JcrProviderState state) {
        state.logout();
    }

    @Override
    public boolean isLive(final @NotNull ResolveContext<JcrProviderState> ctx) {
        return ctx.getProviderState().getSession().isLive();
    }

    @Override
    public Resource getResource(ResolveContext<JcrProviderState> ctx, String path, ResourceContext rCtx, Resource parent) {
        try {
            return ctx.getProviderState().getResourceFactory().createResource(ctx.getResourceResolver(), path, parent, rCtx.getResolveParameters());
        } catch (RepositoryException e) {
            throw new SlingException("Can't get resource", e);
        }
    }

    @Override
    public Iterator<Resource> listChildren(ResolveContext<JcrProviderState> ctx, Resource parent) {
        JcrItemResource<?> parentItemResource;

        // short cut for known JCR resources
        if (parent instanceof JcrItemResource) {
            parentItemResource = (JcrItemResource<?>) parent;
        } else {
            // try to get the JcrItemResource for the parent path to list
            // children
            try {
                parentItemResource = ctx.getProviderState().getResourceFactory().createResource(
                        parent.getResourceResolver(), parent.getPath(), null,
                        parent.getResourceMetadata().getParameterMap());
            } catch (RepositoryException re) {
                throw new SlingException("Can't list children", re);
            }
        }

        // return children if there is a parent item resource, else null
        return (parentItemResource != null)
                ? parentItemResource.listJcrChildren()
                : null;
    }

    @Override
    public @Nullable Resource getParent(final @NotNull ResolveContext<JcrProviderState> ctx, final @NotNull Resource child) {
        if (child instanceof JcrItemResource<?>) {
            try {
                String version = null;
                if (child.getResourceMetadata().getParameterMap() != null) {
                    version = child.getResourceMetadata().getParameterMap().get("v");
                }
                if (version == null) {
                    String parentPath = ResourceUtil.getParent(child.getPath());
                    if (parentPath != null) {
                        Item parentItem = ctx.getProviderState().getResourceFactory()
                            .getItemOrNull(parentPath);
                        if (parentItem != null && parentItem.isNode()) {
                            return new JcrNodeResource(ctx.getResourceResolver(),
                                parentPath, null, (Node)parentItem,
                                ctx.getProviderState().getHelperData());
                        }
                    }
                    return null;
                }
            } catch (RepositoryException e) {
                logger.warn("Can't get parent for {}", child, e);
                return null;
            }
        }
        return super.getParent(ctx, child);
    }

    @Override
    public Collection<String> getAttributeNames(final @NotNull ResolveContext<JcrProviderState> ctx) {
        final Set<String> names = new HashSet<String>();
        final String[] sessionNames = ctx.getProviderState().getSession().getAttributeNames();
        for(final String name : sessionNames) {
            if ( isAttributeVisible(name) ) {
                names.add(name);
            }
        }
        return names;
    }

    @Override
    public Object getAttribute(final @NotNull ResolveContext<JcrProviderState> ctx, final @NotNull String name) {
        if (isAttributeVisible(name)) {
            if (ResourceResolverFactory.USER.equals(name)) {
                return ctx.getProviderState().getSession().getUserID();
            }
            return ctx.getProviderState().getSession().getAttribute(name);
        }
        return null;
    }

    @Override
    public Resource create(final @NotNull ResolveContext<JcrProviderState> ctx, final String path, final Map<String, Object> properties)
    throws PersistenceException {
        // check for node type
        final Object nodeObj = (properties != null ? properties.get(JcrConstants.JCR_PRIMARYTYPE) : null);
        // check for sling:resourcetype
        final String nodeType;
        if ( nodeObj != null ) {
            nodeType = nodeObj.toString();
        } else {
            final Object rtObj =  (properties != null ? properties.get(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY) : null);
            boolean isNodeType = false;
            if ( rtObj != null ) {
                final String resourceType = rtObj.toString();
                if ( resourceType.indexOf(':') != -1 && resourceType.indexOf('/') == -1 ) {
                    try {
                        ctx.getProviderState().getSession().getWorkspace().getNodeTypeManager().getNodeType(resourceType);
                        isNodeType = true;
                    } catch (final RepositoryException ignore) {
                        // we expect this, if this isn't a valid node type, therefore ignoring
                    }
                }
            }
            if ( isNodeType ) {
                nodeType = rtObj.toString();
            } else {
                nodeType = null;
            }
        }
        final String jcrPath = path;
        if ( jcrPath == null ) {
            throw new PersistenceException("Unable to create node at " + path, null, path, null);
        }
        Node node = null;
        try {
            final int lastPos = jcrPath.lastIndexOf('/');
            final Node parent;
            if ( lastPos == 0 ) {
                parent = ctx.getProviderState().getSession().getRootNode();
            } else {
                parent = (Node) ctx.getProviderState().getSession().getItem(jcrPath.substring(0, lastPos));
            }
            final String name = jcrPath.substring(lastPos + 1);
            if ( nodeType != null ) {
                node = parent.addNode(name, nodeType);
            } else {
                node = parent.addNode(name);
            }

            if ( properties != null ) {
                // create modifiable map
                final JcrModifiableValueMap jcrMap = new JcrModifiableValueMap(node, ctx.getProviderState().getHelperData());
                // check mixin types first
                final Object value = properties.get(JcrConstants.JCR_MIXINTYPES);
                if ( value != null ) {
                    jcrMap.put(JcrConstants.JCR_MIXINTYPES, value);
                }
                for(final Map.Entry<String, Object> entry : properties.entrySet()) {
                    if ( !IGNORED_PROPERTIES.contains(entry.getKey()) ) {
                        try {
                            jcrMap.put(entry.getKey(), entry.getValue());
                        } catch (final IllegalArgumentException iae) {
                            try {
                                node.remove();
                            } catch ( final RepositoryException re) {
                                // we ignore this
                            }
                            throw new PersistenceException(iae.getMessage(), iae, path, entry.getKey());
                        }
                    }
                }
            }

            return new JcrNodeResource(ctx.getResourceResolver(), path, null, node, ctx.getProviderState().getHelperData());
        } catch (final RepositoryException e) {
            throw new PersistenceException("Unable to create node at " + jcrPath, e, path, null);
        }
    }

    @Override
    public boolean orderBefore(@NotNull ResolveContext<JcrProviderState> ctx, @NotNull Resource parent, @NotNull String name,
            @Nullable String followingSiblingName) throws PersistenceException {
        Node node = parent.adaptTo(Node.class);
        if (node == null) {
            throw new PersistenceException("The resource " + parent.getPath() + " cannot be adapted to Node. It is probably not provided by the JcrResourceProvider");
        }
        try {
            // check if reordering necessary
            NodeIterator nodeIterator = node.getNodes();
            long existingNodePosition = -1;
            long index = 0;
            while (nodeIterator.hasNext()) {
                Node childNode = nodeIterator.nextNode();
                if (childNode.getName().equals(name)) {
                    existingNodePosition = index;
                }
                if (existingNodePosition >= 0) {
                    // is existing resource already at the desired position?
                    if (childNode.getName().equals(followingSiblingName)) {
                        if (existingNodePosition == index-1) {
                            return false;
                        }
                    }
                    // is the existing node already the last one in the list?
                    else if (followingSiblingName == null && existingNodePosition == nodeIterator.getSize()-1) {
                        return false;
                    }
                }
                index++;
            }
            node.orderBefore(name, followingSiblingName);
            return true;
        } catch (final RepositoryException e) {
            throw new PersistenceException("Unable to reorder children below " + parent.getPath(), e, parent.getPath(), null);
        }
    }

    @Override
    public void delete(final @NotNull ResolveContext<JcrProviderState> ctx, final @NotNull Resource resource)
    throws PersistenceException {
        // try to adapt to Item
        Item item = resource.adaptTo(Item.class);
        try {
            if ( item == null ) {
                final String jcrPath = resource.getPath();
                if (jcrPath == null) {
                    logger.debug("delete: {} maps to an empty JCR path", resource.getPath());
                    throw new PersistenceException("Unable to delete resource", null, resource.getPath(), null);
                }
                item = ctx.getProviderState().getSession().getItem(jcrPath);
            }
            item.remove();
        } catch (final RepositoryException e) {
            throw new PersistenceException("Unable to delete resource", e, resource.getPath(), null);
        }
    }

    @Override
    public void revert(final @NotNull ResolveContext<JcrProviderState> ctx) {
        try {
            ctx.getProviderState().getSession().refresh(false);
        } catch (final RepositoryException ignore) {
            logger.warn("Unable to revert pending changes.", ignore);
        }
    }

    @Override
    public void commit(final @NotNull ResolveContext<JcrProviderState> ctx)
    throws PersistenceException {
        try {
            ctx.getProviderState().getSession().save();
        } catch (final RepositoryException e) {
            throw new PersistenceException("Unable to commit changes to session.", e);
        }
    }

    @Override
    public boolean hasChanges(final @NotNull ResolveContext<JcrProviderState> ctx) {
        try {
            return ctx.getProviderState().getSession().hasPendingChanges();
        } catch (final RepositoryException ignore) {
            logger.warn("Unable to check session for pending changes.", ignore);
        }
        return false;
    }

    @Override
    public void refresh(final @NotNull ResolveContext<JcrProviderState> ctx) {
        try {
            ctx.getProviderState().getSession().refresh(true);
        } catch (final RepositoryException ignore) {
            logger.warn("Unable to refresh session.", ignore);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public @Nullable <AdapterType> AdapterType adaptTo(final @NotNull ResolveContext<JcrProviderState> ctx,
            final @NotNull Class<AdapterType> type) {
        Session session = ctx.getProviderState().getSession();
        if (type == Session.class) {
            return (AdapterType) session;
        } else if (type == Principal.class) {
            try {
                if (session instanceof JackrabbitSession && session.getUserID() != null) {
                    JackrabbitSession s =((JackrabbitSession) session);
                    final UserManager um = s.getUserManager();
                    if (um != null) {
                        final Authorizable auth = um.getAuthorizable(s.getUserID());
                        if (auth != null) {
                            return (AdapterType) auth.getPrincipal();
                        }
                    }
                }
                logger.debug("not able to adapto Resource to Principal, let the base class try to adapt");
            } catch (RepositoryException e) {
                logger.warn("error while adapting Resource to Principal, let the base class try to adapt", e);
            }
        }
        return super.adaptTo(ctx, type);
    }

    @Override
    public boolean copy(final  @NotNull ResolveContext<JcrProviderState> ctx,
            final String srcAbsPath,
            final String destAbsPath) throws PersistenceException {
        return false;
    }

    @Override
    public boolean move(final  @NotNull ResolveContext<JcrProviderState> ctx,
            final String srcAbsPath,
            final String destAbsPath) throws PersistenceException {
        final String srcNodePath = srcAbsPath;
        final String dstNodePath = destAbsPath + '/' + ResourceUtil.getName(srcAbsPath);
        try {
            ctx.getProviderState().getSession().move(srcNodePath, dstNodePath);
            return true;
        } catch (final RepositoryException e) {
            throw new PersistenceException("Unable to move resource to " + destAbsPath, e, srcAbsPath, null);
        }
    }

    @Override
    public @Nullable QueryLanguageProvider<JcrProviderState> getQueryLanguageProvider() {
        final ProviderContext ctx = this.getProviderContext();
        if ( ctx != null ) {
            if(config.enable_query_limit()){
                return new LimitingQueryLanguageProvider(ctx, config.default_query_limit());
            }
            return new BasicQueryLanguageProvider(ctx);
        }
        return null;
    }

    /**
     * Returns <code>true</code> unless the name is
     * <code>user.jcr.credentials</code> (
     * {@link JcrResourceConstants#AUTHENTICATION_INFO_CREDENTIALS}) or contains
     * the string <code>password</code> as in <code>user.password</code> (
     * {@link org.apache.sling.api.resource.ResourceResolverFactory#PASSWORD})
     *
     * @param name The name to check whether it is visible or not
     * @return <code>true</code> if the name is assumed visible
     * @throws NullPointerException if <code>name</code> is <code>null</code>
     */
    private static boolean isAttributeVisible(final String name) {
        return !name.equals(JcrResourceConstants.AUTHENTICATION_INFO_CREDENTIALS)
            && !name.contains("password");
    }
}
