text:
<?php

namespace Bootstrap\Components\AppzioUiKit\Controls;

use Bootstrap\Components\BootstrapComponent;

trait uiKitHierarchicalCategories
{

    public $current_category_info;
    public $submit_click;
    public $tab;

    /**
     * Takes a specially formatted array to display a hierarchical, collapsible
     * list up to four levels. See actionMitems > Categories traig for more clues on formatting
     * the array. This component will submit only single item and close the popup on selection.
     *
     * Note that the final ordering of the elements happens here in the component, so the
     * model can send the results in any order.
     *
     * @param $categories
     * @param $onclick
     * Onclick the submit upon selection.
     * @return mixed
     */

    public function uiKitHierarchicalCategories($categories,$onclick_save_route=false,$tab=false)
    {

        $cachename = $this->model->appid .'-hierarchical-categories';
        $cache = \Appcaching::getGlobalCache($cachename);

        if(isset($cache['time']) AND $cache['time'] + 1200 > time()){
            return $cache['contents'];
        }

        $this->submit_click = $onclick_save_route;
        $this->tab = $tab;

        if($tab){
            $this->current_category_info['id'] = 0;
            $out = $this->uiKitHierarchicalCategoriesGetRow('{#no_category_filtering#}', '');
            $out[] = $this->getComponentSpacer('10');
        }

        foreach($categories as $category) {

            $this->current_category_info = $category;

            if (empty($category['parents'])) {
                $out[] = $this->uiKitHierarchicalCategoriesMainLevel($category['title'], $category['id']);

                if(!empty($category['children'])) {
                    foreach ($category['children'] as $child) {
                        $this->current_category_info = $categories[$child];
                        $out[] = $this->uiKitHierarchicalCategoriesSecondLevel($this->current_category_info['title'], $this->current_category_info['id'], $this->current_category_info['parent_id']);

                        if ($this->current_category_info['children']) {
                            $thirdlevel = $this->current_category_info['children'];

                            foreach ($thirdlevel as $thirdchild) {
                                $this->current_category_info = $categories[$thirdchild];
                                $out[] = $this->uiKitHierarchicalCategoriesThirdLevel($this->current_category_info['title'], $this->current_category_info['id'], $this->current_category_info['parent_id']);

                                $fourthlevel = $this->current_category_info['children'];
                                if (!empty($fourthlevel)) {
                                    foreach ($fourthlevel as $fourthchild) {
                                        $this->current_category_info = $categories[$fourthchild];
                                        $out[] = $this->uiKitHierarchicalCategoriesFourthLevel($this->current_category_info['title'], $this->current_category_info['id'], $this->current_category_info['parent_id']);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if(isset($out)){
            $output = $this->getComponentColumn($out);
            $cache['contents'] = $output;
            $cache['time'] = time();
            \Appcaching::setGlobalCache($cachename,$cache,1200);
            return $output;
        } else {
            return $this->getComponentText('{#no_categories_found#}',array('style' => 'ukit_hierarchical_firstlevel'));
        }

    }

    private function uiKitHierarchicalCategoriesOnclicks($id,$state='collapsed',$firstlevel=false){

        if($state == 'collapsed'){
            $onclick[] = $this->getOnclickShowElement($id.'_expanded',array('transition' => 'none'));
            $onclick[] = $this->getOnclickHideElement($id.'_collapsed',array('transition' => 'none'));

            if($this->current_category_info['children']){
                $onclick[] = $this->getOnclickShowElement('sub_'.$id.'_*',array('transition' => 'none'));
                $onclick[] = $this->getOnclickShowElement('subcollapsed_'.$id.'_*',array('transition' => 'none'));
            }
        } else {
            $onclick[] = $this->getOnclickHideElement($id.'_expanded',array('transition' => 'none'));
            $onclick[] = $this->getOnclickShowElement($id.'_collapsed',array('transition' => 'none'));

            if($this->current_category_info['all_children']){
                $onclick[] = $this->getOnclickHideElement('sub_'.$id.'_*',array('transition' => 'none'));
                $onclick[] = $this->getOnclickHideElement('subexpanded_'.$id.'_*',array('transition' => 'none'));
            }
        }

        return $onclick;
    }

    private function uiKitHierarchicalCategoriesGetRow($name,$icon,$level='first'){
        if($level == 'first'){
            $out[] = $this->uiKitDivider();
        }

        $id = $this->current_category_info['id'];

        $var = $this->model->getVariableId('category_name') ? $this->model->getVariableId('category_name') : '';

        $params = array();
        $styles = array();

        $row[] = $this->getComponentText($name,array('style' => 'ukit_hierarchical_'.$level.'level'));

        if(empty($this->current_category_info['children'])){
            $params['onclick'][] = $this->getOnclickSubmit($this->submit_click.$id);

            if($this->tab){
                $params['onclick'][] = $this->getOnclickTab(1);
                if($var){
                    $params['onclick'][] = $this->getOnclickSetVariables(array($var => $this->model->getCategoryPath($id)));
                }
            } else {
                $params['onclick'][] = $this->getOnclickClosePopup();
            }

            $row[] = $this->getComponentImage('uikit_selector_green_icon.png',array('style' => 'ukit_selector_arror'));
        } else {
            $row[] = $this->getComponentImage($icon,array('style' => 'ukit_selector_arror'));
        }

        if($level == 'first'){
            $styles['background-color'] = '#E1E4E3';
        }

        $out[] = $this->getComponentRow($row,$params,$styles);

        switch($level){
            case 'first':
                $out[] = $this->uiKitDivider();
                break;

            case 'second':
                $out[] = $this->getComponentText('',array(),array('parent_style' => 'uikit_divider','margin' => '0 0 0 45'));
                break;

            case 'third':
                $out[] = $this->getComponentText('',array(),array('parent_style' => 'uikit_divider','margin' => '0 0 0 45'));
                break;

            case 'fourth':
                $out[] = $this->getComponentText('',array(),array('parent_style' => 'uikit_divider','margin' => '0 0 0 60'));
                break;
        }
        return $out;

    }

    private function uiKitHierarchicalCategoriesMainLevel($name,$id){

        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-fwd.png');

        $output[] = $this->getComponentColumn($out,array(
            'id' => $id.'_collapsed',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id,'collapsed',true)));

        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-down.png');

        $output[] = $this->getComponentColumn($out,array(
            'id' => $id.'_expanded',
            'visibility' => 'hidden',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id,'expanded',true)));

        return $this->getComponentColumn($output,array(),array('margin' => '0 0 1 0'));
    }

    private function uiKitHierarchicalCategoriesSecondLevel($name,$id,$parent_id){
        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-fwd.png','second');

        $output[] = $this->getComponentColumn($out,array(
            'id' => 'subcollapsed_'.$parent_id.'_'.$id.'_collapsed',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id)));

        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-down.png','second');

        $output[] = $this->getComponentColumn($out,array(
            'id' => 'subexpanded_'.$parent_id.'_'.$id.'_expanded',
            'visibility' => 'hidden',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id,'expanded')));

        return $this->getComponentColumn($output,array('id' => 'sub_'.$parent_id.'_'.$id,'visibility' => 'hidden'));

    }
    private function uiKitHierarchicalCategoriesThirdLevel($name,$id,$parent_id){
        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-fwd.png','third');

        $output[] = $this->getComponentColumn($out,array(
            'id' => $id.'_collapsed',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id)));

        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-down.png','third');

        $output[] = $this->getComponentColumn($out,array(
            'id' => $id.'_expanded',
            'visibility' => 'hidden',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id,'expanded')));

        return $this->getComponentColumn($output,array('id' => $id,'visibility' => 'hidden'));

    }
    private function uiKitHierarchicalCategoriesFourthLevel($name,$id,$parent_id){
        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-fwd.png','fourth');

        $output[] = $this->getComponentColumn($out,array(
            'id' => $id.'_collapsed',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id)));

        $out = $this->uiKitHierarchicalCategoriesGetRow($name,'formkit-selector-arrow-down.png','fourth');

        $output[] = $this->getComponentColumn($out,array(
            'id' => $id.'_expanded',
            'visibility' => 'hidden',
            'onclick' => $this->uiKitHierarchicalCategoriesOnclicks($id,'expanded')));

        return $this->getComponentColumn($output,array('id' => $id,'visibility' => 'hidden'));

    }

}


text:
// Copyright 2009 the Sputnik authors.  All rights reserved.
/**
 * When the [[Call]] property for a Function object F is called, the following steps are taken:
 * 2. Evaluate F's FunctionBody;
 * if Result.type is thrown then Result.value is thrown too
 *
 * @path ch13/13.2/S13.2.1_A8_T1.js
 * @description Throwing an exception within a function body. Declaring function with "function __func()"
 */

function __func(){
    var x = 1;
    throw ("Catch Me If You Can")
    return x;
}

try{
    var x=__func()
    $ERROR('#0: var x=__func() lead to throwing exception');
} catch(e){
    if (e !== "Catch Me If You Can") {
    	$ERROR('#1: Exception === "Catch Me If You Can". Actual: exception ==='+e);
    }
}

redpajama_set_name: RedPajamaGithub


text:
#ifndef MITKBASERENDERERHELPER_H
#define MITKBASERENDERERHELPER_H

#include <mitkBaseRenderer.h>
#include <mitkTimeGeometry.h>

namespace mitk
{
  namespace BaseRendererHelper
  {
    /*
     * \brief
     */
    MITKCORE_EXPORT bool IsRendererAlignedWithSegmentation(BaseRenderer* renderer, const TimeGeometry* timeGeometry);

  } // namespace BaseRendererHelper
} // namespace mitk

#endif // MITKBASERENDERERHELPER_H


text:
import {SlideshowComponent} from './slideshow.component';
import {ComponentFixture, getTestBed, TestBed} from '@angular/core/testing';
import {CommonModule} from '@angular/common';
import {TruncateModule} from 'ng2-truncate';
import {StoreModule} from '@ngrx/store';
import {READY, SLIDING, stateReducer} from '../reducers/loading-state.reducer';
import {INCREMENT, indexReducer, RESET} from '../reducers/offset-state.reducer';
import * as Immutable from 'immutable';
import 'hammerjs';
import {NgZone} from '@angular/core';
import {SLIDE_DIRECTION} from '../enums/slide-direction.enum';
import {EVENT} from '../enums/slideshow-event.enum';
import {DOM_CLASSES} from '../enums/dom-classes.enum';
import {SWIPE_ACTION} from '../enums/swipe-action.enum';

const getDebugSlideList = function(howMany = 3, activeIndex = 0) {
  const debugList = document.createDocumentFragment();
  const list = document.createElement('ul');
  let li: HTMLElement;

  for (let i = 0; i < howMany; i++) {
    li = document.createElement('li');

    if (i === activeIndex) {
      li.className = 'active';
      li.id = 'slide-' + i;
    }

    list.appendChild(li);
  }

  debugList.appendChild(list);

  return debugList;
};

const getThumbnailList = function(howMany = 3, activeIndex = 0, left = 0, page = 1) {
  const debugList = document.createDocumentFragment();
  const container = document.createElement('div');
  container.className = 'thumbnails';
  const list = document.createElement('ul');
  let li: HTMLElement;
  const maskElement = document.createElement('div');
  maskElement.classList.add('gradient-mask');

  for (let i = 0; i < howMany; i++) {
    li = document.createElement('li');

    if (i === activeIndex) {
      li.className = 'active';
      li.id = 'thumbnail-' + i;
    }

    list.appendChild(li);
  }

  list.setAttribute('data-left', '' + left);
  list.setAttribute('data-page', '' + page);

  container.appendChild(list);
  container.appendChild(maskElement);
  debugList.appendChild(container);

  return debugList;
};

describe('SlideshowComponent', () => {

  let component: SlideshowComponent;
  let fixture: ComponentFixture<SlideshowComponent>;
  let zone: NgZone;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        CommonModule,
        TruncateModule,
        StoreModule.provideStore({state: stateReducer, index: indexReducer})
      ],
      declarations: [SlideshowComponent]
    });

    fixture = TestBed.createComponent(SlideshowComponent);
    component = fixture.componentInstance;
    zone = getTestBed().get(NgZone);
  });

  describe('Component', () => {

    it('it should implement AfterViewChecked', () => {
      const spy = spyOn(component, 'ngAfterViewChecked').and.returnValue('');
      fixture.detectChanges();
      expect(spy).toHaveBeenCalled();
    });

  });

  describe('Inputs', () => {

    it('it should accept an immutable list as the source for the images', () => {
      component.images = Immutable.List([]);
      expect(component.images.count()).toBe(0);
    });

    it('it should accept an immutable map as the options for the slideshow', () => {
      component.options = Immutable.Map({dummy: 0});
      expect(component.options.get('dummy')).toBe(0);
    });

  });

  describe('Methods', () => {

    describe('ngAfterViewChecked', () => {

      it('it should initialize the thumbnail container if that option is active', () => {
        const spy = spyOn(component, 'initializeThumbnailContainer').and.returnValue('');
        component.options = Immutable.Map({
          'showThumbnails': true
        });
        fixture.detectChanges();
        expect(spy).toHaveBeenCalled();
      });

      it('it should not initialize the thumbnail container if that option is not active', () => {
        const spy = spyOn(component, 'initializeThumbnailContainer').and.returnValue('');
        component.options = Immutable.Map({
          'showThumbnails': false
        });
        fixture.detectChanges();
        expect(spy).not.toHaveBeenCalled();
      });

    });

    describe('moveSlide', () => {

      it('it should prevent default action in case event is available', () => {
        const spyZone = spyOn(zone, 'runOutsideAngular').and.returnValue('');
        const event = new Event('click');
        const spyEvent = spyOn(event, 'preventDefault').and.returnValue('');
        component.moveSlide('', event);
        expect(spyEvent).toHaveBeenCalled();
      });

      it('it should perform the slide action outside of the angular zone', () => {
        const spyZone = spyOn(zone, 'runOutsideAngular').and.returnValue('');
        component.moveSlide('');
        expect(spyZone).toHaveBeenCalled();
      });

      it('it should not change status if current status is sliding', () => {
        const spyState = spyOn(component.loadingStateSubscription, 'dispatch').and.returnValue('');
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList());
        component.loadingStatus = SLIDING;
        component.moveSlide('');

        expect(spyState).not.toHaveBeenCalled();
      });

      it('it should throw an error when there is not an active element', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, -1));
        expect(() => component.moveSlide('')).toThrowError();
      });

      it('it should not slide if current status is on sliding', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        component.loadingStatus = SLIDING;
        const activeElement = fixture.debugElement.nativeElement.querySelector('li.active');

        component.moveSlide('');

        const newActiveElement = fixture.debugElement.nativeElement.querySelector('li.active');
        expect(activeElement.id).toBe(newActiveElement.id);
      });

      it('it should not slide if active element does not have any siblings', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        component.loadingStatus = SLIDING;
        const activeElement = fixture.debugElement.nativeElement.querySelector('li.active');

        component.moveSlide('');

        const newActiveElement = fixture.debugElement.nativeElement.querySelector('li.active');
        expect(activeElement.id).toBe(newActiveElement.id);
      });

      it('it should slide to next slide when direction is set to be next', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));
        const activeElement = fixture.debugElement.nativeElement.querySelector('li.active');
        const nextElement = activeElement.nextElementSibling;

        component.moveSlide(SLIDE_DIRECTION.NEXT);

        expect(activeElement.id).not.toBe(nextElement.id);
      });

      it('it should slide to previous slide when direction is set to be previous', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        const activeElement = fixture.debugElement.nativeElement.querySelector('li.active');
        const previousElement = activeElement.previousElementSibling;

        component.moveSlide(SLIDE_DIRECTION.PREVIOUS);

        expect(activeElement.id).not.toBe(previousElement.id);
      });

      it('it should set slideshow status to SLIDING', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        component.moveSlide(SLIDE_DIRECTION.PREVIOUS);

        expect(component.loadingStatus).toBe(SLIDING);
      });

      it('it should increment offset when direction is set to be next', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));
        const currentOffset = component.offsetStatus;
        component.moveSlide(SLIDE_DIRECTION.NEXT);

        expect(component.offsetStatus).toBe(currentOffset + 1);
      });

      it('it should decrement offset when direction is set to be previous', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        const currentOffset = component.offsetStatus;
        component.moveSlide(SLIDE_DIRECTION.PREVIOUS);

        expect(component.offsetStatus).toBe(currentOffset - 1);
      });

      it('it should emit a next status event when direction is set to be next', () => {
        const spy = spyOn(component.eventDispatcher, 'emit').and.returnValue('');
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));

        component.moveSlide(SLIDE_DIRECTION.NEXT);

        const res = spy.calls.allArgs().filter((args) => args[0] && args[0].label && args[0].label === EVENT.SLIDE_NEXT);

        expect(res.length).toBeGreaterThan(0);
      });

      it('it should emit a previous status event when direction is set to be previous', () => {
        const spy = spyOn(component.eventDispatcher, 'emit').and.returnValue('');
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        component.moveSlide(SLIDE_DIRECTION.PREVIOUS);

        const res = spy.calls.allArgs().filter((args) => args[0] && args[0].label && args[0].label === EVENT.SLIDE_PREVIOUS);

        expect(res.length).toBeGreaterThan(0);
      });

    });

    describe('onActiveTransitionEnd', () => {

      it('it should clear active element outside of the angular zone', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));
        const activeElement = fixture.debugElement.nativeElement.querySelector('li.' + DOM_CLASSES.ACTIVE);
        activeElement.classList.add(DOM_CLASSES.LEFT);
        const spyZone = spyOn(zone, 'runOutsideAngular').and.callThrough();
        const event = new Event('click');

        component.onActiveTransitionEnd(event);

        expect(spyZone).toHaveBeenCalled();
        expect(activeElement.classList.contains(DOM_CLASSES.LEFT)).toBeFalsy();
      });

      it('it should clear next element if exists one', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));
        const activeElement = fixture.debugElement.nativeElement.querySelector('li.' + DOM_CLASSES.ACTIVE).nextElementSibling;
        activeElement.classList.add(DOM_CLASSES.LEFT);
        const spyZone = spyOn(zone, 'runOutsideAngular').and.callThrough();
        const event = new Event('click');

        component.onActiveTransitionEnd(event);

        expect(spyZone).toHaveBeenCalled();
        expect(activeElement.classList.contains(DOM_CLASSES.LEFT)).toBeFalsy();
      });

      it('it should clear previous element if exists one', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        const activeElement = fixture.debugElement.nativeElement.querySelector('li.' + DOM_CLASSES.ACTIVE).previousElementSibling;
        activeElement.classList.add(DOM_CLASSES.RIGHT);
        const spyZone = spyOn(zone, 'runOutsideAngular').and.callThrough();
        const event = new Event('click');

        component.onActiveTransitionEnd(event);

        expect(spyZone).toHaveBeenCalled();
        expect(activeElement.classList.contains(DOM_CLASSES.RIGHT)).toBeFalsy();
      });

      it('it should emit a transition complete event on complete', () => {
        const spy = spyOn(component.eventDispatcher, 'emit').and.returnValue('');
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        const event = new Event('click');

        component.onActiveTransitionEnd(event);

        const res = spy.calls.allArgs().filter((args) => args[0] && args[0].label && args[0].label === EVENT.ACTIVE_TRANSITION_COMPLETE);

        expect(res.length).toBeGreaterThan(0);
      });

      it('it should set loading state to ready on complete', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        const event = new Event('click');
        component.onActiveTransitionEnd(event);
        expect(component.loadingStatus).toBe(READY);
      });

      it('it should throw an error when there is not an active element', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, -1));
        const event = new Event('click');
        expect(() => component.onActiveTransitionEnd(event)).toThrowError();
      });

    });

    describe('swipe', () => {

      it('it should move to previous slide when swipe is to right', () => {
        const spy = spyOn(component, 'moveSlide').and.returnValue('');
        component.swipe(SWIPE_ACTION.RIGHT);
        const res = spy.calls.allArgs().filter((args) => args[0] && args[0] === SLIDE_DIRECTION.PREVIOUS);
        expect(res.length).toBeGreaterThan(0);
      });

      it('it should move to next slide when swipe is to left', () => {
        const spy = spyOn(component, 'moveSlide').and.returnValue('');
        component.swipe(SWIPE_ACTION.LEFT);
        const res = spy.calls.allArgs().filter((args) => args[0] && args[0] === SLIDE_DIRECTION.NEXT);
        expect(res.length).toBeGreaterThan(0);
      });

      it('it should emit a swipe next event when swipe is to left', () => {
        const spy = spyOn(component.eventDispatcher, 'emit').and.returnValue('');
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        component.swipe(SWIPE_ACTION.LEFT);

        const res = spy.calls.allArgs().filter((args) => args[0] && args[0].label && args[0].label === EVENT.SWIPE_NEXT);

        expect(res.length).toBeGreaterThan(0);
      });

      it('it should emit a swipe previous event when swipe is to right', () => {
        const spy = spyOn(component.eventDispatcher, 'emit').and.returnValue('');
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        component.swipe(SWIPE_ACTION.RIGHT);

        const res = spy.calls.allArgs().filter((args) => args[0] && args[0].label && args[0].label === EVENT.SWIPE_PREVIOUS);

        expect(res.length).toBeGreaterThan(0);
      });

    });

    describe('getDomElement', () => {

      it('it should search for a cached version of the element', () => {
        const spy = spyOn(component.domElements, 'filter').and.returnValue('');
        component.getDomElement('.active');
        expect(spy).toHaveBeenCalled();
      });

      it('it should return the element when its on the cache', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        const spy = spyOn(component.domElements, 'push').and.callThrough();
        component.getDomElement('.active');
        component.getDomElement('.active');
        expect(spy.calls.count()).toBe(1);
      });

    });

    describe('showByIndex', () => {

      it('it should show an element given its index outside of the angular zone', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));
        const list =  fixture.debugElement.nativeElement.querySelectorAll('li');
        const spyZone = spyOn(zone, 'runOutsideAngular').and.callThrough();

        component.showByIndex(2);

        expect(spyZone).toHaveBeenCalled();
        expect(list[2].classList.contains(DOM_CLASSES.ACTIVE)).toBeTruthy();
      });

      it('it should move all elements previous to the active-to-be to the left', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));
        const list =  fixture.debugElement.nativeElement.querySelectorAll('li');

        component.showByIndex(2);

        expect(list[0].classList.contains(DOM_CLASSES.LEFT)).toBeTruthy();
        expect(list[1].classList.contains(DOM_CLASSES.LEFT)).toBeTruthy();
        expect(list[2].classList.contains(DOM_CLASSES.LEFT)).toBeFalsy();
      });

      it('it should move all elements next to the active-to-be to the right', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 2));
        const list =  fixture.debugElement.nativeElement.querySelectorAll('li');

        component.showByIndex(0);

        expect(list[0].classList.contains(DOM_CLASSES.RIGHT)).toBeFalsy();
        expect(list[1].classList.contains(DOM_CLASSES.RIGHT)).toBeTruthy();
        expect(list[2].classList.contains(DOM_CLASSES.RIGHT)).toBeTruthy();
      });

      it('it should reset offset state when index is bigger than current index', () => {
        const spy = spyOn(component.offsetStateSubscription, 'dispatch').and.returnValue('');
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(3, 0));

        component.showByIndex(1);

        const res = spy.calls.allArgs().filter((args) => args[0] && args[0].type && args[0].type === RESET);
        expect(res.length).toBeGreaterThan(0);
      });

      it('it should increment offset state as many as many left elements occur', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(6, 1));
        component.showByIndex(4);
        expect(component.offsetStatus).toBe(4);
      });

      it('it should decrement offset state as many as many right elements occur', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(6, 5));
        component.showByIndex(3);
        expect(component.offsetStatus).toBe(3);
      });

      it('it should replace active element', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(6, 3));
        const list =  fixture.debugElement.nativeElement.querySelectorAll('li');

        component.showByIndex(4);

        expect(list[2].classList.contains(DOM_CLASSES.ACTIVE)).toBeFalsy();
        expect(list[4].classList.contains(DOM_CLASSES.ACTIVE)).toBeTruthy();

        component.showByIndex(1);

        expect(list[4].classList.contains(DOM_CLASSES.ACTIVE)).toBeFalsy();
        expect(list[2].classList.contains(DOM_CLASSES.ACTIVE)).toBeFalsy();
        expect(list[1].classList.contains(DOM_CLASSES.ACTIVE)).toBeTruthy();
      });

      it('it should emit a slide in by index event', () => {
        fixture.debugElement.nativeElement.appendChild(getDebugSlideList(6, 3));
        const spy = spyOn(component.eventDispatcher, 'emit').and.returnValue('');

        component.showByIndex(4);

        const res = spy.calls.allArgs().filter((args) => args[0] && args[0].label && args[0].label === EVENT.SLIDE_IN_BY_INDEX);

        expect(res.length).toBeGreaterThan(0);
      });

    });

    describe('initializeThumbnailContainer', () => {

      it('it should throw an error when thumbnailWidth is not defined or is not a number', () => {
        expect(() => component.initializeThumbnailContainer()).toThrowError();
      });

      it('it should allow right scrolling when there more elements that fit the container', () => {
        fixture.debugElement.nativeElement.appendChild(getThumbnailList(6, 3));
        component.options = Immutable.Map({
          'showThumbnails': true,
          'thumbnailWidth': 2000000
        });
        component.images = Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        const parent = fixture.debugElement.nativeElement.querySelector('.thumbnails');

        component.initializeThumbnailContainer();

        expect(parent.classList.contains(DOM_CLASSES.NO_SCROLL_RIGHT)).toBeFalsy();
      });

      it('it should not allow right scrolling when there equal or less elements that fit the container', () => {
        fixture.debugElement.nativeElement.appendChild(getThumbnailList(1, 3));
        component.options = Immutable.Map({
          'showThumbnails': true,
          'thumbnailWidth': 1
        });
        component.images = Immutable.List([]);
        const parent = fixture.debugElement.nativeElement.querySelector('.thumbnails');

        component.initializeThumbnailContainer();

        expect(parent.classList.contains(DOM_CLASSES.NO_SCROLL_RIGHT)).toBeTruthy();
      });

    });

    describe('moveThumbnailsRight', () => {

      it('it should move thumbnails outside of the Angular zone', () => {
        const spyZone = spyOn(zone, 'runOutsideAngular').and.callThrough();
        fixture.debugElement.nativeElement.appendChild(getThumbnailList(15, 3));
        component.options = Immutable.Map({
          'showThumbnails': true,
          'thumbnailWidth': 20000000000
        });
        component.images = Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        const container = fixture.debugElement.nativeElement.querySelector('.thumbnails ul');
        container.style.left = '-100px';

        component.moveThumbnailsRight(container);

        expect(spyZone).toHaveBeenCalled();
        expect(parseInt(container.style.left, 10) > -100).toBeTruthy();
      });

      it('it should increase page number', () => {
        fixture.debugElement.nativeElement.appendChild(getThumbnailList(15, 3));
        component.options = Immutable.Map({
          'showThumbnails': true,
          'thumbnailWidth': 20000000000
        });
        component.images = Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        const container = fixture.debugElement.nativeElement.querySelector('.thumbnails ul');
        container.style.left = '-100px';

        component.moveThumbnailsRight(container);

        expect(parseInt(container.getAttribute('data-page'), 10)).toBe(2);
      });

    });

    describe('moveThumbnailsLeft', () => {

      it('it should move thumbnails outside of the Angular zone', () => {
        const spyZone = spyOn(zone, 'runOutsideAngular').and.callThrough();
        fixture.debugElement.nativeElement.appendChild(getThumbnailList(15, 3, -100, 3));
        component.options = Immutable.Map({
          'showThumbnails': true,
          'thumbnailWidth': 20000000000
        });
        component.images = Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        const container = fixture.debugElement.nativeElement.querySelector('.thumbnails ul');
        container.style.left = '0';

        component.moveThumbnailsLeft(container);

        expect(spyZone).toHaveBeenCalled();
        expect(parseInt(container.style.left, 10) < 0).toBeTruthy();
      });

      it('it should decrease page number', () => {
        fixture.debugElement.nativeElement.appendChild(getThumbnailList(15, 3, -100, 4));
        component.options = Immutable.Map({
          'showThumbnails': true,
          'thumbnailWidth': 20000000000
        });
        component.images = Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        const container = fixture.debugElement.nativeElement.querySelector('.thumbnails ul');
        container.style.left = '0';

        component.moveThumbnailsLeft(container);

        expect(parseInt(container.getAttribute('data-page'), 10)).toBe(3);
      });

    });

  });

});


text:
package org.apache.archiva.rest.services;

import org.apache.archiva.admin.model.RepositoryAdminException;
import org.apache.archiva.admin.model.admin.ArchivaAdministration;
import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.maven2.metadata.MavenMetadataReader;
import org.apache.archiva.maven2.model.Artifact;
import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.model.facets.AuditEvent;
import org.apache.archiva.metadata.model.maven2.MavenArtifactFacet;
import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.metadata.repository.MetadataRepositoryException;
import org.apache.archiva.metadata.repository.MetadataResolutionException;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.metadata.repository.RepositorySessionFactory;
import org.apache.archiva.model.ArchivaRepositoryMetadata;
import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.model.VersionedReference;
import org.apache.archiva.redback.authentication.AuthenticationResult;
import org.apache.archiva.redback.authorization.AuthorizationException;
import org.apache.archiva.redback.components.cache.Cache;
import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
import org.apache.archiva.redback.system.DefaultSecuritySession;
import org.apache.archiva.redback.system.SecuritySession;
import org.apache.archiva.redback.system.SecuritySystem;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManagerException;
import org.apache.archiva.redback.users.UserNotFoundException;
import org.apache.archiva.repository.ContentNotFoundException;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryNotFoundException;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.metadata.MetadataTools;
import org.apache.archiva.repository.metadata.RepositoryMetadataException;
import org.apache.archiva.repository.metadata.RepositoryMetadataWriter;
import org.apache.archiva.repository.scanner.RepositoryScanStatistics;
import org.apache.archiva.repository.scanner.RepositoryScanner;
import org.apache.archiva.repository.scanner.RepositoryScannerException;
import org.apache.archiva.repository.scanner.RepositoryScannerInstance;
import org.apache.archiva.rest.api.model.ArtifactTransferRequest;
import org.apache.archiva.rest.api.model.StringList;
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
import org.apache.archiva.rest.api.services.RepositoriesService;
import org.apache.archiva.scheduler.ArchivaTaskScheduler;
import org.apache.archiva.scheduler.indexing.maven.ArchivaIndexingTaskExecutor;
import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException;
import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler;
import org.apache.archiva.scheduler.repository.model.RepositoryTask;
import org.apache.archiva.security.ArchivaSecurityException;
import org.apache.archiva.security.common.ArchivaRoleConstants;
import org.apache.archiva.xml.XMLException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

/**
 * @author Olivier Lamy
 * @since 1.4-M1
 */
@Service("repositoriesService#rest")
public class DefaultRepositoriesService
    extends AbstractRestService
    implements RepositoriesService
{
    private Logger log = LoggerFactory.getLogger( getClass() );

    @Inject
    @Named(value = "taskExecutor#indexing")
    private ArchivaIndexingTaskExecutor archivaIndexingTaskExecutor;

    @Inject
    private RepositoryRegistry repositoryRegistry;

    @Inject
    private SecuritySystem securitySystem;

    @Inject
    @Named(value = "archivaTaskScheduler#repository")
    private ArchivaTaskScheduler<RepositoryTask> scheduler;

    @Inject
    private DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;

    @Inject
    @Named(value = "repositorySessionFactory")
    protected RepositorySessionFactory repositorySessionFactory;

    @Inject
    @Autowired(required = false)
    protected List<RepositoryListener> listeners = new ArrayList<RepositoryListener>();

    @Inject
    private RepositoryScanner repoScanner;

    /**
     * Cache used for namespaces
     */
    @Inject
    @Named(value = "cache#namespaces")
    private Cache<String, Collection<String>> namespacesCache;

    private List<ChecksumAlgorithm> algorithms = Arrays.asList(ChecksumAlgorithm.SHA256, ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 );

    @Override
    public Boolean scanRepository( String repositoryId, boolean fullScan )
    {
        return doScanRepository( repositoryId, fullScan );
    }

    @Override
    public Boolean alreadyScanning( String repositoryId )
    {
        // check queue first to make sure it doesn't get dequeued between calls
        if ( repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId ) )
        {
            return true;
        }
        for ( RepositoryScannerInstance scan : repoScanner.getInProgressScans() )
        {
            if ( scan.getRepository().getId().equals( repositoryId ) )
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public Boolean removeScanningTaskFromQueue( String repositoryId )
    {
        RepositoryTask task = new RepositoryTask();
        task.setRepositoryId( repositoryId );
        try
        {
            return repositoryTaskScheduler.unQueueTask( task );
        }
        catch ( TaskQueueException e )
        {
            log.error( "failed to unschedule scanning of repo with id {}", repositoryId, e );
            return false;
        }
    }

    private ManagedRepositoryContent getManagedRepositoryContent(String id) throws RepositoryException
    {
        org.apache.archiva.repository.ManagedRepository repo = repositoryRegistry.getManagedRepository( id );
        if (repo==null) {
            throw new RepositoryException( "Repository not found "+id );
        }
        return repo.getContent();
    }

    @Override
    public Boolean scanRepositoryNow( String repositoryId, boolean fullScan )
        throws ArchivaRestServiceException
    {

        try
        {

            org.apache.archiva.repository.ManagedRepository repository = repositoryRegistry.getManagedRepository( repositoryId );

            ArtifactIndexingTask task =
                new ArtifactIndexingTask( repository, null, ArtifactIndexingTask.Action.FINISH, repository.getIndexingContext() );

            task.setExecuteOnEntireRepo( true );
            task.setOnlyUpdate( !fullScan );

            archivaIndexingTaskExecutor.executeTask( task );

            scheduler.queueTask( new RepositoryTask( repositoryId, fullScan ) );

            return Boolean.TRUE;
        }
        catch ( Exception e )
        {
            log.error( e.getMessage(), e );
            throw new ArchivaRestServiceException( e.getMessage(), e );
        }
    }

    @Override
    public Boolean scheduleDownloadRemoteIndex( String repositoryId, boolean now, boolean fullDownload )
        throws ArchivaRestServiceException
    {
        try
        {
            downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, now, fullDownload );
        }
        catch ( DownloadRemoteIndexException e )
        {
            log.error( e.getMessage(), e );
            throw new ArchivaRestServiceException( e.getMessage(), e );
        }
        return Boolean.TRUE;
    }

    @Override
    public Boolean copyArtifact( ArtifactTransferRequest artifactTransferRequest )
        throws ArchivaRestServiceException
    {
        // check parameters
        String userName = getAuditInformation().getUser().getUsername();
        if ( StringUtils.isBlank( userName ) )
        {
            throw new ArchivaRestServiceException( "copyArtifact call: userName not found", null );
        }

        if ( StringUtils.isBlank( artifactTransferRequest.getRepositoryId() ) )
        {
            throw new ArchivaRestServiceException( "copyArtifact call: sourceRepositoryId cannot be null", null );
        }

        if ( StringUtils.isBlank( artifactTransferRequest.getTargetRepositoryId() ) )
        {
            throw new ArchivaRestServiceException( "copyArtifact call: targetRepositoryId cannot be null", null );
        }

        ManagedRepository source = null;
        source = repositoryRegistry.getManagedRepository( artifactTransferRequest.getRepositoryId() );

        if ( source == null )
        {
            throw new ArchivaRestServiceException(
                "cannot find repository with id " + artifactTransferRequest.getRepositoryId(), null );
        }

        ManagedRepository target = null;
        target = repositoryRegistry.getManagedRepository( artifactTransferRequest.getTargetRepositoryId() );

        if ( target == null )
        {
            throw new ArchivaRestServiceException(
                "cannot find repository with id " + artifactTransferRequest.getTargetRepositoryId(), null );
        }

        if ( StringUtils.isBlank( artifactTransferRequest.getGroupId() ) )
        {
            throw new ArchivaRestServiceException( "groupId is mandatory", null );
        }

        if ( StringUtils.isBlank( artifactTransferRequest.getArtifactId() ) )
        {
            throw new ArchivaRestServiceException( "artifactId is mandatory", null );
        }

        if ( StringUtils.isBlank( artifactTransferRequest.getVersion() ) )
        {
            throw new ArchivaRestServiceException( "version is mandatory", null );
        }

        if ( VersionUtil.isSnapshot( artifactTransferRequest.getVersion() ) )
        {
            throw new ArchivaRestServiceException( "copy of SNAPSHOT not supported", null );
        }

        // end check parameters

        User user = null;
        try
        {
            user = securitySystem.getUserManager().findUser( userName );
        }
        catch ( UserNotFoundException e )
        {
            throw new ArchivaRestServiceException( "user " + userName + " not found", e );
        }
        catch ( UserManagerException e )
        {
            throw new ArchivaRestServiceException( "ArchivaRestServiceException:" + e.getMessage(), e );
        }

        // check karma on source : read
        AuthenticationResult authn = new AuthenticationResult( true, userName, null );
        SecuritySession securitySession = new DefaultSecuritySession( authn, user );
        try
        {
            boolean authz =
                securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
                                             artifactTransferRequest.getRepositoryId() );
            if ( !authz )
            {
                throw new ArchivaRestServiceException(
                    "not authorized to access repo:" + artifactTransferRequest.getRepositoryId(), null );
            }
        }
        catch ( AuthorizationException e )
        {
            log.error( "error reading permission: {}", e.getMessage(), e );
            throw new ArchivaRestServiceException( e.getMessage(), e );
        }

        // check karma on target: write
        try
        {
            boolean authz =
                securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
                                             artifactTransferRequest.getTargetRepositoryId() );
            if ( !authz )
            {
                throw new ArchivaRestServiceException(
                    "not authorized to write to repo:" + artifactTransferRequest.getTargetRepositoryId(), null );
            }
        }
        catch ( AuthorizationException e )
        {
            log.error( "error reading permission: {}", e.getMessage(), e );
            throw new ArchivaRestServiceException( e.getMessage(), e );
        }

        // sounds good we can continue !

        ArtifactReference artifactReference = new ArtifactReference();
        artifactReference.setArtifactId( artifactTransferRequest.getArtifactId() );
        artifactReference.setGroupId( artifactTransferRequest.getGroupId() );
        artifactReference.setVersion( artifactTransferRequest.getVersion() );
        artifactReference.setClassifier( artifactTransferRequest.getClassifier() );
        String packaging = StringUtils.trim( artifactTransferRequest.getPackaging() );
        artifactReference.setType( StringUtils.isEmpty( packaging ) ? "jar" : packaging );

        try
        {

            ManagedRepositoryContent sourceRepository =
                getManagedRepositoryContent( artifactTransferRequest.getRepositoryId() );

            String artifactSourcePath = sourceRepository.toPath( artifactReference );

            if ( StringUtils.isEmpty( artifactSourcePath ) )
            {
                log.error( "cannot find artifact {}", artifactTransferRequest );
                throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString(),
                                                       null );
            }

            Path artifactFile = source.getLocalPath().resolve( artifactSourcePath );

            if ( !Files.exists(artifactFile) )
            {
                log.error( "cannot find artifact {}", artifactTransferRequest );
                throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString(),
                                                       null );
            }

            ManagedRepositoryContent targetRepository =
                getManagedRepositoryContent( artifactTransferRequest.getTargetRepositoryId() );

            String artifactPath = targetRepository.toPath( artifactReference );

            int lastIndex = artifactPath.lastIndexOf( '/' );

            String path = artifactPath.substring( 0, lastIndex );
            Path targetPath = target.getLocalPath().resolve( path );

            Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
            int newBuildNumber = 1;
            String timestamp = null;

            Path versionMetadataFile = targetPath.resolve( MetadataTools.MAVEN_METADATA );
            /* unused */ getMetadata( versionMetadataFile );

            if ( !Files.exists(targetPath) )
            {
                Files.createDirectories( targetPath );
            }

            String filename = artifactPath.substring( lastIndex + 1 );

            boolean fixChecksums =
                !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) );

            Path targetFile = targetPath.resolve( filename );
            if ( Files.exists(targetFile) && target.blocksRedeployments())
            {
                throw new ArchivaRestServiceException(
                    "artifact already exists in target repo: " + artifactTransferRequest.getTargetRepositoryId()
                        + " and redeployment blocked", null
                );
            }
            else
            {
                copyFile( artifactFile, targetPath, filename, fixChecksums );
                queueRepositoryTask( target.getId(), targetFile );
            }

            // copy source pom to target repo
            String pomFilename = filename;
            if ( StringUtils.isNotBlank( artifactTransferRequest.getClassifier() ) )
            {
                pomFilename = StringUtils.remove( pomFilename, "-" + artifactTransferRequest.getClassifier() );
            }
            pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";

            Path pomFile = source.getLocalPath().resolve(
                artifactSourcePath.substring( 0, artifactPath.lastIndexOf( '/' ) )).resolve( pomFilename );

            if ( pomFile != null && Files.size( pomFile ) > 0 )
            {
                copyFile( pomFile, targetPath, pomFilename, fixChecksums );
                queueRepositoryTask( target.getId(), targetPath.resolve( pomFilename ) );

            }

            // explicitly update only if metadata-updater consumer is not enabled!
            if ( !archivaAdministration.getKnownContentConsumers().contains( "metadata-updater" ) )
            {
                updateProjectMetadata( targetPath.toAbsolutePath().toString(), lastUpdatedTimestamp, timestamp, newBuildNumber,
                                       fixChecksums, artifactTransferRequest );

            }

            String msg =
                "Artifact \'" + artifactTransferRequest.getGroupId() + ":" + artifactTransferRequest.getArtifactId()
                    + ":" + artifactTransferRequest.getVersion() + "\' was successfully deployed to repository \'"
                    + artifactTransferRequest.getTargetRepositoryId() + "\'";
            log.debug("copyArtifact {}", msg);

        }
        catch ( RepositoryException e )
        {
            log.error( "RepositoryException: {}", e.getMessage(), e );
            throw new ArchivaRestServiceException( e.getMessage(), e );
        }
        catch ( RepositoryAdminException e )
        {
            log.error( "RepositoryAdminException: {}", e.getMessage(), e );
            throw new ArchivaRestServiceException( e.getMessage(), e );
        }
        catch ( IOException e )
        {
            log.error( "IOException: {}", e.getMessage(), e );
            throw new ArchivaRestServiceException( e.getMessage(), e );
        }
        return true;
    }

    private void queueRepositoryTask( String repositoryId, Path localFile )
    {
        RepositoryTask task = new RepositoryTask();
        task.setRepositoryId( repositoryId );
        task.setResourceFile( localFile );
        task.setUpdateRelatedArtifacts( true );
        //task.setScanAll( true );

        try
        {
            scheduler.queueTask( task );
        }
        catch ( TaskQueueException e )
        {
            log.error( "Unable to queue repository task to execute consumers on resource file ['{}"
                           + "'].", localFile.getFileName());
        }
    }

    private ArchivaRepositoryMetadata getMetadata( Path metadataFile )
        throws RepositoryMetadataException
    {
        ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
        if ( Files.exists(metadataFile) )
        {
            try
            {
                metadata = MavenMetadataReader.read( metadataFile );
            }
            catch ( XMLException e )
            {
                throw new RepositoryMetadataException( e.getMessage(), e );
            }
        }
        return metadata;
    }

    private Path getMetadata( String targetPath )
    {
        String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( FileSystems.getDefault().getSeparator() ));

        return Paths.get( artifactPath, MetadataTools.MAVEN_METADATA );
    }

    private void copyFile( Path sourceFile, Path targetPath, String targetFilename, boolean fixChecksums )
        throws IOException
    {
        Files.copy( sourceFile, targetPath.resolve( targetFilename ), StandardCopyOption.REPLACE_EXISTING,
                    StandardCopyOption.COPY_ATTRIBUTES );

        if ( fixChecksums )
        {
            fixChecksums( targetPath.resolve( targetFilename ) );
        }
    }

    private void fixChecksums( Path file )
    {
        ChecksummedFile checksum = new ChecksummedFile( file );
        checksum.fixChecksums( algorithms );
    }

    private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
                                        boolean fixChecksums, ArtifactTransferRequest artifactTransferRequest )
        throws RepositoryMetadataException
    {
        List<String> availableVersions = new ArrayList<>();
        String latestVersion = artifactTransferRequest.getVersion();

        Path projectDir = Paths.get( targetPath ).getParent();
        Path projectMetadataFile = projectDir.resolve( MetadataTools.MAVEN_METADATA );

        ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile );

        if ( Files.exists(projectMetadataFile) )
        {
            availableVersions = projectMetadata.getAvailableVersions();

            Collections.sort( availableVersions, VersionComparator.getInstance() );

            if ( !availableVersions.contains( artifactTransferRequest.getVersion() ) )
            {
                availableVersions.add( artifactTransferRequest.getVersion() );
            }

            latestVersion = availableVersions.get( availableVersions.size() - 1 );
        }
        else
        {
            availableVersions.add( artifactTransferRequest.getVersion() );

            projectMetadata.setGroupId( artifactTransferRequest.getGroupId() );
            projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId() );
        }

        if ( projectMetadata.getGroupId() == null )
        {
            projectMetadata.setGroupId( artifactTransferRequest.getGroupId() );
        }

        if ( projectMetadata.getArtifactId() == null )
        {
            projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId() );
        }

        projectMetadata.setLatestVersion( latestVersion );
        projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
        projectMetadata.setAvailableVersions( availableVersions );

        if ( !VersionUtil.isSnapshot( artifactTransferRequest.getVersion() ) )
        {
            projectMetadata.setReleasedVersion( latestVersion );
        }

        RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile);

        if ( fixChecksums )
        {
            fixChecksums( projectMetadataFile );
        }
    }

    @Override
    public Boolean removeProjectVersion( String repositoryId, String namespace, String projectId, String version )
        throws ArchivaRestServiceException
    {
        // if not a generic we can use the standard way to delete artifact
        if ( !VersionUtil.isGenericSnapshot( version ) )
        {
            Artifact artifact = new Artifact( namespace, projectId, version );
            artifact.setRepositoryId( repositoryId );
            artifact.setContext( repositoryId );
            return deleteArtifact( artifact );
        }

        if ( StringUtils.isEmpty( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "repositoryId cannot be null", 400, null );
        }

        if ( !isAuthorizedToDeleteArtifacts( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "not authorized to delete artifacts", 403, null );
        }

        if ( StringUtils.isEmpty( namespace ) )
        {
            throw new ArchivaRestServiceException( "groupId cannot be null", 400, null );
        }

        if ( StringUtils.isEmpty( projectId ) )
        {
            throw new ArchivaRestServiceException( "artifactId cannot be null", 400, null );
        }

        if ( StringUtils.isEmpty( version ) )
        {
            throw new ArchivaRestServiceException( "version cannot be null", 400, null );
        }

        RepositorySession repositorySession = repositorySessionFactory.createSession();

        try
        {
            ManagedRepositoryContent repository = getManagedRepositoryContent( repositoryId );

            VersionedReference ref = new VersionedReference();
            ref.setArtifactId( projectId );
            ref.setGroupId( namespace );
            ref.setVersion( version );

            repository.deleteVersion( ref );

            /*
            ProjectReference projectReference = new ProjectReference();
            projectReference.setGroupId( namespace );
            projectReference.setArtifactId( projectId );

            repository.getVersions(  )
            */

            ArtifactReference artifactReference = new ArtifactReference();
            artifactReference.setGroupId( namespace );
            artifactReference.setArtifactId( projectId );
            artifactReference.setVersion( version );

            MetadataRepository metadataRepository = repositorySession.getRepository();

            Set<ArtifactReference> related = repository.getRelatedArtifacts( artifactReference );
            log.debug( "related: {}", related );
            for ( ArtifactReference artifactRef : related )
            {
                repository.deleteArtifact( artifactRef );
            }

            Collection<ArtifactMetadata> artifacts =
                metadataRepository.getArtifacts( repositoryId, namespace, projectId, version );

            for ( ArtifactMetadata artifactMetadata : artifacts )
            {
                metadataRepository.removeArtifact( artifactMetadata, version );
            }

            metadataRepository.removeProjectVersion( repositoryId, namespace, projectId, version );
        }
        catch ( MetadataRepositoryException e )
        {
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        catch ( MetadataResolutionException e )
        {
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        catch ( RepositoryException e )
        {
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        finally
        {

            repositorySession.save();

            repositorySession.close();
        }

        return Boolean.TRUE;
    }

    @Override
    public Boolean deleteArtifact( Artifact artifact )
        throws ArchivaRestServiceException
    {

        String repositoryId = artifact.getContext();
        // some rest call can use context or repositoryId
        // so try both!!
        if ( StringUtils.isEmpty( repositoryId ) )
        {
            repositoryId = artifact.getRepositoryId();
        }
        if ( StringUtils.isEmpty( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "repositoryId cannot be null", 400, null );
        }

        if ( !isAuthorizedToDeleteArtifacts( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "not authorized to delete artifacts", 403, null );
        }

        if ( artifact == null )
        {
            throw new ArchivaRestServiceException( "artifact cannot be null", 400, null );
        }

        if ( StringUtils.isEmpty( artifact.getGroupId() ) )
        {
            throw new ArchivaRestServiceException( "artifact.groupId cannot be null", 400, null );
        }

        if ( StringUtils.isEmpty( artifact.getArtifactId() ) )
        {
            throw new ArchivaRestServiceException( "artifact.artifactId cannot be null", 400, null );
        }

        // TODO more control on artifact fields

        boolean snapshotVersion =
            VersionUtil.isSnapshot( artifact.getVersion() ) | VersionUtil.isGenericSnapshot( artifact.getVersion() );

        RepositorySession repositorySession = repositorySessionFactory.createSession();
        try
        {
            Date lastUpdatedTimestamp = Calendar.getInstance().getTime();

            TimeZone timezone = TimeZone.getTimeZone( "UTC" );
            DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
            fmt.setTimeZone( timezone );
            ManagedRepository repoConfig = repositoryRegistry.getManagedRepository( repositoryId );

            VersionedReference ref = new VersionedReference();
            ref.setArtifactId( artifact.getArtifactId() );
            ref.setGroupId( artifact.getGroupId() );
            ref.setVersion( artifact.getVersion() );

            ManagedRepositoryContent repository = getManagedRepositoryContent( repositoryId );

            ArtifactReference artifactReference = new ArtifactReference();
            artifactReference.setArtifactId( artifact.getArtifactId() );
            artifactReference.setGroupId( artifact.getGroupId() );
            artifactReference.setVersion( artifact.getVersion() );
            artifactReference.setClassifier( artifact.getClassifier() );
            artifactReference.setType( artifact.getPackaging() );

            MetadataRepository metadataRepository = repositorySession.getRepository();

            String path = repository.toMetadataPath( ref );

            if ( StringUtils.isNotBlank( artifact.getClassifier() ) )
            {
                if ( StringUtils.isBlank( artifact.getPackaging() ) )
                {
                    throw new ArchivaRestServiceException( "You must configure a type/packaging when using classifier",
                                                           400, null );
                }

                repository.deleteArtifact( artifactReference );

            }
            else
            {

                int index = path.lastIndexOf( '/' );
                path = path.substring( 0, index );
                Path targetPath = repoConfig.getLocalPath().resolve( path );

                if ( !Files.exists(targetPath) )
                {
                    //throw new ContentNotFoundException(
                    //    artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion() );
                    log.warn( "targetPath {} not found skip file deletion", targetPath );
                }

                // TODO: this should be in the storage mechanism so that it is all tied together
                // delete from file system
                if ( !snapshotVersion )
                {
                    repository.deleteVersion( ref );
                }
                else
                {
                    Set<ArtifactReference> related = repository.getRelatedArtifacts( artifactReference );
                    log.debug( "related: {}", related );
                    for ( ArtifactReference artifactRef : related )
                    {
                        repository.deleteArtifact( artifactRef );
                    }
                }
                Path metadataFile = getMetadata( targetPath.toAbsolutePath().toString() );
                ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );

                updateMetadata( metadata, metadataFile, lastUpdatedTimestamp, artifact );
            }
            Collection<ArtifactMetadata> artifacts = Collections.emptyList();

            if ( snapshotVersion )
            {
                String baseVersion = VersionUtil.getBaseVersion( artifact.getVersion() );
                artifacts =
                    metadataRepository.getArtifacts( repositoryId, artifact.getGroupId(), artifact.getArtifactId(),
                                                     baseVersion );
            }
            else
            {
                artifacts =
                    metadataRepository.getArtifacts( repositoryId, artifact.getGroupId(), artifact.getArtifactId(),
                                                     artifact.getVersion() );
            }

            log.debug( "artifacts: {}", artifacts );

            if ( artifacts.isEmpty() )
            {
                if ( !snapshotVersion )
                {
                    // verify metata repository doesn't contains anymore the version
                    Collection<String> projectVersions =
                        metadataRepository.getProjectVersions( repositoryId, artifact.getGroupId(),
                                                               artifact.getArtifactId() );

                    if ( projectVersions.contains( artifact.getVersion() ) )
                    {
                        log.warn( "artifact not found when deleted but version still here ! so force cleanup" );
                        metadataRepository.removeProjectVersion( repositoryId, artifact.getGroupId(),
                                                                 artifact.getArtifactId(), artifact.getVersion() );
                    }

                }
            }

            for ( ArtifactMetadata artifactMetadata : artifacts )
            {

                // TODO: mismatch between artifact (snapshot) version and project (base) version here
                if ( artifactMetadata.getVersion().equals( artifact.getVersion() ) )
                {
                    if ( StringUtils.isNotBlank( artifact.getClassifier() ) )
                    {
                        if ( StringUtils.isBlank( artifact.getPackaging() ) )
                        {
                            throw new ArchivaRestServiceException(
                                "You must configure a type/packaging when using classifier", 400, null );
                        }
                        // cleanup facet which contains classifier information
                        MavenArtifactFacet mavenArtifactFacet =
                            (MavenArtifactFacet) artifactMetadata.getFacet( MavenArtifactFacet.FACET_ID );

                        if ( StringUtils.equals( artifact.getClassifier(), mavenArtifactFacet.getClassifier() ) )
                        {
                            artifactMetadata.removeFacet( MavenArtifactFacet.FACET_ID );
                            String groupId = artifact.getGroupId(), artifactId = artifact.getArtifactId(), version =
                                artifact.getVersion();
                            MavenArtifactFacet mavenArtifactFacetToCompare = new MavenArtifactFacet();
                            mavenArtifactFacetToCompare.setClassifier( artifact.getClassifier() );
                            metadataRepository.removeArtifact( repositoryId, groupId, artifactId, version,
                                                               mavenArtifactFacetToCompare );
                            metadataRepository.save();
                        }

                    }
                    else
                    {
                        if ( snapshotVersion )
                        {
                            metadataRepository.removeArtifact( artifactMetadata,
                                                               VersionUtil.getBaseVersion( artifact.getVersion() ) );
                        }
                        else
                        {
                            metadataRepository.removeArtifact( artifactMetadata.getRepositoryId(),
                                                               artifactMetadata.getNamespace(),
                                                               artifactMetadata.getProject(), artifact.getVersion(),
                                                               artifactMetadata.getId() );
                        }
                    }
                    // TODO: move into the metadata repository proper - need to differentiate attachment of
                    //       repository metadata to an artifact
                    for ( RepositoryListener listener : listeners )
                    {
                        listener.deleteArtifact( metadataRepository, repository.getId(),
                                                 artifactMetadata.getNamespace(), artifactMetadata.getProject(),
                                                 artifactMetadata.getVersion(), artifactMetadata.getId() );
                    }

                    triggerAuditEvent( repositoryId, path, AuditEvent.REMOVE_FILE );
                }
            }
        }
        catch ( ContentNotFoundException e )
        {
            throw new ArchivaRestServiceException( "Artifact does not exist: " + e.getMessage(), 400, e );
        }
        catch ( RepositoryNotFoundException e )
        {
            throw new ArchivaRestServiceException( "Target repository cannot be found: " + e.getMessage(), 400, e );
        }
        catch ( RepositoryException e )
        {
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        catch ( MetadataResolutionException e )
        {
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        catch ( MetadataRepositoryException e )
        {
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        finally
        {

            repositorySession.save();

            repositorySession.close();
        }
        return Boolean.TRUE;
    }

    @Override
    public Boolean deleteGroupId( String groupId, String repositoryId )
        throws ArchivaRestServiceException
    {
        if ( StringUtils.isEmpty( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "repositoryId cannot be null", 400, null );
        }

        if ( !isAuthorizedToDeleteArtifacts( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "not authorized to delete artifacts", 403, null );
        }

        if ( StringUtils.isEmpty( groupId ) )
        {
            throw new ArchivaRestServiceException( "groupId cannot be null", 400, null );
        }

        RepositorySession repositorySession = repositorySessionFactory.createSession();

        try
        {
            ManagedRepositoryContent repository = getManagedRepositoryContent( repositoryId );

            repository.deleteGroupId( groupId );

            MetadataRepository metadataRepository = repositorySession.getRepository();

            metadataRepository.removeNamespace( repositoryId, groupId );

            // just invalidate cache entry
            String cacheKey = repositoryId + "-" + groupId;
            namespacesCache.remove( cacheKey );
            namespacesCache.remove( repositoryId );

            metadataRepository.save();
        }
        catch ( MetadataRepositoryException e )
        {
            log.error( e.getMessage(), e );
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        catch ( RepositoryException e )
        {
            log.error( e.getMessage(), e );
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        finally
        {

            repositorySession.close();
        }
        return true;
    }

    @Override
    public Boolean deleteProject( String groupId, String projectId, String repositoryId )
        throws ArchivaRestServiceException
    {
        if ( StringUtils.isEmpty( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "repositoryId cannot be null", 400, null );
        }

        if ( !isAuthorizedToDeleteArtifacts( repositoryId ) )
        {
            throw new ArchivaRestServiceException( "not authorized to delete artifacts", 403, null );
        }

        if ( StringUtils.isEmpty( groupId ) )
        {
            throw new ArchivaRestServiceException( "groupId cannot be null", 400, null );
        }

        if ( StringUtils.isEmpty( projectId ) )
        {
            throw new ArchivaRestServiceException( "artifactId cannot be null", 400, null );
        }

        RepositorySession repositorySession = repositorySessionFactory.createSession();

        try
        {
            ManagedRepositoryContent repository = getManagedRepositoryContent( repositoryId );

            repository.deleteProject( groupId, projectId );
        }
        catch ( ContentNotFoundException e )
        {
            log.warn( "skip ContentNotFoundException: {}", e.getMessage() );
        }
        catch ( RepositoryException e )
        {
            log.error( e.getMessage(), e );
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }

        try
        {

            MetadataRepository metadataRepository = repositorySession.getRepository();

            metadataRepository.removeProject( repositoryId, groupId, projectId );

            metadataRepository.save();
        }
        catch ( MetadataRepositoryException e )
        {
            log.error( e.getMessage(), e );
            throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 500, e );
        }
        finally
        {

            repositorySession.close();
        }
        return true;

    }

    @Override
    public Boolean isAuthorizedToDeleteArtifacts( String repoId )
        throws ArchivaRestServiceException
    {
        String userName =
            getAuditInformation().getUser() == null ? "guest" : getAuditInformation().getUser().getUsername();

        try
        {
            return userRepositories.isAuthorizedToDeleteArtifacts( userName, repoId );
        }
        catch ( ArchivaSecurityException e )
        {
            throw new ArchivaRestServiceException( e.getMessage(),
                                                   Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
        }
    }

    @Override
    public RepositoryScanStatistics scanRepositoryDirectoriesNow( String repositoryId )
        throws ArchivaRestServiceException
    {
        long sinceWhen = RepositoryScanner.FRESH_SCAN;
        try
        {
            return repoScanner.scan( repositoryRegistry.getManagedRepository( repositoryId ), sinceWhen );
        }
        catch ( RepositoryScannerException e )
        {
            log.error( e.getMessage(), e );
            throw new ArchivaRestServiceException( "RepositoryScannerException exception: " + e.getMessage(), 500, e );
        }
    }

    /**
     * Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
     *
     * @param metadata
     */
    private void updateMetadata( ArchivaRepositoryMetadata metadata, Path metadataFile, Date lastUpdatedTimestamp,
                                 Artifact artifact )
        throws RepositoryMetadataException
    {
        List<String> availableVersions = new ArrayList<>();
        String latestVersion = "";

        if ( Files.exists(metadataFile) )
        {
            if ( metadata.getAvailableVersions() != null )
            {
                availableVersions = metadata.getAvailableVersions();

                if ( availableVersions.size() > 0 )
                {
                    Collections.sort( availableVersions, VersionComparator.getInstance() );

                    if ( availableVersions.contains( artifact.getVersion() ) )
                    {
                        availableVersions.remove( availableVersions.indexOf( artifact.getVersion() ) );
                    }
                    if ( availableVersions.size() > 0 )
                    {
                        latestVersion = availableVersions.get( availableVersions.size() - 1 );
                    }
                }
            }
        }

        if ( metadata.getGroupId() == null )
        {
            metadata.setGroupId( artifact.getGroupId() );
        }
        if ( metadata.getArtifactId() == null )
        {
            metadata.setArtifactId( artifact.getArtifactId() );
        }

        if ( !VersionUtil.isSnapshot( artifact.getVersion() ) )
        {
            if ( metadata.getReleasedVersion() != null && metadata.getReleasedVersion().equals(
                artifact.getVersion() ) )
            {
                metadata.setReleasedVersion( latestVersion );
            }
        }

        metadata.setLatestVersion( latestVersion );
        metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
        metadata.setAvailableVersions( availableVersions );

        RepositoryMetadataWriter.write( metadata, metadataFile);
        ChecksummedFile checksum = new ChecksummedFile( metadataFile );
        checksum.fixChecksums( algorithms );
    }

    @Override
    public StringList getRunningRemoteDownloadIds()
    {
        return new StringList( downloadRemoteIndexScheduler.getRunningRemoteDownloadIds() );
    }

    public RepositorySessionFactory getRepositorySessionFactory()
    {
        return repositorySessionFactory;
    }

    public void setRepositorySessionFactory( RepositorySessionFactory repositorySessionFactory )
    {
        this.repositorySessionFactory = repositorySessionFactory;
    }

    public List<RepositoryListener> getListeners()
    {
        return listeners;
    }

    public void setListeners( List<RepositoryListener> listeners )
    {
        this.listeners = listeners;
    }

    public ArchivaAdministration getArchivaAdministration()
    {
        return archivaAdministration;
    }

    public void setArchivaAdministration( ArchivaAdministration archivaAdministration )
    {
        this.archivaAdministration = archivaAdministration;
    }
}


text:
var expect = require('unexpected'),
    cldr = require('../lib/cldr');

describe('cldr.resolveParentLocaleId', function () {
    it('should use the data in supplementalData.xml to resolve the parent locale id', function () {
        expect(cldr.resolveParentLocaleId('en_gb'), 'to equal', 'en_001');
    });

    it('should normalize a locale id and correctly resolve it\'s parent', function () {
        expect(cldr.resolveParentLocaleId('en-GB'), 'to equal', 'en_001');
    });

    it('should fallback to stripping away the last underscore/hyphen if a locale id\'s parent is not found in supplementalData.xml', function () {
        expect(cldr.resolveParentLocaleId('en_gb_oed'), 'to equal', 'en_gb');
        expect(cldr.resolveParentLocaleId('en-GB-oed'), 'to equal', 'en_gb');
    });
});


text:
title: Filter
---
A filter is used to modify some specified data. Hexo passes data to filters in sequence and the filters then modify the data one after the other. This concept was borrowed from [WordPress](http://codex.wordpress.org/Plugin_API#Filters).

## Synopsis

``` js
hexo.extend.filter.register(type, function() {
  // User configuration
  const { config } = this;
  if (config.external_link.enable) // do something...

  // Theme configuration
  const { config: themeCfg } = this.theme;
  if (themeCfg.fancybox) // do something...

}, priority);
```

You can define the `priority`. Lower `priority` means that it will be executed first. The default `priority` is 10. We recommend using user-configurable priority value that user can specify in the config, e.g. `hexo.config.your_plugin.priority`.

## Execute Filters

``` js
hexo.extend.filter.exec(type, data, options);
hexo.extend.filter.execSync(type, data, options);
```

Option | Description
--- | ---
`context` | Context
`args` | Arguments. This must be an array.

The first argument passed into each filter is `data`. The `data` passed into the next filter can be modified by returning a new value. If nothing is returned, the data remains unmodified. You can even use `args` to specify other arguments in filters. For example:

``` js
hexo.extend.filter.register('test', function(data, arg1, arg2){
  // data === 'some data'
  // arg1 === 'foo'
  // arg2 === 'bar'

  return 'something';
});

hexo.extend.filter.register('test', function(data, arg1, arg2){
  // data === 'something'
});

hexo.extend.filter.exec('test', 'some data', {
  args: ['foo', 'bar']
});
```

You can also use the following methods to execute filters:

``` js
hexo.execFilter(type, data, options);
hexo.execFilterSync(type, data, options);
```

## Unregister Filters

``` js
hexo.extend.filter.unregister(type, filter);
```

**Example**

``` js
// Unregister a filter which is registered with named function

const filterFn = (data) => {
  data = 'something';
  return data;
};
hexo.extend.filter.register('example', filterFn);

hexo.extend.filter.unregister('example', filterFn);
```

``` js
// Unregister a filter which is registered with commonjs module

hexo.extend.filter.register('example', require('path/to/filter'));

hexo.extend.filter.unregister('example', require('path/to/filter'));
```

## Filter List

Here is a list of filters used by Hexo.

### before_post_render

Executed before a post is rendered. Refer to [post rendering](posts.html#Render) to learn the execution steps.

For example, to transform the title to lower case:

``` js
hexo.extend.filter.register('before_post_render', function(data){
  data.title = data.title.toLowerCase();
  return data;
});
```

### after_post_render

Executed after a post is rendered. Refer to [post rendering](posts.html#Render) to learn the execution steps.

For example, to replace `@username` with a link to a Twitter profile:

``` js
hexo.extend.filter.register('after_post_render', function(data){
  data.content = data.content.replace(/@(\d+)/, '<a href="http://twitter.com/$1">#$1</a>');
  return data;
});
```

### before_exit

Executed before Hexo is about to exit -- this will run right after `hexo.exit` is called.

``` js
hexo.extend.filter.register('before_exit', function(){
  // ...
});
```

### before_generate

Executed before generation begins.

``` js
hexo.extend.filter.register('before_generate', function(){
  // ...
});
```

### after_generate

Executed after generation finishes.

``` js
hexo.extend.filter.register('after_generate', function(){
  // ...
});
```

### template_locals

Modify [local variables](../docs/variables.html) in templates.

For example, to add the current time to the local variables of templates:

``` js
hexo.extend.filter.register('template_locals', function(locals){
  locals.now = Date.now();
  return locals;
});
```

### after_init

Executed after Hexo is initialized -- this will run right after `hexo.init` completes.

``` js
hexo.extend.filter.register('after_init', function(){
  // ...
});
```

### new_post_path

Executed when creating a post to determine the path of new posts.

``` js
hexo.extend.filter.register('new_post_path', function(data, replace){
  // ...
});
```

### post_permalink

Used to determine the permalink of posts.

``` js
hexo.extend.filter.register('post_permalink', function(data){
  // ...
});
```

### after_render

Executed after rendering finishes. You can see [rendering](rendering.html#after_render_Filters) for more info.

### after_clean

Executed after generated files and cache are removed with `hexo clean` command.

``` js
hexo.extend.filter.register('after_clean', function(){
  // remove some other temporary files
});
```

### server_middleware

Add middleware to the server. `app` is a [Connect] instance.

For example, to add `X-Powered-By: Hexo` to the response header:

``` js
hexo.extend.filter.register('server_middleware', function(app){
  app.use(function(req, res, next){
    res.setHeader('X-Powered-By', 'Hexo');
    next();
  });
});
```

[Connect]: https://github.com/senchalabs/connect


text:
package main

import (
	"github.com/jjyr/ringo"
	"github.com/jjyr/ringo/middleware"
)

// user model
// validation details: gopkg.in/go-playground/validator.v8
type user struct {
	Name string `json:"name" validate:"required"`
}

var users []user

// controllers
type Users struct {
	ringo.Controller
}

func (_ *Users) Get(c ringo.Context) {
	c.JSON(200, ringo.H{"users": users})
}

func (ctl *Users) Post(c ringo.Context) {
	u := user{}
	if err := c.BindJSON(&u); err == nil {
		users = append(users, u)
		c.JSON(200, u)
	} else {
		c.JSON(400, ringo.H{"message": "format error"})
	}
}

func DisplayList(c ringo.Context) {
	// render html template
	c.HTML(200, "list.html", users)
}

type User struct {
	ringo.Controller
}

func (ctl *User) Delete(c ringo.Context) {
	idx := -1
	name := c.Params().ByName("id")
	for i, u := range users {
		if name == u.Name {
			// found
			idx = i
			break
		}
	}
	if idx >= 0 {
		users = append(users[:idx], users[idx+1:]...)
		c.JSON(200, ringo.H{"message": "ok"})
	} else {
		c.JSON(404, ringo.H{"message": "not found"})
	}
}

func main() {
	app := ringo.NewApp()

	// register controllers
	app.Add("/users", &Users{})
	app.GET("/users-list", DisplayList)
	app.Add("/user/:id", &User{})
	// use recover middleware, response 500 if handler panic
	app.Use(middleware.Recover())
	// setup templates path
	app.SetTemplatePath("templates")
	app.Run("localhost:8000")
}


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

namespace CareerHub.Client.API.Integrations.Jobs {
    public class EmployerModel {
        public int ID { get; set; }
        public string Name { get; set; }
        public EmployerType Type { get; set; }

        public string Description { get; set; }
    }
}


text:
package io.resourcepool.dashboard.revisioncontroll.find;

import io.resourcepool.dashboard.dto.BundleMetadataDto;
import io.resourcepool.dashboard.dto.MediaMetadataDto;
import io.resourcepool.dashboard.model.metadata.BundleMetadata;
import io.resourcepool.dashboard.revisioncontroll.AbstractRevisionControllerTest;
import io.resourcepool.dashboard.model.type.MediaType;
import org.junit.Test;
import org.springframework.test.web.servlet.MvcResult;

import static org.junit.Assert.assertNotEquals;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * Created by Florian Castelain on 17/06/16.
 */
public class RevisionControllerFindTest extends AbstractRevisionControllerTest {

    // ============================================================
    //	Tests
    // ============================================================

    @Test
    public void successGetLatestRevision() throws Exception {
        mockMvc.perform(getAuthenticated("/revision"))
                .andExpect(status().isOk())
                .andExpect(content().json("0"));
    }

    @Test
    public void successCheckRevisionVersionWithAddMedia() throws Exception {
        MvcResult resultOldRevision = mockMvc.perform(getAuthenticated("/revision"))
                .andExpect(status().isOk())
                .andReturn();

        final long oldRevision = fromJson(resultOldRevision.getResponse().getContentAsString(), Long.class);

        final String name = "Killua Zoldik";
        final String bundleName = "bundleRevision";
        final String url = "http://www.google.fr";
        final MediaType mediaType = MediaType.WEB;

        final BundleMetadata bundleEntity = new BundleMetadata.Builder().name(bundleName).build();
        bundleService.save(bundleEntity);
        BundleMetadataDto globalBundleMetadataDto = bundleDtoMapper.toDto(bundleService.getByTag(bundleEntity.getTag()));

        mockMvc.perform(fileUploadAuthenticated("/media")
                .param("media", toJson(new MediaMetadataDto.Builder()
                        .name(name)
                        .mediaType(mediaType)
                        .bundleTag(globalBundleMetadataDto.getUuid())
                        .url(url)
                        .build())))
                .andExpect(status().isOk());

        MvcResult resultLatestRevision = mockMvc.perform(getAuthenticated("/revision"))
                .andExpect(status().isOk())
                .andReturn();

        final long LatestRevision = fromJson(resultLatestRevision.getResponse().getContentAsString(), Long.class);

        assertNotEquals(oldRevision, LatestRevision);
    }

    @Test
    public void failedGetRevisionListBadRequest() throws Exception {
        mockMvc.perform(getAuthenticated("/revision/szfgqsf/feed/1234"))
                .andExpect(status().isBadRequest());
    }

    @Test
    public void successGetRevisionList() throws Exception {
        MvcResult resultOldRevision = mockMvc.perform(getAuthenticated("/revision"))
                .andExpect(status().isOk())
                .andReturn();

        final long oldRevision = fromJson(resultOldRevision.getResponse().getContentAsString(), Long.class);

        mockMvc.perform(getAuthenticated("/revision/" + oldRevision + "/feed/1234"))
                .andExpect(status().isOk());
    }

}


text:
<?xml version="1.0" encoding="utf-8"?>
<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <StorageProviders>
      <Provider Type="Orleans.Storage.MemoryStorage" Name="MemoryStore" NumStorageGrains="1" />
      <Provider Type="UnitTests.StorageTests.ErrorInjectionStorageProvider" Name="PubSubStore" />
    </StorageProviders>
    <StreamProviders>
      <Provider Type="Orleans.Providers.Streams.SimpleMessageStream.SimpleMessageStreamProvider" Name="SMSProvider" FireAndForgetDelivery="false"/>
    </StreamProviders>
    <SeedNode Address="localhost" Port="22222" />
    <Messaging ResponseTimeout="30s" MaxResendCount="0"/>
  </Globals>
  <Defaults>
    <Networking Address="localhost" Port="0" />
    <Scheduler MaxActiveThreads="0" />
    <Tracing DefaultTraceLevel="Info" TraceToConsole="false" TraceToFile="{0}-{1}.log" PropagateActivityId="false" BulkMessageLimit="1000">
      <TraceLevelOverride LogPrefix="AssemblyLoader.Silo" TraceLevel="Warning" />
      <!--
      <TraceLevelOverride LogPrefix="InsideGrainClient.InvokeException" TraceLevel="Verbose" />
      -->
      <TraceLevelOverride LogPrefix="PubSub" TraceLevel="Verbose3" />
      <TraceLevelOverride LogPrefix="Stream" TraceLevel="Verbose3" />
      <TraceLevelOverride LogPrefix="SimpleMessageStream" TraceLevel="Verbose3" />
      <TraceLevelOverride LogPrefix="Grain.InvokeException" TraceLevel="Verbose" />
      <TraceLevelOverride LogPrefix="Storage" TraceLevel="Verbose3" />
      <TraceLevelOverride LogPrefix="Storage.AzureTableStorage" TraceLevel="Verbose3" />
      <TraceLevelOverride LogPrefix="AzureTableDataManager" TraceLevel="Warning" />
      <TraceLevelOverride LogPrefix="PubSubRendezvousGrain" TraceLevel="Verbose" />
    </Tracing>
    <Statistics MetricsTableWriteInterval="30s" PerfCounterWriteInterval="30s" LogWriteInterval="300s"/>
  </Defaults>
  <Override Node="Primary">
    <Networking Port="22222" />
    <ProxyingGateway Address="localhost" Port="40000" />
  </Override>
  <Override Node="Secondary_1">
    <Networking Port="22223" />
    <ProxyingGateway Address="localhost" Port="40001" />
  </Override>
  <Override Node="Node2">
    <Networking Port="22224" />
  </Override>
  <Override Node="Node3">
    <Networking Port="22225" />
  </Override>
</OrleansConfiguration>