switch(item.getItemId()) {
                case R.id.search:
                    enabled = searchEnabled;
                    break;
                default:
                    enabled = true;
            }

/*
 *
 * This file is part of PageTurner
 *
 */
package net.nightwhistler.pageturner.fragment;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.widget.SearchView;
import com.github.rtyley.android.sherlock.roboguice.fragment.RoboSherlockFragment;
import com.google.inject.Inject;
import com.google.inject.Provider;
import jedi.option.Option;
import net.nightwhistler.nucular.atom.AtomConstants;
import net.nightwhistler.nucular.atom.Entry;
import net.nightwhistler.nucular.atom.Feed;
import net.nightwhistler.nucular.atom.Link;
import net.nightwhistler.pageturner.R;
import net.nightwhistler.pageturner.catalog.*;
import net.nightwhistler.ui.UiUtils;
import net.nightwhistler.ui.DialogFactory;
import net.nightwhistler.pageturner.activity.PageTurnerPrefsActivity;
import net.nightwhistler.pageturner.scheduling.TaskQueue;
import net.nightwhistler.pageturner.view.FastBitmapDrawable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import roboguice.inject.InjectView;
import javax.annotation.Nullable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static jedi.functional.FunctionalPrimitives.isEmpty;
import static jedi.option.Options.option;

public class CatalogFragment extends RoboSherlockFragment implements LoadFeedCallback {

    private static final Logger LOG = LoggerFactory.getLogger("CatalogFragment");

    @InjectView(R.id.catalogList)
    @Nullable
    private ListView catalogList;

    @Inject
    private Provider<LoadOPDSTask> loadOPDSTaskProvider;

    @Inject
    private Provider<ParseBinDataTask> parseBinDataTaskProvider;

    @Inject
    private Provider<LoadThumbnailTask> loadThumbnailTaskProvider;

    @Inject
    private DialogFactory dialogFactory;

    @Inject
    private CatalogListAdapter adapter;

    @Inject
    private Provider<DisplayMetrics> metricsProvider;

    @Inject
    private TaskQueue taskQueue;

    private Map<String, Drawable> thumbnailCache = new ConcurrentHashMap<>();

    private MenuItem searchMenuItem;

    private String baseURL;

    private Feed staticFeed;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DisplayMetrics metrics = metricsProvider.get();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
        this.taskQueue.setTaskQueueListener(this::onLoadingDone);
    }

    public void setBaseURL(String baseURL) {
        this.baseURL = baseURL;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_catalog, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setHasOptionsMenu(true);
        catalogList.setAdapter(adapter);
        adapter.setImageLoader((baseURL, link) -> option(thumbnailCache.get(link.getHref())));
        catalogList.setOnScrollListener(new LoadingScrollListener());
        catalogList.setOnItemClickListener((list, v, position, a) -> {
            Option<Entry> entry = adapter.getItem(position);
            entry.forEach(e -> onEntryClicked(e, position));
        });
        if (staticFeed != null) {
            adapter.setFeed(staticFeed);
        }
    }

    public void onBecameVisible() {
        adapter.getFeed().forEach(f -> ((CatalogParent) getActivity()).onFeedLoaded(f));
    }

    private void loadOPDSFeed(Entry entry, String url, boolean asDetailsFeed, boolean asSearchFeed, ResultType resultType) {
        LoadOPDSTask task = this.loadOPDSTaskProvider.get();
        task.setCallBack(this);
        task.setResultType(resultType);
        task.setAsDetailsFeed(asDetailsFeed);
        task.setAsSearchFeed(asSearchFeed);
        // If we're going to load a completely new feed,
        // cancel all pending downloads.
        if (resultType == ResultType.REPLACE) {
            taskQueue.clear();
            taskQueue.executeTask(task, url);
        } else {
            taskQueue.jumpQueueExecuteTask(task, url);
            this.adapter.setLoading(true);
        }
    }

    public void setStaticFeed(Feed feed) {
        this.staticFeed = feed;
    }

    public void performSearch(String searchTerm) {
        if (searchTerm != null && searchTerm.length() > 0) {
            String searchString = URLEncoder.encode(searchTerm);
            Option<Feed> feed = adapter.getFeed();
            feed.forEach(f -> f.getSearchLink().forEach(searchLink -> {
                String linkUrl = searchLink.getHref();
                linkUrl = linkUrl.replace(AtomConstants.SEARCH_TERMS, searchString);
                loadURL(null, linkUrl, false, true, ResultType.REPLACE);
            }));
        }
    }

    public boolean supportsSearch() {
        return searchMenuItem.isEnabled();
    }

    public void onSearchRequested() {
        if (searchMenuItem == null || !searchMenuItem.isEnabled()) {
            return;
        }
        if (searchMenuItem.getActionView() != null) {
            this.searchMenuItem.expandActionView();
            this.searchMenuItem.getActionView().requestFocus();
        } else {
            dialogFactory.showSearchDialog(R.string.search_books, R.string.enter_query, this::performSearch);
        }
    }

    public void onEntryClicked(Entry entry, int position) {
        if (entry.getId() != null && entry.getId().equals(Catalog.CUSTOM_SITES_ID)) {
            ((CatalogParent) getActivity()).loadCustomSitesFeed();
        } else if (!isEmpty(entry.getAlternateLink())) {
            String href = entry.getAlternateLink().unsafeGet().getHref();
            replaceFeed(entry, href, true);
        } else if (!isEmpty(entry.getEpubLink())) {
            loadFakeFeek(entry);
        } else if (!isEmpty(entry.getAtomLink())) {
            String href = entry.getAtomLink().unsafeGet().getHref();
            replaceFeed(entry, href, false);
        } else if (!isEmpty(entry.getWebsiteLink())) {
            String url = entry.getWebsiteLink().unsafeGet().getHref();
            Intent i = new Intent(Intent.ACTION_VIEW);
            i.setData(Uri.parse(url));
            startActivity(i);
        }
    }

    private void replaceFeed(Entry entry, String href, boolean asDetailsFeed) {
        String baseURL = entry.getBaseURL();
        if (baseURL == null) {
            baseURL = this.baseURL;
        }
        LOG.debug("Loading new Feed with baseURL: " + baseURL);
        ((CatalogParent) getActivity()).loadFeed(entry, href, baseURL, asDetailsFeed);
    }

    private void loadFakeFeek(Entry entry) {
        Feed fakeFeed = new Feed();
        fakeFeed.addEntry(entry);
        fakeFeed.setTitle(entry.getTitle());
        fakeFeed.setDetailFeed(true);
        fakeFeed.setURL(entry.getBaseURL());
        ((CatalogParent) getActivity()).loadFakeFeed(fakeFeed);
    }

    public void loadURL(Entry entry, String url, boolean asDetailsFeed, boolean asSearchFeed, ResultType resultType) {
        String base = null;
        if (entry != null) {
            base = entry.getBaseURL();
        }
        if (base == null) {
            base = this.baseURL;
        }
        LOG.debug("Using baseURL: " + base);
        try {
            String target = url;
            if (base != null && !base.equals(Catalog.CUSTOM_SITES_ID)) {
                target = new URL(new URL(base), url).toString();
            }
            LOG.info("Loading " + target);
            loadOPDSFeed(entry, target, asDetailsFeed, asSearchFeed, resultType);
        } catch (MalformedURLException u) {
            LOG.error("Malformed URL:", u);
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        SherlockFragmentActivity activity = getSherlockActivity();
        if (activity == null) {
            return;
        }
        activity.getSupportActionBar().setHomeButtonEnabled(true);
        inflater.inflate(R.menu.catalog_menu, menu);
        this.searchMenuItem = menu.findItem(R.id.search);
        if (searchMenuItem != null) {
            final SearchView searchView = (SearchView) searchMenuItem.getActionView();
            if (searchView != null) {
                searchView.setSubmitButtonEnabled(true);
                searchView.setOnQueryTextListener(UiUtils.onQuery(this::performSearch));
            } else {
                searchMenuItem.setOnMenuItemClickListener(item -> {
                    dialogFactory.showSearchDialog(R.string.search_books, R.string.enter_query, this::performSearch);
                    return false;
                });
            }
        }
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        Option<Feed> feed = adapter.getFeed();
        boolean searchEnabled = !isEmpty((Option<Link>) feed.flatMap(Feed::getSearchLink));
        for (int i = 0; i < menu.size(); i++) {
            MenuItem item = menu.getItem(i);
            boolean enabled;

            item.setEnabled(enabled);
            item.setVisible(enabled);
        }
        LOG.debug("Adapter has feed: " + adapter.getFeed());
    }

    @Override
    public void notifyLinkUpdated(Link link, Drawable drawable) {
        if (drawable != null) {
            this.thumbnailCache.put(link.getHref(), drawable);
            adapter.notifyDataSetChanged();
        }
    }

    @Override
    public void errorLoadingFeed(String error) {
        if (isAdded()) {
            Toast.makeText(getActivity(), getString(R.string.feed_failed) + ": " + error, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void emptyFeedLoaded(Feed feed) {
        if (feed.isSearchFeed()) {
            Toast.makeText(getActivity(), R.string.no_search_results, Toast.LENGTH_LONG).show();
        } else {
            errorLoadingFeed(getActivity().getString(R.string.empty_opds_feed));
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        destroyThumbnails();
    }

    @Override
    public void onLowMemory() {
        destroyThumbnails();
    }

    public void setNewFeed(Feed result, ResultType resultType) {
        if (result != null) {
            if (resultType == null || resultType == ResultType.REPLACE) {
                destroyThumbnails();
                thumbnailCache.clear();
                adapter.setFeed(result);
                if (isAdded()) {
                    ((CatalogParent) getActivity()).onFeedLoaded(result);
                }
            } else {
                this.adapter.setLoading(false);
                adapter.addEntriesFromFeed(result);
            }
        }
    }

    private void destroyThumbnails() {
        for (Map.Entry<String, Drawable> entry : thumbnailCache.entrySet()) {
            Drawable value = entry.getValue();
            if (value instanceof FastBitmapDrawable) {
                ((FastBitmapDrawable) value).destroy();
            }
        }
    }

    private void queueImageLoading(String baseURL, Link imageLink) {
        Context context = getActivity();
        if (context == null) {
            return;
        }
        // Make sure we only start a single background task for each url
        if (this.thumbnailCache.containsKey(imageLink.getHref())) {
            return;
        } else {
            this.thumbnailCache.put(imageLink.getHref(), context.getResources().getDrawable(R.drawable.unknown_cover));
        }
        String href = imageLink.getHref();
        // If the image is contained in the feed, load it
        // directly
        if (href.startsWith("data:image")) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
                ParseBinDataTask binDataTask = this.parseBinDataTaskProvider.get();
                binDataTask.setLoadFeedCallback(this);
                taskQueue.executeTask(binDataTask, imageLink);
            }
        } else {
            LoadThumbnailTask thumbnailTask = this.loadThumbnailTaskProvider.get();
            thumbnailTask.setBaseUrl(baseURL);
            thumbnailTask.setLoadFeedCallback(this);
            taskQueue.executeTask(thumbnailTask, imageLink);
        }
    }

    private void setSupportProgressBarIndeterminateVisibility(boolean enable) {
        SherlockFragmentActivity activity = getSherlockActivity();
        if (activity != null) {
            LOG.debug("Setting progress bar to " + enable);
            activity.setSupportProgressBarIndeterminateVisibility(enable);
        } else {
            LOG.debug("Got null activity.");
        }
    }

    private void onLoadingDone() {
        LOG.debug("Done loading.");
        setSupportProgressBarIndeterminateVisibility(false);
    }

    @Override
    public void onLoadingStart() {
        LOG.debug("Start loading.");
        setSupportProgressBarIndeterminateVisibility(true);
    }

    private class LoadingScrollListener implements AbsListView.OnScrollListener {

        private static final int LOAD_THRESHOLD = 2;

        private String lastLoadedUrl = "";

        private Handler handler = new Handler();

        private Runnable updater;

        @Override
        public void onScroll(AbsListView view, final int firstVisibleItem, final int visibleItemCount, int totalItemCount) {
            loadThumbnails(firstVisibleItem, visibleItemCount, totalItemCount);
            loadNextFeed(firstVisibleItem, visibleItemCount, totalItemCount);
        }

        private void loadNextFeed(final int firstVisibleItem, final int visibleItemCount, int totalItemCount) {
            int lastVisibleItem = firstVisibleItem + visibleItemCount;
            if (totalItemCount - lastVisibleItem <= LOAD_THRESHOLD && adapter.getCount() > 0) {
                Option<Entry> lastEntry = adapter.getItem(adapter.getCount() - 1);
                lastEntry.flatMap(Entry::getFeed).forEach(feed -> feed.getNextLink().forEach(link -> {
                    if (!link.getHref().equals(lastLoadedUrl)) {
                        Entry nextEntry = new Entry();
                        nextEntry.setFeed(feed);
                        nextEntry.addLink(link);
                        LOG.debug("Starting download for " + link.getHref() + " after scroll");
                        lastLoadedUrl = link.getHref();
                        loadURL(nextEntry, link.getHref(), false, false, ResultType.APPEND);
                    }
                }));
            }
        }

        private void loadThumbnails(final int firstVisibleItem, final int visibleItemCount, int totalItemCount) {
            if (updater != null) {
                handler.removeCallbacks(updater);
            }
            updater = () -> {
                for (int i = 0; i < visibleItemCount; i++) {
                    Option<Entry> entry = adapter.getItem(firstVisibleItem + i);
                    entry.forEach(e -> e.getFeed().forEach(feed -> {
                        Catalog.getImageLink(feed, e).forEach(imageLink -> {
                            if (!thumbnailCache.containsKey(imageLink.getHref())) {
                                queueImageLoading(e.getBaseURL(), imageLink);
                            }
                        });
                    }));
                }
            };
            long delay;
            if (firstVisibleItem + visibleItemCount == totalItemCount) {
                // All items on screen, no wait
                delay = 0;
            } else {
                // Default delay
                delay = 500;
            }
            handler.postDelayed(updater, delay);
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }
    }
}


switch(visibility) {
                            case 0:
                                view.setVisibility(View.VISIBLE);
                                break;
                            case 1:
                                view.setVisibility(View.INVISIBLE);
                                break;
                            case 2:
                                view.setVisibility(View.GONE);
                                break;
                        }

package android.view;

import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.util.Xml;
import android.widget.FrameLayout;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.HashMap;

/**
 * Instantiates a layout XML file into its corresponding {@link android.view.View}
 * objects. It is never used directly. Instead, use
 * {@link android.app.Activity#getLayoutInflater()} or
 * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
 * that is already hooked up to the current context and correctly configured
 * for the device you are running on.  For example:
 *
 *
LayoutInflater inflater = (LayoutInflater)context.getSystemService
 *      (Context.LAYOUT_INFLATER_SERVICE);

 *
 *

 * To create a new LayoutInflater with an additional {@link Factory} for your
 * own views, you can use {@link #cloneInContext} to clone an existing
 * ViewFactory, and then call {@link #setFactory} on it to include your
 * Factory.
 *
 *

 * For performance reasons, view inflation relies heavily on pre-processing of
 * XML files that is done at build time. Therefore, it is not currently possible
 * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
 * it only works with an XmlPullParser returned from a compiled resource
 * (R.something file.)
 *
 * @see Context#getSystemService
 */
public abstract class LayoutInflater {

    private static final String TAG = LayoutInflater.class.getSimpleName();

    private static final boolean DEBUG = false;

    /**
     * Empty stack trace used to avoid log spam in re-throw exceptions.
     */
    private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];

    /**
     * This field should be made private, so it is hidden from the SDK.
     * {@hide}
     */
    protected final Context mContext;

    // these are optional, set by the caller
    private boolean mFactorySet;

    private Factory mFactory;

    private Factory2 mFactory2;

    private Factory2 mPrivateFactory;

    private Filter mFilter;

    final Object[] mConstructorArgs = new Object[2];

    static final Class<?>[] mConstructorSignature = new Class[] { Context.class, AttributeSet.class };

    private static final HashMap<String, Constructor<? extends View>> sConstructorMap = new HashMap<String, Constructor<? extends View>>();

    private HashMap<String, Boolean> mFilterMap;

    private TypedValue mTempValue;

    private static final String TAG_MERGE = "merge";

    private static final String TAG_INCLUDE = "include";

    private static final String TAG_1995 = "blink";

    private static final String TAG_REQUEST_FOCUS = "requestFocus";

    private static final String TAG_TAG = "tag";

    private static final String ATTR_LAYOUT = "layout";

    private static final int[] ATTRS_THEME = new int[] { com.android.internal.R.attr.theme };

    /**
     * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
     * to be inflated.
     */
    public interface Filter {

        /**
         * Hook to allow clients of the LayoutInflater to restrict the set of Views
         * that are allowed to be inflated.
         *
         * @param clazz The class object for the View that is about to be inflated
         *
         * @return True if this class is allowed to be inflated, or false otherwise
         */
        @SuppressWarnings("unchecked")
        boolean onLoadClass(Class clazz);
    }

    public interface Factory {

        /**
         * Hook you can supply that is called when inflating from a LayoutInflater.
         * You can use this to customize the tag names available in your XML
         * layout files.
         *
         *

         * Note that it is good practice to prefix these custom names with your
         * package (i.e., com.coolcompany.apps) to avoid conflicts with system
         * names.
         *
         * @param name Tag name to be inflated.
         * @param context The context the view is being created in.
         * @param attrs Inflation attributes as specified in XML file.
         *
         * @return View Newly created view. Return null for the default
         *         behavior.
         */
        public View onCreateView(String name, Context context, AttributeSet attrs);
    }

    public interface Factory2 extends Factory {

        /**
         * Version of {@link #onCreateView(String, Context, AttributeSet)}
         * that also supplies the parent that the view created view will be
         * placed in.
         *
         * @param parent The parent that the created view will be placed
         * in; note that this may be null.
         * @param name Tag name to be inflated.
         * @param context The context the view is being created in.
         * @param attrs Inflation attributes as specified in XML file.
         *
         * @return View Newly created view. Return null for the default
         *         behavior.
         */
        public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
    }

    private static class FactoryMerger implements Factory2 {

        private final Factory mF1, mF2;

        private final Factory2 mF12, mF22;

        FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
            mF1 = f1;
            mF2 = f2;
            mF12 = f12;
            mF22 = f22;
        }

        public View onCreateView(String name, Context context, AttributeSet attrs) {
            View v = mF1.onCreateView(name, context, attrs);
            if (v != null)
                return v;
            return mF2.onCreateView(name, context, attrs);
        }

        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
            View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs) : mF1.onCreateView(name, context, attrs);
            if (v != null)
                return v;
            return mF22 != null ? mF22.onCreateView(parent, name, context, attrs) : mF2.onCreateView(name, context, attrs);
        }
    }

    /**
     * Create a new LayoutInflater instance associated with a particular Context.
     * Applications will almost always want to use
     * {@link Context#getSystemService Context.getSystemService()} to retrieve
     * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
     *
     * @param context The Context in which this LayoutInflater will create its
     * Views; most importantly, this supplies the theme from which the default
     * values for their attributes are retrieved.
     */
    protected LayoutInflater(Context context) {
        mContext = context;
    }

    /**
     * Create a new LayoutInflater instance that is a copy of an existing
     * LayoutInflater, optionally with its Context changed.  For use in
     * implementing {@link #cloneInContext}.
     *
     * @param original The original LayoutInflater to copy.
     * @param newContext The new Context to use.
     */
    protected LayoutInflater(LayoutInflater original, Context newContext) {
        mContext = newContext;
        mFactory = original.mFactory;
        mFactory2 = original.mFactory2;
        mPrivateFactory = original.mPrivateFactory;
        setFilter(original.mFilter);
    }

    /**
     * Obtains the LayoutInflater from the given context.
     */
    public static LayoutInflater from(Context context) {
        LayoutInflater LayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (LayoutInflater == null) {
            throw new AssertionError("LayoutInflater not found.");
        }
        return LayoutInflater;
    }

    /**
     * Create a copy of the existing LayoutInflater object, with the copy
     * pointing to a different Context than the original.  This is used by
     * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
     * with the new Context theme.
     *
     * @param newContext The new Context to associate with the new LayoutInflater.
     * May be the same as the original Context if desired.
     *
     * @return Returns a brand spanking new LayoutInflater object associated with
     * the given Context.
     */
    public abstract LayoutInflater cloneInContext(Context newContext);

    /**
     * Return the context we are running in, for access to resources, class
     * loader, etc.
     */
    public Context getContext() {
        return mContext;
    }

    /**
     * Return the current {@link Factory} (or null). This is called on each element
     * name. If the factory returns a View, add that to the hierarchy. If it
     * returns null, proceed to call onCreateView(name).
     */
    public final Factory getFactory() {
        return mFactory;
    }

    /**
     * Return the current {@link Factory2}.  Returns null if no factory is set
     * or the set factory does not implement the {@link Factory2} interface.
     * This is called on each element
     * name. If the factory returns a View, add that to the hierarchy. If it
     * returns null, proceed to call onCreateView(name).
     */
    public final Factory2 getFactory2() {
        return mFactory2;
    }

    /**
     * Attach a custom Factory interface for creating views while using
     * this LayoutInflater.  This must not be null, and can only be set once;
     * after setting, you can not change the factory.  This is
     * called on each element name as the xml is parsed. If the factory returns
     * a View, that is added to the hierarchy. If it returns null, the next
     * factory default {@link #onCreateView} method is called.
     *
     *
If you have an existing
     * LayoutInflater and want to add your own factory to it, use
     * {@link #cloneInContext} to clone the existing instance and then you
     * can use this function (once) on the returned new instance.  This will
     * merge your own factory with whatever factory the original instance is
     * using.
     */
    public void setFactory(Factory factory) {
        if (mFactorySet) {
            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
        }
        if (factory == null) {
            throw new NullPointerException("Given factory can not be null");
        }
        mFactorySet = true;
        if (mFactory == null) {
            mFactory = factory;
        } else {
            mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
        }
    }

    /**
     * Like {@link #setFactory}, but allows you to set a {@link Factory2}
     * interface.
     */
    public void setFactory2(Factory2 factory) {
        if (mFactorySet) {
            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
        }
        if (factory == null) {
            throw new NullPointerException("Given factory can not be null");
        }
        mFactorySet = true;
        if (mFactory == null) {
            mFactory = mFactory2 = factory;
        } else {
            mFactory = mFactory2 = new FactoryMerger(factory, factory, mFactory, mFactory2);
        }
    }

    /**
     * @hide for use by framework
     */
    public void setPrivateFactory(Factory2 factory) {
        if (mPrivateFactory == null) {
            mPrivateFactory = factory;
        } else {
            mPrivateFactory = new FactoryMerger(factory, factory, mPrivateFactory, mPrivateFactory);
        }
    }

    /**
     * @return The {@link Filter} currently used by this LayoutInflater to restrict the set of Views
     * that are allowed to be inflated.
     */
    public Filter getFilter() {
        return mFilter;
    }

    /**
     * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
     * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
     * throw an {@link InflateException}. This filter will replace any previous filter set on this
     * LayoutInflater.
     *
     * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
     *        This filter will replace any previous filter set on this LayoutInflater.
     */
    public void setFilter(Filter filter) {
        mFilter = filter;
        if (filter != null) {
            mFilterMap = new HashMap<String, Boolean>();
        }
    }

    /**
     * Inflate a new view hierarchy from the specified xml resource. Throws
     * {@link InflateException} if there is an error.
     *
     * @param resource ID for an XML layout resource to load (e.g.,
     *        R.layout.main_page)
     * @param root Optional view to be the parent of the generated hierarchy.
     * @return The root View of the inflated hierarchy. If root was supplied,
     *         this is the root View; otherwise it is the root of the inflated
     *         XML file.
     */
    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
        return inflate(resource, root, root != null);
    }

    /**
     * Inflate a new view hierarchy from the specified xml node. Throws
     * {@link InflateException} if there is an error. *
     *

     * Important   For performance
     * reasons, view inflation relies heavily on pre-processing of XML files
     * that is done at build time. Therefore, it is not currently possible to
     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
     *
     * @param parser XML dom node containing the description of the view
     *        hierarchy.
     * @param root Optional view to be the parent of the generated hierarchy.
     * @return The root View of the inflated hierarchy. If root was supplied,
     *         this is the root View; otherwise it is the root of the inflated
     *         XML file.
     */
    public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {
        return inflate(parser, root, root != null);
    }

    /**
     * Inflate a new view hierarchy from the specified xml resource. Throws
     * {@link InflateException} if there is an error.
     *
     * @param resource ID for an XML layout resource to load (e.g.,
     *        R.layout.main_page)
     * @param root Optional view to be the parent of the generated hierarchy (if
     *        attachToRoot is true), or else simply an object that
     *        provides a set of LayoutParams values for root of the returned
     *        hierarchy (if attachToRoot is false.)
     * @param attachToRoot Whether the inflated hierarchy should be attached to
     *        the root parameter? If false, root is only used to create the
     *        correct subclass of LayoutParams for the root view in the XML.
     * @return The root View of the inflated hierarchy. If root was supplied and
     *         attachToRoot is true, this is root; otherwise it is the root of
     *         the inflated XML file.
     */
    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" + Integer.toHexString(resource) + ")");
        }
        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

    /**
     * Inflate a new view hierarchy from the specified XML node. Throws
     * {@link InflateException} if there is an error.
     *

     * Important   For performance
     * reasons, view inflation relies heavily on pre-processing of XML files
     * that is done at build time. Therefore, it is not currently possible to
     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
     *
     * @param parser XML dom node containing the description of the view
     *        hierarchy.
     * @param root Optional view to be the parent of the generated hierarchy (if
     *        attachToRoot is true), or else simply an object that
     *        provides a set of LayoutParams values for root of the returned
     *        hierarchy (if attachToRoot is false.)
     * @param attachToRoot Whether the inflated hierarchy should be attached to
     *        the root parameter? If false, root is only used to create the
     *        correct subclass of LayoutParams for the root view in the XML.
     * @return The root View of the inflated hierarchy. If root was supplied and
     *         attachToRoot is true, this is root; otherwise it is the root of
     *         the inflated XML file.
     */
    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
            final Context inflaterContext = mContext;
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            Context lastContext = (Context) mConstructorArgs[0];
            mConstructorArgs[0] = inflaterContext;
            View result = root;
            try {
                // Look for the root node.
                int type;
                while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
                    // Empty
                }
                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(parser.getPositionDescription() + ": No start tag found!");
                }
                final String name = parser.getName();
                if (DEBUG) {
                    System.out.println("**************************");
                    System.out.println("Creating root view: " + name);
                    System.out.println("**************************");
                }
                if (TAG_MERGE.equals(name)) {
                    if (root == null || !attachToRoot) {
                        throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true");
                    }
                    rInflate(parser, root, inflaterContext, attrs, false);
                } else {
                    // Temp is the root view that was found in the xml
                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);
                    ViewGroup.LayoutParams params = null;
                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " + root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }
                    if (DEBUG) {
                        System.out.println("-----> start inflating children");
                    }
                    // Inflate all children under temp against its context.
                    rInflateChildren(parser, temp, attrs, true);
                    if (DEBUG) {
                        System.out.println("-----> done inflating children");
                    }
                    // We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }
                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
                }
            } catch (XmlPullParserException e) {
                final InflateException ie = new InflateException(e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } catch (Exception e) {
                final InflateException ie = new InflateException(parser.getPositionDescription() + ": " + e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } finally {
                // Don't retain static reference on context.
                mConstructorArgs[0] = lastContext;
                mConstructorArgs[1] = null;
                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            }
            return result;
        }
    }

    private static final ClassLoader BOOT_CLASS_LOADER = LayoutInflater.class.getClassLoader();

    private final boolean verifyClassLoader(Constructor<? extends View> constructor) {
        final ClassLoader constructorLoader = constructor.getDeclaringClass().getClassLoader();
        if (constructorLoader == BOOT_CLASS_LOADER) {
            // fast path for boot class loader (most common case?) - always ok
            return true;
        }
        // in all normal cases (no dynamic code loading), we will exit the following loop on the
        // first iteration (i.e. when the declaring classloader is the contexts class loader).
        ClassLoader cl = mContext.getClassLoader();
        do {
            if (constructorLoader == cl) {
                return true;
            }
            cl = cl.getParent();
        } while (cl != null);
        return false;
    }

    /**
     * Low-level function for instantiating a view by name. This attempts to
     * instantiate a view class of the given <var>name</var> found in this
     * LayoutInflater's ClassLoader.
     *
     *

     * There are two things that can happen in an error case: either the
     * exception describing the error will be thrown, or a null will be
     * returned. You must deal with both possibilities -- the former will happen
     * the first time createView() is called for a class of a particular name,
     * the latter every time there-after for that class name.
     *
     * @param name The full name of the class to be instantiated.
     * @param attrs The XML attributes supplied for this instance.
     *
     * @return View The newly instantiated view, or null.
     */
    public final View createView(String name, String prefix, AttributeSet attrs) throws ClassNotFoundException, InflateException {
        Constructor<? extends View> constructor = sConstructorMap.get(name);
        if (constructor != null && !verifyClassLoader(constructor)) {
            constructor = null;
            sConstructorMap.remove(name);
        }
        Class<? extends View> clazz = null;
        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, name);
            if (constructor == null) {
                // Class not found in the cache, see if it's real, and try to add it
                clazz = mContext.getClassLoader().loadClass(prefix != null ? (prefix + name) : name).asSubclass(View.class);
                if (mFilter != null && clazz != null) {
                    boolean allowed = mFilter.onLoadClass(clazz);
                    if (!allowed) {
                        failNotAllowed(name, prefix, attrs);
                    }
                }
                constructor = clazz.getConstructor(mConstructorSignature);
                constructor.setAccessible(true);
                sConstructorMap.put(name, constructor);
            } else {
                // If we have a filter, apply it to cached constructor
                if (mFilter != null) {
                    // Have we seen this name before?
                    Boolean allowedState = mFilterMap.get(name);
                    if (allowedState == null) {
                        // New class -- remember whether it is allowed
                        clazz = mContext.getClassLoader().loadClass(prefix != null ? (prefix + name) : name).asSubclass(View.class);
                        boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                        mFilterMap.put(name, allowed);
                        if (!allowed) {
                            failNotAllowed(name, prefix, attrs);
                        }
                    } else if (allowedState.equals(Boolean.FALSE)) {
                        failNotAllowed(name, prefix, attrs);
                    }
                }
            }
            Object[] args = mConstructorArgs;
            args[1] = attrs;
            final View view = constructor.newInstance(args);
            if (view instanceof ViewStub) {
                // Use the same context when inflating ViewStub later.
                final ViewStub viewStub = (ViewStub) view;
                viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
            }
            return view;
        } catch (NoSuchMethodException e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription() + ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } catch (ClassCastException e) {
            // If loaded class is not a View subclass
            final InflateException ie = new InflateException(attrs.getPositionDescription() + ": Class is not a View " + (prefix != null ? (prefix + name) : name), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } catch (ClassNotFoundException e) {
            // If loadClass fails, we should propagate the exception.
            throw e;
        } catch (Exception e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription() + ": Error inflating class " + (clazz == null ? "<unknown>" : clazz.getName()), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }

    /**
     * Throw an exception because the specified class is not allowed to be inflated.
     */
    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
        throw new InflateException(attrs.getPositionDescription() + ": Class not allowed to be inflated " + (prefix != null ? (prefix + name) : name));
    }

    /**
     * This routine is responsible for creating the correct subclass of View
     * given the xml element name. Override it to handle custom view objects. If
     * you override this in your subclass be sure to call through to
     * super.onCreateView(name) for names you do not recognize.
     *
     * @param name The fully qualified class name of the View to be create.
     * @param attrs An AttributeSet of attributes to apply to the View.
     *
     * @return View The View created.
     */
    protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
        return createView(name, "android.view.", attrs);
    }

    /**
     * Version of {@link #onCreateView(String, AttributeSet)} that also
     * takes the future parent of the view being constructed.  The default
     * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
     *
     * @param parent The future parent of the returned view.  Note that
     * this may be null.
     * @param name The fully qualified class name of the View to be create.
     * @param attrs An AttributeSet of attributes to apply to the View.
     *
     * @return View The View created.
     */
    protected View onCreateView(View parent, String name, AttributeSet attrs) throws ClassNotFoundException {
        return onCreateView(name, attrs);
    }

    /**
     * Convenience method for calling through to the five-arg createViewFromTag
     * method. This method passes {@code false} for the {@code ignoreThemeAttr}
     * argument and should be used for everything except {@code >include>}
     * tag parsing.
     */
    private View createViewFromTag(View parent, String name, Context context, AttributeSet attrs) {
        return createViewFromTag(parent, name, context, attrs, false);
    }

    /**
     * Creates a view from a tag name using the supplied attribute set.
     *

     * Note: Default visibility so the BridgeInflater can
     * override it.
     *
     * @param parent the parent view, used to inflate layout params
     * @param name the name of the XML tag used to define the view
     * @param context the inflation context for the view, typically the
     *                {@code parent} or base layout inflater context
     * @param attrs the attribute set for the XML tag used to define the view
     * @param ignoreThemeAttr {@code true} to ignore the {@code android:theme}
     *                        attribute (if set) for the view being inflated,
     *                        {@code false} otherwise
     */
    View createViewFromTag(View parent, String name, Context context, AttributeSet attrs, boolean ignoreThemeAttr) {
        if (name.equals("view")) {
            name = attrs.getAttributeValue(null, "class");
        }
        // Apply a theme wrapper, if allowed and one is specified.
        if (!ignoreThemeAttr) {
            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
            final int themeResId = ta.getResourceId(0, 0);
            if (themeResId != 0) {
                context = new ContextThemeWrapper(context, themeResId);
            }
            ta.recycle();
        }
        if (name.equals(TAG_1995)) {
            // Let's party like it's 1995!
            return new BlinkLayout(context, attrs);
        }
        try {
            View view;
            if (mFactory2 != null) {
                view = mFactory2.onCreateView(parent, name, context, attrs);
            } else if (mFactory != null) {
                view = mFactory.onCreateView(name, context, attrs);
            } else {
                view = null;
            }
            if (view == null && mPrivateFactory != null) {
                view = mPrivateFactory.onCreateView(parent, name, context, attrs);
            }
            if (view == null) {
                final Object lastContext = mConstructorArgs[0];
                mConstructorArgs[0] = context;
                try {
                    if (-1 == name.indexOf('.')) {
                        view = onCreateView(parent, name, attrs);
                    } else {
                        view = createView(name, null, attrs);
                    }
                } finally {
                    mConstructorArgs[0] = lastContext;
                }
            }
            return view;
        } catch (InflateException e) {
            throw e;
        } catch (ClassNotFoundException e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription() + ": Error inflating class " + name, e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        } catch (Exception e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription() + ": Error inflating class " + name, e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
        }
    }

    /**
     * Recursive method used to inflate internal (non-root) children. This
     * method calls through to {@link #rInflate} using the parent context as
     * the inflation context.
     * Note: Default visibility so the BridgeInflater can
     * call it.
     */
    final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
        rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
    }

    /**
     * Recursive method used to descend down the xml hierarchy and instantiate
     * views, instantiate their children, and then call onFinishInflate().
     *

     * Note: Default visibility so the BridgeInflater can
     * override it.
     */
    void rInflate(XmlPullParser parser, View parent, Context context, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
        final int depth = parser.getDepth();
        int type;
        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }
            final String name = parser.getName();
            if (TAG_REQUEST_FOCUS.equals(name)) {
                parseRequestFocus(parser, parent);
            } else if (TAG_TAG.equals(name)) {
                parseViewTag(parser, parent, attrs);
            } else if (TAG_INCLUDE.equals(name)) {
                if (parser.getDepth() == 0) {
                    throw new InflateException("<include /> cannot be the root element");
                }
                parseInclude(parser, context, parent, attrs);
            } else if (TAG_MERGE.equals(name)) {
                throw new InflateException("<merge /> must be the root element");
            } else {
                final View view = createViewFromTag(parent, name, context, attrs);
                final ViewGroup viewGroup = (ViewGroup) parent;
                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                rInflateChildren(parser, view, attrs, true);
                viewGroup.addView(view, params);
            }
        }
        if (finishInflate) {
            parent.onFinishInflate();
        }
    }

    /**
     * Parses a <request-focus> element and requests focus on
     * the containing View.
     */
    private void parseRequestFocus(XmlPullParser parser, View view) throws XmlPullParserException, IOException {
        view.requestFocus();
        consumeChildElements(parser);
    }

    /**
     * Parses a <tag> element and sets a keyed tag on the
     * containing View.
     */
    private void parseViewTag(XmlPullParser parser, View view, AttributeSet attrs) throws XmlPullParserException, IOException {
        final Context context = view.getContext();
        final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewTag);
        final int key = ta.getResourceId(R.styleable.ViewTag_id, 0);
        final CharSequence value = ta.getText(R.styleable.ViewTag_value);
        view.setTag(key, value);
        ta.recycle();
        consumeChildElements(parser);
    }

    private void parseInclude(XmlPullParser parser, Context context, View parent, AttributeSet attrs) throws XmlPullParserException, IOException {
        int type;
        if (parent instanceof ViewGroup) {
            // Apply a theme wrapper, if requested. This is sort of a weird
            // edge case, since developers think the <include> overwrites
            // values in the AttributeSet of the included View. So, if the
            // included View has a theme attribute, we'll need to ignore it.
            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
            final int themeResId = ta.getResourceId(0, 0);
            final boolean hasThemeOverride = themeResId != 0;
            if (hasThemeOverride) {
                context = new ContextThemeWrapper(context, themeResId);
            }
            ta.recycle();
            // If the layout is pointing to a theme attribute, we have to
            // massage the value to get a resource identifier out of it.
            int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
            if (layout == 0) {
                final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
                if (value == null || value.length() <= 0) {
                    throw new InflateException("You must specify a layout in the" + " include tag: <include layout=\"@layout/layoutID\" />");
                }
                // Attempt to resolve the "?attr/name" string to an identifier.
                layout = context.getResources().getIdentifier(value.substring(1), null, null);
            }
            // The layout might be referencing a theme attribute.
            if (mTempValue == null) {
                mTempValue = new TypedValue();
            }
            if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) {
                layout = mTempValue.resourceId;
            }
            if (layout == 0) {
                final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
                throw new InflateException("You must specify a valid layout " + "reference. The layout ID " + value + " is not valid.");
            } else {
                final XmlResourceParser childParser = context.getResources().getLayout(layout);
                try {
                    final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
                    while ((type = childParser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
                    }
                    if (type != XmlPullParser.START_TAG) {
                        throw new InflateException(childParser.getPositionDescription() + ": No start tag found!");
                    }
                    final String childName = childParser.getName();
                    if (TAG_MERGE.equals(childName)) {
                        // The <merge> tag doesn't support android:theme, so
                        // nothing special to do here.
                        rInflate(childParser, parent, context, childAttrs, false);
                    } else {
                        final View view = createViewFromTag(parent, childName, context, childAttrs, hasThemeOverride);
                        final ViewGroup group = (ViewGroup) parent;
                        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Include);
                        final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
                        final int visibility = a.getInt(R.styleable.Include_visibility, -1);
                        a.recycle();
                        // We try to load the layout params set in the <include /> tag.
                        // If the parent can't generate layout params (ex. missing width
                        // or height for the framework ViewGroups, though this is not
                        // necessarily true of all ViewGroups) then we expect it to throw
                        // a runtime exception.
                        // We catch this exception and set localParams accordingly: true
                        // means we successfully loaded layout params from the <include>
                        // tag, false means we need to rely on the included layout params.
                        ViewGroup.LayoutParams params = null;
                        try {
                            params = group.generateLayoutParams(attrs);
                        } catch (RuntimeException e) {
                            // Ignore, just fail over to child attrs.
                        }
                        if (params == null) {
                            params = group.generateLayoutParams(childAttrs);
                        }
                        view.setLayoutParams(params);
                        // Inflate all children.
                        rInflateChildren(childParser, view, childAttrs, true);
                        if (id != View.NO_ID) {
                            view.setId(id);
                        }

group.addView(view);
                    }
                } finally {
                    childParser.close();
                }
            }
        } else {
            throw new InflateException("<include /> can only be used inside of a ViewGroup");
        }
        LayoutInflater.consumeChildElements(parser);
    }

    /**
     * Note: default visibility so that
     * LayoutInflater_Delegate can call it.
     */
    final static void consumeChildElements(XmlPullParser parser) throws XmlPullParserException, IOException {
        int type;
        final int currentDepth = parser.getDepth();
        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
            // Empty
        }
    }

    private static class BlinkLayout extends FrameLayout {

        private static final int MESSAGE_BLINK = 0x42;

        private static final int BLINK_DELAY = 500;

        private boolean mBlink;

        private boolean mBlinkState;

        private final Handler mHandler;

        public BlinkLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            mHandler = new Handler(new Handler.Callback() {

                @Override
                public boolean handleMessage(Message msg) {
                    if (msg.what == MESSAGE_BLINK) {
                        if (mBlink) {
                            mBlinkState = !mBlinkState;
                            makeBlink();
                        }
                        invalidate();
                        return true;
                    }
                    return false;
                }
            });
        }

        private void makeBlink() {
            Message message = mHandler.obtainMessage(MESSAGE_BLINK);
            mHandler.sendMessageDelayed(message, BLINK_DELAY);
        }

        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            mBlink = true;
            mBlinkState = true;
            makeBlink();
        }

        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            mBlink = false;
            mBlinkState = true;
            mHandler.removeMessages(MESSAGE_BLINK);
        }

        @Override
        protected void dispatchDraw(Canvas canvas) {
            if (mBlinkState) {
                super.dispatchDraw(canvas);
            }
        }
    }
}


switch(strengthValue) {
            case Collator.PRIMARY:
                return STRENGTH_PRIMARY;
            case Collator.SECONDARY:
                return STRENGTH_SECONDARY;
            case Collator.TERTIARY:
                return STRENGTH_TERTIARY;
            case Collator.IDENTICAL:
                return STRENGTH_IDENTICAL;
            default:
                throw new IllegalArgumentException("Incorrect strength value.");
        }

package org.apache.calcite.jdbc;

import org.apache.calcite.sql.SqlCollation;
import org.checkerframework.checker.initialization.qual.UnderInitialization;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.nio.charset.Charset;
import java.text.Collator;
import java.util.Locale;

/**
 * Collation that uses a specific {@link Collator} for comparison.
 */
public class JavaCollation extends SqlCollation {

    private final Collator collator;

    public JavaCollation(Coercibility coercibility, Locale locale, Charset charset, int strength) {
        super(coercibility, locale, charset, getStrengthString(strength));
        collator = Collator.getInstance(locale);
        collator.setStrength(strength);
    }

    // Strength values
    private static final String STRENGTH_PRIMARY = "primary";

    private static final String STRENGTH_SECONDARY = "secondary";

    private static final String STRENGTH_TERTIARY = "tertiary";

    private static final String STRENGTH_IDENTICAL = "identical";

    private static String getStrengthString(int strengthValue) {

    }

    @Override
    protected String generateCollationName(@UnderInitialization JavaCollation this, Charset charset) {
        return super.generateCollationName(charset) + "$JAVA_COLLATOR";
    }

    @Override
    @Nullable
    public Collator getCollator() {
        return collator;
    }
}


switch(in.charAt(i)) {
                    case '\'':
                    case '!':
                        r.append(in, start, i);
                        r.append('\'');
                        r.append('\\');
                        r.append(in.charAt(i));
                        r.append('\'');
                        start = i + 1;
                        break;
                }

/*
 * and other copyright owners as documented in the project's IP log.
 *
 *
 * All rights reserved.
 *
 */
package org.eclipse.jgit.util;

import java.util.Arrays;
import org.eclipse.jgit.lib.Constants;

/**
 * Utility functions related to quoted string handling.
 */
public abstract class QuotedString {

    /**
     * Quoting style that obeys the rules Git applies to file names
     */
    public static final GitPathStyle GIT_PATH = new GitPathStyle();

    /**
     * Quoting style used by the Bourne shell.
     *

     * Quotes are unconditionally inserted during {@link #quote(String)}. This
     * protects shell meta-characters like $ or ~ from
     * being recognized as special.
     */
    public static final BourneStyle BOURNE = new BourneStyle();

    /**
     * Bourne style, but permits ~user at the start of the string.
     */
    public static final BourneUserPathStyle BOURNE_USER_PATH = new BourneUserPathStyle();

    /**
     * Quote an input string by the quoting rules.
     *

     * If the input string does not require any quoting, the same String
     * reference is returned to the caller.
     *

     * Otherwise a quoted string is returned, including the opening and closing
     * quotation marks at the start and end of the string. If the style does not
     * permit raw Unicode characters then the string will first be encoded in
     * UTF-8, with unprintable sequences possibly escaped by the rules.
     *
     * @param in
     *            any non-null Unicode string.
     * @return a quoted string. See above for details.
     */
    public abstract String quote(String in);

    /**
     * Clean a previously quoted input, decoding the result via UTF-8.
     *

     * This method must match quote such that:
     *
     *

     * a.equals(dequote(quote(a)));
     *

     *
     * is true for any a.
     *
     * @param in
     *            a Unicode string to remove quoting from.
     * @return the cleaned string.
     * @see #dequote(byte[], int, int)
     */
    public String dequote(final String in) {
        final byte[] b = Constants.encode(in);
        return dequote(b, 0, b.length);
    }

    /**
     * Decode a previously quoted input, scanning a UTF-8 encoded buffer.
     *

     * This method must match quote such that:
     *
     *

     * a.equals(dequote(Constants.encode(quote(a))));
     *

     *
     * is true for any a.
     *

     * This method removes any opening/closing quotation marks added by
     * {@link #quote(String)}.
     *
     * @param in
     *            the input buffer to parse.
     * @param offset
     *            first position within in to scan.
     * @param end
     *            one position past in in to scan.
     * @return the cleaned string.
     */
    public abstract String dequote(byte[] in, int offset, int end);

    /**
     * Quoting style used by the Bourne shell.
     *

     * Quotes are unconditionally inserted during {@link #quote(String)}. This
     * protects shell meta-characters like $ or ~ from
     * being recognized as special.
     */
    public static class BourneStyle extends QuotedString {

        @Override
        public String quote(final String in) {
            final StringBuilder r = new StringBuilder();
            r.append('\'');
            int start = 0, i = 0;
            for (; i < in.length(); i++) {

            }
            r.append(in, start, i);
            r.append('\'');
            return r.toString();
        }

        @Override
        public String dequote(final byte[] in, int ip, final int ie) {
            boolean inquote = false;
            final byte[] r = new byte[ie - ip];
            int rPtr = 0;
            while (ip < ie) {
                final byte b = in[ip++];
                switch(b) {
                    case '\'':
                        inquote = !inquote;
                        continue;
                    case '\\':
                        if (inquote || ip == ie)
                            // literal within a quote
                            r[rPtr++] = b;
                        else
                            r[rPtr++] = in[ip++];
                        continue;
                    default:
                        r[rPtr++] = b;
                        continue;
                }
            }
            return RawParseUtils.decode(Constants.CHARSET, r, 0, rPtr);
        }
    }

    /**
     * Bourne style, but permits <code>~user</code> at the start of the string.
     */
    public static class BourneUserPathStyle extends BourneStyle {

        @Override
        public String quote(final String in) {
            if (in.matches("^~[A-Za-z0-9_-]+$")) {
                // If the string is just "~user" we can assume they
                return in + "/";
            }
            if (in.matches("^~[A-Za-z0-9_-]*/.*$")) {
                // If the string is of "~/path" or "~user/path"
                // we must not escape ~/ or ~user/ from the shell.
                final int i = in.indexOf('/') + 1;
                if (i == in.length())
                    return in;
                return in.substring(0, i) + super.quote(in.substring(i));
            }
            return super.quote(in);
        }
    }

    /**
     * Quoting style that obeys the rules Git applies to file names
     */
    public static final class GitPathStyle extends QuotedString {

        private static final byte[] quote;

        static {
            quote = new byte[128];
            Arrays.fill(quote, (byte) -1);
            for (int i = '0'; i <= '9'; i++) quote[i] = 0;
            for (int i = 'a'; i <= 'z'; i++) quote[i] = 0;
            for (int i = 'A'; i <= 'Z'; i++) quote[i] = 0;
            quote[' '] = 0;
            quote['$'] = 0;
            quote['%'] = 0;
            quote['&'] = 0;
            quote['*'] = 0;
            quote['+'] = 0;
            quote[','] = 0;
            quote['-'] = 0;
            quote['.'] = 0;
            quote['/'] = 0;
            quote[':'] = 0;
            quote[';'] = 0;
            quote['='] = 0;
            quote['?'] = 0;
            quote['@'] = 0;
            quote['_'] = 0;
            quote['^'] = 0;
            quote['|'] = 0;
            quote['~'] = 0;
            quote['\u0007'] = 'a';
            quote['\b'] = 'b';
            quote['\f'] = 'f';
            quote['\n'] = 'n';
            quote['\r'] = 'r';
            quote['\t'] = 't';
            quote['\u000B'] = 'v';
            quote['\\'] = '\\';
            quote['"'] = '"';
        }

        @Override
        public String quote(final String instr) {
            if (instr.length() == 0)
                return "\"\"";
            boolean reuse = true;
            final byte[] in = Constants.encode(instr);
            final StringBuilder r = new StringBuilder(2 + in.length);
            r.append('"');
            for (int i = 0; i < in.length; i++) {
                final int c = in[i] & 0xff;
                if (c < quote.length) {
                    final byte style = quote[c];
                    if (style == 0) {
                        r.append((char) c);
                        continue;
                    }
                    if (style > 0) {
                        reuse = false;
                        r.append('\\');
                        r.append((char) style);
                        continue;
                    }
                }
                reuse = false;
                r.append('\\');
                r.append((char) (((c >> 6) & 03) + '0'));
                r.append((char) (((c >> 3) & 07) + '0'));
                r.append((char) (((c >> 0) & 07) + '0'));
            }
            if (reuse)
                return instr;
            r.append('"');
            return r.toString();
        }

        @Override
        public String dequote(final byte[] in, final int inPtr, final int inEnd) {
            if (2 <= inEnd - inPtr && in[inPtr] == '"' && in[inEnd - 1] == '"')
                return dq(in, inPtr + 1, inEnd - 1);
            return RawParseUtils.decode(Constants.CHARSET, in, inPtr, inEnd);
        }

        private static String dq(final byte[] in, int inPtr, final int inEnd) {
            final byte[] r = new byte[inEnd - inPtr];
            int rPtr = 0;
            while (inPtr < inEnd) {
                final byte b = in[inPtr++];
                if (b != '\\') {
                    r[rPtr++] = b;
                    continue;
                }
                if (inPtr == inEnd) {
                    // Lone trailing backslash. Treat it as a literal.
                    r[rPtr++] = '\\';
                    break;
                }
                switch(in[inPtr++]) {
                    case 'a':
                        r[rPtr++] = 0x07;
                        continue;
                    case 'b':
                        r[rPtr++] = '\b';
                        continue;
                    case 'f':
                        r[rPtr++] = '\f';
                        continue;
                    case 'n':
                        r[rPtr++] = '\n';
                        continue;
                    case 'r':
                        r[rPtr++] = '\r';
                        continue;
                    case 't':
                        r[rPtr++] = '\t';
                        continue;
                    case 'v':
                        r[rPtr++] = 0x0B;
                        continue;
                    case '\\':
                    case '"':
                        r[rPtr++] = in[inPtr - 1];
                        continue;
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                        {
                            int cp = in[inPtr - 1] - '0';
                            for (int n = 1; n < 3 && inPtr < inEnd; n++) {
                                final byte c = in[inPtr];
                                if ('0' <= c && c <= '7') {
                                    cp <<= 3;
                                    cp |= c - '0';
                                    inPtr++;
                                } else {
                                    break;
                                }
                            }
                            r[rPtr++] = (byte) cp;
                            continue;
                        }
                    default:
                        // Any other code is taken literally.
                        r[rPtr++] = '\\';
                        r[rPtr++] = in[inPtr - 1];
                        continue;
                }
            }
            return RawParseUtils.decode(Constants.CHARSET, r, 0, rPtr);
        }

        private GitPathStyle() {
            // Singleton
        }
    }
}


switch(displaySize) {
                case XS:
                    return CSS_HIDDEN_XS;
                case SM:
                    return CSS_HIDDEN_SM;
                case MD:
                    return CSS_HIDDEN_MD;
                case LG:
                    return CSS_HIDDEN_LG;
                default:
                    return " ";
            }

package com.jarektoro.responsivelayout.Styleable;

import com.jarektoro.responsivelayout.ResponsiveLayout;
import com.vaadin.ui.Component;

/**
 * Created by jarektoro on 11/22/16.
 */
public class VisibilityCSSAdapter {

    private static final String CSS_VISIBLE_XS = "rl-visible-xs";

    private static final String CSS_VISIBLE_SM = "rl-visible-sm";

    private static final String CSS_VISIBLE_MD = "rl-visible-md";

    private static final String CSS_VISIBLE_LG = "rl-visible-lg";

    private static final String CSS_HIDDEN_XS = "rl-hidden-xs";

    private static final String CSS_HIDDEN_SM = "rl-hidden-sm";

    private static final String CSS_HIDDEN_MD = "rl-hidden-md";

    private static final String CSS_HIDDEN_LG = "rl-hidden-lg";

    public static CSSClassGroup xsClassGroup = new CSSClassGroup(CSS_VISIBLE_XS, CSS_HIDDEN_XS);

    public static CSSClassGroup smClassGroup = new CSSClassGroup(CSS_VISIBLE_SM, CSS_HIDDEN_SM);

    public static CSSClassGroup mdClassGroup = new CSSClassGroup(CSS_VISIBLE_MD, CSS_HIDDEN_MD);

    public static CSSClassGroup lgClassGroup = new CSSClassGroup(CSS_VISIBLE_LG, CSS_HIDDEN_LG);

    public final Component component;

    public VisibilityCSSAdapter(Component component) {
        this.component = component;
    }

    public String getCssForDisplaySize(ResponsiveLayout.DisplaySize displaySize, boolean isVisible) {
        if (isVisible) {
            switch(displaySize) {
                case XS:
                    return CSS_VISIBLE_XS;
                case SM:
                    return CSS_VISIBLE_SM;
                case MD:
                    return CSS_VISIBLE_MD;
                case LG:
                    return CSS_VISIBLE_LG;
                default:
                    return "";
            }
        } else {

        }
    }

    // Manipulate user of adapter
    public boolean isVisibleForDisplaySize(ResponsiveLayout.DisplaySize displaySize) {
        if (displaySize == ResponsiveLayout.DisplaySize.XS) {
            for (String clazz : VisibilityCSSAdapter.xsClassGroup.classes) {
                if (this.component.getStyleName().contains(clazz)) {
                    if (clazz.contains("hidden")) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        } else if (displaySize == ResponsiveLayout.DisplaySize.SM) {
            for (String clazz : VisibilityCSSAdapter.smClassGroup.classes) {
                if (this.component.getStyleName().contains(clazz)) {
                    if (clazz.contains("hidden")) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        } else if (displaySize == ResponsiveLayout.DisplaySize.MD) {
            for (String clazz : VisibilityCSSAdapter.mdClassGroup.classes) {
                if (this.component.getStyleName().contains(clazz)) {
                    if (clazz.contains("hidden")) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        } else if (displaySize == ResponsiveLayout.DisplaySize.LG) {
            for (String clazz : VisibilityCSSAdapter.lgClassGroup.classes) {
                if (this.component.getStyleName().contains(clazz)) {
                    if (clazz.contains("hidden")) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        }
        return true;
    }

    public void setVisibility(ResponsiveLayout.DisplaySize displaySize, boolean isVisible) {
        if (displaySize == ResponsiveLayout.DisplaySize.XS) {
            for (String clazz : VisibilityCSSAdapter.xsClassGroup.classes) {
                this.component.removeStyleName(clazz);
            }
        }
        if (displaySize == ResponsiveLayout.DisplaySize.SM) {
            for (String clazz : VisibilityCSSAdapter.smClassGroup.classes) {
                this.component.removeStyleName(clazz);
            }
        }
        if (displaySize == ResponsiveLayout.DisplaySize.MD) {
            for (String clazz : VisibilityCSSAdapter.mdClassGroup.classes) {
                this.component.removeStyleName(clazz);
            }
        }
        if (displaySize == ResponsiveLayout.DisplaySize.LG) {
            for (String clazz : VisibilityCSSAdapter.lgClassGroup.classes) {
                this.component.removeStyleName(clazz);
            }
        }
        this.component.addStyleName(getCssForDisplaySize(displaySize, isVisible));
    }
}


switch(notification) {
            default:
                channelId = "generic_noti";
                channelName = "Generic";
                chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE);
                break;
        }

package io.agora.rtc.ss.utils;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import io.agora.rtc.ss.R;

public class NotificationHelper {

    public static Notification getForeNotification(Context context) {
        Notification notification;
        String eventTitle = context.getResources().getString(R.string.app_name);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationHelper.generateChannelId(context, 55431)).setContentTitle(eventTitle).setContentText(eventTitle);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            builder.setColor(context.getResources().getColor(android.R.color.black));
        notification = builder.build();
        notification.flags |= Notification.FLAG_ONGOING_EVENT;
        return notification;
    }

    public static String generateChannelId(Context ctx, int notification) {
        String channelId;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            channelId = NotificationHelper.createNotificationChannel(ctx, notification);
        } else {
            // If earlier version channel ID is not used
            channelId = "";
        }
        return channelId;
    }

    @RequiresApi(Build.VERSION_CODES.O)
    @TargetApi(Build.VERSION_CODES.O)
    private static String createNotificationChannel(Context ctx, int notification) {
        String channelId;
        String channelName;
        NotificationChannel chan;

        chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        NotificationManager service = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
        service.createNotificationChannel(chan);
        return channelId;
    }
}


switch(_type) {
            case FIXED:
                result.append("fixed");
                break;
            case PERCENT:
                result.append("percent");
                break;
            case VARIABLE:
                result.append("variable");
                break;
            default:
                result.append("unknown");
        }

package com.openhtmltopdf.css.style;

// A simplified version of KHTML's Length type.  It's very convenient to be able
// to treat length values (including auto) in a uniform matter when calculating
// table column widths.  Our own LengthValue is too heavyweight for this purpose and
// doesn't encompass variable (auto) widths.
public class Length {

    // Should use something more reasonable here (e.g. a few feet based on the current
    public static final int MAX_WIDTH = Integer.MAX_VALUE / 2;

    public static final int VARIABLE = 1;

    public static final int FIXED = 2;

    public static final int PERCENT = 3;

    private int _type = VARIABLE;

    private long _value = 0;

    public Length() {
    }

    public Length(long value, int type) {
        _value = value;
        _type = type;
    }

    public void setValue(long value) {
        _value = value;
    }

    public long value() {
        return _value;
    }

    public void setType(int type) {
        _type = type;
    }

    public int type() {
        return _type;
    }

    public boolean isVariable() {
        return _type == VARIABLE;
    }

    public boolean isFixed() {
        return _type == FIXED;
    }

    public boolean isPercent() {
        return _type == PERCENT;
    }

    public long width(int maxWidth) {
        switch(_type) {
            case FIXED:
                return _value;
            case PERCENT:
                return maxWidth * _value / 100;
            case VARIABLE:
                return maxWidth;
            default:
                return -1;
        }
    }

    public long minWidth(int maxWidth) {
        switch(_type) {
            case FIXED:
                return _value;
            case PERCENT:
                return maxWidth * _value / 100;
            default:
                return 0;
        }
    }

    @Override
    public String toString() {
        StringBuilder result = new StringBuilder();
        result.append("(type=");

        result.append(", value=");
        result.append(_value);
        result.append(")");
        return result.toString();
    }
}


switch(kind) {
            case LIST:
                return PropertyKind.LIST;
            case SET:
                return PropertyKind.SET;
            case MAP:
                return PropertyKind.MAP;
            default:
                return PropertyKind.VALUE;
        }

package io.vertx.codegen;

import io.vertx.codegen.type.ClassKind;
import io.vertx.codegen.type.TypeInfo;
import java.util.HashMap;
import java.util.Map;

/**
 * The kind of property.
 *
 * @author Julien Viet
 */
public enum PropertyKind {

    /**
     * The property is a single value setter and optionally a getter.
     */
    VALUE,
    /**
     * The property is a list with a setter and optionally a getter.
     */
    LIST,
    /**
     * The property is a list with a setter and optionally a getter.
     */
    SET,
    /**
     * The property is a map with a setter and optionally a getter.
     */
    MAP;

    /**
     * @return true if the property kind is a list
     */
    public boolean isList() {
        return this == LIST;
    }

    /**
     * @return true if the property kind is a set
     */
    public boolean isSet() {
        return this == SET;
    }

    /**
     * @return true if the property kind is a map
     */
    public boolean isMap() {
        return this == MAP;
    }

    /**
     * @return true if the property kind is a single value
     */
    public boolean isValue() {
        return this == VALUE;
    }

    /**
     * Useful for testing the type property kind, allows to do prop.kind == PROP_VALUE instead of prop.kind.name() == "VALUE"
     */
    public static Map<String, PropertyKind> vars() {
        HashMap<String, PropertyKind> vars = new HashMap<>();
        for (PropertyKind propKind : PropertyKind.values()) {
            vars.put("PROP_" + propKind.name(), propKind);
        }
        return vars;
    }

    static PropertyKind forType(ClassKind kind) {


switch(msgIdx) {
                case MSG_REQUEST_1:
                    consumeRequest(input);
                    break;
                case -1:
                    break;
            }

package com.ociweb.pronghorn.network.schema;

import com.ociweb.pronghorn.pipe.FieldReferenceOffsetManager;
import com.ociweb.pronghorn.pipe.MessageSchema;
import com.ociweb.pronghorn.pipe.Pipe;
import com.ociweb.pronghorn.pipe.PipeReader;
import com.ociweb.pronghorn.pipe.PipeWriter;

/**
 * Defines how HTTP logging of a request works.
 */
public class HTTPLogRequestSchema extends MessageSchema<HTTPLogRequestSchema> {

    public final static FieldReferenceOffsetManager FROM = new FieldReferenceOffsetManager(new int[] { 0xc0400005, 0x90000000, 0x90800001, 0x88000000, 0xa8000000, 0xc0200005 }, (short) 0, new String[] { "Request", "Time", "ChannelId", "Sequence", "Head", null }, new long[] { 1, 11, 12, 13, 14, 0 }, new String[] { "global", null, null, null, null, null }, "HTTPLogRequest.xml", new long[] { 2, 2, 0 }, new int[] { 2, 2, 0 });

    public HTTPLogRequestSchema(FieldReferenceOffsetManager from) {
        super(from);
    }

    public HTTPLogRequestSchema() {
        super(FROM);
    }

    public static final HTTPLogRequestSchema instance = new HTTPLogRequestSchema();

    public static final int MSG_REQUEST_1 = 0x00000000;

    public static final int MSG_REQUEST_1_FIELD_TIME_11 = 0x00800001;

    public static final int MSG_REQUEST_1_FIELD_CHANNELID_12 = 0x00800003;

    public static final int MSG_REQUEST_1_FIELD_SEQUENCE_13 = 0x00400005;

    public static final int MSG_REQUEST_1_FIELD_HEAD_14 = 0x01400006;

    public static void consume(Pipe<HTTPLogRequestSchema> input) {
        while (PipeReader.tryReadFragment(input)) {
            int msgIdx = PipeReader.getMsgIdx(input);

            PipeReader.releaseReadLock(input);
        }
    }

    public static void consumeRequest(Pipe<HTTPLogRequestSchema> input) {
        long fieldTime = PipeReader.readLong(input, MSG_REQUEST_1_FIELD_TIME_11);
        long fieldChannelId = PipeReader.readLong(input, MSG_REQUEST_1_FIELD_CHANNELID_12);
        int fieldSequence = PipeReader.readInt(input, MSG_REQUEST_1_FIELD_SEQUENCE_13);
        StringBuilder fieldHead = PipeReader.readUTF8(input, MSG_REQUEST_1_FIELD_HEAD_14, new StringBuilder(PipeReader.readBytesLength(input, MSG_REQUEST_1_FIELD_HEAD_14)));
    }

    public static void publishRequest(Pipe<HTTPLogRequestSchema> output, long fieldTime, long fieldChannelId, int fieldSequence, CharSequence fieldHead) {
        PipeWriter.presumeWriteFragment(output, MSG_REQUEST_1);
        PipeWriter.writeLong(output, MSG_REQUEST_1_FIELD_TIME_11, fieldTime);
        PipeWriter.writeLong(output, MSG_REQUEST_1_FIELD_CHANNELID_12, fieldChannelId);
        PipeWriter.writeInt(output, MSG_REQUEST_1_FIELD_SEQUENCE_13, fieldSequence);
        PipeWriter.writeUTF8(output, MSG_REQUEST_1_FIELD_HEAD_14, fieldHead);
        PipeWriter.publishWrites(output);
    }
}


switch(action) {
            case PRESS:
                handlePress(key.getCode(), modifiers.getInternalCode());
                break;
            case RELEASE:
                handleRelease(key.getCode(), modifiers.getInternalCode());
                break;
            default:
                break;
        }

package engine.client.input.keybinding;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import engine.client.EngineClient;
import engine.event.Listener;
import engine.event.game.GameStartEvent;
import engine.event.game.GameTerminationEvent;
import engine.graphics.display.Window;
import engine.input.Action;
import engine.input.KeyCode;
import engine.input.Modifiers;
import engine.input.MouseButton;
import engine.logic.Tickable;
import engine.registry.Registries;
import engine.registry.Registry;
import java.util.Collection;
import java.util.List;

/**
 * Handles the registration of KeyBinding and also handles key inputs (and mouse
 * inputs)
 */
public class KeyBindingManager implements Tickable, KeyBindingConfig {

    private final EngineClient engine;

    /**
     * Mappes the key binding index to the KeyBinding objects.
     */
    private final Multimap<Integer, KeyBinding> indexToBinding = HashMultimap.create();

    /**
     * KeyBinding Registry
     */
    private Registry<KeyBinding> registry;

    public KeyBindingManager(EngineClient engine) {
        this.engine = engine;
        engine.getEventBus().register(this);
        Window window = engine.getGraphicsManager().getWindow();
        window.addKeyCallback(this::handleKey);
        window.addMouseCallback(this::handleMouse);
    }

    /**
     * Register a KeyBinding
     *
     * @param keybinding key binding to register
     * @Deprecated This should happen when listening to
     * EngineEvent.RegistrationStart
     */
    @Deprecated
    public void register(KeyBinding keybinding) {
        registry.register(keybinding);
    }

    @Listener
    public void onGameReady(GameStartEvent.Post event) {
        Registries.getRegistryManager().getRegistry(KeyBinding.class).ifPresent(registry -> {
            this.registry = registry;
            reload();
        });
    }

    @Listener
    public void onGameMarkedStop(GameTerminationEvent.Marked event) {
        this.registry = null;
        reload();
    }

    /**
     * Reload the bindings. Use this after keybinding settings have changed
     */
    public void reload() {
        indexToBinding.clear();
        if (registry == null)
            return;
        for (KeyBinding keybinding : registry.getValues()) {
            int code = keybinding.getKey().code;
            int mods = keybinding.getModifier().getInternalCode();
            indexToBinding.put(getIndex(code, mods), keybinding);
        }
    }

    protected void handlePress(int code, int modifiers) {
        Collection<KeyBinding> keyBindings = this.indexToBinding.get(getIndex(code, modifiers));
        for (KeyBinding binding : keyBindings) {
            if (engine.getGraphicsManager().getGUIManager().isShowing() && !binding.isAllowInScreen())
                continue;
            binding.setPressed(true);
            binding.setDirty(true);
        }
        // Trigger single key
        if (modifiers != 0) {
            handlePress(code, 0);
        }
    }

    protected void handleRelease(int code, int modifiers) {
        Collection<KeyBinding> keyBindings = this.indexToBinding.get(getIndex(code, modifiers));
        for (KeyBinding binding : keyBindings) {
            if (engine.getGraphicsManager().getGUIManager().isShowing() && !binding.isAllowInScreen())
                continue;
            binding.setPressed(false);
            if (binding.getActionMode() == ActionMode.PRESS) {
                binding.setDirty(true);
            }
        }
        // Trigger single key
        if (modifiers != 0) {
            handleRelease(code, 0);
        }
    }

    /**
     * Get the index of the modified key
     *
     * @param code      Key code
     * @param modifiers Modifiers
     * @return An index value with last 4-bits presenting the modifiers
     */
    protected int getIndex(int code, int modifiers) {
        return modifiers + (code << 4);
    }

    public void handleMouse(Window window, MouseButton button, Action action, Modifiers modifiers) {
        switch(action) {
            case PRESS:
                handlePress(button.ordinal() + 400, modifiers.getInternalCode());
                break;
            case RELEASE:
                handleRelease(button.ordinal() + 400, modifiers.getInternalCode());
                break;
            default:
                break;
        }
    }

    public void handleKey(Window window, KeyCode key, int scancode, Action action, Modifiers modifiers) {

    }

    /**
     * Handles Mouse and Key inputs
     */
    @Override
    public void tick() {
        boolean displayingScreen = engine.getGraphicsManager().getGUIManager().isShowing();
        if (displayingScreen) {
            releaseAllPressedKeys(false);
        }
        for (KeyBinding keyBinding : indexToBinding.values()) {
            if (displayingScreen && !keyBinding.isAllowInScreen())
                continue;
            if (keyBinding.isDirty()) {
                // state change
                keyBinding.setDirty(false);
                if (keyBinding.getActionMode() == ActionMode.PRESS) {
                    keyBinding.setActive(keyBinding.isPressed());
                } else {
                    if (keyBinding.isPressed()) {
                        keyBinding.setActive(!keyBinding.isActive());
                    }
                }
                if (keyBinding.isActive()) {
                    keyBinding.onKeyStart(engine);
                } else {
                    keyBinding.onKeyEnd(engine);
                }
            } else if (keyBinding.isActive()) {
                // keep key
                keyBinding.onKeyKeep(engine);
            }
        }
    }

    private void releaseAllPressedKeys(boolean releaseAll) {
        for (KeyBinding keyBinding : indexToBinding.values()) {
            if (!releaseAll && keyBinding.isAllowInScreen())
                continue;
            if (keyBinding.isDirty()) {
                // state change
                keyBinding.setDirty(false);
                if (keyBinding.getActionMode() == ActionMode.PRESS) {
                    keyBinding.setActive(keyBinding.isPressed());
                } else {
                    if (keyBinding.isPressed()) {
                        keyBinding.setActive(!keyBinding.isActive());
                    }
                }
                if (keyBinding.isActive()) {
                    keyBinding.setPressed(false);
                    keyBinding.setActive(false);
                } else {
                    keyBinding.onKeyEnd(engine);
                }
            } else if (keyBinding.isActive()) {
                keyBinding.setPressed(false);
                keyBinding.setActive(false);
                keyBinding.onKeyEnd(engine);
            }
        }
    }

    @Override
    public List<String> getRegisteredKeyBindings() {
        return ImmutableList.copyOf(registry.getKeys());
    }

    @Override
    public Key getBoundKeyFor(String target) {
        return registry.getValue(target).getKey();
    }

    @Override
    public void setBoundKeyFor(String target, Key key) {
        registry.getValue(target).setKey(key);
    }

    @Override
    public void setBoundKeyToDefault(String target) {
        KeyBinding binding = registry.getValue(target);
        binding.setKey(binding.getDefaultKey());
    }

    @Override
    public void saveConfig() {
        reload();
        // TODO: save config file to disk
    }

    public void loadConfig() {
        // TODO: load config file from disk
    }
}


switch(type) {
            case ALL:
                return saleService.findAll(onSucess, beforeStart);
            case FINALIZED:
                return saleService.findAllFinalizedSales(onSucess, beforeStart);
            case OPEN:
                return saleService.findAllOpenSales(onSucess, beforeStart);
        }

package com.tiagohs.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.tiagohs.controller.SaleTableController.TypeSaleTable;
import com.tiagohs.model.Sale;
import com.tiagohs.service.SaleService;
import com.tiagohs.util.WindowsUtils;
import javafx.concurrent.Service;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;

@Controller
public class SalesController extends BaseController {

    public static final String PATH_FXML = "/fxml/sales.fxml";

    public static final String SALES_TITLE_KEY = "sales.title";

    public static final String PATH_ICON = WindowsUtils.ICON_APP_PATH;

    @FXML
    private AnchorPane allContainer;

    @FXML
    private AnchorPane openContainer;

    @FXML
    private AnchorPane finalizedContainer;

    @Autowired
    private SaleService saleService;

    @Override
    public <T> void init(Stage stage, HashMap<String, T> parameters) {
        super.init(stage, parameters);
        allContainer.getChildren().add(createAllTable(TypeSaleTable.ALL));
        openContainer.getChildren().add(createAllTable(TypeSaleTable.OPEN));
        finalizedContainer.getChildren().add(createAllTable(TypeSaleTable.FINALIZED));
    }

    @Override
    protected void onClose() {
        saleService.onClose();
    }

    private StackPane createAllTable(TypeSaleTable type) {
        Scene scene = null;
        try {
            FXMLLoader loader = WindowsUtils.loadFxml("/fxml/sale_table.fxml");
            scene = new Scene(loader.load());
            SaleTableController controller = loader.getController();
            controller.init(type, this);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return (StackPane) scene.lookup("#container");
    }

    public Service<List<Sale>> getSales(TypeSaleTable type, EventHandler<WorkerStateEvent> onSucess, EventHandler<WorkerStateEvent> beforeStart) {

        return null;
    }

    @FXML
    public void onNewSale() throws Exception {
        WindowsUtils.openNewWindow(SalesNewController.PATH_FXML, getWindowTitle(SalesNewController.NEW_SALE_TITLE_KEY), SalesNewController.PATH_ICON, null, Modality.APPLICATION_MODAL);
    }
}


switch(event.getModifiers() & (InputEvent.SHIFT_MASK | InputEvent.CTRL_MASK | InputEvent.ALT_MASK)) {
            case InputEvent.SHIFT_MASK:
                visibleRect.x += amount;
                break;
            case 0:
                visibleRect.y += amount;
                break;
            default:
                return State.REJECTED;
        }

package org.netbeans.modules.visual.action;

import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.widget.Widget;
import javax.swing.*;
import java.awt.event.InputEvent;
import java.awt.*;

/**
 * @author David Kaspar
 */
public class WheelPanAction extends WidgetAction.Adapter {

    public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) {
        JComponent view = widget.getScene().getView();
        Rectangle visibleRect = view.getVisibleRect();
        int amount = event.getWheelRotation() * 64;

        view.scrollRectToVisible(visibleRect);
        return State.CONSUMED;
    }
}