/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2005-2009 RSSOwl Development Team                                  **
 **   http://www.rssowl.org/                                                 **
 **                                                                          **
 **   All rights reserved                                                    **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the Eclipse Public License v1.0 which accompanies this    **
 **   distribution, and is available at:                                     **
 **   http://www.rssowl.org/legal/epl-v10.html                               **
 **                                                                          **
 **   A copy is found in the file epl-v10.html and important notices to the  **
 **   license from the team is found in the textfile LICENSE.txt distributed **
 **   in this package.                                                       **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Contributors:                                                          **
 **     RSSOwl Development Team - initial API and implementation             **
 **                                                                          **
 **  **********************************************************************  */

package org.rssowl.ui.internal.dialogs;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.rssowl.core.INewsAction;
import org.rssowl.core.Owl;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.IFilterAction;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.INews.State;
import org.rssowl.core.persist.ISearchCondition;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.ISearchFilter;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.ISearchFilterDAO;
import org.rssowl.core.persist.reference.NewsReference;
import org.rssowl.core.persist.service.IModelSearch;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.SearchHit;
import org.rssowl.core.util.StringUtils;
import org.rssowl.ui.internal.Activator;
import org.rssowl.ui.internal.ApplicationWorkbenchWindowAdvisor;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.filter.NewsActionDescriptor;
import org.rssowl.ui.internal.filter.NewsActionPresentationManager;
import org.rssowl.ui.internal.util.CColumnLayoutData;
import org.rssowl.ui.internal.util.CColumnLayoutData.Size;
import org.rssowl.ui.internal.util.CTable;
import org.rssowl.ui.internal.util.LayoutUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * A dialog to manage news filters in RSSOwl. The dialog allows to add, edit and
 * delete filters as well as moving them up or down to define an order of
 * filters to apply.
 *
 * @author bpasero
 */
public class NewsFiltersListDialog extends TitleAreaDialog {

  /* Number of News to process in a forced Filter run at once */
  private static final int FILTER_CHUNK_SIZE = 50;

  /* Keep the visible instance saved */
  private static NewsFiltersListDialog fgVisibleInstance;

  /* Section for Dialogs Settings */
  private static final String SETTINGS_SECTION = "org.rssowl.ui.internal.dialogs.NewsFiltersListDialog"; //$NON-NLS-1$

  private NewsActionPresentationManager fNewsActionPresentationManager = NewsActionPresentationManager.getInstance();
  private LocalResourceManager fResources;
  private CheckboxTableViewer fViewer;
  private Button fEditButton;
  private Button fDeleteButton;
  private Button fMoveDownButton;
  private Button fMoveUpButton;
  private Image fFilterIcon;
  private ISearchFilterDAO fSearchFilterDao;
  private Button fApplySelectedFilter;
  private ISearchFilter fSelectedFilter;

  /**
   * @param parentShell
   */
  public NewsFiltersListDialog(Shell parentShell) {
    super(parentShell);
    fResources = new LocalResourceManager(JFaceResources.getResources());
    fFilterIcon = OwlUI.getImage(fResources, OwlUI.FILTER);
    fSearchFilterDao = DynamicDAO.getDAO(ISearchFilterDAO.class);
  }

  /**
   * @return Returns an instance of NewsFiltersListDialog or
   * NULL in case no instance is currently open.
   */
  public static NewsFiltersListDialog getVisibleInstance() {
    return fgVisibleInstance;
  }

  /*
   * @see org.eclipse.jface.window.Window#open()
   */
  @Override
  public int open() {
    fgVisibleInstance = this;
    return super.open();
  }

  /*
   * @see org.eclipse.jface.dialogs.TrayDialog#close()
   */
  @Override
  public boolean close() {
    boolean res = super.close();
    fgVisibleInstance = null;
    fResources.dispose();
    return res;
  }

  /*
   * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
   */
  @Override
  protected Control createDialogArea(Composite parent) {

    /* Separator */
    new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

    /* Title */
    setTitle(Messages.NewsFiltersListDialog_NEWS_FILTERS);

    /* Title Image */
    setTitleImage(OwlUI.getImage(fResources, "icons/wizban/filter_wiz.png")); //$NON-NLS-1$

    /* Composite to hold all components */
    Composite composite = new Composite(parent, SWT.NONE);
    composite.setLayout(LayoutUtils.createGridLayout(2, 5, 10));
    composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    Composite tableContainer = new Composite(composite, SWT.NONE);
    tableContainer.setLayout(LayoutUtils.createGridLayout(1, 0, 0));
    tableContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    CTable cTable = new CTable(tableContainer, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);

    fViewer = new CheckboxTableViewer(cTable.getControl());
    fViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    fViewer.getTable().setHeaderVisible(true);
    ((GridData) fViewer.getTable().getLayoutData()).heightHint = fViewer.getTable().getItemHeight() * 15;
    fViewer.getTable().setData(ApplicationWorkbenchWindowAdvisor.FOCUSLESS_SCROLL_HOOK, new Object());

    TableColumn nameCol = new TableColumn(fViewer.getTable(), SWT.NONE);

    CColumnLayoutData data = new CColumnLayoutData(Size.FILL, 100);
    cTable.manageColumn(nameCol, data, Messages.NewsFiltersListDialog_NAME, null, null, false, false);

    /* ContentProvider returns all filters */
    fViewer.setContentProvider(new IStructuredContentProvider() {
      public Object[] getElements(Object inputElement) {
        return fSearchFilterDao.loadAll().toArray();
      }

      public void dispose() {}

      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
    });

    /* Label Provider */
    fViewer.setLabelProvider(new CellLabelProvider() {
      @Override
      public void update(ViewerCell cell) {
        ISearchFilter filter = (ISearchFilter) cell.getElement();
        Display display = fViewer.getControl().getDisplay();
        if (filter.isEnabled())
          cell.setText(filter.getName());
        else
          cell.setText(NLS.bind(Messages.NewsFiltersListDialog_FILTER_DISABLED, filter.getName()));
        cell.setImage(fFilterIcon);
        if (!OwlUI.isHighContrast())
          cell.setForeground(filter.isEnabled() ? display.getSystemColor(SWT.COLOR_BLACK) : display.getSystemColor(SWT.COLOR_DARK_GRAY));
      }
    });

    /* Sort */
    fViewer.setComparator(new ViewerComparator() {
      @Override
      public int compare(Viewer viewer, Object e1, Object e2) {
        ISearchFilter filter1 = (ISearchFilter) e1;
        ISearchFilter filter2 = (ISearchFilter) e2;

        return filter1.getOrder() < filter2.getOrder() ? -1 : 1;
      }
    });

    /* Selection */
    fViewer.addSelectionChangedListener(new ISelectionChangedListener() {
      public void selectionChanged(SelectionChangedEvent event) {
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
        fEditButton.setEnabled(!selection.isEmpty());
        fDeleteButton.setEnabled(!selection.isEmpty());
        fApplySelectedFilter.setEnabled(!selection.isEmpty() && selection.size() == 1);

        updateMoveEnablement();
      }
    });

    /* Doubleclick */
    fViewer.addDoubleClickListener(new IDoubleClickListener() {
      public void doubleClick(DoubleClickEvent event) {
        onEdit();
      }
    });

    /* Set input (ignored by ContentProvider anyways) */
    fViewer.setInput(this);
    updateCheckedState();

    /* Listen on Check State Changes */
    fViewer.addCheckStateListener(new ICheckStateListener() {
      public void checkStateChanged(CheckStateChangedEvent event) {
        ISearchFilter filter = (ISearchFilter) event.getElement();
        filter.setEnabled(event.getChecked());
        fSearchFilterDao.save(filter);
        fViewer.update(filter, null);
        updateTitle();
      }
    });

    /* Container for the Buttons to Manage Filters */
    Composite buttonContainer = new Composite(composite, SWT.None);
    buttonContainer.setLayout(LayoutUtils.createGridLayout(1, 0, 0));
    buttonContainer.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, false));

    /* Adds a new Filter */
    Button addButton = new Button(buttonContainer, SWT.PUSH);
    addButton.setText(Messages.NewsFiltersListDialog_NEW);
    addButton.setFocus();
    applyDialogFont(addButton);
    setButtonLayoutData(addButton);
    addButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onAdd();
      }
    });

    /* Edits a selected Filter */
    fEditButton = new Button(buttonContainer, SWT.PUSH);
    fEditButton.setText(Messages.NewsFiltersListDialog_EDIT);
    applyDialogFont(fEditButton);
    setButtonLayoutData(fEditButton);
    fEditButton.setEnabled(false);
    fEditButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onEdit();
      }
    });

    /* Deletes the selected Filter */
    fDeleteButton = new Button(buttonContainer, SWT.PUSH);
    fDeleteButton.setText(Messages.NewsFiltersListDialog_DELETE);
    applyDialogFont(fDeleteButton);
    setButtonLayoutData(fDeleteButton);
    fDeleteButton.setEnabled(false);
    fDeleteButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onDelete();
      }
    });

    /* Move Filter Up */
    fMoveUpButton = new Button(buttonContainer, SWT.PUSH);
    fMoveUpButton.setText(Messages.NewsFiltersListDialog_MOVE_UP);
    fMoveUpButton.setEnabled(false);
    applyDialogFont(fMoveUpButton);
    setButtonLayoutData(fMoveUpButton);
    ((GridData) fMoveUpButton.getLayoutData()).verticalIndent = 10;
    fMoveUpButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onMove(true);
      }
    });

    /* Move Filter Down */
    fMoveDownButton = new Button(buttonContainer, SWT.PUSH);
    fMoveDownButton.setText(Messages.NewsFiltersListDialog_MOVE_DOWN);
    fMoveDownButton.setEnabled(false);
    applyDialogFont(fMoveDownButton);
    setButtonLayoutData(fMoveDownButton);
    fMoveDownButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onMove(false);
      }
    });

    Composite buttonBar = new Composite(composite, SWT.NONE);
    buttonBar.setLayout(LayoutUtils.createGridLayout(2, 0, 0));
    buttonBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));

    /* Button to apply filter on all News */
    fApplySelectedFilter = new Button(buttonBar, SWT.PUSH);
    fApplySelectedFilter.setText(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER);
    fApplySelectedFilter.setEnabled(false);
    applyDialogFont(fApplySelectedFilter);
    setButtonLayoutData(fApplySelectedFilter);
    ((GridData) fApplySelectedFilter.getLayoutData()).grabExcessHorizontalSpace = false;
    ((GridData) fApplySelectedFilter.getLayoutData()).horizontalAlignment = SWT.BEGINNING;
    fApplySelectedFilter.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onApplySelectedFilter();
      }
    });

    /* Close */
    Button closeButton = new Button(buttonBar, SWT.PUSH);
    closeButton.setText(Messages.NewsFiltersListDialog_CLOSE);
    applyDialogFont(closeButton);
    setButtonLayoutData(closeButton);
    ((GridData) closeButton.getLayoutData()).grabExcessHorizontalSpace = true;
    ((GridData) closeButton.getLayoutData()).horizontalAlignment = SWT.END;
    closeButton.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        close();
      }
    });

    /* Update Title Message */
    updateTitle();

    /* Set Selection if provided */
    if (fSelectedFilter != null)
      fViewer.setSelection(new StructuredSelection(fSelectedFilter), true);

    applyDialogFont(composite);

    return composite;
  }

  private void onApplySelectedFilter() {
    IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
    if (!selection.isEmpty()) {
      ISearchFilter filter = (ISearchFilter) selection.getFirstElement();

      /* Retrieve those actions that are forcable to run */
      List<IFilterAction> actions = filter.getActions();
      List<IFilterAction> forcableActions = new ArrayList<IFilterAction>(actions.size());
      for (IFilterAction action : actions) {
        NewsActionDescriptor newsActionDescriptor = fNewsActionPresentationManager.getNewsActionDescriptor(action.getActionId());
        if (newsActionDescriptor != null && newsActionDescriptor.isForcable())
          forcableActions.add(action);
      }

      /* Return early if selected Action is not forcable */
      if (forcableActions.isEmpty()) {
        MessageDialog.openWarning(getShell(), NLS.bind(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_N, filter.getName()), NLS.bind(Messages.NewsFiltersListDialog_NO_ACTIONS_TO_RUN, filter.getName()));
        return;
      }

      IModelSearch search = Owl.getPersistenceService().getModelSearch();
      List<SearchHit<NewsReference>> targetNews = null;

      /* Search for all Visible News */
      Set<State> visibleStates = INews.State.getVisible();
      if (filter.getSearch() == null) {
        ISearchField stateField = Owl.getModelFactory().createSearchField(INews.STATE, INews.class.getName());
        ISearchCondition stateCondition = Owl.getModelFactory().createSearchCondition(stateField, SearchSpecifier.IS, EnumSet.of(State.NEW, State.UNREAD, State.UPDATED, State.READ));
        targetNews = search.searchNews(Collections.singleton(stateCondition), true);
      }

      /* Use Search from Filter */
      else {
        List<SearchHit<NewsReference>> result = search.searchNews(filter.getSearch());
        targetNews = new ArrayList<SearchHit<NewsReference>>(result.size());

        /* Filter out those that are not visible */
        for (SearchHit<NewsReference> resultItem : result) {
          INews.State state = (State) resultItem.getData(INews.STATE);
          if (visibleStates.contains(state))
            targetNews.add(resultItem);
        }
      }

      /* Return early if there is no matching News */
      if (targetNews.isEmpty()) {
        MessageDialog.openWarning(getShell(), NLS.bind(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_N, filter.getName()), NLS.bind(Messages.NewsFiltersListDialog_NO_FILTER_MATCH, filter.getName()));
        return;
      }

      /* Ask for Confirmation */
      boolean multipleActions = forcableActions.size() > 1;
      String title = NLS.bind(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_N, filter.getName());
      StringBuilder message = new StringBuilder();
      if (multipleActions)
        message.append(NLS.bind(Messages.NewsFiltersListDialog_PERFORM_ACTIONS, targetNews.size())).append("\n"); //$NON-NLS-1$
      else
        message.append(NLS.bind(Messages.NewsFiltersListDialog_PERFORM_ACTION, targetNews.size())).append("\n"); //$NON-NLS-1$

      for (IFilterAction action : forcableActions) {
        NewsActionDescriptor newsActionDescriptor = fNewsActionPresentationManager.getNewsActionDescriptor(action.getActionId());
        String label = newsActionDescriptor.getNewsAction() != null ? newsActionDescriptor.getNewsAction().getLabel(action.getData()) : null;
        if (StringUtils.isSet(label))
          message.append("\n").append(NLS.bind(Messages.NewsFiltersListDialog_FILTER_LIST_ELEMENT, label)); //$NON-NLS-1$
        else
          message.append("\n").append(NLS.bind(Messages.NewsFiltersListDialog_FILTER_LIST_ELEMENT, newsActionDescriptor.getName())); //$NON-NLS-1$
      }

      message.append("\n\n").append(Messages.NewsFiltersListDialog_CONFIRM); //$NON-NLS-1$

      ConfirmDialog dialog = new ConfirmDialog(getShell(), title, Messages.NewsFiltersListDialog_NO_UNDO, message.toString(), IDialogConstants.OK_LABEL, null) {
        @Override
        protected String getTitleImage() {
          return "icons/wizban/filter_wiz.png"; //$NON-NLS-1$
        }

        @Override
        public void setTitle(String newTitle) {
          super.setTitle(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_TITLE);
        }
      };

      /* Apply Actions in chunks of N Items to avoid Memory issues */
      if (dialog.open() == IDialogConstants.OK_ID) {
        applyFilter(targetNews, filter);
      }
    }
  }

  private void applyFilter(final List<SearchHit<NewsReference>> news, final ISearchFilter filter) {
    IRunnableWithProgress runnable = new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor) {
        List<List<SearchHit<NewsReference>>> chunks = CoreUtils.toChunks(news, FILTER_CHUNK_SIZE);
        monitor.beginTask(NLS.bind(Messages.NewsFiltersListDialog_WAIT_FILTER_APPLIED, filter.getName()), chunks.size());

        if (monitor.isCanceled())
          return;

        int counter = 0;
        for (List<SearchHit<NewsReference>> chunk : chunks) {
          if (monitor.isCanceled())
            return;

          monitor.subTask(NLS.bind(Messages.NewsFiltersListDialog_FILTERED_N_OF_M_NEWS, (counter * FILTER_CHUNK_SIZE), news.size()));
          List<INews> newsItemsToFilter = new ArrayList<INews>(FILTER_CHUNK_SIZE);
          for (SearchHit<NewsReference> chunkItem : chunk) {
            INews newsItemToFilter = chunkItem.getResult().resolve();
            if (newsItemToFilter != null && newsItemToFilter.isVisible())
              newsItemsToFilter.add(newsItemToFilter);
            else
              CoreUtils.reportIndexIssue();
          }

          applyFilterOnChunks(newsItemsToFilter, filter);
          monitor.worked(1);
          counter++;
        }

        monitor.done();
      }
    };

    /* Show progress and allow for cancellation */
    ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
    dialog.setBlockOnOpen(false);
    dialog.setCancelable(true);
    dialog.setOpenOnRun(true);
    try {
      dialog.run(true, true, runnable);
    } catch (InvocationTargetException e) {
      Activator.getDefault().logError(e.getMessage(), e);
    } catch (InterruptedException e) {
      Activator.getDefault().logError(e.getMessage(), e);
    }
  }

  private void applyFilterOnChunks(final List<INews> news, ISearchFilter filter) {
    Collection<IFilterAction> actions = CoreUtils.getActions(filter); //Need to sort structural actions to end
    final Set<IEntity> entitiesToSave = new HashSet<IEntity>(news.size());
    final Map<INews, INews> replacements = new HashMap<INews, INews>();

    for (final IFilterAction action : actions) {
      NewsActionDescriptor newsActionDescriptor = fNewsActionPresentationManager.getNewsActionDescriptor(action.getActionId());
      if (newsActionDescriptor != null && newsActionDescriptor.isForcable()) {
        final INewsAction newsAction = newsActionDescriptor.getNewsAction();
        if (newsAction != null) {
          SafeRunnable.run(new ISafeRunnable() {
            public void handleException(Throwable e) {
              Activator.getDefault().logError(e.getMessage(), e);
            }

            public void run() throws Exception {
              List<IEntity> changedEntities = newsAction.run(news, replacements, action.getData());
              entitiesToSave.addAll(changedEntities);
            }
          });
        }
      }
    }

    /* Make sure that changed entities are saved for all actions */
    if (!entitiesToSave.isEmpty())
      DynamicDAO.saveAll(entitiesToSave);
  }

  private void updateTitle() {
    ISearchFilter problematicFilter = null;

    Table table = fViewer.getTable();
    TableItem[] items = table.getItems();
    for (TableItem item : items) {
      ISearchFilter filter = (ISearchFilter) item.getData();
      if (filter.getSearch() == null && filter.isEnabled()) {
        int index = table.indexOf(item);
        if (index < table.getItemCount() - 1) {
          problematicFilter = filter;
          break;
        }
      }
    }

    if (problematicFilter != null)
      setMessage(NLS.bind(Messages.NewsFiltersListDialog_FILTER_MATCHES_ALL_NEWS, problematicFilter.getName()), IMessageProvider.WARNING);
    else
      setMessage(Messages.NewsFiltersListDialog_ENABLED_FILTERS, IMessageProvider.INFORMATION);
  }

  /*
   * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
   */
  @Override
  protected Control createButtonBar(Composite parent) {
    return null;
  }

  private void updateMoveEnablement() {
    boolean enableMoveUp = true;
    boolean enableMoveDown = true;
    int[] selectionIndices = fViewer.getTable().getSelectionIndices();
    if (selectionIndices.length == 1) {
      enableMoveUp = selectionIndices[0] != 0;
      enableMoveDown = selectionIndices[0] != fViewer.getTable().getItemCount() - 1;
    } else {
      enableMoveUp = false;
      enableMoveDown = false;
    }

    fMoveUpButton.setEnabled(enableMoveUp);
    fMoveDownButton.setEnabled(enableMoveDown);
  }

  private void onMove(boolean up) {
    TableItem[] items = fViewer.getTable().getItems();
    List<ISearchFilter> sortedFilters = new ArrayList<ISearchFilter>(items.length);
    for (TableItem item : items) {
      sortedFilters.add((ISearchFilter) item.getData());
    }

    IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
    ISearchFilter selectedFilter = (ISearchFilter) selection.getFirstElement();
    int selectedFilterOrder = selectedFilter.getOrder();
    ISearchFilter otherFilter = null;
    int index = sortedFilters.indexOf(selectedFilter);

    /* Move Up */
    if (up && index > 0) {
      otherFilter = sortedFilters.get(index - 1);
      selectedFilter.setOrder(otherFilter.getOrder());
      otherFilter.setOrder(selectedFilterOrder);
    }

    /* Move Down */
    else if (!up && index < sortedFilters.size() - 1) {
      otherFilter = sortedFilters.get(index + 1);
      selectedFilter.setOrder(otherFilter.getOrder());
      otherFilter.setOrder(selectedFilterOrder);
    }

    fSearchFilterDao.saveAll(Arrays.asList(new ISearchFilter[] { selectedFilter, otherFilter }));
    fViewer.refresh();
    fViewer.getTable().showSelection();
    updateCheckedState();
    updateMoveEnablement();
    updateTitle();
  }

  private void updateCheckedState() {
    TableItem[] items = fViewer.getTable().getItems();
    for (TableItem item : items) {
      ISearchFilter filter = (ISearchFilter) item.getData();
      fViewer.setChecked(filter, filter.isEnabled());
    }
  }

  private void onAdd() {
    NewsFilterDialog dialog = new NewsFilterDialog(getShell());
    Table table = fViewer.getTable();
    dialog.setFilterPosition(table.getItemCount());
    if (dialog.open() == IDialogConstants.OK_ID) {
      fViewer.refresh();
      updateCheckedState();
      fViewer.setSelection(new StructuredSelection(table.getItem(table.getItemCount() - 1).getData()));
      fViewer.getTable().setFocus();
      updateTitle();
    }
  }

  private void onEdit() {
    IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
    ISearchFilter filter = (ISearchFilter) selection.getFirstElement();

    NewsFilterDialog dialog = new NewsFilterDialog(getShell(), filter);
    if (dialog.open() == IDialogConstants.OK_ID) {
      fViewer.refresh(true);
      fViewer.getTable().setFocus();
      updateTitle();
    }
  }

  private void onDelete() {
    IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();

    List<?> selectedFilters = selection.toList();
    ConfirmDialog dialog = new ConfirmDialog(getShell(), Messages.NewsFiltersListDialog_CONFIRM_DELETE, Messages.NewsFiltersListDialog_NO_UNDO, getMessage(selectedFilters), null);
    if (dialog.open() == IDialogConstants.OK_ID) {
      List<ISearchFilter> filtersToDelete = new ArrayList<ISearchFilter>(selectedFilters.size());
      for (Iterator<?> iterator = selectedFilters.iterator(); iterator.hasNext();) {
        ISearchFilter filter = (ISearchFilter) iterator.next();
        filtersToDelete.add(filter);
      }

      fSearchFilterDao.deleteAll(filtersToDelete);
      fViewer.remove(selection.toArray());
      fixOrderAfterDelete();
      updateTitle();
    }
  }

  /* Ensure that after Delete, the orders are in sync again */
  private void fixOrderAfterDelete() {
    List<ISearchFilter> filtersToSave = new ArrayList<ISearchFilter>();

    TableItem[] items = fViewer.getTable().getItems();
    for (int i = 0; i < items.length; i++) {
      TableItem item = items[i];
      ISearchFilter filter = (ISearchFilter) item.getData();
      filter.setOrder(i);

      filtersToSave.add(filter);
    }

    DynamicDAO.saveAll(filtersToSave);
  }

  private String getMessage(List<?> elements) {
    StringBuilder message = new StringBuilder();

    /* One Element */
    if (elements.size() == 1) {
      ISearchFilter filter = (ISearchFilter) elements.get(0);
      message.append(NLS.bind(Messages.NewsFiltersListDialog_CONFIRM_DELETE_FILTER_N, filter.getName()));
    }

    /* N Elements */
    else {
      message.append(Messages.NewsFiltersListDialog_CONFIRM_DELETE_FILTERS);
    }

    return message.toString();
  }

  /*
   * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
   */
  @Override
  protected void configureShell(Shell shell) {
    super.configureShell(shell);
    shell.setText(Messages.NewsFiltersListDialog_NEWS_FILTERS);
  }

  /**
   * @param filter the {@link ISearchFilter} to select.
   */
  public void setSelection(ISearchFilter filter) {
    fSelectedFilter = filter;
    if (fViewer != null)
      fViewer.setSelection(new StructuredSelection(fSelectedFilter), true);
  }

  /**
   * Refresh the list of displayed Filters.
   */
  public void refresh() {
    if (fViewer != null) {
      fViewer.refresh();
      updateCheckedState();
    }
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#isResizable()
   */
  @Override
  protected boolean isResizable() {
    return true;
  }

  /*
   * @see org.eclipse.jface.window.Window#getShellStyle()
   */
  @Override
  protected int getShellStyle() {
    int style = SWT.TITLE | SWT.BORDER | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | getDefaultOrientation();

    return style;
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsStrategy()
   */
  @Override
  protected int getDialogBoundsStrategy() {
    return DIALOG_PERSISTSIZE;
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings()
   */
  @Override
  protected IDialogSettings getDialogBoundsSettings() {
    IDialogSettings settings = Activator.getDefault().getDialogSettings();
    IDialogSettings section = settings.getSection(SETTINGS_SECTION);
    if (section != null)
      return section;

    return settings.addNewSection(SETTINGS_SECTION);
  }
}


/*
 * Copyright (C) 2017-2019 Dremio Corporation
 *
 * 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 com.dremio.service.scheduler;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAmount;
import java.util.Iterator;

import com.google.common.base.Preconditions;

class BaseSchedule implements Schedule {
  private final TemporalAmount amount;
  private final TemporalAdjuster adjuster;
  private final Instant at;
  private final ZoneId zoneId;
  private final String taskName;
  private final Long scheduledOwnershipRelease;
  private final CleanupListener cleanupListener;

  BaseSchedule(Instant at, TemporalAmount period, TemporalAdjuster adjuster, ZoneId zoneId,
               String taskName, Long scheduledOwnershipRelease, CleanupListener cleanupListener) {
    this.amount = period;
    this.adjuster = adjuster;
    this.at = at;
    this.zoneId = zoneId;
    this.taskName = taskName;
    this.scheduledOwnershipRelease = scheduledOwnershipRelease;
    this.cleanupListener = cleanupListener;
  }

  @Override
  public TemporalAmount getPeriod() {
    return amount;
  }

  @Override
  public Iterator<Instant> iterator() {
    LocalDateTime at = LocalDateTime.ofInstant(this.at, zoneId);
    LocalDateTime adjustedAt = at.with(adjuster);
    final LocalDateTime start = adjustedAt.isBefore(at)
        ? at.plus(amount).with(adjuster)
        : adjustedAt;

    return new Iterator<Instant>() {
      private LocalDateTime next = start;

      @Override
      public boolean hasNext() {
        return true;
      }

      @Override
      public Instant next() {
        Instant result = next.atZone(zoneId).toInstant();
        next = next.plus(amount).with(adjuster);

        return result;
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException("Schedule iterator does not support remove operation.");
      }
    };
  }

  @Override
  public String getTaskName() {
    return taskName;
  }

  @Override
  public Long getScheduledOwnershipReleaseInMillis() {
    Preconditions.checkState(taskName != null,
      "Name of the task for which to release scheduled ownership is missing");
    return scheduledOwnershipRelease;
  }

  @Override
  public CleanupListener getCleanupListener() {
    return cleanupListener;
  }
}


/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * 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.
 */

#include "mylibrary/mylibrary.h"

void my_api() {}


/*
 * Copyright (c) 2012 - 2014 Ngewi Fet <ngewif@gmail.com>
 * Copyright (c) 2014 Yongxin Wang <fefe.wyx@gmail.com>
 *
 * 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.gnucash.android.export.ofx;

import android.database.sqlite.SQLiteDatabase;
import android.preference.PreferenceManager;
import android.util.Log;

import com.crashlytics.android.Crashlytics;

import org.gnucash.android.R;
import org.gnucash.android.app.GnuCashApplication;
import org.gnucash.android.db.adapter.AccountsDbAdapter;
import org.gnucash.android.export.ExportParams;
import org.gnucash.android.export.Exporter;
import org.gnucash.android.model.Account;
import org.gnucash.android.model.Transaction;
import org.gnucash.android.util.PreferencesHelper;
import org.gnucash.android.util.TimestampHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

/**
 * Exports the data in the database in OFX format
 * @author Ngewi Fet <ngewi.fet@gmail.com>
 * @author Yongxin Wang <fefe.wyx@gmail.com>
 */
public class OfxExporter extends Exporter{

    /**
	 * List of accounts in the expense report
	 */
	private List<Account> mAccountsList;

    /**
	 * Builds an XML representation of the {@link Account}s and {@link Transaction}s in the database
	 */
	public OfxExporter(ExportParams params) {
        super(params, null);
        LOG_TAG = "OfxExporter";
	}

    /**
     * Overloaded constructor. Initializes the export parameters and the database to export
     * @param params Export options
     * @param db SQLiteDatabase to export
     */
    public OfxExporter(ExportParams params, SQLiteDatabase db){
        super(params, db);
        LOG_TAG = "OfxExporter";
    }

    /**
	 * Converts all expenses into OFX XML format and adds them to the XML document
	 * @param doc DOM document of the OFX expenses.
	 * @param parent Parent node for all expenses in report
	 */
	private void generateOfx(Document doc, Element parent){
		Element transactionUid = doc.createElement(OfxHelper.TAG_TRANSACTION_UID);
		//unsolicited because the data exported is not as a result of a request
		transactionUid.appendChild(doc.createTextNode(OfxHelper.UNSOLICITED_TRANSACTION_ID));

		Element statementTransactionResponse = doc.createElement(OfxHelper.TAG_STATEMENT_TRANSACTION_RESPONSE);
		statementTransactionResponse.appendChild(transactionUid);

		Element bankmsgs = doc.createElement(OfxHelper.TAG_BANK_MESSAGES_V1);
		bankmsgs.appendChild(statementTransactionResponse);

		parent.appendChild(bankmsgs);

		AccountsDbAdapter accountsDbAdapter = mAccountsDbAdapter;
		for (Account account : mAccountsList) {
			if (account.getTransactionCount() == 0)
				continue;

            //do not export imbalance accounts for OFX transactions and double-entry disabled
            if (!GnuCashApplication.isDoubleEntryEnabled() && account.getName().contains(mContext.getString(R.string.imbalance_account_name)))
                continue;

			//add account details (transactions) to the XML document
			account.toOfx(doc, statementTransactionResponse, mExportParams.getExportStartTime());

			//mark as exported
			accountsDbAdapter.markAsExported(account.getUID());

		}
	}

    /**
     * Generate OFX export file from the transactions in the database
     * @return String containing OFX export
     * @throws ExporterException
     */
    private String generateOfxExport() throws ExporterException {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory
                .newInstance();
        DocumentBuilder docBuilder;
        try {
            docBuilder = docFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new ExporterException(mExportParams, e);
        }

        Document document = docBuilder.newDocument();
        Element root = document.createElement("OFX");

        ProcessingInstruction pi = document.createProcessingInstruction("OFX", OfxHelper.OFX_HEADER);
        document.appendChild(pi);
        document.appendChild(root);

        generateOfx(document, root);

        boolean useXmlHeader = PreferenceManager.getDefaultSharedPreferences(mContext)
                .getBoolean(mContext.getString(R.string.key_xml_ofx_header), false);

        PreferencesHelper.setLastExportTime(TimestampHelper.getTimestampFromNow());

        StringWriter stringWriter = new StringWriter();
        //if we want SGML OFX headers, write first to string and then prepend header
        if (useXmlHeader){
            write(document, stringWriter, false);
            return stringWriter.toString();
        } else {
            Node ofxNode = document.getElementsByTagName("OFX").item(0);
            write(ofxNode, stringWriter, true);
            return OfxHelper.OFX_SGML_HEADER + '\n' + stringWriter.toString();
        }
    }

    @Override
    public List<String> generateExport() throws ExporterException {
        mAccountsList = mAccountsDbAdapter.getExportableAccounts(mExportParams.getExportStartTime());
        if (mAccountsList.isEmpty())
            return new ArrayList<>(); // Nothing to export, so no files generated

        BufferedWriter writer = null;

        try {
            File file = new File(getExportCacheFilePath());
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
            writer.write(generateOfxExport());
        } catch (IOException e) {
            throw new ExporterException(mExportParams, e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    throw new ExporterException(mExportParams, e);
                }
            }
        }

        List<String> exportedFiles = new ArrayList<>();
        exportedFiles.add(getExportCacheFilePath());

        return exportedFiles;
    }

    /**
     * Writes out the document held in node to outputWriter
     * @param node {@link Node} containing the OFX document structure. Usually the parent node
     * @param outputWriter {@link java.io.Writer} to use in writing the file to stream
     * @param omitXmlDeclaration Flag which causes the XML declaration to be omitted
     */
    private void write(Node node, Writer outputWriter, boolean omitXmlDeclaration){
        try {
            TransformerFactory transformerFactory = TransformerFactory
                    .newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(node);
            StreamResult result = new StreamResult(outputWriter);

            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            if (omitXmlDeclaration) {
                transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            }

            transformer.transform(source, result);
        } catch (TransformerException tfException) {
            Log.e(LOG_TAG, tfException.getMessage());
            Crashlytics.logException(tfException);
        }
    }

    /**
     * Returns the MIME type for this exporter.
     * @return MIME type as string
     */
    public String getExportMimeType(){
        return "text/xml";
    }
}


/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <aws/kafka/model/BrokerEBSVolumeInfo.h>
#include <aws/core/utils/json/JsonSerializer.h>

#include <utility>

using namespace Aws::Utils::Json;
using namespace Aws::Utils;

namespace Aws
{
namespace Kafka
{
namespace Model
{

BrokerEBSVolumeInfo::BrokerEBSVolumeInfo() :
    m_kafkaBrokerNodeIdHasBeenSet(false),
    m_volumeSizeGB(0),
    m_volumeSizeGBHasBeenSet(false)
{
}

BrokerEBSVolumeInfo::BrokerEBSVolumeInfo(JsonView jsonValue) :
    m_kafkaBrokerNodeIdHasBeenSet(false),
    m_volumeSizeGB(0),
    m_volumeSizeGBHasBeenSet(false)
{
  *this = jsonValue;
}

BrokerEBSVolumeInfo& BrokerEBSVolumeInfo::operator =(JsonView jsonValue)
{
  if(jsonValue.ValueExists("kafkaBrokerNodeId"))
  {
    m_kafkaBrokerNodeId = jsonValue.GetString("kafkaBrokerNodeId");

    m_kafkaBrokerNodeIdHasBeenSet = true;
  }

  if(jsonValue.ValueExists("volumeSizeGB"))
  {
    m_volumeSizeGB = jsonValue.GetInteger("volumeSizeGB");

    m_volumeSizeGBHasBeenSet = true;
  }

  return *this;
}

JsonValue BrokerEBSVolumeInfo::Jsonize() const
{
  JsonValue payload;

  if(m_kafkaBrokerNodeIdHasBeenSet)
  {
   payload.WithString("kafkaBrokerNodeId", m_kafkaBrokerNodeId);

  }

  if(m_volumeSizeGBHasBeenSet)
  {
   payload.WithInteger("volumeSizeGB", m_volumeSizeGB);

  }

  return payload;
}

} // namespace Model
} // namespace Kafka
} // namespace Aws


mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

bdd
library
mock
mock objects
mockery
stub
tdd
test
test double
testing


OPTIONS sip:bob@example.com SIP/2.0
Via: SIP/2.0/UDP 172.21.40.44;branch=z9hG4bKitIIzAialKS
Via: SIP/2.0/UDP [3ffe:1200:3012:c000:210:a4ff:fe8d:6a46]:5062
     ;branch=z9hG4bKJv+PsUQdfOb
     ;received=172.21.40.24
Record-Route: <sip:bob@example.com;maddr=172.21.40.44>
Record-Route: <sip:bob@example.com
     ;maddr=[3ffe:1200:3012:c000:210:a4ff:fe8d:6a46]>
From: <sip:alice@example.com>;tag=ud6a29947
To: <sip:bob@example.com>
Call-ID: f3359e42-5109-11d6-998d-0010a47e1c0f
CSeq: 1 OPTIONS
Contact: <sip:[3ffe:1200:3012:c000:210:a4ff:fe8d:6a46]:5062>
Content-Length: 0
Accept:
Allow:


#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.

scriptversion=2013-10-28.13; # UTC

# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.

if test $# -eq 0; then
  echo 1>&2 "Try '$0 --help' for more information"
  exit 1
fi

case $1 in

  --is-lightweight)
    # Used by our autoconf macros to check whether the available missing
    # script is modern enough.
    exit 0
    ;;

  --run)
    # Back-compat with the calling convention used by older automake.
    shift
    ;;

  -h|--h|--he|--hel|--help)
    echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...

Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.

Options:
  -h, --help      display this help and exit
  -v, --version   output version information and exit

Supported PROGRAM values:
  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
  bison     yacc      flex         lex       help2man

Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.

Send bug reports to <bug-automake@gnu.org>."
    exit $?
    ;;

  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
    echo "missing $scriptversion (GNU Automake)"
    exit $?
    ;;

  -*)
    echo 1>&2 "$0: unknown '$1' option"
    echo 1>&2 "Try '$0 --help' for more information"
    exit 1
    ;;

esac

# Run the given program, remember its exit status.
"$@"; st=$?

# If it succeeded, we are done.
test $st -eq 0 && exit 0

# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac

# Exit code 63 means version mismatch.  This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
  msg="probably too old"
elif test $st -eq 127; then
  # Program was missing.
  msg="missing on your system"
else
  # Program was found and executed, but failed.  Give up.
  exit $st
fi

perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software

program_details ()
{
  case $1 in
    aclocal|automake)
      echo "The '$1' program is part of the GNU Automake package:"
      echo "<$gnu_software_URL/automake>"
      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
      echo "<$gnu_software_URL/autoconf>"
      echo "<$gnu_software_URL/m4/>"
      echo "<$perl_URL>"
      ;;
    autoconf|autom4te|autoheader)
      echo "The '$1' program is part of the GNU Autoconf package:"
      echo "<$gnu_software_URL/autoconf/>"
      echo "It also requires GNU m4 and Perl in order to run:"
      echo "<$gnu_software_URL/m4/>"
      echo "<$perl_URL>"
      ;;
  esac
}

give_advice ()
{
  # Normalize program name to check for.
  normalized_program=`echo "$1" | sed '
    s/^gnu-//; t
    s/^gnu//; t
    s/^g//; t'`

  printf '%s\n' "'$1' is $msg."

  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
  case $normalized_program in
    autoconf*)
      echo "You should only need it if you modified 'configure.ac',"
      echo "or m4 files included by it."
      program_details 'autoconf'
      ;;
    autoheader*)
      echo "You should only need it if you modified 'acconfig.h' or"
      echo "$configure_deps."
      program_details 'autoheader'
      ;;
    automake*)
      echo "You should only need it if you modified 'Makefile.am' or"
      echo "$configure_deps."
      program_details 'automake'
      ;;
    aclocal*)
      echo "You should only need it if you modified 'acinclude.m4' or"
      echo "$configure_deps."
      program_details 'aclocal'
      ;;
   autom4te*)
      echo "You might have modified some maintainer files that require"
      echo "the 'autom4te' program to be rebuilt."
      program_details 'autom4te'
      ;;
    bison*|yacc*)
      echo "You should only need it if you modified a '.y' file."
      echo "You may want to install the GNU Bison package:"
      echo "<$gnu_software_URL/bison/>"
      ;;
    lex*|flex*)
      echo "You should only need it if you modified a '.l' file."
      echo "You may want to install the Fast Lexical Analyzer package:"
      echo "<$flex_URL>"
      ;;
    help2man*)
      echo "You should only need it if you modified a dependency" \
           "of a man page."
      echo "You may want to install the GNU Help2man package:"
      echo "<$gnu_software_URL/help2man/>"
    ;;
    makeinfo*)
      echo "You should only need it if you modified a '.texi' file, or"
      echo "any other file indirectly affecting the aspect of the manual."
      echo "You might want to install the Texinfo package:"
      echo "<$gnu_software_URL/texinfo/>"
      echo "The spurious makeinfo call might also be the consequence of"
      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
      echo "want to install GNU make:"
      echo "<$gnu_software_URL/make/>"
      ;;
    *)
      echo "You might have modified some files without having the proper"
      echo "tools for further handling them.  Check the 'README' file, it"
      echo "often tells you about the needed prerequisites for installing"
      echo "this package.  You may also peek at any GNU archive site, in"
      echo "case some other package contains this missing '$1' program."
      ;;
  esac
}

give_advice "$1" | sed -e '1s/^/WARNING: /' \
                       -e '2,$s/^/         /' >&2

# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:


fileFormatVersion: 2
guid: 6af95d700b5ba480bbc6d727c10a2ac1
timeCreated: 1434665137
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;

namespace XBMCRPC
{

    public partial class Client:IDisposable
    {
        internal IPlatformServices PlatformServices { get; set; }
        public readonly ConnectionSettings _settings;
        private uint JsonRpcId = 0;

                public Methods.Addons Addons { get; private set; }
        public Methods.Application Application { get; private set; }
        public Methods.AudioLibrary AudioLibrary { get; private set; }
        public Methods.Favourites Favourites { get; private set; }
        public Methods.Files Files { get; private set; }
        public Methods.GUI GUI { get; private set; }
        public Methods.Input Input { get; private set; }
        public Methods.JSONRPC JSONRPC { get; private set; }
        public Methods.Player Player { get; private set; }
        public Methods.Playlist Playlist { get; private set; }
        public Methods.Profiles Profiles { get; private set; }
        public Methods.PVR PVR { get; private set; }
        public Methods.Settings Settings { get; private set; }
        public Methods.System System { get; private set; }
        public Methods.Textures Textures { get; private set; }
        public Methods.VideoLibrary VideoLibrary { get; private set; }
        public Methods.XBMC XBMC { get; private set; }

        public Client(ConnectionSettings settings, IPlatformServices platformServices)
        {
            PlatformServices = platformServices;
            Serializer = new JsonSerializer();
            Serializer.Converters.Add(new StringEnumConverter());
            _settings = settings;
                       Addons = new Methods.Addons(this);
           Application = new Methods.Application(this);
           AudioLibrary = new Methods.AudioLibrary(this);
           Favourites = new Methods.Favourites(this);
           Files = new Methods.Files(this);
           GUI = new Methods.GUI(this);
           Input = new Methods.Input(this);
           JSONRPC = new Methods.JSONRPC(this);
           Player = new Methods.Player(this);
           Playlist = new Methods.Playlist(this);
           Profiles = new Methods.Profiles(this);
           PVR = new Methods.PVR(this);
           Settings = new Methods.Settings(this);
           System = new Methods.System(this);
           Textures = new Methods.Textures(this);
           VideoLibrary = new Methods.VideoLibrary(this);
           XBMC = new Methods.XBMC(this);
        }

        internal JsonSerializer Serializer { get; private set; }

        async internal Task<T> GetData<T>(string method, object args)
        {
            var request = WebRequest.Create(_settings.JsonInterfaceAddress);
            request.Credentials = new NetworkCredential(_settings.UserName, _settings.Password);
            request.ContentType = "application/json";
            request.Method = "POST";
            var postStream = await request.GetRequestStreamAsync();

            var requestId = JsonRpcId++;
            var jsonRequest = BuildJsonPost(method, args, requestId);
            byte[] postData = Encoding.UTF8.GetBytes(jsonRequest);
            postStream.Write(postData, 0, postData.Length);
            postStream.Dispose();

            var response = await request.GetResponseAsync();
            var responseStream = response.GetResponseStream();
            string responseData=null;
            if (responseStream != null)
            {
                var streamReader = new StreamReader(responseStream);
                responseData = streamReader.ReadToEnd();
                responseStream.Dispose();
                streamReader.Dispose();
            }

            response.Dispose();

            JObject query = JObject.Parse(responseData);
            var error = query["error"];
            if (error!=null)
            {
                throw new Exception(error.ToString());
            }
            var result = query["result"].ToObject<T>(Serializer);
            return result;
        }

        private static string BuildJsonPost(string method, object args, uint id)
        {
            var jsonPost = new JObject {new JProperty("jsonrpc", "2.0"), new JProperty("method", method)};
            if (args != null)
            {
                jsonPost.Add(new JProperty("params", args));
            }
            jsonPost.Add(new JProperty("id", id));

            return jsonPost.ToString();
        }

        private ISocket _clientSocket;

        public async Task StartNotificationListener()
        {
            _clientSocket = PlatformServices.SocketFactory.GetSocket();
            await _clientSocket.ConnectAsync(_settings.Host, _settings.TcpPort);

            var stream = _clientSocket.GetInputStream();

            ListenForNotifications(stream);
        }

        private async Task ListenForNotifications(Stream stream)
        {
            var socketState = new NotificationListenerSocketState();
            try
            {
                while (_clientSocket!=null)
                {
                    var receivedDataLength =
                        await stream.ReadAsync(socketState.Buffer, 0, NotificationListenerSocketState.BufferSize);

                    var receivedDataJson = Encoding.UTF8.GetString(socketState.Buffer, 0, receivedDataLength);

                    socketState.Builder.Append(receivedDataJson);

                    JObject jObject;
                    if (TryParseObject(socketState.Builder.ToString(), out jObject))
                    {
                        ParseNotification(jObject);

                        socketState = new NotificationListenerSocketState();
                    }
                    else
                    {
                        // Begin listening for remainder of announcement using same socket state
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        private static bool TryParseObject(string announcementJson, out JObject jObject)
        {
            jObject = null;
            try
            {
                jObject = JObject.Parse(announcementJson);
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        private void ParseNotification(JObject jObject)
        {
            if (jObject["method"] != null)
            {
                string _method;
                _method = jObject["method"].ToString();
                switch (_method)
                {
					        case "Application.OnVolumeChanged":
            Application.RaiseOnVolumeChanged(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Application.OnVolumeChanged_data>(Serializer)
);
            break;
        case "AudioLibrary.OnCleanFinished":
            AudioLibrary.RaiseOnCleanFinished(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "AudioLibrary.OnCleanStarted":
            AudioLibrary.RaiseOnCleanStarted(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "AudioLibrary.OnRemove":
            AudioLibrary.RaiseOnRemove(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.AudioLibrary.OnRemove_data>(Serializer)
);
            break;
        case "AudioLibrary.OnScanFinished":
            AudioLibrary.RaiseOnScanFinished(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "AudioLibrary.OnScanStarted":
            AudioLibrary.RaiseOnScanStarted(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "AudioLibrary.OnUpdate":
            AudioLibrary.RaiseOnUpdate(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.AudioLibrary.OnUpdate_data>(Serializer)
);
            break;
        case "GUI.OnScreensaverActivated":
            GUI.RaiseOnScreensaverActivated(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "GUI.OnScreensaverDeactivated":
            GUI.RaiseOnScreensaverDeactivated(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "Input.OnInputFinished":
            Input.RaiseOnInputFinished(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "Input.OnInputRequested":
            Input.RaiseOnInputRequested(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Input.OnInputRequested_data>(Serializer)
);
            break;
        case "Player.OnPause":
            Player.RaiseOnPause(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Player.Notifications.Data>(Serializer)
);
            break;
        case "Player.OnPlay":
            Player.RaiseOnPlay(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Player.Notifications.Data>(Serializer)
);
            break;
        case "Player.OnPropertyChanged":
            Player.RaiseOnPropertyChanged(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Player.OnPropertyChanged_data>(Serializer)
);
            break;
        case "Player.OnSeek":
            Player.RaiseOnSeek(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Player.OnSeek_data>(Serializer)
);
            break;
        case "Player.OnSpeedChanged":
            Player.RaiseOnSpeedChanged(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Player.Notifications.Data>(Serializer)
);
            break;
        case "Player.OnStop":
            Player.RaiseOnStop(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Player.OnStop_data>(Serializer)
);
            break;
        case "Playlist.OnAdd":
            Playlist.RaiseOnAdd(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Playlist.OnAdd_data>(Serializer)
);
            break;
        case "Playlist.OnClear":
            Playlist.RaiseOnClear(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Playlist.OnClear_data>(Serializer)
);
            break;
        case "Playlist.OnRemove":
            Playlist.RaiseOnRemove(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.Playlist.OnRemove_data>(Serializer)
);
            break;
        case "System.OnLowBattery":
            System.RaiseOnLowBattery(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "System.OnQuit":
            System.RaiseOnQuit(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "System.OnRestart":
            System.RaiseOnRestart(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "System.OnSleep":
            System.RaiseOnSleep(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "System.OnWake":
            System.RaiseOnWake(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "VideoLibrary.OnCleanFinished":
            VideoLibrary.RaiseOnCleanFinished(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "VideoLibrary.OnCleanStarted":
            VideoLibrary.RaiseOnCleanStarted(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "VideoLibrary.OnRemove":
            VideoLibrary.RaiseOnRemove(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.VideoLibrary.OnRemove_data>(Serializer)
);
            break;
        case "VideoLibrary.OnScanFinished":
            VideoLibrary.RaiseOnScanFinished(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "VideoLibrary.OnScanStarted":
            VideoLibrary.RaiseOnScanStarted(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<object>(Serializer)
);
            break;
        case "VideoLibrary.OnUpdate":
            VideoLibrary.RaiseOnUpdate(
jObject["params"]["sender"].ToObject<string>(Serializer)
, jObject["params"]["data"].ToObject<XBMCRPC.VideoLibrary.OnUpdate_data>(Serializer)
);
            break;

                }
            }
        }

        public void Dispose()
        {
            var socket = _clientSocket;
            _clientSocket = null;
            if (socket != null)
            {
                socket.Dispose();
            }
        }

    }
}


const streakjs = require('../../../lib/streakjs/streakjs.min');

export function runDraw(layer) {

    var text = new streakjs.shapes.Text({
        x: (layer.width - 240) / 2,
        y: 100,
        text:"streakjs",
        fontSize: 32,
        fill: '#555',
        width: 240,
        padding: 20,
        align: 'center'
    });

    var rect = new streakjs.shapes.Rect({
        x: (layer.width - 240) / 2,
        y: 100,
        fill: '#ddd',
        width: 240,
        height: 80,
        strokeWidth: 10,
        strokeLinearGradientStartPoint: { x: 0, y: 0 },
        strokeLinearGradientEndPoint: { x: 240, y: 80 },
        strokeLinearGradientColorStops: [0, 'blue', 1, 'green']
    });

    layer.add(rect);
    layer.add(text);

    layer.draw();

}


a=1
echo ">$a"


/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import com.adobe.test.Assert;

gTestfile = 'regress-7224.js';

/**
 *  File Name:          regress-7224.js
 *  Reference:          js1_2
 *  Description:        Remove support for the arg
 *  Author:             ** replace with your e-mail address **
 */

// var SECTION = "regress";       // provide a document reference (ie, ECMA section)
// var VERSION = "JS1_4"; // Version of JavaScript or ECMA
// var TITLE   = "Regression test for bugzilla #7224";       // Provide ECMA section title or a description
var BUGNUMBER = "http://bugzilla.mozilla.org/show_bug.cgi?id=7224";     // Provide URL to bugsplat or bugzilla report

var f = function() {return arguments.caller};
var o = {};

o.foo = f;
o.foo("a", "b", "c");

Assert.expectEq(
  "var f = new Function( 'return arguments.caller' ); f()",
  undefined,
  f() );

Assert.expectEq(
  "var o = {}; o.foo = f; o.foo('a')",
  undefined,
  o.foo('a') );

// displays results.


import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import { Observable, of } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';

import { Hero } from './hero';
import { MessageService } from './message.service';

@Injectable({ providedIn: 'root' })
export class HeroService {

  private heroesUrl = 'api/heroes';  // URL to web api

  httpOptions = {
    headers: new HttpHeaders({ 'Content-Type': 'application/json' })
  };

  constructor(
    private http: HttpClient,
    private messageService: MessageService) { }

  /** GET heroes from the server */
  getHeroes(): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl)
      .pipe(
        tap(_ => this.log('fetched heroes')),
        catchError(this.handleError<Hero[]>('getHeroes', []))
      );
  }

  /** GET hero by id. Return `undefined` when id not found */
  getHeroNo404<Data>(id: number): Observable<Hero> {
    const url = `${this.heroesUrl}/?id=${id}`;
    return this.http.get<Hero[]>(url)
      .pipe(
        map(heroes => heroes[0]), // returns a {0|1} element array
        tap(h => {
          const outcome = h ? `fetched` : `did not find`;
          this.log(`${outcome} hero id=${id}`);
        }),
        catchError(this.handleError<Hero>(`getHero id=${id}`))
      );
  }

  /** GET hero by id. Will 404 if id not found */
  getHero(id: number): Observable<Hero> {
    const url = `${this.heroesUrl}/${id}`;
    return this.http.get<Hero>(url).pipe(
      tap(_ => this.log(`fetched hero id=${id}`)),
      catchError(this.handleError<Hero>(`getHero id=${id}`))
    );
  }

  /* GET heroes whose name contains search term */
  searchHeroes(term: string): Observable<Hero[]> {
    if (!term.trim()) {
      // if not search term, return empty hero array.
      return of([]);
    }
    return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
      tap(x => x.length ?
         this.log(`found heroes matching "${term}"`) :
         this.log(`no heroes matching "${term}"`)),
      catchError(this.handleError<Hero[]>('searchHeroes', []))
    );
  }

  //////// Save methods //////////

  /** POST: add a new hero to the server */
  addHero(hero: Hero): Observable<Hero> {
    return this.http.post<Hero>(this.heroesUrl, hero, this.httpOptions).pipe(
      tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)),
      catchError(this.handleError<Hero>('addHero'))
    );
  }

  /** DELETE: delete the hero from the server */
  deleteHero(hero: Hero | number): Observable<Hero> {
    const id = typeof hero === 'number' ? hero : hero.id;
    const url = `${this.heroesUrl}/${id}`;

    return this.http.delete<Hero>(url, this.httpOptions).pipe(
      tap(_ => this.log(`deleted hero id=${id}`)),
      catchError(this.handleError<Hero>('deleteHero'))
    );
  }

  /** PUT: update the hero on the server */
  updateHero(hero: Hero): Observable<any> {
    return this.http.put(this.heroesUrl, hero, this.httpOptions).pipe(
      tap(_ => this.log(`updated hero id=${hero.id}`)),
      catchError(this.handleError<any>('updateHero'))
    );
  }

  /**
   * Handle Http operation that failed.
   * Let the app continue.
   * @param operation - name of the operation that failed
   * @param result - optional value to return as the observable result
   */
  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {

      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead

      // TODO: better job of transforming error for user consumption
      this.log(`${operation} failed: ${error.message}`);

      // Let the app keep running by returning an empty result.
      return of(result as T);
    };
  }

  /** Log a HeroService message with the MessageService */
  private log(message: string) {
    this.messageService.add(`HeroService: ${message}`);
  }
}


<!DOCTYPE html>

	<TITLE> ZTREE DEMO - Other Mouse Event</TITLE>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
	<link rel="stylesheet" href="../../../css/demo.css" type="text/css">
	<link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type="text/css">

其他鼠标事件监听

[ 文件路径: core/otherMouse.html ]

1、mousedown / mouseup / rightClick 事件回调函数控制

zTree 提供 这几种鼠标事件响应，主要是为了便于用户针对一些特殊需求进行扩展开发，不会对 zTree 造成任何影响，这里简单演示如何监控此事件

请尝试鼠标在 zTree 上胡乱点击（左键、右键）吧，顺便看看 log

					mousedown event log:

					mouseup event log:

					rightClick event log:

2、setting 配置信息说明

事件回调函数的使用，详细请参见 API 文档中 setting.callback 的相关内容

3、treeNode 节点数据说明

对 节点数据 没有特殊要求，用户可以根据自己的需求添加自定义属性


'use strict';

var getPolyfill = require('./polyfill');
var define = require('define-properties');

module.exports = function shimGetOwnPropertyDescriptors() {
	var polyfill = getPolyfill();
	define(
		Object,
		{ getOwnPropertyDescriptors: polyfill },
		{ getOwnPropertyDescriptors: function () { return Object.getOwnPropertyDescriptors !== polyfill; } }
	);
	return polyfill;
};


/***
  This file is part of PulseAudio.

  PulseAudio is free software; you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License as published
  by the Free Software Foundation; either version 2.1 of the License,
  or (at your option) any later version.

  PulseAudio is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
***/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <assert.h>
#include <check.h>

#include <pulse/rtclock.h>
#include <pulse/timeval.h>

#include <pulsecore/core-util.h>
#include <pulsecore/core-rtclock.h>

#ifdef GLIB_MAIN_LOOP

#include <glib.h>
#include <pulse/glib-mainloop.h>

static GMainLoop* glib_main_loop = NULL;

#else /* GLIB_MAIN_LOOP */
#include <pulse/mainloop.h>
#endif /* GLIB_MAIN_LOOP */

static pa_defer_event *de;

static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
    unsigned char c;
    pa_assert_se(read(fd, &c, sizeof(c)) >= 0);
    fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c);
    a->defer_enable(de, 1);
}

static void dcb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
    fprintf(stderr, "DEFER EVENT\n");
    a->defer_enable(e, 0);
}

static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) {
    fprintf(stderr, "TIME EVENT\n");

#if defined(GLIB_MAIN_LOOP)
    g_main_loop_quit(glib_main_loop);
#else
    a->quit(a, 0);
#endif
}

START_TEST (mainloop_test) {
    pa_mainloop_api *a;
    pa_io_event *ioe;
    pa_time_event *te;
    struct timeval tv;

#ifdef GLIB_MAIN_LOOP
    pa_glib_mainloop *g;

    glib_main_loop = g_main_loop_new(NULL, FALSE);
    fail_if(!glib_main_loop);

    g = pa_glib_mainloop_new(NULL);
    fail_if(!g);

    a = pa_glib_mainloop_get_api(g);
    fail_if(!a);
#else /* GLIB_MAIN_LOOP */
    pa_mainloop *m;

    m = pa_mainloop_new();
    fail_if(!m);

    a = pa_mainloop_get_api(m);
    fail_if(!a);
#endif /* GLIB_MAIN_LOOP */

    ioe = a->io_new(a, 0, PA_IO_EVENT_INPUT, iocb, NULL);
    fail_if(!ioe);

    de = a->defer_new(a, dcb, NULL);
    fail_if(!de);

    te = a->time_new(a, pa_timeval_rtstore(&tv, pa_rtclock_now() + 2 * PA_USEC_PER_SEC, true), tcb, NULL);

#if defined(GLIB_MAIN_LOOP)
    g_main_loop_run(glib_main_loop);
#else
    pa_mainloop_run(m, NULL);
#endif

    a->time_free(te);
    a->defer_free(de);
    a->io_free(ioe);

#ifdef GLIB_MAIN_LOOP
    pa_glib_mainloop_free(g);
    g_main_loop_unref(glib_main_loop);
#else
    pa_mainloop_free(m);
#endif
}
END_TEST

int main(int argc, char *argv[]) {
    int failed = 0;
    Suite *s;
    TCase *tc;
    SRunner *sr;

    s = suite_create("MainLoop");
    tc = tcase_create("mainloop");
    tcase_add_test(tc, mainloop_test);
    suite_add_tcase(s, tc);

    sr = srunner_create(s);
    srunner_run_all(sr, CK_NORMAL);
    failed = srunner_ntests_failed(sr);
    srunner_free(sr);

    return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}


---
id: version-5.1.0-integration
title: Integration-test
sidebar_label: Integration
original_id: integration
---

We provide a simple package called [hemera-testsuite](https://github.com/hemerajs/hemera-testsuite) to start a NATS Server programmatically.

### Prerequisites

- Installed NATS Server, included in the user `PATH` environment variable.

```js
const server = HemeraTestsuite.start_server(PORT, done)
server.kill()
```

## Example mocha test

```js
describe('Basic', function() {
  const PORT = 6242
  const natsUrl = 'nats://localhost:' + PORT
  let server

  // Start up our own nats-server
  before(function(done) {
    server = HemeraTestsuite.start_server(PORT, done)
  })

  // Shutdown our server after we are done
  after(function() {
    server.kill()
  })

  it('Should send and receive', function(done) {
    const nats = require('nats').connect(natsUrl)
    const hemera = new Hemera(nats)

    hemera.ready(() => {
      hemera.add(
        {
          topic: 'math',
          cmd: 'add'
        },
        (resp, cb) => {
          cb(null, resp.a.number + resp.b.number)
        }
      )
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).not.to.be.exists()
          expect(resp).to.be.equals(3)
          hemera.close(done)
        }
      )
    })
  })
})
```


{{ 'create_new_stuff'|_ }}

{{ 'new_withdrawal'|_ }}

{{ 'new_deposit'|_ }}

{{ 'new_transfer'|_ }}

{{ 'new_asset_account'|_ }}

{{ 'new_expense_account'|_ }}

{{ 'new_revenue_account'|_ }}

{{ 'new_liabilities_account'|_ }}

{{ 'new_budget'|_ }}

{{ 'new_category'|_ }}

{{ 'new_piggy_bank'|_ }}

{{ 'new_bill'|_ }}

{{ 'new_rule'|_ }}

{{ 'new_recurring_transaction'|_ }}


// == WritableTestBase
// == WritableTestBase-Deserialize
import java.io.*;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.util.StringUtils;

public class WritableTestBase {

  // vv WritableTestBase
  public static byte[] serialize(Writable writable) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataOut = new DataOutputStream(out);
    writable.write(dataOut);
    dataOut.close();
    return out.toByteArray();
  }
  // ^^ WritableTestBase

  // vv WritableTestBase-Deserialize
  public static byte[] deserialize(Writable writable, byte[] bytes)
      throws IOException {
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    DataInputStream dataIn = new DataInputStream(in);
    writable.readFields(dataIn);
    dataIn.close();
    return bytes;
  }
  // ^^ WritableTestBase-Deserialize

  public static String serializeToString(Writable src) throws IOException {
    return StringUtils.byteToHexString(serialize(src));
  }

  public static String writeTo(Writable src, Writable dest) throws IOException {
    byte[] data = deserialize(dest, serialize(src));
    return StringUtils.byteToHexString(data);
  }

}


Performance Co-Pilot shping PMDA for General Performance Monitoring
===================================================================

This PMDA is designed to be configurable to monitor elapsed time and
CPU time (user and system) for arbitrary applications that can be run
from the Bourne shell.  Each application is assumed to run to completion
to probe or ping a particular service or dimension of system performance.

The metrics exported from the shping PMDA may be used to quantify of
service or service availability for both critical system services and
tasks that well correlated to performance as perceived by end-users.

The sample configuration file includes examples to "ping":

    + sh(1) start up and exit
    + a simple task, date(1)
    + sum(1) for some simple user-mode computation
    + compilation and execution of an antipodean variant of the
      generic "hullo world" C program
    + DNS (default server, trivial and error cases)
    + yp service via ypcat(1)
    + rpcinfo(1) for RPC registration from portmap/rpcbind
    + mail delivery (telnet tcp port 25)
    + Usenet news from nntp (telnet tcp port 119)

Metrics
=======

The file ./help contains descriptions for all of the metrics exported
by this PMDA.

Once the PMDA has been installed, the following command will list all
the available metrics and their explanatory "help" text:

	$ pminfo -fT shping

Installation of the shping PMDA
===============================

 +  # cd $PCP_PMDAS_DIR/shping

 +  Check that there is no clash with the Performance Metrics Domain
    number defined in ./domain.h and the other PMDAs currently in use
    (see $PCP_PMCDCONF_PATH).  If there is, edit ./domain.h and choose
    another domain number.

 +  Then run the Install script (as root)

	# ./Install

    and choose both the "collector" and "monitor" installation
    configuration options.

    Answer the questions, which include the option to specify new or
    alternate commands to be run.  See $PCP_PMDAS_DIR/shping/sample.conf
    for example specifications of commands.

De-installation
===============

 +  Simply use

	# cd $PCP_PMDAS_DIR/shping
	# ./Remove

Changing the settings
=====================

The cycle time and timeout period can be dynamically modified using
pmstore(1) for the metrics shping.control.cycletime and
shping.control.timeout respectively.

To make permanent changes, re-run the Install script.

Troubleshooting
===============

 +  After installing or restarting the agent, the PMCD log file
    ($PCP_LOG_DIR/pmcd/pmcd.log) and the PMDA log file
    ($PCP_LOG_DIR/pmcd/shping.log) should be checked for any warnings
    or errors.

 +  If the Install script reports some warnings when checking the
    metrics, the problem should be listed in one of the log files.

 +  Additional information can be logged if there appears to be
    problems.  The PCP application debug flags will cause the PMDA to
    report additional information in $PCP_LOG_DIR/pmcd/shping.log.  For
    details about the agent's debug flags, use the comand

	$ pminfo -T shping.control.debug


<?xml version="1.0"?>
<ZopeData>
  <record id="1" aka="AAAAAAAAAAE=">
    <pickle>
      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
    </pickle>
    <pickle>
      <dictionary>
        <item>
            <key> <string>delegated_list</string> </key>
            <value>
              <list>
                <string>default</string>
                <string>extra</string>
                <string>items</string>
                <string>title</string>
              </list>
            </value>
        </item>
        <item>
            <key> <string>id</string> </key>
            <value> <string>your_classification</string> </value>
        </item>
        <item>
            <key> <string>message_values</string> </key>
            <value>
              <dictionary>
                <item>
                    <key> <string>external_validator_failed</string> </key>
                    <value> <string>The input failed the external validator.</string> </value>
                </item>
              </dictionary>
            </value>
        </item>
        <item>
            <key> <string>overrides</string> </key>
            <value>
              <dictionary>
                <item>
                    <key> <string>field_id</string> </key>
                    <value> <string></string> </value>
                </item>
                <item>
                    <key> <string>form_id</string> </key>
                    <value> <string></string> </value>
                </item>
                <item>
                    <key> <string>target</string> </key>
                    <value> <string></string> </value>
                </item>
              </dictionary>
            </value>
        </item>
        <item>
            <key> <string>tales</string> </key>
            <value>
              <dictionary>
                <item>
                    <key> <string>default</string> </key>
                    <value>
                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
                    </value>
                </item>
                <item>
                    <key> <string>extra</string> </key>
                    <value> <string></string> </value>
                </item>
                <item>
                    <key> <string>field_id</string> </key>
                    <value> <string></string> </value>
                </item>
                <item>
                    <key> <string>form_id</string> </key>
                    <value> <string></string> </value>
                </item>
                <item>
                    <key> <string>items</string> </key>
                    <value>
                      <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
                    </value>
                </item>
                <item>
                    <key> <string>target</string> </key>
                    <value> <string></string> </value>
                </item>
                <item>
                    <key> <string>title</string> </key>
                    <value> <string></string> </value>
                </item>
              </dictionary>
            </value>
        </item>
        <item>
            <key> <string>values</string> </key>
            <value>
              <dictionary>
                <item>
                    <key> <string>default</string> </key>
                    <value> <string></string> </value>
                </item>
                <item>
                    <key> <string>extra</string> </key>
                    <value> <string>style="margin-bottom:10px;"</string> </value>
                </item>
                <item>
                    <key> <string>field_id</string> </key>
                    <value> <string>my_list_field</string> </value>
                </item>
                <item>
                    <key> <string>form_id</string> </key>
                    <value> <string>Base_viewIngestionFieldLibrary</string> </value>
                </item>
                <item>
                    <key> <string>items</string> </key>
                    <value>
                      <list/>
                    </value>
                </item>
                <item>
                    <key> <string>target</string> </key>
                    <value> <string>Click to edit the target</string> </value>
                </item>
                <item>
                    <key> <string>title</string> </key>
                    <value> <string>Classification</string> </value>
                </item>
              </dictionary>
            </value>
        </item>
      </dictionary>
    </pickle>
  </record>
  <record id="2" aka="AAAAAAAAAAI=">
    <pickle>
      <tuple>
        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
        <tuple/>
      </tuple>
    </pickle>
    <pickle>
      <dictionary>
        <item>
            <key> <string>_text</string> </key>
            <value> <string>python: here.portal_preferences.getPreferredDocumentClassification()</string> </value>
        </item>
      </dictionary>
    </pickle>
  </record>
  <record id="3" aka="AAAAAAAAAAM=">
    <pickle>
      <tuple>
        <global name="TALESMethod" module="Products.Formulator.TALESField"/>
        <tuple/>
      </tuple>
    </pickle>
    <pickle>
      <dictionary>
        <item>
            <key> <string>_text</string> </key>
            <value> <string>python: here.portal_categories.classification.getCategoryChildLogicalPathItemList(display_none_category=1,filter_node=1,local_sort_id=\'title\',checked_permission=\'View\')</string> </value>
        </item>
      </dictionary>
    </pickle>
  </record>
</ZopeData>