text:
<?php

namespace Zimbra\Tests\Voice;

use Zimbra\Tests\ZimbraTestCase;
use Zimbra\Enum\VoiceMsgActionOp;
use Zimbra\Enum\VoiceSortBy;

/**
 * Testcase class for voice request.
 */
class RequestTest extends ZimbraTestCase
{
    public function testBaseRequest()
    {
        $req = $this->getMockForAbstractClass('\Zimbra\Voice\Request\Base');
        $this->assertInstanceOf('Zimbra\Soap\Request', $req);
        $this->assertEquals('urn:zimbraVoice', $req->getXmlNamespace());
    }

    public function testChangeUCPassword()
    {
        $password = self::randomName();
        $req = new \Zimbra\Voice\Request\ChangeUCPassword(
            $password
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($password, $req->getPassword());
        $req->setPassword($password);
        $this->assertSame($password, $req->getPassword());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<ChangeUCPasswordRequest password="' . $password . '" />';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'ChangeUCPasswordRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'password' =>$password,
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testGetUCInfo()
    {
        $req = new \Zimbra\Voice\Request\GetUCInfo();
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);

        $xml = '<?xml version="1.0"?>'."\n"
            .'<GetUCInfoRequest />';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'GetUCInfoRequest' => [
                '_jsns' => 'urn:zimbraVoice',
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testGetVoiceFeatures()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );

        $pref = new \Zimbra\Voice\Struct\VoiceMailPrefName($name);
        $voicemailprefs = new \Zimbra\Voice\Struct\VoiceMailPrefsReq([$pref]);
        $anoncallrejection = new \Zimbra\Voice\Struct\AnonCallRejectionReq();
        $calleridblocking = new \Zimbra\Voice\Struct\CallerIdBlockingReq();
        $callforward = new \Zimbra\Voice\Struct\CallForwardReq();
        $callforwardbusyline = new \Zimbra\Voice\Struct\CallForwardBusyLineReq();
        $callforwardnoanswer = new \Zimbra\Voice\Struct\CallForwardNoAnswerReq();
        $callwaiting = new \Zimbra\Voice\Struct\CallWaitingReq();
        $selectivecallforward = new \Zimbra\Voice\Struct\SelectiveCallForwardReq();
        $selectivecallacceptance = new \Zimbra\Voice\Struct\SelectiveCallAcceptanceReq();
        $selectivecallrejection = new \Zimbra\Voice\Struct\SelectiveCallRejectionReq();

        $callFeatures = [
            $voicemailprefs,
            $anoncallrejection,
            $calleridblocking,
            $callforward,
            $callforwardbusyline,
            $callforwardnoanswer,
            $callwaiting,
            $selectivecallforward,
            $selectivecallacceptance,
            $selectivecallrejection
        ];
        $phone = new \Zimbra\Voice\Struct\PhoneVoiceFeaturesSpec(
            $name, $callFeatures
        );

        $req = new \Zimbra\Voice\Request\GetVoiceFeatures(
            $storeprincipal, $phone
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());
        $req->setStorePrincipal($storeprincipal)
            ->setPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<GetVoiceFeaturesRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone name="' . $name . '">'
                    .'<voicemailprefs>'
                        .'<pref name="' . $name . '" />'
                    .'</voicemailprefs>'
                    .'<anoncallrejection />'
                    .'<calleridblocking />'
                    .'<callforward />'
                    .'<callforwardbusyline />'
                    .'<callforwardnoanswer />'
                    .'<callwaiting />'
                    .'<selectivecallforward />'
                    .'<selectivecallacceptance />'
                    .'<selectivecallrejection />'
                .'</phone>'
            .'</GetVoiceFeaturesRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'GetVoiceFeaturesRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    'name' => $name,
                    'voicemailprefs' => [
                        'pref' => [
                            [
                                'name' => $name,
                            ],
                        ],
                    ],
                    'anoncallrejection' => [],
                    'calleridblocking' => [],
                    'callforward' => [],
                    'callforwardbusyline' => [],
                    'callforwardnoanswer' => [],
                    'callwaiting' => [],
                    'selectivecallforward' => [],
                    'selectivecallacceptance' => [],
                    'selectivecallrejection' => [],
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testGetVoiceFolder()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );
        $pref = new \Zimbra\Voice\Struct\PrefSpec($name);
        $phone = new \Zimbra\Voice\Struct\PhoneSpec($name, [$pref]);

        $req = new \Zimbra\Voice\Request\GetVoiceFolder(
            $storeprincipal, [$phone]
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame([$phone], $req->getPhones()->all());
        $req->setStorePrincipal($storeprincipal)
            ->addPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame([$phone, $phone], $req->getPhones()->all());
        $req->getPhones()->remove(1);

        $xml = '<?xml version="1.0"?>'."\n"
            .'<GetVoiceFolderRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone name="' . $name . '">'
                    .'<pref name="' . $name . '" />'
                .'</phone>'
            .'</GetVoiceFolderRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'GetVoiceFolderRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    [
                        'name' => $name,
                        'pref' => [
                            [
                                'name' => $name,
                            ],
                        ],
                    ],
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testGetVoiceInfo()
    {
        $name = self::randomName();
        $pref = new \Zimbra\Voice\Struct\PrefSpec($name);
        $phone = new \Zimbra\Voice\Struct\PhoneSpec($name, [$pref]);

        $req = new \Zimbra\Voice\Request\GetVoiceInfo(
            [$phone]
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame([$phone], $req->getPhones()->all());
        $req->addPhone($phone);
        $this->assertSame([$phone, $phone], $req->getPhones()->all());
        $req->getPhones()->remove(1);

        $xml = '<?xml version="1.0"?>'."\n"
            .'<GetVoiceInfoRequest>'
                .'<phone name="' . $name . '">'
                    .'<pref name="' . $name . '" />'
                .'</phone>'
            .'</GetVoiceInfoRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'GetVoiceInfoRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'phone' => [
                    [
                        'name' => $name,
                        'pref' => [
                            [
                                'name' => $name,
                            ],
                        ],
                    ],
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testGetVoiceMailPrefs()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );
        $pref = new \Zimbra\Voice\Struct\PrefSpec($name);
        $phone = new \Zimbra\Voice\Struct\PhoneSpec($name, [$pref]);

        $req = new \Zimbra\Voice\Request\GetVoiceMailPrefs(
            $storeprincipal, $phone
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());
        $req->setStorePrincipal($storeprincipal)
            ->setPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<GetVoiceMailPrefsRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone name="' . $name . '">'
                    .'<pref name="' . $name . '" />'
                .'</phone>'
            .'</GetVoiceMailPrefsRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'GetVoiceMailPrefsRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    'name' => $name,
                    'pref' => [
                        [
                            'name' => $name,
                        ],
                    ],
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testModifyFromNum()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );

        $oldPhone = self::randomName();
        $newPhone = self::randomName();
        $label = self::randomName();
        $phone = new \Zimbra\Voice\Struct\ModifyFromNumSpec(
            $oldPhone, $newPhone, $id, $label
        );

        $req = new \Zimbra\Voice\Request\ModifyFromNum(
            $storeprincipal, $phone
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());
        $req->setStorePrincipal($storeprincipal)
            ->setPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<ModifyFromNumRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone oldPhone="' . $oldPhone . '" phone="' . $newPhone . '" id="' . $id . '" label="' . $label . '" />'
            .'</ModifyFromNumRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'ModifyFromNumRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    'oldPhone' => $oldPhone,
                    'phone' => $newPhone,
                    'id' => $id,
                    'label' => $label,
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testModifyVoiceFeatures()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );

        $value = self::randomName();
        $pn = self::randomName();
        $ft = self::randomName();
        $nr = self::randomName();

        $pref = new \Zimbra\Voice\Struct\PrefInfo($name, $value);
        $entry = new \Zimbra\Voice\Struct\CallerListEntry($pn, true);
        $voicemailprefs = new \Zimbra\Voice\Struct\VoiceMailPrefsFeature(
            true, false, [$pref]
        );
        $anoncallrejection = new \Zimbra\Voice\Struct\AnonCallRejectionFeature(
            true, false
        );
        $calleridblocking = new \Zimbra\Voice\Struct\CallerIdBlockingFeature(
            true, false
        );
        $callforward = new \Zimbra\Voice\Struct\CallForwardFeature(
            true, false, $ft
        );
        $callforwardbusyline = new \Zimbra\Voice\Struct\CallForwardBusyLineFeature(
            true, false, $ft
        );
        $callforwardnoanswer = new \Zimbra\Voice\Struct\CallForwardNoAnswerFeature(
            true, false, $ft, $nr
        );
        $callwaiting = new \Zimbra\Voice\Struct\CallWaitingFeature(
            true, false
        );
        $selectivecallforward = new \Zimbra\Voice\Struct\SelectiveCallForwardFeature(
            true, false, [$entry], $ft
        );
        $selectivecallacceptance = new \Zimbra\Voice\Struct\SelectiveCallAcceptanceFeature(
            true, false, [$entry]
        );
        $selectivecallrejection = new \Zimbra\Voice\Struct\SelectiveCallRejectionFeature(
            true, false, [$entry]
        );

        $callFeatures = [
            $voicemailprefs,
            $anoncallrejection,
            $calleridblocking,
            $callforward,
            $callforwardbusyline,
            $callforwardnoanswer,
            $callwaiting,
            $selectivecallforward,
            $selectivecallacceptance,
            $selectivecallrejection,
        ];
        $phone = new \Zimbra\Voice\Struct\ModifyVoiceFeaturesSpec(
            $name, $callFeatures
        );

        $req = new \Zimbra\Voice\Request\ModifyVoiceFeatures(
            $storeprincipal, $phone
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());
        $req->setStorePrincipal($storeprincipal)
            ->setPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<ModifyVoiceFeaturesRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone name="' . $name . '">'
                    .'<voicemailprefs s="true" a="false">'
                        .'<pref name="' . $name . '">' . $value  .'</pref>'
                    .'</voicemailprefs>'
                    .'<anoncallrejection s="true" a="false" />'
                    .'<calleridblocking s="true" a="false" />'
                    .'<callforward s="true" a="false" ft="' . $ft . '" />'
                    .'<callforwardbusyline s="true" a="false" ft="' . $ft . '" />'
                    .'<callforwardnoanswer s="true" a="false" ft="' . $ft . '" nr="' . $nr . '" />'
                    .'<callwaiting s="true" a="false" />'
                    .'<selectivecallforward s="true" a="false" ft="' . $ft . '">'
                        .'<phone pn="' . $pn . '" a="true" />'
                    .'</selectivecallforward>'
                    .'<selectivecallacceptance s="true" a="false">'
                        .'<phone pn="' . $pn . '" a="true" />'
                    .'</selectivecallacceptance>'
                    .'<selectivecallrejection s="true" a="false">'
                        .'<phone pn="' . $pn . '" a="true" />'
                    .'</selectivecallrejection>'
                .'</phone>'
            .'</ModifyVoiceFeaturesRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'ModifyVoiceFeaturesRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    'name' => $name,
                    'voicemailprefs' => [
                        's' => true,
                        'a' => false,
                        'pref' => [
                            [
                                'name' => $name,
                                '_content' => $value,
                            ],
                        ],
                    ],
                    'anoncallrejection' => [
                        's' => true,
                        'a' => false,
                    ],
                    'calleridblocking' => [
                        's' => true,
                        'a' => false,
                    ],
                    'callforward' => [
                        's' => true,
                        'a' => false,
                        'ft' => $ft,
                    ],
                    'callforwardbusyline' => [
                        's' => true,
                        'a' => false,
                        'ft' => $ft,
                    ],
                    'callforwardnoanswer' => [
                        's' => true,
                        'a' => false,
                        'ft' => $ft,
                        'nr' => $nr,
                    ],
                    'callwaiting' => [
                        's' => true,
                        'a' => false,
                    ],
                    'selectivecallforward' => [
                        's' => true,
                        'a' => false,
                        'ft' => $ft,
                        'phone' => [
                            [
                                'pn' => $pn,
                                'a' => true,
                            ],
                        ],
                    ],
                    'selectivecallacceptance' => [
                        's' => true,
                        'a' => false,
                        'phone' => [
                            [
                                'pn' => $pn,
                                'a' => true,
                            ],
                        ],
                    ],
                    'selectivecallrejection' => [
                        's' => true,
                        'a' => false,
                        'phone' => [
                            [
                                'pn' => $pn,
                                'a' => true,
                            ],
                        ],
                    ],
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testModifyVoiceMailPin()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );

        $oldPin = self::randomName();
        $pin = self::randomName();
        $phone = new \Zimbra\Voice\Struct\ModifyVoiceMailPinSpec(
            $oldPin, $pin, $name
        );

        $req = new \Zimbra\Voice\Request\ModifyVoiceMailPin(
            $storeprincipal, $phone
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());
        $req->setStorePrincipal($storeprincipal)
            ->setPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<ModifyVoiceMailPinRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone oldPin="' . $oldPin . '" pin="' . $pin . '" name="' . $name . '" />'
            .'</ModifyVoiceMailPinRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'ModifyVoiceMailPinRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    'oldPin' => $oldPin,
                    'pin' => $pin,
                    'name' => $name,
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testModifyVoiceMailPrefs()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $value = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );
        $pref = new \Zimbra\Voice\Struct\PrefInfo($name, $value);
        $phone = new \Zimbra\Voice\Struct\PhoneInfo($name, [$pref]);

        $req = new \Zimbra\Voice\Request\ModifyVoiceMailPrefs(
            $storeprincipal, $phone
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());
        $req->setStorePrincipal($storeprincipal)
            ->setPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<ModifyVoiceMailPrefsRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone name="' . $name . '">'
                    .'<pref name="' . $name . '">' . $value . '</pref>'
                .'</phone>'
            .'</ModifyVoiceMailPrefsRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'ModifyVoiceMailPrefsRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    'name' => $name,
                    'pref' => [
                        [
                            'name' => $name,
                            '_content' => $value,
                        ],
                    ],
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testResetVoiceFeatures()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );

        $anoncallrejection = new \Zimbra\Voice\Struct\AnonCallRejectionReq();
        $calleridblocking = new \Zimbra\Voice\Struct\CallerIdBlockingReq();
        $callforward = new \Zimbra\Voice\Struct\CallForwardReq();
        $callforwardbusyline = new \Zimbra\Voice\Struct\CallForwardBusyLineReq();
        $callforwardnoanswer = new \Zimbra\Voice\Struct\CallForwardNoAnswerReq();
        $callwaiting = new \Zimbra\Voice\Struct\CallWaitingReq();
        $selectivecallforward = new \Zimbra\Voice\Struct\SelectiveCallForwardReq();
        $selectivecallacceptance = new \Zimbra\Voice\Struct\SelectiveCallAcceptanceReq();
        $selectivecallrejection = new \Zimbra\Voice\Struct\SelectiveCallRejectionReq();

        $callFeatures = [
            $anoncallrejection,
            $calleridblocking,
            $callforward,
            $callforwardbusyline,
            $callforwardnoanswer,
            $callwaiting,
            $selectivecallforward,
            $selectivecallacceptance,
            $selectivecallrejection,
        ];
        $phone = new \Zimbra\Voice\Struct\ResetPhoneVoiceFeaturesSpec(
            $name, $callFeatures
        );

        $req = new \Zimbra\Voice\Request\ResetVoiceFeatures(
            $storeprincipal, $phone
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());
        $req->setStorePrincipal($storeprincipal)
            ->setPhone($phone);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($phone, $req->getPhone());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<ResetVoiceFeaturesRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<phone name="' . $name . '">'
                    .'<anoncallrejection />'
                    .'<calleridblocking />'
                    .'<callforward />'
                    .'<callforwardbusyline />'
                    .'<callforwardnoanswer />'
                    .'<callwaiting />'
                    .'<selectivecallforward />'
                    .'<selectivecallacceptance />'
                    .'<selectivecallrejection />'
                .'</phone>'
            .'</ResetVoiceFeaturesRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'ResetVoiceFeaturesRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'phone' => [
                    'name' => $name,
                    'anoncallrejection' => [],
                    'calleridblocking' => [],
                    'callforward' => [],
                    'callforwardbusyline' => [],
                    'callforwardnoanswer' => [],
                    'callwaiting' => [],
                    'selectivecallforward' => [],
                    'selectivecallacceptance' => [],
                    'selectivecallrejection' => [],
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testSearchVoice()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $query = self::randomName();
        $types = self::randomName();
        $limit = mt_rand(0, 100);
        $offset = mt_rand(0, 100);

        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );
        $req = new \Zimbra\Voice\Request\SearchVoice(
            $query, $storeprincipal, $limit, $offset, $types, VoiceSortBy::DATE_DESC()
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($query, $req->getQuery());
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($limit, $req->getLimit());
        $this->assertSame($offset, $req->getOffset());
        $this->assertSame($types, $req->getTypes());
        $this->assertTrue($req->getSortBy()->is('dateDesc'));

        $req->setQuery($query)
            ->setStorePrincipal($storeprincipal)
            ->setLimit($limit)
            ->setOffset($offset)
            ->setTypes($types)
            ->setSortBy(VoiceSortBy::DATE_DESC());
        $this->assertSame($query, $req->getQuery());
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($limit, $req->getLimit());
        $this->assertSame($offset, $req->getOffset());
        $this->assertSame($types, $req->getTypes());
        $this->assertTrue($req->getSortBy()->is('dateDesc'));

        $xml = '<?xml version="1.0"?>'."\n"
            .'<SearchVoiceRequest query="' . $query . '" limit="' . $limit . '" offset="' . $offset . '" types="' . $types . '" sortBy="' . VoiceSortBy::DATE_DESC() . '">'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
            .'</SearchVoiceRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'SearchVoiceRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'query' => $query,
                'limit' => $limit,
                'offset' => $offset,
                'types' => $types,
                'sortBy' => VoiceSortBy::DATE_DESC()->value(),
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testUploadVoiceMail()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $phone = self::randomName();
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );
        $vm = new \Zimbra\Voice\Struct\VoiceMsgUploadSpec(
            $id, $phone
        );

        $req = new \Zimbra\Voice\Request\UploadVoiceMail(
            $storeprincipal, $vm
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($vm, $req->getVoiceMsg());
        $req->setStorePrincipal($storeprincipal)
            ->setVoiceMsg($vm);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($vm, $req->getVoiceMsg());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<UploadVoiceMailRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<vm id="' . $id . '" phone="' . $phone . '" />'
            .'</UploadVoiceMailRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'UploadVoiceMailRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'vm' => [
                    'id' => $id,
                    'phone' => $phone,
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }

    public function testVoiceMsgAction()
    {
        $id = self::randomName();
        $name = self::randomName();
        $accountNumber = self::randomName();
        $phone = self::randomName();
        $folderId = self::randomName();
        $action = new \Zimbra\Voice\Struct\VoiceMsgActionSpec(
            VoiceMsgActionOp::MOVE(), $phone, $id, $folderId
        );
        $storeprincipal = new \Zimbra\Voice\Struct\StorePrincipalSpec(
            $id, $name, $accountNumber
        );

        $req = new \Zimbra\Voice\Request\VoiceMsgAction(
            $action, $storeprincipal
        );
        $this->assertInstanceOf('Zimbra\Voice\Request\Base', $req);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($action, $req->getAction());
        $req->setStorePrincipal($storeprincipal)
            ->setAction($action);
        $this->assertSame($storeprincipal, $req->getStorePrincipal());
        $this->assertSame($action, $req->getAction());

        $xml = '<?xml version="1.0"?>'."\n"
            .'<VoiceMsgActionRequest>'
                .'<storeprincipal id="' . $id . '" name="' . $name . '" accountNumber="' . $accountNumber . '" />'
                .'<action op="' . VoiceMsgActionOp::MOVE() . '" phone="' . $phone . '" id="' . $id . '" l="' . $folderId . '" />'
            .'</VoiceMsgActionRequest>';
        $this->assertXmlStringEqualsXmlString($xml, (string) $req);

        $array = [
            'VoiceMsgActionRequest' => [
                '_jsns' => 'urn:zimbraVoice',
                'storeprincipal' => [
                    'id' => $id,
                    'name' => $name,
                    'accountNumber' => $accountNumber,
                ],
                'action' => [
                    'op' => VoiceMsgActionOp::MOVE()->value(),
                    'phone' => $phone,
                    'id' => $id,
                    'l' => $folderId,
                ],
            ],
        ];
        $this->assertEquals($array, $req->toArray());
    }
}


text:
<?php session_start();?>
<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>Login form using HTML5 and CSS3</title>
    <link rel="stylesheet" href="/EasyMVC_/views/css/style.css">

		<form action="" method ="POST">

Welcom

Login</button>

Register</button>

		</form>

redpajama_set_name: RedPajamaGithub


text:
package com.picas.features.captcha;

/**
 * 验证码常量
 */
public class CaptchaConstant {

	/**
	 * 验证码常量
	 */
	public static final String KEY_CAPTCHA = "SE_KEY_MM_CODE";
}


text:
package com.github.ambry.account;

import com.github.ambry.commons.ByteBufferReadableStreamChannel;
import com.github.ambry.commons.ReadableStreamChannelInputStream;
import com.github.ambry.config.HelixAccountServiceConfig;
import com.github.ambry.messageformat.BlobProperties;
import com.github.ambry.router.GetBlobOptionsBuilder;
import com.github.ambry.router.GetBlobResult;
import com.github.ambry.router.PutBlobOptions;
import com.github.ambry.router.Router;
import com.github.ambry.utils.Utils;
import com.google.common.base.Charsets;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import org.apache.helix.AccessOption;
import org.apache.helix.store.HelixPropertyStore;
import org.apache.helix.zookeeper.datamodel.ZNRecord;
import org.apache.zookeeper.data.Stat;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * RouterStore stores the full set of {@link Account} metadata in {@code AmbryServer} and keep the list of blob ids in
 * a single {@link ZNRecord} in {@link HelixPropertyStore} at {@link #ACCOUNT_METADATA_BLOB_IDS_PATH}. Each item in the
 * list contains the blob id, as well as the version number. In this way, RouterStore keeps track of various versions
 * of {@link Account} metadata, and making rolling back to previous version much easier.
 *
 * When saving {@link Account} metadata as a blob in the {@code AmbryServer}, it's serialized as a json object, where
 * each {@link Account}'id is the key and the {@link Account}'s json format string is the value. Each blob has a predefined
 * {@link Account} id and {@link Container} id. The Account and Container are not actually created but serve as dummy ones
 * to bootstrap the creation of {@link Account} metadata.
 */
class RouterStore extends AccountMetadataStore {
  static final String ACCOUNT_METADATA_BLOB_IDS_PATH = "/account_metadata/blobids";
  static final String ACCOUNT_METADATA_BLOB_IDS_LIST_KEY = "accountMetadataBlobIds";
  private static final String ZN_RECORD_ID = "account_metadata_version_list";
  private static final Logger logger = LoggerFactory.getLogger(RouterStore.class);

  private static final Short ACCOUNT_ID = Account.HELIX_ACCOUNT_SERVICE_ACCOUNT_ID;
  private static final Short CONTAINER_ID = Container.HELIX_ACCOUNT_SERVICE_CONTAINER_ID;
  private static final String SERVICE_ID = "helixAccountService";

  private final int totalNumberOfVersionToKeep;
  private final AtomicReference<Router> router;
  // If forBackFill is true, then when updating the account metadata, we don't create backup files and we don't merge
  // accounts from ambry-server with the provided accounts set.
  private final boolean forBackFill;
  private final HelixAccountServiceConfig config;

  /**
   * Constructor to create the RouterStore.
   * @param accountServiceMetrics The metrics set to update metrics.
   * @param backupFileManager The {@link BackupFileManager} instance to manage backup files.
   * @param helixStore The {@link HelixPropertyStore} to fetch and update data.
   * @param router The {@link Router} instance to retrieve and put blobs.
   * @param forBackFill True if this {@link RouterStore} is created for backfill accounts to new zookeeper node.
   * @param totalNumberOfVersionToKeep The total number of previous versions of account metadata to keep.
   */
  RouterStore(AccountServiceMetrics accountServiceMetrics, BackupFileManager backupFileManager,
      HelixPropertyStore<ZNRecord> helixStore, AtomicReference<Router> router, boolean forBackFill,
      int totalNumberOfVersionToKeep, HelixAccountServiceConfig config) {
    super(accountServiceMetrics, backupFileManager, helixStore, ACCOUNT_METADATA_BLOB_IDS_PATH);
    this.router = router;
    this.forBackFill = forBackFill;
    this.totalNumberOfVersionToKeep = totalNumberOfVersionToKeep;
    this.config = config;
  }

  @Override
  Map<String, String> fetchAccountMetadataFromZNRecord(ZNRecord record) {
    if (router.get() == null) {
      logger.error("Router is not yet initialized");
      return null;
    }
    List<String> blobIDAndVersionsJson = record.getListField(ACCOUNT_METADATA_BLOB_IDS_LIST_KEY);
    if (blobIDAndVersionsJson == null || blobIDAndVersionsJson.size() == 0) {
      logger.info("ZNRecord={} to read on path={} does not have a simple list with key={}", record,
          ACCOUNT_METADATA_BLOB_IDS_PATH, ACCOUNT_METADATA_BLOB_IDS_LIST_KEY);
      return null;
    } else {
      // Parse the json string list and get the blob id with the latest version
      // Since the the blobIDAndVersionsJson.size() is greater than 0, max will return an optional with solid value.
      BlobIDAndVersion blobIDAndVersion = blobIDAndVersionsJson.stream()
          .map(BlobIDAndVersion::fromJson)
          .max(Comparator.comparing(BlobIDAndVersion::getVersion))
          .get();

      logger.trace("Start reading remote account data from blob {} and versioned at {}.", blobIDAndVersion.blobID,
          blobIDAndVersion.version);
      return readAccountMetadataFromBlobID(blobIDAndVersion.blobID);
    }
  }

  /**
   * Fetch the {@link Account} metadata from the given blob id.
   * @param blobID The blobID to fetch {@link Account} metadata from.
   * @return {@link Account} metadata in a map, and null when there is any error.
   */
  Map<String, String> readAccountMetadataFromBlobID(String blobID) {
    long startTimeMs = System.currentTimeMillis();
    Future<GetBlobResult> resultF = router.get().getBlob(blobID, new GetBlobOptionsBuilder().build());
    try {
      GetBlobResult result = resultF.get();
      accountServiceMetrics.accountFetchFromAmbryTimeInMs.update(System.currentTimeMillis() - startTimeMs);

      int blobSize = (int) result.getBlobInfo().getBlobProperties().getBlobSize();
      InputStream input = new ReadableStreamChannelInputStream(result.getBlobDataChannel());
      byte[] bytes = Utils.readBytesFromStream(input, blobSize);

      JSONObject object = new JSONObject(new String(bytes, Charsets.UTF_8));
      Map<String, String> map = new HashMap<>();
      object.keySet().forEach(key -> map.put(key, object.getString(key)));
      return map;
    } catch (Exception e) {
      logger.error("Failed to read account metadata from blob id={}", blobID, e);
      accountServiceMetrics.accountFetchFromAmbryServerErrorCount.inc();
    }
    return null;
  }

  /**
   * Get the list of {@link BlobIDAndVersion} from {@link ZNRecord}. This function returns null when there
   * is any error.
   * @return list of {@link BlobIDAndVersion}.
   */
  private List<BlobIDAndVersion> fetchAllBlobIDAndVersions() {
    if (router.get() == null) {
      logger.error("Router is not yet initialized");
      return null;
    }
    long startTimeMs = System.currentTimeMillis();
    logger.trace("Start reading ZNRecord from path={}", znRecordPath);
    Stat stat = new Stat();
    ZNRecord znRecord = helixStore.get(znRecordPath, stat, AccessOption.PERSISTENT);
    logger.trace("Fetched ZNRecord from path={}, took time={} ms", znRecordPath,
        System.currentTimeMillis() - startTimeMs);
    if (znRecord == null) {
      logger.info("The ZNRecord to read does not exist on path={}", znRecordPath);
      return null;
    }

    List<String> blobIDAndVersionsJson = znRecord.getListField(ACCOUNT_METADATA_BLOB_IDS_LIST_KEY);
    if (blobIDAndVersionsJson == null || blobIDAndVersionsJson.size() == 0) {
      logger.info("ZNRecord={} to read on path={} does not have a simple list with key={}", znRecord,
          ACCOUNT_METADATA_BLOB_IDS_PATH, ACCOUNT_METADATA_BLOB_IDS_LIST_KEY);
      return null;
    } else {
      return blobIDAndVersionsJson.stream().map(BlobIDAndVersion::fromJson).collect(Collectors.toList());
    }
  }

  /**
   * Returns all the versions of {@link Account} metadata as a list. It will return null when the versions are empty.
   * @return All the versions of {@link Account} metadata.
   */
  public List<Integer> getAllVersions() {
    List<BlobIDAndVersion> blobIDAndVersions = fetchAllBlobIDAndVersions();
    if (blobIDAndVersions == null) {
      return null;
    } else {
      return blobIDAndVersions.stream().map(BlobIDAndVersion::getVersion).collect(Collectors.toList());
    }
  }

  /**
   * Return a map from account id to {@link Account} metadata at given version. It returns null when there is any error.
   * @param version The version of {@link Account} metadata to return.
   * @return A map from account id to {@link Account} metadata in json format.
   * @throws IllegalArgumentException When the version is not valid.
   */
  public Map<String, String> fetchAccountMetadataAtVersion(int version) throws IllegalArgumentException {
    List<BlobIDAndVersion> blobIDAndVersions = fetchAllBlobIDAndVersions();
    if (blobIDAndVersions == null) {
      return null;
    }
    for (BlobIDAndVersion blobIDAndVersion : blobIDAndVersions) {
      if (blobIDAndVersion.getVersion() == version) {
        return readAccountMetadataFromBlobID(blobIDAndVersion.getBlobID());
      }
    }
    throw new IllegalArgumentException("Version " + version + " doesn't exist");
  }

  @Override
  AccountMetadataStore.ZKUpdater createNewZKUpdater(Collection<Account> accounts) {
    Objects.requireNonNull(router.get(), "Router is null");
    return new ZKUpdater(accounts);
  }

  /**
   * Save the given {@link Account} metadata, as json object, in a blob in {@code AmbryServer}.
   * @param accountMap The {@link Account} metadata to save.
   * @param router The {@link Router} instance.
   * @return A blob id if the operation is finished successfully.
   * @throws Exception If there is any exceptions while saving the bytes to {@code AmbryServer}.
   */
  static String writeAccountMapToRouter(Map<String, String> accountMap, Router router) throws Exception {
    Objects.requireNonNull(router, "Router is null");
    // Construct the json object and save it to ambry server.
    JSONObject object = new JSONObject();
    for (Map.Entry<String, String> entry : accountMap.entrySet()) {
      object.put(entry.getKey(), entry.getValue());
    }

    ByteBufferReadableStreamChannel channel =
        new ByteBufferReadableStreamChannel(ByteBuffer.wrap(object.toString().getBytes(Charsets.UTF_8)));
    BlobProperties properties = new BlobProperties(channel.getSize(), SERVICE_ID, ACCOUNT_ID, CONTAINER_ID, false);
    return router.putBlob(properties, null, channel, PutBlobOptions.DEFAULT).get();
  }

  /**
   * Helper function to log the error message out and throw an {@link IllegalStateException}.
   * @param errorMessage The error message.
   * @param cause The cause exception.
   */
  private void logAndThrowIllegalStateException(String errorMessage, Exception cause) {
    logger.error(errorMessage, cause);
    throw new IllegalStateException(errorMessage, cause);
  }

  /**
   * A {@link DataUpdater} to be used for updating {@link #ACCOUNT_METADATA_BLOB_IDS_PATH} inside of
   * {@link #updateAccounts(Collection)}
   */
  private class ZKUpdater implements AccountMetadataStore.ZKUpdater {
    private final Collection<Account> accounts;
    private String newBlobID = null;
    private List<String> oldBlobIDsToDelete = null;

    /**
     * @param accounts The {@link Account}s to update.
     */
    ZKUpdater(Collection<Account> accounts) {
      this.accounts = accounts;
    }

    @Override
    public ZNRecord update(ZNRecord znRecord) {
      /* There are several steps to finish an update
       * 1. Fetch the list from the ZNRecord
       * 2. Fetch the AccountMetadata from the blob id if the list exist in the ZNRecord
       * 3. Construct a new AccountMetadata
       * 4. Save it as a blob in the ambry server
       * 5. Remove oldest version if number of version exceeds the maximum value.
       * 6. Add the new blob id to the list.
       */

      // Start step 1:
      ZNRecord recordToUpdate;
      if (znRecord == null) {
        logger.info(
            "ZNRecord does not exist on path={} in HelixPropertyStore when updating accounts. Creating a new ZNRecord.",
            ACCOUNT_METADATA_BLOB_IDS_PATH);
        recordToUpdate = new ZNRecord(ZN_RECORD_ID);
      } else {
        recordToUpdate = znRecord;
      }
      // This is the version number for the new blob id.
      int newVersion = 1;
      List<BlobIDAndVersion> blobIDAndVersions = new ArrayList<>();
      List<String> blobIDAndVersionsJson = recordToUpdate.getListField(ACCOUNT_METADATA_BLOB_IDS_LIST_KEY);
      blobIDAndVersionsJson =
          blobIDAndVersionsJson == null ? new LinkedList<>() : new LinkedList<>(blobIDAndVersionsJson);
      Map<String, String> accountMap = new HashMap<>();

      if (blobIDAndVersionsJson.size() != 0) {
        try {
          // Parse the json string list and get the BlobIDAndVersion with the latest version number.
          blobIDAndVersionsJson.forEach(
              accountBlobIDInJson -> blobIDAndVersions.add(BlobIDAndVersion.fromJson(accountBlobIDInJson)));
          Collections.sort(blobIDAndVersions, Comparator.comparing(BlobIDAndVersion::getVersion));
          BlobIDAndVersion blobIDAndVersion = blobIDAndVersions.get(blobIDAndVersions.size() - 1);
          newVersion = blobIDAndVersion.version + 1;

          // Start Step 2:
          // If this is not for backfill, then just read account metadata from blob, otherwise, initialize it with
          // an empty map and fill it up with the accountMap passed to constructor.
          accountMap = (!forBackFill) ? readAccountMetadataFromBlobID(blobIDAndVersion.blobID) : new HashMap<>();
          if (accountMap == null) {
            logAndThrowIllegalStateException("Fail to read account metadata from blob id " + blobIDAndVersion.blobID,
                null);
          }
        } catch (JSONException e) {
          accountServiceMetrics.remoteDataCorruptionErrorCount.inc();
          logAndThrowIllegalStateException(
              "Exception occurred when parsing the blob id list from " + blobIDAndVersionsJson, e);
        } catch (Exception e) {
          logAndThrowIllegalStateException(
              "Unexpected exception occurred when parsing the blob id list from " + blobIDAndVersionsJson, e);
        }
      }

      if (!forBackFill) {
        // Start step 3:
        AccountInfoMap localAccountInfoMap = null;
        try {
          localAccountInfoMap = new AccountInfoMap(accountServiceMetrics, accountMap);
        } catch (JSONException e) {
          accountServiceMetrics.remoteDataCorruptionErrorCount.inc();
          logAndThrowIllegalStateException(
              "Exception occurred when building AccountInfoMap from accountMap " + accountMap, e);
        }

        // If there is any conflict with the existing record, fail the update. Exception thrown in this updater will
        // be caught by Helix and helixStore#update will return false.
        if (localAccountInfoMap.hasConflictingAccount(this.accounts, config.ignoreVersionMismatch)) {
          // Throw exception, so that helixStore can capture and terminate the update operation
          logAndThrowIllegalStateException(
              "Updating accounts failed because one account to update conflicts with existing accounts", null);
        }
      }

      for (Account account : this.accounts) {
        try {
          String accountJsonStr = objectMapper.writeValueAsString(
              new AccountBuilder(account).snapshotVersion(account.getSnapshotVersion() + 1).build());
          accountMap.put(String.valueOf(account.getId()), accountJsonStr);
        } catch (Exception e) {
          logAndThrowIllegalStateException(
              "Updating accounts failed because unexpected exception occurred when updating accountId="
                  + account.getId() + " accountName=" + account.getName(), e);
        }
      }

      // Start step 4:
      long startTimeMs = System.currentTimeMillis();
      try {
        this.newBlobID = writeAccountMapToRouter(accountMap, router.get());
        accountServiceMetrics.accountUpdateToAmbryTimeInMs.update(System.currentTimeMillis() - startTimeMs);
      } catch (Exception e) {
        accountServiceMetrics.accountUpdatesToAmbryServerErrorCount.inc();
        logAndThrowIllegalStateException(
            "Updating accounts failed because unexpected error occurred when uploading AccountMetadata to ambry", e);
      }

      // Start step 5:
      if (blobIDAndVersions.size() + 1 > totalNumberOfVersionToKeep) {
        Iterator<BlobIDAndVersion> iter = blobIDAndVersions.iterator();
        oldBlobIDsToDelete = new ArrayList<>();
        while (blobIDAndVersions.size() + 1 > totalNumberOfVersionToKeep) {
          BlobIDAndVersion blobIDAndVersion = iter.next();
          iter.remove();
          logger.info("Adding blob {} at version {} to delete", blobIDAndVersion.getBlobID(),
              blobIDAndVersion.getVersion());
          oldBlobIDsToDelete.add(blobIDAndVersion.getBlobID());
        }
        blobIDAndVersionsJson = blobIDAndVersions.stream().map(BlobIDAndVersion::toJson).collect(Collectors.toList());
      }

      // Start step 6:
      blobIDAndVersionsJson.add(new BlobIDAndVersion(this.newBlobID, newVersion).toJson());
      recordToUpdate.setListField(ACCOUNT_METADATA_BLOB_IDS_LIST_KEY, blobIDAndVersionsJson);
      return recordToUpdate;
    }

    @Override
    public void afterUpdate(boolean isUpdateSucceeded) {
      if (!isUpdateSucceeded && newBlobID != null) {
        // Delete the ambry blob regardless what error fails the update.
        try {
          logger.info("Removing blob {} since the update failed", newBlobID);
          // Block this execution? or maybe wait for a while then get out?
          router.get().deleteBlob(newBlobID, SERVICE_ID).get();
        } catch (Exception e) {
          logger.error("Failed to delete blob={}", newBlobID, e);
          accountServiceMetrics.accountDeletesToAmbryServerErrorCount.inc();
        }
      }
      // Notice this logic might end up with the dangling blobs, when the process crashes before the for loop.
      // But since the frequency to update account metadata is pretty rare, it won't be a big problem.
      if (isUpdateSucceeded && oldBlobIDsToDelete != null) {
        for (String blobID : oldBlobIDsToDelete) {
          try {
            logger.info("Removing blob {}", blobID);
            // Block this execution? or maybe wait for a while then get out?
            router.get().deleteBlob(blobID, SERVICE_ID).get();
          } catch (Exception e) {
            logger.error("Failed to delete blob={}", blobID, e);
            accountServiceMetrics.accountDeletesToAmbryServerErrorCount.inc();
          }
        }
      }
    }
  }

  /**
   * Helper class that encapsulates the blob id and version number to serve as each item in the blob id list that would
   * eventually be persisted in {@link ZNRecord} at {@link #ACCOUNT_METADATA_BLOB_IDS_PATH}.
   */
  static class BlobIDAndVersion {
    private final String blobID;
    private final int version;

    private static final String BLOBID_KEY = "blob_id";
    private static final String VERSION_KEY = "version";

    /**
     * Constructor to create a {@link BlobIDAndVersion}.
     * @param blobID The blob id.
     * @param version The version associated with this blob id.
     */
    BlobIDAndVersion(String blobID, int version) {
      this.blobID = blobID;
      this.version = version;
    }

    /**
     * Return a string in json format of this object.
     * @return A string in json format of this object.
     */
    public String toJson() {
      JSONObject object = new JSONObject();
      object.put(BLOBID_KEY, blobID);
      object.put(VERSION_KEY, version);
      return object.toString();
    }

    /**
     * Return version number.
     * @return Version number.
     */
    public int getVersion() {
      return version;
    }

    /**
     * Return blob id.
     * @return Blob id.
     */
    public String getBlobID() {
      return blobID;
    }

    @Override
    public boolean equals(Object o) {
      if (o == this) {
        return true;
      }
      if (!(o instanceof BlobIDAndVersion)) {
        return false;
      }
      BlobIDAndVersion other = (BlobIDAndVersion) o;
      return blobID.equals(other.blobID) && version == other.version;
    }

    /**
     * Deserialize a string that carries a json object to an {@link BlobIDAndVersion}.
     * @param json The string that carries a json object.
     * @return A {@link BlobIDAndVersion} object.
     * @throws JSONException If parsing the string to {@link JSONObject} fails.
     */
    static BlobIDAndVersion fromJson(String json) throws JSONException {
      JSONObject object = new JSONObject(json);
      String blobID = object.getString(BLOBID_KEY);
      int version = object.getInt(VERSION_KEY);
      return new BlobIDAndVersion(blobID, version);
    }
  }
}


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

namespace NullDesk.Extensions.Mailer.Tests.Common
{
    public class TemplateMailerTestData : IEnumerable<object[]>
    {
        private readonly List<object[]> _data = new List<object[]>
        {
            new object[] {"template1", new string[] { }},
            new object[] {"template1", new[] {@"..\..\..\..\TestData\attachments\testFile.1.txt"}},
            new object[]
            {
                "template1",
                new[]
                {
                    @"..\..\..\..\TestData\attachments\testFile.1.txt",
                    @"..\..\..\..\TestData\attachments\testFile.2.txt"
                }
            },
            new object[] {"template2", new[] {@"..\..\..\..\TestData\attachments\testFile.1.txt"}},
            new object[] {"template2", null}
        };

        public IEnumerator<object[]> GetEnumerator()
        {
            return _data.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}


text:
'use strict';

function SpreadsheetException(message, parameters) {
    this.message = message;
    this.parameters = parameters;
}

angular.module('services.spreadsheet', [])
    .config(['$routeProvider', 'securityAuthorizationProvider', function ($routeProvider, securityAuthorizationProvider) {
    $routeProvider.when('/data', {
                controller: 'SpreadsheetCtrl',
                template: ''

            });
    }])

    .controller('SpreadsheetCtrl', ['$scope', '$location', function($scope, $location){
        $scope.showSpreadsheet = function(){
            return $location.url() === '/data';
        };

    }]).

    factory('spreadsheet_interface', ['i18nNotifications', 'I18N.MESSAGES', '$location',
        function (i18nNotifications, I18N_MESSAGES, $location) {
    var sInterface  = {};

    sInterface.getBetween = function(){
        var groupsCol  = this.getColData(0);
        var groups = {};
        var groupList = [];
        for (var g in groupsCol){
            if (groupsCol.hasOwnProperty(g)){
            if (!(groupsCol[g] in groups)){
                groupList.push(groupsCol[g]);
                groups[groupsCol[g]] = " ";
            }
            if (groupsCol[g] === null || !groupsCol[g]){
                throw new SpreadsheetException('GROUP_CANNOT_BE_NULL', {row: (parseInt(g, 10) + 1)});
            }
            }
        }
        return groupList;
    };

    sInterface.getWithin = function(){
        var groupsCol  = this.getRowData(0);
        var groups = {};
        var groupList = [];
        for (var g in groupsCol){
            if (groupsCol[g] in groups){
                throw new SpreadsheetException('DUPLICATE_WITHIN_FACTOR', {factor: (groupsCol[g])});
            }
            else if (groupsCol[g] === null || !groupsCol[g]){
                throw new SpreadsheetException('WITHIN_FACTOR_CANNOT_BE_NULL', {col: (parseInt(g, 10) + 1)});
            }
            else{
                groups[groupsCol[g]] = "";
                groupList.push(groupsCol[g]);
            }
        }
        return groupList;
    };

    sInterface.getData = function(){
        var data = {};

        data.group = this.getColData(0);
        //checking group constrains
        for (var g in data.group){

            if (data.group[g] === null || !data.group[g]){
                throw new SpreadsheetException('GROUP_CANNOT_BE_NULL', {row: (parseInt(g, 10) + 1)});
            }
        }

        var  factors  = this.getRowData(0);
        //checking within factor constrains
        var factorList = {};
        for (var f in factors){
            if (factors[f] in factorList){
                throw new SpreadsheetException('DUPLICATE_WITHIN_FACTOR', {factor: (factors[f])});
            }
            else if (factors[f] === null || !factors[f]){
                throw new SpreadsheetException('WITHIN_FACTOR_CANNOT_BE_NULL', {col: (parseInt(f, 10) + 1)});
            }
            else{
                factorList[factors[f]] = "";
            }
        }

        for (var i = 0; i < factors.length; i++){
            var colData = this.getColData(i+1);
            for(var j=0;j<colData.length;j++){
                if(colData[j] === null || colData[j] === ""){
                    throw new SpreadsheetException('EMPTY_DATA_POINT', {factor: factors[i], row: (parseInt(j, 10)+1)});
                }
            }
            data[factors[i]] = colData;
        }

        return data;
    };

    sInterface.handleError = function(e){
        i18nNotifications.pushForNextRoute(e.message, "danger", e.parameters);
        $location.path('/data');
    };

    return sInterface;

}]);


text:
package pdutil

import (
	"context"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"sync"
	"testing"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/pingcap/failpoint"
	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/tidb/store/pdtypes"
	"github.com/pingcap/tidb/util/codec"
	"github.com/stretchr/testify/require"
)

func TestScheduler(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	scheduler := "balance-leader-scheduler"
	mock := func(context.Context, string, string, *http.Client, string, io.Reader) ([]byte, error) {
		return nil, errors.New("failed")
	}
	schedulerPauseCh := make(chan struct{})
	pdController := &PdController{addrs: []string{"", ""}, schedulerPauseCh: schedulerPauseCh}
	// As pdController.Client is nil, (*pdController).Close() can not be called directly.
	defer close(schedulerPauseCh)

	_, err := pdController.pauseSchedulersAndConfigWith(ctx, []string{scheduler}, nil, mock)
	require.EqualError(t, err, "failed")

	go func() {
		<-schedulerPauseCh
	}()
	err = pdController.resumeSchedulerWith(ctx, []string{scheduler}, mock)
	require.NoError(t, err)

	cfg := map[string]interface{}{
		"max-merge-region-keys":       0,
		"max-snapshot":                1,
		"enable-location-replacement": false,
		"max-pending-peer-count":      uint64(16),
	}
	_, err = pdController.pauseSchedulersAndConfigWith(ctx, []string{}, cfg, mock)
	require.Error(t, err)
	require.Regexp(t, "^failed to update PD", err.Error())
	go func() {
		<-schedulerPauseCh
	}()
	err = pdController.resumeSchedulerWith(ctx, []string{scheduler}, mock)
	require.NoError(t, err)

	_, err = pdController.listSchedulersWith(ctx, mock)
	require.EqualError(t, err, "failed")

	mock = func(context.Context, string, string, *http.Client, string, io.Reader) ([]byte, error) {
		return []byte(`["` + scheduler + `"]`), nil
	}

	_, err = pdController.pauseSchedulersAndConfigWith(ctx, []string{scheduler}, cfg, mock)
	require.NoError(t, err)

	// pauseSchedulersAndConfigWith will wait on chan schedulerPauseCh
	err = pdController.resumeSchedulerWith(ctx, []string{scheduler}, mock)
	require.NoError(t, err)

	schedulers, err := pdController.listSchedulersWith(ctx, mock)
	require.NoError(t, err)
	require.Len(t, schedulers, 1)
	require.Equal(t, scheduler, schedulers[0])
}

func TestGetClusterVersion(t *testing.T) {
	pdController := &PdController{addrs: []string{"", ""}} // two endpoints
	counter := 0
	mock := func(context.Context, string, string, *http.Client, string, io.Reader) ([]byte, error) {
		counter++
		if counter <= 1 {
			return nil, errors.New("mock error")
		}
		return []byte(`test`), nil
	}

	ctx := context.Background()
	respString, err := pdController.getClusterVersionWith(ctx, mock)
	require.NoError(t, err)
	require.Equal(t, "test", respString)

	mock = func(context.Context, string, string, *http.Client, string, io.Reader) ([]byte, error) {
		return nil, errors.New("mock error")
	}
	_, err = pdController.getClusterVersionWith(ctx, mock)
	require.Error(t, err)
}

func TestRegionCount(t *testing.T) {
	regions := &pdtypes.RegionTree{}
	regions.SetRegion(pdtypes.NewRegionInfo(&metapb.Region{
		Id:          1,
		StartKey:    codec.EncodeBytes(nil, []byte{1, 1}),
		EndKey:      codec.EncodeBytes(nil, []byte{1, 3}),
		RegionEpoch: &metapb.RegionEpoch{},
	}, nil))
	regions.SetRegion(pdtypes.NewRegionInfo(&metapb.Region{
		Id:          2,
		StartKey:    codec.EncodeBytes(nil, []byte{1, 3}),
		EndKey:      codec.EncodeBytes(nil, []byte{1, 5}),
		RegionEpoch: &metapb.RegionEpoch{},
	}, nil))
	regions.SetRegion(pdtypes.NewRegionInfo(&metapb.Region{
		Id:          3,
		StartKey:    codec.EncodeBytes(nil, []byte{2, 3}),
		EndKey:      codec.EncodeBytes(nil, []byte{3, 4}),
		RegionEpoch: &metapb.RegionEpoch{},
	}, nil))
	require.Equal(t, 3, len(regions.Regions))

	mock := func(
		_ context.Context, addr string, prefix string, _ *http.Client, _ string, _ io.Reader,
	) ([]byte, error) {
		query := fmt.Sprintf("%s/%s", addr, prefix)
		u, e := url.Parse(query)
		require.NoError(t, e, query)
		start := u.Query().Get("start_key")
		end := u.Query().Get("end_key")
		t.Log(hex.EncodeToString([]byte(start)))
		t.Log(hex.EncodeToString([]byte(end)))
		scanRegions := regions.ScanRange([]byte(start), []byte(end), 0)
		stats := pdtypes.RegionStats{Count: len(scanRegions)}
		ret, err := json.Marshal(stats)
		require.NoError(t, err)
		return ret, nil
	}

	pdController := &PdController{addrs: []string{"http://mock"}}
	ctx := context.Background()
	resp, err := pdController.getRegionCountWith(ctx, mock, []byte{}, []byte{})
	require.NoError(t, err)
	require.Equal(t, 3, resp)

	resp, err = pdController.getRegionCountWith(ctx, mock, []byte{0}, []byte{0xff})
	require.NoError(t, err)
	require.Equal(t, 3, resp)

	resp, err = pdController.getRegionCountWith(ctx, mock, []byte{1, 2}, []byte{1, 4})
	require.NoError(t, err)
	require.Equal(t, 2, resp)
}

func TestPDVersion(t *testing.T) {
	v := []byte("\"v4.1.0-alpha1\"\n")
	r := parseVersion(v)
	expectV := semver.New("4.1.0-alpha1")
	require.Equal(t, expectV.Major, r.Major)
	require.Equal(t, expectV.Minor, r.Minor)
	require.Equal(t, expectV.PreRelease, r.PreRelease)
}

func TestPDRequestRetry(t *testing.T) {
	ctx := context.Background()

	require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/br/pkg/pdutil/FastRetry", "return(true)"))
	defer func() {
		require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/br/pkg/pdutil/FastRetry"))
	}()

	count := 0
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		count++
		if count <= pdRequestRetryTime-1 {
			w.WriteHeader(http.StatusGatewayTimeout)
			return
		}
		w.WriteHeader(http.StatusOK)
	}))
	cli := http.DefaultClient
	taddr := ts.URL
	_, reqErr := pdRequest(ctx, taddr, "", cli, http.MethodGet, nil)
	require.NoError(t, reqErr)
	ts.Close()
	count = 0
	ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		count++
		if count <= pdRequestRetryTime+1 {
			w.WriteHeader(http.StatusGatewayTimeout)
			return
		}
		w.WriteHeader(http.StatusOK)
	}))
	defer ts.Close()
	taddr = ts.URL
	_, reqErr = pdRequest(ctx, taddr, "", cli, http.MethodGet, nil)
	require.Error(t, reqErr)
}

func TestStoreInfo(t *testing.T) {
	storeInfo := pdtypes.StoreInfo{
		Status: &pdtypes.StoreStatus{
			Capacity:  pdtypes.ByteSize(1024),
			Available: pdtypes.ByteSize(1024),
		},
		Store: &pdtypes.MetaStore{
			StateName: "Tombstone",
		},
	}
	mock := func(
		_ context.Context, addr string, prefix string, _ *http.Client, _ string, _ io.Reader,
	) ([]byte, error) {
		query := fmt.Sprintf("%s/%s", addr, prefix)
		require.Equal(t, "http://mock/pd/api/v1/store/1", query)
		ret, err := json.Marshal(storeInfo)
		require.NoError(t, err)
		return ret, nil
	}

	pdController := &PdController{addrs: []string{"http://mock"}}
	ctx := context.Background()
	resp, err := pdController.getStoreInfoWith(ctx, mock, 1)
	require.NoError(t, err)
	require.NotNil(t, resp)
	require.NotNil(t, resp.Status)
	require.Equal(t, "Tombstone", resp.Store.StateName)
	require.Equal(t, uint64(1024), uint64(resp.Status.Available))
}

func TestPauseSchedulersByKeyRange(t *testing.T) {
	const ttl = time.Second

	labelExpires := make(map[string]time.Time)

	var (
		mu      sync.Mutex
		deleted bool
	)

	httpSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mu.Lock()
		defer mu.Unlock()
		if deleted {
			return
		}
		if r.Method == http.MethodDelete {
			ruleID := strings.TrimPrefix(r.URL.Path, "/"+regionLabelPrefix+"/")
			delete(labelExpires, ruleID)
			deleted = true
			return
		}
		var labelRule LabelRule
		err := json.NewDecoder(r.Body).Decode(&labelRule)
		require.NoError(t, err)
		require.Len(t, labelRule.Labels, 1)
		regionLabel := labelRule.Labels[0]
		require.Equal(t, "schedule", regionLabel.Key)
		require.Equal(t, "deny", regionLabel.Value)
		reqTTL, err := time.ParseDuration(regionLabel.TTL)
		require.NoError(t, err)
		if reqTTL == 0 {
			delete(labelExpires, labelRule.ID)
		} else {
			require.Equal(t, ttl, reqTTL)
			if expire, ok := labelExpires[labelRule.ID]; ok {
				require.True(t, expire.After(time.Now()), "should not expire before now")
			}
			labelExpires[labelRule.ID] = time.Now().Add(ttl)
		}
	}))
	defer httpSrv.Close()

	pdController := &PdController{addrs: []string{httpSrv.URL}, cli: http.DefaultClient}
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	done, err := pdController.pauseSchedulerByKeyRangeWithTTL(ctx, []byte{0, 0, 0, 0}, []byte{0xff, 0xff, 0xff, 0xff}, ttl)
	require.NoError(t, err)
	time.Sleep(ttl * 3)
	cancel()
	<-done
	require.Len(t, labelExpires, 0)
}


text:
0.20.0 / 2016-02-01
==================

 * Add coveralls badge, remove link to old report (Felix Böhm)
 * Update lodash dependeny to 4.1.0 (leif.hanack)
 * Fix PR #726 adding 'appendTo()' and 'prependTo()' (Delgan)
 * Added appendTo and prependTo with tests #641 (digihaven)
 * Fix #780 by changing options context in '.find()' (Felix Böhm)
 * Add an unit test checking the query of child (Delgan)
 * fix #667: attr({foo: null}) removes attribute foo, like attr('foo', null) (Ray Waldin)
 * Include reference to dedicated "Loading" section (Mike Pennisi)
 * Added load method to $ (alanev)
 * update css-select to 1.2.0 (Felix Böhm)
 * Fixing Grammatical Error (Dan Corman)
 * Test against node v0.12 --> v4.2 (Jason Kurian)
 * Correct output in example (Felix Böhm)
 * Fix npm files filter (Bogdan Chadkin)
 * Enable setting data on all elements in selection (Mike Pennisi)
 * Reinstate `$.fn.toArray` (Mike Pennisi)
 * update css-select to 1.1.0 (Thomas Shafer)
 * Complete implementation of `wrap` (Mike Pennisi)
 * Correct name of unit test (Mike Pennisi)
 * Correct grammar in test titles (Mike Pennisi)
 * Normalize whitespace (Mike Pennisi)
 * Insert omitted assertion (Mike Pennisi)
 * Update invocation of `children` (Mike Pennisi)
 * Begin implementation of `wrap` method (Dandlezzz)
 * Update Readme.md (Sven Slootweg)
 * fix document's mistake in Readme.md (exoticknight)
 * Add tests for setting text and html as non-strings (Ryc O'Chet)
 * Fix for passing non-string values to .html or .text (Ryc O'Chet)
 * use a selector to filter form elements (fb55)
 * fix README.md typo (Yutian Li)
 * README: fix spelling (Chris Rebert)
 * Added support for options without a `value` attribute. Fixes #633 (Todd Wolfson)
 * responding to pull request feedback - remove item() method and related tests (Ray Waldin)
 * add length property and item method to object returned by prop('style'), plus tests (Ray Waldin)
 * Added .prop method to readme (Artem Burtsev)
 * Added .prop method (Artem Burtsev)
 * Added Gitter badge (The Gitter Badger)

0.19.0 / 2015-03-21
==================

 * fixed allignment (fb55)
 * added test case for malformed json in data attributes (fb55)
 * fix: handle some extreme cases like `data-custom="{{templatevar}}"`. There is possibility error while parsing json . (Harish.K)
 * Add missing optional selector doc for {prev,next}{All,Until} (Jérémie Astori)
 * update to dom-serializer@0.1.0 (Felix Böhm)
 * Document `Cheerio#serialzeArray` (Mike Pennisi)
 * Fixed up `serializeArray()` and added multiple support (Todd Wolfson)
 * Implement serializeArray() (Jarno Leppänen)
 * recognize options in $.xml() (fb55)
 * lib/static.js: text(): rm errant space before ++ (Chris Rebert)
 * Do not expose internal `children` array (Mike Pennisi)
 * Change lodash dependencies to ^3.1.0 (Samy Pessé)
 * Update lodash@3.1.0 (Samy Pessé)
 * Updates Readme.md: .not(function (index, elem)) (Patrick Ward)
 * update to css-select@1.0.0 (fb55)
 * Allow failures in Node.js v0.11 (Mike Pennisi)
 * Added: Gittask badge (Matthew Mueller)
 * Isolate prototypes of functions created via `load` (Mike Pennisi)
 * Updates Readme.md: adds JS syntax highlighting (frankcash)
 * #608 -- Add support for insertBefore/insertAfter syntax. Supports target types of: $, [$], selector (both single and multiple results) (Ben Cochran)
 * Clone input nodes when inserting over a set (Mike Pennisi)
 * Move unit test files (Mike Pennisi)
 * remove unnecessarily tricky code (David Chambers)
 * pass options to $.html in toString (fb55)
 * add license info to package.json (Chris Rebert)
 * xyz@~0.5.0 (David Chambers)
 * Remove unofficial signature of `children` (Mike Pennisi)
 * Fix bug in `css` method (Mike Pennisi)
 * Correct bug in implementation of `Cheerio#val` (Mike Pennisi)

0.18.0 / 2014-11-06
==================

 * bump htmlparser2 dependency to ~3.8.1 (Chris Rebert)
 * Correct unit test titles (Mike Pennisi)
 * Correct behavior of `after` and `before` (Mike Pennisi)
 * implement jQuery's .has() (Chris Rebert)
 * Update repository url (haqii)
 * attr() should return undefined or name for booleans (Raoul Millais)
 * Update Readme.md (Ryan Breen)
 * Implement `Cheerio#not` (Mike Pennisi)
 * Clone nodes according to original parsing options (Mike Pennisi)
 * fix lint error (David Chambers)
 * Add explicit tests for DOM level 1 API (Mike Pennisi)
 * Expose DOM level 1 API for Node-like objects (Mike Pennisi)
 * Correct error in documentation (Mike Pennisi)
 * Return a fully-qualified Function from `$.load` (Mike Pennisi)
 * Update tests to avoid duck typing (Mike Pennisi)
 * Alter "loaded" functions to produce true instances (Mike Pennisi)
 * Organize tests for `cheerio.load` (Mike Pennisi)
 * Complete `$.prototype.find` (Mike Pennisi)
 * Use JSHint's `extends` option (Mike Pennisi)
 * Remove aliases for exported methods (Mike Pennisi)
 * Disallow unused variables (Mike Pennisi)
 * Remove unused internal variables (Mike Pennisi)
 * Remove unused variables from unit tests (Mike Pennisi)
 * Remove unused API method references (Mike Pennisi)
 * Move tests for `contains` method (Mike Pennisi)
 * xyz@0.4.0 (David Chambers)
 * Created a wiki for companies using cheerio in production (Matthew Mueller)
 * Implement `$.prototype.index` (Mike Pennisi)
 * Implement `$.prototype.addBack` (Mike Pennisi)
 * Added double quotes to radio attribute name to account for characters such as brackets (akant10)
 * Update History.md (Gabriel Falkenberg)
 * add 0.17.0 changelog (David Chambers)
 * exit prepublish script if tag not found (David Chambers)
 * alphabetize devDependencies (fb55)
 * ignore coverage dir (fb55)
 * submit coverage to coveralls (fb55)
 * replace jscoverage with istanbul (fb55)

0.17.0 / 2014-06-10
==================

 * Fix bug in internal `uniqueSplice` function (Mike Pennisi)
 * accept buffer argument to cheerio.load (David Chambers)
 * Respect options on the element level (Alex Indigo)
 * Change state definition to more readable (Artem Burtsev)
 * added test (0xBADC0FFEE)
 * add class only if doesn't exist (Artem Burtsev)
 * Made it less insane. (Alex Indigo)
 * Implement `Cheerio#add` (Mike Pennisi)
 * Use "loaded" instance of Cheerio in unit tests (Mike Pennisi)
 * Be more strict with object check. (Alex Indigo)
 * Added options argument to .html() static method. (Alex Indigo)
 * Fixed encoding mishaps. Adjusted tests. (Alex Indigo)
 * use dom-serializer module (fb55)
 * don't test on 0.8, don't ignore 0.11 (Felix Böhm)
 * parse: rm unused variables (coderaiser)
 * cheerio: rm unused variable (coderaiser)
 * Fixed test (Avi Kohn)
 * Added test (Avi Kohn)
 * Changed == to === (Avi Kohn)
 * Fixed a bug in removing type="hidden" attr (Avi Kohn)
 * sorted (Alexey Raspopov)
 * add `muted` attr to booleanAttributes (Alexey Raspopov)
 * fixed context of `this` in .html (Felix Böhm)
 * append new elements for each element in selection (fb55)

0.16.0 / 2014-05-08
==================

 * fix `make bench` (David Chambers)
 * makefile: add release-* targets (David Chambers)
 * alphabetize dependencies (David Chambers)
 * Rewrite `data` internals with caching behavior (Mike Pennisi)
 * Fence .val example as js (Kevin Sawicki)
 * Fixed typos. Deleted trailing whitespace from test/render.js (Nattaphoom Ch)
 * Fix manipulation APIs with removed elements (kpdecker)
 * Perform manual string parsing for hasClass (kpdecker)
 * Fix existing element removal (kpdecker)
 * update render tests (Felix Böhm)
 * fixed cheerio path (Felix Böhm)
 * use `entities.escape` for attribute values (Felix Böhm)
 * bump entities version (Felix Böhm)
 * remove lowerCaseTags option from readme (Felix Böhm)
 * added test case for .html in xmlMode (fb55)
 * render xml in `html()` when `xmlMode: true` (fb55)
 * use a map for booleanAttributes (fb55)
 * update singleTags, use utils.isTag (fb55)
 * update travis badge URL (Felix Böhm)
 * use typeof instead of _.isString and _.isNumber (fb55)
 * use Array.isArray instead of _.isArray (fb55)
 * replace _.isFunction with typeof (fb55)
 * removed unnecessary error message (fb55)
 * decode entities in htmlparser2 (fb55)
 * pass options object to CSSselect (fb55)

0.15.0 / 2014-04-08
==================

 * Update callbacks to pass element per docs (@kpdecker)
 * preserve options (@fb55)
 * Use SVG travis badge (@t3chnoboy)
 * only use static requires (@fb55)
 * Optimize manipulation methods (@kpdecker)
 * Optimize add and remove class cases (@kpdecker)
 * accept dom of DomHandler to cheerio.load (@nleush)
 * added parentsUntil method (@finspin)
 * Add performance optimization and bug fix `empty` method (@kpdecker)

0.14.0 / 2014-04-01
==================

 * call encodeXML and directly expose decodeHTML (@fb55)
 * use latest htmlparser2 and entities versions (@fb55)
 * Deprecate `$.fn.toArray` (@jugglinmike)
 * Implement `$.fn.get` (@jugglinmike)
 * .replaceWith now replaces all selected elements. (@xavi-)
 * Correct arguments for 'replaceWith' callback (@jugglinmike)
 * switch to lodash (@fb55)
 * update to entities@0.5.0 (@fb55)
 * Fix attr when $ collection contains text modules (@kpdecker)
 * Update to latest version of expect.js (@jugglinmike)
 * Remove nodes from their previous structures (@jugglinmike)
 * Update render.js (@stevenvachon)
 * CDATA test (@stevenvachon)
 * only ever one child index for cdata (@stevenvachon)
 * don't loop through cdata children array (@stevenvachon)
 * proper rendering of CDATA (@stevenvachon)
 * Add cheerio-only bench option (@kpdecker)
 * Avoid delete operations (@kpdecker)
 * Add independent html benchmark (@kpdecker)
 * Cache tag check in render (@kpdecker)
 * Simplify attribute rendering step (@kpdecker)
 * Add html rendering bench case (@kpdecker)
 * Remove unnecessary check from removeAttr (@kpdecker)
 * Remove unnecessary encoding step for attrs (@kpdecker)
 * Add test for removeAttr+attr on boolean attributes (@kpdecker)
 * Add single element benchmark case (@kpdecker)
 * Optimize filter with selector (@kpdecker)
 * Fix passing context as dom node (@alfred-nsh)
 * Fix bug in `nextUntil` (@jugglinmike)
 * Fix bug in `nextAll` (@jugglinmike)
 * Implement `selector` argument of `next` method (@jugglinmike)
 * Fix bug in `prevUntil` (@jugglinmike)
 * Implement `selector` argument of `prev` method (@jugglinmike)
 * Fix bug in `prevAll` (@jugglinmike)
 * Fix bug in `siblings` (@jugglinmike)
 * Avoid unnecessary indexOf from toggleClass (@kpdecker)
 * Use strict equality rather than falsy check in eq (@kpdecker)
 * Add benchmark coverage for all $ APIs (@kpdecker)
 * Optimize filter Cheerio intermediate creation (@kpdecker)
 * Optimize siblings cheerio instance creation (@kpdecker)
 * Optimize identity cases for first/last/eq (@kpdecker)
 * Use domEach for traversal (@kpdecker)
 * Inline children lookup in find (@kpdecker)
 * Use domEach in data accessor (@kpdecker)
 * Avoid cheerio creation in add/remove/toggleClass (@kpdecker)
 * Implement getAttr local helper (@kpdecker)

0.13.1 / 2014-01-07
==================

 * Fix select with context in Cheerio function (@jugglinmike)
 * Remove unecessary DOM maintenance logic (@jugglinmike)
 * Deprecate support for node 0.6

0.13.0 / 2013-12-30
==================

 * Remove "root" node (@jugglinmike)
 * Fix bug in `prevAll`, `prev`, `nextAll`, `next`, `prevUntil`, `nextUntil` (@jugglinmike)
 * Fix `replaceWith` method (@jugglinmike)
 * added nextUntil() and prevUntil() (@finspin)
 * Remove internal `connect` function (@jugglinmike)
 * Rename `Cheerio#make` to document private status (@jugginmike)
 * Remove extraneous call to `_.uniq` (@jugglinmike)
 * Use CSSselect library directly (@jugglinmike)
 * Run CI against Node v0.11 as an allowed failure (@jugginmike)
 * Correct bug in `Cheerio#parents` (@jugglinmike)
 * Implement `$.fn.end` (@jugginmike)
 * Ignore colons inside of url(.*) when parsing css (@Meekohi)
 * Introduce rudimentary benchmark suite (@jugglinmike)
 * Update HtmlParser2 version (@jugglinmike)
 * Correct inconsistency in `$.fn.map` (@jugglinmike)
 * fixed traversing tests (@finspin)
 * Simplify `make` method (@jugglinmike)
 * Avoid shadowing instance methods from arrays (@jugglinmike)

0.12.4 / 2013-11-12
==================

 * Coerce JSON values returned by `data` (@jugglinmike)
 * issue #284: when rendering HTML, use original data attributes (@Trott)
 * Introduce JSHint for automated code linting (@jugglinmike)
 * Prevent `find` from returning duplicate elements (@jugglinmike)
 * Implement function signature of `replaceWith` (@jugglinmike)
 * Implement function signature of `before` (@jugglinmike)
 * Implement function signature of `after` (@jugglinmike)
 * Implement function signature of `append`/`prepend` (@jugglinmike)
 * Extend iteration methods to accept nodes (@jugglinmike)
 * Improve `removeClass` (@jugglinmike)
 * Complete function signature of `addClass` (@jugglinmike)
 * Fix bug in `removeClass` (@jugglinmike)
 * Improve contributing.md (@jugglinmike)
 * Fix and document .css() (@jugglinmike)

0.12.3 / 2013-10-04
===================

 * Add .toggleClass() function (@cyberthom)
 * Add contributing guidelines (@jugglinmike)
 * Fix bug in `siblings` (@jugglinmike)
 * Correct the implementation `filter` and `is` (@jugglinmike)
 * add .data() function (@andi-neck)
 * add .css() (@yields)
 * Implements contents() (@jlep)

0.12.2 / 2013-09-04
==================

 * Correct implementation of `$.fn.text` (@jugglinmike)
 * Refactor Cheerio array creation (@jugglinmike)
 * Extend manipulation methods to accept Arrays (@jugglinmike)
 * support .attr(attributeName, function(index, attr)) (@xiaohwan)

0.12.1 / 2013-07-30
==================

 * Correct behavior of `Cheerio#parents` (@jugglinmike)
 * Double quotes inside attributes kills HTML (@khoomeister)
 * Making next({}) and prev({}) return empty object (@absentTelegraph)
 * Implement $.parseHTML (@jugglinmike)
 * Correct bug in jQuery.fn.closest (@jugglinmike)
 * Correct behavior of $.fn.val on 'option' elements (@jugglinmike)

0.12.0 / 2013-06-09
===================

  * Breaking Change: Changed context from parent to the actual passed one (@swissmanu)
  * Fixed: jquery checkbox val behavior (@jhubble)
  * Added: output xml with $.xml() (@Maciek416)
  * Bumped: htmlparser2 to 3.1.1
  * Fixed: bug in attr(key, val) on empty objects (@farhadi)
  * Added: prevAll, nextAll (@lessmind)
  * Fixed: Safety check in parents and closest (@zero21xxx)
  * Added: .is(sel) (@zero21xxx)

0.11.0 / 2013-04-22
==================

* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
* Added: Travis support for node 0.10.0 (@jeremy-dentel)
* Fixed: .find() if no selector (@davidchambers)
* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers)

0.10.8 / 2013-03-11
==================

* Add slice method (SBoudrias)

0.10.7 / 2013-02-10
==================

* Code & doc cleanup (davidchambers)
* Fixed bug in filter (jugglinmike)

0.10.6 / 2013-01-29
==================

* Added `$.contains(...)` (jugglinmike)
* formatting cleanup (davidchambers)
* Bug fix for `.children()` (jugglinmike & davidchambers)
* Remove global `render` bug (wvl)

0.10.5 / 2012-12-18
===================

* Fixed botched publish from 0.10.4 - changes should now be present

0.10.4 / 2012-12-16
==================

* $.find should query descendants only (@jugglinmike)
* Tighter underscore dependency

0.10.3 / 2012-11-18
===================

* fixed outer html bug
* Updated documentation for $(...).html() and $.html()

0.10.2 / 2012-11-17
===================

* Added a toString() method (@bensheldon)
* use `_.each` and `_.map` to simplify cheerio namesakes (@davidchambers)
* Added filter() with tests and updated readme (@bensheldon & @davidchambers)
* Added spaces between attributes rewritten by removeClass (@jos3000)
* updated docs to remove reference to size method (@ironchefpython)
* removed HTML tidy/pretty print from cheerio

0.10.1 / 2012-10-04
===================

* Fixed regression, filtering with a context (#106)

0.10.0 / 2012-09-24
===================

* Greatly simplified and reorganized the library, reducing the loc by 30%
* Now supports mocha's test-coverage
* Deprecated self-closing tags (HTML5 doesn't require them)
* Fixed error thrown in removeClass(...) @robashton

0.9.2 / 2012-08-10
==================

* added $(...).map(fn)
* manipulation: refactor `makeCheerioArray`
* make .removeClass() remove *all* occurrences (#64)

0.9.1 / 2012-08-03
==================

* fixed bug causing options not to make it to the parser

0.9.0 / 2012-07-24
==================

* Added node 8.x support
* Removed node 4.x support
* Add html(dom) support (@wvl)
* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55)
* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers)
* Tons of cleanup (@davidchambers)

0.8.3 / 2012-06-12
==================

* Fixed minor package regression (closes #60)

0.8.2 / 2012-06-11
==================

* Now fails gracefully in cases that involve special chars, which is inline with jQuery (closes #59)
* text() now decode special entities (closes #52)
* updated travis.yml to test node 4.x

0.8.1 / 2012-06-02
==================

* fixed regression where if you created an element, it would update the root
* compatible with node 4.x (again)

0.8.0 / 2012-05-27
==================

* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests

0.7.0 / 2012-04-08
==================

* Now testing with node v0.7.7
* Added travis-ci integration
* Replaced should.js with expect.js. Browser testing to come
* Fixed spacing between attributes and their values
* Added HTML tidy/pretty print
* Exposed node-htmlparser2 parsing options
* Revert .replaceWith(...) to be consistent with jQuery

0.6.2 / 2012-02-12
==================

* Fixed .replaceWith(...) regression

0.6.1 / 2012-02-12
==================

* Added .first(), .last(), and .clone() commands.
* Option to parse using whitespace added to `.load`.
* Many bug fixes to make cheerio more aligned with jQuery.
* Added $(':root') to select the highest level element.

Many thanks to the contributors that made this release happen: @ironchefpython and @siddMahen

0.6.0 / 2012-02-07
==================

* *Important:* `$(...).html()` now returns inner HTML, which is in line with the jQuery spec
* `$.html()` returns the full HTML string. `$.html([cheerioObject])` will return the outer(selected element's tag) and inner HTML of that object
* Fixed bug that prevented HTML strings with depth (eg. `append('<ul><li><li></ul>')`) from getting `parent`, `next`, `prev` attributes.
* Halted [htmlparser2](https://github.com/FB55/node-htmlparser) at v2.2.2 until single attributes bug gets fixed.

0.5.1 / 2012-02-05
==================

* Fixed minor regression: $(...).text(fn) would fail

0.5.1 / 2012-02-05
==================

* Fixed regression: HTML pages with comments would fail

0.5.0 / 2012-02-04
==================

* Transitioned from Coffeescript back to Javascript
* Parser now ignores whitespace
* Fixed issue with double slashes on self-enclosing tags
* Added boolean attributes to html rendering

0.4.2 / 2012-01-16
==================

* Multiple selectors support: $('.apple, .orange'). Thanks @siddMahen!
* Update package.json to always use latest cheerio-soupselect
* Fix memory leak in index.js

0.4.1 / 2011-12-19
==================
* Minor packaging changes to allow `make test` to work from npm installation

0.4.0 / 2011-12-19
==================

* Rewrote all unit tests as cheerio transitioned from vows -> mocha
* Internally, renderer.render -> render(...), parser.parse -> parse(...)
* Append, prepend, html, before, after all work with only text (no tags)
* Bugfix: Attributes can now be removed from script and style tags
* Added yield as a single tag
* Cheerio now compatible with node >=0.4.7

0.3.2 / 2011-12-1
=================

* Fixed $(...).text(...) to work with "root" element

0.3.1 / 2011-11-25
==================

* Now relying on cheerio-soupselect instead of node-soupselect
* Removed all lingering htmlparser dependencies
* parser now returns parent "root" element. Root now never needs to be updated when there is multiple roots. This fixes ongoing issues with before(...), after(...) and other manipulation functions
* Added jQuery's $(...).replaceWith(...)

0.3.0 / 2011-11-19
==================

* Now using htmlparser2 for parsing (2x speed increase, cleaner, actively developed)
* Added benchmark directory for future speed tests
* $('...').dom() was funky, so it was removed in favor of $('...').get(). $.dom() still works the same.
* $.root now correctly static across all instances of $
* Added a screencast

0.2.2 / 2011-11-9
=================

* Traversing will select `<script>` and `<style>` tags (Closes Issue: #8)
* .text(string) now working with empty elements (Closes Issue: #7)
* Fixed before(...) & after(...) again if there is no parent (Closes Issue: #2)

0.2.1 / 2011-11-5
=================

* Fixed before(...) & after(...) if there is no parent (Closes Issue: #2)
* Comments now rendered correctly (Closes Issue: #5)

< 0.2.0 / 2011-10-31
====================

* Initial release (untracked development)


text:
function theBuffer = nc_getbuffer ( ncfile, varargin )
%NC_GETBUFFER  Read unlimited variables into structure.
%
%   theBuffer = NC_GETBUFFER(NCFILE) reads all unlimited variables into a
%   structure.
%
%   theBuffer = NC_GETBUFFER(NCFILE,VARLIST) reads variables listed in the
%   cell array VARLIST into a structure.
%
%   theBuffer = NC_GETBUFFER(NCFILE,START,COUNT) reads all unlimited
%   variables into a structure.  I/O starts at zero-indexed record number
%   START and encompasses COUNT records.  IF COUNT is negative, then all
%   records starting at COUNT to the end of the file are retrieved.
%
%   theBuffer = NC_GETBUFFER(NCFILE,VARLIST,START,COUNT) reads variables
%   listed in the cell array VARLIST into a structure.  I/O starts at
%   zero-indexed record number START and encompasses COUNT records.
%
%   See also NC_VARGET.

preserve_fvd = nc_getpref('PRESERVE_FVD');

% assume failure until success is known
theBuffer = [];

error(nargchk(1,4,nargin,'struct'));
error(nargoutchk(1,1,nargout,'struct'));

%
% check that the first argument is a char
if ~ischar ( ncfile )
       error (  'snctools:getbuffer:badInput', 'filename argument must be character.' );
end

[varlist,start,count] = parse_inputs ( varargin{:} );

metadata = nc_info ( ncfile );

num_datasets = length(metadata.Dataset);

skip_this_variable = construct_skip_list(varlist,metadata);

%
% Find the unlimited dimension and it's length
record_length = -1;
num_dims = length(metadata.Dimension);
for j = 1:num_dims
    if metadata.Dimension(j).Unlimited
        record_length = metadata.Dimension(j).Length;
    end
end
if record_length < 0
       error (  'snctools:getbuffer:noUnlimitedDimension', ...
             'An unlimited dimension is required.');
end

%
% figure out what the start and count really are.
if ~isempty(start) && ~isempty(count)
    if start < 0
        start = record_length - count;
    end
    if count < 0
        count = record_length - start;
    end
    if (start < 0) && (count < 0)
           error (  'snctools:getbuffer:badIndexing', ...
                 'both start and count cannot be less than zero.');
    end
end

for j = 1:num_datasets

    %
    % Did we restrict retrieval to a few variables?
    if ~isempty(varlist) && skip_this_variable(j)
        continue
    end

    %
    % If it is not an unlimited variable, we don't want it.
    if ~metadata.Dataset(j).Unlimited
        continue
    end

    if ~isempty(start) && ~isempty(count)

        varstart = zeros(size(metadata.Dataset(j).Size));
        varcount = metadata.Dataset(j).Size;

        if preserve_fvd
            varstart(end) = start;
            varcount(end) = count;
        else
            varstart(1) = start;
            varcount(1) = count;
        end

        vardata = nc_varget ( ncfile, metadata.Dataset(j).Name, varstart, varcount );

    else
        vardata = nc_varget ( ncfile, metadata.Dataset(j).Name );
    end

    theBuffer.(metadata.Dataset(j).Name) = vardata;

end

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [varlist, start, count] = parse_inputs ( varargin )

varlist = {};
start = [];
count = [];

%
% figure out what the inputs actually were
switch nargin
case 1
    if iscell(varargin{1})
        varlist = varargin{1};
    else
        error ( 'snctools:getbuffer:badInput', '2nd of two input arguments must be a cell array.' );
    end
case 2
    if isnumeric(varargin{1}) && isnumeric(varargin{2})
        start = varargin{1};
        count = varargin{2};
    else
        error ( 'snctools:getbuffer:badInput', '2nd and 3rd of three input arguments must be numeric.' );
    end
case 3
    if iscell(varargin{1})
        varlist = varargin{1};
    else
        error ( 'snctools:getbuffer:badInput', '2nd of four input arguments must be a cell array.' );
    end
    if isnumeric(varargin{2}) && isnumeric(varargin{3})
        start = varargin{2};
        count = varargin{3};
    else
        error ( 'snctools:getbuffer:badInput', '3rd and 4th of four input arguments must be numeric.' );
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function skip_it = construct_skip_list(varlist,metadata)

num_datasets = length(metadata.Dataset);
if ~isempty(varlist)

    skip_it = ones(num_datasets,1);

    %
    % Go thru and quickly set up a flag for each Dataset
    for j = 1:num_datasets
        for k = 1:length(varlist)
            if strcmp(varlist{k}, metadata.Dataset(j).Name)
                skip_it(j) = 0;
            end
        end
    end

else
    skip_it = zeros(num_datasets,1);
end

retrievable_datasets = find(1 - skip_it);
if ~any(retrievable_datasets)
    error ( 'No datasets found.\n' );
end


text:
global using Pitstop.TimeService;
global using Pitstop.TimeService.Events;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Pitstop.Infrastructure.Messaging.Configuration;
global using Pitstop.Infrastructure.Messaging;
global using Serilog;


text:
package lejos.nxt.addon;

import lejos.nxt.*;

/*
 * WARNING: THIS CLASS IS SHARED BETWEEN THE classes AND pccomms PROJECTS.
 * DO NOT EDIT THE VERSION IN pccomms AS IT WILL BE OVERWRITTEN WHEN THE PROJECT IS BUILT.
 */

/**
 * Supports HiTechnics EOPD (Electro Optical Proximity Detector) sensor.<br>
 * This sensor is used to detect objects and small changes in distance to a target.
 *  Unlike the lego light sensor it is not affected by other light sources.
 *
 * @author Michael Smith <mdsmitty@gmail.com>
 *
 */
public class EOPD implements SensorConstants{
	ADSensorPort port;

	/**
	 * By default the sensor is short range.
	 * @param port NXT sensor port 1-4
	 */
	public EOPD (ADSensorPort port){
		this.port = port;
		port.setTypeAndMode(TYPE_LIGHT_INACTIVE, MODE_PCTFULLSCALE);
	}

	/**
	 *
	 * @param port NXT sensor port 1-4.
	 * @param longRange true = long range false = short range.
	 */
	public EOPD(ADSensorPort port, boolean longRange)
	{
		this.port = port;
		port.setTypeAndMode((longRange ? TYPE_LIGHT_ACTIVE : TYPE_LIGHT_INACTIVE),
			MODE_PCTFULLSCALE);
	}

	/**
	 * Changes the sensor to short range mode.
	 *
	 */
	public void setModeShort(){
		port.setTypeAndMode(TYPE_LIGHT_INACTIVE, MODE_PCTFULLSCALE);
	}

	/**
	 * Changes the port to long range mode.
	 *
	 */
	public void setModeLong(){
		port.setTypeAndMode(TYPE_LIGHT_ACTIVE, MODE_PCTFULLSCALE);
	}

	/**
	 * @return The raw value is returned.
	 *
	 */
	public int readRawValue() {
		return port.readRawValue();
	}

	/**
	 *
	 * @return A value between 0 and 100. This mimics the HiTechnic
	 *  programming block.
	 */
	public int processedValue()
	{
		return (int)Math.sqrt((1023-port.readRawValue())*10);
	}
}


text:
require "philippines/version"
require "yaml"

module Philippines

  REGION_DATA = YAML.load_file(File.join(File.dirname(__FILE__),"philippines", "data", "regions_provinces.yml"))

  REGIONS = REGION_DATA.keys

  PROVINCE_DATA = YAML.load_file(File.join(File.dirname(__FILE__),"philippines", "data", "provinces_municipalities.yml"))

  PROVINCES = PROVINCE_DATA.keys.sort

  CITIES = PROVINCE_DATA.map { |_, v| v["cities"] }.flatten.compact.sort
  MUNICIPALITIES = PROVINCE_DATA.map { |_, v| v["municipalities"] }.flatten.compact.sort
  MUNICIPALITIES_WITH_PROVINCE = PROVINCE_DATA.map do |province, v|
    v["municipalities"].map { |m| "#{m}, #{province}"}
  end.flatten.sort

end


text:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <title>absolute? (RIO::IF::Test)</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  <link rel="stylesheet" href="../../../.././rdoc-style.css" type="text/css" media="screen" />

     # File lib/rio/if/test.rb, line 256
256:       def absolute?() target.absolute?()  end