text:
import { HashTable, Helpers } from "./helpers";
import { JsonObject, Serializer, property } from "./jsonobject";
import {
  SurveyError,
  SurveyElement,
  IElement,
  IQuestion,
  IPanel,
  IConditionRunner,
  ISurveyImpl,
  IPage,
  Event,
  ITitleOwner,
  IProgressInfo,
  Base,
} from "./base";
import { surveyLocalization } from "./surveyStrings";
import { AnswerRequiredError, CustomError } from "./error";
import { SurveyValidator, IValidatorOwner, ValidatorRunner } from "./validator";
import { TextPreProcessor, TextPreProcessorValue } from "./textPreProcessor";
import { ILocalizableOwner, LocalizableString } from "./localizablestring";
import { ConditionRunner } from "./conditions";
import { QuestionCustomWidget } from "./questionCustomWidgets";
import { CustomWidgetCollection } from "./questionCustomWidgets";
import { settings } from "./settings";
import { SurveyModel } from "./survey";
import { PanelModel } from "./panel";
import { RendererFactory } from "./rendererFactory";

export interface IConditionObject {
  name: string;
  text: string;
  question: Question;
}

/**
 * A base class for all questions.
 */
export class Question
  extends SurveyElement
  implements
    IQuestion,
    IConditionRunner,
    ILocalizableOwner,
    IValidatorOwner,
    ITitleOwner {
  [index: string]: any;
  private static TextPreprocessorValuesMap = {
    title: "processedTitle",
    require: "requiredText",
  };
  private static questionCounter = 100;
  private static getQuestionId(): string {
    return "sq_" + Question.questionCounter++;
  }
  private conditionRunner: ConditionRunner = null;
  private isCustomWidgetRequested: boolean = false;
  private customWidgetValue: QuestionCustomWidget;
  customWidgetData = { isNeedRender: true };
  focusCallback: () => void;
  surveyLoadCallback: () => void;

  private textPreProcessor: TextPreProcessor;
  private conditionEnabelRunner: ConditionRunner;
  private conditionRequiredRunner: ConditionRunner;
  valueChangedCallback: () => void;
  commentChangedCallback: () => void;
  validateValueCallback: () => SurveyError;
  questionTitleTemplateCallback: () => string;
  afterRenderQuestionCallback: (question: Question, element: any) => any;
  private locProcessedTitle: LocalizableString;
  protected isReadyValue: boolean = true;

  /**
   * The event is fired when isReady property of question is changed.
   *
 options.question - the question
   *
 options.isReady - current value of isReady
   *
 options.oldIsReady - old value of isReady
   */
  public onReadyChanged: Event<
    (sender: Question, options: any) => any,
    any
  > = new Event<(sender: Question, options: any) => any, any>();

  public isReadOnlyRenderDiv() {
    return this.isReadOnly && settings.readOnlyCommentRenderMode === "div";
  }

  constructor(public name: string) {
    super(name);
    this.id = Question.getQuestionId();
    this.onCreating();
    var self = this;
    this.createNewArray("validators", function (validator: any) {
      validator.errorOwner = self;
    });
    var locTitleValue = this.createLocalizableString("title", this, true);
    locTitleValue.onGetTextCallback = function (text) {
      if (!text) {
        text = self.name;
      }
      if (!self.survey) return text;
      return self.survey.getUpdatedQuestionTitle(self, text);
    };
    this.locProcessedTitle = new LocalizableString(this, true);
    this.locProcessedTitle.sharedData = locTitleValue;
    var locCommentText = this.createLocalizableString(
      "commentText",
      this,
      true
    );
    locCommentText.onGetTextCallback = function (text) {
      return !!text ? text : surveyLocalization.getString("otherItemText");
    };

    this.createLocalizableString("requiredErrorText", this);
    this.registerFunctionOnPropertyValueChanged("width", function () {
      self.updateElementCss();
      if (!!self.parent) {
        self.parent.elementWidthChanged(self);
      }
    });
    this.registerFunctionOnPropertiesValueChanged(
      ["indent", "rightIndent"],
      function () {
        self.onIndentChanged();
      }
    );

    this.registerFunctionOnPropertiesValueChanged(
      ["hasComment", "hasOther"],
      function () {
        self.initCommentFromSurvey();
      }
    );
  }
  public getValueName(): string {
    if (!!this.valueName) return this.valueName.toString();
    return this.name;
  }
  /**
   * Use this property if you want to store the question result in the name different from the question name.
   * Question name should be unique in the survey and valueName could be not unique. It allows to share data between several questions with the same valueName.
   * The library set the value automatically if the question.name property is not valid. For example, if it contains the period '.' symbol.
   * In this case if you set the question.name property to 'x.y' then the valueName becomes 'x y'.
   * Please note, this property is hidden for questions without input, for example html question.
   * @see name
   */
  public get valueName(): string {
    return this.getPropertyValue("valueName", "");
  }
  public set valueName(val: string) {
    var oldValueName = this.getValueName();
    this.setPropertyValue("valueName", val);
    this.onValueNameChanged(oldValueName);
  }
  protected onValueNameChanged(oldValue: string) {
    if (!this.survey) return;
    this.survey.questionRenamed(
      this,
      this.name,
      !!oldValue ? oldValue : this.name
    );
    this.initDataFromSurvey();
  }
  protected onNameChanged(oldValue: string) {
    if (!this.survey) return;
    this.survey.questionRenamed(
      this,
      oldValue,
      this.valueName ? this.valueName : oldValue
    );
  }
  public get isReady(): boolean {
    return this.isReadyValue;
  }
  /**
   * Get is question ready to use
   */
  public choicesLoaded(): void {}
  /**
   * Get/set the page where the question is located.
   */
  public get page(): IPage {
    return this.getPage(this.parent);
  }
  public set page(val: IPage) {
    this.setPage(this.parent, val);
  }
  public getPanel(): IPanel {
    return null;
  }
  public delete() {
    if (!!this.parent) {
      this.removeSelfFromList(this.parent.elements);
    }
  }
  public get isFlowLayout(): boolean {
    return this.getLayoutType() === "flow";
  }
  public getLayoutType(): string {
    if (!!this.parent) return this.parent.getChildrenLayoutType();
    return "row";
  }
  isLayoutTypeSupported(layoutType: string): boolean {
    return layoutType !== "flow";
  }
  /**
   * Use it to get/set the question visibility.
   * @see visibleIf
   */
  public get visible(): boolean {
    return this.getPropertyValue("visible", true);
  }
  public set visible(val: boolean) {
    if (val == this.visible) return;
    this.setPropertyValue("visible", val);
    this.onVisibleChanged();
    this.notifySurveyVisibilityChanged();
  }
  protected onVisibleChanged() {
    this.setPropertyValue("isVisible", this.isVisible);
    if (this.isVisible && this.survey && this.survey.isClearValueOnHidden) {
      this.updateValueWithDefaults();
    }
    if (!this.isVisible && this.errors && this.errors.length > 0) {
      this.errors = [];
    }
  }
  /**
   * Use it to choose how other question values will be rendered in title if referenced in {}.
   * Please note, this property is hidden for question without input, for example html question.
   */
  public get useDisplayValuesInTitle(): boolean {
    return this.getPropertyValue("useDisplayValuesInTitle", true);
  }
  public set useDisplayValuesInTitle(val: boolean) {
    this.setPropertyValue("useDisplayValuesInTitle", val);
  }
  /**
   * An expression that returns true or false. If it returns true the Question becomes visible and if it returns false the Question becomes invisible. The library runs the expression on survey start and on changing a question value. If the property is empty then visible property is used.
   * @see visible
   */
  public get visibleIf(): string {
    return this.getPropertyValue("visibleIf", "");
  }
  public set visibleIf(val: string) {
    this.setPropertyValue("visibleIf", val);
    this.runConditions();
  }
  /**
   * Returns true if the question is visible or survey is in design mode right now.
   */
  public get isVisible(): boolean {
    if (this.survey && this.survey.areEmptyElementsHidden && this.isEmpty())
      return false;
    return this.visible || this.areInvisibleElementsShowing;
  }
  /**
   * Returns the visible index of the question in the survey. It can be from 0 to all visible questions count - 1
   * The visibleIndex is -1 if the title is 'hidden' or hideNumber is true
   * @see titleLocation
   * @see hideNumber
   */
  public get visibleIndex(): number {
    return this.getPropertyValue("visibleIndex", -1);
  }
  /**
   * Set hideNumber to true to stop showing the number for this question. The question will not be counter
   * @see visibleIndex
   * @see titleLocation
   */
  public get hideNumber(): boolean {
    return this.getPropertyValue("hideNumber", false);
  }
  public set hideNumber(val: boolean) {
    this.setPropertyValue("hideNumber", val);
    this.notifySurveyVisibilityChanged();
  }
  /**
   * Returns true if the question may have a title located on the left
   */
  public get isAllowTitleLeft(): boolean {
    return true;
  }
  /**
   * Returns the type of the object as a string as it represents in the json.
   */
  public getType(): string {
    return "question";
  }
  /**
   * Move question to a new container Page/Panel. Add as a last element if insertBefore parameter is not used or inserted into the given index,
   * if insert parameter is number, or before the given element, if the insertBefore parameter is a question or panel
   * @param container Page or Panel to where a question is relocated.
   * @param insertBefore Use it if you want to set the question to a specific position. You may use a number (use 0 to insert int the beginning) or element, if you want to insert before this element.
   */
  public moveTo(container: IPanel, insertBefore: any = null): boolean {
    return this.moveToBase(this.parent, container, insertBefore);
  }
  public getProgressInfo(): IProgressInfo {
    if (!this.hasInput) return super.getProgressInfo();
    return {
      questionCount: 1,
      answeredQuestionCount: !this.isEmpty() ? 1 : 0,
      requiredQuestionCount: this.isRequired ? 1 : 0,
      requiredAnsweredQuestionCount: !this.isEmpty() && this.isRequired ? 1 : 0,
    };
  }
  private runConditions() {
    if (this.data && !this.isLoadingFromJson && !this.isDesignMode) {
      this.runCondition(
        this.getDataFilteredValues(),
        this.getDataFilteredProperties()
      );
      this.locStrsChanged();
    }
  }
  public setSurveyImpl(value: ISurveyImpl) {
    super.setSurveyImpl(value);
    if (this.survey) {
      this.survey.questionCreated(this);
    }
    if (this.survey && this.survey.isDesignMode && !this.isDesignMode) {
      this.onVisibleChanged();
    }
    this.runConditions();
  }
  public getDataFilteredValues(): any {
    return !!this.data ? this.data.getFilteredValues() : null;
  }
  public getDataFilteredProperties(): any {
    var props = !!this.data ? this.data.getFilteredProperties() : {};
    props.question = this;
    return props;
  }
  /**
   * A parent element. It can be panel or page.
   */
  public get parent(): IPanel {
    return this.getPropertyValue("parent", null);
  }
  public set parent(val: IPanel) {
    this.setPropertyValue("parent", val);
    this.updateElementCss();
    this.onParentChanged();
  }
  private parentQuestionValue: Question = null;
  /**
   * A parent question. It can be a dynamic panel or dynamic/dropdown matrices. If the value is a matrix, it means that question is a cell question.
   * This property is null for a stand alone question.
   */
  public get parentQuestion(): Question {
    return this.parentQuestionValue;
  }
  setParentQuestion(val: Question) {
    this.parentQuestionValue = val;
  }
  protected onParentChanged() {}
  /**
   * Returns false if the question doesn't have a title property, for example: QuestionHtmlModel, or titleLocation property equals to "hidden"
   * @see titleLocation
   */
  public get hasTitle(): boolean {
    return this.getTitleLocation() !== "hidden";
  }
  /**
   * Set this property different from "default" to set the specific question title location for this panel/page.
   * Please note, this property is hidden for questions without input, for example html question.
   * @see SurveyModel.questionTitleLocation
   */
  public get titleLocation(): string {
    return this.getPropertyValue("titleLocation");
  }
  public set titleLocation(value: string) {
    var isVisibilityChanged =
      this.titleLocation == "hidden" || value == "hidden";
    this.setPropertyValue("titleLocation", value.toLowerCase());
    if (!this.isLoadingFromJson) {
      this.updateElementCss();
    }
    if (isVisibilityChanged) {
      this.notifySurveyVisibilityChanged();
    }
  }
  private notifySurveyVisibilityChanged() {
    if (!this.survey || this.isLoadingFromJson) return;
    this.survey.questionVisibilityChanged(this, this.isVisible);
    if (this.survey.isClearValueOnHidden && !this.visible) {
      this.clearValue();
    }
  }
  /**
   * Return the title location based on question titleLocation property and QuestionTitleLocation of it's parents
   * @see titleLocation
   * @see PanelModelBase.QuestionTitleLocation
   * @see SurveyModel.QuestionTitleLocation
   */
  public getTitleLocation(): string {
    if (this.isFlowLayout) return "hidden";
    var location = this.getTitleLocationCore();
    if (location === "left" && !this.isAllowTitleLeft) location = "top";
    return location;
  }
  protected getTitleLocationCore(): string {
    if (this.titleLocation !== "default") return this.titleLocation;
    if (!!this.parent) return this.parent.getQuestionTitleLocation();
    if (!!this.survey) return this.survey.questionTitleLocation;
    return "top";
  }
  get hasTitleOnLeft(): boolean {
    return this.hasTitle && this.getTitleLocation() === "left";
  }
  get hasTitleOnTop(): boolean {
    return this.hasTitle && this.getTitleLocation() === "top";
  }
  get hasTitleOnBottom(): boolean {
    return this.hasTitle && this.getTitleLocation() === "bottom";
  }
  get hasTitleOnLeftTop(): boolean {
    if (!this.hasTitle) return false;
    var location = this.getTitleLocation();
    return location === "left" || location === "top";
  }
  public get errorLocation(): string {
    return this.survey ? this.survey.questionErrorLocation : "top";
  }
  /**
   * Returns false if the question doesn't have an input element, for example: QuestionHtmlModel
   * @see hasSingleInput
   */
  public get hasInput(): boolean {
    return true;
  }
  /**
   * Returns false if the question doesn't have an input element or have multiple inputs: matrices or panel dynamic
   * @see hasInput
   */
  public get hasSingleInput(): boolean {
    return this.hasInput;
  }
  public get inputId(): string {
    return this.id + "i";
  }
  /**
   * Question title. Use survey questionTitleTemplate property to change the title question is rendered. If it is empty, then question name property is used.
   * @see SurveyModel.questionTitleTemplate
   */
  public get title(): string {
    return this.getLocalizableStringText("title", this.name);
  }
  public set title(val: string) {
    this.setLocalizableStringText("title", val);
  }
  get locTitle(): LocalizableString {
    return this.getLocalizableString("title");
  }
  /**
   * Question description. It renders under question title by using smaller font. Unlike the title, description can be empty.
   * Please note, this property is hidden for questions without input, for example html question.
   * @see title
   */
  @property({ localizable: true })
  description: string;
  /**
   * Question description location. By default, value is "default" and it depends on survey questionDescriptionLocation property
   * You may change it to "underInput" to render it under question input or "underTitle" to rendered it under title.
   * @see description
   * @see Survey.questionDescriptionLocation
   */
  public get descriptionLocation(): string {
    return this.getPropertyValue("descriptionLocation");
  }
  public set descriptionLocation(val: string) {
    this.setPropertyValue("descriptionLocation", val);
  }
  get hasDescriptionUnderTitle(): boolean {
    return this.getDescriptionLocation() == "underTitle";
  }
  get hasDescriptionUnderInput(): boolean {
    return this.getDescriptionLocation() == "underInput";
  }
  private getDescriptionLocation() {
    if (this.descriptionLocation !== "default") return this.descriptionLocation;
    return !!this.survey
      ? this.survey.questionDescriptionLocation
      : "underTitle";
  }
  public get clickTitleFunction(): any {
    if (this.hasInput) {
      var self = this;
      return function () {
        self.focus();
        return true;
      };
    }
    return undefined;
  }
  /**
   * The custom text that will be shown on required error. Use this property, if you do not want to show the default text.
   * Please note, this property is hidden for question without input, for example html question.
   */
  public get requiredErrorText(): string {
    return this.getLocalizableStringText("requiredErrorText");
  }
  public set requiredErrorText(val: string) {
    this.setLocalizableStringText("requiredErrorText", val);
  }
  get locRequiredErrorText(): LocalizableString {
    return this.getLocalizableString("requiredErrorText");
  }
  /**
   * Use it to get or set the comment value.
   */
  public get commentText(): string {
    return this.getLocalizableStringText(
      "commentText",
      surveyLocalization.getString("otherItemText")
    );
  }
  public set commentText(val: string) {
    this.setLocalizableStringText("commentText", val);
  }
  get locCommentText(): LocalizableString {
    return this.getLocalizableString("commentText");
  }
  /**
   * Returns a copy of question errors survey. For some questions like matrix and panel dynamic it includes the errors of nested questions.
   */
  public getAllErrors(): Array<SurveyError> {
    return this.errors.slice();
  }
  public getErrorByType(errorType: string): SurveyError {
    for (var i = 0; i < this.errors.length; i++) {
      if (this.errors[i].getErrorType() === errorType) return this.errors[i];
    }
    return null;
  }
  /**
   * The link to the custom widget.
   */
  public get customWidget(): QuestionCustomWidget {
    if (!this.isCustomWidgetRequested && !this.customWidgetValue) {
      this.isCustomWidgetRequested = true;
      this.updateCustomWidget();
    }
    return this.customWidgetValue;
  }
  public updateCustomWidget() {
    this.customWidgetValue = CustomWidgetCollection.Instance.getCustomWidget(
      this
    );
  }
  public get isCompositeQuestion(): boolean {
    return false;
  }
  public afterRenderQuestionElement(el: any) {
    if (!this.survey || !this.hasSingleInput) return;
    this.survey.afterRenderQuestionInput(this, el);
  }
  public afterRender(el: any) {
    if (!this.survey) return;
    this.survey.afterRenderQuestion(this, el);
    if (!!this.afterRenderQuestionCallback) {
      this.afterRenderQuestionCallback(this, el);
    }
  }
  public beforeDestroyQuestionElement(el: any) {}
  /**
   * Returns the rendred question title.
   */
  public get processedTitle() {
    var res = this.locProcessedTitle.textOrHtml;
    return res ? res : this.name;
  }
  /**
   * Returns the title after processing the question template.
   * @see SurveyModel.questionTitleTemplate
   */
  public get fullTitle(): string {
    return this.locTitle.renderedHtml;
  }
  protected get titlePattern(): string {
    return !!this.survey ? this.survey.questionTitlePattern : "numTitleRequire";
  }
  public get isRequireTextOnStart() {
    return this.isRequired && this.titlePattern == "requireNumTitle";
  }
  public get isRequireTextBeforeTitle() {
    return this.isRequired && this.titlePattern == "numRequireTitle";
  }
  public get isRequireTextAfterTitle() {
    return this.isRequired && this.titlePattern == "numTitleRequire";
  }
  /**
   * The Question renders on the new line if the property is true. If the property is false, the question tries to render on the same line/row with a previous question/panel.
   */
  public get startWithNewLine(): boolean {
    return this.getPropertyValue("startWithNewLine", true);
  }
  public set startWithNewLine(val: boolean) {
    if (this.startWithNewLine == val) return;
    this.setPropertyValue("startWithNewLine", val);
  }
  /**
   * Returns all css classes that used for rendering the question. You may use survey.updateQuestionCssClasses event to override css classes for a question.
   * @see SurveyModel.updateQuestionCssClasses
   */
  public get cssClasses(): any {
    var css = this.css;
    var classes = { error: {} };
    this.copyCssClasses(classes, css.question);
    this.copyCssClasses(classes.error, css.error);
    this.updateCssClasses(classes, css);
    if (this.survey) {
      this.survey.updateQuestionCssClasses(this, classes);
    }
    this.updateElementCssCore(classes);
    return classes;
  }
  public get cssRoot(): string {
    return this.getPropertyValue("cssRoot", "");
  }
  protected setCssRoot(val: string) {
    this.setPropertyValue("cssRoot", val);
  }
  protected getCssRoot(cssClasses: any): string {
    var res =
      this.isFlowLayout && !this.isDesignMode
        ? cssClasses.flowRoot
        : cssClasses.mainRoot;
    if (!res) res = "";
    if (
      !this.isFlowLayout &&
      this.hasTitleOnLeft &&
      !!cssClasses.titleLeftRoot
    ) {
      res += " " + cssClasses.titleLeftRoot;
    }
    if (this.errors.length > 0 && !!cssClasses.hasError) {
      res += " " + cssClasses.hasError;
    }
    if (cssClasses.small && !this.width) {
      res += " " + cssClasses.small;
    }
    return res;
  }
  public get cssHeader(): string {
    return this.getPropertyValue("cssHeader", "");
  }
  protected setCssHeader(val: string) {
    this.setPropertyValue("cssHeader", val);
  }
  protected getCssHeader(cssClasses: any): string {
    var res = cssClasses.header || "";
    if (this.hasTitleOnTop && !!cssClasses.headerTop) {
      res += " " + cssClasses.headerTop;
    }
    if (this.hasTitleOnLeft && !!cssClasses.headerLeft) {
      res += " " + cssClasses.headerLeft;
    }
    if (this.hasTitleOnBottom && !!cssClasses.headerBottom) {
      res += " " + cssClasses.headerBottom;
    }
    return res;
  }
  public get cssContent(): string {
    return this.getPropertyValue("cssContent", "");
  }
  protected setCssContent(val: string) {
    this.setPropertyValue("cssContent", val);
  }
  protected getCssContent(cssClasses: any): string {
    var res = cssClasses.content || "";
    if (this.hasTitleOnLeft && !!cssClasses.contentLeft) {
      res += " " + cssClasses.contentLeft;
    }
    return res;
  }
  public get cssTitle(): string {
    return this.getPropertyValue("cssTitle", "");
  }
  protected setCssTitle(val: string) {
    this.setPropertyValue("cssTitle", val);
  }
  protected getCssTitle(cssClasses: any): string {
    var result = cssClasses.title;

    if (this.isCollapsed || this.isExpanded) {
      result += " " + cssClasses.titleExpandable;
    }

    if (this.containsErrors) {
      if (!!cssClasses.titleOnError) {
        result += " " + cssClasses.titleOnError;
      }
    } else if (this.isAnswered && !!cssClasses.titleOnAnswer) {
      result += " " + cssClasses.titleOnAnswer;
    }
    return result;
  }
  public get cssError(): string {
    return this.getPropertyValue("cssError", "");
  }
  protected setCssError(val: string) {
    this.setPropertyValue("cssError", val);
  }
  //TODO was not removed from other places
  protected getCssError(cssClasses: any): string {
    var res = cssClasses.error.root || "";
    if (this.errorLocation == "top") {
      if (!!cssClasses.error.locationTop) {
        res += " " + cssClasses.error.locationTop;
      }
    } else if (
      this.errorLocation === "bottom" &&
      !!cssClasses.error.locationBottom
    ) {
      res += " " + cssClasses.error.locationBottom;
    }
    return res;
  }
  public updateElementCss() {
    if (this.isLoadingFromJson) return;
    this.updateElementCssCore(this.cssClasses);
  }
  protected updateElementCssCore(cssClasses: any) {
    this.setCssRoot(this.getCssRoot(cssClasses));
    this.setCssHeader(this.getCssHeader(cssClasses));
    this.setCssContent(this.getCssContent(cssClasses));
    this.setCssTitle(this.getCssTitle(cssClasses));
    this.setCssError(this.getCssError(cssClasses));
  }
  protected updateCssClasses(res: any, css: any) {
    if (!css.question) return;
    if (this.isRequired) {
      if (!!css.question.required) {
        res.root = (res.root ? res.root + " " : "") + objCss;
      }
      if (css.question.titleRequired) {
        res.title += " " + css.question.titleRequired;
      }
    }
    var objCss = css[this.getCssType()];
    if (objCss === undefined || objCss === null) return;
    if (typeof objCss === "string" || objCss instanceof String) {
      res.root = (res.root ? res.root + " " : "") + objCss;
    } else {
      for (var key in objCss) {
        res[key] = objCss[key];
      }
    }
  }
  protected getCssType(): string {
    return this.getType();
  }
  private get css(): any {
    return !!this.survey ? this.survey.getCss() : {};
  }
  /**
   * Use it to set the specific width to the question like css style (%, px, em etc).
   */
  public get width(): string {
    return this.getPropertyValue("width", "");
  }
  public set width(val: string) {
    this.setPropertyValue("width", val);
  }
  /**
   * Use it to set the specific minWidth constraint to the question like css style (%, px, em etc).
   */
  public get minWidth(): string {
    return this.getPropertyValue("minWidth", settings.minWidth);
  }
  public set minWidth(val: string) {
    this.setPropertyValue("minWidth", val);
  }
  /**
   * Use it to set the specific maxWidth constraint to the question like css style (%, px, em etc).
   */
  public get maxWidth(): string {
    return this.getPropertyValue("maxWidth", settings.maxWidth);
  }
  public set maxWidth(val: string) {
    this.setPropertyValue("maxWidth", val);
  }
  /**
   * The rendered width of the question.
   */
  public get renderWidth(): string {
    return this.getPropertyValue("renderWidth", "");
  }
  public set renderWidth(val: string) {
    this.setPropertyValue("renderWidth", val);
  }
  /**
   * Set it different from 0 to increase the left padding.
   */
  public get indent(): number {
    return this.getPropertyValue("indent", 0);
  }
  public set indent(val: number) {
    this.setPropertyValue("indent", val);
  }
  /**
   * Set it different from 0 to increase the right padding.
   */
  public get rightIndent(): number {
    return this.getPropertyValue("rightIndent", 0);
  }
  public set rightIndent(val: number) {
    this.setPropertyValue("rightIndent", val);
  }
  get paddingLeft(): string {
    return this.getPropertyValue("paddintLeft", "");
  }
  set paddingLeft(val: string) {
    this.setPropertyValue("paddintLeft", val);
  }
  get paddingRight(): string {
    return this.getPropertyValue("paddingRight", "");
  }
  set paddingRight(val: string) {
    this.setPropertyValue("paddingRight", val);
  }
  private onIndentChanged() {
    this.paddingLeft = this.getIndentSize(this.indent);
    this.paddingRight = this.getIndentSize(this.rightIndent);
  }
  private getIndentSize(indent: number): string {
    if (indent < 1) return "";
    return indent * this.cssClasses.indent + "px";
  }
  /**
   * Move the focus to the input of this question.
   * @param onError set this parameter to true, to focus the input with the first error, other wise the first input will be focused.
   */
  public focus(onError: boolean = false) {
    if (this.isDesignMode) return;

    if (!!this.survey) {
      this.survey.scrollElementToTop(this, this, null, this.id);
    }
    var id = !onError
      ? this.getFirstInputElementId()
      : this.getFirstErrorInputElementId();
    if (SurveyElement.FocusElement(id)) {
      this.fireCallback(this.focusCallback);
    }
  }
  protected fireCallback(callback: () => void) {
    if (callback) callback();
  }
  public getOthersMaxLength(): any {
    if (!this.survey) return null;
    return this.survey.maxOthersLength > 0 ? this.survey.maxOthersLength : null;
  }
  protected onCreating() {}
  protected getFirstInputElementId(): string {
    return this.inputId;
  }
  protected getFirstErrorInputElementId(): string {
    return this.getFirstInputElementId();
  }
  protected getProcessedTextValue(textValue: TextPreProcessorValue) {
    var name = textValue.name.toLocaleLowerCase();
    textValue.isExists =
      Object.keys(Question.TextPreprocessorValuesMap).indexOf(name) !== -1 ||
      (<any>this)[textValue.name] !== undefined;
    textValue.value = (<any>this)[
      (<any>Question.TextPreprocessorValuesMap)[name] || textValue.name
    ];
  }
  public supportComment(): boolean {
    return false;
  }
  public supportOther(): boolean {
    return false;
  }
  /**
   * Set this property to true, to make the question a required. If a user doesn't answer the question then a validation error will be generated.
   * Please note, this property is hidden for question without input, for example html question.
   */
  public get isRequired(): boolean {
    return this.getPropertyValue("isRequired", false);
  }
  public set isRequired(val: boolean) {
    if (this.isRequired == val) return;
    this.setPropertyValue("isRequired", val);
    if (!this.isLoadingFromJson) {
      this.locTitle.onChanged();
    }
  }
  /**
   * An expression that returns true or false. If it returns true the Question becomes required and an end-user has to answer it.
   * If it returns false the Question then an end-user may not answer it the Question maybe empty.
   * The library runs the expression on survey start and on changing a question value. If the property is empty then isRequired property is used.
   * Please note, this property is hidden for question without input, for example html question.
   * @see isRequired
   */
  public get requiredIf(): string {
    return this.getPropertyValue("requiredIf", "");
  }
  public set requiredIf(val: string) {
    this.setPropertyValue("requiredIf", val);
    this.runConditions();
  }
  /**
   * Set it to true, to add a comment for the question.
   */
  public get hasComment(): boolean {
    return this.getPropertyValue("hasComment", false);
  }
  public set hasComment(val: boolean) {
    if (!this.supportComment()) return;
    this.setPropertyValue("hasComment", val);
    if (this.hasComment) this.hasOther = false;
  }
  /**
   * The unique identificator. It is generated automatically.
   */
  public get id(): string {
    return this.getPropertyValue("id");
  }
  public set id(val: string) {
    this.setPropertyValue("id", val);
  }
  public get ariaTitleId(): string {
    return this.id + "_ariaTitle";
  }
  public get ariaRole(): string {
    return null;
  }
  public get hasOther(): boolean {
    return this.getPropertyValue("hasOther", false);
  }
  public set hasOther(val: boolean) {
    if (!this.supportOther() || this.hasOther == val) return;
    this.setPropertyValue("hasOther", val);
    if (this.hasOther) this.hasComment = false;
    this.hasOtherChanged();
  }
  protected hasOtherChanged() {}
  public get requireUpdateCommentValue() {
    return this.hasComment || this.hasOther;
  }
  /**
   * Returns true if readOnly property is true or survey is in display mode or parent panel/page is readOnly.
   * @see SurveyModel.model
   * @see readOnly
   */
  public get isReadOnly() {
    var isParentReadOnly = !!this.parent && this.parent.isReadOnly;
    var isSurveyReadOnly = !!this.survey && this.survey.isDisplayMode;
    return this.readOnly || isParentReadOnly || isSurveyReadOnly;
  }
  /**
   * An expression that returns true or false. If it returns false the Question becomes read only and an end-user will not able to answer on the qustion. The library runs the expression on survey start and on changing a question value. If the property is empty then readOnly property is used.
   * Please note, this property is hidden for question without input, for example html question.
   * @see readOnly
   * @see isReadOnly
   */
  public get enableIf(): string {
    return this.getPropertyValue("enableIf", "");
  }
  public set enableIf(val: string) {
    this.setPropertyValue("enableIf", val);
    this.runConditions();
  }
  /**
   * Run visibleIf and enableIf expressions. If visibleIf or/and enabledIf are not empty, then the results of performing the expression (true or false) set to the visible/readOnly properties.
   * @param values Typically survey results
   * @see visible
   * @see visibleIf
   * @see readOnly
   * @see enableIf
   */
  public runCondition(values: HashTable<any>, properties: HashTable<any>) {
    if (this.isDesignMode) return;
    if (!properties) properties = {};
    properties["question"] = this;
    if (!this.areInvisibleElementsShowing) {
      this.runVisibleIfCondition(values, properties);
    }
    this.runEnableIfCondition(values, properties);
    this.runRequiredIfCondition(values, properties);
  }
  private runVisibleIfCondition(
    values: HashTable<any>,
    properties: HashTable<any>
  ) {
    if (!this.visibleIf) return;
    if (!this.conditionRunner)
      this.conditionRunner = new ConditionRunner(this.visibleIf);
    this.conditionRunner.expression = this.visibleIf;
    this.conditionRunner.onRunComplete = (res: boolean) => {
      this.visible = res;
    };
    this.conditionRunner.run(values, properties);
  }
  private runEnableIfCondition(
    values: HashTable<any>,
    properties: HashTable<any>
  ) {
    if (!this.enableIf) return;
    if (!this.conditionEnabelRunner)
      this.conditionEnabelRunner = new ConditionRunner(this.enableIf);
    this.conditionEnabelRunner.expression = this.enableIf;
    this.conditionEnabelRunner.onRunComplete = (res: boolean) => {
      this.readOnly = !res;
    };
    this.conditionEnabelRunner.run(values, properties);
  }
  private runRequiredIfCondition(
    values: HashTable<any>,
    properties: HashTable<any>
  ) {
    if (!this.requiredIf) return;
    if (!this.conditionRequiredRunner)
      this.conditionRequiredRunner = new ConditionRunner(this.requiredIf);
    this.conditionRequiredRunner.expression = this.requiredIf;
    this.conditionRequiredRunner.onRunComplete = (res: boolean) => {
      this.isRequired = res;
    };
    this.conditionRequiredRunner.run(values, properties);
  }
  /**
   * The property returns the question number. If question is invisible then it returns empty string.
   * If visibleIndex is 1, then no is 2, or 'B' if survey.questionStartIndex is 'A'.
   * @see SurveyModel.questionStartIndex
   */
  public get no(): string {
    if (!this.hasTitle || this.hideNumber) return "";
    var no = Helpers.getNumberByIndex(this.visibleIndex, this.getStartIndex());
    if (!!this.survey) {
      no = this.survey.getUpdatedQuestionNo(this, no);
    }
    return no;
  }
  protected getStartIndex(): string {
    if (!!this.parent) return this.parent.getQuestionStartIndex();
    if (!!this.survey) return this.survey.questionStartIndex;
    return "";
  }
  public onSurveyLoad() {
    this.fireCallback(this.surveyLoadCallback);
    this.updateValueWithDefaults();
    this.updateDisplayValue();
    this.updateElementCss();
  }
  protected onSetData() {
    super.onSetData();
    this.initDataFromSurvey();
    this.onSurveyValueChanged(this.value);
    this.updateValueWithDefaults();
    this.updateElementCss();
  }
  protected initDataFromSurvey() {
    if (!!this.data) {
      this.updateValueFromSurvey(this.data.getValue(this.getValueName()));
      this.initCommentFromSurvey();
    }
  }
  protected initCommentFromSurvey() {
    if (!!this.data && this.requireUpdateCommentValue) {
      this.updateCommentFromSurvey(this.data.getComment(this.getValueName()));
    } else {
      this.updateCommentFromSurvey("");
    }
  }
  protected runExpression(expression: string): any {
    if (!this.survey || !expression) return undefined;
    return this.survey.runExpression(expression);
  }
  private get questionValue(): any {
    return this.getPropertyValue("value");
  }
  private set questionValue(val: any) {
    this.setPropertyValue("value", val);
  }
  private get questionComment(): string {
    return this.getPropertyValue("comment");
  }
  private set questionComment(val: string) {
    this.setPropertyValue("comment", val);
    this.fireCallback(this.commentChangedCallback);
  }
  /**
   * Get/Set the question value.
   * @see SurveyMode.setValue
   * @see SurveyMode.getValue
   */
  public get value(): any {
    return this.getValueCore();
  }
  public set value(newValue: any) {
    this.setNewValue(newValue);
  }
  /**
   * Clear the question value. It clears the question comment as well.
   */
  public clearValue() {
    this.value = null;
    this.comment = null;
  }
  public unbindValue() {
    this.clearValue();
  }
  public createValueCopy(): any {
    return this.getUnbindValue(this.value);
  }
  protected isEditingSurveyElement(value: any): boolean {
    return Base.isSurveyElement(value);
  }
  protected getUnbindValue(value: any) {
    if (this.isEditingSurveyElement(value)) return value;
    return Helpers.getUnbindValue(value);
  }
  private canClearValueAsInvisible(): boolean {
    if (this.isVisible && this.isParentVisible) return false;
    if (!!this.page && this.page.isStarted) return false;
    if (!this.survey || !this.valueName) return true;
    return !this.survey.hasVisibleQuestionByValueName(this.valueName);
  }
  private get isParentVisible(): boolean {
    var parent = this.parent;
    while (parent) {
      if (!parent.isVisible) return false;
      parent = parent.parent;
    }
    return true;
  }
  public clearValueIfInvisible() {
    if (this.canClearValueAsInvisible()) {
      this.clearValue();
    }
  }
  public get displayValue(): any {
    this.updateDisplayValue();
    return this.getPropertyValue("displayValue", "");
  }
  protected updateDisplayValue(): any {
    if (this.isLoadingFromJson) return;
    this.setPropertyValue("displayValue", this.getDisplayValue(true));
  }
  /**
   * Return the question value as a display text. For example, for dropdown, it would return the item text instead of item value.
   * @param keysAsText Set this value to true, to return key (in matrices questions) as display text as well.
   * @param value use this parameter, if you want to get display value for this value and not question.value. It is undefined by default.
   */
  public getDisplayValue(keysAsText: boolean, value: any = undefined): any {
    if (this.customWidget) {
      var res = this.customWidget.getDisplayValue(this, value);
      if (res) return res;
    }
    value = value == undefined ? this.createValueCopy() : value;
    if (Helpers.isValueEmpty(value)) return "";
    return this.getDisplayValueCore(keysAsText, value);
  }
  protected getDisplayValueCore(keyAsText: boolean, value: any): any {
    return value;
  }
  /**
   * Set the default value to the question. It will be assign to the question on loading the survey from JSON or adding a question to the survey or on setting this property of the value is empty.
   * Please note, this property is hidden for question without input, for example html question.
   */
  public get defaultValue(): any {
    return this.getPropertyValue("defaultValue");
  }
  public set defaultValue(val: any) {
    if (this.isValueExpression(val)) {
      this.defaultValueExpression = val.substr(1);
      return;
    }
    this.setPropertyValue("defaultValue", this.convertDefaultValue(val));
    this.updateValueWithDefaults();
  }
  public get defaultValueExpression(): any {
    return this.getPropertyValue("defaultValueExpression");
  }
  public set defaultValueExpression(val: any) {
    this.setPropertyValue("defaultValueExpression", val);
    this.updateValueWithDefaults();
  }
  /**
   * Returns question answer data as a plain object: with question title, name, value and displayValue.
   * For complex questions (like matrix, etc.) isNode flag is set to true and data contains array of nested objects (rows)
   * set options.includeEmpty to false if you want to skip empty answers
   */
  public getPlainData(
    options: {
      includeEmpty?: boolean;
      includeQuestionTypes?: boolean;
      calculations?: Array<{
        propertyName: string;
      }>;
    } = {
      includeEmpty: true,
      includeQuestionTypes: false,
    }
  ) {
    if (options.includeEmpty || !this.isEmpty()) {
      var questionPlainData = <any>{
        name: this.name,
        title: this.locTitle.renderedHtml,
        value: this.value,
        displayValue: this.displayValue,
        isNode: false,
        getString: (val: any) =>
          typeof val === "object" ? JSON.stringify(val) : val,
      };
      if (options.includeQuestionTypes === true) {
        questionPlainData.questionType = this.getType();
      }
      (options.calculations || []).forEach((calculation) => {
        questionPlainData[calculation.propertyName] = this[
          calculation.propertyName
        ];
      });
      if (this.hasComment) {
        questionPlainData.isNode = true;
        questionPlainData.data = [
          {
            name: 0,
            isComment: true,
            title: "Comment",
            value: settings.commentPrefix,
            displayValue: this.comment,
            getString: (val: any) =>
              typeof val === "object" ? JSON.stringify(val) : val,
            isNode: false,
          },
        ];
      }
      return questionPlainData;
    }
    return undefined;
  }
  /**
   * The correct answer on the question. Set this value if you are doing a quiz.
   * Please note, this property is hidden for question without input, for example html question.
   * @see SurveyModel.correctAnswers
   * @see SurveyModel.inCorrectAnswers
   */
  public get correctAnswer(): any {
    return this.getPropertyValue("correctAnswer");
  }
  public set correctAnswer(val: any) {
    this.setPropertyValue("correctAnswer", this.convertDefaultValue(val));
  }
  protected convertDefaultValue(val: any): any {
    return val;
  }
  /**
   * Returns questions count: 1 for the non-matrix questions and all inner visible questions that has input(s) widgets for question of matrix types.
   * @see getQuizQuestions
   */
  public get quizQuestionCount(): number {
    if (
      this.isVisible &&
      this.hasInput &&
      !Helpers.isValueEmpty(this.correctAnswer)
    )
      return this.getQuizQuestionCount();
    return 0;
  }
  public get correctAnswerCount(): number {
    if (!this.isEmpty() && !this.isValueEmpty(this.correctAnswer))
      return this.getCorrectAnswerCount();
    return 0;
  }
  protected getQuizQuestionCount() {
    return 1;
  }
  protected getCorrectAnswerCount(): number {
    return this.isTwoValueEquals(this.value, this.correctAnswer, true) ? 1 : 0;
  }
  public isAnswerCorrect(): boolean {
    return this.correctAnswerCount == this.quizQuestionCount;
  }
  public updateValueWithDefaults() {
    if (
      this.isLoadingFromJson ||
      (!this.isDesignMode && this.isDefaultValueEmpty())
    )
      return;
    if (!this.isDesignMode && !this.isEmpty()) return;
    if (this.isEmpty() && this.isDefaultValueEmpty()) return;
    if (!!this.survey && this.survey.isClearValueOnHidden && !this.isVisible)
      return;
    this.setDefaultValue();
  }
  getQuestionFromArray(name: string, index: number): IQuestion {
    return null;
  }
  public getDefaultValue(): any {
    return this.defaultValue;
  }
  protected isDefaultValueEmpty(): boolean {
    return !this.defaultValueExpression && this.isValueEmpty(this.defaultValue);
  }
  protected setDefaultValue() {
    this.value = this.getValueAndRunExpression(
      this.getUnbindValue(this.defaultValue),
      this.defaultValueExpression
    );
  }
  protected isValueExpression(val: any) {
    return !!val && typeof val == "string" && val.length > 0 && val[0] == "=";
  }
  protected getValueAndRunExpression(val: any, expression: string) {
    if (!!expression) {
      val = this.runExpression(expression);
    }
    if (!val) return val;
    if (val instanceof Date) {
      val = val.toISOString().slice(0, 10);
    }
    return val;
  }

  /**
   * The question comment value.
   */
  public get comment(): string {
    return this.getQuestionComment();
  }
  public set comment(newValue: string) {
    if (!!newValue) {
      newValue = newValue.toString().trim();
    }
    if (this.comment == newValue) return;
    this.setQuestionComment(newValue);
  }
  protected getQuestionComment(): string {
    return this.questionComment;
  }
  protected setQuestionComment(newValue: string) {
    this.setNewComment(newValue);
  }
  /**
   * Returns true if the question value is empty
   */
  public isEmpty(): boolean {
    return this.isValueEmpty(this.value);
  }
  public get isAnswered(): boolean {
    return this.getPropertyValue("isAnswered");
  }
  public set isAnswered(val: boolean) {
    this.setPropertyValue("isAnswered", val);
  }
  protected updateIsAnswered() {
    this.setPropertyValue("isAnswered", this.getIsAnswered());
  }
  protected getIsAnswered(): boolean {
    return !this.isEmpty();
  }
  /**
   * The list of question validators.
   * Please note, this property is hidden for question without input, for example html question.
   */
  public get validators(): Array<SurveyValidator> {
    return this.getPropertyValue("validators");
  }
  public set validators(val: Array<SurveyValidator>) {
    this.setPropertyValue("validators", val);
  }
  public getValidators(): Array<SurveyValidator> {
    return this.validators;
  }
  public getSupportedValidators(): Array<string> {
    var res: Array<string> = [];
    var className = this.getType();
    while (!!className) {
      var classValidators = (<any>settings.supportedValidators)[className];
      if (!!classValidators) {
        for (var i = classValidators.length - 1; i >= 0; i--) {
          res.splice(0, 0, classValidators[i]);
        }
      }
      var classInfo = Serializer.findClass(className);
      className = classInfo.parentName;
    }
    return res;
  }
  private addSupportedValidators(
    supportedValidators: Array<string>,
    classValidators: Array<string>
  ) {}
  public addConditionObjectsByContext(
    objects: Array<IConditionObject>,
    context: any
  ) {
    objects.push({
      name: this.getValueName(),
      text: this.processedTitle,
      question: this,
    });
  }
  public getConditionJson(operator: string = null, path: string = null): any {
    var json = new JsonObject().toJsonObject(this);
    json["type"] = this.getType();
    return json;
  }
  /**
   * Returns true if there is a validation error(s) in the question.
   * @param fireCallback set it to true to show an error in UI.
   */
  public hasErrors(fireCallback: boolean = true, rec: any = null): boolean {
    var oldHasErrors = this.errors.length > 0;
    var errors = this.checkForErrors(!!rec && rec.isOnValueChanged === true);
    if (fireCallback) {
      if (!!this.survey) {
        this.survey.beforeSettingQuestionErrors(this, errors);
      }
      this.errors = errors;
    }
    this.updateContainsErrors();
    if (oldHasErrors != errors.length > 0) {
      this.updateElementCss();
    }
    if (this.isCollapsed && rec && fireCallback && errors.length > 0) {
      this.expand();
    }
    return errors.length > 0;
  }
  /**
   * Returns the validation errors count.
   */
  public get currentErrorCount(): number {
    return this.errors.length;
  }
  /**
   * Returns the char/string for a required question.
   * @see SurveyModel.requiredText
   */
  public get requiredText(): string {
    return this.survey != null && this.isRequired
      ? this.survey.requiredText
      : "";
  }
  /**
   * Add error into the question error list.
   * @param error
   */
  public addError(error: SurveyError | string) {
    if (!error) return;
    let newError: SurveyError = null;
    if (typeof error === "string" || error instanceof String) {
      newError = new CustomError(<string>error, this.survey);
    } else {
      newError = <SurveyError>error;
    }
    this.errors.push(newError);
  }
  /**
   * Remove a particular error from the question error list.
   * @param error
   */
  public removeError(error: SurveyError) {
    var errors = this.errors;
    var index = errors.indexOf(error);
    if (index !== -1) errors.splice(index, 1);
  }
  private checkForErrors(isOnValueChanged: boolean): Array<SurveyError> {
    var qErrors = new Array<SurveyError>();
    if (this.isVisible && !this.isReadOnly) {
      this.collectErrors(qErrors, isOnValueChanged);
    }
    return qErrors;
  }
  private collectErrors(
    qErrors: Array<SurveyError>,
    isOnValueChanged: boolean
  ) {
    this.onCheckForErrors(qErrors, isOnValueChanged);
    if (qErrors.length > 0 || !this.canRunValidators(isOnValueChanged)) return;
    var errors = this.runValidators();
    if (errors.length > 0) {
      //validators may change the question value.
      qErrors.length = 0;
      for (var i = 0; i < errors.length; i++) {
        qErrors.push(errors[i]);
      }
    }
    if (this.survey && qErrors.length == 0) {
      var error = this.fireSurveyValidation();
      if (error) {
        qErrors.push(error);
      }
    }
  }
  protected canRunValidators(isOnValueChanged: boolean): boolean {
    return true;
  }
  private fireSurveyValidation(): SurveyError {
    if (this.validateValueCallback) return this.validateValueCallback();
    return this.survey ? this.survey.validateQuestion(this) : null;
  }
  protected onCheckForErrors(
    errors: Array<SurveyError>,
    isOnValueChanged: boolean
  ) {
    if (!isOnValueChanged && this.hasRequiredError()) {
      errors.push(new AnswerRequiredError(this.requiredErrorText, this));
    }
  }
  protected hasRequiredError(): boolean {
    return this.isRequired && this.isEmpty();
  }
  private validatorRunner: ValidatorRunner;
  private isRunningValidatorsValue = false;
  public onCompletedAsyncValidators: (hasErrors: boolean) => void;
  public get isRunningValidators(): boolean {
    return this.getIsRunningValidators();
  }
  protected getIsRunningValidators(): boolean {
    return this.isRunningValidatorsValue;
  }
  protected runValidators(): Array<SurveyError> {
    if (!!this.validatorRunner) {
      this.validatorRunner.onAsyncCompleted = null;
    }
    this.validatorRunner = new ValidatorRunner();
    this.isRunningValidatorsValue = true;
    this.validatorRunner.onAsyncCompleted = (errors: Array<SurveyError>) => {
      this.doOnAsyncCompleted(errors);
    };
    return this.validatorRunner.run(this);
  }
  private doOnAsyncCompleted(errors: Array<SurveyError>) {
    for (var i = 0; i < errors.length; i++) {
      this.errors.push(errors[i]);
    }
    this.isRunningValidatorsValue = false;
    this.raiseOnCompletedAsyncValidators();
  }
  protected raiseOnCompletedAsyncValidators() {
    if (!!this.onCompletedAsyncValidators && !this.isRunningValidators) {
      this.onCompletedAsyncValidators(this.getAllErrors().length > 0);
      this.onCompletedAsyncValidators = null;
    }
  }
  private isValueChangedInSurvey = false;
  protected allowNotifyValueChanged = true;
  protected setNewValue(newValue: any) {
    var oldAnswered = this.isAnswered;
    this.setNewValueInData(newValue);
    this.allowNotifyValueChanged && this.onValueChanged();
    if (this.isAnswered != oldAnswered) {
      this.updateElementCss();
    }
  }
  protected locNotificationInData = false;
  protected isTextValue(): boolean {
    return false;
  }
  public get isSurveyInputTextUpdate(): boolean {
    return !!this.survey ? this.survey.isUpdateValueTextOnTyping : false;
  }
  private getDataLocNotification(): any {
    if (this.locNotificationInData) return this.locNotificationInData;
    return this.isInputTextUpdate ? "text" : false;
  }
  public get isInputTextUpdate() {
    return this.isSurveyInputTextUpdate && this.isTextValue();
  }
  protected setNewValueInData(newValue: any) {
    newValue = this.valueToData(newValue);
    if (!this.isValueChangedInSurvey) {
      this.setValueCore(newValue);
    }
  }
  protected getValueCore() {
    return this.questionValue;
  }
  protected setValueCore(newValue: any) {
    this.setQuestionValue(newValue);
    if (this.data != null) {
      this.data.setValue(
        this.getValueName(),
        newValue,
        this.getDataLocNotification(),
        this.allowNotifyValueChanged
      );
    }
  }
  protected valueFromData(val: any): any {
    return val;
  }
  protected valueToData(val: any): any {
    return val;
  }
  protected onValueChanged() {}
  protected setNewComment(newValue: string) {
    this.questionComment = newValue;
    if (this.data != null) {
      this.data.setComment(
        this.getValueName(),
        newValue,
        this.isSurveyInputTextUpdate ? "text" : false
      );
    }
  }
  protected getValidName(name: string): string {
    if (!name) return name;
    return name.trim().replace(/[\{\}]+/g, "");
  }
  //IQuestion
  updateValueFromSurvey(newValue: any) {
    newValue = this.getUnbindValue(newValue);
    this.setQuestionValue(this.valueFromData(newValue));
  }
  updateCommentFromSurvey(newValue: any): any {
    this.questionComment = newValue;
  }
  protected setQuestionValue(newValue: any, updateIsAnswered: boolean = true) {
    this.questionValue = newValue;
    this.allowNotifyValueChanged &&
      this.fireCallback(this.valueChangedCallback);
    if (updateIsAnswered) this.updateIsAnswered();
  }
  onSurveyValueChanged(newValue: any) {
    if (this.isLoadingFromJson) return;
    this.updateDisplayValue();
  }
  public setVisibleIndex(val: number): number {
    if (
      !this.isVisible ||
      (!this.hasTitle && !settings.setQuestionVisibleIndexForHiddenTitle) ||
      (this.hideNumber && !settings.setQuestionVisibleIndexForHiddenNumber)
    ) {
      val = -1;
    }
    this.setPropertyValue("visibleIndex", val);
    return val < 0 ? 0 : 1;
  }
  public removeElement(element: IElement): boolean {
    return false;
  }
  public supportGoNextPageAutomatic() {
    return false;
  }
  public supportGoNextPageError() {
    return true;
  }
  /**
   * Call this function to remove values from the current question, that end-user will not be able to enter.
   * For example the value that doesn't exists in a radigroup/dropdown/checkbox choices or matrix rows/columns.
   */
  public clearIncorrectValues() {}
  public clearOnDeletingContainer() {}
  /**
   * Call this function to clear all errors in the question
   */
  public clearErrors() {
    this.errors = [];
  }
  public clearUnusedValues() {}
  onAnyValueChanged(name: string) {}
  checkBindings(valueName: string, value: any) {
    if (this.bindings.isEmpty() || !this.data) return;
    var props = this.bindings.getPropertiesByValueName(valueName);
    for (var i = 0; i < props.length; i++) {
      this[props[i]] = value;
    }
  }
  //ILocalizableOwner
  locOwner: ILocalizableOwner = null;
  /**
   * Returns the current survey locale
   * @see SurveyModel.locale
   */
  public getLocale(): string {
    return this.survey
      ? (<ILocalizableOwner>(<any>this.survey)).getLocale()
      : this.locOwner
      ? this.locOwner.getLocale()
      : "";
  }
  public getMarkdownHtml(text: string, name: string): string {
    return this.survey
      ? this.survey.getSurveyMarkdownHtml(this, text, name)
      : this.locOwner
      ? this.locOwner.getMarkdownHtml(text, name)
      : null;
  }
  public getProcessedText(text: string): string {
    if (this.textProcessor)
      return this.textProcessor.processText(text, this.useDisplayValuesInTitle);
    if (this.locOwner) return this.locOwner.getProcessedText(text);
    return text;
  }
  public getComponentName(): string {
    return RendererFactory.Instance.getRendererByQuestion(this);
  }

  public getTitleActions(): Array<any> {
    var titleActions = super.getTitleActions()
    this.titleActions = this.survey.getUpdatedQuestionTitleActions(
      this,
      titleActions
    );
    return this.titleActions;
  }

  public isDefaultRendering(): boolean {
    return (
      !!this.customWidget ||
      this.renderAs === "default" ||
      this.getComponentName() === "default"
    );
  }

  @property({ defaultValue: "default" })
  renderAs: string;

  //ISurveyErrorOwner
  getErrorCustomText(text: string, error: SurveyError): string {
    if (!!this.survey) return this.survey.getErrorCustomText(text, error);
    return text;
  }
  //IValidatorOwner
  getValidatorTitle(): string {
    return null;
  }
  get validatedValue(): any {
    return this.value;
  }
  set validatedValue(val: any) {
    this.value = val;
  }
  getAllValues(): any {
    return !!this.data ? this.data.getAllValues() : null;
  }
  public dispose() {}
}
Serializer.addClass("question", [
  "!name",
  {
    name: "state",
    default: "default",
    choices: ["default", "collapsed", "expanded"],
  },
  { name: "visible:switch", default: true },
  { name: "useDisplayValuesInTitle:boolean", default: true, layout: "row" },
  "visibleIf:condition",
  { name: "width" },
  { name: "minWidth", default: settings.minWidth },
  { name: "maxWidth", default: settings.maxWidth },
  { name: "startWithNewLine:boolean", default: true, layout: "row" },
  { name: "indent:number", default: 0, choices: [0, 1, 2, 3], layout: "row" },
  {
    name: "page",
    isSerializable: false,
    visibleIf: function (obj: any) {
      var survey = obj ? obj.survey : null;
      return !survey || survey.pages.length > 1;
    },
    choices: function (obj: any) {
      var survey = obj ? obj.survey : null;
      return survey
        ? survey.pages.map((p: any) => {
            return { value: p.name, text: p.title };
          })
        : [];
    },
  },
  { name: "title:text", serializationProperty: "locTitle", layout: "row" },
  {
    name: "titleLocation",
    default: "default",
    choices: ["default", "top", "bottom", "left", "hidden"],
    layout: "row",
  },
  {
    name: "description:text",
    serializationProperty: "locDescription",
    layout: "row",
  },
  {
    name: "descriptionLocation",
    default: "default",
    choices: ["default", "underInput", "underTitle"],
  },
  {
    name: "hideNumber:boolean",
    dependsOn: "titleLocation",
    visibleIf: function (obj: any) {
      if (!obj) {
        return true;
      }
      if ((<Question>obj).titleLocation === "hidden") {
        return false;
      }
      var parent: PanelModel = obj ? obj.parent : null;
      var numberingAllowedByParent =
        !parent || parent.showQuestionNumbers !== "off";
      if (!numberingAllowedByParent) {
        return false;
      }
      var survey: SurveyModel = obj ? obj.survey : null;
      return (
        !survey ||
        survey.showQuestionNumbers !== "off" ||
        (!!parent && parent.showQuestionNumbers === "onpanel")
      );
    },
  },
  "valueName",
  "enableIf:condition",
  "defaultValue:value",
  {
    name: "defaultValueExpression:expression",
    category: "logic",
  },
  "correctAnswer:value",
  "isRequired:switch",
  "requiredIf:condition",
  {
    name: "requiredErrorText:text",
    serializationProperty: "locRequiredErrorText",
  },
  "readOnly:switch",
  {
    name: "validators:validators",
    baseClassName: "surveyvalidator",
    classNamePart: "validator",
  },
  {
    name: "bindings:bindings",
    serializationProperty: "bindings",
    visibleIf: function (obj: any) {
      return obj.bindings.getNames().length > 0;
    },
  },
  { name: "renderAs", default: "default", visible: false },
  { name: "renderTitleAs", default: "default", visible: false },
]);
Serializer.addAlterNativeClassName("question", "questionbase");


text:
New IO for Ruby
===============
[![Gem
Version](https://badge.fury.io/rb/nio4r.png)](http://rubygems.org/gems/nio4r)
[![Build
Status](https://secure.travis-ci.org/celluloid/nio4r.png?branch=master)](http://travis-ci.org/celluloid/nio4r)
[![Code
Climate](https://codeclimate.com/github/celluloid/nio4r.png)](https://codeclimate.com/github/celluloid/nio4r)
[![Coverage
Status](https://coveralls.io/repos/celluloid/nio4r/badge.png?branch=master)](https://coveralls.io/r/celluloid/nio4r)

When it comes to managing many IO objects on Ruby, there aren't a whole lot of
options. The most powerful API Ruby itself gives you is Kernel.select, and
select is hurting when it comes to performance and in terms of having a nice
API.

Once upon a time Java was a similar mess. They got out of it by adding the
Java NIO API. Java NIO provides a high performance selector API for monitoring
large numbers of file descriptors.

This library aims to incorporate the ideas of Java NIO in Ruby. These are:

* Expose high level interfaces for doing high performance IO, but keep the
  codebase small to encourage multiple implementations on different platforms
* Be as portable as possible, in this case across several Ruby VMs
* Provide inherently thread-safe facilities for working with IO objects

Supported Platforms
-------------------

nio4r is known to work on the following Ruby implementations:

* MRI/YARV 1.8.7, 1.9.2, 1.9.3
* REE (2011.12)
* JRuby 1.6.x (and likely earlier versions too)
* Rubinius 1.x/2.0
* A pure Ruby implementation based on Kernel.select is also provided

Platform notes:

* MRI/YARV and Rubinius implement nio4j with a C extension based on libev,
  which provides a high performance binding to native IO APIs
* JRuby uses a Java extension based on the high performance Java NIO subsystem
* A pure Ruby implementation is also provided for Ruby implementations which
  don't implement the MRI C extension API

Usage
-----

### Selectors

The NIO::Selector class is the main API provided by nio4r. Use it where you
might otherwise use Kernel.select, but want to monitor the same set of IO
objects across multiple select calls rather than having to reregister them
every single time:

```ruby
require 'nio'

selector = NIO::Selector.new
```

To monitor IO objects, attach them to the selector with the NIO::Selector#register
method, monitoring them for read readiness with the :r parameter, write
readiness with the :w parameter, or both with :rw.

```ruby
>> reader, writer = IO.pipe
 => [#<IO:0xf30>, #<IO:0xf34>]
>> monitor = selector.register(reader, :r)
 => #<NIO::Monitor:0xfbc>
```

After registering an IO object with the selector, you'll get a NIO::Monitor
object which you can use for managing how a particular IO object is being
monitored. Monitors will store an arbitrary value of your choice, which
provides an easy way to implement callbacks:

```ruby
>> monitor = selector.register(reader, :r)
 => #<NIO::Monitor:0xfbc>
>> monitor.value = proc { puts "Got some data: #{monitor.io.read_nonblock(4096)}" }
 => #<Proc:0x1000@(irb):4>
```

The main method of importance is NIO::Selector#select, which monitors all
registered IO objects and returns an array of monitors that are ready.

```ruby
>> writer << "Hi there!"
 => #<IO:0x103c>
>> ready = selector.select
 => [#<NIO::Monitor:0xfbc>]
>> ready.each { |m| m.value.call }
Got some data: Hi there!
 => [#<NIO::Monitor:0xfbc>]
```

By default, NIO::Selector#select will block indefinitely until one of the IO
objects being monitored becomes ready. However, you can also pass a timeout to
wait in seconds to NIO::Selector#select just like you can with Kernel.select:

```ruby
ready = selector.select(15) # Wait 15 seconds
```

If a timeout occurs, ready will be nil.

You can avoid allocating an array each time you call NIO::Selector#select by
passing a block to select. The block will be called for each ready monitor
object, with that object passed as an argument. The number of ready monitors
is returned as a Fixnum:

```ruby
>> selector.select { |m| m.value.call }
Got some data: Hi there!
 => 1
```

When you're done monitoring a particular IO object, just deregister it from
the selector:

```ruby
selector.deregister(reader)
```

### Monitors

Monitors provide methods which let you introspect on why a particular IO
object was selected. These methods are not thread safe unless you are holding
the selector lock (i.e. if you're in a block passed to #select). Only use them
if you aren't concerned with thread safety, or you're within a #select
block:

- ***#interests***: what this monitor is interested in (:r, :w, or :rw)
- ***#readiness***: what the monitored IO object is ready for according to the last select operation
- ***#readable?***: was the IO readable last time it was selected?
- ***#writable?***: was the IO writable last time it was selected?

Monitors also support a ***#value*** and ***#value=*** method for storing a
handle to an arbitrary object of your choice (e.g. a proc)

Concurrency
-----------

nio4r provides internal locking to ensure that it's safe to use from multiple
concurrent threads. Only one thread can select on a NIO::Selector at a given
time, and while a thread is selecting other threads are blocked from
registering or deregistering IO objects. Once a pending select has completed,
requests to register/unregister IO objects will be processed.

NIO::Selector#wakeup allows one thread to unblock another thread that's in the
middle of an NIO::Selector#select operation. This lets other threads that need
to communicate immediately with the selector unblock it so it can process
other events that it's not presently selecting on.

What nio4r is not
-----------------

nio4r is not a full-featured event framework like EventMachine or Cool.io.
Instead, nio4r is the sort of thing you might write a library like that on
top of. nio4r provides a minimal API such that individual Ruby implementers
may choose to produce optimized versions for their platform, without having
to maintain a large codebase.

As of the time of writing, the current implementation is (approximately):

* 200 lines of Ruby code
* 700 lines of "custom" C code (not counting libev)
* 400 lines of Java code

nio4r is also not a replacement for Kinder Gentler IO (KGIO), a set of
advanced Ruby IO APIs. At some point in the future nio4r might provide a
cross-platform implementation that uses KGIO on CRubies, and Java NIO on JRuby,
however this is not the case today.

License
-------

Copyright (c) 2011-12 Tony Arcieri. Distributed under the MIT License. See
LICENSE.txt for further details.

Includes libev. Copyright (C)2007-09 Marc Alexander Lehmann. Distributed under
the BSD license. See ext/libev/LICENSE for details.

redpajama_set_name: RedPajamaGithub


text:
#include <linux/export.h>
#include <linux/remoteproc.h>
#include <linux/virtio.h>
#include <linux/virtio_config.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_ring.h>
#include <linux/err.h>
#include <linux/kref.h>
#include <linux/slab.h>

#include "remoteproc_internal.h"

/* kick the remote processor, and let it know which virtqueue to poke at */
static bool rproc_virtio_notify(struct virtqueue *vq)
{
	struct rproc_vring *rvring = vq->priv;
	struct rproc *rproc = rvring->rvdev->rproc;
	int notifyid = rvring->notifyid;

	dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid);

	rproc->ops->kick(rproc, notifyid);
	return true;
}

/**
 * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted
 * @rproc: handle to the remote processor
 * @notifyid: index of the signalled virtqueue (unique per this @rproc)
 *
 * This function should be called by the platform-specific rproc driver,
 * when the remote processor signals that a specific virtqueue has pending
 * messages available.
 *
 * Returns IRQ_NONE if no message was found in the @notifyid virtqueue,
 * and otherwise returns IRQ_HANDLED.
 */
irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid)
{
	struct rproc_vring *rvring;

	dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid);

	rvring = idr_find(&rproc->notifyids, notifyid);
	if (!rvring || !rvring->vq)
		return IRQ_NONE;

	return vring_interrupt(0, rvring->vq);
}
EXPORT_SYMBOL(rproc_vq_interrupt);

static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
				    unsigned id,
				    void (*callback)(struct virtqueue *vq),
				    const char *name)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct rproc *rproc = vdev_to_rproc(vdev);
	struct device *dev = &rproc->dev;
	struct rproc_vring *rvring;
	struct virtqueue *vq;
	void *addr;
	int len, size, ret;

	/* we're temporarily limited to two virtqueues per rvdev */
	if (id >= ARRAY_SIZE(rvdev->vring))
		return ERR_PTR(-EINVAL);

	if (!name)
		return NULL;

	ret = rproc_alloc_vring(rvdev, id);
	if (ret)
		return ERR_PTR(ret);

	rvring = &rvdev->vring[id];
	addr = rvring->va;
	len = rvring->len;

	/* zero vring */
	size = vring_size(len, rvring->align);
	memset(addr, 0, size);

	dev_dbg(dev, "vring%d: va %p qsz %d notifyid %d\n",
					id, addr, len, rvring->notifyid);

	/*
	 * Create the new vq, and tell virtio we're not interested in
	 * the 'weak' smp barriers, since we're talking with a real device.
	 */
	vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, addr,
					rproc_virtio_notify, callback, name);
	if (!vq) {
		dev_err(dev, "vring_new_virtqueue %s failed\n", name);
		rproc_free_vring(rvring);
		return ERR_PTR(-ENOMEM);
	}

	rvring->vq = vq;
	vq->priv = rvring;

	return vq;
}

static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
{
	struct virtqueue *vq, *n;
	struct rproc_vring *rvring;

	list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
		rvring = vq->priv;
		rvring->vq = NULL;
		vring_del_virtqueue(vq);
		rproc_free_vring(rvring);
	}
}

static void rproc_virtio_del_vqs(struct virtio_device *vdev)
{
	struct rproc *rproc = vdev_to_rproc(vdev);

	/* power down the remote processor before deleting vqs */
	rproc_shutdown(rproc);

	__rproc_virtio_del_vqs(vdev);
}

static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
		       struct virtqueue *vqs[],
		       vq_callback_t *callbacks[],
		       const char *names[])
{
	struct rproc *rproc = vdev_to_rproc(vdev);
	int i, ret;

	for (i = 0; i < nvqs; ++i) {
		vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
		if (IS_ERR(vqs[i])) {
			ret = PTR_ERR(vqs[i]);
			goto error;
		}
	}

	/* now that the vqs are all set, boot the remote processor */
	ret = rproc_boot(rproc);
	if (ret) {
		dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret);
		goto error;
	}

	return 0;

error:
	__rproc_virtio_del_vqs(vdev);
	return ret;
}

static u8 rproc_virtio_get_status(struct virtio_device *vdev)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct fw_rsc_vdev *rsc;

	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;

	return rsc->status;
}

static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct fw_rsc_vdev *rsc;

	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;

	rsc->status = status;
	dev_dbg(&vdev->dev, "status: %d\n", status);
}

static void rproc_virtio_reset(struct virtio_device *vdev)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct fw_rsc_vdev *rsc;

	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;

	rsc->status = 0;
	dev_dbg(&vdev->dev, "reset !\n");
}

/* provide the vdev features as retrieved from the firmware */
static u32 rproc_virtio_get_features(struct virtio_device *vdev)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct fw_rsc_vdev *rsc;

	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;

	return rsc->dfeatures;
}

static void rproc_virtio_finalize_features(struct virtio_device *vdev)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct fw_rsc_vdev *rsc;

	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;

	/* Give virtio_ring a chance to accept features */
	vring_transport_features(vdev);

	/*
	 * Remember the finalized features of our vdev, and provide it
	 * to the remote processor once it is powered on.
	 */
	rsc->gfeatures = vdev->features[0];
}

static void rproc_virtio_get(struct virtio_device *vdev, unsigned offset,
							void *buf, unsigned len)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct fw_rsc_vdev *rsc;
	void *cfg;

	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
	cfg = &rsc->vring[rsc->num_of_vrings];

	if (offset + len > rsc->config_len || offset + len < len) {
		dev_err(&vdev->dev, "rproc_virtio_get: access out of bounds\n");
		return;
	}

	memcpy(buf, cfg + offset, len);
}

static void rproc_virtio_set(struct virtio_device *vdev, unsigned offset,
		      const void *buf, unsigned len)
{
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct fw_rsc_vdev *rsc;
	void *cfg;

	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
	cfg = &rsc->vring[rsc->num_of_vrings];

	if (offset + len > rsc->config_len || offset + len < len) {
		dev_err(&vdev->dev, "rproc_virtio_set: access out of bounds\n");
		return;
	}

	memcpy(cfg + offset, buf, len);
}

static const struct virtio_config_ops rproc_virtio_config_ops = {
	.get_features	= rproc_virtio_get_features,
	.finalize_features = rproc_virtio_finalize_features,
	.find_vqs	= rproc_virtio_find_vqs,
	.del_vqs	= rproc_virtio_del_vqs,
	.reset		= rproc_virtio_reset,
	.set_status	= rproc_virtio_set_status,
	.get_status	= rproc_virtio_get_status,
	.get		= rproc_virtio_get,
	.set		= rproc_virtio_set,
};

/*
 * This function is called whenever vdev is released, and is responsible
 * to decrement the remote processor's refcount which was taken when vdev was
 * added.
 *
 * Never call this function directly; it will be called by the driver
 * core when needed.
 */
static void rproc_vdev_release(struct device *dev)
{
	struct virtio_device *vdev = dev_to_virtio(dev);
	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
	struct rproc *rproc = vdev_to_rproc(vdev);

	list_del(&rvdev->node);
	kfree(rvdev);

	put_device(&rproc->dev);
}

/**
 * rproc_add_virtio_dev() - register an rproc-induced virtio device
 * @rvdev: the remote vdev
 *
 * This function registers a virtio device. This vdev's partent is
 * the rproc device.
 *
 * Returns 0 on success or an appropriate error value otherwise.
 */
int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
{
	struct rproc *rproc = rvdev->rproc;
	struct device *dev = &rproc->dev;
	struct virtio_device *vdev = &rvdev->vdev;
	int ret;

	vdev->id.device	= id,
	vdev->config = &rproc_virtio_config_ops,
	vdev->dev.parent = dev;
	vdev->dev.release = rproc_vdev_release;

	/*
	 * We're indirectly making a non-temporary copy of the rproc pointer
	 * here, because drivers probed with this vdev will indirectly
	 * access the wrapping rproc.
	 *
	 * Therefore we must increment the rproc refcount here, and decrement
	 * it _only_ when the vdev is released.
	 */
	get_device(&rproc->dev);

	ret = register_virtio_device(vdev);
	if (ret) {
		put_device(&rproc->dev);
		dev_err(dev, "failed to register vdev: %d\n", ret);
		goto out;
	}

	dev_info(dev, "registered %s (type %d)\n", dev_name(&vdev->dev), id);

out:
	return ret;
}

/**
 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device
 * @rvdev: the remote vdev
 *
 * This function unregisters an existing virtio device.
 */
void rproc_remove_virtio_dev(struct rproc_vdev *rvdev)
{
	unregister_virtio_device(&rvdev->vdev);
}


text:
using System;

using Xamarin.Forms.CustomAttributes;
using System.Threading.Tasks;
using Xamarin.Forms.Internals;

#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
#endif

namespace Xamarin.Forms.Controls
{
	[Preserve (AllMembers = true)]
	[Issue (IssueTracker.Bugzilla, 32615, "OnAppearing is not called on previous page when modal page is popped")]
	public class Bugzilla32615 : TestContentPage // or TestMasterDetailPage, etc ...
	{
		int _counter;
		Label _textField;
		protected override void Init ()
		{
			var btnModal = new Button { AutomationId = "btnModal",  Text = "open",  HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
			btnModal.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Bugzilla32615Page2 ());
			_textField = new Label { AutomationId = "lblCount"};
			var layout = new StackLayout ();
			layout.Children.Add (btnModal);
			layout.Children.Add (_textField);
			// Initialize ui here instead of ctor
			Content = layout;
		}

		protected override void OnAppearing()
		{
			_textField.Text = _counter++.ToString();
		}

		class Bugzilla32615Page2 : ContentPage
		{
			public Bugzilla32615Page2 ()
			{
				var btnPop = new Button { AutomationId = "btnPop",  Text = "pop",  HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
				btnPop.Clicked += async (sender, e) => await Navigation.PopModalAsync ();
				Content = btnPop;
			}

			protected override void OnDisappearing ()
			{
				System.Diagnostics.Debug.WriteLine ("Disappearing Modal");
				base.OnDisappearing ();
			}

			protected override void OnAppearing ()
			{
				System.Diagnostics.Debug.WriteLine ("Appearing Modal");
				base.OnAppearing ();
			}
		}

#if UITEST
		[Test]
		public async void Bugzilla32615Test ()
		{
			RunningApp.Tap (q => q.Marked ("btnModal"));
			RunningApp.Tap (q => q.Marked ("btnPop"));
			await Task.Delay (1000);
			var lbl = RunningApp.WaitForElement (c => c.Marked("lblCount"));
			Assert.AreEqual ("1", lbl [0].Text);
		}
#endif
	}
}


text:
require "spec_helper"

describe Sockit do

  subject { Sockit }

  describe "class" do

    it "should be Sockit" do
      expect(subject).to be Sockit
    end

    it "should have a default config" do
      expect(subject.config.debug).to eq false
      expect(subject.config.username).to eq nil
      expect(subject.config.password).to eq nil
      expect(subject.config.host).to eq nil
      expect(subject.config.port).to eq nil
    end

    it "should report as configured when it is" do
      Sockit.config.version = 5
      Sockit.config.host = "127.0.0.1"
      Sockit.config.port = "1080"

      expect(Sockit.is_configured?).to eq true
    end

    it "should not report as configured when it is not" do
      Sockit.config.version = 5
      Sockit.config.host = "127.0.0.1"
      Sockit.config.port = ""

      expect(Sockit.is_configured?).to eq false
    end

    it "should report as SOCKS v5 when configured as such" do
      Sockit.config.version = 5
      Sockit.config.host = "127.0.0.1"
      Sockit.config.port = "1080"

      expect(Sockit.is_socks_v5?).to eq true
    end

    it "should not report as SOCKS v5 when configured as such" do
      Sockit.config.version = 5
      Sockit.config.host = ""
      Sockit.config.port = "1080"

      expect(Sockit.is_socks_v5?).to eq false
    end

    it "should report as SOCKS v4 when configured as such" do
      Sockit.config.version = 4
      Sockit.config.host = "127.0.0.1"
      Sockit.config.port = "1080"

      expect(Sockit.is_socks_v4?).to eq true
    end

    it "should not report as SOCKS v4 when configured as such" do
      Sockit.config.version = 4
      Sockit.config.host = ""
      Sockit.config.port = "1080"

      expect(Sockit.is_socks_v4?).to eq false
    end

  end

end


text:
package com.delmar.sys.model;

import com.delmar.core.model.CoreModel;

public class UsergroupAccess extends CoreModel{

    private Integer userId;

    private Integer usergroupId;

    private Usergroup usergroup;

    private User user;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public Integer getUsergroupId() {
        return usergroupId;
    }

    public void setUsergroupId(Integer usergroupId) {
        this.usergroupId = usergroupId;
    }

	/**
	 * @return the usergroup
	 */
	public Usergroup getUsergroup() {
		return usergroup;
	}

	/**
	 * @param usergroup the usergroup to set
	 */
	public void setUsergroup(Usergroup usergroup) {
		this.usergroup = usergroup;
	}

	/**
	 * @return the user
	 */
	public User getUser() {
		return user;
	}

	/**
	 * @param user the user to set
	 */
	public void setUser(User user) {
		this.user = user;
	}

}


text:
package com.rocketfuel.sdbc.postgresql.jdbc

import java.sql.{Date, Time, Timestamp}
import java.time._
import java.util.UUID

import com.rocketfuel.sdbc.base.jdbc.Updater
import org.json4s.JValue
import org.json4s.jackson.JsonMethods
import scodec.bits.ByteVector

import scala.reflect.ClassTag
import scala.xml.Node

class UpdatersSpec
  extends PostgreSqlSuite {

  def testUpdate[T](typeName: String)(before: T)(after: T)(implicit ctag: ClassTag[T], updater: Updater[T], converter: Row => T): Unit = {
    test(s"Update ${ctag.runtimeClass.getName}") {implicit connection =>
      Update(s"CREATE TABLE tbl (id serial PRIMARY KEY, v $typeName)").update()

      update"INSERT INTO tbl (v) VALUES ($before)".update()

      for (row <- selectForUpdate"SELECT * FROM tbl".iterator()) {
        row("v") = after
        row.updateRow()
      }

      val maybeValue = Select[T]("SELECT v FROM tbl").option()

      assert(maybeValue.nonEmpty)

      assertResult(Some(after))(maybeValue)
    }
  }

  testUpdate[Long]("int8")(1L)(2L)

  testUpdate[Int]("int4")(1)(2)

  testUpdate[Short]("int2")(1.toShort)(2.toShort)

  testUpdate[Double]("float8")(1.0)(2.0)

  testUpdate[Float]("float4")(1.0F)(2.0F)

  testUpdate[java.lang.Long]("int8")(1L)(2L)

  testUpdate[java.lang.Integer]("int4")(1)(2)

  testUpdate[java.lang.Short]("int2")(1.toShort)(2.toShort)

  testUpdate[java.lang.Double]("float8")(1.0)(2.0)

  testUpdate[java.lang.Float]("float4")(1.0F)(2.0F)

  testUpdate[ByteVector]("bytea")(ByteVector(1, 2, 3))(ByteVector(4, 5, 6))

  testUpdate[BigDecimal]("numeric")(BigDecimal(3))(BigDecimal("500"))

  testUpdate[Timestamp]("timestamp")(new Timestamp(0))(Timestamp.from(Instant.now()))

  testUpdate[Date]("date")(new Date(0))(Date.valueOf(LocalDate.now()))

  testUpdate[Time]("time")(new Time(0))(Time.valueOf(LocalTime.now()))

  testUpdate[Instant]("timestamp")(Instant.ofEpochMilli(0))(Instant.now())

  testUpdate[LocalDate]("date")(LocalDate.ofEpochDay(0))(LocalDate.now())

  testUpdate[LocalTime]("time")(LocalTime.of(0, 0, 0))(LocalTime.now())

  testUpdate[Boolean]("bool")(false)(true)

  testUpdate[String]("text")("hi")("bye")

  testUpdate[UUID]("uuid")(UUID.randomUUID())(UUID.randomUUID())

  testUpdate[Map[String, String]]("hstore")(Map("hi" -> "there"))(Map("bye" -> "now"))

  testUpdate[Node]("xml")()()

  testUpdate[JValue]("json")(JsonMethods.parse("{}"))(JsonMethods.parse("""{"a": 1}"""))

  test(s"Update None") {implicit connection =>
    val before = Some(1)
    val after = None

    Update(s"CREATE TABLE tbl (id serial PRIMARY KEY, v int)").update()

    update"INSERT INTO tbl (v) VALUES ($before)".update()

    for (row <- selectForUpdate"SELECT id, v FROM tbl".iterator()) {
      row("v") = after
      row.updateRow()
    }

    val maybeRow = Select[Option[Int]]("SELECT v FROM tbl").iterator.toStream.headOption

    assert(maybeRow.nonEmpty, "There was a row")

    val maybeValue = maybeRow.get

    assert(maybeValue.isEmpty)
  }

}


text:
package org.camunda.bpm.container.impl.jmx.deployment.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.camunda.bpm.container.impl.deployment.scanning.ClassPathProcessApplicationScanner;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * @author Falko Menge
 * @author Daniel Meyer
 */
@RunWith(Parameterized.class)
public class ClassPathScannerTest {

  private final String url;
  private static ClassPathProcessApplicationScanner scanner;

  @Parameters
  public static List<Object[]> data() {
    return Arrays.asList(new Object[][] {
            { "file:src/test/resources/org/camunda/bpm/container/impl/jmx/deployment/util/ClassPathScannerTest.testScanClassPathWithFiles/" },
            { "file:src/test/resources/org/camunda/bpm/container/impl/jmx/deployment/util/ClassPathScannerTest.testScanClassPathWithFilesRecursive/" },
            { "file:src/test/resources/org/camunda/bpm/container/impl/jmx/deployment/util/ClassPathScannerTest.testScanClassPathWithFilesRecursiveTwoDirectories/" },
            { "file:src/test/resources/org/camunda/bpm/container/impl/jmx/deployment/util/ClassPathScannerTest.testScanClassPathWithAdditionalResourceSuffixes/" },
            { "file:src/test/resources/org/camunda/bpm/container/impl/jmx/deployment/util/ClassPathScannerTest.testScanClassPath.jar" },
            { "file:src/test/resources/org/camunda/bpm/container/impl/jmx/deployment/util/ClassPathScannerTest.testScanClassPathRecursive.jar" },
            { "file:src/test/resources/org/camunda/bpm/container/impl/jmx/deployment/util/ClassPathScannerTest.testScanClassPathRecursiveTwoDirectories.jar" },
    });
  }

  public ClassPathScannerTest(String url) {
    this.url = url;
  }

  @BeforeClass
  public static void setup() {
    scanner = new ClassPathProcessApplicationScanner();
  }

  /**
   * Test method for {@link org.camunda.bpm.container.impl.deployment.scanning.ClassPathProcessApplicationScanner#scanClassPath(java.lang.ClassLoader)}.
   * @throws MalformedURLException
   */
  @Test
  public void testScanClassPath() throws MalformedURLException {

    URLClassLoader classLoader = getClassloader();

    Map<String, byte[]> scanResult = new HashMap<String, byte[]>();

    scanner.scanPaResourceRootPath(classLoader, new URL(url+"/META-INF/processes.xml"), null, scanResult);

    assertTrue("'testDeployProcessArchive.bpmn20.xml' not found", contains(scanResult, "testDeployProcessArchive.bpmn20.xml"));
    assertTrue("'testDeployProcessArchive.png' not found", contains(scanResult, "testDeployProcessArchive.png"));
    if(url.contains("TwoDirectories")) {
      assertEquals(4, scanResult.size());
    } else {
      assertEquals(2, scanResult.size());
    }
  }

  @Test
  public void testScanClassPathWithNonExistingRootPath_relativeToPa() throws MalformedURLException {

    URLClassLoader classLoader = getClassloader();

    Map<String, byte[]> scanResult = new HashMap<String, byte[]>();
    scanner.scanPaResourceRootPath(classLoader, new URL(url+"/META-INF/processes.xml"), "pa:nonexisting", scanResult);

    assertFalse("'testDeployProcessArchive.bpmn20.xml' found", contains(scanResult, "testDeployProcessArchive.bpmn20.xml"));
    assertFalse("'testDeployProcessArchive.png' found", contains(scanResult, "testDeployProcessArchive.png"));
    assertEquals(0, scanResult.size());
  }

  @Test
  public void testScanClassPathWithNonExistingRootPath_nonRelativeToPa() throws MalformedURLException {

    URLClassLoader classLoader = getClassloader();

    Map<String, byte[]> scanResult = new HashMap<String, byte[]>();
    scanner.scanPaResourceRootPath(classLoader, null, "nonexisting", scanResult);

    assertFalse("'testDeployProcessArchive.bpmn20.xml' found", contains(scanResult, "testDeployProcessArchive.bpmn20.xml"));
    assertFalse("'testDeployProcessArchive.png' found", contains(scanResult, "testDeployProcessArchive.png"));
    assertEquals(0, scanResult.size());
  }

  @Test
  public void testScanClassPathWithExistingRootPath_relativeToPa() throws MalformedURLException {

    URLClassLoader classLoader = getClassloader();

    Map<String, byte[]> scanResult = new HashMap<String, byte[]>();
    scanner.scanPaResourceRootPath(classLoader, new URL(url+"/META-INF/processes.xml"), "pa:directory/", scanResult);

    if(url.contains("Recursive")) {
      assertTrue("'testDeployProcessArchive.bpmn20.xml' not found", contains(scanResult, "testDeployProcessArchive.bpmn20.xml"));
      assertTrue("'testDeployProcessArchive.png' not found", contains(scanResult, "testDeployProcessArchive.png"));
      assertEquals(2, scanResult.size());
    } else {
      assertFalse("'testDeployProcessArchive.bpmn20.xml' found", contains(scanResult, "testDeployProcessArchive.bpmn20.xml"));
      assertFalse("'testDeployProcessArchive.png' found", contains(scanResult, "testDeployProcessArchive.png"));
      assertEquals(0, scanResult.size());
    }
  }

  @Test
  public void testScanClassPathWithExistingRootPath_nonRelativeToPa() throws MalformedURLException {

    URLClassLoader classLoader = getClassloader();

    Map<String, byte[]> scanResult = new HashMap<String, byte[]>();
    scanner.scanPaResourceRootPath(classLoader, null, "directory/", scanResult);

    if(url.contains("Recursive")) {
      assertTrue("'testDeployProcessArchive.bpmn20.xml' not found", contains(scanResult, "testDeployProcessArchive.bpmn20.xml"));
      assertTrue("'testDeployProcessArchive.png' not found", contains(scanResult, "testDeployProcessArchive.png"));
      assertEquals(2, scanResult.size());
    } else {
      assertFalse("'testDeployProcessArchive.bpmn20.xml' found", contains(scanResult, "testDeployProcessArchive.bpmn20.xml"));
      assertFalse("'testDeployProcessArchive.png' found", contains(scanResult, "testDeployProcessArchive.png"));
      assertEquals(0, scanResult.size());
    }
  }

  @Test
  public void testScanClassPathWithAdditionalResourceSuffixes() throws MalformedURLException {
    URLClassLoader classLoader = getClassloader();

    String[] additionalResourceSuffixes = new String[] {"py", "rb", "groovy"};

    Map<String, byte[]> scanResult = scanner.findResources(classLoader, null, new URL(url + "/META-INF/processes.xml"), additionalResourceSuffixes);

    if (url.contains("AdditionalResourceSuffixes")) {
      assertEquals(5, scanResult.size());
    }
  }

  private URLClassLoader getClassloader() throws MalformedURLException {
    return new URLClassLoader(new URL[]{new URL(url)});
  }

  private boolean contains(Map<String, byte[]> scanResult, String suffix) {
    for (String string : scanResult.keySet()) {
      if (string.endsWith(suffix)) {
        return true;
      }
    }
    return false;
  }

}


text:
import { registerExamples } from '../register';
import { UISchemaElement } from '@jsonforms/core';

export const schema = {
  type: 'object',
  properties: {
    Level1: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          Level2: {
            type: 'object',
            properties: {
              Level3: {
                type: 'string'
              }
            }
          }
        }
      }
    }
  }
};

export const uischema: UISchemaElement = undefined;

export const data = {};

registerExamples([
  {
    name: '1169',
    label: 'Issue 1169',
    data,
    schema,
    uischema
  }
]);


text:
Symfony2 Application
====================

1) Installing
-------------

    git clone git@github.com:alexbrouwer/s2-zero-app.git

    php composer.phar install

    HTTPDUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1`
    sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX var/cache var/logs
    sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX var/cache var/logs

What's inside?
---------------

Defaults:

  * Twig is the only configured template engine;
  * Doctrine ORM/DBAL is configured;
  * Swiftmailer is configured;
  * Annotations for everything are enabled.
  * Translations are turned on
  * Both REST and 'normal' routes are supported
  * REST data can be serialized to JSON (default) or XML

It comes pre-configured with the following bundles:

  * **FrameworkBundle** - The core Symfony framework bundle
  * [**SensioFrameworkExtraBundle**][1] - Adds several enhancements, including template and routing annotation capability
  * [**DoctrineBundle**][2] - Adds support for the Doctrine ORM
  * [**TwigBundle**][3] - Adds support for the Twig templating engine
  * [**SecurityBundle**][4] - Adds security by integrating Symfony's security component
  * [**SwiftmailerBundle**][5] - Adds support for Swiftmailer, a library for sending emails
  * [**MonologBundle**][6] - Adds support for Monolog, a logging library
  * [**AsseticBundle**][7] - Adds support for Assetic, an asset processing library
  * **WebProfilerBundle** (in dev/test env) - Adds profiling functionality and the web debug toolbar
  * **SensioDistributionBundle** (in dev/test env) - Adds functionality for configuring and working with Symfony distributions
  * [**SensioGeneratorBundle**][8] (in dev/test env) - Adds code generation capabilities
  * [FOSRestBundle][9] - Adds REST API capabilities
  * [BazingaRestExtraBundle][10] - Adds additional features for REST API
  * [JMSSerializerBundle][11] - Adds serialization capabilities
  * [NelmioApiDocBundle][12] - Rest API documentation generation
  * [AlexAsseticExtraBundle][13] - Automatically move assets (not css/js) to a custom folder and adapt css file accordingly
  * [DoctrineFixturesBundle][14] (in dev/test env) - Provides Data fixtures for testing purposes
  * [WebProfilerExtraBundle][15] (in dev/test env) - Adds Routing, Container and Twig to profile toolbar
  * [LuneticsLocaleBundle][16] - Adds locale guessing

[1]:  http://symfony.com/doc/2.4/bundles/SensioFrameworkExtraBundle/index.html
[2]:  http://symfony.com/doc/2.4/book/doctrine.html
[3]:  http://symfony.com/doc/2.4/book/templating.html
[4]:  http://symfony.com/doc/2.4/book/security.html
[5]:  http://symfony.com/doc/2.4/cookbook/email.html
[6]:  http://symfony.com/doc/2.4/cookbook/logging/monolog.html
[7]:  http://symfony.com/doc/2.4/cookbook/assetic/asset_management.html
[8]:  http://symfony.com/doc/2.4/bundles/SensioGeneratorBundle/index.html
[9]:  https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/Resources/doc/index.md
[10]: https://github.com/willdurand/BazingaRestExtraBundle/blob/master/Resources/doc/index.md
[11]: http://jmsyst.com/bundles/JMSSerializerBundle
[12]: https://github.com/nelmio/NelmioApiDocBundle/blob/master/Resources/doc/index.md
[13]: https://github.com/alexandresalome/assetic-extra-bundle
[14]: http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html
[15]: https://github.com/Elao/WebProfilerExtraBundle
[16]: https://github.com/lunetics/LocaleBundle/blob/master/Resources/doc/index.markdown


text:
package eu.riscoss.shared;

public class JDataItem {

	String			id;
	EChunkDataType	type;
	EDataOrigin		origin;
	String			value;
	String			label;
	String			description;

	public String getId() {
		return id;
	}
	public void setId( String id ) {
		this.id = id;
	}
	public EChunkDataType getType() {
		return type;
	}
	public void setType( EChunkDataType type ) {
		this.type = type;
	}
	public EDataOrigin getOrigin() {
		return origin;
	}
	public void setOrigin( EDataOrigin origin ) {
		this.origin = origin;
	}
	public String getValue() {
		return value;
	}
	public void setValue( String value ) {
		this.value = value;
	}
	public String getLabel() {
		return label;
	}
	public void setLabel( String label ) {
		this.label = label;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription( String description ) {
		this.description = description;
	}

}


text:
package org.jbehave.core.reporters;

import java.util.Properties;
import org.jbehave.core.configuration.Keywords;
import org.jbehave.core.reporters.SGRCodes.SGRCode;

import static org.jbehave.core.reporters.SGRCodes.SGRCode.*;
import static org.jbehave.core.steps.StepCreator.PARAMETER_VALUE_END;
import static org.jbehave.core.steps.StepCreator.PARAMETER_VALUE_START;

/**
 * <p>
 * Story reporter that outputs as ANSI-coded text to System.out.
 * Uses {@link SGRCodes} to decorate ConsoleOutput format patterns.
 * </p>
 */
public class ANSIConsoleOutput extends ConsoleOutput {

    private static final char ESCAPE_CHARACTER = (char) 27;
    private static final String SGR_CONTROL = "m";
    private static final String CODE_SEPARATOR = ";";

    private SGRCodes codes = new SGRCodes();

    public ANSIConsoleOutput() {
        super();
    }

    public ANSIConsoleOutput(Keywords keywords) {
        super(keywords);
    }

    public ANSIConsoleOutput(Properties outputPatterns, Keywords keywords, boolean reportFailureTrace) {
        super(outputPatterns, keywords, reportFailureTrace);
    }

    public ANSIConsoleOutput assignCode(String key, SGRCode code) {
        codes.assignCode(key, code);
        return this;
    }

    public ANSIConsoleOutput withCodes(SGRCodes codes) {
        this.codes = codes;
        return this;
    }

    @Override
    protected String format(String key, String defaultPattern, Object... args) {
        String formatted = super.format(key, defaultPattern, args);

        if (codes.hasCode(key)) {
            SGRCode code = codes.getCode(key);
            formatted = escapeCodeFor(code) + highlightParameterValues(formatted, code) + escapeCodeFor(RESET);
        }

        return formatted;
    }

    private String highlightParameterValues(String formatted, SGRCode code) {
        final String valueStart = lookupPattern(PARAMETER_VALUE_START, PARAMETER_VALUE_START);
        final String valueEnd = lookupPattern(PARAMETER_VALUE_END, PARAMETER_VALUE_END);
        return formatted
                .replaceAll(valueStart, escapeCodeFor(highlightCode(), code))
                .replaceAll(valueEnd, escapeCodeFor(RESET, code));
    }

    private SGRCode highlightCode() {
        if (codes.hasCode("highlight")) {
            return codes.getCode("highlight");
        }
        return UNDERLINE;
    }

    private String escapeCodeFor(SGRCode code) {
        return controlSequenceInitiator(code + SGR_CONTROL);
    }

    private String escapeCodeFor(SGRCode first, SGRCode second) {
        return controlSequenceInitiator(first + CODE_SEPARATOR + second + SGR_CONTROL);
    }

    private String controlSequenceInitiator(String code) {
        return ESCAPE_CHARACTER + "[" + code;
    }

}