text:
package com.evolveum.midpoint.eclipse.ui.menus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.services.IServiceLocator;

import com.evolveum.midpoint.eclipse.ui.PluginConstants;
import com.evolveum.midpoint.eclipse.ui.handlers.ServerLogHandler;
import com.evolveum.midpoint.eclipse.ui.handlers.server.DownloadHandler;
import com.evolveum.midpoint.eclipse.ui.handlers.server.ServerRequestPack;
import com.evolveum.midpoint.eclipse.ui.handlers.sources.SelectionUtils;
import com.evolveum.midpoint.eclipse.ui.prefs.PluginPreferences;
import com.evolveum.midpoint.eclipse.ui.prefs.ServerInfo;

public class MenuUtil {

	public static void addUploadOrExecuteWithoutAction(List<IContributionItem> items, IServiceLocator serviceLocator) {
		CommandContributionItem cci = new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_UPLOAD_OR_EXECUTE, null,
						null, null, null,
						"Upload/execute (no after-action)",
						null, null, CommandContributionItem.STYLE_PUSH, null, true));
		items.add(cci);
	}

	public static void addUploadOrExecuteWithAction(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_WITH_ACTION, "true");
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_UPLOAD_OR_EXECUTE, parameters,
						null, null, null,
						"&Upload/execute",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addUploadOrExecuteStopOnError(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_STOP_ON_ERROR, "true");
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_UPLOAD_OR_EXECUTE, parameters,
						null, null, null,
						"Upload/execute (stop on &error)",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addBrowse(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_BROWSE, null,
						null, null, null,
						"&Browse server objects",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addDownload(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, DownloadHandler.CMD_DOWNLOAD, null,
						null, null, null,
						"&Bulk download of predefined objects",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addReloadFromServer(List<IContributionItem> items, IServiceLocator serviceLocator) {
		List<IFile> files = SelectionUtils.getSelectedXmlFiles(SelectionUtils.getWorkbenchSelection());
		if ((files == null || files.size() == 0) ) {
			return;
		}
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_RELOAD_FROM_SERVER, null,
						null, null, null,
						"&Reload objects from server",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addComputeDifferences(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_COMPUTE_DIFFERENCE, null,
						null, null, null,
						"Compute &differences",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

//	public static void addEnableOnServer(List<IContributionItem> items, IServiceLocator serviceLocator) {
//		items.add(new CommandContributionItem(
//				new CommandContributionItemParameter(
//						serviceLocator, null, PluginConstants.CMD_ENABLE_ON_SERVER, null,
//						null, null, null,
//						"Enable",
//						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
//	}
//
//	public static void addDisableOnServer(List<IContributionItem> items, IServiceLocator serviceLocator) {
//		items.add(new CommandContributionItem(
//				new CommandContributionItemParameter(
//						serviceLocator, null, PluginConstants.CMD_DISABLE_ON_SERVER, null,
//						null, null, null,
//						"Disable",
//						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
//	}

	public static void addDeleteOnServerRaw(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_RAW, "true");
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_DELETE_ON_SERVER, parameters,
						null, null, null,
						"Delete (raw)",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addDeleteOnServerNonRaw(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_DELETE_ON_SERVER, null,
						null, null, null,
						"Delete (non-raw)",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addDeleteOnServerRawAndLocally(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_RAW, "true");
		parameters.put(PluginConstants.PARAM_ALSO_LOCALLY, "true");
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_DELETE_ON_SERVER, parameters,
						null, null, null,
						"Delete on server (raw) and locally",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addRecomputeOnServer(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_RECOMPUTE_ON_SERVER, parameters,
						null, null, null,
						"Recompute",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addRecomputeOnServerWithUpload(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_UPLOAD_FIRST, "true");
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_RECOMPUTE_ON_SERVER, parameters,
						null, null, null,
						"Upload and recompute",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addTestResourceOnServer(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_TEST_RESOURCE, null,
						null, null, null,
						"Test resource",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addTestResourceOnServerWithUpload(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_UPLOAD_FIRST, "true");
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_TEST_RESOURCE, parameters,
						null, null, null,
						"Upload and test resource",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addTestAndValidateResourceOnServerWithUpload(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_UPLOAD_FIRST, "true");
		parameters.put(PluginConstants.PARAM_VALIDATE, "true");
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_TEST_RESOURCE, parameters,
						null, null, null,
						"Upload, test and validate resource",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addServerNameLabel(List<IContributionItem> items, IServiceLocator serviceLocator) {
		String serverName = PluginPreferences.getSelectedServerName();
		if (serverName == null) {
			serverName = "(none)";
		}
		MenuManager dummy = new MenuManager("Selected midPoint server: " + serverName);
		int index = 0;
		for (ServerInfo serverInfo : PluginPreferences.getServers()) {
			Map<String,String> parameters = new HashMap<>();
			parameters.put(PluginConstants.PARAM_SERVER_NUMBER, String.valueOf(index++));
			dummy.add(new CommandContributionItem(
					new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SELECT_SERVER, parameters,
						null, null, null,
						"Select server " + serverInfo.getDisplayName() + (serverInfo.isSelected() ? " (selected)" : ""),
						null, null, CommandContributionItem.STYLE_PUSH, null, false)) {
							@Override
							public boolean isEnabled() {
								return !serverInfo.isSelected();
							}
			});
		}
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_SERVER_NUMBER, "");
		dummy.add(new CommandContributionItem(
				new CommandContributionItemParameter(
					serviceLocator, null, PluginConstants.CMD_SELECT_SERVER, null,
					null, null, null,
					"Select none",
					null, null, CommandContributionItem.STYLE_PUSH, null, true)));
		items.add(dummy);
	}

	public static void addTransferMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		String serverName = PluginPreferences.getSelectedServerName();
		if (serverName == null) {
			return;
		}
		MenuManager dummy = new MenuManager("Transfer-related actions");
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addUploadOrExecuteWithAction(dummyItems, serviceLocator);
		MenuUtil.addUploadOrExecuteWithoutAction(dummyItems, serviceLocator);
		MenuUtil.addUploadOrExecuteStopOnError(dummyItems, serviceLocator);
		MenuUtil.addComputeDifferences(dummyItems, serviceLocator);
		MenuUtil.addReloadFromServer(dummyItems, serviceLocator);
		MenuUtil.addDownload(dummyItems, serviceLocator);
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addSetAsActionMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		MenuManager dummy = new MenuManager("Set as action");
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addSetAsAction(dummyItems, serviceLocator, 1);
		MenuUtil.addSetAsAction(dummyItems, serviceLocator, 2);
		MenuUtil.addSetAsAction(dummyItems, serviceLocator, 3);
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addServerSideMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		String serverName = PluginPreferences.getSelectedServerName();
		if (serverName == null) {
			return;
		}
		MenuManager dummy = new MenuManager("&Server-side actions");
		List<IContributionItem> dummyItems = new ArrayList<>();
//		MenuUtil.addEnableOnServer(dummyItems, serviceLocator);
//		MenuUtil.addDisableOnServer(dummyItems, serviceLocator);
		//MenuUtil.addRecomputeOnServer(dummyItems, serviceLocator);
		MenuUtil.addRecomputeOnServerWithUpload(dummyItems, serviceLocator);
		//MenuUtil.addTestResourceOnServer(dummyItems, serviceLocator);
		MenuUtil.addTestResourceOnServerWithUpload(dummyItems, serviceLocator);
		MenuUtil.addTestAndValidateResourceOnServerWithUpload(dummyItems, serviceLocator);
		MenuUtil.addDeleteOnServerRaw(dummyItems, serviceLocator);
		MenuUtil.addDeleteOnServerNonRaw(dummyItems, serviceLocator);
		MenuUtil.addDeleteOnServerRawAndLocally(dummyItems, serviceLocator);
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addMiscMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		MenuManager dummy = new MenuManager("&Miscellaneous");
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addGenerateOid(dummyItems, serviceLocator);
		MenuUtil.addAnalyzePrismStructure(dummyItems, serviceLocator);
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addGenerateOid(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_GENERATE_OID, null,
						null, null, null,
						"Generate random &OID",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addAnalyzePrismStructure(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_ANALYZE_PRISM_STRUCTURE, null,
						null, null, null,
						"&Analyze prism structure",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addExecuteAction(List<IContributionItem> items, IServiceLocator serviceLocator, int actionNumber) {
		if (StringUtils.isNotBlank(PluginPreferences.getActionFile(actionNumber))) {
			Map<String,String> parameters = new HashMap<>();
			parameters.put(PluginConstants.PARAM_ACTION_NUMBER, String.valueOf(actionNumber));
			items.add(new CommandContributionItem(
					new CommandContributionItemParameter(
							serviceLocator, null, PluginConstants.CMD_EXECUTE_ACTION, parameters,
							null, null, null,
							"Execute predefined action " + actionNumber,
							null, null, CommandContributionItem.STYLE_PUSH, null, true)));
		}
	}

	public static void addTestConnections(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_TEST_CONNECTIONS, null,
						null, null, null,
						"&Test connections to servers",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addShowConsole(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_CONSOLE, null,
						null, null, null,
						"Show plugin &console",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addEditPreferences(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_EDIT_PREFERENCES, null,
						null, null, null,
						"&Preferences...",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addSetAsAction(List<IContributionItem> items, IServiceLocator serviceLocator, int number) {
		List<IFile> files = SelectionUtils.getSelectedXmlFiles(SelectionUtils.getWorkbenchSelection());
		if (files == null || files.size() != 1) {
			return;
		}

		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_ACTION_NUMBER, String.valueOf(number));
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SET_AS_ACTION, parameters,
						null, null, null,
						"Set as action &" + number,
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addServerLogMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		if (!PluginPreferences.isServerSelected()) {
			return;
		}

		MenuManager dummy = new MenuManager("Server &log");
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addShowLogInConsoleMenu(dummyItems, serviceLocator);
		MenuUtil.addShowLogInViewerMenu(dummyItems, serviceLocator);
		MenuUtil.addMarkCurrentPosition(dummyItems, serviceLocator);
		MenuUtil.addClearServerLog(dummyItems, serviceLocator);
		dummyItems.add(new Separator());
		MenuUtil.addModelLogMenu(dummyItems, serviceLocator);
		MenuUtil.addOtherLogMenu(dummyItems, serviceLocator, PluginConstants.VALUE_PROVISIONING, "Set Provisioning logging");
		MenuUtil.addOtherLogMenu(dummyItems, serviceLocator, PluginConstants.VALUE_REPOSITORY, "Set Repository logging");
		MenuUtil.addOtherLogMenu(dummyItems, serviceLocator, PluginConstants.VALUE_GUI, "Set GUI logging");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_ALL, PluginConstants.VALUE_INFO, "Set all of these to INFO");
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addModelLogMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		MenuManager dummy = new MenuManager("Set Model logging");
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_INFO, "Set to INFO");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_CLOCKWORK_SUMMARY, "Set to 'clockwork summary' (Clockwork=DEBUG)");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_PROJECTOR_SUMMARY, "Set to 'projector summary' (previous + Projector=TRACE)");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_MAPPING_TRACE, "Set to 'mapping trace' (previous + Mapping=TRACE)");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_EXPRESSION_TRACE, "Set to 'expression trace' (previous + Expression=TRACE)");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_PROJECTOR_TRACE, "Set to 'projector trace' (previous + projector.*=TRACE)");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_LENS_TRACE, "Set to 'lens trace' (previous + lens.*=TRACE)");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_DEBUG, "Set to DEBUG (whole module)");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, PluginConstants.VALUE_MODEL, PluginConstants.VALUE_TRACE, "Set to TRACE (whole module)");
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addOtherLogMenu(List<IContributionItem> items, IServiceLocator serviceLocator, String module, String label) {
		MenuManager dummy = new MenuManager(label);
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addLogEntry(dummyItems, serviceLocator, module, PluginConstants.VALUE_INFO, "Set to INFO");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, module, PluginConstants.VALUE_DEBUG, "Set to DEBUG");
		MenuUtil.addLogEntry(dummyItems, serviceLocator, module, PluginConstants.VALUE_TRACE, "Set to TRACE");
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addLogEntry(List<IContributionItem> items, IServiceLocator serviceLocator, String component, String level, String label) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_COMPONENT, component);
		parameters.put(PluginConstants.PARAM_LEVEL, level);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SET_LOG_LEVEL, parameters,
						null, null, null,
						label,
						null, null, CommandContributionItem.STYLE_PUSH, null, false)));
	}

	public static void addShowLogInConsoleMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		MenuManager dummy = new MenuManager("Show log in &console");
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addShowLogInConsoleFromStart(dummyItems, serviceLocator);
		MenuUtil.addShowLogInConsoleBackN(dummyItems, serviceLocator);
		MenuUtil.addShowLogInConsoleFromMark(dummyItems, serviceLocator);
		MenuUtil.addShowLogInConsoleFromNow(dummyItems, serviceLocator);
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addShowLogInViewerMenu(List<IContributionItem> items, IServiceLocator serviceLocator) {
		MenuManager dummy = new MenuManager("Show log in &viewer");
		List<IContributionItem> dummyItems = new ArrayList<>();
		MenuUtil.addShowLogInViewerFromStart(dummyItems, serviceLocator);
		MenuUtil.addShowLogInViewerBackN(dummyItems, serviceLocator);
		MenuUtil.addShowLogInViewerFromMark(dummyItems, serviceLocator);
		MenuUtil.addShowLogInViewerFromConsole(dummyItems, serviceLocator);
		for (IContributionItem item : dummyItems) {
			dummy.add(item);
		}
		items.add(dummy);
	}

	public static void addMarkCurrentPosition(List<IContributionItem> items, IServiceLocator serviceLocator) {
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_MARK_CURRENT_LOG_POSITION, null,
						null, null, null,
						"&Mark current log position",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addShowLogInConsoleFromStart(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_START);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_CONSOLE, parameters,
						null, null, null,
						"Show &whole log",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addShowLogInConsoleBackN(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_BACK_N);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_CONSOLE, parameters,
						null, null, null,
						"Show &last " + PluginPreferences.getLogGoBackN() + " KB",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addShowLogInConsoleFromMark(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_MARK);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_CONSOLE, parameters,
						null, null, null,
						"Show from &mark",
						null, null, CommandContributionItem.STYLE_PUSH, null, false)) {
			@Override
			public boolean isEnabled() {
				return ServerLogHandler.getCurrentMark() != null;
			}
		});
	}

	public static void addShowLogInConsoleFromNow(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_NOW);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_CONSOLE, parameters,
						null, null, null,
						"Show from &now",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addShowLogInViewerFromStart(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_START);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_EDITOR, parameters,
						null, null, null,
						"Show &whole log",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addShowLogInViewerBackN(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_BACK_N);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_EDITOR, parameters,
						null, null, null,
						"Show &last " + PluginPreferences.getLogGoBackN() + " KB",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addShowLogInViewerFromMark(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_MARK);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_EDITOR, parameters,
						null, null, null,
						"Show from &mark",
						null, null, CommandContributionItem.STYLE_PUSH, null, false)) {
							@Override
							public boolean isEnabled() {
								return ServerLogHandler.getCurrentMark() != null;
							}
		});
	}

	public static void addShowLogInViewerFromConsole(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		parameters.put(PluginConstants.PARAM_FROM, PluginConstants.VALUE_CONSOLE);
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_SHOW_LOG_IN_EDITOR, parameters,
						null, null, null,
						"Copy from &console",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

	public static void addClearServerLog(List<IContributionItem> items, IServiceLocator serviceLocator) {
		Map<String,String> parameters = new HashMap<>();
		items.add(new CommandContributionItem(
				new CommandContributionItemParameter(
						serviceLocator, null, PluginConstants.CMD_CLEAR_SERVER_LOG, parameters,
						null, null, null,
						"Cl&ear server log",
						null, null, CommandContributionItem.STYLE_PUSH, null, true)));
	}

}


text:
package com.hubspot.dropwizard.guice;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.hubspot.dropwizard.guice.objects.ExplicitResource;
import com.hubspot.dropwizard.guice.objects.JitResource;
import com.hubspot.dropwizard.guice.objects.TestModule;
import com.squarespace.jersey2.guice.BootstrapUtils;
import org.glassfish.hk2.api.ServiceLocator;
import org.junit.AfterClass;
import org.junit.Test;

import javax.servlet.ServletException;

import static org.assertj.core.api.Assertions.assertThat;

public class HK2LinkerTest {

    final Injector injector = Guice.createInjector(new JerseyModule(), new TestModule());
    final ServiceLocator serviceLocator = injector.getInstance(ServiceLocator.class);

    @AfterClass
    public static void tearDown() {
        BootstrapUtils.reset();
    }

    @Test
    public void explicitGuiceBindingsAreBridgedToHk2() throws ServletException {
        // when
        ExplicitResource resource = serviceLocator.createAndInitialize(ExplicitResource.class);

        // then
        assertThat(resource).isNotNull();
        assertThat(resource.getDAO()).isNotNull();
    }

    @Test
    public void jitGuiceBindingsAreBridgedToHk2() throws ServletException {
        // when
        JitResource resource = serviceLocator.createAndInitialize(JitResource.class);

        // then
        assertThat(resource).isNotNull();
        assertThat(resource.getDAO()).isNotNull();
    }
}

redpajama_set_name: RedPajamaGithub


text:
<?php

declare(strict_types=1);

namespace OlajosCs\Nestable\Elements;

/**
 * Class AbstractNestableElement
 *
 * Basic implementation of the NestableElement, which is needed in the NestableGenerator class
 */
abstract class AbstractNestableElement implements NestableElement
{
    /**
     * @var int
     */
    protected $id;

    /**
     * @var string
     */
    protected $content;

    /**
     * @var int|null
     */
    protected $parentId;

    /**
     * @var int
     */
    protected $index;

    /**
     * @var NestableElement[]
     */
    protected $children = [];

    /**
     * Create a new Nestable element from the basic element
     *
     * @param Element $element
     *
     * @return NestableElement
     */
    public static function create(Element $element): NestableElement
    {
        $nestableElement = new static();

        $nestableElement->id = $element->getId();
        $nestableElement->content = $element->getName();
        $nestableElement->parentId = $element->getParentId();
        $nestableElement->index = $element->getIndex();

        return $nestableElement;
    }

    /**
     * Specify data which should be serialized to JSON
     *
     * @return mixed Data which can be serialized by <b>json_encode</b>,
     */
    public function jsonSerialize()
    {
        $return = [
            'id'      => $this->getId(),
            'content' => $this->getContent(),
        ];

        if (!empty($this->children)) {
            $return += ['children' => $this->getChildren()];
        }

        return $return;
    }

    /**
     * Return the ID of the element
     *
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * Return the content of the element.
     * This will be showed on the labels.
     *
     * @return string
     */
    public function getContent(): string
    {
        return $this->content;
    }

    /**
     * Return the parent ID of the element
     *
     * @return int
     */
    public function getParentId(): ?int
    {
        return $this->parentId;
    }

    /**
     * Return the children of the element
     *
     * @return NestableElement[]
     */
    public function getChildren(): array
    {
        return $this->children;
    }

    /**
     * Set the children of the element
     *
     * @param NestableElement[] $children
     *
     * @return NestableElement
     */
    public function setChildren(array $children): NestableElement
    {
        $this->children = $children;

        return $this;
    }

    /**
     * Add a child to the children list
     *
     * @param NestableElement $element
     *
     * @return NestableElement
     */
    public function addChild(NestableElement $element): NestableElement
    {
        $this->children[] = $element;

        return $this;
    }

    /**
     * Return the index of the element on the given level
     *
     * @return int
     */
    public function getIndex(): int
    {
        return $this->index;
    }

    /**
     * Set the index of the element on the given level
     *
     * @param int $index
     *
     * @return NestableElement
     */
    public function setIndex(int $index): NestableElement
    {
        $this->index = $index;

        return $this;
    }
}


text:
using JonasPluginBase;
using Microsoft.Xrm.Sdk;
using System;

namespace eXtremePlugins
{
    public class NoFaxPlease : JonasPluginBase.JonasPluginBase
    {
        public override void Execute(JonasPluginBag bag)
        {
            // Read updated value for Fax from Target entity
            string fax = bag.TargetEntity.GetAttributeValue<string>("fax");

            if (!string.IsNullOrWhiteSpace(fax))
            {
                throw new InvalidPluginExecutionException($"Fax? Really? This is {DateTime.Now.Year}, you know... ");
            }

            // Get name of the record that triggered the plugin
            string recordName = bag.CompleteEntity.Name(bag, false);
            bag.Trace("No fax for {0}, this {1} is ready for the future.", recordName, bag.PluginContext.PrimaryEntityName);
        }
    }
}


text:
using BusinessServiceInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BusinessServiceModule
{
	class BusinessService : IBusinessService
	{
		public List<string> GetAllNames()
		{
			List<string> names = new List<string>();
			names.Add("Me");
			names.Add("Myself");
			names.Add("George");

			return names;
		}
	}
}


text:
from __future__ import print_function
import os
import sys
import time
import signal
import itertools
import subprocess

from commandsession import CommandError, CommandSession, ParamDict

from hobo.util import is_rh_family, Timeout, timeout, tempname, Config
from hobo.net import mac_in_arp_cache, populate_arp_cache, get_hostname
from hobo.libvirt import Libvirt, Libguestfs

config = Config()

class Hobo(object):
    """
    TODO:
        - refactor
        - better exception handling, and cleanup of templates
        - add vms to known_hosts
        - inject environment vars to debug libguestf (commandsession)
    """
    images_dir = config.images_dir
    template_file = config.template_file
    db = config.db

    def __init__(self, session=None):
        self.session = session or CommandSession()
        self.libvirt = Libvirt(
            config.bridge_device,
            images_dir=self.images_dir,
            session=self.session
        )
        self.libgf = Libguestfs(
            template_file=self.template_file,
            libvirt=self.libvirt,
        )

        self._check_template_file()

    def base(self, image_name, image_desc, base_os, upload=None, install=None, run=None, size=None, compress=True):
        """Generate a base os image built upon another base image.
        """

        if image_desc is None:
            image_desc = image_name

        if self.libgf.template_available(image_name):
            raise ValueError('Template for base image {} exists.'.format(image_name))

        if self.libvirt.disk_exists(image_name):
            raise ValueError('Disk for base image {} exists.'.format(image_name))

        params = ParamDict()

        #if self.debug:
        #    params['root_password'] = '.hobo'

        if install: params['install'] = install

        if run:
            if not isinstance(run, list):
                run = [run]
            for item in run:
                assert os.path.exists(item)
                params.add('run', item)

        if upload:
            if not isinstance(upload, list):
                upload = [upload]
            for item in upload:
                params.add('upload', item)

        if size: params['size'] = size

        #TODO: add a keypair for root
        #params.add('run_command', 'cat /dev/zero | ssh-keygen -q -N ""')

        try:
            print('Building image')
            self.libgf.virt_build(
                image_name,
                base_os,
                # required for RHEL after messing around with authorized keys
                # might be able to use restorecon instead, in a run_command
                'selinux_relabel',
                **params
            )
        except (Exception, KeyboardInterrupt) as ex:
            try:
                self.libvirt.delete_disk(image_name)
            except: pass
            print(ex)
        else:

            try:

                print('Creating sparse image')
                self.libgf.virt_sparsify(self.libvirt.disk_path(image_name))

                image_path = self.libvirt.disk_path(image_name)
                print('Running sysprep')
                self.libgf.virt_sysprep_img(
                    ['udev-persistent-net'], image_name
                )

                image_sz = os.stat(os.path.join(image_path)).st_size
                ## compress the image?
                compressed_size = None
                if compress:
                    print('Compressing using {}'.format(config.compress_flags))
                    print('Warning: this can take a long time.')
                    _stream = self.session._stream
                    self.session._stream = True
                    self.session.call("xz {} {}".format(config.compress_flags, image_path))
                    self.session._stream = _stream
                    image_path = self.libvirt.disk_path(image_name) + '.xz'
                    compressed_size = os.stat(os.path.join(image_path)).st_size

                # manually remove this template from the cache, it is flaky
                self.libgf.delete_cache(image_name)

                # get arch of base os to populate arch of our new image
                arch = self.libgf.get_arch(base_os)

                self.libgf.generate_template(
                    image_name,
                    image_desc,
                    arch,
                    image_sz,
                    self.template_file,
                    csz=compressed_size
                )
            #except CommandError as ex:
            #    print(ex)
            #    raise
            except (Exception, KeyboardInterrupt) as ex:
                print(ex)
                # remove the image we created
                try:
                    #FIXME - sometimes this doesnt work
                    print('Cleanup after error')
                    self.session.call('rm -f {}'.format(self.libvirt.disk_path(image_name)))
                except: pass
                raise

            print('Done building image')
            return True

    def build(self, base_os, name, hostname=None, size=None, ram=None, cpus=None, tags=None):
        """clone a base image
        TODO: the image for this clone should not go into the images dir, it should
        instead go into the current dirextory, or somewhere else.
        TODO: if size is not provided, get size somehow to store in db
        TODO: need to add users pubkey to auth keys automatically
        TODO: need to add a github privkey to the root account in v

        note - resize will fail if size given is less than current size.  issue?
        """

        params = ParamDict()

        #params['root_password'] = 'password:.hobo'

        if size:
            print((
                'Note: providing custom size requires virt-resize and virt-sparsify, '
                'so this may take some time.'
            ))
            params['size'] = size

        # inject user's pubkey
        pubkey = os.path.join(os.path.expanduser('~'), '.ssh', 'id_rsa.pub')
        assert os.path.exists(pubkey)
        #FIXME only supported on libguestfs >= 1.29
        #params['ssh_inject'] = 'root:file:{}'.format(pubkey)
        params.add('mkdir', '/root/.ssh')
        #FIXME: this will overwrite any existing authorized keys
        params.add('upload', "{}:/root/.ssh/authorized_keys".format(pubkey))
        params.add('run_command', "chmod 0700 /root/.ssh")
        params.add('run_command', "chmod 0600 /root/.ssh/authorized_keys")
        params.add('run_command', "chown root:root /root/.ssh/authorized_keys")
        params.add('run_command', "restorecon -FRvv /root/.ssh")

        bridge = config.bridge_device
        ram = ram or config.base_mem
        cpus = cpus or config.base_cpu
        hostname = hostname or '{}.local'.format(name)

        print('Importing image for {}'.format(name))
        self.libgf.virt_build(
            name,
            base_os,
            'selinux-relabel',
            hostname=hostname,
            **params
        )

        try:
            if size:
                print('Creating sparse image')
                self.libgf.virt_sparsify(self.libvirt.disk_path(name))

            print('Creating domain')
            self.libgf.virt_import(
                name,
                name,
                bridge=bridge,
                ram=ram,
                vcpus=cpus
            )

            try:
                self.libvirt.get_domain(name)
            except ValueError:
                print('domain was not created!')
                raise

        except (Exception, KeyboardInterrupt):
            self.libvirt.delete_disk(name)
            raise

        else:
            if tags and not isinstance(tags, list):
                tags = [tags]
            elif not tags:
                tags = []

            self.db.write(
                'domains',
                name,
                {
                    'user': 'root',
                    'hostname': hostname,
                    'disk_size': size,
                    'bridge_iface': bridge,
                    'memory': ram,
                    'cpus': cpus,
                    'tags': tags
                }
            )

        return True

    def package(self, domain_name, image_name, image_desc, install=False, compress=True):
        """Grab a domain's disk and package it.
        #TODO: this disk abstraxtion needs a fixup.
        """

        if self.libgf.template_available(image_name):
            raise ValueError('Template for base image {} exists.'.format(image_name))

        if self.libvirt.disk_exists(image_name):
            raise ValueError('Disk for base image {} exists.'.format(image_name))

        dom = self.libvirt.get_domain(domain_name)

        if not dom.stopped:
            print('Error: cannot package a domain that is running')
            return False

        dest = self.libvirt.disk_path(image_name)

        print('Copying disk')
        self.session.check_call([
            'cp', '--preserve=all',
            self.libvirt.disk_path(domain_name),
            dest
        ])

        try:
            print('Creating sparse image')
            self.libgf.virt_sparsify(dest)

            print('Running sysprep')
            sysprep_ops = [
                'bash_history',
                'udev-persistent-net',
                'logfiles',
                'machine-id',
                'net-hostname',
                'package-manager-cache',
                'ssh-hostkeys',
                #'ssh-userdir',  # req'd for ansible.key
                'tmp-files',
                'utmp',
            ]
            #self.libgf.virt_sysprep_img(
            #    sysprep_ops, image_name
            #)
            image_path = self.libvirt.disk_path(image_name)
            image_sz = os.stat(os.path.join(image_path)).st_size
            compressed_size = None
            if compress:
                print('Compressing using {}'.format(config.compress_flags))
                print('Warning: this can take a long time.')
                _stream = self.session._stream
                self.session._stream = True
                self.session.call("xz {} {}".format(config.compress_flags, image_path))
                self.session._stream = _stream
                image_path = self.libvirt.disk_path(image_name) + '.xz'
                compressed_size = os.stat(os.path.join(image_path)).st_size

            # manually remove this template from the cache, it is flaky
            self.libgf.delete_cache(image_name)

            # get arch of base os to populate arch of our new image
            #FIXME
            arch = 'x86_64'
            #arch = self.libgf.get_arch(base_os)

            if install:
                self.libgf.generate_template(
                    image_name,
                    image_desc,
                    arch,
                    image_sz,
                    self.template_file,
                    csz=compressed_size
                )
            else:

                templ = self.libgf.get_template(
                    image_name,
                    image_desc,
                    arch,
                    image_sz,
                    self.template_file,
                    csz=compressed_size
                )
                print(templ)

        except (Exception, KeyboardInterrupt) as ex:

            print(ex)
            self.session.call(['rm', '-f', dest])
            return False

        return True

    def info(self, domain=None, format=None):
        """Print some info about a domain"""
        if not self.db.read('domains'):
            return False

        if domain:
            assert domain in self.db.read('domains').keys()
            domains = [domain]
        else:
            domains = self.db.read('domains').keys()

        records = {}
        for item in domains:
            try:
                domain_obj = self.libvirt.get_domain(item)
            except CommandError:
                #FIXME - the database is out of sync with what exists in system
                continue
            state = domain_obj.state
            if not domain_obj.ip_address and state=='running':
                state = 'booting'

            info = self.db.read('domains', item)
            info.update({
                'mac': domain_obj.mac_address,
                'ip': domain_obj.ip_address if state=='running' else '',  # if not running, it may not still have cached ip
                'state': state
            })
            records[item] = info

        if not format:
            for k, v in records.items():
                print('{}: {}'.format(k, v))

        elif format == 'ansible':
            # generate a hosts file
            #MAYBE use inventory script
            def ansible_host(record):
                args = [record['hostname']]
                if record['user']: args.append('ansible_ssh_user={}'.format(record['user']))
                if record['ip']: args.append('ansible_ssh_host={}'.format(record['ip']))
                return ' '.join(args)

            running = [d for d in records.keys() if records[d]['state'] == 'running']
            for dom in running:
                rec = records[dom]
                print(ansible_host(rec))

            if len(running): print()

            tags = list(set(itertools.chain(*[t['tags'] for t in records.values()])))
            for tag in tags:
                matches = [k for k in records.keys() if tag in records[k]['tags'] and k in running]
                if len(matches):
                    print('[{}]'.format(tag))
                for dom in matches:
                    print(ansible_host(records[dom]))
                if len(matches):
                    print()

        return True

    def destroy(self, domain=None):
        """Remove a domain fro the system completely.
        :returns: False if all calls have failed, else True
        """
        if not self.db.read('domains'):
            print('No domains exist')
            return False

        if domain:
            assert domain in self.db.read('domains').keys()
            domains = [domain]
        else:
            domains = self.db.read('domains').keys()

        for domain in domains:
            try:
                self.session.call(
                    'virsh shutdown {}'.format(domain)
                )
                self.session.call(
                    'virsh destroy {}'.format(domain)
                )
                self.session.call(
                    'virsh undefine {}'.format(domain)
                )
                #FIXME
                self.session.call('rm -f /home/mike/hobo/images/{}.qcow2'.format(domain))
            except CommandError: pass
            finally:
                self.db.delete('domains', domain)

        print('{} deleted.'.format(domains))

        return True

    def _check_template_file(self):
        """Verify that template file is present, configured, and is well-formed."""
        #TODO: this is an install task, belongs in Makefile
        if not os.path.exists('/etc/virt-builder/repos.d/hobo.conf'):
            with open('/etc/virt-builder/repos.d/hobo.conf', 'w') as fh:
                fh.write('[hobo]\n')
                fh.write('uri=file:///{}\n'.format(
                    os.path.abspath(self.template_file)
                ))
                fh.write('proxy=off\n')

        # virt-builder will raise an error if existing template
        # file is not valid, but it will return a success error code,
        # which will allow this function to continue but eventually fail.
        if not self.libgf.check_template_file():
            raise RuntimeError('Base template file {}'.format(self.template_file))


text:
Clazz.declarePackage ("JM");
Clazz.load (["JM.ProteinStructure"], "JM.Helix", ["JU.Measure", "$.P3", "$.V3", "J.c.STR"], function () {
c$ = Clazz.declareType (JM, "Helix", JM.ProteinStructure);
Clazz.makeConstructor (c$,
function (apolymer, monomerIndex, monomerCount, subtype) {
Clazz.superConstructor (this, JM.Helix, []);
this.setupPS (apolymer, J.c.STR.HELIX, monomerIndex, monomerCount);
this.subtype = subtype;
}, "JM.AlphaPolymer,~N,~N,J.c.STR");
Clazz.overrideMethod (c$, "calcAxis",
function () {
if (this.axisA != null) return;
var points =  new Array (this.nRes + 1);
for (var i = 0; i <= this.nRes; i++) this.apolymer.getLeadMidPoint (this.monomerIndexFirst + i, points[i] =  new JU.P3 ());

this.axisA =  new JU.P3 ();
this.axisUnitVector =  new JU.V3 ();
JU.Measure.calcBestAxisThroughPoints (points, this.axisA, this.axisUnitVector, this.vectorProjection, 4);
this.axisB = JU.P3.newP (points[this.nRes]);
JU.Measure.projectOntoAxis (this.axisB, this.axisA, this.axisUnitVector, this.vectorProjection);
});
});


text:
div:hover, div:focus, div:active {
background: red;
}
:selection {
  background-color: rgba(0,0,0,0.5);
}


text:
<?php

namespace morningtrain\Acl\Extensions;

use morningtrain\Acl\Models\Permission;
use morningtrain\Acl\Models\Role;
use morningtrain\Janitor\Services\Janitor;

trait Roleable
{
    use Permissionable;

    /*
     * Relationships
     */

    public function roles()
    {
        return $this->morphToMany(app()->make(Janitor::class)->getPublishedModelFor(Role::class), 'roleable');
    }

    /*
     * Scopes
     */

    public function scopeWhereIsSuper($query)
    {
        return $query->whereHas('roles', function ($query) {
            return $query->whereIsSuper();
        });
    }

    public function scopeWhereIsAssigned($query, array $roles)
    {
        foreach ($roles as $role) {
            $slug = $role instanceof Role ? $role->slug : $role;

            $query->whereHas('roles', function ($query) use ($slug) {
                $query->where('slug', $slug);
            });
        }

        return $query;
    }

    public function scopeWhereIsAssignedEither($query, array $roles)
    {
        return $query->where(function ($query) use ($roles) {
            foreach ($roles as $role) {
                $slug = $role instanceof Role ? $role->slug : $role;

                $query->orWhereHas('roles', function ($query) use ($slug) {
                    $query->where('slug', $slug);
                });
            }
        });
    }

    public function scopeWhereIsAllowed($query, $permission)
    {

        if ($permission instanceof Permission) {
            $permission = $permission->slug;
        }

        $permissionables = ['roles'];

        // Append new permissionables if set
        if (isset($this->permissionables) && is_array($this->permissionables)) {
            $permissionables = array_merge($permissionables, $this->permissionables);
        }

        return $query->where(function ($query) use ($permission, $permissionables) {

            // Check assigned permissions
            $query->whereHas('permissions', function ($query) use ($permission) {
                return $query->where('slug', $permission);
            });

            // Check permissionables
            foreach ($permissionables as $relation) {
                $query->orWhereHas($relation, function ($query) use ($permission) {
                    return $query->where('is_super', 1)->orWhereHas('permissions',
                        function ($query) use ($permission) {
                            $query->where('slug', $permission);
                        });
                });
            }

            return $query;

        });
    }

    public function scopeWhereHasAccess($query, $slug)
    {
        return $this->scopeWhereIsAllowed($query, "access.$slug");
    }

    /*
     * Helpers
     */

    public function allowed($permission)
    {
        return $this->newQuery()
            ->where('id', $this->id)
            ->whereIsAllowed($permission)
            ->count() > 0;
    }

    public function hasAccess($slug)
    {
        return $this->allowed("access.$slug");
    }

    public function isSuper()
    {
        return $this->roles()->whereIsSuper()->count() > 0;
    }

    public function assign(array $roles)
    {
        foreach ($roles as $role) {
            if (!$role instanceof Role) {
                $role = Role::where('slug', $role)->first();
            }

            if (!is_null($role) && ($this->roles()->where('id', $role->id)->count() === 0)) {
                $this->roles()->attach($role->id);
            }
        }
    }

    public function unassign(array $roles)
    {
        foreach ($roles as $role) {
            if (!$role instanceof Role) {
                $role = Role::where('slug', $role)->first();
            }

            if (!is_null($role)) {
                $this->roles()->detach($role->id);
            }
        }
    }

    public function isAssigned(array $roles)
    {
        return $this->newQuery()
            ->where('id', $this->id)
            ->whereIsAssigned($roles)
            ->count() > 0;
    }

    public function isAssignedEither(array $roles)
    {
        return $this->newQuery()
            ->where('id', $this->id)
            ->whereIsAssignedEither($roles)
            ->count() > 0;
    }

}