text:
//
//  APIFaceAnalystEntity.h
//  TestRationFace
//
//  Created by sonnt2 on 3/29/17.
//  Copyright © 2017 com.devMoney. All rights reserved.
//

#import <Foundation/Foundation.h>

/*!
 @class APIFaceAnalyst entity
 @abstract Keep information corresponding to each landmark of API face plus plus
 */
@interface APIFaceAnalystEntity : NSObject

@property(copy, nonatomic) NSString *age;
@property(copy, nonatomic) NSString *faceQuality;
@property(copy, nonatomic) NSString *gender;

/*!
 @abstract Width of Face
*/
@property(nonatomic) NSInteger faceRectangleWidth;

/*!
 @abstract Height of Face
 */
@property(nonatomic) NSInteger faceRectangleHeight;

/*!
 @abstract Position and landmark of right Eye
 */
@property(nonatomic) NSInteger rightEyeCenterX;
@property(nonatomic) NSInteger rightEyeCenterY;
@property(nonatomic) NSInteger rightEyeTopX;
@property(nonatomic) NSInteger rightEyeTopY;
@property(nonatomic) NSInteger rightEyeBottomX;
@property(nonatomic) NSInteger rightEyeBottomY;
@property(nonatomic) NSInteger rightEyeRightCornerX;
@property(nonatomic) NSInteger rightEyeRightCornerY;
@property(nonatomic) NSInteger rightEyeLeftCornerX;
@property(nonatomic) NSInteger rightEyeLeftCornerY;
@property(nonatomic) NSInteger rightEyeUpperRightQuarterX;
@property(nonatomic) NSInteger rightEyeUpperRightQuarterY;
@property(nonatomic) NSInteger rightEyeUpperLeftQuarterX;
@property(nonatomic) NSInteger rightEyeUpperLeftQuarterY;
@property(nonatomic) NSInteger rightEyebrowUpperRightQuarterX;
@property(nonatomic) NSInteger rightEyebrowUpperRightQuarterY;
@property(nonatomic) NSInteger rightEyebrowUpperMiddleX;
@property(nonatomic) NSInteger rightEyebrowUpperMiddleY;

/*!
 @abstract Position and landmark of left Eye
 */
@property(nonatomic) NSInteger leftEyeCenterX;
@property(nonatomic) NSInteger leftEyeCenterY;
@property(nonatomic) NSInteger leftEyeTopX;
@property(nonatomic) NSInteger leftEyeTopY;
@property(nonatomic) NSInteger leftEyeBottomX;
@property(nonatomic) NSInteger leftEyeBottomY;
@property(nonatomic) NSInteger leftEyeRightCornerX;
@property(nonatomic) NSInteger leftEyeRightCornerY;
@property(nonatomic) NSInteger leftEyeLeftCornerX;
@property(nonatomic) NSInteger leftEyeLeftCornerY;
@property(nonatomic) NSInteger leftEyeUpperRightQuarterX;
@property(nonatomic) NSInteger leftEyeUpperRightQuarterY;
@property(nonatomic) NSInteger leftEyeUpperLeftQuarterX;
@property(nonatomic) NSInteger leftEyeUpperLeftQuarterY;
@property(nonatomic) NSInteger leftEyebrowUpperRightQuarterX;
@property(nonatomic) NSInteger leftEyebrowUpperRightQuarterY;
@property(nonatomic) NSInteger leftEyebrowUpperMiddleX;
@property(nonatomic) NSInteger leftEyebrowUpperMiddleY;

/*!
 @abstract Position and landmark of nose
 */
@property(nonatomic) NSInteger noseContourLeft1X;
@property(nonatomic) NSInteger noseContourLeft1Y;
@property(nonatomic) NSInteger noseContourLeft2X;
@property(nonatomic) NSInteger noseContourLeft2Y;
@property(nonatomic) NSInteger noseContourLeft3X;
@property(nonatomic) NSInteger noseContourLeft3Y;
@property(nonatomic) NSInteger noseContourLowerMiddleX;
@property(nonatomic) NSInteger noseContourLowerMiddleY;
@property(nonatomic) NSInteger noseTipX;
@property(nonatomic) NSInteger noseTipY;
@property(nonatomic) NSInteger noseLeftX;
@property(nonatomic) NSInteger noseLeftY;
@property(nonatomic) NSInteger noseRightX;
@property(nonatomic) NSInteger noseRightY;

/*!
 @abstract Position and landmark of Upper Lip
 */
@property(nonatomic) NSInteger mouthUpperLipTopX;
@property(nonatomic) NSInteger mouthUpperLipTopY;
@property(nonatomic) NSInteger mouthUpperLipBottomX;
@property(nonatomic) NSInteger mouthUpperLipBottomY;
@property(nonatomic) NSInteger mouthUpperLipLeftContour1X;
@property(nonatomic) NSInteger mouthUpperLipLeftContour1Y;
@property(nonatomic) NSInteger mouthUpperLipRightContour1X;
@property(nonatomic) NSInteger mouthUpperLipRightContour1Y;
@property(nonatomic) NSInteger mouthLeftCornerX;
@property(nonatomic) NSInteger mouthLeftCornerY;
@property(nonatomic) NSInteger mouthRightCornerX;
@property(nonatomic) NSInteger mouthRightCornerY;

/*!
 @abstract Position and landmark of Lower Lip
 */
@property(nonatomic) NSInteger mouthLowerLipTopX;
@property(nonatomic) NSInteger mouthLowerLipTopY;
@property(nonatomic) NSInteger mouthLowerLipBottomX;
@property(nonatomic) NSInteger mouthLowerLipBottomY;

/*!
 @abstract Position and landmark of contour
 */
@property(nonatomic) NSInteger contourRight1X;
@property(nonatomic) NSInteger contourRight1Y;
@property(nonatomic) NSInteger contourChinX;
@property(nonatomic) NSInteger contourChinY;
@property(nonatomic) NSInteger contourLeft1X;
@property(nonatomic) NSInteger contourLeft1Y;

@end


text:
package net.mehmetatas.kata.impl;

import net.mehmetatas.kata.Iterator;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class CompositeIteratorImpl<T> implements Iterator<Iterable<T>> {
    private final int iteratorCount;
    private final Iterable<Iterator<T>> iterators;
    private final List<T> currentItems;
    private final List<Iterator<T>> iteratorsToReset;

    @SafeVarargs
    public CompositeIteratorImpl(Iterator<T>... iterators) {
        if (iterators == null) {
            throw new IllegalArgumentException("collection cannot be null");
        }

        int count = 0;
        for (Iterator<T> iterator : iterators) {
            if (iterator == null) {
                throw new IllegalArgumentException("iterator cannot be null");
            }
            count++;
        }

        this.iteratorCount = count;
        this.currentItems = new LinkedList<>();
        this.iteratorsToReset = new LinkedList<>();
        this.iterators = Arrays.asList(iterators);
    }

    private boolean isEnd() {
        return iteratorsToReset.size() == iteratorCount;
    }

    @Override
    public Iterable<T> current() {
        currentItems.clear();
        for (Iterator<T> iterator : iterators) {
            currentItems.add(iterator.current());
        }
        return currentItems;
    }

    @Override
    public boolean moveNext() {
        if (isEnd()) {
            return false;
        }

        iteratorsToReset.clear();

        for (Iterator<T> iterator : iterators) {
            if (iterator.moveNext()) {
                break;
            }
            iteratorsToReset.add(iterator);
        }

        if (isEnd()) {
            return false;
        }

        reset(iteratorsToReset);
        return true;
    }

    @Override
    public void reset() {
        iteratorsToReset.clear();
        reset(iterators);
    }

    private void reset(Iterable<Iterator<T>> iterators) {
        for (Iterator<T> iterator : iterators) {
            iterator.reset();
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
var storyStore

describe('Story store', function(){
  it('should instantiate', function(){
    storyStore = require('../src/stores/story');
    storyStore.eventLabel.should.equal('change');
  });
});


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Brittonia 19:203. 1967

#### Original name
null

### Remarks
null


text:
'use strict';
var path = require('path');
var gulp = require('gulp');
var less = require('gulp-less');
var cortexCompiler = require('gulp-cortex-handlebars-compiler');
var testCompiler = require('./util/test-compiler');

var pagesPath = {
    src: path.join(__dirname, 'html/**/*.html'),
    dest: path.join(__dirname, 'pages'),
    less: path.join(__dirname, 'less/page/*.less')
};

gulp.task('pages', function() {
    if (process.env.CORTEX_EFTE_TEST_BUILD === 'true') {
        return gulp.src(pagesPath.src)
            .pipe(testCompiler())
            .pipe(gulp.dest(pagesPath.dest))
    } else {
        return gulp.src(pagesPath.src)
            .pipe(cortexCompiler({
                cwd: __dirname,
                href_root: process.env.CORTEX_EFTE_HREF_ROOT,
                js_ext: process.env.CORTEX_EFTE_JS_EXT || '.js',
                css_ext: process.env.CORTEX_EFTE_CSS_EXT || '.css'
            }).compile())
            .pipe(gulp.dest(pagesPath.dest));
    }
});

gulp.task('less', function() {
    gulp.src(pagesPath.less)
        .pipe(less({
            paths: [path.join(__dirname, 'less', 'base'), path.join(__dirname, 'less', 'component')]
        }))
        .pipe(gulp.dest('pages/css'));
    gulp.src('./less/common/img/**/*.*')
        .pipe(gulp.dest('pages/img'));

});

gulp.task('img', function() {
    gulp.src('./less/page/img/**/*.*')
        .pipe(gulp.dest('src/img'));

});

gulp.task('default', ['pages', 'less', 'img']);


text:
package org.elasticsearch.transport.client;

import io.netty.util.ThreadDeathWatcher;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.reindex.ReindexPlugin;
import org.elasticsearch.percolator.PercolatorPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.mustache.MustachePlugin;
import org.elasticsearch.transport.Netty4Plugin;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * A builder to create an instance of {@link TransportClient}
 * This class pre-installs the
 * {@link Netty4Plugin},
 * {@link ReindexPlugin},
 * {@link PercolatorPlugin},
 * and {@link MustachePlugin}
 * for the client. These plugins are all elasticsearch core modules required.
 */
@SuppressWarnings({"unchecked","varargs"})
public class PreBuiltTransportClient extends TransportClient {

    private static final Collection<Class<? extends Plugin>> PRE_INSTALLED_PLUGINS =
            Collections.unmodifiableList(
                    Arrays.asList(
                            Netty4Plugin.class,
                            ReindexPlugin.class,
                            PercolatorPlugin.class,
                            MustachePlugin.class));

    @SafeVarargs
    public PreBuiltTransportClient(Settings settings, Class<? extends Plugin>... plugins) {
        this(settings, Arrays.asList(plugins));
    }

    public PreBuiltTransportClient(Settings settings, Collection<Class<? extends Plugin>> plugins) {
        super(settings, Settings.EMPTY, addPlugins(plugins, PRE_INSTALLED_PLUGINS));
    }

    @Override
    public void close() {
        super.close();
        if (NetworkModule.TRANSPORT_TYPE_SETTING.exists(settings) == false
            || NetworkModule.TRANSPORT_TYPE_SETTING.get(settings).equals(Netty4Plugin.NETTY_TRANSPORT_NAME)) {
            try {
                GlobalEventExecutor.INSTANCE.awaitInactivity(5, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            try {
                ThreadDeathWatcher.awaitInactivity(5, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

}


text:
{% extends "base.django.html" %}

{% load canvas_tags %}

{% block header %}{% endblock %}

{% block extra_css %}
<style>
</style>
{% endblock %}

{% block content %}
{% endblock %}

{% block extra_javascript %}
<script>
    window.top.location = '{{ redirect_url }}';
</script>
{% endblock %}

{% block footer %}{% endblock %}


text:
package com.muje.parcel;

import java.util.ArrayList;
import java.util.Collections;

/**
 * Carrier abstract class
 * TODO: sort track collection in descending for convenient reading.
 * @author yeang-shing.then
 *
 */
public abstract class Carrier {
	public Carrier() {
        this.name = "";
        this.consignmentNo = "";
        this.tracks = new ArrayList<Track>();
    }
	protected String name;
	/**
	 * Return name of the provider after trace the consignment no.
	 * @return
	 */
	public String getProviderName() { return this.name;}
    protected String consignmentNo;
	/**
	 * Return resource id for logo image.
	 * @return
	 */
	public int getLogoId() {
		if(this.name.equals("poslaju")) {
			return R.drawable.poslaju;
		} else if(this.name.equals("citylink")) {
			return R.drawable.citylink;
		} else if(this.name.equals("gdex")) {
            return R.drawable.gdex;
        } else if(this.name.equals("fedex")) {
            return R.drawable.fedex;
        } else if(this.name.equals("skynet")) {
            return R.drawable.skynet;
        } else if(this.name.equals("ups")) {
            return R.drawable.ups;// source http://upload.wikimedia.org/wikipedia/en/9/9f/United_Parcel_Service_logo.svg
        }

		return -1;//null
	}

//	protected String origin;
//	public void setOrigin(String origin) {
//		this.origin = origin;
//	}
//	public String getOrigin() {return this.origin;}
//
//	protected String destination;
//	public void setDestination(String destination) {
//		this.destination = destination;
//	}
//	public String getDestination() {return this.destination;}

    protected String url;

    /**
     * Return tracking number in original courier website.
     * @return
     */
    public String getUrl() {
        return this.url;
    }

	protected ArrayList<Track> tracks;
	/**
	 * Return track collection in descending order of time.
	 * @return
	 */
	public ArrayList<Track> getTracks() {

		Collections.sort(this.tracks, new TrackComparator());
		//HACK: Collections.sort(this.tracks, Collections.reverseOrder());//fail
		return this.tracks;
	}
	/**
	 * Trace by consignment no.
	 * @param consignmentNo
	 * @throws Exception
	 */
	public abstract void trace(String consignmentNo) throws Exception;

}


text:
The scope of the project is to provide ASP.NET Identity based on Cache database.
ASP.NET Identity is the new membership system for building ASP.NET web applications. ASP.NET Identity allows you to add login features to your application and makes it easy to customize data about the logged in user.

#### Install necessary software
- Visual Studio 2012/2013
- Cache 2015.2
- .NET Framework 4.5

####Second stage:
- AspNet Identity completely implemented for Cache database (with IdentityUserStore and IdentityRoleStore).
- Asp.Net MVC test project added to display provided functionality (AspNetIdentityTestProject).
- Integration tests added (Identity.Test).
- Nuget package created (Release/InterSystems.AspNet.Identity.Cache.1.0.0.nupkg).
- Binary library created (Release/InterSystems.AspNet.Identity.Cache.dll).

####Now you can test provided functionality by performing following steps:
- Download Project from GitHub.
- Open solution in visual studio.
- In AspNetIdentityTestProject Web.config in connectionStrings section find next string:
```
<add name="DefaultConnection" connectionString="Server=localhost; Port=1972; Namespace=USER;Password=SYS; User ID=_SYSTEM;" providerName="InterSystems.Data.CacheClient" />
```
You should replace Namespace and Port to yours if needed.
- Then launch AspNetIdentityTestProject. This is the simple web application that demonstrates AspNet.Identity implementation for cache. You can register and login to site using facebook or google account. All the data is stored in your Cache database.

We provided unit testing (Identity.Test project).
####Testing with unit tests.
- In Identity.Test project App.config in connectionStrings section find next string:
```
<add name="DefaultConnection" connectionString="Server=localhost; Port=1972; Namespace=USER;Password=SYS; User ID=_SYSTEM;" providerName="InterSystems.Data.CacheClient" />
```
You should replace Namespace and Port to yours if needed.
- Use next commangs to install needed package to Identity.Test:
	 - Install-Package xunit -Version 1.9.2
	 - Install-Package Microsoft.AspNet.Identity.Owin
	 - Install-Package Microsoft.AspNet.Identity.EntityFramework
- Then build Identity.Test project
- Download XUnit test enviroment from https://xunit.codeplex.com/releases/view/90058 (xunit-1.9.1.zip).
- Launch xunit.gui.clr4.exe.
- Before running test you should clean all data from Identity tables in Cache (DBO.AspNetUsers, DBO.AspNetUserLogins, DBO.AspNetUserClaims, DBO.AspNetRoles, DBO.AspNetUserRoles).
- Add Identity.Test.dll (Assembly -> Open) and press RunAll tests.

Nuget package.
#####We created package - InterSystems.AspNet.Identity.Cache.1.0.0.nupkg (Release folder).
#####Installation of nuget package to your project - http://stackoverflow.com/questions/10240029/how-to-install-a-nuget-package-nupkg-file-locally.

Dll placed to Release folder.


text:
require "fast_spec_helper"
require "active_support/core_ext/hash"

require "specialist_document"

describe SpecialistDocument do
  subject(:doc) {
    SpecialistDocument.new(slug_generator, document_id, editions, edition_factory)
  }

  def key_classes_for(hash)
    hash.keys.map(&:class).uniq
  end

  let(:document_id)         { "a-document-id" }
  let(:document_type)       { "cma_case" }
  let(:slug)                { double(:slug) }
  let(:published_slug)      { double(:published_slug) }
  let(:slug_generator)      { double(:slug_generator, call: slug) }
  let(:edition_factory)     { double(:edition_factory, call: new_edition) }
  let(:new_edition)         { double(:new_edition, published?: false, draft?: true, assign_attributes: nil, version_number: 2) }
  let(:attachments)         { double(:attachments) }

  let(:extra_fields) {
    {
      "case_state" => "open",
    }
  }

  let(:edition_messages)    {
    {
      build_attachment: nil,
      assign_attributes: nil,
      attachments: attachments_proxy,
      publish: nil,
      archive: nil,
      attributes: {},
      extra_fields: extra_fields,
      minor_update: false,
      change_note: "Some changes",
      :exported_at= => nil,
      save: nil,
    }
  }

  let(:attachments_proxy) { double(:attachments_proxy, to_a: attachments) }

  let(:draft_edition_v1) {
    double(:draft_edition_v1,
      edition_messages.merge(
        title: "Draft edition v1",
        state: "draft",
        draft?: true,
        published?: false,
        archived?: false,
        version_number: 1,
        document_type: document_type,
      )
    )
  }

  let(:draft_edition_v2) {
    double(:draft_edition_v2,
      edition_messages.merge(
        title: "Draft edition v2",
        state: "draft",
        draft?: true,
        published?: false,
        archived?: false,
        version_number: 2,
        extra_fields: extra_fields,
        document_type: document_type,
      )
    )
  }

  let(:published_edition_v1) {
    double(:published_edition_v1,
      edition_messages.merge(
        title: "Published edition",
        state: "published",
        published?: true,
        draft?: false,
        archived?: false,
        slug: published_slug,
        version_number: 1,
        document_type: document_type,
      )
    )
  }

  let(:withdrawn_edition_v2) {
    double(:withdrawn_edition_v2,
      edition_messages.merge(
        title: "Withdrawn edition",
        state: "withdrawn",
        published?: false,
        draft?: false,
        archived?: true,
        slug: published_slug,
        version_number: 2,
        document_type: document_type,
      )
    )
  }

  context "with one draft edition" do
    let(:editions) { [draft_edition_v1] }

    it "is in draft" do
      expect(doc).to be_draft
    end

    it "is not published" do
      expect(doc).not_to be_published
    end
  end

  context "with one published edition" do
    let(:editions) { [published_edition_v1] }

    it "is published" do
      expect(doc).to be_published
    end

    it "is not in draft" do
      expect(doc).not_to be_draft
    end
  end

  context "with one published edition and one draft edition" do
    let(:editions) { [published_edition_v1, draft_edition_v2] }

    it "is published and in draft" do
      expect(doc).to be_draft
      expect(doc).to be_published
    end
  end

  describe "#update" do
    context "with string keyed attributes hashes" do
      let(:editions) { [draft_edition_v1] }
      let(:string_keyed_attrs) {
        {
          "body" => "o hai",
        }
      }

      it "symbolizes the keys" do
        doc.update(string_keyed_attrs)

        expect(draft_edition_v1).to have_received(:assign_attributes).with(
          hash_including(body: "o hai")
        )
      end
    end

    context "with bad attributes hashes" do
      let(:editions) { [draft_edition_v1] }
      let(:bad_attrs) {
        {
          key_that_is_not_allowed: "o hai",
        }
      }

      it "cleans the hash" do
        doc.update(bad_attrs)

        expect(draft_edition_v1).to have_received(:assign_attributes).with({})
      end
    end

    context "document is new, with no previous editions" do
      let(:editions) { [] }
      let(:attrs)    { { title: "Test title" } }

      it "creates the first edition" do
        doc.update(attrs)

        expect(edition_factory).to have_received(:call).with(
          version_number: 1,
          state: "draft",
          document_id: document_id,
        )
      end
    end

    context "before the document is published" do
      context "with an existing draft edition" do
        let(:editions)  { [draft_edition_v1] }

        context "when providing a title" do
          let(:new_title) { double(:new_title) }
          let(:slug)      { double(:slug) }

          it "generates a slug" do
            doc.update(title: new_title)

            expect(slug_generator).to have_received(:call).with(new_title)
          end

          it "assigns the title and slug to the draft edition" do
            doc.update(title: new_title)

            expect(draft_edition_v1).to have_received(:assign_attributes)
              .with(hash_including(
                title: new_title,
                slug: slug,
              ))
          end
        end
      end
    end

    context "when the current document is published" do
      let(:editions) { [published_edition_v1] }

      let(:params) { {title: "It is a new title"} }

      let(:edition_body) { double(:edition_body) }
      let(:edition_attributes) {
        {
          "_id" => "superfluous id",
          "updated_at" => "superfluous timestamp",
          "body" => edition_body,
        }
      }

      before do
        allow(published_edition_v1).to receive(:attributes)
          .and_return(edition_attributes)
      end

      it "builds a new edition with the new params" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(params))
      end

      it "builds the new edition with attributes carried over from the previous edition" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(
          body: edition_body,
        ))
      end

      it "filters the previous edition's attributes" do
        doc.update(params)

        expect(edition_factory).not_to have_received(:call).with(hash_including(
          _id: "superfluous id",
          updated_at: "superfluous timestamp",
        ))

        expect(edition_factory).not_to have_received(:call).with(hash_including(
          "_id" => "superfluous id",
          "updated_at" => "superfluous timestamp",
        ))
      end

      it "builds a new edition with an incremented version number" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(version_number: 2))
      end

      it "builds a new edition in the 'draft' state" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(state: "draft"))
      end

      it "builds a new edition copying over the previous edition's attachments" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(
          attachments: attachments,
        ))
      end

      it "presents the new edition" do
        doc.update(params)

        expect(doc.version_number).to eq(new_edition.version_number)
      end

      it "returns nil" do
        expect(doc.update(params)).to eq(nil)
      end

      context "when providing a title" do
        let(:new_title) { double(:new_title) }
        let(:slug)      { double(:slug) }

        it "does not update the slug" do
          doc.update(title: new_title)

          expect(edition_factory).to have_received(:call).with(
            hash_including(
              slug: published_slug,
            )
          )
        end
      end
    end

    context "when the current document is withdrawn" do
      let(:editions) { [withdrawn_edition_v2] }

      let(:params) { {title: "It is a new title"} }

      it "builds a new edition with the new params" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(params))
      end

      it "builds a new edition with an incremented version number" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(version_number: 3))
      end

      it "builds a new edition in the 'draft' state" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(state: "draft"))
      end

      it "builds a new edition copying over the previous edition's attachments" do
        doc.update(params)

        expect(edition_factory).to have_received(:call).with(hash_including(
          attachments: attachments,
        ))
      end

      it "presents the new edition" do
        doc.update(params)

        expect(doc.version_number).to eq(new_edition.version_number)
      end

      it "returns nil" do
        expect(doc.update(params)).to eq(nil)
      end

      context "when providing a title" do
        let(:new_title) { double(:new_title) }
        let(:slug)      { double(:slug) }

        it "does not update the slug" do
          doc.update(title: new_title)

          expect(edition_factory).to have_received(:call).with(
            hash_including(
              slug: published_slug,
            )
          )
        end
      end
    end
  end

  describe "#publish!" do
    context "one draft" do
      let(:editions) { [draft_edition_v1] }

      it "should set its state to published" do
        doc.publish!
        expect(draft_edition_v1).to have_received(:publish)
      end
    end

    context "one published and one draft edition" do
      let(:editions) { [published_edition_v1, draft_edition_v2] }

      it "should set the draft edition's state to published" do
        doc.publish!
        expect(draft_edition_v2).to have_received(:publish)
      end

      it "archives the previous edition" do
        doc.publish!

        expect(published_edition_v1).to have_received(:archive)
      end
    end

    context "one published edition" do
      let(:editions) { [published_edition_v1] }

      it "do nothing" do
        doc.publish!
        expect(published_edition_v1).not_to have_received(:publish)
      end
    end
  end

  describe "#add_attachment" do
    let(:editions) { [published_edition_v1, draft_edition_v2] }
    let(:params) { double(:params) }

    it "tells the latest edition to create an attachment using the supplied parameters" do
      doc.add_attachment(params)

      expect(draft_edition_v2).to have_received(:build_attachment).with(params)
    end
  end

  describe "#attachments" do
    let(:editions) { [published_edition_v1, draft_edition_v2] }

    it "delegates to the latest edition" do
      doc.attachments

      expect(draft_edition_v2).to have_received(:attachments)
    end

    it "returns the attachments from the latest edition" do
      expect(doc.attachments).to eq(attachments)
    end
  end

  describe "#extra_fields" do
    let(:editions) {
      [draft_edition_v1]
    }

    it "returns the extra fields from the edition (symbolized)" do
      expect(key_classes_for(doc.extra_fields)).to eq([Symbol])
    end
  end

  describe "#attributes" do
    let(:relevant_document_attrs) {
      {
        "title" => "document_title",
      }
    }

    let(:undesirable_edtion_attrs) {
      {
        "junk_key" => "junk_value",
      }
    }

    let(:edition) {
      draft_edition_v2.tap do |e|
        allow(e).to receive(:attributes).and_return(relevant_document_attrs.merge(undesirable_edtion_attrs))
      end
    }

    let(:editions) { [published_edition_v1, edition] }

    context "with extra fields" do
      let(:extra_fields) {
        {
          "case_state" => "open",
        }
      }

      before do
        allow(edition).to receive(:attributes)
          .and_return(relevant_document_attrs.merge("extra_fields" => extra_fields))
      end

      it "deep symbolizes the extra field keys" do
        expect(key_classes_for(doc.attributes.fetch(:extra_fields))).to eq([Symbol])
      end
    end

    it "symbolizes the keys" do
      expect(key_classes_for(doc.attributes)).to eq([Symbol])
    end

    it "returns attributes with junk removed" do
      expect(doc.attributes).not_to include(
        undesirable_edtion_attrs.symbolize_keys
      )
    end

    it "returns the latest edition's attributes" do
      expect(doc.attributes).to include(
        relevant_document_attrs.symbolize_keys
      )
    end

    it "returns a has including the document's id" do
      expect(doc.attributes).to include(
        id: document_id,
      )
    end
  end

  describe "#find_attachment_by_id" do
    let(:editions) { [published_edition_v1] }

    let(:attachment_one) { double("attachment_one", id: id_object("one")) }
    let(:attachment_two) { double("attachment_two", id: id_object("two")) }

    let(:attachments) {
      [
        attachment_one,
        attachment_two,
      ]
    }

    def id_object(id_string)
      # like a Mongoid BSON id
      double(to_s: id_string)
    end

    it "returns the attachment with the corresponding id" do
      expect(
        doc.find_attachment_by_id("one")
      ).to eq(attachment_one)
    end

    it "returns nil if the attachment does not exist" do
      expect(
        doc.find_attachment_by_id("does-not-exist")
      ).to be_nil
    end
  end

  describe "#publication_state" do
    context "when the first edition is in draft" do
      let(:editions) { [draft_edition_v1] }

      it "returns 'draft'" do
        expect(doc.publication_state).to eq("draft")
      end
    end

    context "with a single published edition" do
      let(:editions) { [published_edition_v1] }

      it "returns 'published'" do
        expect(doc.publication_state).to eq("published")
      end
    end

    context "with a single published edition" do
      let(:editions) { [published_edition_v1, draft_edition_v2] }

      it "returns 'published'" do
        expect(doc.publication_state).to eq("published")
      end
    end

    context "with a published edition, and withdrawn edition" do
      let(:editions) { [published_edition_v1, withdrawn_edition_v2] }

      it "returns 'withdrawn'" do
        expect(doc.publication_state).to eq("withdrawn")
      end
    end
  end

  describe "#withdrawn?" do
    context "one draft" do
      let(:editions) { [draft_edition_v1] }

      it "returns false" do
        expect(doc).not_to be_withdrawn
      end
    end

    context "one published" do
      let(:editions) { [published_edition_v1] }

      it "returns false" do
        expect(doc).not_to be_withdrawn
      end
    end

    context "one published and one withdrawn" do
      let(:editions) { [published_edition_v1, withdrawn_edition_v2] }

      it "returns true" do
        expect(doc).to be_withdrawn
      end
    end
  end

  describe "#withdraw!" do
    context "one draft" do
      let(:editions) { [draft_edition_v1] }

      it "does nothing" do
        doc.withdraw!

        expect(draft_edition_v1).not_to have_received(:archive)
      end
    end

    context "one published and one withdrawn" do
      let(:editions) { [published_edition_v1, withdrawn_edition_v2] }

      it "does nothing" do
        doc.withdraw!

        expect(published_edition_v1).not_to have_received(:archive)
        expect(withdrawn_edition_v2).not_to have_received(:archive)
      end
    end

    context "one published and one draft edition" do
      let(:editions) { [published_edition_v1, draft_edition_v2] }

      it "sets the published edition's state to withdrawn" do
        doc.withdraw!

        expect(published_edition_v1).to have_received(:archive)
      end
    end

    context "one published edition" do
      let(:editions) { [published_edition_v1] }

      it "sets the published edition's state to withdrawn" do
        doc.withdraw!

        expect(published_edition_v1).to have_received(:archive)
      end
    end
  end

  describe "#mark_as_exported_to_live_publishing_api!" do
    let(:editions) { [published_edition_v1, draft_edition_v2] }

    it "sets the exported_at date on the latest edition" do
      time = Time.now
      Timecop.freeze(time) do
        doc.mark_as_exported_to_live_publishing_api!
        expect(draft_edition_v2).to have_received(:exported_at=).with(time).ordered
        expect(draft_edition_v2).to have_received(:save).ordered

        expect(published_edition_v1).not_to have_received(:exported_at=)
        expect(published_edition_v1).not_to have_received(:save)
      end
    end
  end
end


text:
layout: page
title: Cross Chemical Executive Retreat
date: 2016-05-24
author: Vincent Haley
tags: weekly links, java
status: published
summary: Nulla sagittis nisi ac efficitur.
banner: images/banner/people.jpg
booking:
  startDate: 07/11/2019
  endDate: 07/16/2019
  ctyhocn: TYSHSHX
  groupCode: CCER
published: true
---
Vivamus id blandit nisi, accumsan interdum augue. Ut id ultrices orci. Duis lorem justo, commodo ac facilisis non, commodo ac mi. Praesent ac odio nec est pulvinar placerat in a justo. Proin non nisl lacus. Nullam venenatis pretium risus nec hendrerit. Sed id nunc ligula. Mauris congue, lectus sit amet tincidunt mollis, nulla elit dapibus mauris, vel molestie nisi sem in enim. Sed sit amet enim non lorem scelerisque pretium nec sed dui. Proin scelerisque fringilla elit. Sed elementum pharetra elit, sit amet commodo felis euismod sed. Maecenas bibendum libero ut varius bibendum. Vivamus at augue lorem.

1 Proin ut lacus sit amet leo porta tincidunt
1 Integer suscipit purus vel libero posuere, id interdum tellus malesuada.

Fusce scelerisque auctor consequat. Donec eget nibh nec ipsum cursus viverra ac vitae augue. Donec congue fringilla mauris, eu iaculis arcu fringilla id. Morbi eget risus hendrerit, interdum ligula convallis, viverra ante. Curabitur porttitor justo non eros sagittis efficitur vel fermentum tellus. Sed efficitur maximus porttitor. Integer in ornare quam, pharetra iaculis metus. Nulla id purus nec sapien consequat egestas sed quis elit. Etiam porttitor mi quis elementum sollicitudin.