<commit_before>package org.odfi.wsb.fwapp.views

import com.idyria.osi.vui.html.Html
import com.idyria.osi.vui.html.Head
import com.idyria.osi.vui.html.HTMLNode
import org.w3c.dom.html.HTMLElement
import com.idyria.osi.vui.html.Body
import org.odfi.wsb.fwapp.assets.AssetsManager
import org.odfi.wsb.fwapp.assets.AssetsSource
import scala.collection.mutable.LinkedHashMap

trait LibraryView extends FWappView {

  var libraries = new LinkedHashMap[String, List[(Option[AssetsSource], HTMLNode[HTMLElement, Any]) => Any]]();
  var librariesPlaced = false

  /*def addLibrary(cl: HTMLNode[HTMLElement, Any] => Any) = {
    
  }*/

  def addLibrary(name: String)(cl: (Option[AssetsSource], HTMLNode[HTMLElement, Any]) => Any): Unit = {

    //-- Look for list
    var closures = libraries.get(name) match {
      case Some(lst) => lst
      case None => List()
    }

    //-- Update
    closures = closures :+ cl
    
    //println("Adding CL for: "+name)

    //-- Save
    libraries += (name -> closures)
  }

  def placeLibraries = {

    // Check Libraries
    try {
    this.libraries.foreach {
      case (lib, builders) =>

       // println("Placing: "+lib)
        getAssetsResolver match {
          case Some(resolver) if (resolver.findAssetsSource(lib).isDefined) =>
            builders.foreach(_(Some(resolver.findAssetsSource(lib).get), currentNode))
          case other =>
            builders.foreach(_(None, currentNode))
        }

      /*AssetsManager.findAssetSource(lib) match {
          case Some(source) =>
            builders.foreach(_(Some(source), currentNode))

          case None =>
            builders.foreach(_(None, currentNode))
        }*/
    }
    } catch {
      case e : Throwable => e.printStackTrace()
    }
    librariesPlaced = true
  }

  override def render: HTMLNode[HTMLElement, HTMLNode[HTMLElement, _]] = {

    // Let Main Rendereing Chain happen
    var result = super.render

    //println("Library view main render done:" +result)

    if (!librariesPlaced) {
      // Add Scripts/Stylesheet depending on result
      var (contentNode, targetNode) = result match {

        // HTML: Look for Head; if none; add to result node
        case h: Html[_, _] =>

          var target = h.children.find {
            case n if (classOf[Head[HTMLElement, _]].isInstance(n)) => true
            case _ => false
          } match {
            case Some(head) => head.asInstanceOf[Head[HTMLElement, _]]
            case None =>
              result
          }

          var content = h.children.find {
            case n if (classOf[Body[HTMLElement, _]].isInstance(n)) => true
            case _ => false
          } match {
            case Some(body) => body.asInstanceOf[Body[HTMLElement, _]]
            case None =>
              result
          }

          (content, target)

        // Others: Add to result node
        case _ => (result, result)

      }

      // Add
      // Reverse and add to first nodes
      this.libraries.foreach {

        case (lib, builders) =>

          getAssetsResolver match {
            case Some(resolver) if (resolver.findAssetsSource(lib).isDefined) =>
              builders.foreach(_(Some(resolver.findAssetsSource(lib).get), currentNode))
            case other =>
              builders.foreach(_(None, currentNode))
          }

        /*AssetsManager.findAssetSource(lib) match {
            case Some(source) =>
              builders.foreach(_(Some(source), currentNode))

            case None =>
              builders.foreach(_(None, currentNode))

              onNode(contentNode) {
                "warning" :: div {
                  text(s"Library $lib cannot be provided through assets manager, maybe a configuration is missing")
                }
              }

          }*/
      }
    }
    //  Add scripts to target
    // externalAdd(targetNode)

    /*switchToNode(targetNode, {
      
      stylesheet(new URI(s"${viewPath}/resources/semantic/semantic.min.css".noDoubleSlash)) {

      }
  
      script(new URI(s"${viewPath}/resources/semantic/semantic.min.js".noDoubleSlash)) {

      }
    })*/

    // Return
    result
  }

}<commit_msg>Improved library placement for sub views<commit_after>package org.odfi.wsb.fwapp.views

import com.idyria.osi.vui.html.Html
import com.idyria.osi.vui.html.Head
import com.idyria.osi.vui.html.HTMLNode
import org.w3c.dom.html.HTMLElement
import com.idyria.osi.vui.html.Body
import org.odfi.wsb.fwapp.assets.AssetsManager
import org.odfi.wsb.fwapp.assets.AssetsSource
import scala.collection.mutable.LinkedHashMap
import com.idyria.osi.vui.html.Script
import com.idyria.osi.vui.html.Stylesheet

trait LibraryView extends FWappView {

  var libraries = new LinkedHashMap[String, List[(Option[AssetsSource], HTMLNode[HTMLElement, Any]) => Any]]();
  var librariesPlaced = false
  var librariesPlacedLocation: Option[HTMLNode[HTMLElement, _]] = None

  /*def addLibrary(cl: HTMLNode[HTMLElement, Any] => Any) = {
    
  }*/

  def hasLibrary(name: String) = libraries.keySet.contains(name)

  def addLibrary(name: String)(cl: (Option[AssetsSource], HTMLNode[HTMLElement, Any]) => Any): Unit = {

    //val  targetView = getTopViewOrSelfAs[LibraryView] 
    val targetView = this

    //-- Look for list
    var closures = targetView.libraries.get(name) match {
      case Some(lst) => lst
      case None      => List()
    }

    //-- Update
    closures = closures :+ cl

    //println("Adding CL for: "+name)

    //-- Save
    targetView.libraries += (name -> closures)
  }

  /**
   * If the placement location is defined, remove duplicate scripts and such
   */
  def cleanupLibraries = this.librariesPlacedLocation match {
    case Some(location) =>

      val scriptsAndStyle = location.children.filter {
        case s: Script[_, _]     => s.hasAttribute("src")
        case s: Stylesheet[_, _] => s.hasAttribute("href")
        case other               => false
      }

      // group by location and only keep one of duplicates
      scriptsAndStyle.groupBy {
        case s: Script[_, _]     => s.attribute("src")
        case s: Stylesheet[_, _] => s.attribute("href")
      }.foreach {
        case (loc, nodes) => nodes.drop(1).foreach(_.detach)
      }

    case None =>
  }

  def placeLibraries = {

    librariesPlacedLocation = Some(currentNode)

    // Check Libraries
    try {

      // Real target node cna be local or in the parent's placement location
      ///val realTargetNode = currentNode
      val realTargetNode = getTopView[LibraryView] match {
        case Some(parentLibView) if (parentLibView.librariesPlacedLocation.isDefined) =>
          //println("Found Top View")
          parentLibView.librariesPlacedLocation.get
        case other =>
          currentNode

      }

      //println(s"calling place libraries on: " + realTargetNode.hashCode() + " -> " + currentNode.children.size)

      onNode(realTargetNode) {
        this.libraries.foreach {
          case (lib, builders) =>

            // println("Placing: "+lib)
            getAssetsResolver match {
              case Some(resolver) if (resolver.findAssetsSource(lib).isDefined) =>
                builders.foreach(_(Some(resolver.findAssetsSource(lib).get), realTargetNode))
              case other =>
                builders.foreach(_(None, realTargetNode))
            }

          /*AssetsManager.findAssetSource(lib) match {
          case Some(source) =>
            builders.foreach(_(Some(source), currentNode))

          case None =>
            builders.foreach(_(None, currentNode))
        }*/
        }
      }

      // Cleanup libraries to avoid duplicates
      getTopViewOrSelfAs[LibraryView].cleanupLibraries

    } catch {
      case e: Throwable => e.printStackTrace()
    }
   // println(s"done calling place libraries on: " + currentNode.hashCode() + " -> " + currentNode.children.size)
    librariesPlaced = true
  }

  override def render: HTMLNode[HTMLElement, HTMLNode[HTMLElement, _]] = {

    // Let Main Rendereing Chain happen
    var result = super.render

    //println(s"Library view main render on ${getClass} done: " + result.hashCode())

    if (!librariesPlaced) {

      //println(s"Library view on ${getClass} placing libraries")

      // Add Scripts/Stylesheet depending on result
      var (contentNode, targetNode) = result match {

        // HTML: Look for Head; if none; add to result node
        case h: Html[_, _] =>

          var target = h.children.find {
            case n if (classOf[Head[HTMLElement, _]].isInstance(n)) => true
            case _ => false
          } match {
            case Some(head) => head.asInstanceOf[Head[HTMLElement, _]]
            case None =>
              result
          }

          var content = h.children.find {
            case n if (classOf[Body[HTMLElement, _]].isInstance(n)) => true
            case _ => false
          } match {
            case Some(body) => body.asInstanceOf[Body[HTMLElement, _]]
            case None =>
              result
          }

          (content, target)

        // Others: Add to result node
        case _ => (result, result)

      }

      // Add
      onNode(targetNode) {
        placeLibraries
      }
      /*this.libraries.foreach {

        case (lib, builders) =>

          getAssetsResolver match {
            case Some(resolver) if (resolver.findAssetsSource(lib).isDefined) =>
              builders.foreach(_(Some(resolver.findAssetsSource(lib).get), currentNode))
            case other =>
              builders.foreach(_(None, currentNode))
          }
      }*/
    }

    // Return
    result
  }

}
{'fraction_non_alphanumeric': 0.11783042394014963, 'fraction_numerical': 0.0003117206982543641, 'mean_word_length': 2.1881417687976152, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6611589', 'n_tokens_mistral': 2886, 'n_tokens_neox': 2822, 'n_words': 624}