1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5const EXPORTED_SYMBOLS = ["TagNoun"];
6
7const { MailServices } = ChromeUtils.import(
8  "resource:///modules/MailServices.jsm"
9);
10
11const { Gloda } = ChromeUtils.import("resource:///modules/gloda/Gloda.jsm");
12
13/**
14 * @namespace Tag noun provider.
15 */
16var TagNoun = {
17  name: "tag",
18  clazz: Ci.nsIMsgTag,
19  usesParameter: true,
20  allowsArbitraryAttrs: false,
21  idAttr: "key",
22  _msgTagService: null,
23  _tagMap: null,
24  _tagList: null,
25
26  _init() {
27    this._msgTagService = MailServices.tags;
28    this._updateTagMap();
29  },
30
31  getAllTags() {
32    if (this._tagList == null) {
33      this._updateTagMap();
34    }
35    return this._tagList;
36  },
37
38  _updateTagMap() {
39    this._tagMap = {};
40    let tagArray = (this._tagList = this._msgTagService.getAllTags());
41    for (let iTag = 0; iTag < tagArray.length; iTag++) {
42      let tag = tagArray[iTag];
43      this._tagMap[tag.key] = tag;
44    }
45  },
46
47  comparator(a, b) {
48    if (a == null) {
49      if (b == null) {
50        return 0;
51      }
52      return 1;
53    } else if (b == null) {
54      return -1;
55    }
56    return a.tag.localeCompare(b.tag);
57  },
58  userVisibleString(aTag) {
59    return aTag.tag;
60  },
61
62  // we cannot be an attribute value
63
64  toParamAndValue(aTag) {
65    return [aTag.key, null];
66  },
67  toJSON(aTag) {
68    return aTag.key;
69  },
70  fromJSON(aTagKey, aIgnored) {
71    let tag = this._tagMap.hasOwnProperty(aTagKey)
72      ? this._tagMap[aTagKey]
73      : undefined;
74    // you will note that if a tag is removed, we are unable to aggressively
75    //  deal with this.  we are okay with this, but it would be nice to be able
76    //  to listen to the message tag service to know when we should rebuild.
77    if (tag === undefined && this._msgTagService.isValidKey(aTagKey)) {
78      this._updateTagMap();
79      tag = this._tagMap[aTagKey];
80    }
81    // we intentionally are returning undefined if the tag doesn't exist
82    return tag;
83  },
84  /**
85   * Convenience helper to turn a tag key into a tag name.
86   */
87  getTag(aTagKey) {
88    return this.fromJSON(aTagKey);
89  },
90};
91
92TagNoun._init();
93Gloda.defineNoun(TagNoun, Gloda.NOUN_TAG);
94