/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2017, 2018 New Vector Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig';
import dis from '../../../dispatcher/dispatcher';
import {isValid3pidInvite} from "../../../RoomInvite";
import rate_limited_func from "../../../ratelimitedfunc";
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import * as sdk from "../../../index";
import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore";
import BaseCard from "../right_panel/BaseCard";
import {RightPanelPhases} from "../../../stores/RightPanelStorePhases";

const INITIAL_LOAD_NUM_MEMBERS = 30;
const INITIAL_LOAD_NUM_INVITED = 5;
const SHOW_MORE_INCREMENT = 100;

// Regex applied to filter our punctuation in member names before applying sort, to fuzzy it a little
// matches all ASCII punctuation: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
const SORT_REGEX = /[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+/g;

export default class MemberList extends React.Component {
    constructor(props) {
        super(props);

        const cli = MatrixClientPeg.get();
        if (cli.hasLazyLoadMembersEnabled()) {
            // show an empty list
            this.state = this._getMembersState([]);
        } else {
            this.state = this._getMembersState(this.roomMembers());
        }

        cli.on("Room", this.onRoom); // invites & joining after peek
        const enablePresenceByHsUrl = SdkConfig.get()["enable_presence_by_hs_url"];
        const hsUrl = MatrixClientPeg.get().baseUrl;
        this._showPresence = true;
        if (enablePresenceByHsUrl && enablePresenceByHsUrl[hsUrl] !== undefined) {
            this._showPresence = enablePresenceByHsUrl[hsUrl];
        }
    }

    // eslint-disable-next-line camelcase
    UNSAFE_componentWillMount() {
        const cli = MatrixClientPeg.get();
        this._mounted = true;
        if (cli.hasLazyLoadMembersEnabled()) {
            this._showMembersAccordingToMembershipWithLL();
            cli.on("Room.myMembership", this.onMyMembership);
        } else {
            this._listenForMembersChanges();
        }
    }

    _listenForMembersChanges() {
        const cli = MatrixClientPeg.get();
        cli.on("RoomState.members", this.onRoomStateMember);
        cli.on("RoomMember.name", this.onRoomMemberName);
        cli.on("RoomState.events", this.onRoomStateEvent);
        // We listen for changes to the lastPresenceTs which is essentially
        // listening for all presence events (we display most of not all of
        // the information contained in presence events).
        cli.on("User.lastPresenceTs", this.onUserPresenceChange);
        cli.on("User.presence", this.onUserPresenceChange);
        cli.on("User.currentlyActive", this.onUserPresenceChange);
        // cli.on("Room.timeline", this.onRoomTimeline);
    }

    componentWillUnmount() {
        this._mounted = false;
        const cli = MatrixClientPeg.get();
        if (cli) {
            cli.removeListener("RoomState.members", this.onRoomStateMember);
            cli.removeListener("RoomMember.name", this.onRoomMemberName);
            cli.removeListener("Room.myMembership", this.onMyMembership);
            cli.removeListener("RoomState.events", this.onRoomStateEvent);
            cli.removeListener("Room", this.onRoom);
            cli.removeListener("User.lastPresenceTs", this.onUserPresenceChange);
            cli.removeListener("User.presence", this.onUserPresenceChange);
            cli.removeListener("User.currentlyActive", this.onUserPresenceChange);
        }

        // cancel any pending calls to the rate_limited_funcs
        this._updateList.cancelPendingCall();
    }

    /**
     * If lazy loading is enabled, either:
     * show a spinner and load the members if the user is joined,
     * or show the members available so far if the user is invited
     */
    async _showMembersAccordingToMembershipWithLL() {
        const cli = MatrixClientPeg.get();
        if (cli.hasLazyLoadMembersEnabled()) {
            const cli = MatrixClientPeg.get();
            const room = cli.getRoom(this.props.roomId);
            const membership = room && room.getMyMembership();
            if (membership === "join") {
                this.setState({loading: true});
                try {
                    await room.loadMembersIfNeeded();
                } catch (ex) {/* already logged in RoomView */}
                if (this._mounted) {
                    this.setState(this._getMembersState(this.roomMembers()));
                    this._listenForMembersChanges();
                }
            } else if (membership === "invite") {
                // show the members we've got when invited
                this.setState(this._getMembersState(this.roomMembers()));
            }
        }
    }

    _getMembersState(members) {
        // set the state after determining _showPresence to make sure it's
        // taken into account while rerendering
        return {
            loading: false,
            members: members,
            filteredJoinedMembers: this._filterMembers(members, 'join'),
            filteredInvitedMembers: this._filterMembers(members, 'invite'),

            // ideally we'd size this to the page height, but
            // in practice I find that a little constraining
            truncateAtJoined: INITIAL_LOAD_NUM_MEMBERS,
            truncateAtInvited: INITIAL_LOAD_NUM_INVITED,
            searchQuery: "",
        };
    }

    onUserPresenceChange = (event, user) => {
        // Attach a SINGLE listener for global presence changes then locate the
        // member tile and re-render it. This is more efficient than every tile
        // ever attaching their own listener.
        const tile = this.refs[user.userId];
        // console.log(`Got presence update for ${user.userId}. hasTile=${!!tile}`);
        if (tile) {
            this._updateList(); // reorder the membership list
        }
    };

    onRoom = room => {
        if (room.roomId !== this.props.roomId) {
            return;
        }
        // We listen for room events because when we accept an invite
        // we need to wait till the room is fully populated with state
        // before refreshing the member list else we get a stale list.
        this._showMembersAccordingToMembershipWithLL();
    };

    onMyMembership = (room, membership, oldMembership) => {
        if (room.roomId === this.props.roomId && membership === "join") {
            this._showMembersAccordingToMembershipWithLL();
        }
    };

    onRoomStateMember = (ev, state, member) => {
        if (member.roomId !== this.props.roomId) {
            return;
        }
        this._updateList();
    };

    onRoomMemberName = (ev, member) => {
        if (member.roomId !== this.props.roomId) {
            return;
        }
        this._updateList();
    };

    onRoomStateEvent = (event, state) => {
        if (event.getRoomId() === this.props.roomId &&
            event.getType() === "m.room.third_party_invite") {
            this._updateList();
        }
    };

    _updateList = rate_limited_func(() => {
        this._updateListNow();
    }, 500);

    _updateListNow() {
        // console.log("Updating memberlist");
        const newState = {
            loading: false,
            members: this.roomMembers(),
        };
        newState.filteredJoinedMembers = this._filterMembers(newState.members, 'join', this.state.searchQuery);
        newState.filteredInvitedMembers = this._filterMembers(newState.members, 'invite', this.state.searchQuery);
        this.setState(newState);
    }

    getMembersWithUser() {
        if (!this.props.roomId) return [];
        const cli = MatrixClientPeg.get();
        const room = cli.getRoom(this.props.roomId);
        if (!room) return [];

        const allMembers = Object.values(room.currentState.members);

        allMembers.forEach(function(member) {
            // work around a race where you might have a room member object
            // before the user object exists.  This may or may not cause
            // https://github.com/vector-im/vector-web/issues/186
            if (member.user === null) {
                member.user = cli.getUser(member.userId);
            }

            // XXX: this user may have no lastPresenceTs value!
            // the right solution here is to fix the race rather than leave it as 0
        });

        return allMembers;
    }

    roomMembers() {
        const allMembers = this.getMembersWithUser();
        const filteredAndSortedMembers = allMembers.filter((m) => {
            return (
                m.membership === 'join' || m.membership === 'invite'
            );
        });
        filteredAndSortedMembers.sort(this.memberSort);
        return filteredAndSortedMembers;
    }

    _createOverflowTileJoined = (overflowCount, totalCount) => {
        return this._createOverflowTile(overflowCount, totalCount, this._showMoreJoinedMemberList);
    };

    _createOverflowTileInvited = (overflowCount, totalCount) => {
        return this._createOverflowTile(overflowCount, totalCount, this._showMoreInvitedMemberList);
    };

    _createOverflowTile = (overflowCount, totalCount, onClick) => {
        // For now we'll pretend this is any entity. It should probably be a separate tile.
        const EntityTile = sdk.getComponent("rooms.EntityTile");
        const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
        const text = _t("and %(count)s others...", { count: overflowCount });
        return (
            <EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
                <BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
            } name={text} presenceState="online" suppressOnHover={true}
            onClick={onClick} />
        );
    };

    _showMoreJoinedMemberList = () => {
        this.setState({
            truncateAtJoined: this.state.truncateAtJoined + SHOW_MORE_INCREMENT,
        });
    };

    _showMoreInvitedMemberList = () => {
        this.setState({
            truncateAtInvited: this.state.truncateAtInvited + SHOW_MORE_INCREMENT,
        });
    };

    memberString(member) {
        if (!member) {
            return "(null)";
        } else {
            const u = member.user;
            return "(" + member.name + ", " + member.powerLevel + ", " + (u ? u.lastActiveAgo : "<null>") + ", " + (u ? u.getLastActiveTs() : "<null>") + ", " + (u ? u.currentlyActive : "<null>") + ", " + (u ? u.presence : "<null>") + ")";
        }
    }

    // returns negative if a comes before b,
    // returns 0 if a and b are equivalent in ordering
    // returns positive if a comes after b.
    memberSort = (memberA, memberB) => {
        // order by presence, with "active now" first.
        // ...and then by power level
        // ...and then by last active
        // ...and then alphabetically.
        // We could tiebreak instead by "last recently spoken in this room" if we wanted to.

        // console.log(`Comparing userA=${this.memberString(memberA)} userB=${this.memberString(memberB)}`);

        const userA = memberA.user;
        const userB = memberB.user;

        // if (!userA) console.log("!! MISSING USER FOR A-SIDE: " + memberA.name + " !!");
        // if (!userB) console.log("!! MISSING USER FOR B-SIDE: " + memberB.name + " !!");

        if (!userA && !userB) return 0;
        if (userA && !userB) return -1;
        if (!userA && userB) return 1;

        // First by presence
        if (this._showPresence) {
            const convertPresence = (p) => p === 'unavailable' ? 'online' : p;
            const presenceIndex = p => {
                const order = ['active', 'online', 'offline'];
                const idx = order.indexOf(convertPresence(p));
                return idx === -1 ? order.length : idx; // unknown states at the end
            };

            const idxA = presenceIndex(userA.currentlyActive ? 'active' : userA.presence);
            const idxB = presenceIndex(userB.currentlyActive ? 'active' : userB.presence);
            // console.log(`userA_presenceGroup=${idxA} userB_presenceGroup=${idxB}`);
            if (idxA !== idxB) {
                // console.log("Comparing on presence group - returning");
                return idxA - idxB;
            }
        }

        // Second by power level
        if (memberA.powerLevel !== memberB.powerLevel) {
            // console.log("Comparing on power level - returning");
            return memberB.powerLevel - memberA.powerLevel;
        }

        // Third by last active
        if (this._showPresence && userA.getLastActiveTs() !== userB.getLastActiveTs()) {
            // console.log("Comparing on last active timestamp - returning");
            return userB.getLastActiveTs() - userA.getLastActiveTs();
        }

        // Fourth by name (alphabetical)
        const nameA = (memberA.name[0] === '@' ? memberA.name.substr(1) : memberA.name).replace(SORT_REGEX, "");
        const nameB = (memberB.name[0] === '@' ? memberB.name.substr(1) : memberB.name).replace(SORT_REGEX, "");
        // console.log(`Comparing userA_name=${nameA} against userB_name=${nameB} - returning`);
        return nameA.localeCompare(nameB, {
            ignorePunctuation: true,
            sensitivity: "base",
        });
    };

    onSearchQueryChanged = searchQuery => {
        this.setState({
            searchQuery,
            filteredJoinedMembers: this._filterMembers(this.state.members, 'join', searchQuery),
            filteredInvitedMembers: this._filterMembers(this.state.members, 'invite', searchQuery),
        });
    };

    _onPending3pidInviteClick = inviteEvent => {
        dis.dispatch({
            action: 'view_3pid_invite',
            event: inviteEvent,
        });
    };

    _filterMembers(members, membership, query) {
        return members.filter((m) => {
            if (query) {
                query = query.toLowerCase();
                const matchesName = m.name.toLowerCase().indexOf(query) !== -1;
                const matchesId = m.userId.toLowerCase().indexOf(query) !== -1;

                if (!matchesName && !matchesId) {
                    return false;
                }
            }

            return m.membership === membership;
        });
    }

    _getPending3PidInvites() {
        // include 3pid invites (m.room.third_party_invite) state events.
        // The HS may have already converted these into m.room.member invites so
        // we shouldn't add them if the 3pid invite state key (token) is in the
        // member invite (content.third_party_invite.signed.token)
        const room = MatrixClientPeg.get().getRoom(this.props.roomId);

        if (room) {
            return room.currentState.getStateEvents("m.room.third_party_invite").filter(function(e) {
                if (!isValid3pidInvite(e)) return false;

                // discard all invites which have a m.room.member event since we've
                // already added them.
                const memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey());
                if (memberEvent) return false;
                return true;
            });
        }
    }

    _makeMemberTiles(members) {
        const MemberTile = sdk.getComponent("rooms.MemberTile");
        const EntityTile = sdk.getComponent("rooms.EntityTile");

        return members.map((m) => {
            if (m.userId) {
                // Is a Matrix invite
                return <MemberTile key={m.userId} member={m} ref={m.userId} showPresence={this._showPresence} />;
            } else {
                // Is a 3pid invite
                return <EntityTile key={m.getStateKey()} name={m.getContent().display_name} suppressOnHover={true}
                                   onClick={() => this._onPending3pidInviteClick(m)} />;
            }
        });
    }

    _getChildrenJoined = (start, end) => this._makeMemberTiles(this.state.filteredJoinedMembers.slice(start, end));

    _getChildCountJoined = () => this.state.filteredJoinedMembers.length;

    _getChildrenInvited = (start, end) => {
        let targets = this.state.filteredInvitedMembers;
        if (end > this.state.filteredInvitedMembers.length) {
            targets = targets.concat(this._getPending3PidInvites());
        }

        return this._makeMemberTiles(targets.slice(start, end));
    };

    _getChildCountInvited = () => {
        return this.state.filteredInvitedMembers.length + (this._getPending3PidInvites() || []).length;
    }

    render() {
        if (this.state.loading) {
            const Spinner = sdk.getComponent("elements.Spinner");
            return <BaseCard
                className="mx_MemberList"
                onClose={this.props.onClose}
                previousPhase={RightPanelPhases.RoomSummary}
            >
                <Spinner />
            </BaseCard>;
        }

        const SearchBox = sdk.getComponent('structures.SearchBox');
        const TruncatedList = sdk.getComponent("elements.TruncatedList");

        const cli = MatrixClientPeg.get();
        const room = cli.getRoom(this.props.roomId);
        let inviteButton;

        if (room && room.getMyMembership() === 'join') {
            // assume we can invite until proven false
            let canInvite = true;

            const plEvent = room.currentState.getStateEvents("m.room.power_levels", "");
            const me = room.getMember(cli.getUserId());
            if (plEvent && me) {
                const content = plEvent.getContent();
                if (content && content.invite > me.powerLevel) {
                    canInvite = false;
                }
            }

            let inviteButtonText = _t("Invite to this room");
            const chat = CommunityPrototypeStore.instance.getSelectedCommunityGeneralChat();
            if (chat && chat.roomId === this.props.roomId) {
                inviteButtonText = _t("Invite to this community");
            }

            const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
            inviteButton =
                <AccessibleButton className="mx_MemberList_invite" onClick={this.onInviteButtonClick} disabled={!canInvite}>
                    { inviteButtonText }
                </AccessibleButton>;
        }

        let invitedHeader;
        let invitedSection;
        if (this._getChildCountInvited() > 0) {
            invitedHeader =
{ _t("Invited") }
;
            invitedSection = <TruncatedList className="mx_MemberList_section mx_MemberList_invited" truncateAt={this.state.truncateAtInvited}
                        createOverflowElement={this._createOverflowTileInvited}
                        getChildren={this._getChildrenInvited}
                        getChildCount={this._getChildCountInvited}
                />;
        }

        const footer = (
            <SearchBox
                className="mx_MemberList_query mx_textinput_icon mx_textinput_search"
                placeholder={ _t('Filter room members') }
                onSearch={ this.onSearchQueryChanged } />
        );

        return <BaseCard
            className="mx_MemberList"
            header={inviteButton}
            footer={footer}
            onClose={this.props.onClose}
            previousPhase={RightPanelPhases.RoomSummary}
        >

                <TruncatedList className="mx_MemberList_section mx_MemberList_joined" truncateAt={this.state.truncateAtJoined}
                               createOverflowElement={this._createOverflowTileJoined}
                               getChildren={this._getChildrenJoined}
                               getChildCount={this._getChildCountJoined} />
                { invitedHeader }
                { invitedSection }

        </BaseCard>;
    }

    onInviteButtonClick = () => {
        if (MatrixClientPeg.get().isGuest()) {
            dis.dispatch({action: 'require_registration'});
            return;
        }

        // call AddressPickerDialog
        dis.dispatch({
            action: 'view_invite',
            roomId: this.props.roomId,
        });
    };
}


/**
 * @name exports
 * @summary AuditEventObjectDetail Class
 */
module.exports = class AuditEventObjectDetail {
  constructor(opts) {
    // Create an object to store all props
    Object.defineProperty(this, '__data', { value: {} });

    // Define getters and setters as enumerable

    Object.defineProperty(this, '_id', {
      enumerable: true,
      get: () => this.__data._id,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        let Element = require('./element.js');
        this.__data._id = new Element(value);
      },
    });

    Object.defineProperty(this, 'id', {
      enumerable: true,
      get: () => this.__data.id,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        this.__data.id = value;
      },
    });

    Object.defineProperty(this, 'extension', {
      enumerable: true,
      get: () => this.__data.extension,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        let Extension = require('./extension.js');
        this.__data.extension = Array.isArray(value)
          ? value.map((v) => new Extension(v))
          : [new Extension(value)];
      },
    });

    Object.defineProperty(this, 'modifierExtension', {
      enumerable: true,
      get: () => this.__data.modifierExtension,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        let Extension = require('./extension.js');
        this.__data.modifierExtension = Array.isArray(value)
          ? value.map((v) => new Extension(v))
          : [new Extension(value)];
      },
    });

    Object.defineProperty(this, '_type', {
      enumerable: true,
      get: () => this.__data._type,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        let Element = require('./element.js');
        this.__data._type = new Element(value);
      },
    });

    Object.defineProperty(this, 'type', {
      enumerable: true,
      get: () => this.__data.type,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        this.__data.type = value;
      },
    });

    Object.defineProperty(this, '_value', {
      enumerable: true,
      get: () => this.__data._value,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        let Element = require('./element.js');
        this.__data._value = new Element(value);
      },
    });

    Object.defineProperty(this, 'value', {
      enumerable: true,
      get: () => this.__data.value,
      set: (value) => {
        if (value === undefined || value === null) {
          return;
        }

        this.__data.value = value;
      },
    });

    // Merge in any defaults
    Object.assign(this, opts);

    // Define a default non-writable resourceType property
    Object.defineProperty(this, 'resourceType', {
      value: 'AuditEventObjectDetail',
      enumerable: true,
      writable: false,
    });
  }

  static get resourceType() {
    return 'AuditEventObjectDetail';
  }

  toJSON() {
    return {
      id: this.id,
      extension: this.extension && this.extension.map((v) => v.toJSON()),
      modifierExtension: this.modifierExtension && this.modifierExtension.map((v) => v.toJSON()),
      _type: this._type && this._type.toJSON(),
      type: this.type,
      _value: this._value && this._value.toJSON(),
      value: this.value,
    };
  }
};


<?php

namespace Topxia\Api\Resource;

use Silex\Application;
use AppBundle\Common\ArrayToolkit;
use Topxia\Service\Common\ServiceKernel;
use Symfony\Component\HttpFoundation\Request;

class Status extends BaseResource
{
    public function get(Application $app, Request $request, $courseId)
    {
        try {
            list($course, $member) = $this->getCourseService()->tryTakeCourse($courseId);
        } catch (\Exception $e) {
            return $this->error(404, "用户尚未登录或不是课程学员");
        }

        $start = $request->query->get('start', 0);
        $limit = $request->query->get('limit', 10);

        $statuses = $this->getStatusService()->searchStatuses(
            array('userId' => $member['userId'], 'courseId' => $courseId),
            array('createdTime' => 'DESC'),
            $start,
            $limit
        );

        return $this->_filterStatus($statuses);
    }

    public function filter($res)
    {
        $res = ArrayToolkit::parts($res, array('id', 'userId', 'courseId', 'classroomId', 'type', 'objectType', 'objectId', 'properties', 'createdTime'));

        return $res;
    }

    private function _filterStatus(&$res)
    {
        foreach ($res as $key => &$item) {
            unset($item['private']);
            unset($item['commentNum']);
            unset($item['likeNum']);
        }

        return $res;
    }

    protected function getStatusService()
    {
        return ServiceKernel::instance()->createService('User:StatusService');
    }

    protected function getUserService()
    {
        return ServiceKernel::instance()->createService('User:UserService');
    }

    protected function getCourseService()
    {
        return $this->getServiceKernel()->createService('Course:CourseService');
    }
}


<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (C) 2018 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
   -->

<resources xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"Corte largo"</string>
</resources>


/*
 * Copyright © 2019 Cask Data, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package io.cdap.cdap.metadata.elastic;

import io.cdap.cdap.api.data.schema.Schema;
import io.cdap.cdap.api.metadata.MetadataEntity;
import org.junit.Assert;
import org.junit.Test;

public class MetadataDocumentTest {

  @Test
  public void testSchema() {
    Schema bytesArraySchema = Schema.arrayOf(Schema.of(Schema.Type.BYTES));
    Schema stringArraySchema = Schema.arrayOf(Schema.of(Schema.Type.STRING));
    Schema booleanBytesMapSchema = Schema.mapOf(Schema.of(Schema.Type.BOOLEAN), Schema.of(Schema.Type.BYTES));
    Schema nestedMapSchema = Schema.mapOf(bytesArraySchema, booleanBytesMapSchema);
    Schema record22Schema = Schema.recordOf("record22", Schema.Field.of("a", nestedMapSchema));
    Schema record22ArraySchema = Schema.arrayOf(record22Schema);
    Schema bytesDoubleMapSchema = Schema.mapOf(Schema.of(Schema.Type.BYTES), Schema.of(Schema.Type.DOUBLE));
    Schema record21Schema = Schema.recordOf("record21",
                                            Schema.Field.of("x", Schema.of(Schema.Type.STRING)),
                                            Schema.Field.of("y", stringArraySchema),
                                            Schema.Field.of("z", bytesDoubleMapSchema));
    Schema record21to22MapSchema = Schema.mapOf(record21Schema, record22ArraySchema);
    Schema nullableIntSchema = Schema.nullableOf(Schema.of(Schema.Type.INT));
    Schema tripeUnionSchema = Schema.unionOf(Schema.of(Schema.Type.INT), Schema.of(Schema.Type.LONG),
                                             Schema.of(Schema.Type.NULL));
    Schema complexSchema = Schema.recordOf("record1",
                                           Schema.Field.of("map1", record21to22MapSchema),
                                           Schema.Field.of("i", nullableIntSchema),
                                           Schema.Field.of("j", tripeUnionSchema));
    Schema anotherComplexSchema = Schema.arrayOf(Schema.of(Schema.Type.STRING));
    Schema superComplexSchema = Schema.unionOf(complexSchema, anotherComplexSchema, Schema.of(Schema.Type.NULL));

    String[] results = MetadataDocument.Builder.parseSchema(MetadataEntity.ofDataset("ds"),
                                                            superComplexSchema.toString()).split(" ");
    String[] expected = {
      "record1", "record1:RECORD",
      "map1", "map1:MAP",
      "record21", "record21:RECORD",
      "x", "x:STRING",
      "y", "y:ARRAY",
      "z", "z:MAP",
      "record22", "record22:RECORD",
      "a", "a:MAP",
      "i", "i:INT",
      "j", "j:UNION",
    };
    Assert.assertArrayEquals(expected, results);
  }

  @Test
  public void testInvalidSchema() {
    Schema schema = Schema.recordOf("mystruct",
                                    Schema.Field.of("x", Schema.of(Schema.Type.STRING)),
                                    Schema.Field.of("y", Schema.of(Schema.Type.INT)),
                                    Schema.Field.of("z", Schema.of(Schema.Type.DOUBLE)));
    String schemaString = schema.toString();
    MetadataEntity entity = MetadataEntity.ofDataset("ds");
    String[] results = MetadataDocument.Builder.parseSchema(entity, schemaString).split(" ");
    String[] expected = {"mystruct", "mystruct:RECORD", "x", "x:STRING", "y", "y:INT", "z", "z:DOUBLE"};
    Assert.assertArrayEquals(expected, results);

    String schemaWithInvalidTypes = schemaString.replace("string", "nosuchtype");
    Assert.assertEquals(schemaWithInvalidTypes, MetadataDocument.Builder.parseSchema(entity, schemaWithInvalidTypes));

    String truncatedSchema = schemaString.substring(10, schemaString.length() - 10);
    Assert.assertEquals(truncatedSchema, MetadataDocument.Builder.parseSchema(entity, truncatedSchema));
  }
}


This is a brain teaser kind of problem.

Observation #1, whether #N light stays on depends on how many unique factors N have. Prime numbers must be off, because it is switched on Round 1 and off in Round N.

Observation #2, for a light #N to stays on, N needs to have odd number of factors. Fact: only square numbers can have odd number of unique factors.

Proof by contradiction: If a number has odd number of unique factors, and is not a square number, write down all its unique factors, and start crossing off the factors: If I*J=N, cross off J as well as I. In the end, there is only one factor M left, M*M has to be N.


<?php declare(strict_types=1);

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

/**
 * @property Name $namespacedName Namespaced name (for class constants, if using NameResolver)
 */
class Const_ extends NodeAbstract
{
    /** @var Identifier Name */
    public $name;
    /** @var Expr Value */
    public $value;

    /**
     * Constructs a const node for use in class const and const statements.
     *
     * @param string|Identifier $name       Name
     * @param Expr              $value      Value
     * @param array             $attributes Additional attributes
     */
    public function __construct($name, Expr $value, array $attributes = []) {
        parent::__construct($attributes);
        $this->name = \is_string($name) ? new Identifier($name) : $name;
        $this->value = $value;
    }

    public function getSubNodeNames() : array {
        return ['name', 'value'];
    }

    public function getType() : string {
        return 'Const';
    }
}


<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.com-->
<resources>
    <string name="appearance">Görünüm</string>
    <string name="appearance_desc">Tema, Gösterilecek öğe, vb</string>
    <string name="notifications_desc">Frekans, filtreler, zilsesi, vb</string>
    <string name="newsfeed">Haber akışı</string>
    <string name="newsfeed_desc">Haberleşme kısmında hangi öğelerin görüneceğini belirle</string>
    <string name="behaviour">Davranış</string>
    <string name="behaviour_desc">Uygulamanın belirli ayarlarla nasıl etkilesime girdiğini tanımlayın</string>
    <string name="network">Ağ</string>
    <string name="network_desc">Ölcülen ağları etkiliyen secenekleri tanımlayın</string>
    <string name="experimental">Deneysel</string>
    <string name="experimental_desc">Potansiyel olarak kararsız özelliklere erken erişim sağlamayı etkin kıl</string>
    <string name="about_frost">Frost Hakkında Facebook için</string>
    <string name="about_frost_desc">Versiyon, Crediler, ve SSS</string>
    <string name="help_translate">Çeviri Yardımı</string>
    <string name="help_translate_desc">Frost kalabalıklar içindedir. İsterseniz kendi dilinizde katkı sağlayın!</string>
    <string name="debug_frost">Frost Hata ayıklayıcı</string>
    <string name="debug_frost_desc">Yardımcı olmak için hataları gönderebilirsiniz.</string>
    <string name="replay_intro">Kural tekrarı</string>
</resources>


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

export class UIHandler {
  init() {
    browser.commands.onCommand.addListener(this.onKeyCommand.bind(this));
    browser.convContacts.onColumnHandler.addListener(
      () => {},
      browser.i18n.getMessage("between.columnName"),
      browser.i18n.getMessage("between.columnTooltip"),
      browser.i18n.getMessage("message.meBetweenMeAndSomeone"),
      browser.i18n.getMessage("message.meBetweenSomeoneAndMe"),
      browser.i18n.getMessage("header.commaSeparator"),
      browser.i18n.getMessage("header.andSeparator")
    );
  }

  onKeyCommand(command) {
    if (command == "quick_compose") {
      console.warn("Quick Compose is currently disabled");
      // The title/description for this pref is really confusing, we should
      // reconsider it when we re-enable.
      // if (Prefs.compose_in_tab) {
      //   window.openTab("chromeTab", {
      //     chromePage:
      //       "chrome://conversations/content/stub.xhtml?quickCompose=1",
      //   });
      // } else {
      //   window.open(
      //     "chrome://conversations/content/stub.xhtml?quickCompose=1",
      //     "",
      //     "chrome,width=1020,height=600"
      //   );
      // }
    }
  }
}


codeinsight.settings=CodeInsight settings
error.hint.file.is.readonly=File {0} is read-only
error.dialog.readonly.file.title=File Is Read-Only
error.dialog.readonly.files.title=Cannot Modify Read-Only Files
error.dialog.readonly.files.message={0} contains read-only file(s).\nProcess all other (writeable) files?
process.scope.directory=Directory ''{0}''
process.scope.project=Project ''{0}''
process.scope.module=Module ''{0}''
reformat.code.accept.button.text=Run
process.scope.changed.files=process only VCS changed files
process.scope.file=&File {0}
reformat.option.selected.text=&Selected text
reformat.option.all.files.in.directory=&All files in directory {0}
reformat.option.include.subdirectories=&Include subdirectories
reformat.option.optimize.imports=&Optimize imports
reformat.option.rearrange.entries=&Rearrange entries
reformat.option.vcs.changed.region=Only &VCS changed text
reformat.progress.file.with.known.name.text=Reformatting {0}
reformat.and.optimize.progress.common.text=Preparing imports...
reformat.progress.common.text=Reformatting code...
process.optimize.imports=Optimize Imports
process.optimize.imports.before.commit=Optimize Imports Before Commit
progress.text.optimizing.imports=Optimizing imports...
progress.reformat.and.optimize.common.command.text=Reformat and Optimize Imports
progress.reformat.stage.wrapping.blocks=Preparing...
progress.reformat.stage.processing.blocks=Calculating changes...
progress.reformat.stage.applying.changes=Storing changes...
process.reformat.code=Reformat Code
process.reformat.code.before.commit=Reformat Code Before Commit
dialog.reformat.files.title=Reformat Files
dialog.reformat.files.optimize.imports.checkbox=&Optimize imports
dialog.reformat.files.reformat.selected.files.label=Reformat selected files?
command.name.typing=Typing
dialog.import.on.paste.title=Select Classes to Import
dialog.import.on.paste.title2=Select Elements to Import
dialog.paste.on.import.text=The code fragment which you have pasted uses classes that are not accessible by imports in the new context.
Select classes that you want to import to the new file.
dialog.paste.on.import.text2=The code fragment which you have pasted uses elements that are not accessible by imports in the new context.
Select elements that you want to import to the new file.
paste.data.flavor.folding=FoldingData
paste.dataflavor.referencedata=ReferenceData
generate.constructor.fields.chooser.title=Choose Fields to Initialize by Constructor
error.attempt.to.generate.constructor.for.anonymous.class=Cannot add constructor to an anonymous class
generate.constructor.super.constructor.chooser.title=Choose Super Class Constructor
generate.delegate.method.chooser.title=Select Methods to Generate Delegates for
generate.delegate.target.chooser.title=Select Target to Generate Delegates for
generate.equals.and.hashcode.already.defined.warning=Methods ''boolean equals(Object)'' and ''int hashCode()'' are already defined\nfor class {0}. Do you want to delete them and proceed?
generate.equals.and.hashcode.already.defined.warning.anonymous=Methods 'boolean equals(Object)' and 'int hashCode()' are already defined\nfor this anonymous class. Do you want to delete them and proceed?
generate.equals.and.hashcode.already.defined.title=Generate equals() and hashCode()
generate.equals.and.hashcode.error.no.object.class.message=Cannot generate equals() and hashCode().\nNo java.lang.Object class found.
generate.equals.and.hashcode.error.no.object.class.title=No java.lang.Object
generate.equals.compare.nested.arrays.comment= // Compare nested arrays - values of {0} here
generate.equals.compare.arrays.comment= // Probably incorrect - comparing Object[] arrays with Arrays.equals
generate.getter.setter.title=Select Fields to Generate Getters and Setters
generate.getter.fields.chooser.title=Select Fields to Generate Getters
generate.setter.fields.chooser.title=Select Fields to Generate Setters
override.implement.broken.file.template.message=Please Correct "Overridden/Implemented Method Body" Template
override.implement.broken.file.template.title=File Template Error
methods.to.implement.chooser.title=Select Methods to Implement
methods.to.override.chooser.title=Select Methods to Override
methods.to.override.implement.chooser.title=Select Methods to Override/Implement
generate.list.popup.title=Generate
surround.with.cast.template=((Type)expr)
surround.with.dowhile.template=do / while
surround.with.for.template=for
surround.with.ifelse.expression.template=if (expr) {...} else {...}
surround.with.ifelse.template=if / else
surround.with.if.expression.template=if (expr) {...}
surround.with.if.template=if
surround.with.not.instanceof.template=!(expr instanceof Type)
surround.with.not.template=!(expr)
surround.with.parenthesis.template=(expr)
surround.with.runnable.template=Runnable
surround.with.synchronized.template=synchronized
surround.with.try.catch.finally.template=try / catch / finally
surround.with.try.catch.template=try / catch
surround.with.try.catch.incorrect.template.message=Invalid File Template for Catch Body!
surround.with.try.catch.incorrect.template.title=Surround With Try / Catch
surround.with.try.finally.template=try / finally
surround.with.while.template=while
surround.with.runtime.type.template=((RuntimeType)expr)
surround.with.chooser.title=Surround With
unwrap.popup.title=Choose the statement to unwrap/remove
unwrap.if=Unwrap 'if...'
unwrap.else=Unwrap 'else...'
remove.else=Remove 'else...'
unwrap.while=Unwrap 'while...'
unwrap.for=Unwrap 'for...'
unwrap.braces=Unwrap braces
unwrap.try=Unwrap 'try...'
unwrap.conditional=Unwrap 'f ? a : b'
remove.catch=Remove 'catch...'
unwrap.synchronized=Unwrap 'synchronized...'
unwrap.with.placeholder=Unwrap ''{0}''
unwrap.anonymous=Unwrap 'anonymous...'
generate.equals.hashcode.wizard.title=Generate equals() and hashCode()
generate.equals.hashcode.equals.fields.chooser.title=Choose &fields to be included in equals()
generate.equals.hashcode.hashcode.fields.chooser.title=Choose &fields to be included in hashCode()
generate.equals.hashcode.non.null.fields.chooser.title=Select all non-null &fields
generate.equals.hashcode.accept.sublcasses=Accept &subclasses as parameter to equals() method
generate.equals.hashcode.accept.sublcasses.explanation=While generally incompliant to Object.equals() specification accepting
subclasses might be necessary for generated \
method to work correctly
with frameworks, which generate Proxy subclasses like Hibernate.
generate.equals.hashcode.internal.error=Internal error
generate.equals.warning.equals.for.nested.arrays.not.supported=equals() for nested arrays is not supported
generate.equals.warning.generated.equals.could.be.incorrect=Generated equals() for Object[] can be incorrect
generate.equals.hashcode.warning.hashcode.for.arrays.is.not.supported=hashCode () for arrays is not supported
highlight.thrown.exceptions.chooser.all.entry=All listed
highlight.exceptions.thrown.chooser.title=Choose Exception Classes to Highlight
highlight.exceptions.thrown.notfound=No exceptions thrown in the method found
status.bar.exit.points.highlighted.message={0} exit {0, choice, 1#point|2#points} highlighted (press {1} again to remove the highlighting, Escape to remove all highlighting)
status.bar.highlighted.usages.message={0} {0, choice, 1#usage|2#usages} of {1} found (press {2} again to remove the highlighting, Escape to remove all highlighting)
status.bar.highlighted.usages.no.target.message={0} {0, choice, 1#usage|2#usages} found (press {2} again to remove the highlighting, Escape to remove all highlighting)
status.bar.overridden.methods.highlighted.message={0} overridden {0, choice, 1#method|2#methods} found (press {1} again to remove the highlighting, Escape to remove all highlighting)
status.bar.highlighted.usages.not.found.message=No usages of {0} found
status.bar.highlighted.usages.not.found.no.target.message=No usages found
parameter.info.no.parameters=<no parameters>
xml.tag.info.no.attributes=<no attributes>
n.of.m={0} of {1}
quick.definition.back=Back
quick.definition.forward=Forward
quick.definition.edit.source=Edit Source
quick.definition.show.source=Show Source
i18n.quickfix.property.panel.title=Property Info
i18n.quickfix.property.panel.update.all.files.in.bundle.checkbox=Update all properties files in &Resource bundle
i18n.quickfix.property.panel.properties.file.label=&Properties File:
i18n.quickfix.property.panel.property.value.label=Property &Value:
i18n.quickfix.property.panel.property.key.label=Property &Key:
i18n.quickfix.code.panel.title=Java Code Info
i18n.quickfix.code.panel.resource.bundle.expression.label=Resource bundle &expression:
i18n.quickfix.preview.panel.title=Preview
quickfix.i18n.concatentation=I18nize string concatenation containing hard coded string literal
quickfix.i18n.concatentation.error=String concatenation not found
quickfix.i18n.command.name=I18nize
inspection.i18n.display.name=Hard coded strings
inspection.i18n.option.ignore.assert=Ignore for assert statement arguments
inspection.i18n.option.ignore.for.exception.constructor.arguments=Ignore for exception constructor arguments:
inspection.i18n.option.ignore.for.specified.exception.constructor.arguments=Ignore for specified exception constructor arguments
inspection.i18n.option.ignore.for.junit.assert.arguments=Ignore for JUnit assert arguments
inspection.i18n.option.ignore.qualified.class.names=Ignore literals which have value equal to existing qualified class name
inspection.i18n.option.ignore.property.keys=Ignore literals which have value equal to existing property key
inspection.i18n.option.ignore.nonalphanumerics=Ignore literals which do not contain alphabetic characters
inspection.i18n.quickfix=I18nize hard coded string literal
inspection.i18n.message.general.with.value=Hard coded string literal: {0}
inspection.unresolved.property.key.reference.name=Invalid property key
inspection.unresolved.property.key.reference.message=String literal ''{0}'' doesn''t appear to be valid property key
inspection.invalid.resource.bundle.reference=Invalid resource bundle reference ''{0}''
i18nize.dialog.title=I18nize Hardcoded String
i18nize.dialog.error.jdk.message=Class 'java.util.ResourceBundle' cannot be found.\nPlease setup correct JDK.
i18nize.dialog.error.jdk.title=Class Not Found
i18nize.dialog.property.file.chooser.title=Choose Properties File
i18nize.dialog.template.link.label=Edit I18n template
i18nize.dialog.error.property.already.defined.message=Property ''{0}'' already exists in the file ''{1}''
i18nize.dialog.error.property.already.defined.title=Property Already Exists
intention.split.declaration.family=Split Declaration
intention.split.declaration.text=Split into separate declarations
intention.split.declaration.assignment.text=Split into declaration and assignment
intention.add.override.annotation=Add '@Override' Annotation
intention.add.override.annotation.family=Add Override Annotation
intention.make.type.generic.family=Make Type Generic
intention.make.type.generic.text=Change type of {0} to {1}
intention.split.if.family=Split If
intention.split.if.text=Split into 2 if's
intention.introduce.variable.text=Introduce local variable
intention.encapsulate.field.text=Encapsulate field
intention.implement.abstract.method.family=Implement Abstract Method
intention.implement.abstract.method.text=Implement method ''{0}''
intention.override.method.text=Override method ''{0}''
intention.add.annotation.family=Add Annotation
intention.add.on.demand.static.import.family=Add On Demand Static Import
intention.add.on.demand.static.import.text=Add on demand static import for ''{0}''
intention.add.single.member.static.import.family=Add Single-Member Static Import
intention.add.single.member.static.import.text=Add static import for ''{0}''
intention.replace.concatenation.with.formatted.output.family=Replace Concatenation with Formatted Output
intention.replace.concatenation.with.formatted.output.text=Replace '+' with 'java.text.MessageFormat.format()'
intention.color.chooser.dialog=Choose Color
intention.convert.to.basic.latin=Convert to Basic Latin
intention.surround.resource.with.ARM.block=Surround with try-with-resources block
dialog.create.field.from.parameter.title=Create Field
dialog.create.field.from.parameter.already.exists.text=Use existing field ''{0}''?
dialog.create.field.from.parameter.already.exists.title=Field Already Exists
dialog.create.field.from.parameter.field.type.label=Field of type:
dialog.create.field.from.parameter.field.name.label=Name:
dialog.create.field.from.parameter.declare.final.checkbox=Declare &final
dialog.create.class.destination.package.label=Destination package:
dialog.create.class.package.chooser.title=Choose Destination Package
create.directory.command=Create directory
dialog.create.class.label=Create {0}:
dialog.create.class.name=Create {0} {1}
intention.implement.abstract.class.family=Implement Abstract Class or Interface
intention.implement.abstract.class.default.text=Implement Abstract Class
intention.implement.abstract.class.interface.text=Implement Interface
intention.implement.abstract.class.subclass.text=Create Subclass
intention.error.cannot.create.class.message=Cannot Create Class ''{0}''
intention.error.cannot.create.class.title=Failed to Create Class
intention.assign.field.from.parameter.text=Assign Parameter to Field ''{0}''
intention.assign.field.from.parameter.family=Assign Parameter to Field
intention.create.field.from.parameter.text=Create Field for Parameter ''{0}''
intention.create.field.from.parameter.family=Create Field for Parameter
intention.bind.fields.from.parameters.text=Bind {0} Parameters to Fields
intention.bind.fields.from.parameters.family=Bind Parameters to Fields
intention.implement.abstract.method.searching.for.descendants.progress=Searching For Descendants...
intention.implement.abstract.method.error.no.classes.message=There are no classes found where this method can be implemented
intention.implement.abstract.method.error.no.classes.title=No Classes Found
intention.implement.abstract.method.class.chooser.title=Choose Implementing Class
intention.implement.abstract.method.command.name=Implement method
intention.invert.if.condition=Invert If Condition
intention.extract.if.condition.text=Extract if ({0})
intention.extract.if.condition.family=Extract If Condition
intention.underscores.in.literals.family=Underscores in numeric literals
intention.remove.literal.underscores=Remove underscores from literal
intention.insert.literal.underscores=Insert underscores into literal
intention.replace.cast.with.var.text=Replace ''{0}'' with ''{1}''
intention.replace.cast.with.var.family=Replace cast with variable
intention.convert.color.representation.text=Convert to ''new Color{0}''
intention.convert.color.representation.family=Convert Color representation
intention.break.string.on.line.breaks.text=Break string on '\\n'

intention.create.test=Create Test
intention.create.test.dialog.testing.library=Testing library:
intention.create.test.dialog.language=Language:
intention.create.test.dialog.class.name=Class name:
intention.create.test.dialog.super.class=Superclass:
intention.create.test.dialog.choose.super.class=Choose Superclass
intention.create.test.dialog.generate=Generate:
intention.create.test.dialog.show.inherited=Show inherited methods
intention.create.test.dialog.select.methods=Generate test methods for:
intention.create.test.dialog.library.not.found={0} library not found in the module
intention.create.test.dialog.fix.library=Fix
intention.create.test.dialog.java=Java

lightbulb.tooltip=Click or press {0}
dialog.intention.settings.intention.list.title=Intention List
dialog.intention.settings.description.panel.title=Description
dialog.intention.settings.description.usage.example.title=Usage Example
intention.settings=Intentions
intention.settings.category.text=\
  You have selected the intention category ''{0}''.\
  By clicking the checkbox, you can enable/disable all intentions in this category.\
  To enable/disable a particular intention, select the intention inside this category.\

javadoc.description.copied.from.interface=Description copied from interface:
javadoc.description.copied.from.class=Description copied from class:
javadoc.deprecated=Deprecated
javadoc.since=Since:
javadoc.see.also=See Also:
javadoc.parameters=Parameters:
javadoc.returns=Returns:
javadoc.throws=Throws:
javadoc.method.in.interface={0} in interface {1}
javadoc.method.in.class={0} in class {1}
javadoc.method.overrides=Overrides:
javadoc.method.specified.by=Specified by:
javadoc.external.fetch.error.message=Cannot fetch remote documentation: {0}
searching.for.implementations=Searching For Implementations...

goto.implementation.chooserTitle=Choose Implementation of {0} ({1} found)
goto.implementation.findUsages.title=Implementations of {0}
goto.implementation.notFound=No implementations found

goto.test.chooserTitle.test=Choose Test for {0} ({1} found)
goto.test.findUsages.test.title=Tests for {0}
goto.test.chooserTitle.subject=Choose Test Subject for {0} ({1} found)
goto.test.findUsages.subject.title=Test Subjects for {0}
goto.test.notFound=No test subjects found

incremental.search.tooltip.prefix=Search for:
goto.super.method.chooser.title=Choose super method
goto.super.method.findUsages.title=Super methods of {0}
goto.super.class.chooser.title=Choose super class or interface
javadoc.action.back=Back
javadoc.action.forward=Forward
javadoc.action.view.external=View External Documentation
javadoc.documentation.not.found.message=The documentation for this element is not found.\nPlease add all the needed paths to API docs in Project Settings.
javadoc.documentation.not.found.title=No Documentation
javadoc.fetching.progress=Fetching Documentation...
no.documentation.found=No documentation found.
javadoc.candiates=Candidates for method call {0} are:

{1}
javadoc.candidates.not.found=No candidates found for method call {0}.
declaration.navigation.title=Choose Declaration
template.shortcut.enter=Enter
template.shortcut.tab=Tab
template.shortcut.space=Space
dialog.edit.live.template.title=Edit Live Template
dialog.add.live.template.title=Add Live Template
templates.no.defined=No templates defined in this context
templates.surround.no.defined=No surround templates defined in this context
templates.no.defined.with.prefix=No templates starting with ''{0}'' defined in this context
templates.settings.page.title=Live Templates
templates.select.template.chooser.title=Select Template
templates.export.display.name=Live templates
templates.dialog.edit.variables.title=Edit Template Variables
templates.dialog.edit.variables.border.title=Variables
templates.dialog.edit.variables.action.move.up=Move &Up
templates.dialog.edit.variables.action.move.down=Move &Down
templates.dialog.edit.variables.table.column.name=Name
templates.dialog.edit.variables.table.column.expression=Expression
templates.dialog.edit.variables.table.column.default.value=Default value
templates.dialog.edit.variables.table.column.skip.if.defined=Skip if defined
templates.dialog.table.column.abbreviation=Abbreviation
templates.dialog.table.column.description=Description
templates.dialog.table.column.active=Active
templates.dialog.shortcut.chooser.label=By default expand with
dialog.copy.live.template.title=Copy Live Template
dialog.edit.template.shortcut.default=Default ({0})
dialog.edit.template.template.text.title=&Template text:
dialog.edit.template.button.edit.variables=&Edit variables
dialog.edit.template.label.abbreviation=&Abbreviation:
dialog.edit.template.label.group=&Group:
dialog.edit.template.label.description=&Description:
dialog.edit.template.options.title=Options
dialog.edit.template.label.expand.with=E&xpand with
dialog.edit.template.checkbox.reformat.according.to.style=&Reformat according to style
dialog.edit.template.checkbox.shorten.fq.names=Shorten &FQ names
dialog.edit.template.checkbox.use.static.import=Use static &import if possible
dialog.edit.template.context.title=Context
dialog.edit.template.checkbox.html=&HTML
dialog.edit.template.checkbox.xml=&XML
dialog.edit.template.checkbox.jsp=JS&P
dialog.edit.template.checkbox.smart.type.completion=Smart type c&ompletion
dialog.edit.template.error.title=Cannot Save
dialog.edit.template.error.malformed.abbreviation=Cannot save the template.\nTemplate abbreviation should contain only letters, digits, dots and hyphens.
dialog.edit.template.error.already.exists=Cannot save the template.\nTemplate with the abbreviation \"{0}\"\nalready exists in group \"{1}\".\nPlease choose a different abbreviation or group.
finish.template.command=Finish Template
insert.code.template.command=Insert Code Template
template.next.variable.command=Go to Next Code Template Tab
template.previous.variable.command=Go to Previous Code Template Tab
macro.array.variable=arrayVariable()
macro.capitalize.string=capitalize(String)
macro.cast.to.left.side.type=castToLeftSideType()
macro.classname=className()
macro.component.type.of.array=componentTypeOf(Array)
macro.current.package=currentPackage()
macro.decapitalize.string=decapitalize(String)
macro.firstWord.string=firstWord(String)
macro.undescoresToSpaces.string=underscoresToSpaces(String)
macro.undescoresToCamelCase.string=underscoresToCamelCase(String)
macro.capitalizeAndUnderscore.string=capitalizeAndUnderscore(String)
macro.descendant.classes.enum=descendantClassesEnum(String)
macro.enum=enum(...)
macro.expected.type=expectedType()
macro.groovy.script=groovyScript("groovy code")
macro.guess.element.type.of.container=guessElementType(Container)
macro.iterable.component.type=iterableComponentType(ArrayOrIterable)
macro.iterable.variable=iterableVariable()
macro.linenumber=lineNumber()
macro.methodname=methodName()
macro.method.parameters=methodParameters()
macro.qualified.class.name=qualifiedClassName()
macro.right.side.type=rightSideType()
macro.suggest.index.name=suggestIndexName()
macro.suggest.variable.name=suggestVariableName()
macro.suggest.first.variable.name=suggestFirstVariableName()
macro.variable.of.type=variableOfType(Type)
macro.file.name=fileName()
macro.file.name.without.extension=fileNameWithoutExtension()
command.name.surround.with.runtime.cast=Surround with runtime cast
inspection.i18n.expression.is.invalid.error.message=The I18nized Expression template is not a valid expression
inspection.error.dialog.title=Error
livetemplate.description.tag.pair=Tag pair
livetemplate.description.itar=Iterate elements of array
livetemplate.description.itco=Iterate elements of java.util.Collection
livetemplate.description.iten=Iterate java.util.Enumeration
livetemplate.description.itit=Iterate java.util.Iterator
livetemplate.description.itli=Iterate elements of java.util.List
livetemplate.description.ittok=Iterate tokens from String
livetemplate.description.itve=Iterate elements of java.util.Vector
livetemplate.description.ritar=Iterate elements of array in reverse order
livetemplate.description.iter=Iterate Iterable | Array in J2SDK 5.0 syntax
livetemplate.description.itover=Iterate over an Iterable or Array selection in J2SDK 5.0 syntax
livetemplate.description.inst=Checks object type with instanceof and down-casts it
livetemplate.description.lst=Fetches last element of an array
livetemplate.description.mn=Sets lesser value to a variable
livetemplate.description.mx=Sets greater value to a variable
livetemplate.description.psvm=main() method declaration
livetemplate.description.toar=Stores elements of java.util.Collection into array
livetemplate.description.lazy=Performs lazy initialization
livetemplate.description.if.not.null=Inserts ''if not null'' statement
livetemplate.description.if.null=Inserts ''if null'' statement
livetemplate.description.geti=Inserts singleton method getInstance
livetemplate.description.serr=Prints a string to System.err
livetemplate.description.sout=Prints a string to System.out
livetemplate.description.souf=Prints a formatted string to System.out
livetemplate.description.soutm=Prints current class and method names to System.out
livetemplate.description.soutp=Prints method parameter names and values to System.out
livetemplate.description.soutv=Prints a value to System.out
livetemplate.description.st=String
livetemplate.description.psf=public static final
livetemplate.description.psfi=public static final int
livetemplate.description.psfs=public static final String
livetemplate.description.thr=throw new
livetemplate.description.surround.braces=Surround with {}
livetemplate.description.surround.parens=Surround with ()
livetemplate.description.surround.tag=Surround with <tag></tag>
livetemplate.description.surround.tag.in.htmlorjsp=Surround with <tag></tag> in HTML/JSP
livetemplate.description.surround.cdata.in.xmlorhtmlorjsp=Surround with CDATA section
livetemplate.description.surround.with.callable=Surround with Callable
livetemplate.description.surround.with.read.lock=Surround with ReadWriteLock.readLock
livetemplate.description.surround.with.write.lock=Surround with ReadWriteLock.writeLock
quickfix.add.variable.text=Initialize variable ''{0}''
quickfix.add.variable.family.name=Initialize variable
inspection.i18n.quickfix.annotate.as=Annotate as @{0}
inspection.i18n.quickfix.annotate.element.as=Annotate {0} ''{1}'' as @{2}
disable.intention.action=Disable ''{0}''
enable.intention.action=Enable ''{0}''
under.construction.string=Under construction.
inspection.i18n.option.ignore.comment.pattern=Ignore lines containing this comment (pattern in java.util.Pattern format):
inspection.i18n.option.ignore.comment.title=Non-Nls comment pattern
inspection.i18n.option.ignore.assigned.to.constants=Ignore literals assigned to constants
inspection.i18n.option.ignore.tostring=Ignore contents of toString() method
intention.move.initializer.to.constructor=Move initializer to constructor
intention.move.initializer.to.set.up=Move initializer to setUp method
intention.move.field.assignment.to.declaration=Move assignment to field declaration
i18nize.jsp.error=Please select JSP text to I18nize.\nMake sure you have not selected any scriptlets, custom tags or other foreign languages elements.\nAlso, HTML tags inside selection must be balanced.
i18nize.error.title=Cannot I18nize Selection
i18nize.error.message=You can only i18nize Java string literal or substring thereof.\nPlease point the caret inside Java string literal or select part of it.
display.coverage.prompt=Do you want to display coverage data for ''{0}''?
code.coverage=Code Coverage
coverage.button.add.package=Add Package
coverage.pattern.filter.editor.choose.package.title=Choose Package
no.coverage=No coverage
code.coverage.is.not.supported=Code coverage is supported for jre 5.0 or higher
title.popup.show.coverage=Coverage Suites
prompt.remove.coverage=Do you want to remove ''{0}'' coverage data?
title.remove.coverage.data=Remove Coverage Data
coverage.data.outdated=Coverage data outdated
coverage.data.not.found=Coverage data not found
error.cannot.resolve.class=Cannot resolve class ''{0}''
implementation.view.title=Definition of {0}
javadoc.info.title=Documentation for {0}
intention.intercept.ejb.method.or.class.family=Add EJB interceptor
intention.intercept.ejb.method.or.class.class.text=Add interceptor for EJB class ''{0}''
intention.intercept.ejb.method.or.class.method.text=Add interceptor for business method ''{0}''
intention.edit.interceptor.binding.family=Interceptor Bindings
intention.edit.interceptor.binding.text=Edit Interceptor ''{0}'' bindings
powered.by=Powered by
powered.by.plugin=''{0}'' plugin.
error.cannot.convert.default.message=Invalid value: ''{0}''
error.cannot.resolve.default.message=Cannot resolve symbol ''{0}''
error.cannot.resolve.0.1=Cannot resolve {0} ''{1}''
error.unknown.enum.value.message=Unknown enum value ''{0}''
unknown.encoding.0=Unknown encoding: ''{0}''
i18nize.cant.create.properties.file.because.its.name.is.associated=Can''t create properties file ''{0}'' because its name is associated with the {1}.
i18nize.error.creating.properties.file=Error creating properties file
node.method.tooltip=Method
node.field.tooltip=Field
node.annotation.tooltip=Annotation
node.anonymous.class.tooltip=Anonymous Class
node.enum.tooltip=Enum
node.exception.tooltip=Exception
node.interface.tooltip=Interface
node.junit.test.tooltip=JUnit Test
node.runnable.class.tooltip=Runnable Class
node.class.tooltip=Class
node.excluded.flag.tooltip=Excluded
node.abstract.flag.tooltip=Abstract
node.final.flag.tooltip=Final
node.static.flag.tooltip=Static
multiple.implementations.tooltip=Multiple implementations
static.class.initializer={0}class initializer

# suppress inspection "UnusedProperty"
intentions.category.ejb=EJB
set.language.level=Set language level
set.language.level.to.0=Set language level to {0}
remove.annotation=Remove annotation
deannotate.intention.action.text=Deannotate
deannotate.intention.chooser.title=Choose annotation to delete
javadoc.type.parameters=Type parameters:
highlight.overridden.classes.chooser.title=Choose Classes to Highlight Overridden Methods from
no.methods.overriding.0.are.found=No methods overriding {0, choice, 0#|1# '{1}'|2#these classes} are found
copy.abstract.method.no.existing.implementations.found=No existing implementations found
copy.abstract.method.intention.name=Use existing implementation of ''{0}''
copy.abstract.method.popup.title=Choose implementation to copy
copy.abstract.method.title=Use Abstract Method Implementation
i18nize.empty.file.path=Please specify properties file path
choose.type.popup.title=Choose Type
cast.expression=Cast expression
cast.to.0=Cast to ''{0}''
class.completion.file.path=Press {0} again to search for all matching project files
class.completion.file.path.all.variants=Press {0} to search for matching files of any type
property.has.more.parameters.than.passed=Property ''{0}'' expected {1} {1, choice, 1#parameter|2#parameters}, passed {2}
create.file.family=Create File
rename.file.reference.family=Rename File Reference
rename.file.reference.text=Rename File Reference to {0}
create.directory.text=Create Directory {0}
create.file.text=Create File {0}
create.tagfile.text=Create Tag File {0}
rename.file.fix=Rename File
rename.element.family=Rename Element
rename.public.class.text=Rename class ''{0}'' to ''{1}''
rename.named.element.text=Rename ''{0}'' to ''{1}''
dialog.edit.template.checkbox.html.text=HTML Text
dialog.edit.template.checkbox.xsl.text=XSL Text

javadoc.error.resolving.url=Couldn''t resolve URL {0}
Configuring paths to API docs in project settings might help

block.comment.intersects.existing.comment=Selected region intersects existing comment
block.comment.wrapping.suffix=Selected region contains block comment suffix
block.comment.nested.comment=Selected region contained block {0, choice, 1#comment|2#comments},\nsurrounding ranges were commented.

popup.title.next.error.action.0.goes.through=''Next Error'' Action{0} Goes Through

parameter.info.switch.overload.shortcuts=Switch with {0} or {1}
parameter.info.switch.overload.shortcuts.single=Switch with {0}

parameter.info.progress.title=Calculating parameter info...
parameter.info.indexing.mode.not.supported=Parameter Info is unavailable during indexing


/**
 * @file /magma/objects/config/config.h
 *
 * @brief	The user configuration interface.
 */

#ifndef MAGMA_OBJECTS_CONFIG_H
#define MAGMA_OBJECTS_CONFIG_H

typedef struct __attribute__ ((packed)) {
	uint64_t flags;
	stringer_t *key, *value;
} user_config_entry_t;

// Possible flag values for user config entries.
enum {
	USER_CONF_STATUS_NONE = 0,
	USER_CONF_STATUS_CRITICAL = 1
};

typedef struct __attribute__ ((packed)) {
	inx_t *entries;
	uint64_t usernum, serial;
} user_config_t;

/// config.c
user_config_t *        user_config_alloc(uint64_t usernum);
user_config_t *        user_config_create(uint64_t usernum);
int_t                  user_config_edit(user_config_t *collection, stringer_t *key, stringer_t *value);
user_config_entry_t *  user_config_entry_alloc(stringer_t *key, stringer_t *value, uint64_t flags);
void                   user_config_entry_free(user_config_entry_t *entry);
void                   user_config_free(user_config_t *collection);
int_t                  user_config_update(user_config_t *collection);

/// datatier.c
int_t   user_config_delete(uint64_t usernum, stringer_t *key);
bool_t  user_config_fetch(user_config_t *collection);
int_t   user_config_upsert(uint64_t usernum, stringer_t *key, stringer_t *value, uint64_t flags);

#endif


<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-GB">
  <info>
    <title>Stellenbosch University - Harvard</title>
    <id>http://www.zotero.org/styles/harvard-stellenbosch-university</id>
    <link href="http://www.zotero.org/styles/harvard-stellenbosch-university" rel="self"/>
    <link href="http://www.zotero.org/styles/harvard-cite-them-right" rel="template"/>
    <link href="http://libguides.sun.ac.za/content.php?pid=344501&sid=2818229" rel="documentation"/>
    <author>
      <name>Yusuf Ras</name>
      <email>yr@sun.ac.za</email>
      <uri>http://www.mendeley.com/profiles/yusuf-ras/</uri>
    </author>
    <category citation-format="author-date"/>
    <category field="generic-base"/>
    <updated>2015-09-01T08:01:34+00:00</updated>
    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
  </info>
  <locale xmlns="http://purl.org/net/xbiblio/csl" xml:lang="en-GB">
    <terms>
      <term name="available at">available</term>
      <term name="open-quote">“</term>
      <term name="close-quote">”</term>
      <term name="open-inner-quote">‘</term>
      <term name="close-inner-quote">’</term>
    </terms>
  </locale>
  <macro name="editor-translator">
    <choose>
      <if variable="editor">
        <names variable="editor">
          <name and="symbol" initialize-with="." delimiter=", "/>
          <label form="short" prefix=" (" suffix=")"/>
        </names>
      </if>
    </choose>
    <choose>
      <if variable="translator">
        <names variable="translator">
          <label form="verb" text-case="capitalize-first" suffix=" "/>
          <name and="symbol" delimiter=", "/>
        </names>
      </if>
    </choose>
  </macro>
  <macro name="author">
    <names variable="author">
      <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with="." delimiter=", " delimiter-precedes-last="never"/>
      <label form="short" prefix=" " text-case="capitalize-first"/>
      <substitute>
        <names variable="editor"/>
        <names variable="translator"/>
        <choose>
          <if type="bill book graphic legal_case legislation motion_picture report song webpage" match="any">
            <text variable="title" font-style="italic"/>
          </if>
          <else>
            <text variable="title" quotes="true" text-case="capitalize-first"/>
          </else>
        </choose>
      </substitute>
    </names>
  </macro>
  <macro name="author-short">
    <names variable="author">
      <name form="short" and="symbol" delimiter-precedes-last="never" initialize-with="." sort-separator=" "/>
      <et-al font-style="italic"/>
      <substitute>
        <names variable="editor"/>
        <names variable="translator"/>
        <choose>
          <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
            <text variable="title" form="short" font-style="italic"/>
          </if>
          <else>
            <text variable="title" form="short" quotes="true" text-case="capitalize-first"/>
          </else>
        </choose>
      </substitute>
    </names>
  </macro>
  <macro name="author-count">
    <names variable="author">
      <name form="count"/>
    </names>
  </macro>
  <macro name="date-issued">
    <choose>
      <if type="article-journal" match="none">
        <text macro="date-issued-year"/>
      </if>
      <else-if variable="page" match="none">
        <text macro="date-issued-year"/>
      </else-if>
      <else-if is-numeric="page">
        <text macro="date-issued-year"/>
      </else-if>
      <else>
        <text term="in press" prefix="(" suffix=")"/>
      </else>
    </choose>
  </macro>
  <macro name="date-issued-no-parentheses">
    <choose>
      <if type="article-journal" match="none">
        <text macro="date-issued-year"/>
      </if>
      <else-if variable="page" match="none">
        <text macro="date-issued-year"/>
      </else-if>
      <else-if is-numeric="page">
        <text macro="date-issued-year"/>
      </else-if>
      <else>
        <text term="in press"/>
      </else>
    </choose>
  </macro>
  <macro name="date-issued-year">
    <choose>
      <if variable="issued">
        <date variable="issued">
          <date-part name="year"/>
        </date>
      </if>
      <else>
        <text term="no date" form="short"/>
      </else>
    </choose>
  </macro>
  <macro name="access">
    <choose>
      <if variable="DOI"/>
      <else-if variable="URL">
        <group delimiter=" ">
          <group delimiter=": ">
            <group delimiter=", ">
              <text term="online" prefix="[" suffix="]" text-case="capitalize-first"/>
              <text term="available at" text-case="capitalize-first"/>
            </group>
            <text variable="URL"/>
          </group>
          <text macro="date-access"/>
        </group>
      </else-if>
      <else-if variable="source accessed" match="all">
        <group delimiter=" ">
          <text variable="source"/>
          <text macro="date-access"/>
        </group>
      </else-if>
    </choose>
  </macro>
  <macro name="date-access">
    <date variable="accessed" prefix="[" suffix="]">
      <date-part name="year"/>
      <date-part name="month" form="long" prefix=", "/>
      <date-part name="day" form="numeric-leading-zeros" prefix=" "/>
    </date>
  </macro>
  <macro name="title">
    <choose>
      <if type="bill book graphic legal_case legislation motion_picture report song webpage" match="any">
        <text variable="title" font-style="italic"/>
      </if>
      <else>
        <text variable="title"/>
      </else>
    </choose>
  </macro>
  <macro name="book-details">
    <group delimiter=". ">
      <group delimiter=" ">
        <number variable="edition" form="ordinal"/>
        <label variable="edition" form="short"/>
      </group>
      <group delimiter=" ">
        <label variable="volume" form="short" text-case="capitalize-first"/>
        <text variable="volume"/>
      </group>
      <text macro="editor-translator"/>
      <group delimiter=" " prefix="(" suffix=")">
        <text variable="collection-title"/>
        <group delimiter=" ">
          <label variable="issue" form="short"/>
          <text variable="collection-number"/>
        </group>
      </group>
      <text macro="publisher"/>
    </group>
  </macro>
  <macro name="publisher">
    <group delimiter=": ">
      <text variable="publisher-place"/>
      <text variable="publisher"/>
    </group>
  </macro>
  <citation disambiguate-add-year-suffix="true" year-suffix-delimiter="," disambiguate-add-names="true" disambiguate-add-givenname="false" collapse="year-suffix" et-al-min="4" et-al-use-first="3" et-al-subsequent-min="3" et-al-subsequent-use-first="1">
    <sort>
      <key macro="author"/>
      <key macro="date-issued-no-parentheses"/>
    </sort>
    <layout prefix="(" suffix=")" delimiter="; ">
      <group delimiter=", ">
        <text macro="author-short"/>
        <text macro="date-issued-no-parentheses"/>
      </group>
      <group>
        <choose>
          <if locator="page" match="any">
            <text variable="locator" prefix=": "/>
          </if>
          <else>
            <label variable="locator" form="short" prefix=", "/>
            <text variable="locator" prefix=" "/>
          </else>
        </choose>
      </group>
    </layout>
  </citation>
  <bibliography hanging-indent="true" et-al-min="9" et-al-use-first="8">
    <sort>
      <key macro="author-short" names-min="1" names-use-first="1"/>
      <key macro="author-count" names-min="3" names-use-first="3"/>
      <key macro="author" names-min="3" names-use-first="1"/>
      <key macro="date-issued-no-parentheses"/>
    </sort>
    <layout suffix=".">
      <group delimiter=". ">
        <text macro="author"/>
        <text macro="date-issued"/>
        <choose>
          <if type="bill book graphic legal_case legislation motion_picture post-weblog song webpage" match="any">
            <text macro="title"/>
            <text macro="book-details"/>
          </if>
          <else-if type="article-journal article-magazine" match="any">
            <text macro="title"/>
            <text variable="container-title" font-style="italic"/>
            <group delimiter=":">
              <choose>
                <if variable="volume issue" match="any">
                  <group>
                    <text variable="volume"/>
                    <text variable="issue" prefix="(" suffix=")"/>
                  </group>
                </if>
                <else>
                  <date variable="issued" prefix="(" suffix=")">
                    <date-part name="month" form="long"/>
                    <date-part name="day" prefix=", "/>
                  </date>
                </else>
              </choose>
              <text variable="page"/>
            </group>
          </else-if>
          <else-if type="article-newspaper" match="any">
            <text macro="title"/>
            <group delimiter=" ">
              <text variable="container-title" font-style="italic"/>
              <text variable="publisher-place" prefix="(" suffix=")"/>
            </group>
            <group delimiter=": ">
              <date variable="issued">
                <date-part name="day" suffix=" "/>
                <date-part name="month" form="long"/>
              </date>
              <text variable="page"/>
            </group>
          </else-if>
          <else-if type="thesis" match="any">
            <text macro="title"/>
            <text variable="genre"/>
            <text variable="publisher"/>
          </else-if>
          <else-if type="chapter paper-conference entry-encyclopedia entry-dictionary" match="any">
            <text macro="title"/>
            <group delimiter=" ">
              <text term="in"/>
              <text variable="container-title" font-style="italic"/>
              <text macro="book-details"/>
              <text macro="editor-translator"/>
            </group>
            <text variable="page"/>
          </else-if>
          <else-if type="patent" match="any">
            <group font-style="italic">
              <text variable="number" prefix="Patent No. "/>
            </group>
            <group delimiter=": ">
              <text macro="publisher"/>
              <text variable="authority"/>
            </group>
          </else-if>
          <else-if type="report" match="any">
            <text macro="title"/>
            <group delimiter=" " prefix="(" suffix=")">
              <text variable="genre" text-case="capitalize-first"/>
              <text variable="number"/>
            </group>
            <text macro="publisher"/>
          </else-if>
        </choose>
        <text macro="access"/>
      </group>
    </layout>
  </bibliography>
</style>


<!--
title: 进阶
sort: 3
-->


/* @flow */

import type Node from '../../elements/Node';
import Reference from './Reference';
import Variable from './Variable';
import {default as Definition, types, typeOrder} from './Definition';
import toArray from '../../utils/toArray';

export default class Scope {
    constructor(scopeInfo: ScopeInfo) {
        let {node, parentScope, isProgramScope, isFunctionScope, isClassScope, isArrowFunctionScope} = scopeInfo;

        this.node = node;
        this.parentScope = parentScope;
        if (parentScope) {
            parentScope.childScopes.push(this);
            this._depth = parentScope._depth + 1;
        } else {
            this._depth = 0;
        }
        this.childScopes = [];
        this._variables = new Map();
        this._references = new Map();
        this._isProgramScope = Boolean(isProgramScope);
        this._isFunctionScope = Boolean(isFunctionScope);
        this._isClassScope = Boolean(isClassScope);
        this._isArrowFunctionScope = Boolean(isArrowFunctionScope);

        if (isProgramScope) {
            this._programReferences = new Map();
            this._programDefinitions = new Map();
        }
    }

    _isProgramScope: boolean;
    _isFunctionScope: boolean;
    _isClassScope: boolean;
    _isArrowFunctionScope: boolean;
    node: Node;
    _depth: number;
    parentScope: ?Scope;
    childScopes: Scope[];
    _variables: Map<string, Variable[]>;
    _references: Map<string, Reference[]>;

    _programReferences: Map<Node, Reference>;
    _programDefinitions: Map<Node, Definition>;

    _addVariable(variable: Variable) {
        let variables = this._variables.get(variable.name);
        if (variables) {
            variables.push(variable);
            variables.sort((variable1: Variable, variable2: Variable) => {
                let typeOrder1 = typeOrder[variable1.type];
                let typeOrder2 = typeOrder[variable2.type];
                if (typeOrder1 > typeOrder2) {
                    return 1;
                }
                if (typeOrder1 < typeOrder2) {
                    return -1;
                }
                return 0;
            });
        } else {
            this._variables.set(variable.name, [variable]);
        }
    }

    _addDefinition(definitionInfo: DefinitionInfo) {
        let {node, name, type} = definitionInfo;
        if (type === types.Variable) {
            if (!this._isFunctionScope && this.parentScope) {
                this.parentScope._addDefinition(definitionInfo);
                return;
            }
        }

        let variables = this._variables.get(name) || [];
        let variable: ?Variable;
        for (let item of variables) {
            if (item.type === type) {
                variable = item;
                break;
            }
        }

        if (!variable) {
            variable = new Variable({name, type, scope: this});
            this._adjustReferencesOnVariableAdd(variable);
            this._addVariable(variable);
        }

        let definition = new Definition({node, type, scope: this});

        variable._addDefinition(definition);

        let programScope = this._getProgramScope();
        if (programScope) {
            programScope._programDefinitions.set(node, definition);
        }
    }

    _removeDefinition(definition: Definition) {
        let variable = definition.variable;

        variable._removeDefinition(definition);

        if (
            variable._definitions.size === 0 &&
            (
                variable.type === 'LetVariable' ||
                variable.type === 'Constant' ||
                variable.type === 'Variable' ||
                variable.type === 'Parameter' ||
                variable.type === 'SelfReference' ||
                variable.type === 'CatchClauseError' ||
                variable.type === 'ImportBinding'
            )
        ) {
            removeVariable(variable);
        }

        let programScope = this._getProgramScope();
        if (programScope) {
            programScope._programDefinitions.delete(definition.node);
        }
    }

    _adjustReferencesOnVariableAdd(variable: Variable) {
        let depth = variable.scope._depth;
        let references = this._references.get(variable.name);
        if (references) {
            for (let reference of references) {
                let refVar = reference.variable;
                let varDepth = refVar.scope._depth;
                if (varDepth === depth) {
                    if (typeOrder[variable.type] < typeOrder[refVar.type]) {
                        refVar._transferReferences(variable);
                        removeVariableIfRequired(refVar);
                    }
                } else if (varDepth < depth) {
                    refVar._references.delete(reference);
                    variable._addReference(reference);
                    reference.variable = variable;
                    removeVariableIfRequired(refVar);
                }
            }
        }

        for (let childScope of this.childScopes) {
            childScope._adjustReferencesOnVariableAdd(variable);
        }
    }

    _addReference(referenceInfo: ReferenceInfo) {
        let {name} = referenceInfo;
        let reference = new Reference({scope: this, ...referenceInfo});
        this._assignReference(reference, name);
        let references = this._references.get(name);
        if (references) {
            references.push(reference);
        } else {
            this._references.set(name, [reference]);
        }

        let programScope = this._getProgramScope();
        if (programScope) {
            programScope._programReferences.set(reference.node, reference);
        }
    }

    _assignReference(reference: Reference, name: string) {
        let currentScope = this;
        do {
            let variables = currentScope._variables.get(name);
            if (variables) {
                if (reference.type) {
                    for (let variable of variables) {
                        if (variable.type === reference.type) {
                            variable._addReference(reference);
                            return;
                        }
                    }
                } else {
                    variables[0]._addReference(reference);
                    return;
                }
            }
            if (!currentScope.parentScope) {
                let globalVariable = new Variable({
                    name, type: types.ImplicitGlobal, scope: currentScope,
                });
                globalVariable._addReference(reference);
                currentScope._addVariable(globalVariable);
                return;
            } else {
                if (
                    (
                        (name === 'arguments' || name === 'this') &&
                        currentScope._isFunctionScope &&
                        !currentScope._isArrowFunctionScope &&
                        !currentScope._isProgramScope
                    ) ||
                    (
                        name === 'super' && currentScope._isClassScope
                    )
                ) {
                    let builtInVariable = new Variable({
                        name, type: types.BuiltIn, scope: currentScope,
                    });
                    builtInVariable._addReference(reference);
                    currentScope._addVariable(builtInVariable);
                    return;
                }
                currentScope = currentScope.parentScope;
            }
        } while (true);
    }

    _removeReference(reference: Reference) {
        let variable = reference.variable;
        let name = variable.name;
        let references = this._references.get(name);
        if (references) {
            let index = references.indexOf(reference);
            if (index !== -1) {
                references.splice(index, 1);
            }
        }
        variable._removeReference(reference);
        if (
            variable._references.size === 0 &&
            (
                variable.type === 'ImplicitGlobal' ||
                variable.type === 'BuiltIn'
            )
        ) {
            removeVariable(variable);
        }

        let programScope = this._getProgramScope();
        if (programScope) {
            programScope._programReferences.delete(reference.node);
        }
    }

    _getProgramScope(): ?Scope {
        let scope = this;
        while (scope && !scope._isProgramScope) {
            scope = scope.parentScope;
        }
        return scope;
    }

    getVariables(): Variable[] {
        return [].concat(...toArray(this._variables.values()));
    }

    getReferences(): Reference[] {
        return [].concat(...toArray(this._references.values()));
    }

    destroy() {
        let parentScope = this.parentScope;
        if (parentScope) {
            let scopeIndex = parentScope.childScopes.indexOf(this);
            if (scopeIndex !== -1) {
                parentScope.childScopes.splice(scopeIndex, 1);
            }
        }
        this.getReferences().forEach(this._removeReference, this);
    }
}

function removeVariableIfRequired(variable: Variable) {
    if (variable._references.size === 0 && variable._definitions.size === 0) {
        let variables = variable.scope._variables.get(variable.name);
        if (variables) {
            let index = variables.indexOf(variable);

            if (index !== -1) {
                variables.splice(index, 1);
            }

            if (variables.length === 0) {
                variable.scope._variables.delete(variable.name);
            }
        }
    }
}

function removeVariable(variable: Variable) {
    let scope = variable.scope;
    let variables = scope._variables.get(variable.name);

    if (variables) {
        let index = variables.indexOf(variable);
        if (index !== -1) {
            variables.splice(index, 1);
            if (variables.length === 0) {
                scope._variables.delete(variable.name);
            }
            for (let reference of variable._references) {
                reference.scope._assignReference(reference, variable.name);
            }
        }
    }
}

export type ReferenceInfo = {
    node: Node,
    name: string,
    read: boolean,
    write: boolean,
    type?: string
};

export type DefinitionInfo = {
    node: Node,
    name: string,
    type: string
};

export type ScopeInfo = {
    node: Node,
    parentScope: ?Scope,
    isProgramScope?: boolean,
    isFunctionScope?: boolean,
    isClassScope?: boolean,
    isArrowFunctionScope?: boolean
};


#!/usr/bin/env python

import os

import keras
import numpy
import scipy.ndimage
from image_ocr import TextImageGenerator, create_model, ctc_lambda_func
from keras import backend as K
from keras.layers import Lambda
from keras.models import load_model
from keras.utils.data_utils import get_file

img_h = 64
img_w = 512
pool_size = 2
words_per_epoch = 16000
val_split = 0.2
val_words = int(words_per_epoch * (val_split))
if K.image_data_format() == 'channels_first':
    input_shape = (1, img_w, img_h)
else:
    input_shape = (img_w, img_h, 1)

fdir = os.path.dirname(get_file('wordlists.tgz',
                                origin='http://www.mythic-ai.com/datasets/wordlists.tgz', untar=True))

img_gen = TextImageGenerator(monogram_file=os.path.join(fdir, 'wordlist_mono_clean.txt'),
                             bigram_file=os.path.join(fdir, 'wordlist_bi_clean.txt'),
                             minibatch_size=32,
                             img_w=img_w,
                             img_h=img_h,
                             downsample_factor=(pool_size ** 2),
                             val_split=words_per_epoch - val_words
                             )
print(f"Input shape: {input_shape}")
model, _, _ = create_model(input_shape, img_gen, pool_size, img_w, img_h)

model.load_weights("my_model.h5")

x = scipy.ndimage.imread('example.png', mode='L').transpose()
x = x.reshape(x.shape + (1,))

# Does not work
print(model.predict(x, batch_size=1, verbose=0))


from .stateful_unit import StatefulUnit

class Vocabulary(StatefulUnit):
    """
    Vocabulary class.

    :param pad_value: The string value for the padding position.
    :param oov_value: The string value for the out-of-vocabulary terms.

    Examples:
        >>> vocab = Vocabulary(pad_value='[PAD]', oov_value='[OOV]')
        >>> vocab.fit(['A', 'B', 'C', 'D', 'E'])
        >>> term_index = vocab.state['term_index']
        >>> term_index  # doctest: +SKIP
        {'[PAD]': 0, '[OOV]': 1, 'D': 2, 'A': 3, 'B': 4, 'C': 5, 'E': 6}
        >>> index_term = vocab.state['index_term']
        >>> index_term  # doctest: +SKIP
        {0: '[PAD]', 1: '[OOV]', 2: 'D', 3: 'A', 4: 'B', 5: 'C', 6: 'E'}

        >>> term_index['out-of-vocabulary-term']
        1
        >>> index_term[0]
        '[PAD]'
        >>> index_term[42]
        Traceback (most recent call last):
            ...
        KeyError: 42
        >>> a_index = term_index['A']
        >>> c_index = term_index['C']
        >>> vocab.transform(['C', 'A', 'C']) == [c_index, a_index, c_index]
        True
        >>> vocab.transform(['C', 'A', '[OOV]']) == [c_index, a_index, 1]
        True
        >>> indices = vocab.transform(list('ABCDDZZZ'))
        >>> ' '.join(vocab.state['index_term'][i] for i in indices)
        'A B C D D [OOV] [OOV] [OOV]'

    """

    def __init__(self, pad_value: str = '<PAD>', oov_value: str = '<OOV>'):
        """Vocabulary unit initializer."""
        super().__init__()
        self._pad = pad_value
        self._oov = oov_value
        self._context['term_index'] = self.TermIndex()
        self._context['index_term'] = dict()

    class TermIndex(dict):
        """Map term to index."""

        def __missing__(self, key):
            """Map out-of-vocabulary terms to index 1."""
            return 1

    def fit(self, tokens: list):
        """Build a :class:`TermIndex` and a :class:`IndexTerm`."""
        self._context['term_index'][self._pad] = 0
        self._context['term_index'][self._oov] = 1
        self._context['index_term'][0] = self._pad
        self._context['index_term'][1] = self._oov
        terms = set(tokens)
        for index, term in enumerate(terms):
            self._context['term_index'][term] = index + 2
            self._context['index_term'][index + 2] = term

    def transform(self, input_: list) -> list:
        """Transform a list of tokens to corresponding indices."""
        return [self._context['term_index'][token] for token in input_]

class BertVocabulary(StatefulUnit):
    """
    Vocabulary class.

    :param pad_value: The string value for the padding position.
    :param oov_value: The string value for the out-of-vocabulary terms.

    Examples:
        >>> vocab = BertVocabulary(pad_value='[PAD]', oov_value='[UNK]')
        >>> indices = vocab.transform(list('ABCDDZZZ'))

    """

    def __init__(self, pad_value: str = '[PAD]', oov_value: str = '[UNK]'):
        """Vocabulary unit initializer."""
        super().__init__()
        self._pad = pad_value
        self._oov = oov_value
        self._context['term_index'] = self.TermIndex()
        self._context['index_term'] = {}

    class TermIndex(dict):
        """Map term to index."""

        def __missing__(self, key):
            """Map out-of-vocabulary terms to index 100 ."""
            return 100

    def fit(self, vocab_path: str):
        """Build a :class:`TermIndex` and a :class:`IndexTerm`."""
        with open(vocab_path, 'r', encoding='utf-8') as vocab_file:
            for idx, line in enumerate(vocab_file):
                term = line.strip()
                self._context['term_index'][term] = idx
                self._context['index_term'][idx] = term

    def transform(self, input_: list) -> list:
        """Transform a list of tokens to corresponding indices."""
        return [self._context['term_index'][token] for token in input_]


/*
 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.media.sound;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.ShortMessage;

/**
 * A short message class that support for than 16 midi channels.
 *
 * @author Karl Helgason
 */
public final class SoftShortMessage extends ShortMessage {

    int channel = 0;

    @Override
    public int getChannel() {
        return channel;
    }

    @Override
    public void setMessage(int command, int channel, int data1, int data2)
            throws InvalidMidiDataException {
        this.channel = channel;
        super.setMessage(command, channel & 0xF, data1, data2);
    }

    @Override
    public Object clone() {
        SoftShortMessage clone = new SoftShortMessage();
        try {
            clone.setMessage(getCommand(), getChannel(), getData1(), getData2());
        } catch (InvalidMidiDataException e) {
            throw new IllegalArgumentException(e);
        }
        return clone;
    }
}