Pops all {@link Controller}s until the Controller with the passed tag is at the top

@param tag The tag being popped to
@return Whether or not any {@link Controller}s were popped in order to get to the transaction with the passed tag
508696
@UiThread
    public boolean popToTag(@NonNull String tag) {
        ThreadUtils.ensureMainThread();

        return popToTag(tag, null);
    }
1346035
public Set<Tag> getDescendantTags(Tag tag)
    {
        Set<Tag> ancestors = new HashSet<>();
        getDescendantTags(tag, ancestors);
        return ancestors;
    }
1072358
protected function processEndTag(Tag $tag)
	{
		$tagName = $tag->getName();

		if (empty($this->cntOpen[$tagName]))
		{
			// This is an end tag with no start tag
			return;
		}

		/**
		* @var array List of tags need to be closed before given tag
		*/
		$closeTags = [];

		// Iterate through all open tags from last to first to find a match for our tag
		$i = count($this->openTags);
		while (--$i >= 0)
		{
			$openTag = $this->openTags[$i];

			if ($tag->canClose($openTag))
			{
				break;
			}

			$closeTags[] = $openTag;
			++$this->currentFixingCost;
		}

		if ($i < 0)
		{
			// Did not find a matching tag
			$this->logger->debug('Skipping end tag with no start tag', ['tag' => $tag]);

			return;
		}

		// Accumulate flags to determine whether whitespace should be trimmed
		$flags = $tag->getFlags();
		foreach ($closeTags as $openTag)
		{
			$flags |= $openTag->getFlags();
		}
		$ignoreWhitespace = (bool) ($flags & self::RULE_IGNORE_WHITESPACE);

		// Only reopen tags if we haven't exceeded our "fixing" budget
		$keepReopening = (bool) ($this->currentFixingCost < $this->maxFixingCost);

		// Iterate over tags that are being closed, output their end tag and collect tags to be
		// reopened
		$reopenTags = [];
		foreach ($closeTags as $openTag)
		{
			$openTagName = $openTag->getName();

			// Test whether this tag should be reopened automatically
			if ($keepReopening)
			{
				if ($openTag->getFlags() & self::RULE_AUTO_REOPEN)
				{
					$reopenTags[] = $openTag;
				}
				else
				{
					$keepReopening = false;
				}
			}

			// Find the earliest position we can close this open tag
			$tagPos = $tag->getPos();
			if ($ignoreWhitespace)
			{
				$tagPos = $this->getMagicEndPos($tagPos);
			}

			// Output an end tag to close this start tag, then update the context
			$endTag = new Tag(Tag::END_TAG, $openTagName, $tagPos, 0);
			$endTag->setFlags($openTag->getFlags());
			$this->outputTag($endTag);
			$this->popContext();
		}

		// Output our tag, moving the cursor past it, then update the context
		$this->outputTag($tag);
		$this->popContext();

		// If our fixing budget allows it, peek at upcoming tags and remove end tags that would
		// close tags that are already being closed now. Also, filter our list of tags being
		// reopened by removing those that would immediately be closed
		if (!empty($closeTags) && $this->currentFixingCost < $this->maxFixingCost)
		{
			/**
			* @var integer Rightmost position of the portion of text to ignore
			*/
			$ignorePos = $this->pos;

			$i = count($this->tagStack);
			while (--$i >= 0 && ++$this->currentFixingCost < $this->maxFixingCost)
			{
				$upcomingTag = $this->tagStack[$i];

				// Test whether the upcoming tag is positioned at current "ignore" position and it's
				// strictly an end tag (not a start tag or a self-closing tag)
				if ($upcomingTag->getPos() > $ignorePos
				 || $upcomingTag->isStartTag())
				{
					break;
				}

				// Test whether this tag would close any of the tags we're about to reopen
				$j = count($closeTags);

				while (--$j >= 0 && ++$this->currentFixingCost < $this->maxFixingCost)
				{
					if ($upcomingTag->canClose($closeTags[$j]))
					{
						// Remove the tag from the lists and reset the keys
						array_splice($closeTags, $j, 1);

						if (isset($reopenTags[$j]))
						{
							array_splice($reopenTags, $j, 1);
						}

						// Extend the ignored text to cover this tag
						$ignorePos = max(
							$ignorePos,
							$upcomingTag->getPos() + $upcomingTag->getLen()
						);

						break;
					}
				}
			}

			if ($ignorePos > $this->pos)
			{
				/**
				* @todo have a method that takes (pos,len) rather than a Tag
				*/
				$this->outputIgnoreTag(new Tag(Tag::SELF_CLOSING_TAG, 'i', $this->pos, $ignorePos - $this->pos));
			}
		}

		// Re-add tags that need to be reopened, at current cursor position
		foreach ($reopenTags as $startTag)
		{
			$newTag = $this->addCopyTag($startTag, $this->pos, 0);

			// Re-pair the new tag
			$endTag = $startTag->getEndTag();
			if ($endTag)
			{
				$newTag->pairWith($endTag);
			}
		}
	}
503684
public function hasTag($tag)
    {
        if ($this->isTopTag($tag)) {
            return true;
        }

        return isset($this->tags[$tag]) && is_array($this->tags[$tag]);
    }
17286
public void setTags( Collection<String> tags ) {

		synchronized( this.tags ) {
			this.tags.clear();
			if( tags != null )
				this.tags.addAll( tags );
		}
	}
604916
@Override
	public boolean isEmptyElementTag() {
		if (type != START_TAG) {
			throw new KriptonRuntimeException(ILLEGAL_TYPE, true, this.getLineNumber(), this.getColumnNumber(), getPositionDescription(), null);
		}
		return degenerated;
	}
123878
public static Tag getParentTag(Tag tag) {
	Statement p = tag.getParent();
	if (p == null) return null;
	p = p.getParent();
	if (p instanceof Tag) return (Tag) p;
	return null;
    }
1352751
@SuppressWarnings("unchecked")
	public T tag(final String tag) {
		if (this.tags == null) {
			this.tags = new HashSet<>();
		}

		this.tags.add(tag);
		return (T) this;
	}
689787
public <R extends Request<T>> R setTag(Object tag) {
        checkIfActive();
        this.tag = tag;
        return (R) this;
    }
866827
public List<MarcField> getFields(String tag) {
        return marcFields.stream().filter(marcField -> marcField.getTag().equals(tag))
                .collect(Collectors.toList());
    }
793127
public void removeTag(Tag tag) {
    Iterable<Tag> tags = getTags();
    removeAll(tags, singletonList(tag));
    set(PackageMetadata.TAGS, tag);
  }
150893
public boolean hasOneTag(Tag... tags) {
        for(Tag t : tags) {
            if (this.tags.contains(t)) return true;
        }
        return false;
    }
528899
public boolean isUnderTag(String superTagName, String subTagName)
    {
        if (superTagName == null || subTagName == null)
            throw new IllegalArgumentException("Looking for a null tag name.");

        superTagName = Tag.normalizeName(superTagName);
        subTagName = Tag.normalizeName(subTagName);

        if (superTagName.equals(subTagName))
            return false;

        final Tag superTag = this.findTag(superTagName);
        final Tag subTag = this.findTag(subTagName);
        if (subTag == null || superTag == null)
            return false;
        return this.isUnderTag(superTag, subTag);
    }
770886
public static void w(String tag, String msg) {
        if (logger != null && isLoggingEnabled(tag, WARN)) {
            logger.w(tag, msg);
        }
    }
829854
public function addTag(Tag $tag)
    {
        if (!$this->tags->contains($tag)) {
            $this->tags->add($tag);
            return true;
        }
        return false;
    }
647401
private boolean checkRequiredTag(IfdTags metadata, String tagName, int cardinality) {
    return checkRequiredTag(metadata, tagName, cardinality, null);
  }
685341
public static TagModel getSingleParent(TagModel tag)
    {
        final Iterator<TagModel> parents = tag.getDesignatedByTags().iterator();
        if (!parents.hasNext())
            throw new WindupException("Tag is not designated by any tags: " + tag);

        final TagModel maybeOnlyParent = parents.next();

        if (parents.hasNext()) {
            StringBuilder sb = new StringBuilder();
            tag.getDesignatedByTags().iterator().forEachRemaining(x -> sb.append(x).append(", "));
            throw new WindupException(String.format("Tag %s is designated by multiple tags: %s", tag, sb.toString()));
        }

        return maybeOnlyParent;
    }