<commit_before>package io.udash.properties
package seq

import java.util.UUID

import io.udash.properties.single._
import io.udash.utils.{Registration, SetRegistration}

import scala.collection.mutable

private[properties]
abstract class BaseReadableSeqPropertyFromSingleValue[A, B: ModelValue]
                                                     (origin: ReadableProperty[A], transformer: A => Seq[B])
  extends ReadableSeqProperty[B, ReadableProperty[B]] {

  override val id: UUID = PropertyCreator.newID()
  override protected[properties] def parent: ReadableProperty[_] = null

  protected val structureListeners: mutable.Set[Patch[Property[B]] => Any] = mutable.Set()

  val pc = implicitly[PropertyCreator[B]]
  protected val children = mutable.ListBuffer.empty[Property[B]]

  update(origin.get)
  origin.listen(update)

  private def structureChanged(patch: Patch[Property[B]]): Unit =
    CallbackSequencer.queue(
      s"${this.id.toString}:fireElementsListeners:${patch.hashCode()}",
      () => structureListeners.foreach(_.apply(patch))
    )

  private def update(v: A): Unit = {
    val transformed = transformer(v)
    val current = get

    def commonIdx(s1: Iterator[B], s2: Iterator[B]): Int =
      math.max(0,
        s1.zipAll(s2, null, null).zipWithIndex
          .indexWhere { case (((x, y), idx)) => x != y })

    val commonBegin = commonIdx(transformed.iterator, current.iterator)
    val commonEnd = commonIdx(transformed.reverseIterator, current.reverseIterator)

    val patch = if (transformed.size > current.size) {
      val added: Seq[CastableProperty[B]] = Seq.fill(transformed.size - current.size)(pc.newProperty(this))
      children.insertAll(commonBegin, added)
      Some(Patch(commonBegin, Seq(), added, false))
    } else if (transformed.size < current.size) {
      val removed = children.slice(commonBegin, commonBegin + current.size - transformed.size)
      children.remove(commonBegin, current.size - transformed.size)
      Some(Patch(commonBegin, removed, Seq(), transformed.isEmpty))
    } else None

    CallbackSequencer.sequence {
      transformed.zip(children)
        .slice(commonBegin, math.max(commonBegin + transformed.size - current.size, transformed.size - commonEnd))
        .foreach { case (pv, p) => p.set(pv) }
      patch.foreach(structureChanged)
      valueChanged()
    }
  }

  override def elemProperties: Seq[ReadableProperty[B]] =
    children.map(_.transform((id: B) => id))

  override def get: Seq[B] =
    children.map(_.get)
}

private[properties]
class ReadableSeqPropertyFromSingleValue[A, B: ModelValue](origin: ReadableProperty[A], transformer: A => Seq[B])
  extends BaseReadableSeqPropertyFromSingleValue(origin, transformer) {<commit_msg>Don't expose implicit PropertyCreator in SeqPropertyFromSingleValue.<commit_after>package io.udash.properties
package seq

import java.util.UUID

import io.udash.properties.single._
import io.udash.utils.{Registration, SetRegistration}

import scala.collection.mutable

private[properties]
abstract class BaseReadableSeqPropertyFromSingleValue[A, B: ModelValue]
                                                     (origin: ReadableProperty[A], transformer: A => Seq[B])
  extends ReadableSeqProperty[B, ReadableProperty[B]] {

  override val id: UUID = PropertyCreator.newID()
  override protected[properties] def parent: ReadableProperty[_] = null

  protected val structureListeners: mutable.Set[Patch[Property[B]] => Any] = mutable.Set()
  protected val children = mutable.ListBuffer.empty[Property[B]]

  update(origin.get)
  origin.listen(update)

  private def structureChanged(patch: Patch[Property[B]]): Unit =
    CallbackSequencer.queue(
      s"${this.id.toString}:fireElementsListeners:${patch.hashCode()}",
      () => structureListeners.foreach(_.apply(patch))
    )

  private def update(v: A): Unit = {
    val transformed = transformer(v)
    val current = get

    def commonIdx(s1: Iterator[B], s2: Iterator[B]): Int =
      math.max(0,
        s1.zipAll(s2, null, null).zipWithIndex
          .indexWhere { case (((x, y), idx)) => x != y })

    val commonBegin = commonIdx(transformed.iterator, current.iterator)
    val commonEnd = commonIdx(transformed.reverseIterator, current.reverseIterator)

    val patch = if (transformed.size > current.size) {
      val added: Seq[CastableProperty[B]] = Seq.fill(transformed.size - current.size)(implicitly[PropertyCreator[B]].newProperty(this))
      children.insertAll(commonBegin, added)
      Some(Patch(commonBegin, Seq(), added, false))
    } else if (transformed.size < current.size) {
      val removed = children.slice(commonBegin, commonBegin + current.size - transformed.size)
      children.remove(commonBegin, current.size - transformed.size)
      Some(Patch(commonBegin, removed, Seq(), transformed.isEmpty))
    } else None

    CallbackSequencer.sequence {
      transformed.zip(children)
        .slice(commonBegin, math.max(commonBegin + transformed.size - current.size, transformed.size - commonEnd))
        .foreach { case (pv, p) => p.set(pv) }
      patch.foreach(structureChanged)
      valueChanged()
    }
  }

  override def elemProperties: Seq[ReadableProperty[B]] =
    children.map(_.transform((id: B) => id))

  override def get: Seq[B] =
    children.map(_.get)
}

private[properties]
class ReadableSeqPropertyFromSingleValue[A, B: ModelValue](origin: ReadableProperty[A], transformer: A => Seq[B])
  extends BaseReadableSeqPropertyFromSingleValue(origin, transformer) {
{'fraction_non_alphanumeric': 0.12245269286754003, 'fraction_numerical': 0.001819505094614265, 'mean_word_length': 3.997272727272727, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6651579', 'n_tokens_mistral': 1627, 'n_tokens_neox': 1589, 'n_words': 344}