text:
package org.wso2.carbon.context.internal;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.util.XMLUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.base.DiscoveryService;
import org.wso2.carbon.base.UnloadTenantTask;
import org.wso2.carbon.queuing.CarbonQueue;
import org.wso2.carbon.queuing.CarbonQueueManager;
import org.wso2.carbon.queuing.QueuingException;
import org.wso2.carbon.registry.api.Registry;
import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserRealmService;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.ServerConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantCarbonQueueManager;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;

import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NoInitialContextException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.event.EventContext;
import javax.naming.event.EventDirContext;
import javax.naming.event.NamingListener;
import javax.naming.ldap.Control;
import javax.naming.ldap.ExtendedRequest;
import javax.naming.ldap.ExtendedResponse;
import javax.naming.ldap.LdapContext;
import javax.naming.spi.InitialContextFactory;
import javax.naming.spi.InitialContextFactoryBuilder;
import javax.naming.spi.NamingManager;
import javax.xml.namespace.QName;
import java.lang.ref.WeakReference;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;

/**
 * This class will preserve an instance the current CarbonContext as a thread local variable. If a
 * CarbonContext is available on a global-scope (i.e. HTTP Session or AxisConfiguration) this class
 * will do the required lookup and obtain the corresponding instance.
 *

 * The CarbonContext provides the API for sub-tenant/super-tenant programming around WSO2 Carbon and WSO2
 * Stratos.
 */
@SuppressWarnings("unused")
public final class CarbonContextDataHolder {
    private static final Log log = LogFactory.getLog(CarbonContextDataHolder.class);

    /**
     * The name of the property that stores a reference to the local repository instance of the
     * current tenant.
     */
    protected Registry localRepository;

    /**
     * The name of the property that stores a reference to the configuration registry instance of
     * the current tenant, as visible to the system.
     */
    protected Registry configSystemRegistry;

    /**
     * The name of the property that stores a reference to the governance registry instance of the
     * current tenant, as visible to the system.
     */
    protected Registry governanceSystemRegistry;

    /**
     * The name of the property that stores a reference to the configuration registry instance of
     * the current tenant, as visible to a user.
     */
    protected Registry configUserRegistry;

    /**
     * The name of the property that stores a reference to the governance registry instance of the
     * current tenant, as visible to a user.
     */
    protected Registry governanceUserRegistry;

    /**
     * The name of the property that stores a reference to the UserRealm instance of the current
     * tenant, as visible to a user.
     */
    protected UserRealm userRealm;

    // The CarbonContextHolder parameter is restricted. We have used the hardcoded string value in
    // TenantAxisConfiguration and CarbonHttpSession and ThriftSession. Any change to this constant, should also be
    // propagated to the three classes mentioned above.
    private static final String CARBON_CONTEXT_HOLDER = "carbonContextHolder";

    private int tenantId = org.wso2.carbon.base.MultitenantConstants.INVALID_TENANT_ID;
    private static final int CARBON_AUTHENTICATION_UTIL_INDEX = 5;
    private static final String CARBON_AUTHENTICATION_UTIL_CLASS = "org.wso2.carbon.core.services.util.CarbonAuthenticationUtil";
    private static final int CARBON_AUTHENTICATION_HANDLER_INDEX = 5;
    private static final String CARBON_AUTHENTICATION_HANDLER_CLASS = "org.wso2.carbon.server.admin.module.handler.AuthenticationHandler";

    private String username;
    private String tenantDomain;
    private String applicationName;

    private Map<String, Object> properties;

    private static List<UnloadTenantTask> unloadTenantTasks = null;

    private static final AtomicReference<DiscoveryService> discoveryServiceProvider = new AtomicReference<DiscoveryService>();

    // stores the current CarbonContext local to the running thread.
    private static ThreadLocal<CarbonContextDataHolder> currentContextHolder = new ThreadLocal<CarbonContextDataHolder>() {
        protected CarbonContextDataHolder initialValue() {
            return new CarbonContextDataHolder();
        }
    };

    // stores references to the existing CarbonContexts when starting tenant
    // flows. These
    // references will be popped back, when a tenant flow is ended.
    private static ThreadLocal<Stack<CarbonContextDataHolder>> parentContextHolderStack =
            new ThreadLocal<Stack<CarbonContextDataHolder>>();

    // contains static initializations for multi-tenant caching, queuing and JNDI support available
    // via the CarbonContext.
    static {
        try {
            log.debug("Started Setting up Authenticator Configuration");
            CarbonAuthenticator authenticator = new CarbonAuthenticator();
            try {
                setupAuthenticator(authenticator);
            } finally {
                String username = System.getProperty("http.proxyUser");
                String password = System.getProperty("http.proxyPassword");
                if (username != null && password != null) {
                    authenticator.addAuthenticator("proxy", ".*", username, password);
                }
                Authenticator.setDefault(authenticator);
            }
            log.debug("Completed Setting up Authenticator Configuration");
        } catch (NoClassDefFoundError ignore) {
            // There can be situations where the CarbonContext is accessed, when there is no Axis2
            // library on the classpath.
            if (log.isDebugEnabled()) {
                log.debug("There can be situations where the CarbonContext is accessed, when there is no Axis2" +
                          "library on the classpath.", ignore);
            }
        } catch (Exception e) {
            String msg = "Unable to read Server Configuration";
            log.error(msg, e);
        }

        unloadTenantTasks = new LinkedList<UnloadTenantTask>();
        registerUnloadTenantTask(new CarbonContextCleanupTask());

        try {
            CarbonQueueManager.setInstance(new InternalCarbonQueueManager());
        } catch (RuntimeException ignore) {
            // We don't mind an exception being thrown in here. Since there can be a possibility of
            // the same class loading twice and then trying to reset the queue manager.
            if (log.isDebugEnabled()) {
                log.debug("there can be a possibility of the same class loading twice and then trying " +
                          "to reset the initial context factory builder", ignore);
            }
        }
        try {
            NamingManager.
                    setInitialContextFactoryBuilder(new CarbonInitialJNDIContextFactoryBuilder());
        } catch (NamingException ignore) {
            // We don't mind an exception being thrown in here. Since there can be a possibility of
            // the same class loading twice and then trying to reset the initial context factory
            // builder.
            if (log.isDebugEnabled()) {
                log.debug("there can be a possibility of the same class loading twice and then trying " +
                          "to reset the initial context factory builder", ignore);
            }
        } catch (RuntimeException ignore) {
            // We don't mind an exception being thrown in here. Since there can be a possibility of
            // the same class loading twice and then trying to reset the initial context factory
            // builder. We are also catching Runtime exceptions here, since some JDKs do throw them
            // instead of the expected NamingException.
            if (log.isDebugEnabled()) {
                log.debug("there can be a possibility of the same class loading twice and then trying " +
                          "to reset the initial context factory builder", ignore);
            }
        }
    }

    public Registry getLocalRepository() {
        return localRepository;
    }

    public void setLocalRepository(Registry localRepository) {
        this.localRepository = localRepository;
    }

    public Registry getConfigSystemRegistry() {
        return configSystemRegistry;
    }

    public void setConfigSystemRegistry(Registry configSystemRegistry) {
        this.configSystemRegistry = configSystemRegistry;
    }

    public Registry getGovernanceSystemRegistry() {
        return governanceSystemRegistry;
    }

    public void setGovernanceSystemRegistry(Registry governanceSystemRegistry) {
        this.governanceSystemRegistry = governanceSystemRegistry;
    }

    public Registry getConfigUserRegistry() {
        return configUserRegistry;
    }

    public void setConfigUserRegistry(Registry configUserRegistry) {
        this.configUserRegistry = configUserRegistry;
    }

    public Registry getGovernanceUserRegistry() {
        return governanceUserRegistry;
    }

    public void setGovernanceUserRegistry(Registry governanceUserRegistry) {
        this.governanceUserRegistry = governanceUserRegistry;
    }

    public UserRealm getUserRealm() {
        if(userRealm == null){
            UserRealmService userRealmService = OSGiDataHolder.getInstance().getUserRealmService();
            if (userRealmService != null) {
                try {
                    userRealm = userRealmService.getTenantUserRealm(tenantId);
                } catch (UserStoreException e) {
                    log.error("Cannot retrieve UserRealm for tenant " + tenantId, e);
                }
            }
        }
        return userRealm;
    }

    public void setUserRealm(UserRealm userRealm) {
        this.userRealm = userRealm;
    }

    public String getApplicationName() {
        return applicationName;
    }

    public void setApplicationName(String applicationName) {
        this.applicationName = applicationName;
    }

    private static void setupAuthenticator(CarbonAuthenticator authenticator) throws Exception {
        OMElement documentElement = XMLUtils.toOM(
                CarbonUtils.getServerConfiguration().getDocumentElement());
        OMElement authenticators = documentElement.getFirstChildWithName(
                new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Security")).
                getFirstChildWithName(
                        new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "NetworkAuthenticatorConfig"));

        if (authenticators == null) {
            return;
        }

        for (Iterator iterator = authenticators.getChildElements(); iterator.hasNext(); ) {
            OMElement authenticatorElement = (OMElement) iterator.next();
            if (!authenticatorElement.getLocalName().equalsIgnoreCase("Credential")) {
                continue;
            }
            String pattern = authenticatorElement.getFirstChildWithName(
                    new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Pattern")).getText();
            String type = authenticatorElement.getFirstChildWithName(
                    new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Type")).getText();
            String username = authenticatorElement.getFirstChildWithName(
                    new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Username")).getText();
            String password = authenticatorElement.getFirstChildWithName(
                    new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Password")).getText();
            authenticator.addAuthenticator(type, pattern, username, password);
        }
    }

    /**
     * Method to be called when this tenant is unloaded. This will clear all the resources created
     * by this tenant on the carbon contexts.
     */
    public void unloadTenant() {
        // The security checks are done at the CarbonContextHolderBase level.
        int tenantId = getTenantId();
        unloadTenant(tenantId);
    }

    /**
     * This method will always attempt to obtain an instance of the current CarbonContext from the
     * thread-local copy.
     *
     * @return the CarbonContext holder.
     */
    public static CarbonContextDataHolder getThreadLocalCarbonContextHolder() {
        return currentContextHolder.get();
    }

    /**
     * This method will set the current multi-tenant queue manager instance.
     *
     * @param queueManager the multi-tenant queue manager.
     * @throws org.wso2.carbon.queuing.QueuingException
     *          if the operation failed.
     */
    public void setQueueManager(MultitenantCarbonQueueManager queueManager)
            throws QueuingException {
        CarbonQueueManager manager = CarbonQueueManager.getInstance();
        if (manager instanceof InternalCarbonQueueManager) {
            ((InternalCarbonQueueManager) manager).setQueueManager(queueManager);
        }
        log.debug("Successfully set the Queue Manager");
    }

    /**
     * This method will remove the current multi-tenant queue manager instance.
     *
     * @throws QueuingException if the operation failed.
     */
    public void removeQueueManager() throws QueuingException {
        CarbonQueueManager manager = CarbonQueueManager.getInstance();
        if (manager instanceof InternalCarbonQueueManager) {
            ((InternalCarbonQueueManager) manager).removeQueueManager();
        }
        log.debug("Successfully removed the Queue Manager");
    }

    // Checks whether the given tenant is a sub-tenant or not.
    private static boolean isSubTenant(int tenantId) {
        return (tenantId != MultitenantConstants.SUPER_TENANT_ID &&
                tenantId != MultitenantConstants.INVALID_TENANT_ID);
    }

    // A tenant-aware queue manager implementation. This will internally hold an instance of the
    // {@link MultitenantCarbonQueueManager}.
    private static class InternalCarbonQueueManager extends CarbonQueueManager {

        private AtomicReference<MultitenantCarbonQueueManager> queueManager =
                new AtomicReference<MultitenantCarbonQueueManager>();

        public CarbonQueue<?> getQueue(String name) {
            int tenantId = getThreadLocalCarbonContextHolder().getTenantId();
            if (queueManager.get() != null) {
                if (log.isDebugEnabled()) {
                    log.debug("Retrieving named queue: " + name);
                }
                return queueManager.get().getQueue(name,
                                                   isSubTenant(tenantId) ?
                                                   tenantId : MultitenantConstants.SUPER_TENANT_ID);
            }
            return null;
        }

        public synchronized void setQueueManager(MultitenantCarbonQueueManager queueManager)
                throws QueuingException {
            CarbonUtils.checkSecurity();
            if (getThreadLocalCarbonContextHolder().getTenantId() !=
                MultitenantConstants.SUPER_TENANT_ID) {
                throw new QueuingException("Only the super-tenant can set the queue manager.");
            }
            InternalCarbonQueueManager carbonQueueManager = null;
            if (this.queueManager.get() != null) {
                throw new QueuingException("The queue manager has already been set.");
            }
            this.queueManager.set(queueManager);
        }

        public synchronized void removeQueueManager() throws QueuingException {
            CarbonUtils.checkSecurity();
            if (getThreadLocalCarbonContextHolder().getTenantId() !=
                MultitenantConstants.SUPER_TENANT_ID) {
                throw new QueuingException("Only the super-tenant can remove the queue manager.");
            }
            this.queueManager.set(null);
        }
    }

    // A tenant-aware JNDI Initial Context Factory Builder implementation.
    private static class CarbonInitialJNDIContextFactoryBuilder implements
                                                                InitialContextFactoryBuilder {

        private static final String defaultInitialContextFactory =
                CarbonUtils.getServerConfiguration().getFirstProperty(
                        "JNDI.DefaultInitialContextFactory");

        public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> h)
                throws NamingException {
            try {
                // get factory class name
                String factoryClassName = (String) h.get(Context.INITIAL_CONTEXT_FACTORY);
                // if the factory class has not been provided use the default initial context
                // factory defined in carbon.xml.
                if (factoryClassName == null) {
                    factoryClassName = defaultInitialContextFactory;
                }else{
                    Class<?> factoryClass = classForName(factoryClassName);
                    return (InitialContextFactory)factoryClass.newInstance();
                }

                if (factoryClassName == null) {
                    throw new NoInitialContextException("Failed to create " +
                                                        "InitialContext. No factory specified in hash table.");
                }
                // new factory instance
                if (log.isDebugEnabled()) {
                    log.debug("Loading JNDI Initial Context Factory: " + factoryClassName);
                }
                Class<?> factoryClass = classForName(factoryClassName);
                InitialContextFactory initialContextFactory = null;
                String defaultInitialContextFactoryClassName =
                        CarbonUtils.getServerConfiguration().getFirstProperty(
                                "JNDI.CarbonInitialJNDIContextFactory");
                if(defaultInitialContextFactoryClassName!=null){
                    Class<?> defaultInitialContextFactoryBuilderClass;
                    try {
                        defaultInitialContextFactoryBuilderClass=classForName
                                (defaultInitialContextFactoryClassName);
                        initialContextFactory=(InitialContextFactory)
                                defaultInitialContextFactoryBuilderClass.getConstructor
                                        (InitialContextFactory.class).newInstance(factoryClass.newInstance());
                    } catch (ClassNotFoundException e) {
                        log.warn("The specified InitialContextFactoryBuilder "
                                +defaultInitialContextFactoryClassName+" is not there in the class " +
                                "path.Using the default InitialContextFactoryBuilder ",e);
                    } catch (InstantiationException e) {
                        log.warn("The specified InitialContextFactoryBuilder " +
                                ""+defaultInitialContextFactoryClassName+" could not be " +
                                "instantiated.Using the default InitialContextFactoryBuilder ",e);
                    } catch (IllegalAccessException e) {
                        log.warn("The specified InitialContextFactoryBuilder "
                                +defaultInitialContextFactoryClassName+" could not be " +
                                "accessed.Using the default InitialContextFactoryBuilder ",e);
                    }
                }

                if(initialContextFactory!=null){
                    return initialContextFactory;
                }

                //InitialContextFactory is not defined in carbon.xml, loading the default implementation.
                return new CarbonInitialJNDIContextFactory((InitialContextFactory) factoryClass.newInstance());
            } catch (Exception e) {
                NamingException nex = new NoInitialContextException("Failed to create " +
                                                                    "InitialContext using factory specified in hash table.");
                nex.setRootCause(e);
                throw nex;
            }
        }
    }

    // A tenant-aware JNDI Initial Context Factory implementation.
    private static class CarbonInitialJNDIContextFactory implements InitialContextFactory {

        private InitialContextFactory factory;

        public CarbonInitialJNDIContextFactory(InitialContextFactory factory) {
            this.factory = factory;
        }

        public Context getInitialContext(Hashtable<?, ?> h) throws NamingException {
            return new CarbonInitialJNDIContext(factory.getInitialContext(h));
        }
    }

    // A tenant-aware JNDI Initial Context implementation.
    private static class CarbonInitialJNDIContext implements EventDirContext, LdapContext {

        private Context initialContext;
        private Map<String, Context> contextCache =
                Collections.synchronizedMap(new HashMap<String, Context>());
        private static ContextCleanupTask contextCleanupTask;
        private static List<String> superTenantOnlyUrlContextSchemes;
        private static List<String> allTenantUrlContextSchemes;

        static {
            contextCleanupTask = new ContextCleanupTask();
            registerUnloadTenantTask(contextCleanupTask);
            superTenantOnlyUrlContextSchemes = Arrays.asList(
                    CarbonUtils.getServerConfiguration().getProperties(
                            "JNDI.Restrictions.SuperTenantOnly.UrlContexts.UrlContext.Scheme"));
            allTenantUrlContextSchemes = Arrays.asList(
                    CarbonUtils.getServerConfiguration().getProperties(
                            "JNDI.Restrictions.AllTenants.UrlContexts.UrlContext.Scheme"));
        }

        public CarbonInitialJNDIContext(Context initialContext) throws NamingException {
            this.initialContext = initialContext;
        }

        private static String getScheme(String url) {
            if (null == url) {
                return null;
            }
            int colPos = url.indexOf(':');
            if (colPos < 0) {
                return null;
            }
            String scheme = url.substring(0, colPos);
            char c;
            boolean inCharSet;
            for (int i = 0; i < scheme.length(); i++) {
                c = scheme.charAt(i);
                inCharSet = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
                            || (c >= '0' && c <= '9') || c == '+' || c == '.'
                            || c == '-' || c == '_';
                if (!inCharSet) {
                    return null;
                }
            }
            return scheme;
        }

        private Context getInitialContext(Name name) {
            return getInitialContext(name.get(0));
        }

        private Context getInitialContext() {
            return getInitialContext((String) null);
        }

        private boolean isBaseContextRequested() {

            try {
                String baseContextRequested = (String) this.initialContext.getEnvironment().
                        get(CarbonConstants.REQUEST_BASE_CONTEXT);
                if (baseContextRequested != null && baseContextRequested.equals("true")) {
                    return true;
                }
            } catch (NamingException e) {
                log.warn(
                        "An error occurred while retrieving environment properties from initial context.",
                        e);
            }

            return false;
        }

        private Context getInitialContext(String name) {

            /**
             * If environment is requesting a base context return the
             * base context.
             */

            if (isBaseContextRequested()) {
                return initialContext;
            }

            Context base = null;
            String scheme = null;
            if (name != null) {
                // If the name has components
                scheme = getScheme(name);
                if (scheme != null) {
                    if (contextCache.containsKey(scheme)) {
                        base = contextCache.get(scheme);
                    } else {
                        try {
                            Context urlContext = NamingManager.getURLContext(scheme,
                                                                             initialContext.getEnvironment());
                            if (urlContext != null) {
                                contextCache.put(scheme, urlContext);
                                base = urlContext;
                            }
                        } catch (NamingException ignored) {
                            // If we are unable to find the context, we use the default context.
                            if (log.isDebugEnabled()) {
                                log.debug("If we are unable to find the context, we use the default context.", ignored);
                            }
                        }
                    }
                }
            }
            if (base == null) {
                base = initialContext;
                scheme = null;
            }
            int tenantId = getThreadLocalCarbonContextHolder().getTenantId();
            if (!isSubTenant(tenantId)) {
                return base;
            } else if (scheme != null) {
                if (allTenantUrlContextSchemes.contains(scheme)) {
                    return base;
                } else if (superTenantOnlyUrlContextSchemes.contains(scheme)) {
                    throw new SecurityException("Tenants are not allowed to use JNDI contexts " +
                                                "with scheme: " + scheme);
                }
            }
            String tenantContextName = Integer.toString(tenantId);
            Context subContext;
            try {
                subContext = (Context) base.lookup(tenantContextName);
                if (subContext != null) {
                    return subContext;
                }
            } catch (NamingException ignored) {
                // Depending on the JNDI Initial Context factory, the above operation may or may not
                // throw an exception. But, since we don't mind the exception, we can ignore it.
                if (log.isDebugEnabled()) {
                    log.debug(ignored);
                }

            }
            try {
                log.debug("Creating Sub-Context: " + tenantContextName);
                subContext = base.createSubcontext(tenantContextName);
                contextCleanupTask.register(tenantId, subContext);
                if (subContext == null) {
                    throw new RuntimeException("Initial context was not created for tenant: " +
                                               tenantId);
                }
                return subContext;
            } catch (NamingException e) {
                throw new RuntimeException("An error occurred while creating the initial context " +
                                           "for tenant: " + tenantId, e);
            }
        }

        private static class ContextCleanupTask implements UnloadTenantTask<Context> {

            private Map<Integer, ArrayList<Context>> contexts
                    = new ConcurrentHashMap<Integer, ArrayList<Context>>();

            public void register(int tenantId, Context context) {
                ArrayList<Context> list = contexts.get(tenantId);
                if (list == null) {
                    list = new ArrayList<Context>();
                    list.add(context);
                    contexts.put(tenantId, list);
                } else if (!list.contains(context)) {
                    list.add(context);
                }
            }

            public void cleanup(int tenantId) {
                ArrayList<Context> list = contexts.remove(tenantId);
                // We need to close the context in a LIFO fashion.
                if (list != null) {
                    Collections.reverse(list);
                    for (Context context : list) {
                        try {
                            context.close();
                        } catch (NamingException ignore) {
                            // We are not worried about the exception thrown here, as we are simply
                            // doing a routine cleanup.
                            if (log.isDebugEnabled()) {
                                log.debug("Exception while outine cleanup", ignore);
                            }
                        }
                    }
                    list.clear();
                }
            }
        }

        public Object lookup(String s) throws NamingException {
            return getInitialContext(s).lookup(s);
        }

        public Object lookup(Name name) throws NamingException {
            return getInitialContext(name).lookup(name);
        }

        public void bind(String s, Object o) throws NamingException {
            getInitialContext(s).bind(s, o);
        }

        public void bind(Name name, Object o) throws NamingException {
            getInitialContext(name).bind(name, o);
        }

        public void rebind(String s, Object o) throws NamingException {
            getInitialContext(s).rebind(s, o);
        }

        public void rebind(Name name, Object o) throws NamingException {
            getInitialContext(name).rebind(name, o);
        }

        public void unbind(String s) throws NamingException {
            getInitialContext(s).unbind(s);
        }

        public void unbind(Name name) throws NamingException {
            getInitialContext(name).unbind(name);
        }

        public void rename(String s, String s1) throws NamingException {
            getInitialContext(s).rename(s, s1);
        }

        public void rename(Name name, Name name1) throws NamingException {
            getInitialContext(name).rename(name, name1);
        }

        public NamingEnumeration<NameClassPair> list(String s) throws NamingException {
            return getInitialContext(s).list(s);
        }

        public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
            return getInitialContext(name).list(name);
        }

        public NamingEnumeration<Binding> listBindings(String s) throws NamingException {
            return getInitialContext(s).listBindings(s);
        }

        public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
            return getInitialContext(name).listBindings(name);
        }

        public void destroySubcontext(String s) throws NamingException {
            getInitialContext(s).destroySubcontext(s);
        }

        public void destroySubcontext(Name name) throws NamingException {
            getInitialContext(name).destroySubcontext(name);
        }

        public Context createSubcontext(String s) throws NamingException {
            return getInitialContext(s).createSubcontext(s);
        }

        public Context createSubcontext(Name name) throws NamingException {
            return getInitialContext(name).createSubcontext(name);
        }

        public Object lookupLink(String s) throws NamingException {
            return getInitialContext(s).lookupLink(s);
        }

        public Object lookupLink(Name name) throws NamingException {
            return getInitialContext(name).lookupLink(name);
        }

        public NameParser getNameParser(String s) throws NamingException {
            return getInitialContext(s).getNameParser(s);
        }

        public NameParser getNameParser(Name name) throws NamingException {
            return getInitialContext(name).getNameParser(name);
        }

        public String composeName(String s, String s1) throws NamingException {
            return getInitialContext(s).composeName(s, s1);
        }

        public Name composeName(Name name, Name name1) throws NamingException {
            return getInitialContext(name).composeName(name, name1);
        }

        public Object addToEnvironment(String s, Object o) throws NamingException {
            return getInitialContext().addToEnvironment(s, o);
        }

        public Object removeFromEnvironment(String s) throws NamingException {
            return getInitialContext().removeFromEnvironment(s);
        }

        public Hashtable<?, ?> getEnvironment() throws NamingException {
            if (isSubTenant(getThreadLocalCarbonContextHolder().getTenantId())) {
                throw new NamingException("Tenants cannot retrieve the environment.");
            }
            return getInitialContext().getEnvironment();
        }

        public void close() throws NamingException {
            if (isSubTenant(getThreadLocalCarbonContextHolder().getTenantId()) &&
                !isBaseContextRequested()) {
                CarbonUtils.checkSecurity();
            }

            Context ctx = this.getInitialContext();
            /* the below condition is there, because of a bug in Tomcat JNDI context close method,
             * see org.apache.naming.NamingContext#close() */
            if (!ctx.getClass().getName().equals("org.apache.naming.SelectorContext")) {
                ctx.close();
            }
        }

        public String getNameInNamespace() throws NamingException {
            return getInitialContext().getNameInNamespace();
        }

        public int hashCode() {
            return initialContext.hashCode();
        }

        public boolean equals(Object o) {
            return (o instanceof CarbonInitialJNDIContext) && initialContext.equals(o);
        }

        ////////////////////////////////////////////////////////
        // Methods Required by a DirContext
        ////////////////////////////////////////////////////////

        private DirContext getDirectoryContext(Name name) throws NamingException {
            return getDirectoryContext(name.get(0));
        }

        private DirContext getDirectoryContext() throws NamingException {
            return getDirectoryContext((String) null);
        }

        private DirContext getDirectoryContext(String name) throws NamingException {
            Context initialContext = getInitialContext(name);
            if (initialContext instanceof DirContext) {
                return (DirContext) initialContext;
            }
            throw new NamingException("The given Context is not an instance of "
                                      + DirContext.class.getName());
        }

        public Attributes getAttributes(Name name) throws NamingException {
            return getDirectoryContext(name).getAttributes(name);
        }

        public Attributes getAttributes(String s) throws NamingException {
            return getDirectoryContext(s).getAttributes(s);
        }

        public Attributes getAttributes(Name name, String[] strings) throws NamingException {
            return getDirectoryContext(name).getAttributes(name, strings);
        }

        public Attributes getAttributes(String s, String[] strings)
                throws NamingException {
            return getDirectoryContext(s).getAttributes(s, strings);
        }

        public void modifyAttributes(Name name, int i, Attributes attributes)
                throws NamingException {
            getDirectoryContext(name).modifyAttributes(name, i, attributes);
        }

        public void modifyAttributes(String s, int i, Attributes attributes)
                throws NamingException {
            getDirectoryContext(s).modifyAttributes(s, i, attributes);
        }

        public void modifyAttributes(Name name, ModificationItem[] modificationItems)
                throws NamingException {
            getDirectoryContext(name).modifyAttributes(name, modificationItems);
        }

        public void modifyAttributes(String s, ModificationItem[] modificationItems)
                throws NamingException {
            getDirectoryContext(s).modifyAttributes(s, modificationItems);
        }

        public void bind(Name name, Object o, Attributes attributes) throws NamingException {
            getDirectoryContext(name).bind(name, o, attributes);
        }

        public void bind(String s, Object o, Attributes attributes) throws NamingException {
            getDirectoryContext(s).bind(s, o, attributes);
        }

        public void rebind(Name name, Object o, Attributes attributes) throws NamingException {
            getDirectoryContext(name).rebind(name, o, attributes);
        }

        public void rebind(String s, Object o, Attributes attributes) throws NamingException {
            getDirectoryContext(s).rebind(s, o, attributes);
        }

        public DirContext createSubcontext(Name name, Attributes attributes)
                throws NamingException {
            return getDirectoryContext(name).createSubcontext(name, attributes);
        }

        public DirContext createSubcontext(String s, Attributes attributes)
                throws NamingException {
            return getDirectoryContext(s).createSubcontext(s, attributes);
        }

        public DirContext getSchema(Name name) throws NamingException {
            return getDirectoryContext(name).getSchema(name);
        }

        public DirContext getSchema(String s) throws NamingException {
            return getDirectoryContext(s).getSchema(s);
        }

        public DirContext getSchemaClassDefinition(Name name) throws NamingException {
            return getDirectoryContext(name).getSchemaClassDefinition(name);
        }

        public DirContext getSchemaClassDefinition(String s) throws NamingException {
            return getDirectoryContext(s).getSchemaClassDefinition(s);
        }

        public NamingEnumeration<SearchResult> search(Name name, Attributes attributes,
                                                      String[] strings) throws NamingException {
            return getDirectoryContext(name).search(name, attributes, strings);
        }

        public NamingEnumeration<SearchResult> search(String s, Attributes attributes,
                                                      String[] strings)
                throws NamingException {
            return getDirectoryContext(s).search(s, attributes, strings);
        }

        public NamingEnumeration<SearchResult> search(Name name, Attributes attributes)
                throws NamingException {
            return getDirectoryContext(name).search(name, attributes);
        }

        public NamingEnumeration<SearchResult> search(String s, Attributes attributes)
                throws NamingException {
            return getDirectoryContext(s).search(s, attributes);
        }

        public NamingEnumeration<SearchResult> search(Name name, String filter,
                                                      SearchControls searchControls)
                throws NamingException {
            return getDirectoryContext(name).search(name, filter, searchControls);
        }

        public NamingEnumeration<SearchResult> search(String s, String filter,
                                                      SearchControls searchControls)
                throws NamingException {
            return getDirectoryContext(s).search(s, filter, searchControls);
        }

        public NamingEnumeration<SearchResult> search(Name name, String filter, Object[] objects,
                                                      SearchControls searchControls)
                throws NamingException {
            return getDirectoryContext(name).search(name, filter, objects, searchControls);
        }

        public NamingEnumeration<SearchResult> search(String s, String filter, Object[] objects,
                                                      SearchControls searchControls)
                throws NamingException {
            return getDirectoryContext(s).search(s, filter, objects, searchControls);
        }

        ////////////////////////////////////////////////////////
        // Methods Required by a LdapContext
        ////////////////////////////////////////////////////////

        private LdapContext getLdapContext() throws NamingException {
            DirContext dirContext = getDirectoryContext();
            if (dirContext instanceof EventContext) {
                return (LdapContext) dirContext;
            }
            throw new NamingException("The given Context is not an instance of "
                                      + LdapContext.class.getName());
        }

        public ExtendedResponse extendedOperation(ExtendedRequest extendedRequest)
                throws NamingException {
            return getLdapContext().extendedOperation(extendedRequest);
        }

        public LdapContext newInstance(Control[] controls) throws NamingException {
            return getLdapContext().newInstance(controls);
        }

        public void reconnect(Control[] controls) throws NamingException {
            getLdapContext().reconnect(controls);
        }

        public Control[] getConnectControls() throws NamingException {
            return getLdapContext().getConnectControls();
        }

        public void setRequestControls(Control[] controls) throws NamingException {
            getLdapContext().setRequestControls(controls);
        }

        public Control[] getRequestControls() throws NamingException {
            return getLdapContext().getRequestControls();
        }

        public Control[] getResponseControls() throws NamingException {
            return getLdapContext().getResponseControls();
        }

        ////////////////////////////////////////////////////////
        // Methods Required by a EventContext
        ////////////////////////////////////////////////////////

        private EventContext getEventContext(Name name) throws NamingException {
            return getEventContext(name.get(0));
        }

        private EventContext getEventContext() throws NamingException {
            return getEventContext((String) null);
        }

        private EventContext getEventContext(String name) throws NamingException {
            Context initialContext = getInitialContext(name);
            if (initialContext instanceof EventContext) {
                return (EventContext) initialContext;
            }
            throw new NamingException("The given Context is not an instance of "
                                      + EventContext.class.getName());
        }

        public void addNamingListener(Name name, int i, NamingListener namingListener)
                throws NamingException {
            CarbonUtils.checkSecurity();
            getEventContext(name).addNamingListener(name, i, namingListener);
        }

        public void addNamingListener(String s, int i, NamingListener namingListener)
                throws NamingException {
            CarbonUtils.checkSecurity();
            getEventContext(s).addNamingListener(s, i, namingListener);
        }

        public void removeNamingListener(NamingListener namingListener) throws NamingException {
            CarbonUtils.checkSecurity();
            getEventContext().removeNamingListener(namingListener);
        }

        public boolean targetMustExist() throws NamingException {
            return getEventContext().targetMustExist();
        }

        ////////////////////////////////////////////////////////
        // Methods Required by a EventDirContext
        ////////////////////////////////////////////////////////

        private EventDirContext getEventDirContext(Name name) throws NamingException {
            return getEventDirContext(name.get(0));
        }

        private EventDirContext getEventDirContext(String name) throws NamingException {
            EventContext eventContext = getEventContext(name);
            if (eventContext instanceof EventDirContext) {
                return (EventDirContext) eventContext;
            }
            throw new NamingException("The given Context is not an instance of "
                                      + EventDirContext.class.getName());
        }

        public void addNamingListener(Name name, String filter, SearchControls searchControls,
                                      NamingListener namingListener) throws NamingException {
            CarbonUtils.checkSecurity();
            getEventDirContext(name)
                    .addNamingListener(name, filter, searchControls, namingListener);
        }

        public void addNamingListener(String s, String filter, SearchControls searchControls,
                                      NamingListener namingListener) throws NamingException {
            CarbonUtils.checkSecurity();
            getEventDirContext(s).addNamingListener(s, filter, searchControls, namingListener);
        }

        public void addNamingListener(Name name, String filter, Object[] objects,
                                      SearchControls searchControls, NamingListener namingListener)
                throws NamingException {
            CarbonUtils.checkSecurity();
            getEventDirContext(name).addNamingListener(name, filter, objects, searchControls,
                                                       namingListener);
        }

        public void addNamingListener(String s, String filter, Object[] objects,
                                      SearchControls searchControls, NamingListener namingListener)
                throws NamingException {
            CarbonUtils.checkSecurity();
            getEventDirContext(s).addNamingListener(s, filter, objects, searchControls,
                                                    namingListener);
        }
    }

    private static class CarbonAuthenticator extends Authenticator {

        private static class AuthenticatorBean {

            private Pattern pattern;
            private PasswordAuthentication credential;

            public AuthenticatorBean(String regEx, String username, String password) {
                this.pattern = Pattern.compile(regEx);
                credential = new PasswordAuthentication(username, password.toCharArray());
            }

            public PasswordAuthentication getPasswordAuthentication() {
                return credential;
            }

            public boolean matches(String protocol, String host, int port) {
                return pattern.matcher((protocol + "://" + host + ':' + port).toLowerCase()).matches();
            }

            public boolean matches(URL url) {
                return pattern.matcher(url.toString()).matches();
            }
        }

        private List<AuthenticatorBean> proxyAuthenticators = new LinkedList<AuthenticatorBean>();
        private List<AuthenticatorBean> serverAuthenticators = new LinkedList<AuthenticatorBean>();

        public void addAuthenticator(String type, String regEx, String username, String password) {
            if (type.equalsIgnoreCase("proxy")) {
                proxyAuthenticators.add(new AuthenticatorBean(regEx, username, password));
            } else if (type.equalsIgnoreCase("server")) {
                serverAuthenticators.add(new AuthenticatorBean(regEx, username, password));
            }
        }

        protected PasswordAuthentication getPasswordAuthentication() {
            if (Authenticator.RequestorType.PROXY.equals(getRequestorType())) {
                for (AuthenticatorBean authenticator : proxyAuthenticators) {
                    if (authenticator.matches(getRequestingProtocol(), getRequestingHost(),
                                              getRequestingPort()) || authenticator.matches(getRequestingURL())) {
                        return authenticator.getPasswordAuthentication();
                    }
                }
            } else if (Authenticator.RequestorType.SERVER.equals(getRequestorType())) {
                for (AuthenticatorBean authenticator : serverAuthenticators) {
                    if (authenticator.matches(getRequestingScheme(), getRequestingHost(),
                                              getRequestingPort()) || authenticator.matches(getRequestingURL())) {
                        return authenticator.getPasswordAuthentication();
                    }
                }
            }
            return super.getPasswordAuthentication();
        }
    }

    // loads a class.
    private static Class<?> classForName(final String className)
            throws ClassNotFoundException {

        Class<?> cls = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
            public Class<?> run() {
                // try thread context class loader first
                try {
                    return Class.forName(className, true, Thread
                            .currentThread().getContextClassLoader());
                } catch (ClassNotFoundException ignored) {
                    if (log.isDebugEnabled()) {
                        log.debug(ignored);
                    }

                }
                // try system class loader second
                try {
                    return Class.forName(className, true, ClassLoader
                            .getSystemClassLoader());
                } catch (ClassNotFoundException ignored) {
                    if (log.isDebugEnabled()) {
                        log.debug(ignored);
                    }
                }
                // return null, if fail to load class
                return null;
            }
        });

        if (cls == null) {
            throw new ClassNotFoundException("class " + className + " not found");
        }

        return cls;
    }

    /**
     * Method to obtain an instance to the Discovery Service.
     *
     * @return instance of the Discovery Service
     */
    public static DiscoveryService getDiscoveryServiceProvider() {
        return discoveryServiceProvider.get();
    }

    /**
     * Method to define the instance of the Discovery Service.
     *
     * @param discoveryServiceProvider the Discovery Service instance.
     */
    public static void setDiscoveryServiceProvider(DiscoveryService discoveryServiceProvider) {
        CarbonContextDataHolder.discoveryServiceProvider.set(discoveryServiceProvider);
    }

    /**
     * Method to obtain the current carbon context holder's base.
     *
     * @return the current carbon context holder's base.
     */
    public static CarbonContextDataHolder getCurrentCarbonContextHolderBase() {
        return currentContextHolder.get();
    }

    /**
     * Method to register a task that will be executed when a tenant is
     * unloaded.
     *
     * @param unloadTenantTask the task to run.
     * @see UnloadTenantTask
     */
    public static synchronized void registerUnloadTenantTask(
            UnloadTenantTask unloadTenantTask) {
        if (log.isDebugEnabled()) {
            log.debug("Unload Tenant Task: "
                      + unloadTenantTask.getClass().getName() + " was "
                      + "registered.");
        }
        unloadTenantTasks.add(unloadTenantTask);
    }

    /**
     * Method that will be called when a tenant is unloaded. This will run all
     * the corresponding tasks that have been registered to be called when a
     * tenant is unloaded.
     *
     * @param tenantId the tenant's identifier.
     */
    public static void unloadTenant(int tenantId) {
        log.debug("Started unloading tenant");
        for (UnloadTenantTask unloadTenantTask : unloadTenantTasks) {
            unloadTenantTask.cleanup(tenantId);
        }
        log.info("Completed unloading tenant");
    }

    /**
     * Starts a tenant flow. This will stack the current CarbonContext and begin
     * a new nested flow which can have an entirely different context. This is
     * ideal for scenarios where multiple super-tenant and sub-tenant phases are
     * required within as a single block of execution.
     */
    public void startTenantFlow() {
        Stack<CarbonContextDataHolder> carbonContextDataHolders = parentContextHolderStack.get();
        if(carbonContextDataHolders == null){
            carbonContextDataHolders = new Stack<CarbonContextDataHolder>();
            parentContextHolderStack.set(carbonContextDataHolders);
        }
        carbonContextDataHolders.push(currentContextHolder.get());
        currentContextHolder.remove();
    }

    /**
     * This will end the tenant flow and restore the previous CarbonContext.
     */
    public void endTenantFlow() {
        Stack<CarbonContextDataHolder> carbonContextDataHolders = parentContextHolderStack.get();
        if (carbonContextDataHolders != null) {
            currentContextHolder.set(carbonContextDataHolders.pop());
        }
    }

    /**
     * Default constructor to disallow creation of the CarbonContext.
     */
    private CarbonContextDataHolder() {
        this.tenantId = org.wso2.carbon.base.MultitenantConstants.INVALID_TENANT_ID;
        this.username = null;
        this.tenantDomain = null;
    }

    /**
     * Constructor that can be used to create clones.
     *
     * @param carbonContextHolder the CarbonContext holder instance of which the clone will be
     *                            created from.
     */
    public CarbonContextDataHolder(CarbonContextDataHolder carbonContextHolder) {
        this.tenantId = carbonContextHolder.tenantId;
        this.username = carbonContextHolder.username;
        this.tenantDomain = carbonContextHolder.tenantDomain;
        if (carbonContextHolder.properties != null) {
            this.properties = new HashMap<String, Object>(carbonContextHolder.properties);
        }
    }

    /**
     * Method to obtain the tenant id on this CarbonContext instance.
     *
     * @return the tenant id.
     */
    public int getTenantId() {
        return tenantId;
    }

    /**
     * Method to set the tenant id on this CarbonContext instance.
     *
     * @param tenantId the tenant id.
     */
    public void setTenantId(int tenantId) {
        try {
            if (this.tenantId == org.wso2.carbon.base.MultitenantConstants.INVALID_TENANT_ID ||
                this.tenantId == org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_ID) {
                this.tenantId = tenantId;
            } else if (this.tenantId != tenantId) {
                StackTraceElement[] traces = Thread.currentThread().getStackTrace();
                if (!isAllowedToChangeTenantDomain(traces)) {
                    throw new IllegalStateException("Trying to set the domain from " + this.tenantId + " to " + tenantId);
                }
            }
        } catch (IllegalStateException e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * Method to obtain the username on this CarbonContext instance.
     *
     * @return the username.
     */
    public String getUsername() {
        return username;
    }

    /**
     * Method to set the username on this CarbonContext instance.
     *
     * @param username the username.
     */
    public void setUsername(String username) {
        CarbonUtils.checkSecurity();
        this.username = username;
    }

    /**
     * Method to obtain the tenant domain on this CarbonContext instance.
     *
     * @return the tenant domain.
     */
    public String getTenantDomain() {
        return tenantDomain;
    }

    /**
     * Method to set the tenant domain on this CarbonContext instance.
     *
     * @param domain the tenant domain.
     */
    public void setTenantDomain(String domain) {
        try {
            if (this.tenantDomain == null ||
                this.tenantDomain.equals(org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
                this.tenantDomain = domain;
            } else if (!tenantDomain.equals(domain)) {
                StackTraceElement[] traces = Thread.currentThread().getStackTrace();
                if (!isAllowedToChangeTenantDomain(traces)) {
                    throw new IllegalStateException("Trying to set the domain from " + this.tenantDomain + " to " + domain);
                }
            }
        } catch (IllegalStateException e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * Method to obtain a property on this CarbonContext instance.
     *
     * @param name the property name.
     * @return the value of the property by the given name.
     */
    public Object getProperty(String name) {
        if (properties == null) {
            return null;
        }
        return properties.get(name);
    }

    /**
     * Method to set a property on this CarbonContext instance.
     *
     * @param name  the property name.
     * @param value the value to be set to the property by the given name.
     */
    public void setProperty(String name, Object value) {
        if (properties == null) {
            properties = new HashMap<String, Object>();
        }
        properties.put(name, value);
    }

    // Method to cleanup all properties.
    private void cleanupProperties() {
        // This method would be called to reclaim memory. Therefore, this might
        // be called on an
        // object which has been partially garbage collected. Even unlikely, it
        // might be possible
        // that the object exists without any field-references, until all
        // WeakReferences are
        // cleaned-up.
        if (properties != null) {
            properties.clear();
        }
    }

    private boolean isAllowedToChangeTenantDomain(StackTraceElement[] traces) {
        boolean allowChange = false;
        if ((traces.length > CARBON_AUTHENTICATION_UTIL_INDEX) &&
            (traces[CARBON_AUTHENTICATION_UTIL_INDEX].getClassName().equals(CARBON_AUTHENTICATION_UTIL_CLASS))) {
            allowChange = true;
        } else if ((traces.length > CARBON_AUTHENTICATION_HANDLER_INDEX) &&
                   traces[CARBON_AUTHENTICATION_HANDLER_INDEX].getClassName().equals(CARBON_AUTHENTICATION_HANDLER_CLASS)) {
            allowChange = true;
        }
        return allowChange;
    }

    /**
     * This method will destroy the current CarbonContext holder.
     */
    public static void destroyCurrentCarbonContextHolder() {
        currentContextHolder.remove();
        parentContextHolderStack.remove();
    }

    private static class CarbonContextCleanupTask implements
                                                  UnloadTenantTask<CarbonContextDataHolder> {

        private Map<Integer, ArrayList<WeakReference<CarbonContextDataHolder>>> contextHolderList =
                new ConcurrentHashMap<Integer, ArrayList<WeakReference<CarbonContextDataHolder>>>();

        public void register(int tenantId,
                             CarbonContextDataHolder contextHolderBase) {
            ArrayList<WeakReference<CarbonContextDataHolder>> list = contextHolderList
                    .get(tenantId);
            if (list == null) {
                list = new ArrayList<WeakReference<CarbonContextDataHolder>>();
                list.add(new WeakReference<CarbonContextDataHolder>(
                        contextHolderBase));
                contextHolderList.put(tenantId, list);
            } else {
                list.add(new WeakReference<CarbonContextDataHolder>(
                        contextHolderBase));
            }
        }

        public void cleanup(int tenantId) {
            ArrayList<WeakReference<CarbonContextDataHolder>> list = contextHolderList
                    .remove(tenantId);
            if (list != null) {
                for (WeakReference<CarbonContextDataHolder> carbonContextHolderBaseRef : list) {
                    CarbonContextDataHolder carbonContextHolderBase =
                            carbonContextHolderBaseRef.get();
                    if (carbonContextHolderBase != null) {
                        carbonContextHolderBase.cleanupProperties();
                    }
                }
                list.clear();
            }
        }
    }
}


text:
package br.edu.ifmt.cba.alphalab.gui.javafx.controller.laboratorio;

import java.net.URL;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;

import br.edu.ifmt.cba.alphalab.business.Reserva;
import br.edu.ifmt.cba.alphalab.dao.DAOFactory;
import br.edu.ifmt.cba.alphalab.dao.mock.laboratorio.MockLaboratorioDAO;
import br.edu.ifmt.cba.alphalab.entity.laboratorio.DepartamentoEntity;
import br.edu.ifmt.cba.alphalab.entity.laboratorio.EnumDisciplina;
import br.edu.ifmt.cba.alphalab.entity.laboratorio.EnumReserva;
import br.edu.ifmt.cba.alphalab.entity.laboratorio.EnumTipoReserva;
import br.edu.ifmt.cba.alphalab.entity.laboratorio.Horario;
import br.edu.ifmt.cba.alphalab.entity.laboratorio.LaboratorioEntity;
import br.edu.ifmt.cba.alphalab.entity.laboratorio.ReservaEntity;
import br.edu.ifmt.cba.alphalab.entity.pessoa.ServidorEntity;
import br.edu.ifmt.cba.alphalab.gui.javafx.controller.exemplo.FrmPrincipal;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;

public class FrmGerenciarHorario implements Initializable {

	@FXML
	private Tab tabVisualizar;

	@FXML
	private ComboBox<LaboratorioEntity> cmbLaboratorio;

	@FXML
	private Button btnProximo;

	@FXML
	private TableView<Horario> tblGerenciarHorario;

	@FXML
	private TableColumn<Horario, String> tbcHorario;

	@FXML
	private TableColumn<Horario, HorarioAdapter> tbcSegunda;

	@FXML
	private TableColumn<Horario, HorarioAdapter> tbcTerca;

	@FXML
	private TableColumn<Horario, HorarioAdapter> tbcQuarta;

	@FXML
	private TableColumn<Horario, HorarioAdapter> tbcQuinta;

	@FXML
	private TableColumn<Horario, HorarioAdapter> tbcSexta;

	@FXML
	private TableColumn<Horario, HorarioAdapter> tbcSabado;

	@FXML
	private TableColumn<Horario, HorarioAdapter> tbcDomingo;

	@FXML
	private TabPane tbpDados;

	@FXML
	private Tab tabPreencherDados;

	@FXML
	private Text texLaboratorio;

	@FXML
	private ComboBox<ServidorEntity> cmbProfessor;

	@FXML
	private ComboBox<EnumDisciplina> cmbDisciplina;

	@FXML
	private ComboBox<DepartamentoEntity> cmbDepartamento;

	@FXML
	private HBox hbxHorarios;

	@FXML
	private TextField txtTurma;

	@FXML
	private TextArea txaObservacoes;

	@FXML
	private Button btnConfirmar;

	@FXML
	private Button btnVoltar;

	ResourceBundle resources = ResourceBundle.getBundle(FrmPrincipal.LINGUA_PORTUGUES);

	private List<ReservaEntity> reservas = new ArrayList<ReservaEntity>(
			DAOFactory.getDAOFactory().getReservaDAO().getAtivosNaSemana(LocalDate.now()));

	private List<ReservaEntity> reservasFiltradas = new ArrayList<>();

	private ArrayList<HorarioAdapter> matriz = new ArrayList<>();

	private ArrayList<StackPane> listaSelecionados = new ArrayList<>();

	private Set<TableColumn<Horario, HorarioAdapter>> diasAReservar = new HashSet<>();

	private List<ReservaEntity> novasReservas = new ArrayList<>();

	static final Comparator<ReservaEntity> DATA_INICIO = new Comparator<ReservaEntity>() {
		public int compare(ReservaEntity r1, ReservaEntity r2) {
			return r1.getDataInicio().compareTo(r2.getDataInicio());
		}
	};

	@FXML
	void btnConfirmar_onAction(ActionEvent event) {
		Alert alerta = new Alert(Alert.AlertType.CONFIRMATION);
		ButtonType sim = new ButtonType("Sim");
		ButtonType nao = new ButtonType("Não");
		alerta.setTitle("AlphaLab");
		alerta.setHeaderText("Confirmar Reserva de Horário");
		alerta.setContentText("Deseja confirmar as Reservas de Horário?");
		alerta.getButtonTypes().setAll(sim, nao);

		alerta.showAndWait().ifPresent(option -> {
			if (option == sim) {
				Reserva salvarReserva = new Reserva(DAOFactory.getDAOFactory().getReservaDAO());
				for (ReservaEntity reserva : novasReservas) {
					setDados(reserva);

					if (reserva.validar() == null) {
						salvarReserva.save(reserva);
					} else {
						Alert alertaDadosInvalidos = new Alert(Alert.AlertType.INFORMATION);
						alertaDadosInvalidos.setTitle("AlphaLab");
						alertaDadosInvalidos.setHeaderText("Dados inconsistentes!");
						alertaDadosInvalidos.setContentText(reserva.validar().getMessage());

						alertaDadosInvalidos.show();
						break;
					}
				}
				tbpDados.getSelectionModel().select(tabVisualizar);
				tabPreencherDados.setDisable(true);
				tabVisualizar.setDisable(false);
				atualizarReservas();
				cmbLaboratorio_onAction(new ActionEvent());
			} else {
				alerta.close();
			}
		});
	}

	@FXML
	void btnProximo_onAction(ActionEvent event) {
		String string = getDadosTabVisualizar();

		if (string.length() > 0) {
			Alert alerta = new Alert(AlertType.INFORMATION);
			alerta.setTitle("AlphaLab");
			alerta.setHeaderText("Dados de Requisitos");
			alerta.setContentText(string);
			alerta.show();
		} else {
			tabVisualizar.setDisable(true);
			tabPreencherDados.setDisable(false);
			tbpDados.getSelectionModel().select(tabPreencherDados);
			texLaboratorio.setText(cmbLaboratorio.getValue().getNome());
			if (hbxHorarios.getChildren() != null)
				hbxHorarios.getChildren().clear();
			criarNovasReservas();
			hbxHorarios.getChildren().addAll(buildBoxHorario());
			cmbProfessor.requestFocus();
		}
	}

	@FXML
	void btnProximo_onKeyPressed(KeyEvent event) {

	}

	@FXML
	void btnVoltar_onAction(ActionEvent event) {
		tabPreencherDados.setDisable(true);
		tabVisualizar.setDisable(false);
		tbpDados.getSelectionModel().select(tabVisualizar);
		cmbLaboratorio.requestFocus();
	}

	@FXML
	void cmbDepartamento_onAction(ActionEvent event) {

	}

	@FXML
	void cmbDisciplina_onAction(ActionEvent event) {

	}

	@FXML
	void cmbLaboratorio_onAction(ActionEvent event) {
		if (!listaSelecionados.isEmpty())
			listaSelecionados.clear();
		filtrarReservas();
		tblGerenciarHorario.refresh();
	}

	@FXML
	void cmbProfessor_onAction(ActionEvent event) {

	}

	@FXML
	void cmbProfessor_onKeyPressed(KeyEvent event) {

	}

	@FXML
	void txaObservacoes_onKeyPressed(KeyEvent event) {

	}

	@FXML
	void txtDisciplina_onKeyPressed(KeyEvent event) {

	}

	@FXML
	void txtTurma_onKeyPressed(KeyEvent event) {

	}

	@Override
	public void initialize(URL location, ResourceBundle resources) {
		for (int i = 1; i < 8; i++) {
			for (int j = 0; j < 16; j++) {
				matriz.add(new HorarioAdapter(i, j, new StackPane(), null));
			}
		}
		tabPreencherDados.setDisable(true);

		cmbDisciplina.getItems().setAll(EnumDisciplina.values());
		cmbLaboratorio.getItems().setAll(DAOFactory.getDAOFactory().getLaboratorioDAO().buscarTodos());
		cmbProfessor.getItems().setAll(DAOFactory.getDAOFactory().getServidorDAO().buscarTodosProfessores());
		cmbDepartamento.getItems().setAll(DAOFactory.getDAOFactory().getDepartamentoDAO().buscarTodos());

		fillColumns();
	}

	private void fillColumns() {
		String estilo = new String("-fx-alignment: CENTER;");

		// Inicializa coluna de horários
		tbcHorario.setCellValueFactory(conteudo -> new SimpleStringProperty(conteudo.getValue().getEstampa()));
		tbcHorario.setStyle(estilo);
		tblGerenciarHorario.getItems().addAll(Horario.values());

		// Implementação da rotina de criação de células para a matriz de horários
		tbcSegunda.setStyle(estilo);
		tbcSegunda.setCellFactory(col -> new TableCell<Horario, HorarioAdapter>() {
			@Override
			protected void updateItem(HorarioAdapter adapter, boolean empty) {
				super.updateItem(adapter, empty);
				updateCelula(this, adapter, empty);
			}
		});
		tbcTerca.setStyle(estilo);
		tbcTerca.setCellFactory(col -> new TableCell<Horario, HorarioAdapter>() {
			@Override
			protected void updateItem(HorarioAdapter adapter, boolean empty) {
				super.updateItem(adapter, empty);
				updateCelula(this, adapter, empty);
			}
		});
		tbcQuarta.setStyle(estilo);
		tbcQuarta.setCellFactory(col -> new TableCell<Horario, HorarioAdapter>() {
			@Override
			protected void updateItem(HorarioAdapter adapter, boolean empty) {
				super.updateItem(adapter, empty);
				updateCelula(this, adapter, empty);
			}
		});
		tbcQuinta.setStyle(estilo);
		tbcQuinta.setCellFactory(col -> new TableCell<Horario, HorarioAdapter>() {
			@Override
			protected void updateItem(HorarioAdapter adapter, boolean empty) {
				super.updateItem(adapter, empty);
				updateCelula(this, adapter, empty);
			}
		});
		tbcSexta.setStyle(estilo);
		tbcSexta.setCellFactory(col -> new TableCell<Horario, HorarioAdapter>() {
			@Override
			protected void updateItem(HorarioAdapter adapter, boolean empty) {
				super.updateItem(adapter, empty);
				updateCelula(this, adapter, empty);
			}
		});
		tbcSabado.setStyle(estilo);
		tbcSabado.setCellFactory(col -> new TableCell<Horario, HorarioAdapter>() {
			@Override
			protected void updateItem(HorarioAdapter adapter, boolean empty) {
				super.updateItem(adapter, empty);
				updateCelula(this, adapter, empty);
			}
		});
		tbcDomingo.setStyle(estilo);
		tbcDomingo.setCellFactory(col -> new TableCell<Horario, HorarioAdapter>() {
			@Override
			protected void updateItem(HorarioAdapter adapter, boolean empty) {
				super.updateItem(adapter, empty);
				updateCelula(this, adapter, empty);
			}
		});
	}

	/**
	 * O único propósito deste método é evitar a repetição de código dentro das
	 * implementações de updateItem das células da matriz
	 *
	 * @param celula
	 * @param txt
	 * @param empty
	 */
	private void updateCelula(TableCell<Horario, HorarioAdapter> celula, HorarioAdapter adapter, boolean empty) {

		if (empty) {
			celula.setGraphic(null);
		} else {
			adapter = matriz.get(
					((tblGerenciarHorario.getColumns().indexOf(celula.getTableColumn()) - 1) << 4) + celula.getIndex());
			adapter.clearPane();

			if (cmbLaboratorio.getSelectionModel().isEmpty()) {
				adapter.addNode(new Text("Selecione um lab."));
			} else {
				if (!reservasFiltradas.isEmpty()) {
					for (ReservaEntity reservaEntity : reservasFiltradas) {
						if (reservaEntity.getDataInicio().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
								.getDayOfWeek().getValue() == adapter.getColuna())
							for (Horario horario : reservaEntity.getHorarios()) {
								if (horario.ordinal() == adapter.getLinha()) {
									adapter.setReserva(reservaEntity);
									adapter.setHorario(horario);

									Button btn = new Button("X");
									btn.setTextFill(Color.RED);

									btn.setOnAction(new EventHandler<ActionEvent>() {

										@Override
										public void handle(ActionEvent event) {
											HorarioAdapter adapter = new HorarioAdapter();
											for (HorarioAdapter hAdapter : matriz) {
												if (hAdapter.getPane().equals(btn.getParent())) {
													adapter = hAdapter;
													break;
												}
											}

											SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
											String conteudo = new String(
													formatter.format(adapter.getReserva().getDataInicio())
															+ "\n-------------\n");
											for (Horario horario : adapter.getReserva().getHorarios()) {
												conteudo += (horario.getEstampa() + "\n");
											}

											Alert alerta = new Alert(Alert.AlertType.CONFIRMATION);
											ButtonType confirmar = new ButtonType(
													resources.getString("button.confirmar"));
											ButtonType cancelar = new ButtonType(
													resources.getString("button.cancelar"));
											alerta.setTitle("AlphaLab");
											alerta.setHeaderText("Cancelar de Reserva de Horário");
											alerta.setContentText(
													"Tem certeza que deseja cancelar esta Reserva de Horário?\n\n"
															+ conteudo);
											alerta.getButtonTypes().setAll(confirmar, cancelar);

											alerta.showAndWait().ifPresent(opcao -> {
												if (opcao == confirmar) {
													for (HorarioAdapter hAdapter : matriz) {
														if (hAdapter.getPane().equals(btn.getParent())) {
															hAdapter.getReserva().setStatus(EnumReserva.CANCELADA);
															atualizarReservas();
															tblGerenciarHorario.refresh();
															break;
														}
													}
												}
												if (opcao == cancelar) {
												}
											});
										}
									});

									adapter.addNode(new Text(reservaEntity.getSolicitante().getNome() + "\n"
											+ reservaEntity.getDisciplina().toString() + "\n"
											+ reservaEntity.getDepartamentoAula().getSigla() + " "
											+ reservaEntity.getTurma()));
									adapter.addNode(btn);
									StackPane.setAlignment(btn, Pos.CENTER_RIGHT);
								}
							}
					}
				}

				if (adapter.getPane().getChildren().isEmpty()) {
					ToggleButton btn = new ToggleButton(resources.getString("button.selecionar"));

					btn.setOnAction(new EventHandler<ActionEvent>() {

						@Override
						public void handle(ActionEvent event) {
							ToggleButton btn = (ToggleButton) event.getSource();
							if (btn.isSelected()) {
								listaSelecionados.add((StackPane) btn.getParent());
							} else {
								listaSelecionados.remove((StackPane) btn.getParent());
							}
						}
					});

					adapter.addNode(btn);
				}
			}
			celula.setGraphic(adapter.getPane());
		}

	}

	/**
	 * Povoa a lista reservasFiltradas de acordo com o filtro selecionado
	 */
	private void filtrarReservas() {
		reservasFiltradas.clear();
		if (!cmbLaboratorio.getSelectionModel().isEmpty())
			for (ReservaEntity reservaEntity : reservas) {
				if (reservaEntity.getLaboratorio().equals(cmbLaboratorio.getSelectionModel().getSelectedItem()))
					reservasFiltradas.add(reservaEntity);
			}
	}

	private String getDadosTabVisualizar() {
		StringBuilder string = new StringBuilder();
		if (cmbLaboratorio.getSelectionModel().isEmpty()) {
			string.append("Selecione um laboratório para ver os horário a gerenciar.\n");
		} else if (listaSelecionados.isEmpty()) {
			string.append("Ao menos um horário disponível deve ser selecionado!\n");
		}

		return string.toString();
	}

	private List<StackPane> buildBoxHorario() {
		List<StackPane> boxHorarios = new ArrayList<>();

		for (ReservaEntity reservaEntity : novasReservas) {

			VBox vbox = new VBox(7);
			vbox.setAlignment(Pos.CENTER);

			Rectangle rect = new Rectangle(100, 150);
			rect.setStroke(Color.BLACK);
			rect.setStrokeWidth(2);
			rect.setFill(Color.TRANSPARENT);

			Text data = new Text(new SimpleDateFormat("dd/MM/yyyy").format(reservaEntity.getDataInicio()));
			data.setFont(Font.font("Verdana", FontWeight.BOLD, 12.0));
			vbox.getChildren().add(data);

			for (Horario horario : reservaEntity.getHorarios()) {
				vbox.getChildren().add(new Text(horario.getEstampa()));
			}

			boxHorarios.add(new StackPane(rect, vbox));
		}

		return boxHorarios;
	}

	/**
	 * Inicializa as reservas para cada dia selecionado
	 */
	private void criarNovasReservas() {
		diasAReservar.clear();
		for (StackPane pane : listaSelecionados) {
			for (HorarioAdapter adapter : matriz) {
				if (adapter.getPane().equals(pane))
					diasAReservar.add((TableColumn<Horario, HorarioAdapter>) tblGerenciarHorario.getColumns()
							.get(adapter.getColuna()));
			}
		}

		LocalDate dtAux = LocalDate.now();
		if (!dtAux.getDayOfWeek().equals(DayOfWeek.MONDAY))
			dtAux = dtAux.minusDays((long) dtAux.getDayOfWeek().getValue() - 1);

		novasReservas.clear();
		for (TableColumn<Horario, HorarioAdapter> tableColumn : diasAReservar) {
			ReservaEntity novaReserva = new ReservaEntity();
			novaReserva
					.setDataInicio(Date.from((dtAux.plusDays(tblGerenciarHorario.getColumns().indexOf(tableColumn) - 1)
							.atStartOfDay(ZoneId.systemDefault()).toInstant())));
			novasReservas.add(novaReserva);
		}

		for (ReservaEntity reserva : novasReservas) {

			int k = ((reserva.getDataInicio().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getDayOfWeek()
					.getValue() - 1) << 4);
			if (reserva.getHorarios() != null) {
				reserva.getHorarios().clear();
			} else {
				reserva.setHorarios(new ArrayList<>());
			}

			for (int i = k; i < (k + 16); i++) {
				if (listaSelecionados.contains(matriz.get(i).getPane()))
					reserva.getHorarios().add(Horario.values()[matriz.get(i).getLinha()]);
			}
		}
		Collections.sort(novasReservas, DATA_INICIO);
	}

	private void setDados(ReservaEntity reserva) {
		reserva.setId(
				Long.parseLong("" + (DAOFactory.getDAOFactory().getReservaDAO().buscarTodasReservas().size() + 1)));
		reserva.setSolicitante(cmbProfessor.getValue());
		reserva.setDisciplina(cmbDisciplina.getValue());
		reserva.setDepartamentoAula(cmbDepartamento.getValue());
		reserva.setTurma(txtTurma.getText());
		reserva.setObservacao(txaObservacoes.getText());
		reserva.setDataSolicitacao(reserva.getDataInicio());
		reserva.setDataFim(reserva.getDataInicio());
		reserva.setDataAprovacaoRecusa(reserva.getDataInicio());
		reserva.setLaboratorio(cmbLaboratorio.getValue());
		// TODO Aprovador deve ser obtido automaticamente quando a funcionalidade de
		// login for implementada
		reserva.setAprovador(DAOFactory.getDAOFactory().getServidorDAO().getById(1L));
		reserva.setStatus(EnumReserva.CONFIRMADO);
		reserva.setTipo(EnumTipoReserva.UNICA);
	}

	private void atualizarReservas() {
		reservas.clear();
		reservas.addAll(DAOFactory.getDAOFactory().getReservaDAO().getAtivosNaSemana(LocalDate.now()));
		filtrarReservas();
	}

	private class HorarioAdapter {
		private int coluna, linha;
		private StackPane pane;
		private ReservaEntity reserva;
		private Horario horario;

		public HorarioAdapter() {
			super();
		}

		public HorarioAdapter(int coluna, int linha, StackPane pane, ReservaEntity reserva) {
			super();
			this.coluna = coluna;
			this.linha = linha;
			this.pane = pane;
			this.reserva = reserva;
			this.horario = Horario.values()[linha];
		}

		public void clearPane() {
			this.pane.getChildren().clear();
		}

		public void addNode(Node no) {
			this.pane.getChildren().add(no);
		}

		public int getColuna() {
			return coluna;
		}

		public void setColuna(int coluna) {
			this.coluna = coluna;
		}

		public int getLinha() {
			return linha;
		}

		public void setLinha(int linha) {
			this.linha = linha;
		}

		public StackPane getPane() {
			return pane;
		}

		public void setPane(StackPane pane) {
			this.pane = pane;
		}

		public ReservaEntity getReserva() {
			return reserva;
		}

		public void setReserva(ReservaEntity reserva) {
			this.reserva = reserva;
		}

		public Horario getHorario() {
			return horario;
		}

		public void setHorario(Horario horario) {
			this.horario = horario;
		}
	}
}

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace Krlove\EloquentModelGenerator\Model;

class BelongsToMany extends Relation
{
    protected string $joinTable;

    public function __construct(string $tableName, string $joinTable, string $foreignColumnName, string $localColumnName)
    {
        $this->joinTable = $joinTable;
        parent::__construct($tableName, $foreignColumnName, $localColumnName);
    }

    public function getJoinTable(): string
    {
        return $this->joinTable;
    }
}


text:
/* !!!! GENERATED FILE - DO NOT EDIT !!!! */

/*
 * Copyright (c) 2014 liblcf authors
 * This file is released under the MIT License
 * http://opensource.org/licenses/MIT
 */

#ifndef LCF_RPG_SAVEPARTYLOCATION_H
#define LCF_RPG_SAVEPARTYLOCATION_H

// Headers
#include <string>
#include "rpg_moveroute.h"

/**
 * RPG::SavePartyLocation class.
 */
namespace RPG {
	class SavePartyLocation {
	public:
		enum VehicleType {
			VehicleType_none = 0,
			VehicleType_skiff = 1,
			VehicleType_ship = 2,
			VehicleType_airship = 3
		};

		SavePartyLocation();

		bool active;
		int map_id;
		int position_x;
		int position_y;
		int direction;
		int sprite_direction;
		int anim_frame;
		int transparency;
		int remaining_step;
		int move_frequency;
		int layer;
		bool overlap_forbidden;
		int animation_type;
		bool lock_facing;
		int move_speed;
		MoveRoute move_route;
		bool move_route_overwrite;
		int move_route_index;
		bool move_route_repeated;
		bool sprite_transparent;
		int unknown_2f_overlap;
		int anim_paused;
		bool through;
		int stop_count;
		int anim_count;
		int max_stop_count;
		bool jumping;
		int begin_jump_x;
		int begin_jump_y;
		int unknown_47;
		bool flying;
		std::string sprite_name;
		int sprite_id;
		int unknown_4b;
		int flash_red;
		int flash_green;
		int flash_blue;
		double flash_current_level;
		int flash_time_left;
		bool boarding;
		bool aboard;
		int vehicle;
		bool unboarding;
		int preboard_move_speed;
		int unknown_6c;
		int pan_state;
		int pan_current_x;
		int pan_current_y;
		int pan_finish_x;
		int pan_finish_y;
		int unknown_79;
		int encounter_steps;
		int unknown_7d;
		int map_save_count;
		int database_save_count;
	};
}

#endif


text:
const isBufferExists = typeof Buffer !== 'undefined';

/**
 * is it Buffer?
 *
 * @private
 */
export const isBuffer: typeof Buffer.isBuffer = isBufferExists
  ? Buffer.isBuffer.bind(Buffer)
  : /**
     * return false every time if Buffer unsupported
     *
     * @private
     */
    function isBuffer(
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      obj: Parameters<typeof Buffer.isBuffer>[0]
    ): obj is Buffer {
      return false;
    };

/**
 * clone Buffer
 *
 * @private
 */
export const cloneBuffer: typeof Buffer.from = isBufferExists
  ? Buffer.from.bind(Buffer)
  : /**
     * return argument
     * use if Buffer unsupported
     *
     * @private
     * @param value
     */
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    function cloneBuffer(value: unknown): any {
      return value;
    };


text:
import React, {Component} from 'react';
import PropTypes from 'prop-types';

class Test extends Component {
  render() {
    return (

    );
  }
}

Test.propTypes = {};
Test.defaultProps = {};

export default Test;


text:
using System;
using System.Collections.Generic;

namespace InvertedTomato.Compression.Integers
{
    public class EliasOmegaCodec : ICodec
    {
        public UInt64 MinValue => UInt64.MinValue;
        public UInt64 MaxValue => UInt64.MaxValue - 1; // TODO: Check!

        private void Encode(UInt64 value, IBitWriter buffer)
        {
            // Offset min value
            value++;

            // Prepare buffer
            var groups = new Stack<KeyValuePair<UInt64, Int32>>();

            // #1 Place a "0" at the end of the code.
            groups.Push(new KeyValuePair<UInt64, Int32>(0, 1));

            // #2 If N=1, stop; encoding is complete.
            while (value > 1)
            {
                // Calculate the length of value
                var length = BitOperation.CountUsed(value);

                // #3 Prepend the binary representation of N to the beginning of the code (this will be at least two bits, the first bit of which is a 1)
                groups.Push(new KeyValuePair<UInt64, Int32>(value, length));

                // #4 Let N equal the number of bits just prepended, minus one.
                value = (UInt64) length - 1;
            }

            // Write buffer
            foreach (var item in groups)
            {
                var bits = item.Value;
                var group = item.Key;

                buffer.WriteBits(group, bits);
            }
        }

        private UInt64 Decode(IBitReader buffer)
        {
            // #1 Start with a variable N, set to a value of 1.
            UInt64 value = 1;

            // #2 If the next bit is a "0", stop. The decoded number is N.
            while (buffer.PeakBit())
            {
                // #3 If the next bit is a "1", then read it plus N more bits, and use that binary number as the new value of N.
                value = buffer.ReadBits((Int32) value + 1);
            }

            // Burn last bit from input
            buffer.ReadBit();

            // Offset for min value
            return value - 1;
        }

        public Int32? CalculateEncodedBits(UInt64 value)
        {
            var result = 1; // Termination bit

            // Offset value to allow for 0s
            value++;

            // #2 If N=1, stop; encoding is complete.
            while (value > 1)
            {
                // Calculate the length of value
                var length = BitOperation.CountUsed(value);

                // #3 Prepend the binary representation of N to the beginning of the code (this will be at least two bits, the first bit of which is a 1)
                result += length;

                // #4 Let N equal the number of bits just prepended, minus one.
                value = (UInt64) length - 1;
            }

            return result;
        }

        public void EncodeBit(bool value, IBitWriter buffer) => Encode(1, buffer);
        public void EncodeUInt8(byte value, IBitWriter buffer) => Encode(value, buffer);
        public void EncodeUInt16(ushort value, IBitWriter buffer) => Encode(value, buffer);
        public void EncodeUInt32(uint value, IBitWriter buffer) => Encode(value, buffer);
        public void EncodeUInt64(ulong value, IBitWriter buffer) => Encode(value, buffer);
        public void EncodeInt8(sbyte value, IBitWriter buffer) => Encode(ZigZag.Encode(value), buffer);
        public void EncodeInt16(short value, IBitWriter buffer) => Encode(ZigZag.Encode(value), buffer);
        public void EncodeInt32(int value, IBitWriter buffer) => Encode(ZigZag.Encode(value), buffer);
        public void EncodeInt64(long value, IBitWriter buffer) => Encode(ZigZag.Encode(value), buffer);

        public Boolean DecodeBit(IBitReader buffer) => Decode(buffer) > 0;
        public Byte DecodeUInt8(IBitReader buffer) => (Byte) Decode(buffer);
        public UInt16 DecodeUInt16(IBitReader buffer) => (UInt16) Decode(buffer);
        public UInt32 DecodeUInt32(IBitReader buffer) => (UInt32) Decode(buffer);
        public UInt64 DecodeUInt64(IBitReader buffer) => Decode(buffer);
        public SByte DecodeInt8(IBitReader buffer) => (SByte) ZigZag.Decode(Decode(buffer));
        public Int16 DecodeInt16(IBitReader buffer) => (Int16) ZigZag.Decode(Decode(buffer));
        public Int32 DecodeInt32(IBitReader buffer) => (Int32) ZigZag.Decode(Decode(buffer));
        public Int64 DecodeInt64(IBitReader buffer) => ZigZag.Decode(Decode(buffer));
    }
}