org.alfresco.mobile.android.application.fragments.node.browser.DocumentFolderBrowserFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.mobile.android.application.fragments.node.browser.DocumentFolderBrowserFragment.java

Source

/*
 *  Copyright (C) 2005-2015 Alfresco Software Limited.
 *
 *  This file is part of Alfresco Mobile for Android.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.alfresco.mobile.android.application.fragments.node.browser;

import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.alfresco.mobile.android.api.model.Folder;
import org.alfresco.mobile.android.api.model.Node;
import org.alfresco.mobile.android.api.model.Permissions;
import org.alfresco.mobile.android.api.model.Site;
import org.alfresco.mobile.android.api.model.impl.RepositoryVersionHelper;
import org.alfresco.mobile.android.api.session.AlfrescoSession;
import org.alfresco.mobile.android.application.R;
import org.alfresco.mobile.android.application.activity.BaseActivity;
import org.alfresco.mobile.android.application.activity.MainActivity;
import org.alfresco.mobile.android.application.activity.PrivateDialogActivity;
import org.alfresco.mobile.android.application.activity.PublicDispatcherActivity;
import org.alfresco.mobile.android.application.capture.DeviceCapture;
import org.alfresco.mobile.android.application.capture.DeviceCaptureHelper;
import org.alfresco.mobile.android.application.configuration.ConfigurableActionHelper;
import org.alfresco.mobile.android.application.configuration.model.view.RepositoryConfigModel;
import org.alfresco.mobile.android.application.fragments.DisplayUtils;
import org.alfresco.mobile.android.application.fragments.FragmentDisplayer;
import org.alfresco.mobile.android.application.fragments.GridAdapterHelper;
import org.alfresco.mobile.android.application.fragments.MenuFragmentHelper;
import org.alfresco.mobile.android.application.fragments.actions.AbstractActions;
import org.alfresco.mobile.android.application.fragments.actions.NodeActions;
import org.alfresco.mobile.android.application.fragments.builder.ListingFragmentBuilder;
import org.alfresco.mobile.android.application.fragments.create.DocumentTypesDialogFragment;
import org.alfresco.mobile.android.application.fragments.node.create.AddContentDialogFragment;
import org.alfresco.mobile.android.application.fragments.node.create.AddFolderDialogFragment;
import org.alfresco.mobile.android.application.fragments.node.create.CreateFolderDialogFragment;
import org.alfresco.mobile.android.application.fragments.node.details.NodeDetailsActionMode;
import org.alfresco.mobile.android.application.fragments.node.details.NodeDetailsFragment;
import org.alfresco.mobile.android.application.fragments.node.rendition.CarouselPreviewFragment;
import org.alfresco.mobile.android.application.fragments.search.SearchFragment;
import org.alfresco.mobile.android.application.intent.RequestCode;
import org.alfresco.mobile.android.application.managers.ActionUtils;
import org.alfresco.mobile.android.application.ui.form.picker.DocumentPickerFragment.onPickDocumentFragment;
import org.alfresco.mobile.android.application.widgets.ActionShortcutActivity;
import org.alfresco.mobile.android.application.widgets.BaseShortcutActivity;
import org.alfresco.mobile.android.application.widgets.FolderShortcutActivity;
import org.alfresco.mobile.android.async.OperationRequest;
import org.alfresco.mobile.android.async.OperationRequest.OperationBuilder;
import org.alfresco.mobile.android.async.Operator;
import org.alfresco.mobile.android.async.node.browse.NodeChildrenEvent;
import org.alfresco.mobile.android.async.node.browse.NodeChildrenRequest;
import org.alfresco.mobile.android.async.node.create.CreateDocumentEvent;
import org.alfresco.mobile.android.async.node.create.CreateDocumentRequest;
import org.alfresco.mobile.android.async.node.create.CreateFolderEvent;
import org.alfresco.mobile.android.async.node.delete.DeleteNodeEvent;
import org.alfresco.mobile.android.async.node.download.DownloadEvent;
import org.alfresco.mobile.android.async.node.favorite.FavoriteNodeEvent;
import org.alfresco.mobile.android.async.node.favorite.FavoriteNodeRequest;
import org.alfresco.mobile.android.async.node.sync.SyncNodeEvent;
import org.alfresco.mobile.android.async.node.sync.SyncNodeRequest;
import org.alfresco.mobile.android.async.node.update.UpdateContentEvent;
import org.alfresco.mobile.android.async.node.update.UpdateNodeEvent;
import org.alfresco.mobile.android.async.utils.ContentFileProgressImpl;
import org.alfresco.mobile.android.async.utils.NodePlaceHolder;
import org.alfresco.mobile.android.platform.exception.AlfrescoAppException;
import org.alfresco.mobile.android.platform.extensions.AnalyticsHelper;
import org.alfresco.mobile.android.platform.extensions.AnalyticsManager;
import org.alfresco.mobile.android.platform.extensions.ScanSnapManager;
import org.alfresco.mobile.android.platform.intent.PrivateIntent;
import org.alfresco.mobile.android.platform.io.AlfrescoStorageManager;
import org.alfresco.mobile.android.platform.utils.AccessibilityUtils;
import org.alfresco.mobile.android.platform.utils.BundleUtils;
import org.alfresco.mobile.android.platform.utils.SessionUtils;
import org.alfresco.mobile.android.sync.SyncContentManager;
import org.alfresco.mobile.android.sync.SyncContentScanEvent;
import org.alfresco.mobile.android.ui.SelectableFragment;
import org.alfresco.mobile.android.ui.activity.AlfrescoActivity;
import org.alfresco.mobile.android.ui.fragments.BaseListAdapter;
import org.alfresco.mobile.android.ui.node.browse.NodeBrowserFragment;
import org.alfresco.mobile.android.ui.node.browse.NodeBrowserTemplate;
import org.alfresco.mobile.android.ui.operation.OperationWaitingDialogFragment;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.impl.JSONConverter;

import com.cocosw.bottomsheet.BottomSheet;
import com.squareup.otto.Subscribe;

import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.ActionBar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.SpinnerAdapter;
import android.widget.TextView;

/**
 * Display a dialogFragment to retrieve information about the content of a
 * specific folder.
 * 
 * @author Jean Marie Pascal
 */
public class DocumentFolderBrowserFragment extends NodeBrowserFragment implements SelectableFragment {
    public static final String TAG = DocumentFolderBrowserFragment.class.getName();

    private boolean shortcutAlreadyVisible = false;

    private Folder importFolder;

    private File createFile;

    private long lastModifiedDate;

    private Button validationButton;

    private static final String ARGUMENT_IS_SHORTCUT = "isShortcut";

    private AbstractActions<Node> nActions;

    private File tmpFile;

    private onPickDocumentFragment fragmentPick;

    private Map<String, Node> pickedNodes = new HashMap<String, Node>(0);

    private List<Node> nodesToFavorite;

    private int displayMode = GridAdapterHelper.DISPLAY_GRID;

    private MenuItem displayMenuItem;

    private String fieldId;

    private boolean doFavorite;

    private Permissions permission;

    private boolean hasAudioRecorder = false;

    // //////////////////////////////////////////////////////////////////////
    // CONSTRUCTORS
    // //////////////////////////////////////////////////////////////////////
    public DocumentFolderBrowserFragment() {
        displayAsList = false;
        /** By default, the fragment is in Listing mode. */
        mode = MODE_LISTING;
        setHasOptionsMenu(true);
    }

    public static DocumentFolderBrowserFragment newInstanceByTemplate(Bundle b) {
        DocumentFolderBrowserFragment cbf = new DocumentFolderBrowserFragment();
        cbf.setArguments(b);
        b.putBoolean(ARGUMENT_BASED_ON_TEMPLATE, true);

        if (b != null) {
            if (b.containsKey(ARGUMENT_FOLDER_TYPE_ID)) {
                int index = b.getInt(ARGUMENT_FOLDER_TYPE_ID);
                if (index == NodeChildrenRequest.FOLDER_SHARED) {
                    cbf.screenName = AnalyticsManager.SCREEN_REPOSITORY_SHARED;
                } else if (index == NodeChildrenRequest.FOLDER_USER_HOMES) {
                    cbf.screenName = AnalyticsManager.SCREEN_REPOSITORY_USERHOME;
                }
            } else if (!b.containsKey(ARGUMENT_FOLDER) && !b.containsKey(ARGUMENT_SITE)
                    && !b.containsKey(ARGUMENT_PATH) && !b.containsKey(ARGUMENT_FOLDER_NODEREF)
                    && !b.containsKey(ARGUMENT_SITE_SHORTNAME)) {
                cbf.screenName = AnalyticsManager.SCREEN_REPOSITORY;
            } else {
                cbf.screenName = AnalyticsManager.SCREEN_NODE_LISTING;
            }
        }

        return cbf;
    }

    // //////////////////////////////////////////////////////////////////////
    // LIFE CYCLE
    // //////////////////////////////////////////////////////////////////////
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // HomeScreen Shortcut ?
        if (getArguments() != null && getArguments().containsKey(ARGUMENT_IS_SHORTCUT)) {
            checkSession = false;
        }

        // In case of Import mode, we disable thumbnails.
        if (getActivity() instanceof PublicDispatcherActivity) {
            mode = MODE_IMPORT;
            setActivateThumbnail(false);
        } else if (getActivity() instanceof PrivateDialogActivity) {
            mode = MODE_PICK;
            fragmentPick = ((PrivateDialogActivity) getActivity()).getOnPickDocumentFragment();
            fieldId = ((PrivateDialogActivity) getActivity()).getFieldId();
        } else if (getActivity() instanceof BaseShortcutActivity) {
            mode = MODE_IMPORT;
            setActivateThumbnail(false);
        }

        super.onActivityCreated(savedInstanceState);

        if (getSession() != null && RepositoryVersionHelper.isAlfrescoProduct(getSession())) {
            setActivateThumbnail(true);
        }

        // Test Audio Recording
        Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
        hasAudioRecorder = intent.resolveActivity(getActivity().getPackageManager()) != null;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v;
        // In case of Import mode, we wrap the listing with buttons.
        if (getActivity() instanceof PublicDispatcherActivity || getActivity() instanceof PrivateDialogActivity
                || getActivity() instanceof BaseShortcutActivity) {
            setRootView(inflater.inflate(R.layout.app_browser_import, container, false));
            init(getRootView(), emptyListMessageId);

            validationButton = (Button) viewById(R.id.action_validation);
            GridView gridView = (GridView) viewById(R.id.gridview);
            if (getActivity() instanceof PrivateDialogActivity) {
                validationButton.setText(R.string.done);
                gridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE);
            } else if (getActivity() instanceof BaseShortcutActivity) {
                validationButton.setText(R.string.select_folder);
                gridView.setChoiceMode(GridView.CHOICE_MODE_SINGLE);
            } else {
                gridView.setChoiceMode(GridView.CHOICE_MODE_SINGLE);
            }
            gridView.setClickable(true);

            v = getRootView();
        } else {
            v = super.onCreateView(inflater, container, savedInstanceState);

            GridView gridView = (GridView) v.findViewById(R.id.gridview);
            gridView.setChoiceMode(GridView.CHOICE_MODE_SINGLE);
            gridView.setClickable(true);

            gridView.setBackgroundColor(getResources().getColor(R.color.grey_lighter));
        }

        return v;
    }

    protected void prepareEmptyInitialView(View ev, ImageView emptyImageView, TextView firstEmptyMessage,
            TextView secondEmptyMessage) {
        prepareEmptyView(ev, emptyImageView, firstEmptyMessage, secondEmptyMessage);
    }

    @Override
    protected void prepareEmptyView(View ev, ImageView emptyImageView, TextView firstEmptyMessage,
            TextView secondEmptyMessage) {

        int iconId = R.drawable.ic_empty_folder_ro;
        int titleId = R.string.nodebrowser_empty_ro_title;
        int descriptionId = -1;
        try {
            if (parentFolder != null) {
                if (ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                        ConfigurableActionHelper.ACTION_CREATE_FOLDER)) {
                    iconId = R.drawable.ic_empty_folder_rw;
                    titleId = R.string.nodebrowser_empty_rw_title;
                    descriptionId = R.string.nodebrowser_empty_rw_description;
                }
            }
        } catch (Exception e) {
            // DO Nothing
        }

        emptyImageView.setImageResource(iconId);
        emptyImageView.setLayoutParams(DisplayUtils.resizeLayout(getActivity(), 275, 275));
        firstEmptyMessage.setText(titleId);
        if (descriptionId != -1) {
            secondEmptyMessage.setVisibility(View.VISIBLE);
            secondEmptyMessage.setText(descriptionId);
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        int titleId = R.string.app_name;
        if (getActivity() instanceof PublicDispatcherActivity) {
            mode = MODE_IMPORT;
            titleId = R.string.import_document_title;
            checkValidationButton();
        } else if (getActivity() instanceof PrivateDialogActivity) {
            mode = MODE_PICK;
            titleId = R.string.picker_document_title;
            checkValidationButton();
        } else if (getActivity() instanceof ActionShortcutActivity) {
            mode = MODE_IMPORT;
            titleId = R.string.shortcut_action_create;
            checkValidationButton();
        } else if (getActivity() instanceof FolderShortcutActivity) {
            mode = MODE_IMPORT;
            titleId = R.string.shortcut_create;
            checkValidationButton();
        }

        // If the fragment is resumed after user content creation action, we
        // have to check if the file has been modified or not. Depending on
        // result we prompt the upload dialog or we do nothing (no modification
        // / blank file)
        if (createFile != null) {
            if (createFile.length() > 0 && lastModifiedDate < createFile.lastModified()) {
                tmpFile = createFile;
            } else {
                if (!createFile.delete()) {
                    Log.w(TAG, createFile.getName() + "is not deleted.");
                }
                createFile = null;
            }
        }

        if (tmpFile != null) {
            importFolder = ((MainActivity) getActivity()).getImportParent();
            createFile(tmpFile);
        }

        if (getActionBar() != null) {
            getActionBar().setDisplayHomeAsUpEnabled(true);
            getActionBar().setDisplayShowCustomEnabled(false);
            getActivity().setTitle(titleId);
            AccessibilityUtils.sendAccessibilityEvent(getActivity());
            if (shortcutAlreadyVisible) {
                displayPathShortcut();
            }
        }

        refreshListView();

        // For tablet : Display Item if node has been selected previously and
        // after a resume
        if (selectedItems != null && selectedItems.size() == 1 && DisplayUtils.hasCentralPane(getActivity())
                && getFragmentManager()
                        .findFragmentById(DisplayUtils.getCentralFragmentId(getActivity())) == null) {
            NodeDetailsFragment.with(getActivity()).parentFolder(parentFolder).node(selectedItems.get(0)).display();
        }
    }

    @Override
    public void onStop() {
        if (nActions != null) {
            nActions.finish();
        }
        super.onStop();
    }

    public void refreshListView() {
        super.refreshListView();
        if (adapter != null && adapter instanceof ProgressNodeAdapter) {
            ((ProgressNodeAdapter) adapter).refreshOperations();
        }
    }

    // //////////////////////////////////////////////////////////////////////
    // PATH
    // //////////////////////////////////////////////////////////////////////
    private void displayPathShortcut() {
        displayPathShortcut(false);
    }

    private void displayPathShortcut(boolean force) {
        // /QUICK PATH
        if (parentFolder != null && getActionBar() != null) {
            // If tablet & right panel displayed show nothing
            if (DisplayUtils.hasCentralPane(getActivity()) && !force) {
                Fragment sideFragment = getFragmentManager()
                        .findFragmentById(DisplayUtils.getCentralFragmentId(getActivity()));
                if (sideFragment != null) {
                    return;
                }
            }

            ((ViewGroup) getActionBar().getCustomView()).setVisibility(View.GONE);
            getActionBar().setDisplayUseLogoEnabled(false);
            getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
            String pathValue = parentFolder.getName();
            if (parentFolder.getProperty(PropertyIds.PATH) != null) {
                pathValue = parentFolder.getProperty(PropertyIds.PATH).getValue();
            }

            boolean fromSite = false;
            if (getActivity() instanceof MainActivity) {
                fromSite = site != null;
            }

            List<String> listFolder = getPath(pathValue, fromSite);
            SpinnerAdapter adapter = new FolderPathAdapter(getActivity(),
                    android.R.layout.simple_spinner_dropdown_item, listFolder);

            ActionBar.OnNavigationListener mOnNavigationListener = new android.support.v7.app.ActionBar.OnNavigationListener() {

                @Override
                public boolean onNavigationItemSelected(int itemPosition, long itemId) {
                    if (itemPosition == 0) {
                        return true;
                    }

                    if (isShortcut()) {
                        boolean fromSite = false;
                        if (getActivity() instanceof MainActivity) {
                            fromSite = site != null;
                        }

                        // Determine the path
                        String pathValue = parentFolder.getProperty(PropertyIds.PATH).getValue();
                        List<String> listFolder = getPath(pathValue, fromSite);

                        List<String> subPath = listFolder.subList(itemPosition, listFolder.size());
                        Collections.reverse(subPath);
                        String path = subPath.remove(0);
                        for (String string : subPath) {
                            path += string + "/";
                        }

                        DocumentFolderBrowserFragment.with(getActivity()).path(path).shortcut(true).display();
                    } else {
                        for (int i = 0; i < itemPosition; i++) {
                            getFragmentManager().popBackStack();
                        }
                    }
                    return true;
                }

            };

            getActionBar().setListNavigationCallbacks(adapter, mOnNavigationListener);

            shortcutAlreadyVisible = true;
        }
    }

    private List<String> getPath(String pathValue, boolean fromSite) {
        String[] path = pathValue.split("/");
        if (path.length == 0) {
            path = new String[] { "/" };
        }

        String tmpPath;

        List<String> listFolder = new ArrayList<String>(path.length);
        for (int i = path.length - 1; i > -1; i--) {
            tmpPath = path[i];

            if (tmpPath.isEmpty()) {
                tmpPath = "/";
            }
            listFolder.add(tmpPath);
        }

        if (fromSite && listFolder.size() > 3) {
            for (int i = 0; i < 3; i++) {
                listFolder.remove(listFolder.size() - 1);
            }
            listFolder.add(listFolder.size() - 1, site.getTitle());
            listFolder.remove(listFolder.size() - 1);
        }

        return listFolder;
    }

    // //////////////////////////////////////////////////////////////////////
    // LIST ACTIONS
    // //////////////////////////////////////////////////////////////////////
    @Override
    public void onListItemClick(GridView l, View v, int position, long id) {
        Node item = (Node) l.getItemAtPosition(position);

        if (item instanceof NodePlaceHolder) {
            l.setItemChecked(position, false);
            return;
        }

        // In case of import mode, we disable selection of document.
        // It's only possible to select a folder for navigation purpose.
        if (mode == MODE_IMPORT && getActivity() instanceof PublicDispatcherActivity
                || getActivity() instanceof BaseShortcutActivity) {
            l.setChoiceMode(GridView.CHOICE_MODE_NONE);
            if (item.isFolder()) {
                DocumentFolderBrowserFragment.with(getActivity()).folder((Folder) item).shortcut(isShortcut())
                        .display();
            }
            return;
        }

        // In case of pick mode, we allow multiSelection
        if (mode == MODE_PICK && getActivity() instanceof PrivateDialogActivity && item.isDocument()) {
            l.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE);
            if (pickedNodes.containsKey(item.getIdentifier())) {
                pickedNodes.remove(item.getIdentifier());
            } else {
                pickedNodes.put(item.getIdentifier(), item);
            }
            l.setItemChecked(position, true);
            checkValidationButton();
            return;
        }

        // In other case, listing mode
        Boolean hideDetails = false;
        if (!selectedItems.isEmpty()) {
            hideDetails = selectedItems.get(0).getIdentifier().equals(item.getIdentifier());
        }
        l.setItemChecked(position, true);

        if (nActions != null && nActions.hasMultiSelectionEnabled()) {
            nActions.selectNode(item);
            if (selectedItems.size() == 0) {
                hideDetails = true;
            }
        } else {
            selectedItems.clear();
            if (!hideDetails && item.isDocument() && DisplayUtils.hasCentralPane(getActivity())) {
                selectedItems.add(item);
            }
        }

        if (hideDetails) {
            FragmentDisplayer.clearCentralPane(getActivity());
            if (nActions != null && !nActions.hasMultiSelectionEnabled()) {
                nActions.finish();
            }
            getActivity().supportInvalidateOptionsMenu();
            displayPathShortcut(true);
        } else if (nActions == null || (nActions != null && !nActions.hasMultiSelectionEnabled())) {
            if (item.isFolder()) {
                FragmentDisplayer.clearCentralPane(getActivity());
                DocumentFolderBrowserFragment.with(getActivity()).site(site).folder((Folder) item)
                        .shortcut(isShortcut()).display();
            } else {
                NodeDetailsFragment.with(getActivity()).parentFolder(parentFolder).node(item).display();
            }
        }
    }

    public boolean onListItemLongClick(GridView l, View v, int position, long id) {
        // We disable long click during import mode.
        if (mode == MODE_IMPORT || mode == MODE_PICK) {
            return false;
        }

        if (nActions != null && nActions instanceof NodeDetailsActionMode) {
            nActions.finish();
        }

        Node n = (Node) l.getItemAtPosition(position);
        boolean b;
        if (n instanceof NodePlaceHolder) {
            getActivity().startActivity(new Intent(PrivateIntent.ACTION_DISPLAY_OPERATIONS)
                    .putExtra(PrivateIntent.EXTRA_ACCOUNT_ID, SessionUtils.getAccount(getActivity()).getId()));
            b = false;
        } else {
            l.setItemChecked(position, true);
            b = startSelection(n);
            if (DisplayUtils.hasCentralPane(getActivity())) {
                FragmentDisplayer.with(getActivity()).remove(DisplayUtils.getCentralFragmentId(getActivity()));
                FragmentDisplayer.with(getActivity()).remove(android.R.id.tabcontent);
            }
        }
        return b;
    }

    public boolean hasActionMode() {
        return nActions != null;
    }

    private boolean startSelection(Node item) {
        if (nActions != null) {
            return false;
        }

        selectedItems.clear();
        selectedItems.add(item);

        // Start the CAB using the ActionMode.Callback defined above
        nActions = new NodeActions(DocumentFolderBrowserFragment.this, selectedItems);
        nActions.setOnFinishModeListener(new AbstractActions.onFinishModeListener() {
            @Override
            public void onFinish() {
                if (fab != null) {
                    fab.hide(true);
                    if (permission.canAddChildren()) {
                        fab.setImageResource(R.drawable.ic_content_add);
                        fab.setOnClickListener(onPrepareFabClickListener());
                        fab.show(true);
                    }
                }
                nActions = null;
                unselect();
                refreshListView();
            }
        });
        if (fab != null) {
            fab.hide(true);
            fab.setImageResource(R.drawable.ic_done_all_white);
            fab.setOnClickListener(onMultiSelectionFabClickListener());
            fab.show(true);
        }
        getActivity().startActionMode(nActions);
        return true;
    }

    // //////////////////////////////////////////////////////////////////////
    // REQUEST & RESULTS
    // //////////////////////////////////////////////////////////////////////
    @Override
    @Subscribe
    public void onResult(NodeChildrenEvent event) {
        if (getActivity() instanceof MainActivity && ((MainActivity) getActivity()).getCurrentNode() != null) {
            selectedItems.clear();
            selectedItems.add(((MainActivity) getActivity()).getCurrentNode());
        }

        if (event.parentFolder != null) {
            parentFolder = event.parentFolder;
            importFolder = parentFolder;
        }

        if (event.site != null) {
            this.site = event.site;
        }

        if (adapter == null) {
            adapter = onAdapterCreation();
            ((BaseListAdapter) adapter).setFragmentSettings(getArguments());
        }

        if (event.hasException) {
            if (adapter.getCount() == 0) {
                ev.setVisibility(View.VISIBLE);
            }

            if (event.exception != null && event.exception.getCause() instanceof CmisObjectNotFoundException) {
                displayEmptyView();
                if (viewById(R.id.empty_text) != null) {
                    ((TextView) viewById(R.id.empty_text)).setText(R.string.node_browser_folder_not_found);
                }
            } else {
                onResultError(event.exception);
            }
        } else {
            displayData(event);
        }
        ((NodeAdapter) adapter).setActivateThumbnail(hasActivateThumbnail());
        getActivity().invalidateOptionsMenu();
        displayPathShortcut();
        checkValidationButton();

        // Hide Loading progress
        refreshHelper.setRefreshComplete();
    }

    @Override
    protected ArrayAdapter<?> onAdapterCreation() {
        if (mode == MODE_PICK && adapter == null) {
            pickedNodes = fragmentPick.getNodeSelected(fieldId);
            return new ProgressNodeAdapter(this,
                    GridAdapterHelper.getDisplayItemLayout(getActivity(), gv, displayMode), parentFolder,
                    new ArrayList<Node>(0), pickedNodes, mode);
        } else if (adapter == null) {
            return new ProgressNodeAdapter(this,
                    GridAdapterHelper.getDisplayItemLayout(getActivity(), gv, displayMode), parentFolder,
                    new ArrayList<Node>(0), selectedItems, mode);
        }
        return null;
    }

    // //////////////////////////////////////////////////////////////////////
    // ACTIONS
    // //////////////////////////////////////////////////////////////////////
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case RequestCode.FILEPICKER:
            if (data != null && PrivateIntent.ACTION_PICK_FILE.equals(data.getAction())) {
                ActionUtils.actionPickFile(getFragmentManager().findFragmentByTag(TAG), RequestCode.FILEPICKER);
            } else if (data != null && data.getData() != null) {
                String tmpPath = ActionUtils.getPath(getActivity(), data.getData());
                if (tmpPath != null) {
                    tmpFile = new File(tmpPath);
                } else {
                    // Error case : Unable to find the file path associated
                    // to user pick.
                    // Sample : Picasa image case
                    ActionUtils.actionDisplayError(this,
                            new AlfrescoAppException(getString(R.string.error_unknown_filepath), true));
                }
            } else if (data != null && data.getExtras() != null
                    && data.getExtras().containsKey(Intent.EXTRA_STREAM)) {
                List<File> files = new ArrayList<File>();
                List<Uri> uris = data.getExtras().getParcelableArrayList(Intent.EXTRA_STREAM);
                for (Uri uri : uris) {
                    files.add(new File(ActionUtils.getPath(getActivity(), uri)));
                }
                createFiles(files);
            }
            break;
        default:
            break;
        }
    }

    public void createFile(File f) {
        // Create and show the dialog.
        AddContentDialogFragment newFragment = AddContentDialogFragment.newInstance(importFolder, f,
                (createFile != null));
        newFragment.show(getActivity().getSupportFragmentManager(), AddContentDialogFragment.TAG);
        tmpFile = null;
        createFile = null;
    }

    public void createFiles(List<File> files) {
        if (files.size() == 1) {
            createFile(files.get(0));
            return;
        } else {
            List<OperationBuilder> requestsBuilder = new ArrayList<OperationBuilder>(selectedItems.size());
            for (File file : files) {
                requestsBuilder.add(new CreateDocumentRequest.Builder(importFolder, file.getName(),
                        new ContentFileProgressImpl(file))
                                .setNotificationVisibility(OperationRequest.VISIBILITY_NOTIFICATIONS));
            }
            Operator.with(getActivity(), getAccount()).load(requestsBuilder);

            if (getActivity() instanceof PublicDispatcherActivity) {
                getActivity().finish();
            }
        }
        tmpFile = null;
        createFile = null;
    }

    public void createFolder() {
        FragmentDisplayer.with(getActivity()).remove(CreateFolderDialogFragment.TAG);

        // Create and show the dialog.
        AddFolderDialogFragment.newInstance(parentFolder)
                .show(getActivity().getSupportFragmentManager().beginTransaction(), CreateFolderDialogFragment.TAG);
    }

    public void refresh() {
        super.refresh();

        // Display Refresh Progress
        refreshHelper.setRefreshing();
    }

    // //////////////////////////////////////////////////////////////////////
    // MENU
    // //////////////////////////////////////////////////////////////////////
    public void getMenu(Menu menu) {
        if (parentFolder == null) {
            return;
        }

        if (getActivity() instanceof MainActivity) {
            getMenu(getSession(), menu, parentFolder);

            if (hasDocument()) {
                displayMenuItem = menu.add(Menu.NONE, R.id.menu_gallery, Menu.FIRST, R.string.display_gallery);
                displayMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
            }
        } else if (getActivity() instanceof PublicDispatcherActivity
                || getActivity() instanceof BaseShortcutActivity) {
            // permission =
            // getSession().getServiceRegistry().getDocumentFolderService().getPermissions(parentFolder);
            if (ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                    ConfigurableActionHelper.ACTION_CREATE_FOLDER)) {
                MenuItem mi = menu.add(Menu.NONE, R.id.menu_create_folder, Menu.FIRST, R.string.folder_create);
                mi.setIcon(R.drawable.ic_repository_light);
                mi.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            }
        }

        MenuFragmentHelper.getMenu(getActivity(), menu);
    }

    public void getMenu(AlfrescoSession session, Menu menu, Folder parentFolder) {
        MenuItem mi;

        if (parentFolder == null) {
            return;
        }
        try {
            permission = session.getServiceRegistry().getDocumentFolderService().getPermissions(parentFolder);
        } catch (Exception e) {
            return;
        }

        mi = menu.add(Menu.NONE, R.id.menu_search_from_folder, Menu.FIRST + 10, R.string.search);
        mi.setIcon(R.drawable.ic_search_light);
        mi.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

        if (ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                ConfigurableActionHelper.ACTION_CREATE_DOC)
                || ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                        ConfigurableActionHelper.ACTION_CREATE_FOLDER)
                || ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                        ConfigurableActionHelper.ACTION_NODE_UPLOAD)) {
            displayFab();
        }
    }

    @Override
    protected OnClickListener onPrepareFabClickListener() {
        if (permission == null || !permission.canAddChildren()) {
            return null;
        }

        return new OnClickListener() {
            @Override
            public void onClick(View v) {
                BottomSheet.Builder builder = new BottomSheet.Builder(getActivity(), R.style.M_StyleDialog)
                        .title(R.string.add_menu);
                if (ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                        ConfigurableActionHelper.ACTION_CREATE_FOLDER)) {
                    builder.sheet(R.id.menu_create_folder, R.drawable.ic_repository_light, R.string.folder_create);
                }

                if (ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                        ConfigurableActionHelper.ACTION_NODE_UPLOAD)) {
                    builder.sheet(R.id.menu_upload, R.drawable.ic_upload, R.string.upload_title);
                }

                if (ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                        ConfigurableActionHelper.ACTION_CREATE_DOC)) {
                    builder.sheet(R.id.menu_create_document, R.drawable.ic_doc_light, R.string.create_document);
                    builder.sheet(R.id.menu_device_capture_camera_photo, R.drawable.ic_camera, R.string.take_photo);
                    builder.sheet(R.id.menu_device_capture_camera_video, R.drawable.ic_videos, R.string.make_video);
                    if (hasAudioRecorder) {
                        builder.sheet(R.id.menu_device_capture_mic_audio, R.drawable.ic_microphone,
                                R.string.record_audio);
                    }
                    if (ScanSnapManager.getInstance(getActivity()) != null
                            && ScanSnapManager.getInstance(getActivity()).hasScanSnapApplication()) {
                        builder.sheet(R.id.menu_scan_document, R.drawable.ic_camera, R.string.scan);
                    }
                }

                builder.grid().listener(new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        onOptionMenuItemSelected(which);
                    }
                }).show();
            }
        };
    }

    protected OnClickListener onMultiSelectionFabClickListener() {
        return new OnClickListener() {
            @Override
            public void onClick(View v) {
                selectAll();
            }
        };
    }

    protected OnClickListener onCancelMultiSelectionFabClickListener() {
        return new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (nActions != null) {
                    nActions.finish();
                }
            }
        };
    }

    private void displayFab() {
        if (fab != null && fab.getVisibility() == View.GONE) {
            fab.setVisibility(View.VISIBLE);
            fab.setOnClickListener(onPrepareFabClickListener());
            fab.show(true);
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        if (!MenuFragmentHelper.canDisplayFragmentMenu(getActivity())) {
            return;
        }
        menu.clear();
        getMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return !onOptionMenuItemSelected(item.getItemId()) ? false : super.onOptionsItemSelected(item);
    }

    private boolean onOptionMenuItemSelected(int itemId) {
        if (getActivity() == null) {
            return false;
        }
        switch (itemId) {
        case R.id.menu_search_from_folder:
            AnalyticsHelper.reportOperationEvent(getActivity(), AnalyticsManager.CATEGORY_DOCUMENT_MANAGEMENT,
                    AnalyticsManager.ACTION_QUICK_ACTIONS, AnalyticsManager.ACTION_SEARCH, 1, false);
            search();
            return true;
        case R.id.menu_create_folder:
            createFolder();
            AnalyticsHelper.reportOperationEvent(getActivity(), AnalyticsManager.CATEGORY_DOCUMENT_MANAGEMENT,
                    AnalyticsManager.ACTION_QUICK_ACTIONS,
                    AnalyticsManager.ACTION_CREATE.concat(" " + AnalyticsManager.TYPE_FOLDER), 1, false);
            return true;
        case R.id.menu_upload:
            Intent i = new Intent(PrivateIntent.ACTION_PICK_FILE, null, getActivity(),
                    PublicDispatcherActivity.class);
            i.putExtra(PrivateIntent.EXTRA_FOLDER, AlfrescoStorageManager.getInstance(getActivity())
                    .getDownloadFolder(SessionUtils.getAccount(getActivity())));
            i.putExtra(PrivateIntent.EXTRA_ACCOUNT_ID, SessionUtils.getAccount(getActivity()).getId());
            startActivityForResult(i, RequestCode.FILEPICKER);
            return true;
        case R.id.menu_create_document:
            DocumentTypesDialogFragment dialogft = DocumentTypesDialogFragment
                    .newInstance(SessionUtils.getAccount(getActivity()), TAG);
            dialogft.show(getFragmentManager(), DocumentTypesDialogFragment.TAG);
            return true;
        case R.id.menu_gallery:
            CarouselPreviewFragment.with(getActivity()).display();
            return true;
        case R.id.menu_device_capture_camera_photo:
        case R.id.menu_device_capture_camera_video:
        case R.id.menu_device_capture_mic_audio:
            DeviceCapture capture = DeviceCaptureHelper.createDeviceCapture((BaseActivity) getActivity(), itemId);
            if (getActivity() instanceof MainActivity) {
                ((MainActivity) getActivity()).setCapture(capture);
            }
            return true;
        case R.id.menu_scan_document:
            if (ScanSnapManager.getInstance(getActivity()) != null) {
                ScanSnapManager.getInstance(getActivity()).startPresetChooser(getActivity());
                AnalyticsHelper.reportOperationEvent(getActivity(), AnalyticsManager.CATEGORY_DOCUMENT_MANAGEMENT,
                        AnalyticsManager.ACTION_QUICK_ACTIONS, AnalyticsManager.ACTION_SCAN, 1, false);
            }
            return true;
        default:
            break;
        }
        return false;
    }

    // //////////////////////////////////////////////////////////////////////
    // LIST MANAGEMENT UTILS
    // //////////////////////////////////////////////////////////////////////
    public void unselect() {
        selectedItems.clear();
    }

    /**
     * Remove a site object inside the listing without requesting an HTTP call.
     */
    public void remove(Node node) {
        if (adapter != null) {
            ((ProgressNodeAdapter) adapter).remove(node.getName());
            if (adapter.isEmpty()) {
                displayEmptyView();
            }
        }
    }

    @Override
    public void selectAll() {
        if (nActions != null && adapter != null) {
            nActions.selectNodes(((ProgressNodeAdapter) adapter).getNodes());
            adapter.notifyDataSetChanged();
        }

        if (fab != null) {
            fab.toggle(true);
            fab.setImageResource(R.drawable.ic_close_dark);
            fab.setOnClickListener(onCancelMultiSelectionFabClickListener());
            fab.toggle(true);
        }
    }

    public void select(Node updatedNode) {
        selectedItems.add(updatedNode);
    }

    public void highLight(Node updatedNode) {
        unselect();
        selectedItems.add(updatedNode);
        adapter.notifyDataSetChanged();
    }

    public List<Node> getNodes() {
        if (adapter != null) {
            return ((ProgressNodeAdapter) adapter).getNodes() != null ? ((ProgressNodeAdapter) adapter).getNodes()
                    : new ArrayList<Node>(0);
        } else {
            return new ArrayList<>(0);
        }
    }

    private boolean hasDocument() {
        if (adapter != null) {
            for (Node node : ((ProgressNodeAdapter) adapter).getNodes()) {
                if (node.isDocument()) {
                    return true;
                }
            }
        }
        return false;
    }

    public Node getSelectedNodes() {
        return (selectedItems != null && !selectedItems.isEmpty()) ? selectedItems.get(0) : null;
    }

    // //////////////////////////////////////////////////////////////////////
    // UTILS
    // //////////////////////////////////////////////////////////////////////
    public void search() {
        // Use case : DocumentLibrary Site
        if (folderParameter == null && site != null) {
            folderParameter = parentFolder;
        }
        SearchFragment.with(getActivity()).folder(folderParameter).site(site).display();
    }

    public void setCreateFile(File newFile) {
        this.createFile = newFile;
        this.lastModifiedDate = newFile.lastModified();
    }

    public Folder getImportFolder() {
        return importFolder;
    }

    public Folder getParentFolder() {
        return parentFolder;
    }

    public Site getSite() {
        return site;
    }

    @Override
    public int getMode() {
        return mode;
    }

    /**
     * Helper method to enable/disable the import button depending on mode and
     * permission.
     */
    private void checkValidationButton() {
        boolean enable = false;
        if (mode == MODE_IMPORT) {
            if (getActivity() instanceof FolderShortcutActivity) {
                validationButton.setEnabled(true);
                return;
            }

            if (parentFolder != null) {
                enable = ConfigurableActionHelper.isVisible(getActivity(), getAccount(), getSession(), parentFolder,
                        ConfigurableActionHelper.ACTION_NODE_UPLOAD);
            }
            validationButton.setEnabled(enable);
        } else if (mode == MODE_PICK && selectedItems != null) {
            validationButton.setText(String.format(
                    MessageFormat.format(getString(R.string.picker_attach_document), pickedNodes.size()),
                    pickedNodes.size()));
            validationButton.setEnabled(!pickedNodes.isEmpty());
            validationButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    fragmentPick.onNodeSelected(fieldId, pickedNodes);
                }
            });
        }
    }

    public boolean isShortcut() {
        if (getArguments().containsKey(ARGUMENT_IS_SHORTCUT)) {
            return (Boolean) getArguments().get(ARGUMENT_IS_SHORTCUT);
        } else {
            return false;
        }
    }

    @Override
    public void displayTitle() {
        displayPathShortcut();
    }

    // ///////////////////////////////////////////////////////////////////////////
    // EVENTS RECEIVER
    // ///////////////////////////////////////////////////////////////////////////
    @Subscribe
    public void onDocumentUpdated(UpdateNodeEvent event) {
        if (event.hasException) {
            return;
        }
        if (event.parentFolder == null || parentFolder == null
                || !event.parentFolder.getIdentifier().equals(parentFolder.getIdentifier())) {
            return;
        }
        Node updatedNode = event.data;
        remove(event.initialNode);

        if (adapter != null) {
            ((ProgressNodeAdapter) adapter).replaceNode(updatedNode);
            displayDataView();
        }
        if (getActivity() instanceof BaseActivity) {
            ((BaseActivity) getActivity()).removeWaitingDialog();
        }
    }

    @Subscribe
    public void onContentUpdated(UpdateContentEvent event) {
        if (event.hasException) {
            return;
        }
        Node updatedNode = event.data;
        remove(event.node);
        if (adapter != null) {
            ((ProgressNodeAdapter) adapter).replaceNode(updatedNode);
            displayDataView();
        }
        if (getActivity() instanceof BaseActivity) {
            ((BaseActivity) getActivity()).removeWaitingDialog();
        }
    }

    @Subscribe
    public void onNodeDeleted(DeleteNodeEvent event) {
        if (event.data == null) {
            return;
        }
        remove(event.data);
        if (adapter.getCount() == 0) {
            setListShown(true);
        }
    }

    @Subscribe
    public void onDocumentDownloaded(DownloadEvent event) {
        if (event.hasException) {
            return;
        }
        if (parentFolder != null && parentFolder.getIdentifier().equals(event.parentFolder.getIdentifier())) {
            ((ProgressNodeAdapter) adapter).replaceNode(event.document);
        }
    }

    @Subscribe
    public void onDocumentCreated(CreateDocumentEvent event) {
        if (event.hasException || adapter == null) {
            return;
        }
        boolean hasEmptyAdapter = true;
        hasEmptyAdapter = (adapter.getCount() == 0);
        if (parentFolder != null && parentFolder.getIdentifier().equals(event.parentFolder.getIdentifier())) {
            ((ProgressNodeAdapter) adapter).replaceNode(event.data);
        }
        if (hasEmptyAdapter) {
            displayDataView();
        }
    }

    @Subscribe
    public void onFolderCreated(CreateFolderEvent event) {
        Node node = event.data;
        if (node == null) {
            return;
        }
        boolean hasEmptyAdapter = true;
        hasEmptyAdapter = (adapter.getCount() == 0);
        ((ProgressNodeAdapter) adapter).replaceNode(node);
        if (hasEmptyAdapter) {
            displayDataView();
        }
        if (getActivity() instanceof BaseActivity) {
            ((BaseActivity) getActivity()).removeWaitingDialog();
        }
    }

    @Subscribe
    public void onFavoriteNodeEvent(FavoriteNodeEvent event) {
        if (event.hasException) {
            return;
        }
        if (adapter != null) {
            ((ProgressNodeAdapter) adapter).refreshOperations();
            refreshListView();
        }
        favorite(nodesToFavorite, doFavorite, true);
    }

    @Subscribe
    public void onSyncCompleted(SyncContentScanEvent event) {
        if (adapter != null) {
            ((ProgressNodeAdapter) adapter).refreshOperations();
            refreshListView();
        }
    }

    @Subscribe
    public void onSyncNodeEvent(SyncNodeEvent event) {
        if (event.hasException) {
            return;
        }
        if (SyncContentManager.getInstance(getActivity()).canSync(SessionUtils.getAccount(getActivity()))) {
            SyncContentManager.getInstance(getActivity()).sync(SessionUtils.getAccount(getActivity()),
                    event.node.getIdentifier());
            ((ProgressNodeAdapter) adapter).refreshOperations();
        }
        refreshListView();
    }

    /**
     * This method is specific to favorite and is bind with NodeActions.
     * Multiple favorite action must be done sequentially and not in parallel.
     * It's not supported by the server for older version.
     */
    public void favorite(List<Node> selectedItems, boolean dofavorite, boolean update) {
        if (selectedItems == null || selectedItems.isEmpty()) {
            ((AlfrescoActivity) getActivity()).removeWaitingDialog();
            return;
        }
        nodesToFavorite = new ArrayList<Node>(selectedItems);
        doFavorite = dofavorite;
        Node node = nodesToFavorite.get(0);
        OperationBuilder requestBuilder = new FavoriteNodeRequest.Builder(parentFolder, node, doFavorite, true)
                .setNotificationVisibility(OperationRequest.VISIBILITY_DIALOG);
        Operator.with(getActivity(), SessionUtils.getAccount(getActivity())).load(requestBuilder);
        nodesToFavorite.remove(0);

        if (!update) {
            int titleId = R.string.unfavorite;
            int iconId = R.drawable.ic_unfavorite_dark;
            if (doFavorite) {
                titleId = R.string.favorite;
                iconId = R.drawable.ic_favorite_light;
            }
            OperationWaitingDialogFragment
                    .newInstance(FavoriteNodeRequest.TYPE_ID, iconId, getActivity().getString(titleId), null,
                            parentFolder, selectedItems.size(), false)
                    .show(getActivity().getSupportFragmentManager(), OperationWaitingDialogFragment.TAG);
        }
    }

    public void sync(List<Node> selectedItems, boolean doSync, boolean update) {
        if (selectedItems == null || selectedItems.isEmpty()) {
            ((AlfrescoActivity) getActivity()).removeWaitingDialog();
            return;
        }

        List<OperationBuilder> requestsBuilder = new ArrayList<>(selectedItems.size());
        for (Node node : selectedItems) {
            requestsBuilder.add(new SyncNodeRequest.Builder(parentFolder, node, doSync, true)
                    .setNotificationVisibility(OperationRequest.VISIBILITY_DIALOG));
        }
        String operationId = Operator.with(getActivity(), SessionUtils.getAccount(getActivity()))
                .load(requestsBuilder);

        if (!update) {
            int titleId = R.string.unsync;
            int iconId = R.drawable.ic_sync_light;
            if (doSync) {
                titleId = R.string.sync;
                iconId = R.drawable.ic_sync_light;
            }
            OperationWaitingDialogFragment
                    .newInstance(SyncNodeRequest.TYPE_ID, iconId, getActivity().getString(titleId), null,
                            parentFolder, selectedItems.size(), operationId)
                    .show(getActivity().getSupportFragmentManager(), OperationWaitingDialogFragment.TAG);
        }
    }

    // ///////////////////////////////////////////////////////////////////////////
    // BUILDER
    // ///////////////////////////////////////////////////////////////////////////
    public static Builder with(FragmentActivity appActivity) {
        return new Builder(appActivity);
    }

    public static class Builder extends ListingFragmentBuilder {
        // ///////////////////////////////////////////////////////////////////////////
        // CONSTRUCTORS
        // ///////////////////////////////////////////////////////////////////////////
        public Builder(FragmentActivity activity) {
            super(activity);
            this.extraConfiguration = new Bundle();
        }

        /** By Folder Object. */
        public Builder(FragmentActivity activity, Folder folder) {
            this(activity, folder, null, null, null);
        }

        /** By Folder PATH. */
        public Builder(FragmentActivity activity, String folderPath) {
            this(activity, null, folderPath, null, null);
        }

        /** By SITE Object. */
        public Builder(FragmentActivity activity, Site site) {
            this(activity, null, null, site, null);
        }

        /** By Folder Type ID. */
        public Builder(FragmentActivity activity, int folderId) {
            this(activity, null, null, null, folderId);
        }

        protected Builder(FragmentActivity activity, Folder parentFolder, String pathFolder, Site site,
                Integer folderId) {
            this(activity);
            BundleUtils.addIfNotEmpty(extraConfiguration, createBundleArgs(parentFolder, pathFolder, site));
            BundleUtils.addIfNotNull(extraConfiguration, ARGUMENT_FOLDER_TYPE_ID, folderId);
        }

        public Builder(FragmentActivity appActivity, Map<String, Object> configuration) {
            super(appActivity, configuration);
            viewConfigModel = new RepositoryConfigModel(configuration);
            this.extraConfiguration = new Bundle();
            if (configuration != null && configuration.containsKey(NodeBrowserTemplate.ARGUMENT_FOLDER_TYPE_ID)) {
                String folderTypeValue = JSONConverter.getString(configuration,
                        NodeBrowserTemplate.ARGUMENT_FOLDER_TYPE_ID);
                if (NodeBrowserTemplate.FOLDER_TYPE_SHARED.equalsIgnoreCase(folderTypeValue)) {
                    extraConfiguration.putSerializable(ARGUMENT_FOLDER_TYPE_ID, NodeChildrenRequest.FOLDER_SHARED);
                    shortcut(true);
                } else if (NodeBrowserTemplate.FOLDER_TYPE_USERHOME.equalsIgnoreCase(folderTypeValue)) {
                    extraConfiguration.putSerializable(ARGUMENT_FOLDER_TYPE_ID,
                            NodeChildrenRequest.FOLDER_USER_HOMES);
                    shortcut(true);
                }
            } else if (configuration != null
                    && ((configuration.containsKey(NodeBrowserTemplate.ARGUMENT_LABEL) && configuration.size() > 1)
                            || (!configuration.containsKey(NodeBrowserTemplate.ARGUMENT_LABEL)
                                    && configuration.size() > 0))) {
                shortcut(true);
            } else {
                shortcut(false);
            }

            this.templateArguments = new String[] { ARGUMENT_FOLDER_NODEREF, ARGUMENT_SITE_SHORTNAME, ARGUMENT_PATH,
                    ARGUMENT_FOLDER_TYPE_ID, ARGUMENT_FOLDER, ARGUMENT_SITE, ARGUMENT_IS_SHORTCUT };
        }

        // ///////////////////////////////////////////////////////////////////////////
        // SETTERS
        // ///////////////////////////////////////////////////////////////////////////
        public Builder folderIdentifier(String folderIdentifier) {
            extraConfiguration.putString(ARGUMENT_FOLDER_NODEREF, folderIdentifier);
            return this;
        }

        public Builder site(Site site) {
            extraConfiguration.putSerializable(ARGUMENT_SITE, site);
            return this;
        }

        public Builder siteShortName(String siteShortName) {
            extraConfiguration.putSerializable(ARGUMENT_SITE_SHORTNAME, siteShortName);
            return this;
        }

        public Builder folder(Folder folder) {
            extraConfiguration.putSerializable(ARGUMENT_FOLDER, folder);
            return this;
        }

        public Builder path(String pathFolder) {
            extraConfiguration.putSerializable(ARGUMENT_PATH, pathFolder);
            return this;
        }

        public Builder shortcut(boolean isShortCut) {
            extraConfiguration.putSerializable(ARGUMENT_IS_SHORTCUT, isShortCut);
            return this;
        }

        // ///////////////////////////////////////////////////////////////////////////
        // CLICK
        // ///////////////////////////////////////////////////////////////////////////
        protected Fragment createFragment(Bundle b) {
            return newInstanceByTemplate(b);
        }
    }
}