text:
using System;
using System.Windows.Forms;
using System.Drawing;
using XenAdmin.Core;
using XenAdmin.Model;
using XenAdmin.XenSearch;
using XenAPI;

namespace XenAdmin.Controls.XenSearch
{
    public class ResourceSelectButton : DropDownComboButton, IAcceptGroups
    {
        private class ResourceRenderer : ToolStripProfessionalRenderer
        {
            private static int RIGHT_MARGIN = 2;
            private static int TOP_MARGIN = 2;

            protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
            {
                // The TextColor for a disabled item is ignored, so we have to temporarily enable the item.
                bool enabled = e.Item.Enabled;
                e.Item.Enabled = true;
                base.OnRenderItemText(e);
                e.Item.Enabled = enabled;

                // Draw an icon just before the text starts
                String s = e.Text;
                String sSpaces = String.Empty;  // sSpaces will be the spaces at the beginning of s
                for (int i = 0; i < s.Length && s[i] == ' '; ++i)
                    sSpaces += ' ';
                Size indent = Drawing.MeasureText(sSpaces, e.TextFont);
                Image im = Images.GetImage16For(e.Item.Tag as IXenObject);
                e.Graphics.DrawImage(im, indent.Width - im.Width - RIGHT_MARGIN, e.TextRectangle.Top + TOP_MARGIN, im.Width, im.Height);
            }
        }

        private static string INDENT = "       ";

        private QueryScope scope = null;
        private FolderListItem folderListItem = null;

        public ResourceSelectButton() : base()
        {
            contextMenuStrip.ShowImageMargin = false;
            contextMenuStrip.Renderer = new ResourceRenderer();
        }

        protected override void SetButtonTextFromItem(ToolStripItem item)
        {
            IXenObject o = item.Tag as IXenObject;
            if (o is Folder)  // for folders we want to show the full pathname using a FolderListItem
            {
                Text = String.Empty;
                folderListItem = new FolderListItem(o.opaque_ref, FolderListItem.AllowSearch.None, false);
                folderListItem.Parent = this;
            }
            else
            {
                Text = Helpers.GetName(o);
                folderListItem = null;
            }
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);
            if (folderListItem != null)
            {
                Rectangle r = pevent.ClipRectangle;
                r.Location = new Point(6, 4);
                r.Width -= 21;
                r.Height -= 6;
                folderListItem.DrawSelf(pevent.Graphics, r, false);
            }
        }

        public IAcceptGroups Add(Grouping grouping, object group, int indent)
        {
            ToolStripMenuItem menuItem = new ToolStripMenuItem();
            IXenObject o = group as IXenObject;
            if (o != null)
            {
                // Pad the item name with spaces on the left. This is nasty, but we
                // don't know any way to specify a width or padding in pixels and have
                // it affect the area on which we can write or the width of the tool
                // strip; so it seems necessary to fool the framework in this way.
                menuItem.Text = INDENT;
                for (int i = 0; i < indent; ++i)
                    menuItem.Text += INDENT;
                menuItem.Text += Helpers.GetName(o).EscapeAmpersands();
                menuItem.Tag = o;
                if (scope != null && !scope.WantType(o))
                {
                    menuItem.Enabled = false;
                    menuItem.BackColor = System.Drawing.Color.Gainsboro;
                    menuItem.ForeColor = DefaultForeColor;
                }
                AddItem(menuItem);
            }
            return this;
        }

        public void FinishedInThisGroup(bool defaultExpand)
        {
        }

        public void Populate(Search search)
        {
            ClearItems();
            scope = search?.Query?.QueryScope;
            search?.PopulateAdapters(this);
        }
    }
}


text:
import {Post, Reply} from '../../db/db';
import {IApplication, IUser, IPost, IReply, IAlbumFile} from '../../db/interfaces';
import serializePost from '../../core/serialize-post';
import savePostMentions from '../../core/save-post-mentions';
import extractHashtags from '../../core/extract-hashtags';
import registerHashtags from '../../core/register-hashtags';
import getAlbumFile from '../../core/get-album-file';
import event from '../../event';

/**
 * 投稿に返信します
 * @param app API利用App
 * @param user API利用ユーザー
 * @param inReplyToPostId 返信先投稿のID
 * @param text 本文
 * @param filesString 添付するファイルのIDを,で区切った文字列
 * @return 作成された投稿オブジェクト
 */
export default function(
	app: IApplication,
	user: IUser,
	inReplyToPostId: string,
	text?: string,
	filesString?: string
): Promise<Object> {
	const maxTextLength = 300;
	const maxFileLength = 4;

	return new Promise<Object>((resolve, reject) => {
		// Init 'inReplyToPostId' parameter
		if (inReplyToPostId === undefined || inReplyToPostId === null || inReplyToPostId === '') {
			return reject('in-reply-to-post-id-is-required');
		}

		// Init 'text' parameter
		if (text !== undefined && text !== null) {
			text = text.trim();
			if (text.length === 0) {
				text = null;
			} else if (text.length > maxTextLength) {
				return reject('too-long-text');
			}
		} else {
			text = null;
		}

		// Init 'filesString' parameter
		let fileIds: string[] = null;
		if (filesString !== undefined && filesString !== null) {
			fileIds = filesString
				.split(',')
				.map(fileId => fileId.trim())
				.filter(fileId => fileId !== '');
			if (fileIds.length === 0) {
				fileIds = null;
			} else if (fileIds.length > maxFileLength) {
				return reject('too-many-files');
			}

			if (fileIds !== null) {
				// 重複チェック
				let isRejected = false;
				fileIds.forEach(fileId => {
					let count = 0;
					fileIds.forEach(fileId2 => {
						if (fileId === fileId2) {
							count++;
							if (count === 2) {
								isRejected = true;
							}
						}
					});
				});
				if (isRejected) {
					return reject('duplicate-files');
				}
			}
		} else {
			fileIds = null;
		}

		// テキストが無いかつ添付ファイルも無かったらエラー
		if (text === null && fileIds === null) {
			return reject('text-or-files-is-required');
		}

		// 最後の投稿を取得
		Post.findById(<string>user.latestPost, (latestPostFindErr: any, latestPost: IPost) => {
			// 最後のReplyと返信先とテキストが同じならエラー(連投検知)
			if (latestPost !== null &&
				(<any>latestPost)._doc.type === 'reply' &&
				(<any>latestPost)._doc.text !== null &&
				text !== null &&
				text === (<any>latestPost)._doc.text &&
				inReplyToPostId === (<any>latestPost)._doc.inReplyToPost.toString()
			) {
				return reject('content-duplicate');
			}

			// 返信先に指定されている投稿が実在するかチェック
			Post.findById(inReplyToPostId, (err: any, inReplyToPost: IPost) => {
				if (err !== null) {
					return reject(err);
				} else if (inReplyToPost === null) {
					return reject('reply-target-not-found');
				} else if (inReplyToPost.isDeleted) {
					return reject('reply-target-not-found');
				} else if (inReplyToPost.type === 'repost') {
					return reject('reply-to-repost-is-not-allowed');
				}

				// 添付ファイルがあれば添付ファイルのバリデーションを行う
				if (fileIds !== null) {
					Promise.all(fileIds.map(fileId => getAlbumFile(user.id, fileId)))
					.then(files => {
						create(files);
					}, (filesCheckErr: any) => {
						reject(filesCheckErr);
					});
				} else {
					create(null);
				}

				function create(files: IAlbumFile[] = null): void {
					// ハッシュタグ抽出
					const hashtags: string[] = extractHashtags(text);

					// 作成
					Reply.create({
						app: app !== null ? app.id : null,
						user: user.id,
						inReplyToPost: inReplyToPost.id,
						files: files !== null ? files.map(file => file.id) : null,
						text: text,
						hashtags: hashtags,
						prevPost: latestPost !== null ? latestPost.id : null,
						nextPost: null
					}, (createErr: any, createdReply: IReply) => {
						if (createErr !== null) {
							return reject(createErr);
						}

						// Resolve promise
						serializePost(createdReply, user).then(serialized => {
							resolve(serialized);
						}, (serializeErr: any) => {
							reject(serializeErr);
						});

						// 作成した投稿を前の投稿の次の投稿に設定する
						if (latestPost !== null) {
							latestPost.nextPost = createdReply.id;
							latestPost.save();
						}

						// 投稿数インクリメント
						user.postsCount++;
						// 最終Postを更新
						user.latestPost = createdReply.id;
						user.save();

						// 返信数インクリメント
						inReplyToPost.repliesCount++;
						inReplyToPost.save();

						// ハッシュタグをデータベースに登録
						registerHashtags(user, hashtags);

						// メンションを抽出してデータベースに登録
						savePostMentions(user, createdReply, createdReply.text);

						event.publishPost(user.id, createdReply);
					});
				}
			});
		});
	});
}

redpajama_set_name: RedPajamaGithub


text:
'use strict';
const _ = require('lodash');
const Parse = require('../lib/parse');
const moment = require('moment');
module.exports = app => {
  /**
     * MessageService Api Service
     */
  class MessageService extends app.Service {
    constructor(ctx) {
      super(ctx);

    }

    // 支付订单,绑定消息,发送大屏
    * saveMessage(options) {

      const Bpwall = Parse.Object.extend('bpwall');
      const bpwall = new Bpwall();
      bpwall.id = options.bpwall_id;
      bpwall.relation('message').add(options.message);

      yield options.message.fetch();
      return yield bpwall.save().then(function(bpwall) {

        if (options.message.get('type') != 'text') {
          app.redis.rpush(`message:bp:${options.bpwall_id}`, options.message.id);
        }
        return bpwall;
      });

    }

    // 处理消息
    * message(options) {
      const { ctx, service } = this;
      const message = {

        content: '',
        ds_gif: '',
        type: 'text',
        isshow: '1',
        is_play: '0',
        is_delete: 0,
        redpackid: null,
        createtime: moment().unix(),
        extend_params: null,
      };

      // console.log("=====")
      // app.logger.info('message:save:%s', JSON.stringify(options));
      // console.info((options));

      message.bp_pic_effect = options.body.bp_pic_effect || 'close';
      message.uid = options.userInfo.objectId;
      // message.openid = options.userInfo.openid;
      message.avatar = options.userInfo.headimgurl;
      message.nickname = options.userInfo.nickname;
      message.content = options.body.content || '';
      message.type = options.type;
      message.image = options.image;

      options.message = message;

      switch (options.type) {
        case 'text':
          // Object.assign(message,this.text(message))
          break;
        case 'el':
          Object.assign(options, yield this.el(options));
          break;
        case 'rp':
          Object.assign(options, yield this.rp(options));

          break;
        case 'ds':
          Object.assign(options, yield this.ds(options));

          break;
        case 'bp':

          Object.assign(options, this.bp(options));

          break;
        default:
          break;

      }

      const Message = Parse.Object.extend('message');
      const msg = new Message();
      // 图片鉴黄
      if (options.message.image) {
        options.message.porn = yield service.ossgreen.checkImage(options.message.image);
      }

      // app.logger.error(options.message)

      return msg.save(options.message);

    }

    // 打赏
    * ds(options) {
      const { ctx, service } = this;

      const extend_params = {};

      const guest = yield service.bpwall.getGuestById(options.bpwall_id, options.body.guest_id);
      const present = yield service.bpwall.getPresentById(options.bpwall_id, options.body.item_id);

      options.message.content = options.userInfo.nickname + '打赏给' + guest.name;

      extend_params.guest_pic = guest.pic;
      extend_params.guest_name = guest.name;

      options.message.image = present.pic;
      options.message.ds_gif = present.df;
      options.message.type = 'ds';
      options.message.bp_time = parseInt(present.bp_time);
      options.message.fee = parseInt(present.price * 100);
      extend_params.item_name = present.name;
      extend_params.says = options.body.says;
      options.message.extend_params = extend_params;
      return options;

    }

    /**
         * 霸屏
         * @param options
         * @returns {*}
         */

    bp(options) {

      // let a={upload:2017.jpg
      // content:kkkkkk
      // imgSrc:http://leven-dev.oss-cn-shanghai.aliyuncs.com//bpmsg/HaDnYC8yuA/1487665921355.jpg
      // bp_index:3
      // type:bp
      // nickname:
      //     admin_bp:on
      // bp_pic_effect:on}

      // move
      // upload:bras.webm
      // content:请大家看小电影5345345435
      // imgSrc:http://leven-dev.oss-cn-shanghai.aliyuncs.com//bpmsg/HaDnYC8yuA/1487666186243.webm
      //     bp_index:0
      // type:video
      // nickname:
      //     admin_bp:on

      const extend_params = {};
      const type = options.body.type;
      if (options.body.imgSrc) {
        options.message.image = options.body.imgSrc;

      }
      if (options.body.bp_index) {
        const bp = options.bpwall.bp_item;
        console.log('bp');

        console.log(bp);

        options.message.bp_time = parseInt(bp[options.body.bp_index].time);
        options.message.fee = parseInt(bp[options.body.bp_index].fee * 100);
      }

      if (type == 'video') {

        options.message.image = 'http://leven-dev.oss-cn-shanghai.aliyuncs.com/static/wall/video.png';
        extend_params.video = options.body.imgSrc;
        extend_params.mime_type = 'video/mp4';
      }
      options.message.extend_params = extend_params;
      return options;
    }

    * el(options) {

      // item_id:vlpS0YTrrK
      // theme_id:LCegBSoH5c
      // uid:61jCYSoOtl
      // love_letter:漫天花雨,只为浪漫我和你
      // image:http://leven-dev.oss-cn-shanghai.aliyuncs.com/static/express_love/images/image_default.png
      //     admin_el:true
      // token:bT03

      const { ctx, service } = this;

      const extend_params = {};

      const love = yield service.bpwall.getLoveById(options.bpwall_id, options.body.theme_id);
      const love_item = yield service.bpwall.getLoveItemById(options.bpwall_id, options.body.item_id);
      const love_user = yield service.user.info(options.body.uid);
      options.love_user = love_user;
      if (love_user) {
        extend_params.lover_name = love_user.nickname;
        extend_params.lover_avatar = love_user.headimgurl;
      } else {
        extend_params.lover_name = '我的爱人';
        extend_params.lover_avatar = app.config.ossURL + '/static/express_love/images/virtual_lover_avatar_x.png';

      }

      extend_params.theme_header = love.header;
      extend_params.theme_src = love.video;
      extend_params.theme_type = 'video';
      extend_params.theme_name = love.name;

      options.message.content = options.body.love_letter || '';

      options.message.bp_time = parseInt(love_item.duration);
      options.message.fee = parseInt(love_item.fee * 100);
      options.message.extend_params = extend_params;
      return options;

    }

    /**
         * 发红包处理
         * @param options
         * @returns {*}
         */
    * rp(options) {

      // num:29
      // money:3
      // content:3
      // desk_name:33
      // payWay:0
      const { ctx, service } = this;
      // console.log(options.body)

      const total = parseFloat(options.body.money);
      const count = parseFloat(options.body.num);
      const pkgs = ctx.helper.generateMoneyPackages(total, count);

      const data = {
        uid: options.userInfo.objectId,
        avatar: options.userInfo.headimgurl,
        nickname: options.userInfo.nickname,
        total,
        count,
        packages: pkgs,
        status: 'init',
        bpwall_id: options.bpwall_id

      };

      const rp = yield service.redpack.create(data);

      options.message.content = options.body.content || '恭喜发财';
      options.message.desk_name = options.body.desk_name;
      options.message.payWay = parseInt(options.body.payWay);
      options.message.fee = parseInt(options.body.money * 100);

      options.message.redpackid = rp.id;

      return options;
    }

  }

  return MessageService;
};


text:
This document covers running unit tests and integration tests within an existing Bosslet.

### Copy up dynamo information in spdb for testing
Now the spdb is a pypi installable it doesn't include the contents of
spdb/spdb/spatialdb/dynamo/
You need to tar up the contents of that directory and use ssh-tunnel to copy it to the endpoint for testing
```bash
$ cd spdb/spdb/spatialdb
$ tar czf /path/to/spdb-spatialdb-dynamo.tar.gz ./dynamo
$ cd spdb
$ tar rzf /path/to/spdb-spatialdb-dynamo.tar.gz ./requirements-test.txt
```

To ssh tunnel:
```bash
$ boss-manage/bin/bastion.py endpoint.hiderrt1.boss ssh-tunnel
```
Connect to localhost:31812 to be forwarded to 10.104.4.18:22

To scp file after tar:
```.bash
$ scp -P 31812 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no /path/to/spdb-spatialdb-dynamo.tar.gz ubuntu@localhost:
```

then untar contents into:
**/usr/local/lib/python3.5/site-packages/spdb/spatialdb**
```bash
$ cd /usr/local/lib/python3.5/site-packages/spdb/spatialdb
$ tar xf ~/spdb-spatialdb-dynamo.tar.gz
$ pip3 install -r requirements-test.txt
```

### Use Test script
If you want to automate the testing of the following
* Endpoint Unit Testing
* Endpoint Integration Testing
* SPDB Integration Tests
* Test the ndingest library

cut and paste the following into a test.sh script on the endpoint.
```bash
#!/usr/bin/env bash

read -n 1 -p "running in screen?, if not ctrl-c to stop: "
echo press ctrl-A D if you want to detach from screen

export RUN_HIGH_MEM_TESTS=true
cd /srv/www/django
sudo -E python3 manage.py test 2>&1 | tee /home/ubuntu/1_django_unittest.txt

cd /srv/www/django
sudo -E python3 manage.py test -- -c inttest.cfg 2>&1 | tee /home/ubuntu/2_django_inttest.txt

cd /usr/local/lib/python3.8/dist-packages/spdb
sudo nose2 2>&1 | tee /home/ubuntu/3_spdb_unittest.txt
sudo nose2 -c inttest.cfg 2>&1 | tee /home/ubuntu/4_spdb_inttest.txt

# Manual install for now.  Will likely remove use of pytest in the future.
sudo -H pip3 install pytest
cd /usr/local/lib/python3.8/dist-packages/ndingest
# Use randomized queue names and prepend 'test_' to bucket/index names.
export NDINGEST_TEST=1
pytest -c test_apl.cfg 2>&1 | tee /home/ubuntu/5_ndingest_test.txt
```
now look over the log files in the home directory.

## Unit Testing

### Run unit tests on Endpoint
If you are following these instructions for your personal development environment, skip the
export RUN_HIGH_MEM_TESTS line.  That line runs 2 tests that need >2.5GB of memory
to run and will fail in your environment

```shell
cd bin
./bastion.py endpoint.integration.boss ssh
export RUN_HIGH_MEM_TESTS=True
cd /srv/www/django
sudo -E python3 manage.py test
```
	output should say Ran XXX tests.
If the number changes often, the important part is that none of the tests should fail.

## Integration Testing

### Endpoint Integration Tests

#### Test While Logged Onto the Endpoint VM
Again, Skip the RUN_HIGH_MEM_TESTS line below if you are following these instructions for
your personal development environment.  That line runs 2 tests that need >2.5GB
of memory to run and will fail in your environment

```shell
export RUN_HIGH_MEM_TESTS=True
cd /srv/www/django
sudo -E python3 manage.py test -- -c inttest.cfg
```
	output should say 55 Tests OK with 7 skipped tests

#### SPDB Integration Tests
```shell
cd /usr/local/lib/python3.8/dist-packages/spdb
sudo nose2
sudo nose2 -c inttest.cfg
```

##### Test the ndingest library.
```shell
# Manual install for now.  Will likely remove use of pytest in the future.
sudo pip3 install pytest
cd /usr/local/lib/python3.8/dist-packages/ndingest
# Use randomized queue names and prepend 'test_' to bucket/index names.
export NDINGEST_TEST=1
pytest -c test_apl.cfg
```

### Cachemanager Integration Tests

#### Test While Logged Onto the Cachemanager VM

```shell
cd /srv/salt/boss-tools/files/boss-tools.git/cachemgr
sudo nose2
sudo nose2 -c inttest.cfg
```
	there is currently issues with some of the tests not getting setup correctly. cache-DB and cache-state-db need to be manutally set to 1.
	or the tests hang.

#### Test Using Intern From a Client

intern integration tests should be run from your local workstation or a VM
**not** running within the integration VPC.

First ensure intern is current:

```shell
# Clone the repository if you do not already have it.
git clone https://github.com/jhuapl-boss/intern.git

# Otherwise update with `pull`.
# git pull

# Make the repository the current working directory.
cd intern

# Check out the integration branch.
# If there is no current integration branch, use master.
git checkout integration

# Ensure dependencies are current.
sudo pip3 install -r requirements.txt
```

In your browser, open https://api.theboss.io/vX.Y/mgmt/token

Your browser should be redirected to the KeyCloak login page.

Create a new account and return to the token page.

Generate a token.

This token will be copied-pasted into the intern config file.

```shell
mkdir ~/.intern
EDITOR ~/.intern/intern.cfg
```

In your text editor, copy and paste the text config values below. Replace all
all tokens with the token displayed in your browser.

```
[Project Service]
protocol = https
host = api.theboss.io
# Replace with your token.
token = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

[Metadata Service]
protocol = https
host = api.theboss.io
# Replace with your token.
token = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

[Volume Service]
protocol = https
host = api.theboss.io
# Replace with your token.
token = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Additionally, create a copy of `~/.intern/intern.cfg` as `test.cfg` in the intern
repository directory.

##### Setup via the Django Admin Page

In your browser, go to https://api.theboss.io/admin

Login using the bossadmin account created previously (this was created during
the endpoint initialization and unit test step).

Click on `Boss roles`.

Click on `MANAGE ROLES`.

Find the user you created and add the `user-manager` and `resource-manager` roles to that user and save.

Next login as that user so the new roles are properly synced.

##### Run Intern Integration Tests

Finally, open a shell and run the integration tests:

```shell
# Go to the location of your cloned intern repository.
cd intern.git
python3 -m unittest discover -p int_test*
```

Output should say:

```
Ran x tests in x.xxxs.

OK
```

#### Run Ingest Tests

* cd ingest-test
* run python3 ./setup_test.py
* Copy the export and and ingest run commands
* cd ../ingest-client
* paste the copied commands above.
    this should start loading the ingest data
* cd back to the ingest-test directory
* python3 validate_ingest.py


text:
<?php
class Block extends DataObject {

	// private static $singular_name = 'Block';
	// private static $plural_name = 'Blocks';
	private static $first_write = false;

	//public static $default_sort = 'SortOrder';

	private static $db = array(
		'Name' 		=> 'Varchar',
		'Header' 	=> "Enum('None, h1, h2, h3, h4, h5, h6')",
        'Link' 		=> 'Varchar',
		'VideoURL' 	=> 'Varchar',
		'Template' 	=> 'Varchar',
		'Active' 	=> 'Boolean(1)',
		'Classes' 	=> 'Text'
    );

	private static $many_many = array(
		'Images' => 'Image',
		'Files' => 'File'
    );

	private static $many_many_extraFields = array(
		'Images' => array('SortOrder' => 'Int'),
		'Files' => array('SortOrder' => 'Int')
	);

	private static $has_one = array(
		'Page' => 'Page'
	);

	private static $has_many = array(
        'BlockTranslations' => 'BlockTranslation'
    );

	private static $defaults = array(
		'Active' => 1,
		'Page_Blocks[SortOrder]' => 999 // TODO: Fix sorting, new blocks should be added to the bottom of the list/gridfield
	);

	public function canView($member=null) {
		return Permission::check('ADMIN') || Permission::check('CMS_ACCESS_BlockAdmin') || Permission::check('CMS_ACCESS_LeftAndMain') ;
	}

	public function canEdit($member=null) {
		return Permission::check('ADMIN') || Permission::check('CMS_ACCESS_BlockAdmin') || Permission::check('CMS_ACCESS_LeftAndMain') ;
	}

	public function canCreate($member=null) {
		return Permission::check('ADMIN') || Permission::check('CMS_ACCESS_BlockAdmin') || Permission::check('CMS_ACCESS_LeftAndMain') ;
	}

	public function canPublish($member=null) {
		return Permission::check('ADMIN') || Permission::check('CMS_ACCESS_BlockAdmin') || Permission::check('CMS_ACCESS_LeftAndMain') ;
	}

	private static $summary_fields = array(
		'ID' => 'ID',
		'Thumbnail' => 'Thumbnail',
		'Name' => 'Name',
		'Template' => 'Template',
		'ClassName' => 'Type',
		'getIsActive' => 'Active',
	);

	private static $searchable_fields = array(
		'ID' => 'PartialMatchFilter',
		'Name' => 'PartialMatchFilter',
		'Header' => 'PartialMatchFilter',
		'Active'
	);

	public function validate() {
        $result = parent::validate();
        if($this->Name == '') {
            $result->error('A block must have a name');
        }
        return $result;
    }

	public function getIsActive(){
		return $this->Active ? 'Yes' : 'No';
	}

	public function getCMSFields() {
		$fields = parent::getCMSFields();

		$fields->removeByName('SortOrder');
		$fields->removeByName('Pages');
		$fields->removeByName('Active');
		$fields->removeByName('Header');
		$fields->removeByName('Images');
		$fields->removeByName('Files');
		$fields->removeByName('BlockTranslationsID');
		$fields->removeByName('BlockTranslations');

		//Translations
		foreach (json_decode(SS_LANGUAGES) as $key => $lang) {
			if ($this->ID) {
				$existingTrans = BlockTranslation::get()->filter([
					'BlockID' => $this->ID,
					'Language' => $key
				])->first();
			}

		  	$fields->addFieldsToTab("Root.".$lang, new TextField('Title-'.$key, 'Title', isset($existingTrans->Title) ? $existingTrans->Title : ''));

		  	if (SS_BLOCK_RTE) {
		  		$fields->addFieldsToTab("Root.".$lang, new HTMLEditorField('Content-'.$key, 'Content', isset($existingTrans->Content) ? $existingTrans->Content : ''));
		  	} else {
		  		$fields->addFieldsToTab("Root.".$lang, new TextareaField('Content-'.$key, 'Content', isset($existingTrans->Content) ? $existingTrans->Content : ''));
		  	}

		}

		// Media tab
		$fields->addFieldToTab('Root', new TabSet('Media'));

		$imgField = new SortableUploadField('Images', 'Images');
		$imgField->allowedExtensions = array('jpg', 'gif', 'png');

		$fields->addFieldsToTab("Root.Main", new TextField('Name', 'Name of block'));
		$fields->addFieldsToTab("Root.Main", new DropdownField('Header', 'Use name as header', $this->dbObject('Header')->enumValues()), 'Content');
		$fields->addFieldsToTab("Root.Main", new TextField('Classes', 'Classes'));

		$fields->addFieldToTab('Root.Media.Images', $imgField);

		$fileField = new SortableUploadField('Files', 'Files');

		$fields->addFieldToTab('Root.Media.Files', $fileField);
		$fields->addFieldToTab('Root.Media.Video', new TextField('VideoURL', 'Video URL'));

		// Template tab
		$optionset = array();
		$theme	= SS_PROJ_DEFAULT_THEME;
		$src	= BASE_PATH . "/themes/".$theme."/templates/BlockTemplates/";
		$imgsrc	= "/themes/".$theme."/templates/BlockTemplates/";

		// TODO: If ClassName == Block, return the templates of the folder.
		// If ClassName is something else (extension of block) then see if there is a folder with that name and only return templates from this folder

		if(file_exists($src)) {
			foreach (glob($src . "*.ss") as $filename) {
				$name = $this->file_ext_strip(basename($filename));

				// Is there a template thumbnail
				$thumbnail = (file_exists($src . $name . '.png') ? '' : ''); // TODO: Perhaps just add blank as alt for image, no need to check for existance?
				$html = '
'.$thumbnail.'
'. $name .'';
				$optionset[$name] = $html;
			}

			$tplField = OptionsetField::create(
				"Template",
				"Choose a template",
				$optionset,
				$this->Template
			)->addExtraClass('stacked');
			$fields->addFieldsToTab("Root.Template", $tplField);

		} else {
			$fields->addFieldsToTab("Root.Template", new LiteralField ($name = "literalfield", $content = '
Warning: The folder '.$src.' was not found.
'));
		}

		// Settings tab
		$fields->addFieldsToTab("Root.Settings", new CheckboxField('Active', 'Active'));
		$fields->addFieldsToTab("Root.Settings", new TextField('Link', 'Link'));

		$PagesConfig = GridFieldConfig_RelationEditor::create(10);
		$PagesConfig->removeComponentsByType('GridFieldAddNewButton');

		// $fields->addFieldToTab("Root.Settings", $gridField);

		return $fields;
	}

	function onBeforeWrite() {
		parent::onBeforeWrite();

		if (!$this->ID) {
			$this->first_write = true;
		}

	}

	function onAfterWrite() {
		parent::onAfterWrite();

	}

	// Should only unlink if a block is on more than one page
	public function canDelete($member = null) {
		if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();

		// extended access checks
		$results = $this->extend('canDelete', $member);

		if($results && is_array($results)) {
			if(!min($results)) return false;
			else return true;
		}

		// No member found
		if(!($member && $member->exists())) return false;

		return true;
	}

	/* TODO: add function to calculate image widths based on columns? */
	public function ColumnClass($totalitems) {
		$totalcolumns	= 12; // should be configurable
		$columns = $totalcolumns / $totalitems;
		return $columns;
	}

	public function getThumbnail() {
		if ($this->Images()->Count() >= 1) {
			return $this->Images()->First()->croppedImage(50,40);
		}
	}

	// Returns only the file extension (without the period).
	function file_ext($filename) {
		if( !preg_match('/\./', $filename) ) return '';
		return preg_replace('/^.*\./', '', $filename);
	}

	// Returns the file name, without the extension.
	function file_ext_strip($filename){
		return preg_replace('/\.[^.]*$/', '', $filename);
	}

	public function write()
	{
		$id = parent::write();

		foreach (json_decode(SS_LANGUAGES) as $slang => $lang) {
			if (isset($this->record['Title-'.$slang])) {
				$existingTrans = BlockTranslation::get()->filter([
					'BlockID' => $id,
					'Language' => $slang
				])->first();

				$trans = [
					'Language' => $slang
				];
				foreach ($this->record as $key => $value) {
					if (strpos($key, $slang) !== false) {
						$key = explode('-', $key);
						$trans[$key[0]] = $value;
					}
				}

				if ($existingTrans) {
					DB::query('UPDATE "BlockTranslation" SET "Title"=\''.$trans['Title'].'\', "Content"=\''.pg_escape_string($trans['Content']).'\' WHERE "ID" = '.$existingTrans->ID.';');
				} else {
					$newTrans = BlockTranslation::create();
					$newTrans->Title = $trans['Title'];
					$newTrans->Content = $trans['Content'];
					$newTrans->Language = $slang;
					$newTrans->BlockID = $id;
					$newTrans->write();
				}
			}
		}
	}
}


text:
import { IRawDiff, DiffHunk, DiffHunkHeader, DiffLine, DiffLineType } from '../models/diff'
import { assertNever } from '../lib/fatal-error'

// https://en.wikipedia.org/wiki/Diff_utility
//
// @@ -l,s +l,s @@ optional section heading
//
// The hunk range information contains two hunk ranges. The range for the hunk of the original
// file is preceded by a minus symbol, and the range for the new file is preceded by a plus
// symbol. Each hunk range is of the format l,s where l is the starting line number and s is
// the number of lines the change hunk applies to for each respective file.
//
// In many versions of GNU diff, each range can omit the comma and trailing value s,
// in which case s defaults to 1
const diffHeaderRe = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/

const DiffPrefixAdd: '+' = '+'
const DiffPrefixDelete: '-' = '-'
const DiffPrefixContext: ' ' = ' '
const DiffPrefixNoNewline: '\\' = '\\'

type DiffLinePrefix = typeof DiffPrefixAdd | typeof DiffPrefixDelete | typeof DiffPrefixContext | typeof DiffPrefixNoNewline
const DiffLinePrefixChars: Set<DiffLinePrefix> = new Set([ DiffPrefixAdd, DiffPrefixDelete, DiffPrefixContext, DiffPrefixNoNewline ])

interface IDiffHeaderInfo {
  /**
   * Whether or not the diff header contained a marker indicating
   * that a diff couldn't be produced due to the contents of the
   * new and/or old file was binary.
   */
  readonly isBinary: boolean
}

/**
 * A parser for the GNU unified diff format
 *
 * See https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html
 */
export class DiffParser {

  /**
   * Line start pointer.
   *
   * The offset into the text property where the current line starts (ie either zero
   * or one character ahead of the last newline character).
   */
  private ls: number

  /**
   * Line end pointer.
   *
   * The offset into the text property where the current line ends (ie it points to
   * the newline character) or -1 if the line boundary hasn't been determined yet
   */
  private le: number

  /**
   * The text buffer containing the raw, unified diff output to be parsed
   */
  private text: string

  public constructor() {
    this.reset()
  }

  /**
   * Resets the internal parser state so that it can be reused.
   *
   * This is done automatically at the end of each parse run.
   */
  private reset() {
    this.ls = 0
    this.le = -1
    this.text = ''
  }

  /**
   * Aligns the internal character pointers at the boundaries of
   * the next line.
   *
   * Returns true if successful or false if the end of the diff
   * has been reached.
   */
  private nextLine(): boolean {
    this.ls = this.le + 1

    // We've reached the end of the diff
    if (this.ls >= this.text.length) {
      return false
    }

    this.le = this.text.indexOf('\n', this.ls)

    // If we can't find the next newline character we'll put our
    // end pointer at the end of the diff string
    if (this.le === -1) {
      this.le = this.text.length
    }

    // We've succeeded if there's anything to read in between the
    // start and the end
    return this.ls !== this.le
  }

  /**
   * Advances to the next line and returns it as a substring
   * of the raw diff text. Returns null if end of diff was
   * reached.
   */
  private readLine(): string | null {
    return this.nextLine()
      ? this.text.substring(this.ls, this.le)
      : null
  }

  /** Tests if the current line starts with the given search text */
  private lineStartsWith(searchString: string): boolean {
    return this.text.startsWith(searchString, this.ls)
  }

  /** Tests if the current line ends with the given search text */
  private lineEndsWith(searchString: string): boolean {
    return this.text.endsWith(searchString, this.le)
  }

  /**
   * Returns the starting character of the next line without
   * advancing the internal state. Returns null if advancing
   * would mean reaching the end of the diff.
   */
  private peek(): string | null {
    const p = this.le + 1
    return p < this.text.length ? this.text[p] : null
  }

  /**
   * Parse the diff header, meaning everything from the
   * start of the diff output to the end of the line beginning
   * with +++
   *
   * Example diff header:
   *
   *   diff --git a/app/src/lib/diff-parser.ts b/app/src/lib/diff-parser.ts
   *   index e1d4871..3bd3ee0 100644
   *   --- a/app/src/lib/diff-parser.ts
   *   +++ b/app/src/lib/diff-parser.ts
   *
   * Returns an object with information extracted from the diff
   * header (currently whether it's a binary patch) or null if
   * the end of the diff was reached before the +++ line could be
   * found (which is a valid state).
   */
  private parseDiffHeader(): IDiffHeaderInfo | null {

    // TODO: There's information in here that we might want to
    // capture, such as mode changes
    while (this.nextLine()) {

      if (this.lineStartsWith('Binary files ') && this.lineEndsWith('differ')) {
        return { isBinary: true }
      }

      if (this.lineStartsWith('+++')) {
        return { isBinary: false }
      }
    }

    // It's not an error to not find the +++ line, see the
    // 'parses diff of empty file' test in diff-parser-tests.ts
    return null
  }

  /**
   * Attempts to convert a RegExp capture group into a number.
   * If the group doesn't exist or wasn't captured the function
   * will return the value of the defaultValue parameter or throw
   * an error if no default value was provided. If the captured
   * string can't be converted to a number an error will be thrown.
   */
  private numberFromGroup(m: RegExpMatchArray, group: number, defaultValue: number | null = null): number {
    const str = m[group]
    if (!str) {
      if (!defaultValue) {
        throw new Error(`Group ${group} missing from regexp match and no defaultValue was provided`)
      }

      return defaultValue
    }

    const num = parseInt(str, 10)

    if (isNaN(num)) {
      throw new Error(`Could not parse capture group ${group} into number: ${str}`)
    }

    return num
  }

  /**
   * Parses a hunk header or throws an error if the given line isn't
   * a well-formed hunk header.
   *
   * We currently only extract the line number information and
   * ignore any hunk headings.
   *
   * Example hunk header:
   *
   * @@ -84,10 +82,8 @@ export function parseRawDiff(lines: ReadonlyArray<string>): Diff {
   *
   * Where everything after the last @@ is what's known as the hunk, or section, heading
   */
  private parseHunkHeader(line: string): DiffHunkHeader {
    const m = diffHeaderRe.exec(line)
    if (!m) { throw new Error(`Invalid hunk header format: '${line}'`) }

    // If endLines are missing default to 1, see diffHeaderRe docs
    const oldStartLine = this.numberFromGroup(m, 1)
    const oldLineCount = this.numberFromGroup(m, 2, 1)
    const newStartLine = this.numberFromGroup(m, 3)
    const newLineCount = this.numberFromGroup(m, 4, 1)

    return new DiffHunkHeader(oldStartLine, oldLineCount, newStartLine, newLineCount)
  }

  /**
   * Convenience function which lets us leverage the type system to
   * prove exhaustive checks in parseHunk.
   *
   * Takes an arbitrary string and checks to see if the first character
   * of that string is one of the allowed prefix characters for diff
   * lines (ie lines in between hunk headers).
   */
  private parseLinePrefix(c: string | null): DiffLinePrefix | null {

    // Since we know that DiffLinePrefixChars and the DiffLinePrefix type
    // include the same characters we can tell the type system that we
    // now know that c[0] is one of the characters in the DifflinePrefix set
    if (c && c.length && (DiffLinePrefixChars as Set<string>).has(c[0])) {
      return c[0] as DiffLinePrefix
    }

    return null
  }

  /**
   * Parses a hunk, including its header or throws an error if the diff doesn't
   * contain a well-formed diff hunk at the current position.
   *
   * Expects that the position has been advanced to the beginning of a presumed
   * diff hunk header.
   *
   * @param linesConsumed The number of unified diff lines consumed up until
   *                      this point by the diff parser. Used to give the
   *                      position and length (in lines) of the parsed hunk
   *                      relative to the overall parsed diff. These numbers
   *                      have no real meaning in the context of a diff and
   *                      are only used to aid the app in line-selections.
   */
  private parseHunk(linesConsumed: number): DiffHunk {

    const headerLine = this.readLine()
    if (!headerLine) {
      throw new Error('Expected hunk header but reached end of diff')
    }

    const header = this.parseHunkHeader(headerLine)
    const lines = new Array<DiffLine>()
    lines.push(new DiffLine(headerLine, DiffLineType.Hunk, null, null))

    let c: DiffLinePrefix | null

    let rollingDiffBeforeCounter = header.oldStartLine
    let rollingDiffAfterCounter = header.newStartLine

    while ((c = this.parseLinePrefix(this.peek()))) {

      const line = this.readLine()

      if (!line) {
        throw new Error('Expected unified diff line but reached end of diff')
      }

      // A marker indicating that the last line in the original or the new file
      // is missing a trailing newline. In other words, the presence of this marker
      // means that the new and/or original file lacks a trailing newline.
      //
      // When we find it we have to look up the previous line and set the
      // noTrailingNewLine flag
      if (c === DiffPrefixNoNewline) {

        // See https://github.com/git/git/blob/21f862b498925194f8f1ebe8203b7a7df756555b/apply.c#L1725-L1732
        if (line.length < 12) {
          throw new Error(`Expected no newline at end of file marker but got ${line}`)
        }

        const previousLineIndex = lines.length - 1
        const previousLine = lines[previousLineIndex]
        lines[previousLineIndex] = previousLine.withNoTrailingNewLine(true)

        continue
      }

      let diffLine: DiffLine

      if (c === DiffPrefixAdd) {
        diffLine = new DiffLine(line, DiffLineType.Add, null, rollingDiffAfterCounter++)
      } else if (c === DiffPrefixDelete) {
        diffLine = new DiffLine(line, DiffLineType.Delete, rollingDiffBeforeCounter++, null)
      } else if (c === DiffPrefixContext) {
        diffLine = new DiffLine(line, DiffLineType.Context, rollingDiffBeforeCounter++, rollingDiffAfterCounter++)
      } else {
        return assertNever(c, `Unknown DiffLinePrefix: ${c}`)
      }

      lines.push(diffLine)
    }

    if (lines.length === 1) {
      throw new Error('Malformed diff, empty hunk')
    }

    return new DiffHunk(header, lines, linesConsumed, linesConsumed + lines.length - 1)
  }

  /**
   * Parse a well-formed unified diff into hunks and lines.
   *
   * @param text A unified diff produced by git diff, git log --patch
   *             or any other git plumbing command that produces unified
   *             diffs.
   */
  public parse(text: string): IRawDiff {

    this.text = text

    try {
      const headerInfo = this.parseDiffHeader()

      const headerEnd = this.le
      const header = this.text.substring(0, headerEnd)

      // empty diff
      if (!headerInfo) {
        return { header, contents: '', hunks: [], isBinary: false }
      }

      if (headerInfo.isBinary) {
        return { header, contents: '', hunks: [], isBinary: true }
      }

      const hunks = new Array<DiffHunk>()
      let linesConsumed = 0

      do {
        const hunk = this.parseHunk(linesConsumed)
        hunks.push(hunk)
        linesConsumed += hunk.lines.length
      } while (this.peek())

      const contents = this.text
        .substring(headerEnd + 1, this.le)
        // Note that this simply returns a reference to the
        // substring if no match is found, it does not create
        // a new string instance.
        .replace(/\n\\ No newline at end of file/g, '')

      return { header, contents, hunks, isBinary: headerInfo.isBinary }
    } finally {
      this.reset()
    }
  }
}


text:
require 'spec_helper'

RSpec.describe Masterman::Collection do
  let(:klass) do
    Class.new do
      include Masterman

      masterman.mount(
        path: File.expand_path('../../fixtures/masterdata.yml', __FILE__),
        loader: :yaml
      )

      masterman.attr_reader :id, :name
    end
  end

  describe '.relation' do
    subject { klass.relation }
    it { is_expected.to be_a(Masterman::Relation) }
  end

  describe 'methods' do
    it 'should not raise error' do
      %i(all first first! last last! exists? any? many? ids).each do |method|
        expect { klass.public_send(method) }.to_not raise_error
      end

      %i(find take take!).each do |method|
        expect { klass.public_send(method, 1) }.to_not raise_error
      end

      %i(pluck).each do |method|
        expect { klass.public_send(method, :id) }.to_not raise_error
      end

      %i(find_by find_by!).each do |method|
        expect { klass.public_send(method, id: 1) }.to_not raise_error
      end
    end
  end
end


text:
The service broker has both unit and end-to-end tests.
End to end tests are generated from the documentation and examples and run outside the standard `go test` framework.
This ensures the auto-generated docs are always up-to-date and the examples work.
By executing the examples as an OSB client, it also ensures the service broker implements the OSB spec correctly.

To run the suite of end-to-end tests:

1. Start an instance of the broker `./gcp-service-broker serve`.
2. In a separate window, run the examples: `./gcp-service-broker client run-examples`
3. Wait for the examples to run and check the exit code. Exit codes other than 0 mean the end-to-end tests failed.

You can also target specific services in the end-to-end tests using the `--service-name` flag.
See `./gcp-service-broker client run-examples --help` for more details.

## Database Setup

You can set up a local MySQL database for testing using Docker:

```
$ docker run -p 3306:3306 --name test-mysql -e MYSQL_ROOT_PASSWORD=password -d mysql:5.7
$ docker exec -it test-mysql mysql -uroot -p
$ mysql> CREATE DATABASE servicebroker;
$ mysql> exit
```

Or, you can run the service broker using SQLite3 for development by specifying
the `db.type` and `db.path` fields:

```
db.type: sqlite3
db.path: service-broker-db.sqlite3
```

## Database Exploration

You can debug the database locally using the `show` sub-command.
It will dump a database table as JSON to stdout.
You can dump: `bindings`, `instances`, `migrations`, and `provisions`.

```
$ ./gcp-service-broker --config test.yaml show provisions
[
    {
        "ID": 1,
        "CreatedAt": "2018-07-17T10:08:07-07:00",
        "UpdatedAt": "2018-07-17T10:08:07-07:00",
        "DeletedAt": null,
        "ServiceInstanceId": "my-cloud-storage",
        "RequestDetails": ""
    }
]
```

## Configuration

Rather than setting environment variables to run the broker you can use the
settings file below and just set the service account JSON as an environment variable:

    ROOT_SERVICE_ACCOUNT_JSON=$(cat service-account.json) ./gcp-service-broker serve --config testconfig.yml

**testconfig.yml**

```
db:
  host: localhost
  name: servicebroker
  password: password
  port: "3306"
  user: root
api:
  user: user
  password: pass
  port: 8000
```

## Useful commands

Create unbind commands for all bindings:

  ./gcp-service-broker show bindings | jq --raw-output '.[] | "./gcp-service-broker client unbind --bindingid \(.BindingId) --instanceid \(.ServiceInstanceId) --planid \(.PlanId) --serviceid \(.ServiceId)"'

Create deprovision commands for all bindings:

  ./gcp-service-broker show instances | jq --raw-output '.[] | "./gcp-service-broker client deprovision --instanceid \(.ID) --serviceid \(.ServiceId) --planid \(.PlanId)"'


text:
<!DOCTYPE html>

		<title>opusX</title>
		<link rel="stylesheet" href="<?php echo _CSS_PATH; ?>/bootstrap.min.css" />
		<link rel="stylesheet" href="<?php echo _CSS_PATH; ?>/opxstyles.css" />
		<link rel="stylesheet" href="<?php echo _CSS_PATH; ?>/dataTables.bootstrap.min.css" />
		<link rel="stylesheet" href="<?php echo _CSS_PATH; ?>/bootstrap-select.min.css" />
		<link rel="stylesheet" href="<?php echo _CSS_PATH; ?>/select2.css" />
		<link rel="stylesheet" href="<?php echo _CSS_PATH; ?>/dataTables.bootstrap.select.min.css" />
		<link rel="stylesheet" href="<?php echo _JS_PATH; ?>/plugins/fuelux/css/fuelux.min.css" />
		<link rel="stylesheet" href="<?php echo _JS_PATH; ?>/plugins/bootstrap-multiselect/css/bootstrap-multiselect.css" />

				<?php echo $main_menu; ?>

		<div id="<?php echo $id_content; ?>" class="container">

				<?php if(isset($sidebar)): ?>

					<?php echo $sidebar; ?>

				<?php endif; ?>
				<?php if(isset($title_content)): ?>

<?php echo $title_content; ?>

							<?php echo $main_content; ?>

				<?php else: ?>
					<?php echo $main_content; ?>
				<?php endif; ?>

			<?php echo $main_footer; ?>


text:
/**
 * Provides classes to control the perspective.<br/>
 */
package tubame.knowhow.plugin.ui.perspective;


text:
from office365.sharepoint.utilities.email_properties import EmailProperties
from office365.sharepoint.utilities.utility import Utility
from tests import test_user_principal_name
from tests.sharepoint.sharepoint_case import SPTestCase

class TestUtility(SPTestCase):

    @classmethod
    def setUpClass(cls):
        super(TestUtility, cls).setUpClass()

    def test1_get_current_user_email_addresses(self):
        result = Utility.get_current_user_email_addresses(self.client).execute_query()
        self.assertIsNotNone(result.value)

    def test2_get_user_permission_levels(self):
        result = Utility.get_user_permission_levels(self.client).execute_query()
        self.assertIsNotNone(result.value)

    def test3_send_email(self):
        email_props = EmailProperties("The new cafeteria is open.", "Meet for lunch?",
                                      [test_user_principal_name])
        Utility.send_email(self.client, email_props).execute_query()

    def test4_expand_groups_to_principals(self):
        owner_group = self.client.web.associated_owner_group.get().execute_query()
        result = Utility.expand_groups_to_principals(self.client, [owner_group.login_name], 10).execute_query()
        self.assertIsNotNone(result.value)

    def test5_create_email_body_for_invitation(self):
        result = Utility.create_email_body_for_invitation(self.client, "SitePages/Home.aspx").execute_query()
        self.assertIsNotNone(result.value)


text:
package net.itimothy.elasticsearch.routes.model;

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

public class Route extends Description {
    private String apiPath;
    private HttpMethod method;
    private String group;
    private Model model;
    private String name;
    private List<Parameter> parameters;
    private String description;
    private String notes;
    private List<Response> responses;
    private List<String> produces;
    private List<String> consumes;

    public Route(String minVersion, String maxVersion, String apiPath, HttpMethod method, String group, Model model, String name, List<Parameter> parameters, String description, String notes, List<Response> responses, List<String> produces, List<String> consumes) {
        super(minVersion, maxVersion);
        this.apiPath = apiPath;
        this.method = method;
        this.group = group;
        this.model = model;
        this.name = name;
        this.parameters = parameters;
        this.description = description;
        this.notes = notes;
        this.responses = responses;
        this.produces = produces;
        this.consumes = consumes;
    }

    public static RouteBuilder builder() {
        return new RouteBuilder();
    }

    protected boolean canEqual(final Object other) {
        return other instanceof Route;
    }

    public String getCategory() {
        String[] parts = group.split(": ");
        return parts.length > 1 ? parts[0] : "misc";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Route)) return false;

        Route route = (Route) o;

        if (apiPath != null ? !apiPath.equals(route.apiPath) : route.apiPath != null) return false;
        if (consumes != null ? !consumes.equals(route.consumes) : route.consumes != null)
            return false;
        if (description != null ? !description.equals(route.description) : route.description != null)
            return false;
        if (group != null ? !group.equals(route.group) : route.group != null) return false;
        if (method != route.method) return false;
        if (model != null ? !model.equals(route.model) : route.model != null) return false;
        if (name != null ? !name.equals(route.name) : route.name != null) return false;
        if (notes != null ? !notes.equals(route.notes) : route.notes != null) return false;
        if (parameters != null ? !parameters.equals(route.parameters) : route.parameters != null)
            return false;
        if (produces != null ? !produces.equals(route.produces) : route.produces != null)
            return false;
        if (responses != null ? !responses.equals(route.responses) : route.responses != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = apiPath != null ? apiPath.hashCode() : 0;
        result = 31 * result + (method != null ? method.hashCode() : 0);
        result = 31 * result + (group != null ? group.hashCode() : 0);
        result = 31 * result + (model != null ? model.hashCode() : 0);
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
        result = 31 * result + (description != null ? description.hashCode() : 0);
        result = 31 * result + (notes != null ? notes.hashCode() : 0);
        result = 31 * result + (responses != null ? responses.hashCode() : 0);
        result = 31 * result + (produces != null ? produces.hashCode() : 0);
        result = 31 * result + (consumes != null ? consumes.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Route{" +
            "apiPath='" + apiPath + '\'' +
            ", method=" + method +
            ", group='" + group + '\'' +
            ", model=" + model +
            ", name='" + name + '\'' +
            ", parameters=" + parameters +
            ", routes='" + description + '\'' +
            ", notes='" + notes + '\'' +
            ", responses=" + responses +
            ", produces=" + produces +
            ", consumes=" + consumes +
            '}';
    }

    public String getApiPath() {
        return this.apiPath;
    }

    public void setApiPath(final String apiPath) {
        this.apiPath = apiPath;
    }

    public List<String> getConsumes() {
        return this.consumes;
    }

    public void setConsumes(final List<String> consumes) {
        this.consumes = consumes;
    }

    public String getDescription() {
        return this.description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    public String getGroup() {
        return this.group;
    }

    public void setGroup(final String group) {
        this.group = group;
    }

    public HttpMethod getMethod() {
        return this.method;
    }

    public void setMethod(final HttpMethod method) {
        this.method = method;
    }

    public Model getModel() {
        return this.model;
    }

    public void setModel(final Model model) {
        this.model = model;
    }

    public String getName() {
        return this.name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public String getNotes() {
        return this.notes;
    }

    public void setNotes(final String notes) {
        this.notes = notes;
    }

    public List<Parameter> getParameters() {
        return this.parameters;
    }

    public void setParameters(final List<Parameter> parameters) {
        this.parameters = parameters;
    }

    public List<String> getProduces() {
        return this.produces;
    }

    public void setProduces(final List<String> produces) {
        this.produces = produces;
    }

    public List<Response> getResponses() {
        return this.responses;
    }

    public void setResponses(final List<Response> responses) {
        this.responses = responses;
    }

    public static class RouteBuilder {

        private String minVersion;
        private String maxVersion;
        private String apiPath;
        private HttpMethod method;
        private String group;
        private Model model;
        private String name;
        private List<Parameter> parameters;
        private String description;
        private String notes;
        private List<Response> responses;
        private List<String> produces;
        private List<String> consumes;

        RouteBuilder() {
        }

        public RouteBuilder apiPath(final String apiPath) {
            this.apiPath = apiPath;
            return this;
        }

        public Route build() {
            return new Route(minVersion, maxVersion, apiPath, method, group, model, name, parameters, description, notes, responses, produces, consumes);
        }

        public RouteBuilder consumes(final List<String> consumes) {
            this.consumes = consumes;
            return this;
        }

        public RouteBuilder description(final String description) {
            this.description = description;
            return this;
        }

        public RouteBuilder group(final String group) {
            this.group = group;
            return this;
        }

        public RouteBuilder maxVersion(final String maxVersion) {
            this.maxVersion = maxVersion;
            return this;
        }

        public RouteBuilder method(final HttpMethod method) {
            this.method = method;
            return this;
        }

        public RouteBuilder minVersion(final String minVersion) {
            this.minVersion = minVersion;
            return this;
        }

        public RouteBuilder model(final Model model) {
            this.model = model;
            return this;
        }

        public RouteBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public RouteBuilder notes(final String notes) {
            this.notes = notes;
            return this;
        }

        public RouteBuilder parameters(final List<Parameter> parameters) {
            this.parameters = parameters;
            return this;
        }

        public RouteBuilder parameters(Parameter... parameters) {
            return parameters(Arrays.asList(parameters));
        }

        public RouteBuilder produces(final List<String> produces) {
            this.produces = produces;
            return this;
        }

        public RouteBuilder responses(final List<Response> responses) {
            this.responses = responses;
            return this;
        }

        @Override
        public String toString() {
            return "RouteBuilder{" +
                "minVersion='" + minVersion + '\'' +
                ", maxVersion='" + maxVersion + '\'' +
                ", apiPath='" + apiPath + '\'' +
                ", method=" + method +
                ", group='" + group + '\'' +
                ", model=" + model +
                ", name='" + name + '\'' +
                ", parameters=" + parameters +
                ", routes='" + description + '\'' +
                ", notes='" + notes + '\'' +
                ", responses=" + responses +
                ", produces=" + produces +
                ", consumes=" + consumes +
                '}';
        }
    }
}


text:
package modfile

import (
	"bytes"
	"errors"
	"fmt"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"unicode"

	"cmd/go/internal/module"
	"cmd/go/internal/semver"
)

// A File is the parsed, interpreted form of a go.mod file.
type File struct {
	Module  *Module
	Go      *Go
	Require []*Require
	Exclude []*Exclude
	Replace []*Replace

	Syntax *FileSyntax
}

// A Module is the module statement.
type Module struct {
	Mod    module.Version
	Syntax *Line
}

// A Go is the go statement.
type Go struct {
	Version string // "1.23"
	Syntax  *Line
}

// A Require is a single require statement.
type Require struct {
	Mod      module.Version
	Indirect bool // has "// indirect" comment
	Syntax   *Line
}

// An Exclude is a single exclude statement.
type Exclude struct {
	Mod    module.Version
	Syntax *Line
}

// A Replace is a single replace statement.
type Replace struct {
	Old    module.Version
	New    module.Version
	Syntax *Line
}

func (f *File) AddModuleStmt(path string) error {
	if f.Syntax == nil {
		f.Syntax = new(FileSyntax)
	}
	if f.Module == nil {
		f.Module = &Module{
			Mod:    module.Version{Path: path},
			Syntax: f.Syntax.addLine(nil, "module", AutoQuote(path)),
		}
	} else {
		f.Module.Mod.Path = path
		f.Syntax.updateLine(f.Module.Syntax, "module", AutoQuote(path))
	}
	return nil
}

func (f *File) AddComment(text string) {
	if f.Syntax == nil {
		f.Syntax = new(FileSyntax)
	}
	f.Syntax.Stmt = append(f.Syntax.Stmt, &CommentBlock{
		Comments: Comments{
			Before: []Comment{
				{
					Token: text,
				},
			},
		},
	})
}

type VersionFixer func(path, version string) (string, error)

// Parse parses the data, reported in errors as being from file,
// into a File struct. It applies fix, if non-nil, to canonicalize all module versions found.
func Parse(file string, data []byte, fix VersionFixer) (*File, error) {
	return parseToFile(file, data, fix, true)
}

// ParseLax is like Parse but ignores unknown statements.
// It is used when parsing go.mod files other than the main module,
// under the theory that most statement types we add in the future will
// only apply in the main module, like exclude and replace,
// and so we get better gradual deployments if old go commands
// simply ignore those statements when found in go.mod files
// in dependencies.
func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) {
	return parseToFile(file, data, fix, false)
}

func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File, error) {
	fs, err := parse(file, data)
	if err != nil {
		return nil, err
	}
	f := &File{
		Syntax: fs,
	}

	var errs bytes.Buffer
	for _, x := range fs.Stmt {
		switch x := x.(type) {
		case *Line:
			f.add(&errs, x, x.Token[0], x.Token[1:], fix, strict)

		case *LineBlock:
			if len(x.Token) > 1 {
				if strict {
					fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " "))
				}
				continue
			}
			switch x.Token[0] {
			default:
				if strict {
					fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " "))
				}
				continue
			case "module", "require", "exclude", "replace":
				for _, l := range x.Line {
					f.add(&errs, l, x.Token[0], l.Token, fix, strict)
				}
			}
		}
	}

	if errs.Len() > 0 {
		return nil, errors.New(strings.TrimRight(errs.String(), "\n"))
	}
	return f, nil
}

var goVersionRE = regexp.MustCompile(`([1-9][0-9]*)\.(0|[1-9][0-9]*)`)

func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
	// If strict is false, this module is a dependency.
	// We ignore all unknown directives as well as main-module-only
	// directives like replace and exclude. It will work better for
	// forward compatibility if we can depend on modules that have unknown
	// statements (presumed relevant only when acting as the main module)
	// and simply ignore those statements.
	if !strict {
		switch verb {
		case "module", "require", "go":
			// want these even for dependency go.mods
		default:
			return
		}
	}

	switch verb {
	default:
		fmt.Fprintf(errs, "%s:%d: unknown directive: %s\n", f.Syntax.Name, line.Start.Line, verb)

	case "go":
		if f.Go != nil {
			fmt.Fprintf(errs, "%s:%d: repeated go statement\n", f.Syntax.Name, line.Start.Line)
			return
		}
		if len(args) != 1 || !goVersionRE.MatchString(args[0]) {
			fmt.Fprintf(errs, "%s:%d: usage: go 1.23\n", f.Syntax.Name, line.Start.Line)
			return
		}
		f.Go = &Go{Syntax: line}
		f.Go.Version = args[0]
	case "module":
		if f.Module != nil {
			fmt.Fprintf(errs, "%s:%d: repeated module statement\n", f.Syntax.Name, line.Start.Line)
			return
		}
		f.Module = &Module{Syntax: line}
		if len(args) != 1 {

			fmt.Fprintf(errs, "%s:%d: usage: module module/path [version]\n", f.Syntax.Name, line.Start.Line)
			return
		}
		s, err := parseString(&args[0])
		if err != nil {
			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
			return
		}
		f.Module.Mod = module.Version{Path: s}
	case "require", "exclude":
		if len(args) != 2 {
			fmt.Fprintf(errs, "%s:%d: usage: %s module/path v1.2.3\n", f.Syntax.Name, line.Start.Line, verb)
			return
		}
		s, err := parseString(&args[0])
		if err != nil {
			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
			return
		}
		old := args[1]
		v, err := parseVersion(s, &args[1], fix)
		if err != nil {
			fmt.Fprintf(errs, "%s:%d: invalid module version %q: %v\n", f.Syntax.Name, line.Start.Line, old, err)
			return
		}
		pathMajor, err := modulePathMajor(s)
		if err != nil {
			fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
			return
		}
		if !module.MatchPathMajor(v, pathMajor) {
			if pathMajor == "" {
				pathMajor = "v0 or v1"
			}
			fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, pathMajor, semver.Major(v), v)
			return
		}
		if verb == "require" {
			f.Require = append(f.Require, &Require{
				Mod:      module.Version{Path: s, Version: v},
				Syntax:   line,
				Indirect: isIndirect(line),
			})
		} else {
			f.Exclude = append(f.Exclude, &Exclude{
				Mod:    module.Version{Path: s, Version: v},
				Syntax: line,
			})
		}
	case "replace":
		arrow := 2
		if len(args) >= 2 && args[1] == "=>" {
			arrow = 1
		}
		if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" {
			fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory\n", f.Syntax.Name, line.Start.Line, verb, verb)
			return
		}
		s, err := parseString(&args[0])
		if err != nil {
			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
			return
		}
		pathMajor, err := modulePathMajor(s)
		if err != nil {
			fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
			return
		}
		var v string
		if arrow == 2 {
			old := args[1]
			v, err = parseVersion(s, &args[1], fix)
			if err != nil {
				fmt.Fprintf(errs, "%s:%d: invalid module version %v: %v\n", f.Syntax.Name, line.Start.Line, old, err)
				return
			}
			if !module.MatchPathMajor(v, pathMajor) {
				if pathMajor == "" {
					pathMajor = "v0 or v1"
				}
				fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, pathMajor, semver.Major(v), v)
				return
			}
		}
		ns, err := parseString(&args[arrow+1])
		if err != nil {
			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
			return
		}
		nv := ""
		if len(args) == arrow+2 {
			if !IsDirectoryPath(ns) {
				fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)\n", f.Syntax.Name, line.Start.Line)
				return
			}
			if filepath.Separator == '/' && strings.Contains(ns, `\`) {
				fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)\n", f.Syntax.Name, line.Start.Line)
				return
			}
		}
		if len(args) == arrow+3 {
			old := args[arrow+1]
			nv, err = parseVersion(ns, &args[arrow+2], fix)
			if err != nil {
				fmt.Fprintf(errs, "%s:%d: invalid module version %v: %v\n", f.Syntax.Name, line.Start.Line, old, err)
				return
			}
			if IsDirectoryPath(ns) {
				fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version\n", f.Syntax.Name, line.Start.Line, ns)
				return
			}
		}
		f.Replace = append(f.Replace, &Replace{
			Old:    module.Version{Path: s, Version: v},
			New:    module.Version{Path: ns, Version: nv},
			Syntax: line,
		})
	}
}

// isIndirect reports whether line has a "// indirect" comment,
// meaning it is in go.mod only for its effect on indirect dependencies,
// so that it can be dropped entirely once the effective version of the
// indirect dependency reaches the given minimum version.
func isIndirect(line *Line) bool {
	if len(line.Suffix) == 0 {
		return false
	}
	f := strings.Fields(line.Suffix[0].Token)
	return (len(f) == 2 && f[1] == "indirect" || len(f) > 2 && f[1] == "indirect;") && f[0] == "//"
}

// setIndirect sets line to have (or not have) a "// indirect" comment.
func setIndirect(line *Line, indirect bool) {
	if isIndirect(line) == indirect {
		return
	}
	if indirect {
		// Adding comment.
		if len(line.Suffix) == 0 {
			// New comment.
			line.Suffix = []Comment{{Token: "// indirect", Suffix: true}}
			return
		}
		// Insert at beginning of existing comment.
		com := &line.Suffix[0]
		space := " "
		if len(com.Token) > 2 && com.Token[2] == ' ' || com.Token[2] == '\t' {
			space = ""
		}
		com.Token = "// indirect;" + space + com.Token[2:]
		return
	}

	// Removing comment.
	f := strings.Fields(line.Suffix[0].Token)
	if len(f) == 2 {
		// Remove whole comment.
		line.Suffix = nil
		return
	}

	// Remove comment prefix.
	com := &line.Suffix[0]
	i := strings.Index(com.Token, "indirect;")
	com.Token = "//" + com.Token[i+len("indirect;"):]
}

// IsDirectoryPath reports whether the given path should be interpreted
// as a directory path. Just like on the go command line, relative paths
// and rooted paths are directory paths; the rest are module paths.
func IsDirectoryPath(ns string) bool {
	// Because go.mod files can move from one system to another,
	// we check all known path syntaxes, both Unix and Windows.
	return strings.HasPrefix(ns, "./") || strings.HasPrefix(ns, "../") || strings.HasPrefix(ns, "/") ||
		strings.HasPrefix(ns, `.\`) || strings.HasPrefix(ns, `..\`) || strings.HasPrefix(ns, `\`) ||
		len(ns) >= 2 && ('A' <= ns[0] && ns[0] <= 'Z' || 'a' <= ns[0] && ns[0] <= 'z') && ns[1] == ':'
}

// MustQuote reports whether s must be quoted in order to appear as
// a single token in a go.mod line.
func MustQuote(s string) bool {
	for _, r := range s {
		if !unicode.IsPrint(r) || r == ' ' || r == '"' || r == '\'' || r == '`' {
			return true
		}
	}
	return s == "" || strings.Contains(s, "//") || strings.Contains(s, "/*")
}

// AutoQuote returns s or, if quoting is required for s to appear in a go.mod,
// the quotation of s.
func AutoQuote(s string) string {
	if MustQuote(s) {
		return strconv.Quote(s)
	}
	return s
}

func parseString(s *string) (string, error) {
	t := *s
	if strings.HasPrefix(t, `"`) {
		var err error
		if t, err = strconv.Unquote(t); err != nil {
			return "", err
		}
	} else if strings.ContainsAny(t, "\"'`") {
		// Other quotes are reserved both for possible future expansion
		// and to avoid confusion. For example if someone types 'x'
		// we want that to be a syntax error and not a literal x in literal quotation marks.
		return "", fmt.Errorf("unquoted string cannot contain quote")
	}
	*s = AutoQuote(t)
	return t, nil
}

func parseVersion(path string, s *string, fix VersionFixer) (string, error) {
	t, err := parseString(s)
	if err != nil {
		return "", err
	}
	if fix != nil {
		var err error
		t, err = fix(path, t)
		if err != nil {
			return "", err
		}
	}
	if v := module.CanonicalVersion(t); v != "" {
		*s = v
		return *s, nil
	}
	return "", fmt.Errorf("version must be of the form v1.2.3")
}

func modulePathMajor(path string) (string, error) {
	_, major, ok := module.SplitPathVersion(path)
	if !ok {
		return "", fmt.Errorf("invalid module path")
	}
	return major, nil
}

func (f *File) Format() ([]byte, error) {
	return Format(f.Syntax), nil
}

// Cleanup cleans up the file f after any edit operations.
// To avoid quadratic behavior, modifications like DropRequire
// clear the entry but do not remove it from the slice.
// Cleanup cleans out all the cleared entries.
func (f *File) Cleanup() {
	w := 0
	for _, r := range f.Require {
		if r.Mod.Path != "" {
			f.Require[w] = r
			w++
		}
	}
	f.Require = f.Require[:w]

	w = 0
	for _, x := range f.Exclude {
		if x.Mod.Path != "" {
			f.Exclude[w] = x
			w++
		}
	}
	f.Exclude = f.Exclude[:w]

	w = 0
	for _, r := range f.Replace {
		if r.Old.Path != "" {
			f.Replace[w] = r
			w++
		}
	}
	f.Replace = f.Replace[:w]

	f.Syntax.Cleanup()
}

func (f *File) AddRequire(path, vers string) error {
	need := true
	for _, r := range f.Require {
		if r.Mod.Path == path {
			if need {
				r.Mod.Version = vers
				f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers)
				need = false
			} else {
				f.Syntax.removeLine(r.Syntax)
				*r = Require{}
			}
		}
	}

	if need {
		f.AddNewRequire(path, vers, false)
	}
	return nil
}

func (f *File) AddNewRequire(path, vers string, indirect bool) {
	line := f.Syntax.addLine(nil, "require", AutoQuote(path), vers)
	setIndirect(line, indirect)
	f.Require = append(f.Require, &Require{module.Version{Path: path, Version: vers}, indirect, line})
}

func (f *File) SetRequire(req []*Require) {
	need := make(map[string]string)
	indirect := make(map[string]bool)
	for _, r := range req {
		need[r.Mod.Path] = r.Mod.Version
		indirect[r.Mod.Path] = r.Indirect
	}

	for _, r := range f.Require {
		if v, ok := need[r.Mod.Path]; ok {
			r.Mod.Version = v
			r.Indirect = indirect[r.Mod.Path]
		}
	}

	var newStmts []Expr
	for _, stmt := range f.Syntax.Stmt {
		switch stmt := stmt.(type) {
		case *LineBlock:
			if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
				var newLines []*Line
				for _, line := range stmt.Line {
					if p, err := parseString(&line.Token[0]); err == nil && need[p] != "" {
						line.Token[1] = need[p]
						delete(need, p)
						setIndirect(line, indirect[p])
						newLines = append(newLines, line)
					}
				}
				if len(newLines) == 0 {
					continue // drop stmt
				}
				stmt.Line = newLines
			}

		case *Line:
			if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
				if p, err := parseString(&stmt.Token[1]); err == nil && need[p] != "" {
					stmt.Token[2] = need[p]
					delete(need, p)
					setIndirect(stmt, indirect[p])
				} else {
					continue // drop stmt
				}
			}
		}
		newStmts = append(newStmts, stmt)
	}
	f.Syntax.Stmt = newStmts

	for path, vers := range need {
		f.AddNewRequire(path, vers, indirect[path])
	}
	f.SortBlocks()
}

func (f *File) DropRequire(path string) error {
	for _, r := range f.Require {
		if r.Mod.Path == path {
			f.Syntax.removeLine(r.Syntax)
			*r = Require{}
		}
	}
	return nil
}

func (f *File) AddExclude(path, vers string) error {
	var hint *Line
	for _, x := range f.Exclude {
		if x.Mod.Path == path && x.Mod.Version == vers {
			return nil
		}
		if x.Mod.Path == path {
			hint = x.Syntax
		}
	}

	f.Exclude = append(f.Exclude, &Exclude{Mod: module.Version{Path: path, Version: vers}, Syntax: f.Syntax.addLine(hint, "exclude", AutoQuote(path), vers)})
	return nil
}

func (f *File) DropExclude(path, vers string) error {
	for _, x := range f.Exclude {
		if x.Mod.Path == path && x.Mod.Version == vers {
			f.Syntax.removeLine(x.Syntax)
			*x = Exclude{}
		}
	}
	return nil
}

func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
	need := true
	old := module.Version{Path: oldPath, Version: oldVers}
	new := module.Version{Path: newPath, Version: newVers}
	tokens := []string{"replace", AutoQuote(oldPath)}
	if oldVers != "" {
		tokens = append(tokens, oldVers)
	}
	tokens = append(tokens, "=>", AutoQuote(newPath))
	if newVers != "" {
		tokens = append(tokens, newVers)
	}

	var hint *Line
	for _, r := range f.Replace {
		if r.Old.Path == oldPath && (oldVers == "" || r.Old.Version == oldVers) {
			if need {
				// Found replacement for old; update to use new.
				r.New = new
				f.Syntax.updateLine(r.Syntax, tokens...)
				need = false
				continue
			}
			// Already added; delete other replacements for same.
			f.Syntax.removeLine(r.Syntax)
			*r = Replace{}
		}
		if r.Old.Path == oldPath {
			hint = r.Syntax
		}
	}
	if need {
		f.Replace = append(f.Replace, &Replace{Old: old, New: new, Syntax: f.Syntax.addLine(hint, tokens...)})
	}
	return nil
}

func (f *File) DropReplace(oldPath, oldVers string) error {
	for _, r := range f.Replace {
		if r.Old.Path == oldPath && r.Old.Version == oldVers {
			f.Syntax.removeLine(r.Syntax)
			*r = Replace{}
		}
	}
	return nil
}

func (f *File) SortBlocks() {
	f.removeDups() // otherwise sorting is unsafe

	for _, stmt := range f.Syntax.Stmt {
		block, ok := stmt.(*LineBlock)
		if !ok {
			continue
		}
		sort.Slice(block.Line, func(i, j int) bool {
			li := block.Line[i]
			lj := block.Line[j]
			for k := 0; k < len(li.Token) && k < len(lj.Token); k++ {
				if li.Token[k] != lj.Token[k] {
					return li.Token[k] < lj.Token[k]
				}
			}
			return len(li.Token) < len(lj.Token)
		})
	}
}

func (f *File) removeDups() {
	have := make(map[module.Version]bool)
	kill := make(map[*Line]bool)
	for _, x := range f.Exclude {
		if have[x.Mod] {
			kill[x.Syntax] = true
			continue
		}
		have[x.Mod] = true
	}
	var excl []*Exclude
	for _, x := range f.Exclude {
		if !kill[x.Syntax] {
			excl = append(excl, x)
		}
	}
	f.Exclude = excl

	have = make(map[module.Version]bool)
	// Later replacements take priority over earlier ones.
	for i := len(f.Replace) - 1; i >= 0; i-- {
		x := f.Replace[i]
		if have[x.Old] {
			kill[x.Syntax] = true
			continue
		}
		have[x.Old] = true
	}
	var repl []*Replace
	for _, x := range f.Replace {
		if !kill[x.Syntax] {
			repl = append(repl, x)
		}
	}
	f.Replace = repl

	var stmts []Expr
	for _, stmt := range f.Syntax.Stmt {
		switch stmt := stmt.(type) {
		case *Line:
			if kill[stmt] {
				continue
			}
		case *LineBlock:
			var lines []*Line
			for _, line := range stmt.Line {
				if !kill[line] {
					lines = append(lines, line)
				}
			}
			stmt.Line = lines
			if len(lines) == 0 {
				continue
			}
		}
		stmts = append(stmts, stmt)
	}
	f.Syntax.Stmt = stmts
}


text:
package net.vidageek.mirror.reflect;

import static org.junit.Assert.assertTrue;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import net.vidageek.mirror.dsl.Mirror;
import net.vidageek.mirror.fixtures.AnnotationFixture;
import net.vidageek.mirror.fixtures.FieldFixture;
import net.vidageek.mirror.provider.java.DefaultMirrorReflectionProvider;

import org.junit.Before;
import org.junit.Test;

/**
 *
 * @author dnfeitosa
 *
 */
public class FieldHandlerTest {

	private DefaultMirrorReflectionProvider provider;
	private Field annotatedField;

	@Before
	public void setup() {
		provider = new DefaultMirrorReflectionProvider();
		annotatedField = new Mirror().on(FieldFixture.class).reflect().field("field");
	}

	@Test(expected = IllegalArgumentException.class)
	public void testThatThrowsExceptionIfFieldIsNull() {
		new DefaultFieldHandler(provider, null);
	}

	@Test
	public void testThatAnnotationsReflectorIsProperlyDispatched() {
		Annotation annotation = new DefaultFieldHandler(provider, annotatedField).annotation(AnnotationFixture.class);

		assertTrue(AnnotationFixture.class.isAssignableFrom(annotation.getClass()));
	}

}


text:
package de.acosix.alfresco.utility.repo.component;

import java.util.Collections;
import java.util.Locale;
import java.util.Properties;

import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.repo.module.ImporterModuleComponent;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.extensions.surf.util.I18NUtil;

/**
 * This class provides a partially enhanced variant of the Alfresco default importer module component. The improvements include:
 *

 *
cleanup of importer state to avoid issues with duplicate execution on context refresh

 *
ability to disable all behaviours during bootstrap without having to set up a complex, custom importer + importer component...

 *
ability to specify specific locale for import execution

 *
ability to set a simple skip flag for disabling the component (e.g. in specific environments)

 *

 *
 * @author Axel Faust
 */
public class NodeImporterModuleComponent extends ImporterModuleComponent implements InitializingBean
{

    protected ImporterBootstrap importer;

    protected BehaviourFilter behaviourFilter;

    protected Locale locale;

    protected boolean disableBehaviours;

    protected boolean skip;

    /**
     *
     * {@inheritDoc}
     */
    @Override
    public void afterPropertiesSet()
    {
        PropertyCheck.mandatory(this, "importer", this.importer);
        if (this.disableBehaviours)
        {
            PropertyCheck.mandatory(this, "behaviourFilter", this.behaviourFilter);
        }

        if (this.skip)
        {
            // use lowest possible version number to effectively disable this component
            this.setAppliesFromVersion("0");
            this.setAppliesToVersion("0");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setImporter(final ImporterBootstrap importer)
    {
        super.setImporter(importer);
        this.importer = importer;
    }

    /**
     * @param behaviourFilter
     *            the behaviourFilter to set
     */
    public void setBehaviourFilter(final BehaviourFilter behaviourFilter)
    {
        this.behaviourFilter = behaviourFilter;
    }

    /**
     * @param locale
     *            the locale to set
     */
    public void setLocale(final Locale locale)
    {
        this.locale = locale;
    }

    /**
     * @param disableBehaviours
     *            the disableBehaviours to set
     */
    public void setDisableBehaviours(final boolean disableBehaviours)
    {
        this.disableBehaviours = disableBehaviours;
    }

    /**
     * @param skip
     *            the skip to set
     */
    public void setSkip(final boolean skip)
    {
        this.skip = skip;
    }

    /**
     *
     * {@inheritDoc}
     */
    @Override
    protected void executeInternal() throws Throwable
    {
        final Properties baseConfiguration = this.importer.getConfiguration();

        final Locale currentLocale = I18NUtil.getLocaleOrNull();
        if (this.locale != null)
        {
            I18NUtil.setLocale(this.locale);
        }

        boolean behavioursWereEnabled = true;
        if (this.disableBehaviours)
        {
            behavioursWereEnabled = this.behaviourFilter.isEnabled();
            this.behaviourFilter.disableBehaviour();
        }
        try
        {
            super.executeInternal();
            ModuleComponentFlags.flagTransactionalChanges();
        }
        finally
        {
            if (this.disableBehaviours && behavioursWereEnabled)
            {
                this.behaviourFilter.enableBehaviour();
            }

            I18NUtil.setLocale(currentLocale);

            // bootstrap beans are AbstractLifecycleBean instances
            // avoid executing the same bootstrap on context refresh
            this.importer.setBootstrapViews(Collections.emptyList());
            this.importer.setConfiguration(baseConfiguration);
        }
    }
}


text:
package securitycenter

import (
	fmt "fmt"
	math "math"

	proto "github.com/golang/protobuf/proto"
	_ "google.golang.org/genproto/googleapis/api/annotations"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

// The mode of inclusion when running Asset Discovery.
// Asset discovery can be limited by explicitly identifying projects to be
// included or excluded. If INCLUDE_ONLY is set, then only those projects
// within the organization and their children are discovered during asset
// discovery. If EXCLUDE is set, then projects that don't match those
// projects are discovered during asset discovery. If neither are set, then
// all projects within the organization are discovered during asset
// discovery.
type OrganizationSettings_AssetDiscoveryConfig_InclusionMode int32

const (
	// Unspecified. Setting the mode with this value will disable
	// inclusion/exclusion filtering for Asset Discovery.
	OrganizationSettings_AssetDiscoveryConfig_INCLUSION_MODE_UNSPECIFIED OrganizationSettings_AssetDiscoveryConfig_InclusionMode = 0
	// Asset Discovery will capture only the resources within the projects
	// specified. All other resources will be ignored.
	OrganizationSettings_AssetDiscoveryConfig_INCLUDE_ONLY OrganizationSettings_AssetDiscoveryConfig_InclusionMode = 1
	// Asset Discovery will ignore all resources under the projects specified.
	// All other resources will be retrieved.
	OrganizationSettings_AssetDiscoveryConfig_EXCLUDE OrganizationSettings_AssetDiscoveryConfig_InclusionMode = 2
)

var OrganizationSettings_AssetDiscoveryConfig_InclusionMode_name = map[int32]string{
	0: "INCLUSION_MODE_UNSPECIFIED",
	1: "INCLUDE_ONLY",
	2: "EXCLUDE",
}

var OrganizationSettings_AssetDiscoveryConfig_InclusionMode_value = map[string]int32{
	"INCLUSION_MODE_UNSPECIFIED": 0,
	"INCLUDE_ONLY":               1,
	"EXCLUDE":                    2,
}

func (x OrganizationSettings_AssetDiscoveryConfig_InclusionMode) String() string {
	return proto.EnumName(OrganizationSettings_AssetDiscoveryConfig_InclusionMode_name, int32(x))
}

func (OrganizationSettings_AssetDiscoveryConfig_InclusionMode) EnumDescriptor() ([]byte, []int) {
	return fileDescriptor_9f5c7b1e9f2f4088, []int{0, 0, 0}
}

// User specified settings that are attached to the Cloud Security Command
// Center (Cloud SCC) organization.
type OrganizationSettings struct {
	// The relative resource name of the settings. See:
	// https://cloud.google.com/apis/design/resource_names#relative_resource_name
	// Example:
	// "organizations/123/organizationSettings".
	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	// A flag that indicates if Asset Discovery should be enabled. If the flag is
	// set to `true`, then discovery of assets will occur. If it is set to `false,
	// all historical assets will remain, but discovery of future assets will not
	// occur.
	EnableAssetDiscovery bool `protobuf:"varint,2,opt,name=enable_asset_discovery,json=enableAssetDiscovery,proto3" json:"enable_asset_discovery,omitempty"`
	// The configuration used for Asset Discovery runs.
	AssetDiscoveryConfig *OrganizationSettings_AssetDiscoveryConfig `protobuf:"bytes,3,opt,name=asset_discovery_config,json=assetDiscoveryConfig,proto3" json:"asset_discovery_config,omitempty"`
	XXX_NoUnkeyedLiteral struct{}                                   `json:"-"`
	XXX_unrecognized     []byte                                     `json:"-"`
	XXX_sizecache        int32                                      `json:"-"`
}

func (m *OrganizationSettings) Reset()         { *m = OrganizationSettings{} }
func (m *OrganizationSettings) String() string { return proto.CompactTextString(m) }
func (*OrganizationSettings) ProtoMessage()    {}
func (*OrganizationSettings) Descriptor() ([]byte, []int) {
	return fileDescriptor_9f5c7b1e9f2f4088, []int{0}
}

func (m *OrganizationSettings) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_OrganizationSettings.Unmarshal(m, b)
}
func (m *OrganizationSettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_OrganizationSettings.Marshal(b, m, deterministic)
}
func (m *OrganizationSettings) XXX_Merge(src proto.Message) {
	xxx_messageInfo_OrganizationSettings.Merge(m, src)
}
func (m *OrganizationSettings) XXX_Size() int {
	return xxx_messageInfo_OrganizationSettings.Size(m)
}
func (m *OrganizationSettings) XXX_DiscardUnknown() {
	xxx_messageInfo_OrganizationSettings.DiscardUnknown(m)
}

var xxx_messageInfo_OrganizationSettings proto.InternalMessageInfo

func (m *OrganizationSettings) GetName() string {
	if m != nil {
		return m.Name
	}
	return ""
}

func (m *OrganizationSettings) GetEnableAssetDiscovery() bool {
	if m != nil {
		return m.EnableAssetDiscovery
	}
	return false
}

func (m *OrganizationSettings) GetAssetDiscoveryConfig() *OrganizationSettings_AssetDiscoveryConfig {
	if m != nil {
		return m.AssetDiscoveryConfig
	}
	return nil
}

// The configuration used for Asset Discovery runs.
type OrganizationSettings_AssetDiscoveryConfig struct {
	// The project ids to use for filtering asset discovery.
	ProjectIds []string `protobuf:"bytes,1,rep,name=project_ids,json=projectIds,proto3" json:"project_ids,omitempty"`
	// The mode to use for filtering asset discovery.
	InclusionMode        OrganizationSettings_AssetDiscoveryConfig_InclusionMode `protobuf:"varint,2,opt,name=inclusion_mode,json=inclusionMode,proto3,enum=google.cloud.securitycenter.v1.OrganizationSettings_AssetDiscoveryConfig_InclusionMode" json:"inclusion_mode,omitempty"`
	XXX_NoUnkeyedLiteral struct{}                                                `json:"-"`
	XXX_unrecognized     []byte                                                  `json:"-"`
	XXX_sizecache        int32                                                   `json:"-"`
}

func (m *OrganizationSettings_AssetDiscoveryConfig) Reset() {
	*m = OrganizationSettings_AssetDiscoveryConfig{}
}
func (m *OrganizationSettings_AssetDiscoveryConfig) String() string { return proto.CompactTextString(m) }
func (*OrganizationSettings_AssetDiscoveryConfig) ProtoMessage()    {}
func (*OrganizationSettings_AssetDiscoveryConfig) Descriptor() ([]byte, []int) {
	return fileDescriptor_9f5c7b1e9f2f4088, []int{0, 0}
}

func (m *OrganizationSettings_AssetDiscoveryConfig) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_OrganizationSettings_AssetDiscoveryConfig.Unmarshal(m, b)
}
func (m *OrganizationSettings_AssetDiscoveryConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_OrganizationSettings_AssetDiscoveryConfig.Marshal(b, m, deterministic)
}
func (m *OrganizationSettings_AssetDiscoveryConfig) XXX_Merge(src proto.Message) {
	xxx_messageInfo_OrganizationSettings_AssetDiscoveryConfig.Merge(m, src)
}
func (m *OrganizationSettings_AssetDiscoveryConfig) XXX_Size() int {
	return xxx_messageInfo_OrganizationSettings_AssetDiscoveryConfig.Size(m)
}
func (m *OrganizationSettings_AssetDiscoveryConfig) XXX_DiscardUnknown() {
	xxx_messageInfo_OrganizationSettings_AssetDiscoveryConfig.DiscardUnknown(m)
}

var xxx_messageInfo_OrganizationSettings_AssetDiscoveryConfig proto.InternalMessageInfo

func (m *OrganizationSettings_AssetDiscoveryConfig) GetProjectIds() []string {
	if m != nil {
		return m.ProjectIds
	}
	return nil
}

func (m *OrganizationSettings_AssetDiscoveryConfig) GetInclusionMode() OrganizationSettings_AssetDiscoveryConfig_InclusionMode {
	if m != nil {
		return m.InclusionMode
	}
	return OrganizationSettings_AssetDiscoveryConfig_INCLUSION_MODE_UNSPECIFIED
}

func init() {
	proto.RegisterEnum("google.cloud.securitycenter.v1.OrganizationSettings_AssetDiscoveryConfig_InclusionMode", OrganizationSettings_AssetDiscoveryConfig_InclusionMode_name, OrganizationSettings_AssetDiscoveryConfig_InclusionMode_value)
	proto.RegisterType((*OrganizationSettings)(nil), "google.cloud.securitycenter.v1.OrganizationSettings")
	proto.RegisterType((*OrganizationSettings_AssetDiscoveryConfig)(nil), "google.cloud.securitycenter.v1.OrganizationSettings.AssetDiscoveryConfig")
}

func init() {
	proto.RegisterFile("google/cloud/securitycenter/v1/organization_settings.proto", fileDescriptor_9f5c7b1e9f2f4088)
}

var fileDescriptor_9f5c7b1e9f2f4088 = []byte{
	// 454 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x92, 0xdf, 0x6e, 0xd3, 0x30,
	0x14, 0xc6, 0x49, 0xda, 0x8d, 0xce, 0x65, 0x53, 0x64, 0x55, 0x53, 0x55, 0xa1, 0x52, 0x7a, 0xd5,
	0x2b, 0x47, 0x19, 0x5c, 0x85, 0x2b, 0x48, 0x03, 0xca, 0xd4, 0xa5, 0x53, 0xaa, 0x95, 0x3f, 0xaa,
	0x14, 0x79, 0x8e, 0xb1, 0x8c, 0x52, 0x3b, 0x8a, 0xdd, 0x4a, 0xe3, 0x02, 0x2e, 0x79, 0x17, 0x1e,
	0x85, 0x47, 0xe0, 0x11, 0x78, 0x01, 0x6e, 0xd1, 0x9c, 0x54, 0x5a, 0x50, 0x81, 0x1b, 0xee, 0x92,
	0xf3, 0xfd, 0xbe, 0xef, 0x9c, 0x63, 0x1d, 0xe0, 0x33, 0x29, 0x59, 0x4e, 0x5d, 0x92, 0xcb, 0x4d,
	0xe6, 0x2a, 0x4a, 0x36, 0x25, 0xd7, 0x37, 0x84, 0x0a, 0x4d, 0x4b, 0x77, 0xeb, 0xb9, 0xb2, 0x64,
	0x58, 0xf0, 0x8f, 0x58, 0x73, 0x29, 0x52, 0x45, 0xb5, 0xe6, 0x82, 0x29, 0x54, 0x94, 0x52, 0x4b,
	0x38, 0xac, 0xbc, 0xc8, 0x78, 0x51, 0xd3, 0x8b, 0xb6, 0xde, 0xe0, 0x61, 0x9d, 0x8d, 0x0b, 0xee,
	0x62, 0x21, 0xa4, 0x36, 0x29, 0xb5, 0x7b, 0xfc, 0xb3, 0x05, 0x7a, 0xf3, 0x3b, 0xe9, 0x8b, 0x3a,
	0x1c, 0x42, 0xd0, 0x16, 0x78, 0x4d, 0xfb, 0xd6, 0xc8, 0x9a, 0x1c, 0x25, 0xe6, 0x1b, 0x3e, 0x05,
	0xa7, 0x54, 0xe0, 0xeb, 0x9c, 0xa6, 0x58, 0x29, 0xaa, 0xd3, 0x8c, 0x2b, 0x22, 0xb7, 0xb4, 0xbc,
	0xe9, 0xdb, 0x23, 0x6b, 0xd2, 0x49, 0x7a, 0x95, 0xfa, 0xfc, 0x56, 0x9c, 0xee, 0x34, 0xf8, 0x19,
	0x9c, 0xfe, 0x86, 0xa7, 0x44, 0x8a, 0xf7, 0x9c, 0xf5, 0x5b, 0x23, 0x6b, 0xd2, 0x3d, 0x8b, 0xd0,
	0xdf, 0x37, 0x40, 0xfb, 0xe6, 0x43, 0xcd, 0x26, 0x81, 0x09, 0x4c, 0x7a, 0x78, 0x4f, 0x75, 0xf0,
	0xc5, 0x06, 0xbd, 0x7d, 0x38, 0x7c, 0x04, 0xba, 0x45, 0x29, 0x3f, 0x50, 0xa2, 0x53, 0x9e, 0xa9,
	0xbe, 0x35, 0x6a, 0x4d, 0x8e, 0x12, 0x50, 0x97, 0xa2, 0x4c, 0xc1, 0x4f, 0xe0, 0x84, 0x0b, 0x92,
	0x6f, 0xd4, 0xed, 0xbb, 0xaf, 0x65, 0x46, 0xcd, 0xa2, 0x27, 0x67, 0xaf, 0xff, 0xdb, 0xc8, 0x28,
	0xda, 0xe5, 0x5f, 0xc8, 0x8c, 0x26, 0xc7, 0xfc, 0xee, 0xef, 0x38, 0x06, 0xc7, 0x0d, 0x1d, 0x0e,
	0xc1, 0x20, 0x8a, 0x83, 0xd9, 0xd5, 0x22, 0x9a, 0xc7, 0xe9, 0xc5, 0x7c, 0x1a, 0xa6, 0x57, 0xf1,
	0xe2, 0x32, 0x0c, 0xa2, 0x97, 0x51, 0x38, 0x75, 0xee, 0x41, 0x07, 0x3c, 0x30, 0xfa, 0x34, 0x4c,
	0xe7, 0xf1, 0xec, 0xad, 0x63, 0xc1, 0x2e, 0xb8, 0x1f, 0xbe, 0x31, 0x15, 0xc7, 0x3e, 0x6f, 0x77,
	0xda, 0xce, 0xc1, 0x79, 0xbb, 0x73, 0xe0, 0x1c, 0xbe, 0xf8, 0x6e, 0x81, 0x31, 0x91, 0xeb, 0x7f,
	0x6c, 0x72, 0x69, 0xbd, 0x9b, 0xd5, 0x04, 0x93, 0x39, 0x16, 0x0c, 0xc9, 0x92, 0xb9, 0x8c, 0x0a,
	0x73, 0x3e, 0x6e, 0x25, 0xe1, 0x82, 0xab, 0x3f, 0xdd, 0xee, 0xb3, 0x66, 0xe5, 0xab, 0x3d, 0x7c,
	0x55, 0xc5, 0x05, 0xa6, 0xe1, 0xa2, 0x56, 0x83, 0xaa, 0xe1, 0xd2, 0xfb, 0xb6, 0x03, 0x56, 0x06,
	0x58, 0x35, 0x81, 0xd5, 0xd2, 0xfb, 0x61, 0x3f, 0xae, 0x00, 0xdf, 0x37, 0x84, 0xef, 0x37, 0x11,
	0xdf, 0x5f, 0x7a, 0xd7, 0x87, 0x66, 0xbc, 0x27, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x57,
	0x11, 0xc7, 0x59, 0x03, 0x00, 0x00,
}


text:
package com.thoughtworks.go.server.service.plugins.processor.serverhealth.v1;

import com.google.gson.Gson;
import com.thoughtworks.go.server.service.plugins.processor.serverhealth.PluginHealthMessage;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Map;

import static com.thoughtworks.go.util.DataStructureUtils.a;
import static com.thoughtworks.go.util.DataStructureUtils.m;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;

public class MessageHandlerForServerHealthRequestProcessorV1Test {
    private MessageHandlerForServerHealthRequestProcessorV1 processor;

    @Before
    public void setUp() {
        processor = new MessageHandlerForServerHealthRequestProcessorV1();
    }

    @Test
    public void shouldDeserializeProperMessage() {
        Map<String, Object> message1 = m("type", "warning", "message", "message 1");
        Map<String, Object> message2 = m("type", "error", "message", "message 2");
        Map<String, Object> message3 = m("type", "misspelled-type", "message", "message 3");
        String input = new Gson().toJson(a(message1, message2, message3));

        List<PluginHealthMessage> messages = processor.deserializeServerHealthMessages(input);

        assertThat(messages.get(0).isWarning(), is(true));
        assertThat(messages.get(0).message(), is("message 1"));

        assertThat(messages.get(1).isWarning(), is(false));
        assertThat(messages.get(1).message(), is("message 2"));

        assertThat(messages.get(2).isWarning(), is(false));
        assertThat(messages.get(2).message(), is("message 3"));
    }

    @Test
    public void shouldDeserializeToEmptyListProperly() {
        assertTrue(processor.deserializeServerHealthMessages("[]").isEmpty());
    }

    @Test
    public void shouldFailIfMessageIsInvalid() {
        try {
            processor.deserializeServerHealthMessages("Invalid JSON");
            fail("Should have failed to deserialize");
        } catch (Exception e) {
            assertThat(e.getMessage(), containsString("Failed to deserialize"));
        }
    }
}


text: export const RETROSPECTIVE_DESCRIPTOR = 'retrospective'


text:
Queries the EMC Unity array to retrieve informations about UnitystorageResource.

## SYNTAX

### Name (Default)
```
Get-UnityStorageResource [-session <Object>] [-Name <String[]>] [-Type <String>]
```

### ID
```
Get-UnityStorageResource [-session <Object>] [-ID <String[]>] [-Type <String>]
```

## DESCRIPTION
Querries the EMC Unity array to retrieve informations about UnitystorageResource.
You need to have an active session with the array.

## EXAMPLES

### -------------------------- EXAMPLE 1 --------------------------
```
Get-UnityStorageResource
```

Retrieve informations about all the storage ressources

### -------------------------- EXAMPLE 2 --------------------------
```
Get-UnityStorageResource -Name 'DATASTORE01'
```

Retrieves informations about storage ressource named DATASTORE01

## PARAMETERS

### -session
Specifies an UnitySession Object.

```yaml
Type: Object
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: ($global:DefaultUnitySession | where-object {$_.IsConnected -eq $true})
Accept pipeline input: False
Accept wildcard characters: False
```

### -Name
Specifies the object name.

```yaml
Type: String[]
Parameter Sets: Name
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: True (ByPropertyName, ByValue)
Accept wildcard characters: False
```

### -ID
Specifies the object ID.

```yaml
Type: String[]
Parameter Sets: ID
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: True (ByPropertyName, ByValue)
Accept wildcard characters: False
```

### -Type
Specifies the storage ressource type.
Might be:
- lun
- vmwareiscsi
- vmwarefs

```yaml
Type: String
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

## INPUTS

## OUTPUTS

## NOTES
Written by Erwan Quelin under MIT licence

## RELATED LINKS

[https://github.com/equelin/Unity-Powershell](https://github.com/equelin/Unity-Powershell)


text:
Barrick Mobile Observer is an Android application for monitoring and alerting of autoclave sensor data at Barrick Gold mines.

# About

Developed for Unearthed Denver 2017.

# Authors

**University of Wyoming _Gecko Rockets_ Hackathon Team**
Android Developer: Stephen Belden
Data Scientist: Esteban Mena
Mechanical Analyst: Tim Bourque
"Self-Proclaimed Concept Manager": Dominic Rainbolt