diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..118f32b
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,9 @@
+version: 2
+updates:
+- package-ecosystem: gradle
+ directory: "/"
+ schedule:
+ interval: daily
+ time: "18:45"
+ timezone: "Europe/Rome"
+ open-pull-requests-limit: 10
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 3e8ce0d..6405921 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,86 @@
+#################
+# Jetbrains IDEs
+#################
+
+
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
#################
## Eclipse
#################
@@ -70,14 +153,12 @@ build/
*.tlb
*.tli
*.tlh
-*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
-*.log
*.scc
# Visual C++ cache files
@@ -196,7 +277,6 @@ $RECYCLE.BIN/
*.egg
*.egg-info
dist/
-build/
eggs/
parts/
var/
@@ -216,3 +296,53 @@ pip-log.txt
#Mr Developer
.mr.developer.cfg
+
+#############
+## Other exclusions from gitignore.io
+#############
+
+# Created by http://gitignore.io
+
+### Linux ###
+.*
+!.gitignore
+!.git*
+
+### OSX ###
+.AppleDouble
+.LSOverride
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+### Java ###
+*.class
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+### Gradle ###
+# Exclude Folder List #
+.gradle/
+
+### Eclipse ###
+bin/**
+tmp/**
+tmp/**/*
+
+### IntelliJ ###
+*.iml
+*.ipr
+
+### SVN ###
+.svn/
+
+/bin
diff --git a/Dockerfile b/Dockerfile
index c420f20..a213e41 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,11 +1,12 @@
-FROM maven:3-jdk-8 AS builder
+FROM openjdk:11-jdk-slim as builder
WORKDIR /app
COPY . /app
-RUN mvn compile war:war
+RUN ./gradlew clean build
-FROM tomcat:7
-LABEL maintainer=adrian.gschwend@zazuko.com
-ENV CATALINA_OPTS="-XX:+UseSerialGC"
-COPY --from=builder /app/target/lodview.war /usr/local/tomcat/webapps/lodview.war
-CMD ["catalina.sh", "run"]
+# Execute container as user.
+FROM openjdk:11-jdk-slim
+LABEL maintainer=g.nespolino@gmail.com
+USER 1001
+COPY --from=builder /app/build/libs/lodview.war /lodview.war
+CMD ["java", "-jar", "/lodview.war"]
EXPOSE 8080 8009
diff --git a/WebContent/META-INF/MANIFEST.MF b/WebContent/META-INF/MANIFEST.MF
deleted file mode 100644
index 254272e..0000000
--- a/WebContent/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Class-Path:
-
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..009fde3
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,100 @@
+plugins {
+ id 'org.springframework.boot' version '2.7.5'
+ id 'io.spring.dependency-management' version '1.1.0'
+ id 'java'
+ id "org.owasp.dependencycheck" version "7.3.0"
+ id 'com.github.spotbugs' version '5.0.13'
+ id 'war'
+}
+
+group = 'it.gov.innovazione'
+version = '0.0.1-SNAPSHOT'
+sourceCompatibility = '11'
+
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation('org.springframework.boot:spring-boot-starter-web') {
+ exclude group: 'org.yaml'
+ }
+
+ providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
+
+ implementation 'org.apache.jena:apache-jena-libs:4.6.1'
+ constraints {
+ implementation ('com.google.protobuf:protobuf-java:3.21.8') {
+ because 'previous versions have security bugs'
+ }
+ }
+
+ implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
+ implementation 'org.apache.commons:commons-text:1.10.0'
+
+ implementation 'org.apache.taglibs:taglibs-standard-spec:1.2.5'
+ implementation 'org.apache.taglibs:taglibs-standard-impl:1.2.5'
+ implementation 'org.apache.taglibs:taglibs-standard-jstlel:1.2.5'
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
+ annotationProcessor 'org.projectlombok:lombok'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+spotbugsMain {
+ excludeFilter = file("${rootProject.projectDir}/config/spotbugs/exclude-filter.xml")
+
+ reports {
+ html {
+ enabled = true
+ destination = file("$buildDir/reports/spotbugs/main/spotbugs.html")
+ }
+ }
+}
+
+spotbugsTest {
+ excludeFilter = file("${rootProject.projectDir}/config/spotbugs/exclude-filter.xml")
+ reports {
+ html {
+ enabled = true
+ destination = file("$buildDir/reports/spotbugs/test/spotbugs.html")
+ }
+ }
+}
+
+dependencyCheck {
+ skipConfigurations = ['spotbugs']
+
+//set up a quality gate for vulnerabilities with high severity level:
+//let's consider that a vulnerability has a high severity level if its CVSS score is higher than 7
+//the build is going to fail if vulnerabilities with high severity level found
+ failBuildOnCVSS = 7
+
+//specify a list of known issues which contain:
+//false-positives
+//confirmed vulnerabilities which are not fixed yet, but we have a ticket for that
+ suppressionFile = 'config/dependency-check/dependency-check-known-issues.xml'
+}
+
+gradle.taskGraph.whenReady { graph ->
+ if (graph.hasTask(build)) {
+ spotbugsMain.enabled = false
+ dependencyCheckAnalyze.enabled = false
+ spotbugsTest.enabled = false
+ }
+}
+
+bootWar {
+ enabled = true
+ archiveName("lodview.war")
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 0000000..9540e2b
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,357 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/dependency-check/dependency-check-known-issues.xml b/config/dependency-check/dependency-check-known-issues.xml
new file mode 100644
index 0000000..6d31793
--- /dev/null
+++ b/config/dependency-check/dependency-check-known-issues.xml
@@ -0,0 +1,9 @@
+
+
+
+
+ CVE-2016-1000027
+
+
diff --git a/config/hooks/copy-precommit-hooks.sh b/config/hooks/copy-precommit-hooks.sh
new file mode 100755
index 0000000..5975c3a
--- /dev/null
+++ b/config/hooks/copy-precommit-hooks.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+echo "Copies pre-commit hooks from config/hooks to .git folder"
+file='.git/hooks/pre-commit'
+
+if [ ! -f "$file" ]
+then
+ echo 'No hooks available. Setting up the hook now..'
+ echo 'Copying pre-commits hook to your git hooks'
+ cp config/hooks/pre-commit .git/hooks
+ chmod +x .git/hooks/pre-commit
+ echo 'Copying Talisman bin to your git hooks'
+ mkdir -p .git/hooks/bin
+ cp config/talisman/talisman .git/hooks/bin/
+
+else
+ echo 'A pre-commit hook already exists. Ensure Talisman check and gradle checks are also part of your pre-commit hook'
+fi
\ No newline at end of file
diff --git a/config/hooks/pre-commit b/config/hooks/pre-commit
new file mode 100644
index 0000000..c0bb3a8
--- /dev/null
+++ b/config/hooks/pre-commit
@@ -0,0 +1,3 @@
+#!/bin/bash
+.git/hooks/bin/talisman --githook pre-commit
+./gradlew checkstyleMain checkstyleTest spotbugsMain spotbugsTest
diff --git a/config/spotbugs/exclude-filter.xml b/config/spotbugs/exclude-filter.xml
new file mode 100644
index 0000000..5b9bdc4
--- /dev/null
+++ b/config/spotbugs/exclude-filter.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/talisman/talisman b/config/talisman/talisman
new file mode 100755
index 0000000..f4dd913
Binary files /dev/null and b/config/talisman/talisman differ
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 0000000..f286bd1
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,20 @@
+#
+# Docker compose to kickstart a development environment
+# based on docker.
+#
+# Start the environment
+#
+# $ docker-compose up -d dev
+# $ docker attach -ti dati-semantic-lodview_dev_1
+#
+version: '3.9'
+services:
+ dev:
+ image: openjdk:11-jdk-slim
+ volumes:
+ - .:/code:z
+ working_dir: /code
+ entrypoint:
+ - /usr/bin/tail
+ - -f
+ - /dev/null
diff --git a/dockerfile-security.rego b/dockerfile-security.rego
new file mode 100644
index 0000000..a125164
--- /dev/null
+++ b/dockerfile-security.rego
@@ -0,0 +1,92 @@
+package main
+
+# Do Not store secrets in ENV variables
+secrets_env = [
+ "passwd",
+ "password",
+ "pass",
+ "secret",
+ "key",
+ "access",
+ "api_key",
+ "apikey",
+ "token",
+ "tkn"
+]
+
+deny[msg] {
+ input[i].Cmd == "env"
+ val := input[i].Value
+ contains(lower(val[_]), secrets_env[_])
+ msg = sprintf("Line %d: Potential secret in ENV key found: %s", [i, val])
+}
+
+# Only use trusted base images
+deny_untrusted_base_image[msg] {
+ input[i].Cmd == "from"
+ val := split(input[i].Value[0], "/")
+ count(val) > 1
+ msg = sprintf("Line %d: use a trusted base image", [i])
+}
+
+# Do not use 'latest' tag for base imagedeny[msg] {
+deny[msg] {
+ input[i].Cmd == "from"
+ val := split(input[i].Value[0], ":")
+ contains(lower(val[1]), "latest")
+ msg = sprintf("Line %d: do not use 'latest' tag for base images", [i])
+}
+
+# Avoid curl bashing
+deny[msg] {
+ input[i].Cmd == "run"
+ val := concat(" ", input[i].Value)
+ matches := regex.find_n("(curl|wget)[^|^>]*[|>]", lower(val), -1)
+ count(matches) > 0
+ msg = sprintf("Line %d: Avoid curl bashing", [i])
+}
+
+# Do not upgrade your system packages
+upgrade_commands = [
+ "apk upgrade",
+ "apt-get upgrade",
+ "dist-upgrade",
+]
+
+deny[msg] {
+ input[i].Cmd == "run"
+ val := concat(" ", input[i].Value)
+ contains(val, upgrade_commands[_])
+ msg = sprintf("Line: %d: Do not upgrade your system packages", [i])
+}
+
+# Do not use ADD if possible
+deny[msg] {
+ input[i].Cmd == "add"
+ msg = sprintf("Line %d: Use COPY instead of ADD", [i])
+}
+
+# Do not root
+any_user {
+ input[i].Cmd == "user"
+ }
+
+deny_root_user[msg] {
+ not any_user
+ msg = "Do not run as root, use USER instead"
+}
+
+# Do not sudo
+deny[msg] {
+ input[i].Cmd == "run"
+ val := concat(" ", input[i].Value)
+ contains(lower(val), "sudo")
+ msg = sprintf("Line %d: Do not use 'sudo' command", [i])
+}
+
+exception[rules] {
+ input[i].Cmd == "from"
+ input[i].Value[0] == "nginxinc/nginx-unprivileged:stable-alpine"
+
+ rules := ["root_user", "untrusted_base_image"]
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..8049c68
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..a69d9cb
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,240 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f127cfd
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,91 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 443a022..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,161 +0,0 @@
-
- 4.0.0
- lodview
- lodview
- 1.2.1-SNAPSHOT
- war
- lodview
- lodview
-
- UTF-8
- 1.7
- 4.2.4.RELEASE
- 1.8.1
- 1.6.1
-
-
-
- org.apache.jena
- apache-jena-libs
- pom
- 2.13.0
-
-
-
-
- org.springframework
- spring-context
- ${org.springframework-version}
-
-
-
- commons-logging
- commons-logging
-
-
-
-
- org.springframework
- spring-webmvc
- ${org.springframework-version}
-
-
-
-
- org.slf4j
- slf4j-api
- 1.7.1
-
-
- org.slf4j
- jcl-over-slf4j
- 1.7.1
-
-
- ch.qos.logback
- logback-classic
- 1.0.7
-
-
-
-
- javax.servlet
- javax.servlet-api
- 3.0.1
- provided
-
-
- javax.servlet.jsp
- jsp-api
- 2.1
- provided
-
-
- javax.servlet.jsp.jstl
- jstl-api
- 1.2
-
-
- javax.servlet
- servlet-api
-
-
-
-
- org.glassfish.web
- jstl-impl
- 1.2
-
-
- javax.servlet
- servlet-api
-
-
-
-
-
-
-
- org.apache.commons
- commons-lang3
- 3.3.1
-
-
- org.springframework.boot
- spring-boot-starter-integration
- 1.1.4.RELEASE
-
-
-
-
- ${project.artifactId}
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 2.3.2
-
- ${java-version}
- ${java-version}
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- install
- install
-
- sources
-
-
-
-
-
- org.apache.tomcat.maven
- tomcat7-maven-plugin
- 2.2
-
-
- org.eclipse.jetty
- jetty-maven-plugin
- 9.2.7.v20150116
-
-
- /${project.artifactId}
-
-
-
-
-
-
-
- io.spring.repo.maven.milestone
- http://repo.spring.io/milestone/
-
- false
-
-
-
-
diff --git a/publiccode.yml b/publiccode.yml
new file mode 100644
index 0000000..b025e73
--- /dev/null
+++ b/publiccode.yml
@@ -0,0 +1,74 @@
+# This repository adheres to the publiccode.yml standard by including this
+# metadata file that makes public software easily discoverable.
+# More info at https://github.com/italia/publiccode.yml
+
+publiccodeYmlVersion: '0.2'
+applicationSuite: NDC
+categories:
+ - data-analytics
+ - data-collection
+ - digital-asset-management
+description:
+ it:
+ features:
+ - viewer
+ genericName: dati-semantic-lodview
+ longDescription: |-
+ Questo repository contiene il visualizzatore di asset semantici
+ (ontologie e vocabolari controllati)
+ per il National Data Catalog for Semantic Interoperability.
+
+ Il viewer è un fork aggiornato di https://github.com/LodLive/LodView/ e
+ visualizza gli asset semantici richiesti interrogando un server SparQL da configurare
+ in fase di deployment.
+
+ Permette inoltre di convertire in JSON-LD ed altri formati le informazioni
+ recuperate da SparQL.
+ shortDescription: Visualizzatore di ontologie e vocabolari per il repository semantico del NDC
+developmentStatus: beta
+intendedAudience:
+ scope:
+ - government
+ - research
+ - science-and-technology
+isBasedOn:
+ - https://github.com/LodLive/LodView/
+it:
+ conforme:
+ gdpr: false
+ lineeGuidaDesign: false
+ misureMinimeSicurezza: false
+ modelloInteroperabilita: true
+ countryExtensionVersion: '0.2'
+ piattaforme:
+ anpr: false
+ cie: false
+ pagopa: false
+ spid: false
+ riuso:
+ codiceIPA: pcm
+legal:
+ license: MIT
+ mainCopyrightOwner: Dipartimento per la Trasformazione Digitale
+ repoOwner: Dipartimento per la Trasformazione Digitale
+localisation:
+ availableLanguages:
+ - en
+ localisationReady: false
+maintenance:
+ contacts:
+ - affiliation: ISTAT
+ email: polizzi@istat.it
+ name: Marco Polizzi
+ contractors:
+ - name: ISTAT
+ until: '2026-12-31'
+ type: contract
+name: LodView
+platforms:
+ - linux
+ - web
+releaseDate: '2021-12-25'
+softwareType: standalone/other
+url: 'https://github.com/teamdigitale/dati-semantic-lodview'
+logo: src/main/resources/static/staticResources/img/logo-footer-lodview.png
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..63a16d7
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'lodview-ng'
diff --git a/src/main/java/it/gov/innovazione/lodviewng/LodviewNgApplication.java b/src/main/java/it/gov/innovazione/lodviewng/LodviewNgApplication.java
new file mode 100644
index 0000000..d37518f
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/LodviewNgApplication.java
@@ -0,0 +1,20 @@
+package it.gov.innovazione.lodviewng;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+@SpringBootApplication
+public class LodviewNgApplication extends SpringBootServletInitializer {
+
+ public static void main(String[] args) {
+ SpringApplication.run(LodviewNgApplication.class, args);
+ }
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
+ return builder.sources(LodviewNgApplication.class);
+ }
+
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/bean/OntologyBean.java b/src/main/java/it/gov/innovazione/lodviewng/bean/OntologyBean.java
new file mode 100644
index 0000000..f7c6f2e
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/bean/OntologyBean.java
@@ -0,0 +1,82 @@
+package it.gov.innovazione.lodviewng.bean;
+
+
+import it.gov.innovazione.lodviewng.utils.ResourceClassPathLoader;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.text.StringEscapeUtils;
+import org.apache.jena.rdf.model.Literal;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.rdf.model.NodeIterator;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.util.FileManager;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.io.File;
+import java.util.List;
+
+@Component
+@Slf4j
+public class OntologyBean {
+
+ private static final String DEFAULT_VALUE = "";
+ @Getter
+ private final Model model = ModelFactory.createDefaultModel();
+ @Value("${lode.ontoDir}")
+ private String ontoDir;
+
+ @PostConstruct
+ void init() {
+ List ontologies = ResourceClassPathLoader.toFiles(ontoDir);
+
+ if (ontologies.isEmpty()) {
+ log.debug("no ontologies found in directory " + ontoDir);
+ return;
+ }
+
+ ontologies.forEach(file -> {
+ if (!file.isDirectory()) {
+ try {
+ log.info("Parsing ontology " + file.getName());
+ log.debug("loading " + file.getCanonicalPath());
+ FileManager.get().readModel(model, file.getAbsolutePath());
+ log.debug("read successfully!");
+ } catch (Exception e) {
+ log.error("error loading " + e.getMessage());
+ }
+ }
+ });
+ }
+
+ public String getValue(String what, String preferredLanguage, String iri) {
+ Resource resource = model.createResource(iri);
+ return getSingleValue(preferredLanguage, resource, "http://www.w3.org/2000/01/rdf-schema#" + what);
+ }
+
+ public String getEscapedValue(String what, String preferredLanguage, String iri) {
+ return StringEscapeUtils.escapeHtml4(getValue(what, preferredLanguage, iri));
+ }
+
+ private String getSingleValue(String preferredLanguage, Resource iri, String prop) {
+ NodeIterator iter = model.listObjectsOfProperty(iri, model.createProperty(prop));
+ String result = DEFAULT_VALUE;
+ boolean betterTitleMatch = false;
+ while (iter.hasNext()) {
+ RDFNode node = iter.nextNode();
+ Literal l = node.asLiteral();
+ if (!betterTitleMatch && (result.equals(DEFAULT_VALUE) || l.getLanguage().equals("en") || l.getLanguage().equals(preferredLanguage))) {
+ if (preferredLanguage.equals(l.getLanguage())) {
+ betterTitleMatch = true;
+ }
+ result = l.getLexicalForm();
+ }
+
+ }
+ return result;
+ }
+
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/bean/PropertyBean.java b/src/main/java/it/gov/innovazione/lodviewng/bean/PropertyBean.java
new file mode 100644
index 0000000..7f57961
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/bean/PropertyBean.java
@@ -0,0 +1,12 @@
+package it.gov.innovazione.lodviewng.bean;
+
+import lombok.Data;
+
+@Data
+public class PropertyBean {
+ private String nsProperty;
+ private String property;
+ private String propertyUrl;
+ private String label = "";
+ private String comment = "";
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/bean/ResultBean.java b/src/main/java/it/gov/innovazione/lodviewng/bean/ResultBean.java
new file mode 100644
index 0000000..2014e28
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/bean/ResultBean.java
@@ -0,0 +1,113 @@
+package it.gov.innovazione.lodviewng.bean;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class ResultBean {
+
+ private String title;
+ private String latitude;
+ private String longitude;
+ private String mainIRI;
+ private PropertyBean descriptionProperty;
+ private PropertyBean typeProperty;
+ private List images;
+ private List linking;
+ private List videos;
+ private List audios;
+ private Map>> literals = new HashMap<>();
+ private Map>> resources = new HashMap<>();
+ private Map>> bnodes = new HashMap<>();
+
+ private void addEle(String iri, TripleBean tripleBean, Map>> ele) {
+ if (ele.get(iri) == null || ele.get(iri).get(tripleBean.getProperty()) == null) {
+ Map> a = ele.get(iri);
+ if (a == null) {
+ a = new LinkedHashMap<>();
+ }
+ List b = new ArrayList<>();
+ b.add(tripleBean);
+ a.put(tripleBean.getProperty(), b);
+ ele.put(iri, a);
+ } else {
+ Map> a = ele.get(iri);
+ List b = a.get(tripleBean.getProperty());
+ b.add(tripleBean);
+ a.put(tripleBean.getProperty(), b);
+ ele.put(iri, a);
+ }
+ }
+
+ private void removeEle(String iri, TripleBean tripleBean, Map>> ele) {
+ if (!(ele.get(iri) == null || ele.get(iri).get(tripleBean.getProperty()) == null)) {
+ Map> a = ele.get(iri);
+ List b = a.get(tripleBean.getProperty());
+ b.remove(tripleBean);
+ a.put(tripleBean.getProperty(), b);
+ ele.put(iri, a);
+ }
+ }
+
+ public void setLiterals(String iri, List localLiterals) {
+ for (TripleBean tripleBean : localLiterals) {
+ addEle(iri, tripleBean, literals);
+ }
+ }
+
+ public void setBnodes(String iri, List localBnodes) {
+ for (TripleBean tripleBean : localBnodes) {
+ addEle(iri, tripleBean, bnodes);
+ }
+ }
+
+ public void setResources(String iri, List localResources) {
+ for (TripleBean tripleBean : localResources) {
+ addEle(iri, tripleBean, resources);
+ }
+ }
+
+ public Map> getResources(String iri) {
+ return resources.get(iri);
+ }
+
+ public Map> getLiterals(String iri) {
+ return literals.get(iri);
+ }
+
+ public Map> getBnodes(String IRI) {
+ return bnodes.get(IRI);
+ }
+
+ public void addBnode(TripleBean tripleBean, String iri) {
+ addEle(iri, tripleBean, bnodes);
+ }
+
+ public void addLiteral(TripleBean tripleBean, String iri) {
+ addEle(iri, tripleBean, literals);
+ }
+
+ public void addResource(TripleBean tripleBean, String iri) {
+ addEle(iri, tripleBean, resources);
+ }
+
+ public void removeBnode(TripleBean tripleBean, String iri) {
+
+ removeEle(iri, tripleBean, bnodes);
+ }
+
+ public void removeLiteral(TripleBean tripleBean, String iri) {
+ removeEle(iri, tripleBean, literals);
+
+ }
+
+ public void removeResource(TripleBean tripleBean, String iri) {
+ removeEle(iri, tripleBean, resources);
+ }
+
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/bean/TripleBean.java b/src/main/java/it/gov/innovazione/lodviewng/bean/TripleBean.java
new file mode 100644
index 0000000..e7ddf1f
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/bean/TripleBean.java
@@ -0,0 +1,18 @@
+package it.gov.innovazione.lodviewng.bean;
+
+import lombok.Data;
+
+@Data
+public class TripleBean {
+ private PropertyBean property;
+ private String nsValue;
+ private String type;
+ private String iri;
+ private String nsIri;
+ private String value;
+ private String dataType;
+ private String nsDataType;
+ private String lang;
+ private String url;
+ private boolean isLocal = false;
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/builder/ResourceBuilder.java b/src/main/java/it/gov/innovazione/lodviewng/builder/ResourceBuilder.java
new file mode 100644
index 0000000..9acd21f
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/builder/ResourceBuilder.java
@@ -0,0 +1,330 @@
+package it.gov.innovazione.lodviewng.builder;
+
+
+import it.gov.innovazione.lodviewng.endpoint.SPARQLEndPoint;
+import it.gov.innovazione.lodviewng.bean.OntologyBean;
+import it.gov.innovazione.lodviewng.bean.ResultBean;
+import it.gov.innovazione.lodviewng.bean.TripleBean;
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import it.gov.innovazione.lodviewng.utils.Misc;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.rdf.model.RDFWriterI;
+import org.apache.jena.riot.Lang;
+import org.springframework.context.MessageSource;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+@NoArgsConstructor
+@AllArgsConstructor
+public class ResourceBuilder {
+
+ public static final String ERROR_NO_CONTENT_NEGOTIATION = "error.noContentNegotiation";
+ public static final String SORRY_BUT_CONTENT_NEGOTIATION_IS_NOT_SUPPORTED_BY_THE_IRI = "sorry but content negotiation is not supported by the IRI";
+ public static final String LITERAL = "literal";
+ public static final String IRI = "iri";
+ public static final String BNODE = "bnode";
+ public static final String SHOW_XML_DECLARATION = "showXMLDeclaration";
+ public static final String RELATIVE_URIS = "relativeURIs";
+ private MessageSource messageSource;
+
+ public ResultBean buildHtmlResource(String iri, Locale locale, ConfigurationBean conf, OntologyBean ontoBean) throws Exception {
+ return buildHtmlResource(iri, locale, conf, ontoBean, false);
+ }
+
+ public ResultBean buildHtmlResource(String iri, Locale locale, ConfigurationBean conf, OntologyBean ontoBean, boolean localMode) throws Exception {
+ ResultBean result = new ResultBean();
+ List videos = new ArrayList<>();
+ List audios = new ArrayList<>();
+ List images = new ArrayList<>();
+ List linking = new ArrayList<>();
+ SPARQLEndPoint se = new SPARQLEndPoint(conf, ontoBean, locale.getLanguage());
+ result.setMainIRI(iri);
+
+ String preferredLanguage = conf.getPreferredLanguage();
+ if (preferredLanguage.equals("auto")) {
+ preferredLanguage = locale.getLanguage();
+ }
+ List triples;
+ if (conf.getEndPointUrl() != null && conf.getEndPointUrl().equals("<>")) {
+ localMode = true;
+ }
+ if (localMode) {
+ /* looking for data via content negotiation */
+ Model m = ModelFactory.createDefaultModel();
+ try {
+ m.read(iri);
+ } catch (Exception e) {
+ throw new Exception(messageSource.getMessage(ERROR_NO_CONTENT_NEGOTIATION, null, SORRY_BUT_CONTENT_NEGOTIATION_IS_NOT_SUPPORTED_BY_THE_IRI, locale));
+ }
+ triples = se.doLocalQuery(m, iri, conf.getDefaultQueries());
+ } else {
+ triples = se.doQuery(iri, conf.getDefaultQueries(), null);
+ }
+ boolean betterTitleMatch = false;
+ boolean betterDescrMatch = false;
+ for (TripleBean tripleBean : triples) {
+
+ if (tripleBean.getIri() == null) {
+ tripleBean.setIri(iri);
+ tripleBean.setNsIri(Misc.toNsResource(tripleBean.getIri(), conf));
+ }
+
+ if (conf.getTitleProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getTitleProperties().contains(tripleBean.getProperty().getProperty())) {
+ if (tripleBean.getIri().equals(iri) && !betterTitleMatch && (result.getTitle() == null || result.getTitle().trim().equals("") || (tripleBean.getLang() != null && (preferredLanguage.equals(tripleBean.getLang()) || tripleBean.getLang().equals("en"))))) {
+ result.setTitle(Misc.stripHTML(tripleBean.getValue()));
+ if (preferredLanguage.equals(tripleBean.getLang())) {
+ betterTitleMatch = true;
+ }
+ }
+ } else if (conf.getDescriptionProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getDescriptionProperties().contains(tripleBean.getProperty().getProperty())) {
+ if (tripleBean.getIri().equals(iri) && !betterDescrMatch && (result.getDescriptionProperty() == null || (tripleBean.getLang() != null && (preferredLanguage.equals(tripleBean.getLang()) || tripleBean.getLang().equals("en"))))) {
+ result.setDescriptionProperty(tripleBean.getProperty());
+ if (preferredLanguage.equals(tripleBean.getLang())) {
+ betterDescrMatch = true;
+ }
+ }
+ } else if (conf.getLatitudeProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getLatitudeProperties().contains(tripleBean.getProperty().getProperty())) {
+ result.setLatitude(tripleBean.getValue());
+ } else if (conf.getLongitudeProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getLongitudeProperties().contains(tripleBean.getProperty().getProperty())) {
+ result.setLongitude(tripleBean.getValue());
+ } else if (conf.getImageProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getImageProperties().contains(tripleBean.getProperty().getProperty())) {
+ images.add(tripleBean.getValue());
+ } else if (conf.getAudioProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getAudioProperties().contains(tripleBean.getProperty().getProperty())) {
+ audios.add(tripleBean.getValue());
+ } else if (conf.getVideoProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getVideoProperties().contains(tripleBean.getProperty().getProperty())) {
+ videos.add(tripleBean.getValue());
+ } else if (conf.getLinkingProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getLinkingProperties().contains(tripleBean.getProperty().getProperty())) {
+ linking.add(tripleBean.getValue());
+ } else if (conf.getTypeProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getTypeProperties().contains(tripleBean.getProperty().getProperty())) {
+ result.setTypeProperty(tripleBean.getProperty());
+ }
+
+ if (tripleBean.getType().equals(IRI)) {
+ tripleBean.setUrl(Misc.toBrowsableUrl(tripleBean.getValue(), conf));
+ tripleBean.setNsValue(Misc.toNsResource(tripleBean.getValue(), conf));
+ if (!tripleBean.getUrl().equals(tripleBean.getValue()) || tripleBean.getValue().startsWith(conf.getPublicUrlPrefix())) {
+ tripleBean.setLocal(true);
+ }
+ result.addResource(tripleBean, tripleBean.getIri());
+ } else if (tripleBean.getType().equals(LITERAL)) {
+ result.addLiteral(tripleBean, tripleBean.getIri());
+ } else if (tripleBean.getType().equals(BNODE)) {
+ result.addBnode(tripleBean, tripleBean.getIri());
+ }
+ }
+
+ result.setImages(images);
+ result.setLinking(linking);
+ result.setVideos(videos);
+ result.setAudios(audios);
+
+ return result;
+ }
+
+ public String buildRDFResource(String iri, String sparql, Lang lang, ConfigurationBean conf) throws Exception {
+ String result;
+ Model model = ModelFactory.createDefaultModel();
+ model.setNsPrefixes(conf.getPrefixes());
+
+ SPARQLEndPoint se = new SPARQLEndPoint(conf, null, null);
+ model = se.extractData(model, iri, sparql, conf.getDefaultRawDataQueries());
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ RDFWriterI rdfWriter = model.getWriter(lang.getName());
+ rdfWriter.setProperty(SHOW_XML_DECLARATION, "true");
+ rdfWriter.setProperty(RELATIVE_URIS, "");
+
+ rdfWriter.write(model, baos, conf.getIRInamespace());
+
+ result = baos.toString(StandardCharsets.UTF_8);
+
+ return result;
+ }
+
+ public String buildRDFResource(String iri, Model m, Lang lang, ConfigurationBean conf) throws Exception {
+ String result;
+ Model model = ModelFactory.createDefaultModel();
+ model.setNsPrefixes(conf.getPrefixes());
+
+ SPARQLEndPoint se = new SPARQLEndPoint(conf, null, null);
+ model = se.extractLocalData(model, iri, m, conf.getDefaultRawDataQueries());
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ RDFWriterI rdfWriter = model.getWriter(lang.getName());
+ rdfWriter.setProperty(SHOW_XML_DECLARATION, "true");
+ rdfWriter.setProperty(RELATIVE_URIS, "");
+
+ rdfWriter.write(model, baos, conf.getIRInamespace());
+ rdfWriter.setProperty(SHOW_XML_DECLARATION, "true");
+ rdfWriter.setProperty(RELATIVE_URIS, "");
+
+ result = baos.toString(StandardCharsets.UTF_8);
+
+ return result;
+ }
+
+ public ResultBean buildPartialHtmlResource(String iri, String[] abouts, Locale locale, ConfigurationBean conf, OntologyBean ontoBean, List filterProperties) {
+
+ SPARQLEndPoint se = new SPARQLEndPoint(conf, ontoBean, locale.getLanguage());
+ ResultBean result = new ResultBean();
+ List literals = new ArrayList<>();
+
+ String preferredLanguage = conf.getPreferredLanguage();
+ if (preferredLanguage.equals("auto")) {
+ preferredLanguage = locale.getLanguage();
+ }
+
+ List triples = new ArrayList<>();
+
+ /*
+ * FIXME: make more distinct queries to avoid length limits, eg
+ * http://dati.camera.it/ocd/assemblea.rdf/a16
+ */
+
+ StringBuilder filter = new StringBuilder();
+ for (String titleProperty : filterProperties) {
+ if (titleProperty.toLowerCase().startsWith("http:")) {
+ filter.append("(?filterProperty = <").append(titleProperty).append(">)");
+ } else {
+ filter.append("(?filterProperty = ").append(titleProperty).append(")");
+ }
+ filter.append(" || ");
+ }
+
+ for (String about : abouts) {
+ List sparqlQueries = new ArrayList<>();
+ sparqlQueries.add(("select distinct ?o " + "{ <" + about + "> ?filterProperty ?o. FILTER (" + filter + "))} ").replaceAll("\\|\\| \\)", ""));
+ try {
+
+ if (conf.getEndPointUrl().equals("<>")) {
+ /* looking for data via content negotiation */
+ Model m = ModelFactory.createDefaultModel();
+ try {
+ m.read(about);
+ } catch (Exception e) {
+ throw new Exception(messageSource.getMessage(ERROR_NO_CONTENT_NEGOTIATION, null, SORRY_BUT_CONTENT_NEGOTIATION_IS_NOT_SUPPORTED_BY_THE_IRI, locale));
+ }
+ triples.addAll(se.doLocalQuery(m, about, sparqlQueries, about));
+ } else {
+ triples.addAll(se.doQuery(null, sparqlQueries, about));
+ }
+
+ } catch (Exception e) {
+ }
+ }
+
+ Map> l = new HashMap<>();
+
+ for (TripleBean tripleBean : triples) {
+ if (tripleBean.getType().equals(LITERAL)) {
+ List al = l.get(tripleBean.getProperty().getProperty());
+ if (al == null) {
+ al = new ArrayList<>();
+ }
+ al.add(tripleBean);
+ l.put(tripleBean.getProperty().getProperty(), al);
+ }
+ }
+
+ for (Map.Entry> about : l.entrySet()) {
+ List al = about.getValue();
+ boolean betterTitleMatch = false;
+ TripleBean title = null;
+ for (TripleBean tripleBean : al) {
+ if (!betterTitleMatch && (title == null || title.getValue() == null || title.getValue().trim().equals("") || preferredLanguage.equals(tripleBean.getLang()) || tripleBean.getLang().equals("en"))) {
+ title = tripleBean;
+ if (preferredLanguage.equals(tripleBean.getLang())) {
+ betterTitleMatch = true;
+ }
+ }
+ }
+ if (title != null) {
+ literals.add(title);
+ }
+ }
+ result.setLiterals(iri, literals);
+ return result;
+ }
+
+ public ResultBean buildHtmlInverseResource(String iri, String property, int start, Locale locale, ConfigurationBean conf, OntologyBean ontoBean) throws Exception {
+ ResultBean result = new ResultBean();
+
+ SPARQLEndPoint se = new SPARQLEndPoint(conf, ontoBean, locale.getLanguage());
+ String preferredLanguage = conf.getPreferredLanguage();
+ if (preferredLanguage.equals("auto")) {
+ preferredLanguage = locale.getLanguage();
+ }
+ if (property == null) {
+ /* counting */
+ List resources = new ArrayList<>();
+ List triples;
+
+ if (conf.getEndPointUrl().equals("<>")) {
+ /* looking for data via content negotiation */
+ Model m = ModelFactory.createDefaultModel();
+ try {
+ m.read(iri);
+ } catch (Exception e) {
+ throw new Exception(messageSource.getMessage(ERROR_NO_CONTENT_NEGOTIATION, null, SORRY_BUT_CONTENT_NEGOTIATION_IS_NOT_SUPPORTED_BY_THE_IRI, locale));
+ }
+ triples = se.doLocalQuery(m, iri, conf.getDefaultInversesCountQueries());
+ } else {
+ triples = se.doQuery(iri, conf.getDefaultInversesCountQueries(), null);
+ }
+
+ for (TripleBean tripleBean : triples) {
+ if (tripleBean.getType().equals(LITERAL)) {
+ resources.add(tripleBean);
+ }
+ }
+
+ result.setResources(iri, resources);
+
+ } else {
+ /* listing */
+ List resources = new ArrayList<>();
+ List triples;
+
+ if (conf.getEndPointUrl().equals("<>")) {
+ /* looking for data via content negotiation */
+ Model m = ModelFactory.createDefaultModel();
+ try {
+ m.read(iri);
+ } catch (Exception e) {
+ throw new Exception(messageSource.getMessage(ERROR_NO_CONTENT_NEGOTIATION, null, SORRY_BUT_CONTENT_NEGOTIATION_IS_NOT_SUPPORTED_BY_THE_IRI, locale));
+ }
+ triples = se.doLocalQuery(m, iri, property, start, conf.getDefaultInversesQueries(), null);
+ } else {
+ triples = se.doQuery(iri, property, start, conf.getDefaultInversesQueries(), null, null);
+ }
+
+ Map controlList = new HashMap<>();
+ for (TripleBean tripleBean : triples) {
+ if (tripleBean.getType().equals(LITERAL)) {
+ if (controlList.get(tripleBean.getProperty().getProperty()) == null || preferredLanguage.equals(tripleBean.getLang())) {
+ controlList.put(tripleBean.getProperty().getProperty(), tripleBean);
+ }
+ }
+ }
+
+ controlList.forEach((ignored, tripleBean) -> resources.add(tripleBean));
+ result.setResources(iri, resources);
+
+ }
+
+ return result;
+ }
+
+ public ResultBean buildHtmlInverseResource(String iri, Locale locale, ConfigurationBean conf, OntologyBean ontoBean) throws Exception {
+ return buildHtmlInverseResource(iri, null, -1, locale, conf, ontoBean);
+ }
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/conf/ConfigurationBean.java b/src/main/java/it/gov/innovazione/lodviewng/conf/ConfigurationBean.java
new file mode 100644
index 0000000..a51e6e4
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/conf/ConfigurationBean.java
@@ -0,0 +1,228 @@
+package it.gov.innovazione.lodviewng.conf;
+
+
+import it.gov.innovazione.lodviewng.utils.ResourceClassPathLoader;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.NodeIterator;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.ResIterator;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.riot.RDFDataMgr;
+import org.springframework.web.context.ServletContextAware;
+
+import javax.servlet.ServletContext;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+@Slf4j
+@Data
+@RequiredArgsConstructor
+public class ConfigurationBean implements ServletContextAware, Cloneable {
+
+ private static final Random RAND = new Random();
+ protected final String confFile;
+ protected Model confModel;
+ protected ServletContext context;
+ private String endPointType;
+ private String redirectionStrategy;
+ private String forceIriEncoding;
+ private String httpRedirectExcludeList;
+ private String homeUrl;
+ private String license;
+ private String httpRedirectSuffix;
+ private String httpRedirectPrefix;
+ private String endPointUrl;
+ private String IRInamespace;
+ private String contentEncoding;
+ private String staticResourceURL;
+ private String preferredLanguage;
+ private String publicUrlPrefix;
+ private String publicUrlSuffix = "";
+ private String authUsername;
+ private String authPassword;
+ private String defaultInverseBehaviour = "collapse";
+ private ColorStrategy colorStrategy = ColorStrategy.RANDOM;
+ private List defaultQueries;
+ private List defaultRawDataQueries;
+ private List defaultInversesQueries;
+ private List defaultInversesTest;
+ private List defaultInversesCountQueries;
+ private List typeProperties;
+ private List audioProperties;
+ private List imageProperties;
+ private List videoProperties;
+ private List linkingProperties;
+ private List titleProperties;
+ private List descriptionProperties;
+ private List longitudeProperties;
+ private List latitudeProperties;
+ private List colorPair;
+ private List skipDomains;
+ private List mainOntologiesPrefixes;
+ private Map colorPairMatcher;
+
+ public ColorStrategy getColorStrategy() {
+ return colorStrategy;
+ }
+
+ public void populateBean() throws Exception {
+ log.debug("Initializing configuration " + confFile);
+
+ confModel = RDFDataMgr.loadModel(ResourceClassPathLoader.toFile("conf/" + confFile).getAbsolutePath());
+
+ endPointUrl = getSingleConfValue("endpoint");
+ endPointType = getSingleConfValue("endpointType", "");
+ authPassword = getSingleConfValue("authPassword");
+ authUsername = getSingleConfValue("authUsername");
+ forceIriEncoding = getSingleConfValue("forceIriEncoding", "auto");
+ redirectionStrategy = getSingleConfValue("redirectionStrategy", "");
+
+ IRInamespace = getSingleConfValue("IRInamespace", "");
+
+ httpRedirectSuffix = getSingleConfValue("httpRedirectSuffix", "");
+ httpRedirectPrefix = getSingleConfValue("httpRedirectPrefix", "");
+ httpRedirectExcludeList = getSingleConfValue("httpRedirectExcludeList", "");
+
+ publicUrlPrefix = getSingleConfValue("publicUrlPrefix", "");
+ publicUrlPrefix = publicUrlPrefix.replaceAll("^(.+/)?auto$", context.getContextPath() + "/");
+
+ contentEncoding = getSingleConfValue("contentEncoding");
+ staticResourceURL = getSingleConfValue("staticResourceURL", "");
+ homeUrl = getSingleConfValue("homeUrl", "/");
+ staticResourceURL = staticResourceURL.replaceAll("^(.+/)?auto$", context.getContextPath() + "/staticResources/");
+
+ preferredLanguage = getSingleConfValue("preferredLanguage");
+
+ typeProperties = getMultiConfValue("typeProperties");
+ titleProperties = getMultiConfValue("titleProperties");
+ descriptionProperties = getMultiConfValue("descriptionProperties");
+ imageProperties = getMultiConfValue("imageProperties");
+ audioProperties = getMultiConfValue("audioProperties");
+ videoProperties = getMultiConfValue("videoProperties");
+ linkingProperties = getMultiConfValue("linkingProperties");
+ longitudeProperties = getMultiConfValue("longitudeProperties");
+ latitudeProperties = getMultiConfValue("latitudeProperties");
+
+ defaultQueries = getMultiConfValue("defaultQueries");
+ defaultRawDataQueries = getMultiConfValue("defaultRawDataQueries");
+
+ defaultInversesQueries = getMultiConfValue("defaultInversesQueries");
+ defaultInversesTest = getMultiConfValue("defaultInversesTest");
+ defaultInversesCountQueries = getMultiConfValue("defaultInversesCountQueries");
+
+ defaultInverseBehaviour = getSingleConfValue("defaultInverseBehaviour", defaultInverseBehaviour);
+ mainOntologiesPrefixes = getMultiConfValue("mainOntologiesPrefixes");
+
+ license = getSingleConfValue("license", "");
+
+ colorPair = getMultiConfValue("colorPair");
+
+ if (colorPair.size() == 1 && colorPair.get(0).startsWith("http://")) {
+ String colorPairSuffix = colorPair.get(0).replace("http://lodview.it/conf#", "");
+ if ("byClass".equals(colorPairSuffix)) {
+ colorStrategy = ColorStrategy.CLASS;
+ } else if ("byPrefix".equals(colorPairSuffix)) {
+ colorStrategy = ColorStrategy.PREFIX;
+ }
+ colorPairMatcher = populateColorPairMatcher();
+ }
+
+ skipDomains = getMultiConfValue("skipDomains");
+ }
+
+ private Map populateColorPairMatcher() {
+ Map result = new HashMap<>();
+ ResIterator iter = confModel.listSubjectsWithProperty(confModel.createProperty(confModel.getNsPrefixURI("conf"), "hasColorPair"));
+ while (iter.hasNext()) {
+ Resource res = iter.next();
+ NodeIterator values = confModel.listObjectsOfProperty(res, confModel.createProperty(confModel.getNsPrefixURI("conf"), "hasColorPair"));
+ if (values.hasNext()) {
+ result.put(res.toString(), values.next().toString());
+ }
+ }
+ return result;
+ }
+
+ private String getSingleConfValue(String prop) {
+ return getSingleConfValue(prop, null);
+ }
+
+ private String getSingleConfValue(String prop, String defaultValue) {
+ String value = System.getenv("LodView" + prop);
+ if (value != null) {
+ return value;
+ }
+ NodeIterator iter = confModel.listObjectsOfProperty(confModel.createProperty(confModel.getNsPrefixURI("conf"), prop));
+ if (iter.hasNext()) {
+ return iter.next().toString();
+ }
+ return defaultValue;
+ }
+
+ private List getMultiConfValue(String prop) {
+ List result = new ArrayList<>();
+ NodeIterator iter = confModel.listObjectsOfProperty(confModel.createProperty(confModel.getNsPrefixURI("conf"), prop));
+ while (iter.hasNext()) {
+ RDFNode node = iter.next();
+ result.add(node.toString());
+ }
+ return result;
+ }
+
+ @Override
+ public void setServletContext(ServletContext arg0) {
+ this.context = arg0;
+ try {
+ populateBean();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public Map getPrefixes() {
+ return confModel.getNsPrefixMap();
+ }
+
+ public String getNsPrefixURI(String prefix) {
+ return confModel.getNsPrefixURI(prefix);
+ }
+
+ public String getNsURIPrefix(String iri) {
+ return confModel.getNsURIPrefix(iri);
+ }
+
+ public String getRandomColorPair() {
+ if (colorStrategy != ColorStrategy.RANDOM) {
+ return "#914848-#7d3e3e";
+ }
+ int randomNum = RAND.nextInt(colorPair.size());
+ return colorPair.get(randomNum);
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error("Something impossible just happened");
+ }
+ }
+
+ public String getForceIriEncoding() {
+ return forceIriEncoding;
+ }
+
+ public String getEndPointType() {
+ return endPointType;
+ }
+
+ public enum ColorStrategy {RANDOM, CLASS, PREFIX}
+
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/conf/ConfigurationBeanConfig.java b/src/main/java/it/gov/innovazione/lodviewng/conf/ConfigurationBeanConfig.java
new file mode 100644
index 0000000..3bbc401
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/conf/ConfigurationBeanConfig.java
@@ -0,0 +1,18 @@
+package it.gov.innovazione.lodviewng.conf;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ConfigurationBeanConfig {
+
+ @Bean
+ public ConfigurationBean conf() {
+ return new ConfigurationBean("conf.ttl");
+ }
+
+ @Bean
+ public ConfigurationBean confLinked() {
+ return new ConfigurationBean("conf-linked.ttl");
+ }
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/controllers/ErrorController.java b/src/main/java/it/gov/innovazione/lodviewng/controllers/ErrorController.java
new file mode 100644
index 0000000..2194d4d
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/controllers/ErrorController.java
@@ -0,0 +1,91 @@
+package it.gov.innovazione.lodviewng.controllers;
+
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+@Controller
+@Slf4j
+@RequiredArgsConstructor
+public class ErrorController {
+
+ public static final String COLOR_PAIR = "colorPair";
+ private final ConfigurationBean conf;
+
+ /* TODO: change the handler to send "error" param to the client */
+ @ResponseStatus(value = HttpStatus.NOT_ACCEPTABLE, reason = "unhandled encoding")
+ @RequestMapping(value = "/406")
+ public String error406(HttpServletResponse res, ModelMap model, @CookieValue(value = COLOR_PAIR) String colorPair) {
+ log.error("not acceptable");
+ model.addAttribute("statusCode", "406");
+ model.addAttribute("conf", conf);
+ colors(colorPair, res, model);
+ res.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
+ return "error";
+ }
+
+ @RequestMapping(value = "/404")
+ public String error404(HttpServletResponse res, ModelMap model, @RequestParam(value = "error", defaultValue = "") String error, @CookieValue(value = COLOR_PAIR, defaultValue = "") String colorPair, @RequestParam(value = "IRI", defaultValue = "") String IRI, @RequestParam(value = "endpoint", defaultValue = "") String endpoint) {
+ log.error("not found " + error + " -- " + IRI + " -- " + endpoint);
+ /* spring bug? */
+ model.addAttribute("IRI", IRI);
+ model.addAttribute("endpoint", endpoint);
+ model.addAttribute("error", error);
+ model.addAttribute("conf", conf);
+ colors(colorPair, res, model);
+ model.addAttribute("statusCode", "404");
+ res.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ return "error";
+ }
+
+ @RequestMapping(value = "/400")
+ public String error400(HttpServletResponse res, ModelMap model, @RequestParam(value = "IRI", defaultValue = "") String IRI, @CookieValue(value = COLOR_PAIR, defaultValue = "") String colorPair) {
+ log.error("error on " + IRI);
+ /* spring bug? */
+ model.addAttribute("IRI", IRI.replaceAll("(http://.+),http://.+", "$1"));
+ model.addAttribute("conf", conf);
+ colors(colorPair, res, model);
+ model.addAttribute("statusCode", "400");
+ res.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
+ return "error";
+ }
+
+ @RequestMapping(value = {"/500", "/error"})
+ public String error500(HttpServletResponse res, ModelMap model, @RequestParam(value = "error", defaultValue = "") String error, @CookieValue(value = COLOR_PAIR, defaultValue = "") String colorPair, @RequestParam(value = "IRI", defaultValue = "") String IRI, @RequestParam(value = "endpoint", defaultValue = "") String endpoint) {
+ log.error("error on " + error + " -- " + IRI + " -- " + endpoint);
+ /* spring bug? */
+ model.addAttribute("IRI", IRI);
+ model.addAttribute("endpoint", endpoint);
+ model.addAttribute("error", error);
+ model.addAttribute("conf", conf);
+ colors(colorPair, res, model);
+ model.addAttribute("statusCode", "500");
+ res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ return "error";
+ }
+
+ private void colors(String colorPair, HttpServletResponse res, ModelMap model) {
+ if (colorPair.equals("")) {
+ colorPair = conf.getRandomColorPair();
+ Cookie c = new Cookie(COLOR_PAIR, colorPair);
+ c.setPath("/");
+ res.addCookie(c);
+ }
+ if (conf != null && conf.getColorPairMatcher() != null && conf.getColorPairMatcher().size() > 0) {
+ model.addAttribute(COLOR_PAIR, conf.getColorPairMatcher().get("http://lodview.it/conf#otherClasses"));
+ } else {
+ model.addAttribute(COLOR_PAIR, colorPair);
+ }
+
+ }
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/controllers/LinkedResourcesController.java b/src/main/java/it/gov/innovazione/lodviewng/controllers/LinkedResourcesController.java
new file mode 100644
index 0000000..a0340bb
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/controllers/LinkedResourcesController.java
@@ -0,0 +1,134 @@
+package it.gov.innovazione.lodviewng.controllers;
+
+import it.gov.innovazione.lodviewng.builder.ResourceBuilder;
+import it.gov.innovazione.lodviewng.bean.OntologyBean;
+import it.gov.innovazione.lodviewng.bean.PropertyBean;
+import it.gov.innovazione.lodviewng.bean.ResultBean;
+import it.gov.innovazione.lodviewng.bean.TripleBean;
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import it.gov.innovazione.lodviewng.utils.Misc;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.MessageSource;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.commons.text.StringEscapeUtils.escapeHtml4;
+import static org.apache.commons.text.StringEscapeUtils.escapeXml11;
+
+@Controller
+@RequiredArgsConstructor
+@Slf4j
+public class LinkedResourcesController {
+
+ public static final String ERROR_LINKED_RESOURCE_UNAVAILABLE = "error.linkedResourceUnavailable";
+ public static final String UNABLE_TO_RETRIEVE_DATA = "unable to retrieve data";
+ public static final String ROOT = "";
+ public static final String RESOURCE_ABOUT = "\n");
+ try {
+ ResultBean results = new ResourceBuilder(messageSource).buildPartialHtmlResource(IRI, abouts, locale, conf, null, conf.getTitleProperties());
+ Map> literals = results.getLiterals(IRI);
+ if (literals == null || literals.size() == 0) {
+ return ("" + messageSource.getMessage("error.noLiteral", null, "no literal values where found", locale) + " ");
+ }
+ for (Map.Entry> literal : literals.entrySet()) {
+ for (TripleBean tripleBean : literal.getValue()) {
+ result.append(RESOURCE_ABOUT)
+ .append(escapeXml11(tripleBean.getProperty().getProperty()))
+ .append(NSABOUT)
+ .append(escapeXml11(tripleBean.getProperty().getNsProperty()))
+ .append("\"> \n");
+ }
+ }
+ result.append(ROOT);
+ return result.toString();
+ } catch (Exception e) {
+ // 404?
+ return ("" + messageSource.getMessage(ERROR_LINKED_RESOURCE_UNAVAILABLE, null, UNABLE_TO_RETRIEVE_DATA, locale) + " " + e.getMessage() + " ");
+ }
+ }
+
+ @ResponseBody
+ @RequestMapping(value = "/linkedResourceInverses", produces = "application/xml;charset=UTF-8")
+ public String resourceInversesController(ModelMap model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "IRI") String IRI, @RequestParam(value = "property", defaultValue = "") String property, @RequestParam(value = "start", defaultValue = "-1") int start) throws Exception {
+ return resourceInverses(model, conf, ontoBean, req, res, locale, IRI, property, start);
+ }
+
+ public String resourceInverses(ModelMap model, ConfigurationBean conf, OntologyBean ontoBean, HttpServletRequest req, HttpServletResponse res, Locale locale, String IRI, String property, int start) throws Exception {
+ StringBuilder result = new StringBuilder("\n");
+ if (property.equals("")) {
+ try {
+ ResultBean results = new ResourceBuilder(messageSource).buildHtmlInverseResource(IRI, locale, conf, ontoBean);
+ Map> resources = results.getResources(IRI);
+ if (resources != null) {
+ for (Map.Entry> resource : resources.entrySet()) {
+ for (TripleBean tripleBean : resource.getValue()) {
+ if (tripleBean.getProperty().getProperty() == null || tripleBean.getProperty().getProperty().equals("")) {
+ throw new Exception("no content");
+ }
+ result.append(RESOURCE_ABOUT).append(escapeXml11(tripleBean.getProperty().getProperty()))
+ .append(NSABOUT).append(escapeXml11(tripleBean.getProperty().getNsProperty()))
+ .append("\" propertyurl=\"").append(escapeXml11(tripleBean.getProperty().getPropertyUrl()))
+ .append("\" propertylabel=\"").append(escapeXml11(Misc.stripHTML(tripleBean.getProperty().getLabel())))
+ .append("\" propertycomment=\"").append(escapeXml11(tripleBean.getProperty().getComment()))
+ .append("\" > \n");
+ }
+ }
+ }
+
+ result.append(ROOT);
+ return result.toString();
+
+ } catch (Exception e) {
+ return ("" + messageSource.getMessage(ERROR_LINKED_RESOURCE_UNAVAILABLE, null, UNABLE_TO_RETRIEVE_DATA, locale) + " " + e.getMessage() + " ");
+ }
+ } else {
+
+ /* retrieving inverse relations */
+ try {
+ ResultBean results = new ResourceBuilder(messageSource).buildHtmlInverseResource(IRI, property, start, locale, conf, null);
+ Map> resources = results.getResources(IRI);
+ for (Map.Entry> resource : resources.entrySet()) {
+ for (TripleBean tripleBean : resource.getValue()) {
+ result.append(RESOURCE_ABOUT).append(escapeXml11(tripleBean.getProperty().getProperty()))
+ .append(NSABOUT).append(escapeXml11(tripleBean.getProperty().getNsProperty()))
+ .append("\" propertyurl=\"").append(escapeXml11(tripleBean.getProperty().getPropertyUrl()))
+ .append("\" >\n");
+ }
+ }
+
+ result.append(ROOT);
+ return result.toString();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return ("" + messageSource.getMessage(ERROR_LINKED_RESOURCE_UNAVAILABLE, null, UNABLE_TO_RETRIEVE_DATA, locale) + " ");
+ }
+ }
+ }
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/controllers/LodController.java b/src/main/java/it/gov/innovazione/lodviewng/controllers/LodController.java
new file mode 100644
index 0000000..b0eed32
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/controllers/LodController.java
@@ -0,0 +1,91 @@
+package it.gov.innovazione.lodviewng.controllers;
+
+import it.gov.innovazione.lodviewng.bean.ResultBean;
+import it.gov.innovazione.lodviewng.bean.TripleBean;
+import it.gov.innovazione.lodviewng.builder.ResourceBuilder;
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.text.StringEscapeUtils;
+import org.springframework.context.MessageSource;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.Locale;
+
+@Controller
+@RequiredArgsConstructor
+@Slf4j
+public class LodController {
+
+ public static final String LOD_CONTROLLER_RESOURCE_LOAD = " LodController.resource() - load - ";
+ private final ConfigurationBean confLinked;
+ private final MessageSource messageSource;
+
+
+ @ResponseBody
+ @RequestMapping(value = {"/linkedResource", "/lodview/linkedResource"}, produces = "application/xml;charset=UTF-8")
+ public String resource(HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "IRI") String IRI) throws Exception {
+
+ if (confLinked.getSkipDomains().contains(IRI.replaceAll("http[s]*://([^/]+)/.*", "$1"))) {
+ return "" + //
+ StringEscapeUtils.escapeXml11(messageSource.getMessage("error.skipedDomain", null, "skiping this URI", locale)) + //
+ " ";
+ }
+ try {
+ log.info(LOD_CONTROLLER_RESOURCE_LOAD + IRI);
+
+ ResultBean results = new ResourceBuilder(messageSource).buildHtmlResource(IRI, locale, confLinked, null, true);
+
+ StringBuilder result = new StringBuilder("\n");
+
+ result.append(" ");
+
+ String lang = locale.getLanguage().toLowerCase();
+ String descr = "";
+ List descrProperties = results.getLiterals(IRI).get(results.getDescriptionProperty());
+ if (descrProperties != null) {
+ for (TripleBean tripleBean : descrProperties) {
+ if (lang.equals(tripleBean.getLang())) {
+ descr = tripleBean.getValue();
+ lang = tripleBean.getLang();
+ break;
+ } else if (tripleBean.getLang().equals("en")) {
+ lang = tripleBean.getLang();
+ descr = tripleBean.getValue();
+ } else if (descr.equals("")) {
+ descr = tripleBean.getValue();
+ lang = tripleBean.getLang();
+ }
+ }
+ }
+
+ result.append(" ");
+
+ for (String img : results.getImages()) {
+ result.append(" ");
+ }
+ for (String link : results.getLinking()) {
+ result.append(" ");
+ }
+ result.append(" ");
+ result.append(" ");
+ result.append(" ");
+
+ result.append(" ");
+ return result.toString();
+
+ } catch (Exception e) {
+ // e.printStackTrace();
+ log.error(IRI + " unable to retrieve data " + e.getMessage());
+ return "" + //
+ messageSource.getMessage("error.linkedResourceUnavailable", null, "unable to retrieve data", locale) + //
+ " ";
+ }
+ }
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/controllers/ResourceController.java b/src/main/java/it/gov/innovazione/lodviewng/controllers/ResourceController.java
new file mode 100644
index 0000000..be11262
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/controllers/ResourceController.java
@@ -0,0 +1,394 @@
+package it.gov.innovazione.lodviewng.controllers;
+
+import it.gov.innovazione.lodviewng.bean.OntologyBean;
+import it.gov.innovazione.lodviewng.bean.ResultBean;
+import it.gov.innovazione.lodviewng.bean.TripleBean;
+import it.gov.innovazione.lodviewng.builder.ResourceBuilder;
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import it.gov.innovazione.lodviewng.utils.Misc;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jena.atlas.web.AcceptList;
+import org.apache.jena.atlas.web.MediaType;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFLanguages;
+import org.springframework.context.MessageSource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.view.RedirectView;
+import org.springframework.web.util.UrlPathHelper;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+
+@Controller
+@RequestMapping(value = "/")
+@RequiredArgsConstructor
+@Slf4j
+public class ResourceController {
+
+ final AcceptList offeringRDF = new AcceptList("text/turtle, application/turtle, " //
+ + "application/x-turtle, application/rdf+xml, " //
+ + "application/rdf+json, application/ld+json, " //
+ + "text/plain, application/n-triples, text/trig, " //
+ + "application/n-quads, application/x-trig, application/trig, " //
+ + "text/n-quads, text/nquads, application/trix+xml, " //
+ + "text/rdf+n3, application/n3, " //
+ + "text/n3");
+ final AcceptList offeringResources = new AcceptList("text/html, application/xhtml+xml");
+ private final ConfigurationBean conf;
+ private final OntologyBean ontoBean;
+ private final MessageSource messageSource;
+
+ @RequestMapping(value = {"{path:(?!staticResources).*$}", "{path:(?!staticResources).*$}/**"})
+ public Object resourceController(ModelMap model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "output", defaultValue = "") String output, @CookieValue(value = "colorPair", defaultValue = "") String colorPair) throws UnsupportedEncodingException {
+ if (colorPair.equals("")) {
+ colorPair = conf.getRandomColorPair();
+ Cookie c = new Cookie("colorPair", colorPair);
+ c.setPath("/");
+ res.addCookie(c);
+ }
+ return resource(conf, model, req, res, locale, output, "", colorPair);
+ }
+
+ public Object resource(ConfigurationBean conf, ModelMap model, HttpServletRequest req, HttpServletResponse res, Locale locale, String output, String forceIRI, String colorPair) throws UnsupportedEncodingException {
+
+ model.addAttribute("conf", conf);
+
+ String IRIsuffix = new UrlPathHelper().getLookupPathForRequest(req).replaceAll("/lodview/", "/");
+ String requestUrl = req.getRequestURI();
+
+ log.info("IRIsuffix " + IRIsuffix);
+ log.info("requestUrl " + requestUrl);
+
+ model.addAttribute("path", new UrlPathHelper().getContextPath(req).replaceAll("/lodview/", "/"));
+ model.addAttribute("locale", locale.getLanguage());
+
+ boolean redirect = false;
+ boolean redirected = false;
+ boolean avoidRedirection = false;
+
+ // managing redirections
+ if (!conf.getHttpRedirectExcludeList().equals("")) {
+ String[] excList = conf.getHttpRedirectExcludeList().split(",");
+ for (String exclude : excList) {
+ if (requestUrl.matches(exclude)) {
+ avoidRedirection = true;
+ break;
+ }
+ }
+ }
+ if (!avoidRedirection && !conf.getHttpRedirectSuffix().equals("")) {
+ // 303 dereferencing mode
+ if (IRIsuffix.matches(".+" + conf.getHttpRedirectSuffix() + "$")) {
+ // after redirect
+ IRIsuffix = IRIsuffix.replaceAll(conf.getHttpRedirectSuffix() + "$", "");
+
+ redirected = true;
+ } else {
+ // before redirect
+ redirect = true;
+ }
+ } else if (!avoidRedirection && !conf.getHttpRedirectPrefix().equals("")) {
+ // 303 dereferencing mode
+ if (IRIsuffix.matches("^" + conf.getHttpRedirectPrefix() + ".+")) {
+ // after redirect
+ IRIsuffix = IRIsuffix.replaceAll("^" + conf.getHttpRedirectPrefix(), "");
+ if (conf.getRedirectionStrategy().equals("pubby")) {
+ IRIsuffix = "/resource/" + IRIsuffix;
+ IRIsuffix = IRIsuffix.replaceAll("//", "/");
+ }
+ redirected = true;
+ } else {
+ // before redirect
+ redirect = true;
+ }
+ }
+
+ IRIsuffix = IRIsuffix.replaceAll("^/", "");
+
+ String IRIprefix = conf.getIRInamespace().replaceAll("/$", "");
+ String IRI = IRIprefix + "/" + IRIsuffix.replaceAll(" ", "%20");
+
+ if (forceIRI != null && !forceIRI.equals("")) {
+ IRI = forceIRI;
+ }
+
+ if (conf.getForceIriEncoding().equals("encode")) {
+ String[] IRItokens = IRI.split("/");
+ for (int i = 0; i < IRItokens.length; i++) {
+ IRItokens[i] = URLEncoder.encode(IRItokens[i], StandardCharsets.UTF_8);
+ }
+ IRI = StringUtils.join("/");
+ } else if (conf.getForceIriEncoding().equals("decode")) {
+ String[] IRItokens = IRI.split("/");
+ for (int i = 0; i < IRItokens.length; i++) {
+ IRItokens[i] = java.net.URLDecoder.decode(IRItokens[i], StandardCharsets.UTF_8);
+ }
+ IRI = StringUtils.join("/");
+ }
+
+ if (conf.getRedirectionStrategy().equals("pubby")) {
+ /*
+ * http://dbpedia.org/data/Barack_Obama.ntriples
+ * http://dbpedia.org/data/Barack_Obama.n3
+ * http://dbpedia.org/data/Barack_Obama.json
+ * http://dbpedia.org/data/Barack_Obama.rdf
+ */
+ if (requestUrl.matches(".+\\.(ntriples|n3|json|rdf)")) {
+ String outputType = "";
+ String newUrl = requestUrl.replaceFirst("/data/", "/resource/").replaceAll("\\.(ntriples|n3|json|rdf)$", "");
+ RedirectView r = new RedirectView();
+ r.setExposeModelAttributes(false);
+ if (requestUrl.endsWith(".ntriples")) {
+ outputType = "text/plain";
+ } else if (requestUrl.endsWith(".n3")) {
+ outputType = "text/turtle";
+ } else if (requestUrl.endsWith(".json")) {
+ outputType = "application/rdf+json";
+ } else if (requestUrl.endsWith(".rdf")) {
+ outputType = "application/rdf+xml";
+ }
+ r.setUrl(newUrl + "?" + (req.getQueryString() != null ? req.getQueryString() + "&" : "") + "output=" + outputType);
+ return r;
+ }
+ }
+
+ log.info("####################################################################");
+ log.info("################# looking for " + IRI + " ################# ");
+
+ String[] acceptedContent = req.getHeader("Accept").split(",");
+ if (redirected) {
+ acceptedContent = "text/html".split(",");
+ }
+ // log.trace("Accept " + req.getHeader("Accept"));
+
+ AcceptList a = AcceptList.create(acceptedContent);
+ // log.trace("-- AcceptList: " + a);
+ // log.trace("-- OffertList: " + offeringRDF);
+
+ MediaType matchItem = AcceptList.match(offeringRDF, a);
+ Lang lang = matchItem != null ? RDFLanguages.contentTypeToLang(matchItem.getContentTypeStr()) : null;
+
+ // override content negotiation
+ if (!output.equals("")) {
+ try {
+ output = output.replaceAll("([a-zA-Z]) ([a-zA-Z])", "$1+$2");
+ a = AcceptList.create(output.split(","));
+ matchItem = AcceptList.match(offeringRDF, a);
+ lang = RDFLanguages.contentTypeToLang(matchItem.getContentTypeStr());
+ } catch (Exception e) {
+ return new ErrorController(conf).error406(res, model, colorPair);
+ }
+ log.debug("override content type " + matchItem.getContentTypeStr());
+ }
+
+ try {
+ if (lang == null) {
+ matchItem = AcceptList.match(offeringResources, a);
+ // probably you are asking for an HTML page
+ if (matchItem != null) {
+ if (redirect && !redirected) {
+ return redirect(req, IRIsuffix);
+ } else {
+ return htmlResource(model, IRI, colorPair, locale, req, res);
+ }
+ } else {
+ return new ErrorController(conf).error406(res, model, colorPair);
+ }
+ } else {
+ return resourceRaw(conf, model, IRI, conf.getEndPointUrl(), matchItem.getContentTypeStr());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ if (e.getMessage() != null && e.getMessage().startsWith("404")) {
+ return new ErrorController(conf).error404(res, model, e.getMessage(), colorPair, IRI, conf.getEndPointUrl());
+ } else {
+ return new ErrorController(conf).error500(res, model, e.getMessage(), colorPair, IRI, conf.getEndPointUrl());
+ }
+ }
+
+ }
+
+ private String htmlResource(ModelMap model, String IRI, String colorPair, Locale locale, HttpServletRequest req, HttpServletResponse res) throws Exception {
+ model.addAttribute("contextPath", new UrlPathHelper().getContextPath(req));
+ ResultBean r = new ResourceBuilder(messageSource).buildHtmlResource(IRI, locale, conf, ontoBean);
+ model.addAttribute("colorPair", Misc.guessColor(colorPair, r, conf));
+ model.addAttribute("results", Misc.guessClass(r, conf, ontoBean));
+ model.addAttribute("ontoBean", ontoBean);
+
+ addDataLinks(IRI, model, req, locale);
+ addLodliveLink(locale, model, IRI);
+ enrichResponse(model, r, req, res);
+ return "resource";
+ }
+
+ private void addDataLinks(String IRI, ModelMap model, HttpServletRequest req, Locale locale) throws UnsupportedEncodingException {
+
+ Map> rawdatalinks = new LinkedHashMap>();
+ String queryString = (req.getQueryString() != null ? "&" + req.getQueryString().replaceAll("&", "&") : "");
+
+ if (conf.getRedirectionStrategy().equals("pubby")) {
+
+ Map list = new LinkedHashMap();
+ list.put("xml", "?output=" + URLEncoder.encode("application/rdf+xml", StandardCharsets.UTF_8) + queryString);
+ list.put("ntriples", "?output=" + URLEncoder.encode("text/plain", StandardCharsets.UTF_8) + queryString);
+ list.put("turtle", "?output=" + URLEncoder.encode("text/turtle", StandardCharsets.UTF_8) + queryString);
+ list.put("json", "?output=" + URLEncoder.encode("application/rdf+json", StandardCharsets.UTF_8) + queryString);
+ list.put("ld+json", "?output=" + URLEncoder.encode("application/ld+json", StandardCharsets.UTF_8) + queryString);
+ rawdatalinks.put("rdf:", list);
+
+ } else {
+ Map list = new LinkedHashMap();
+ list.put("xml", "?output=" + URLEncoder.encode("application/rdf+xml", StandardCharsets.UTF_8) + queryString);
+ list.put("ntriples", "?output=" + URLEncoder.encode("text/plain", StandardCharsets.UTF_8) + queryString);
+ list.put("turtle", "?output=" + URLEncoder.encode("text/turtle", StandardCharsets.UTF_8) + queryString);
+ list.put("ld+json", "?output=" + URLEncoder.encode("application/ld+json", StandardCharsets.UTF_8) + queryString);
+ rawdatalinks.put(messageSource.getMessage("footer.viewAs", null, "view as", locale), list);
+ }
+
+ if (conf.getEndPointType().equals("virtuoso")) {
+ {
+ Map list = new LinkedHashMap();
+ list.put("atom", conf.getEndPointUrl() + "?output=application%2Fatom%2Bxml&query=DESCRIBE+%3C" + IRI + "%3E");
+ list.put("json", conf.getEndPointUrl() + "?output=application%2Fodata%2Bjson&query=DESCRIBE+%3C" + IRI + "%3E");
+ rawdatalinks.put("odata:", list);
+ }
+ {
+ Map list = new LinkedHashMap();
+ list.put("html", conf.getEndPointUrl() + "?output=text%2Fhtml&query=DESCRIBE+%3C" + IRI + "%3E");
+ list.put("json", conf.getEndPointUrl() + "?output=application%2Fmicrodata%2Bjson&query=DESCRIBE+%3C" + IRI + "%3E");
+ rawdatalinks.put("microdata:", list);
+ }
+ {
+ Map list = new LinkedHashMap();
+ list.put("csv", conf.getEndPointUrl() + "?output=text%2Fcsv&query=DESCRIBE+%3C" + IRI + "%3E");
+ list.put("cxml", conf.getEndPointUrl() + "?output=format=text%2Fcxml&query=DESCRIBE+%3C" + IRI + "%3E");
+ rawdatalinks.put("rawdata:", list);
+ }
+ }
+ model.addAttribute("rawdatalinks", rawdatalinks);
+
+ }
+
+ private RedirectView redirect(HttpServletRequest req, String IRIsuffix) throws UnsupportedEncodingException {
+
+ RedirectView r = new RedirectView();
+ // preventing redirect of model attributes
+ r.setExposeModelAttributes(false);
+ r.setContentType("text/html");
+ r.setHttp10Compatible(false);
+ if (!conf.getHttpRedirectPrefix().equals("")) {
+ // prefix mode
+ String redirectUrl = conf.getHttpRedirectPrefix().replaceAll("^/", "");
+ if (conf.getRedirectionStrategy().equals("pubby")) {
+ r.setUrl(conf.getPublicUrlPrefix() + redirectUrl + IRIsuffix.replaceAll("^resource/", "") + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
+ } else {
+ r.setUrl(conf.getPublicUrlPrefix().replaceAll(IRIsuffix + "$", "") + redirectUrl + IRIsuffix + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
+ }
+ } else {
+ // suffix mode
+ String redirectUrl = conf.getHttpRedirectSuffix();
+ // String[] redirectUrlArray = redirectUrl.split("/");
+ // redirectUrl = "";
+ // for (String string : redirectUrlArray) {
+ // redirectUrl += URLEncoder.encode(string, "UTF-8") + "/";
+ // }
+ // redirectUrl = redirectUrl.replaceAll("/$", "");
+ r.setUrl(req.getRequestURL() + redirectUrl + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
+ }
+
+ return r;
+
+ }
+
+ private void addLodliveLink(Locale locale, ModelMap model, String IRI) {
+ if (locale.getLanguage().equals("it")) {
+ model.addAttribute("lodliveUrl", "http://lodlive.it?" + IRI.replaceAll("#", "%23"));
+ } else if (locale.getLanguage().equals("fr")) {
+ model.addAttribute("lodliveUrl", "http://fr.lodlive.it?" + IRI.replaceAll("#", "%23"));
+ } else if (locale.getLanguage().equals("gl")) {
+ model.addAttribute("lodliveUrl", "http://gl.lodlive.it?" + IRI.replaceAll("#", "%23"));
+ } else {
+ model.addAttribute("lodliveUrl", "http://en.lodlive.it?" + IRI.replaceAll("#", "%23"));
+ }
+ }
+
+ private void enrichResponse(ModelMap model, ResultBean r, HttpServletRequest req, HttpServletResponse res) {
+
+ String publicUrl = r.getMainIRI();
+ res.addHeader("Link", "<" + publicUrl + ">; rel=\"about\"");
+
+ @SuppressWarnings("unchecked")
+ Map> rawdatalinks = (LinkedHashMap>) model.get("rawdatalinks");
+
+ rawdatalinks.values().stream()
+ .map(Map::entrySet)
+ .flatMap(Collection::stream)
+ .forEach(e ->
+ res.addHeader(
+ "Link", "<" + e.getValue() + ">;" +
+ " rel=\"alternate\"; type=\"application/rdf+xml\";" +
+ " title=\"Structured Descriptor Document (" + e.getKey() + ")\""));
+
+ try {
+ for (TripleBean t : r.getResources(r.getMainIRI()).get(r.getTypeProperty())) {
+ res.addHeader("Link", "<" + t.getProperty().getProperty() + ">; rel=\"type\"");
+ }
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+
+ @RequestMapping(value = "/rawdata")
+ public ResponseEntity resourceRawController(ModelMap model, @RequestParam(value = "IRI") String IRI, @RequestParam(value = "sparql") String sparql, @RequestParam(value = "contentType", defaultValue = "application/rdf+xml") String contentType) {
+ return resourceRaw(conf, model, IRI, sparql, contentType);
+ }
+
+ public ResponseEntity resourceRaw(ConfigurationBean conf, ModelMap model, @RequestParam(value = "IRI") String IRI, @RequestParam(value = "sparql") String sparql, @RequestParam(value = "contentType", defaultValue = "application/rdf+xml") String contentType) {
+ // logger.trace("ResourceController.resourceRaw()");
+ contentType = contentType.replaceAll("([a-zA-Z]) ([a-zA-Z])", "$1+$2");
+ Lang lang = RDFLanguages.contentTypeToLang(contentType);
+ try {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("Content-Type", contentType + "; charset=" + conf.getContentEncoding());
+
+ if (sparql != null && sparql.equals("<>")) {
+ Model m = ModelFactory.createDefaultModel();
+ try {
+ m.read(IRI);
+ } catch (Exception e) {
+ throw new Exception(messageSource.getMessage("error.noContentNegotiation", null, "sorry but content negotiation is not supported by the IRI", Locale.ENGLISH));
+ }
+ return new ResponseEntity(new ResourceBuilder(messageSource).buildRDFResource(IRI, m, lang, conf), headers, HttpStatus.OK);
+ } else {
+ return new ResponseEntity(new ResourceBuilder(messageSource).buildRDFResource(IRI, sparql, lang, conf), headers, HttpStatus.OK);
+ }
+
+ } catch (Exception e) {
+ if (e.getMessage() != null && e.getMessage().startsWith("404")) {
+ return new ResponseEntity(e.getMessage(), HttpStatus.NOT_FOUND);
+ } else {
+ return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/controllers/SPARQLController.java b/src/main/java/it/gov/innovazione/lodviewng/controllers/SPARQLController.java
new file mode 100644
index 0000000..a5b5a08
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/controllers/SPARQLController.java
@@ -0,0 +1,17 @@
+package it.gov.innovazione.lodviewng.controllers;
+
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequiredArgsConstructor
+public class SPARQLController {
+ private final ConfigurationBean conf;
+
+ @RequestMapping(value = {"/sparql", "/SPARQL"})
+ public String sparql() {
+ return "redirect:" + conf.getEndPointUrl();
+ }
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/controllers/StaticController.java b/src/main/java/it/gov/innovazione/lodviewng/controllers/StaticController.java
new file mode 100644
index 0000000..d7457ba
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/controllers/StaticController.java
@@ -0,0 +1,73 @@
+package it.gov.innovazione.lodviewng.controllers;
+
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.MessageSource;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.util.UrlPathHelper;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Locale;
+
+@Controller
+@RequiredArgsConstructor
+@Slf4j
+public class StaticController {
+
+
+ private final ConfigurationBean conf;
+
+ private final MessageSource messageSource;
+
+ @RequestMapping(value = "/")
+ public String home(HttpServletRequest req, HttpServletResponse res, Model model, Locale locale, @CookieValue(value = "colorPair", defaultValue = "") String colorPair) {
+ colorPair = conf.getRandomColorPair();
+ Cookie c = new Cookie("colorPair", colorPair);
+ c.setPath("/");
+ res.addCookie(c);
+ model.addAttribute("colorPair", colorPair);
+ model.addAttribute("conf", conf);
+ model.addAttribute("locale", locale.getLanguage());
+ model.addAttribute("path", new UrlPathHelper().getContextPath(req).replaceAll("/lodview/", "/"));
+ log.debug("home controller");
+ return "home";
+ }
+
+ @RequestMapping(value = "/lodviewmenu")
+ public String lodviewmenu(Model model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "IRI") String IRI, @CookieValue(value = "colorPair", defaultValue = "") String colorPair) {
+ if (colorPair.equals("")) {
+ colorPair = conf.getRandomColorPair();
+ Cookie c = new Cookie("colorPair", colorPair);
+ c.setPath("/");
+ res.addCookie(c);
+ }
+ return lodviewmenu(req, res, model, locale, IRI, conf, colorPair);
+ }
+
+ @RequestMapping(value = {"/lodviewcolor", "/**/lodviewcolor"})
+ public ResponseEntity lodviewcolor(Model model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "colorPair") String colorPair) {
+ Cookie c = new Cookie("colorPair", colorPair);
+ c.setPath("/");
+ res.addCookie(c);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ public String lodviewmenu(HttpServletRequest req, HttpServletResponse res, Model model, Locale locale, @RequestParam(value = "IRI", defaultValue = "") String IRI, ConfigurationBean conf, String colorPair) {
+ model.addAttribute("conf", conf);
+ model.addAttribute("locale", locale.getLanguage());
+ model.addAttribute("IRI", IRI);
+ model.addAttribute("colorPair", colorPair);
+ model.addAttribute("path", new UrlPathHelper().getContextPath(req).replaceAll("/lodview/", "/"));
+ return "menu";
+ }
+
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/endpoint/SPARQLEndPoint.java b/src/main/java/it/gov/innovazione/lodviewng/endpoint/SPARQLEndPoint.java
new file mode 100644
index 0000000..5ce214b
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/endpoint/SPARQLEndPoint.java
@@ -0,0 +1,341 @@
+package it.gov.innovazione.lodviewng.endpoint;
+
+
+import it.gov.innovazione.lodviewng.bean.OntologyBean;
+import it.gov.innovazione.lodviewng.bean.PropertyBean;
+import it.gov.innovazione.lodviewng.bean.TripleBean;
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import it.gov.innovazione.lodviewng.utils.Misc;
+import org.apache.jena.graph.Node;
+import org.apache.jena.http.auth.AuthEnv;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.QueryExecutionFactory;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.query.ResultSet;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.Property;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.Statement;
+import org.apache.jena.sparql.exec.http.QueryExecutionHTTP;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SPARQLEndPoint {
+
+ private static final Logger logger = LoggerFactory.getLogger(SPARQLEndPoint.class);
+ protected ConfigurationBean conf;
+ OntologyBean ontoBean;
+ String locale = "en";
+
+ public SPARQLEndPoint(ConfigurationBean conf, OntologyBean ontoBean, String locale) {
+ this.locale = locale;
+ this.ontoBean = ontoBean;
+ this.conf = conf;
+ // TODO Auto-generated constructor stub
+ }
+
+ public List doQuery(String IRI, String aProperty, int start, List queries, String filter, String overrideProperty) throws Exception {
+ // logger.trace("executing query on " + conf.getEndPointUrl());
+ List results = new ArrayList();
+ if (conf.getAuthPassword() != null && !conf.getAuthPassword().equals("")) {
+ AuthEnv.get().registerUsernamePassword(URI.create(conf.getEndPointUrl()), conf.getAuthUsername(), conf.getAuthPassword());
+ }
+ for (String query : queries) {
+ // logger.trace("-- " + parseQuery(query, IRI, aProperty,
+ // start, filter));
+ QueryExecution qe = QueryExecutionHTTP.create()
+ .endpoint(conf.getEndPointUrl())
+ .query(parseQuery(query, IRI, aProperty, start, filter))
+ .build();
+ //QueryExecutionFactory.sparqlService(conf.getEndPointUrl(), parseQuery(query, IRI, aProperty, start, filter), auth);
+ results = moreThenOneQuery(qe, results, 0, overrideProperty);
+ qe.close();
+ }
+
+ if (results.size() == 0) {
+ if (IRI != null) {
+ boolean hasInverses = false;
+ for (String query : conf.getDefaultInversesTest()) {
+ // logger.trace("query!!! " + parseQuery(query, IRI,
+ // aProperty, start, filter));
+ QueryExecution qe = QueryExecutionHTTP.create()
+ .endpoint(conf.getEndPointUrl())
+ .query(parseQuery(query, IRI, aProperty, start, filter))
+ .build();
+ if (!hasInverses) {
+ hasInverses = qe.execAsk();
+ }
+ qe.close();
+ }
+ if (!hasInverses) {
+ throw new Exception("404 - not found");
+ }
+ }
+ }
+ return results;
+ }
+
+ private List moreThenOneQuery(QueryExecution qe, List results, int retry, String overrideProperty) throws Exception {
+
+ try {
+ ResultSet rs = qe.execSelect();
+ while (rs.hasNext()) {
+ TripleBean rb = new TripleBean();
+ QuerySolution qs = rs.next();
+ String property = "";
+ if (overrideProperty != null) {
+ property = overrideProperty;
+ } else if (qs.get("p") != null) {
+ property = qs.get("p").asNode().toString();
+ }
+
+ try {
+ if (qs.get("s") != null && !qs.get("s").asNode().toString().startsWith("http://")) { // probably
+ // a
+ // bn
+ rb.setIri(qs.get("s").asNode().toString());
+ rb.setNsIri("_:" + rb.getIri());
+ } else if (qs.get("s") != null && qs.get("s").asNode().toString().startsWith("http://")) {
+ rb.setIri(qs.get("s").asNode().toString());
+ rb.setNsIri(Misc.toNsResource(rb.getIri(), conf));
+ rb.setUrl(Misc.toBrowsableUrl(rb.getIri(), conf));
+ }
+
+ PropertyBean p = new PropertyBean();
+ p.setNsProperty(Misc.toNsResource(property, conf));
+ p.setProperty(property);
+ if (ontoBean != null) {
+ p.setLabel(ontoBean.getEscapedValue("label", locale, property));
+ p.setComment(ontoBean.getEscapedValue("comment", locale, property));
+ }
+ p.setPropertyUrl(Misc.toBrowsableUrl(property, conf));
+ rb.setProperty(p);
+ if (qs.get("o") != null) {
+ Node object = qs.get("o").asNode();
+ if (object.isURI()) {
+ rb.setType("iri");
+ rb.setValue(object.toString(false));
+ } else if (object.isLiteral()) {
+ rb.setType("literal");
+ rb.setDataType(object.getLiteralDatatypeURI());
+ rb.setNsDataType(Misc.toNsResource(object.getLiteralDatatypeURI(), conf));
+ rb.setLang(object.getLiteralLanguage());
+ rb.setValue(object.getLiteralLexicalForm());
+ } else if (object.isBlank()) {
+ rb.setType("bnode");
+ rb.setValue(object.toString(false));
+ }
+ } else {
+ rb.setType("literal");
+ rb.setValue("");
+ }
+ results.add(rb);
+ } catch (Exception e) {
+ logger.error("error? " + e.getMessage());
+ // e.printStackTrace();
+ }
+ }
+ } catch (Exception ez) {
+ if (retry < 3) {
+ retry++;
+ // logger.trace("query failed (" + ez.getMessage() +
+ // "), I'm giving another chance (" + retry + "/3)");
+ return moreThenOneQuery(qe, results, retry, overrideProperty);
+ }
+ ez.printStackTrace();
+ throw new Exception("connection refused");
+ }
+
+ return results;
+ }
+
+ public List doQuery(String IRI, List queries, String overrideProperty) throws Exception {
+ return doQuery(IRI, null, -1, queries, null, overrideProperty);
+ }
+
+ public List doLocalQuery(Model m, String IRI, List queries, String about) throws Exception {
+ return doLocalQuery(m, IRI, null, -1, queries, about);
+ }
+
+ public List doLocalQuery(Model model, String IRI, List queries) throws Exception {
+ return doLocalQuery(model, IRI, null, -1, queries, null);
+ }
+
+ public List doLocalQuery(Model model, String IRI, String localProperty, int start, List queries, String overrideProperty) throws Exception {
+ // logger.trace("executing query on model based on " + IRI);
+ List results = new ArrayList();
+
+ for (String query : queries) {
+ QueryExecution qe = QueryExecutionFactory.create(parseQuery(query, IRI, localProperty, start, null), model);
+ try {
+ ResultSet rs = qe.execSelect();
+ while (rs.hasNext()) {
+ TripleBean rb = new TripleBean();
+ QuerySolution qs = rs.next();
+ String property = "";
+ if (overrideProperty != null) {
+ property = overrideProperty;
+ } else if (qs.get("p") != null) {
+ property = qs.get("p").asNode().toString();
+ }
+ try {
+ if (qs.get("s") != null && !qs.get("s").asNode().toString().startsWith("http://")) { // probably
+ // blanknode
+ rb.setIri(qs.get("s").asNode().toString());
+ rb.setNsIri("_:" + rb.getIri());
+ } else if (qs.get("s") != null && qs.get("s").asNode().toString().startsWith("http://")) {
+ rb.setIri(qs.get("s").asNode().toString());
+ rb.setNsIri(Misc.toNsResource(rb.getIri(), conf));
+ rb.setUrl(Misc.toBrowsableUrl(rb.getIri(), conf));
+ }
+ PropertyBean p = new PropertyBean();
+ p.setNsProperty(Misc.toNsResource(property, conf));
+ p.setProperty(property);
+ p.setPropertyUrl(Misc.toBrowsableUrl(property, conf));
+ if (ontoBean != null) {
+ p.setLabel(ontoBean.getEscapedValue("label", locale, property));
+ p.setComment(ontoBean.getEscapedValue("comment", locale, property));
+ }
+ rb.setProperty(p);
+ if (qs.get("o") != null) {
+ Node object = qs.get("o").asNode();
+ if (object.isURI()) {
+ rb.setType("iri");
+ rb.setValue(object.toString(false));
+ } else if (object.isLiteral()) {
+ rb.setType("literal");
+ rb.setDataType(object.getLiteralDatatypeURI());
+ rb.setNsDataType(Misc.toNsResource(object.getLiteralDatatypeURI(), conf));
+ rb.setLang(object.getLiteralLanguage());
+ rb.setValue(object.getLiteralLexicalForm());
+ } else if (object.isBlank()) {
+ rb.setType("bnode");
+ rb.setValue(object.toString(false));
+ }
+ } else {
+ rb.setType("literal");
+ rb.setValue("");
+ }
+ results.add(rb);
+ } catch (Exception e) {
+ logger.error("error? " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ } catch (Exception e) {
+ throw new Exception("500 - " + e.getMessage());
+ } finally {
+ qe.close();
+ }
+ }
+
+ if (results.size() == 0) {
+ throw new Exception("404 - not found");
+ }
+ return results;
+ }
+
+ public Model extractData(Model result, String IRI, String sparql, List queries) throws Exception {
+
+ // logger.trace("executing query on " + sparql);
+ Resource subject = result.createResource(IRI);
+ for (String query : queries) {
+ QueryExecution qe = QueryExecutionFactory.sparqlService(sparql, parseQuery(query, IRI, null, -1, null));
+ try {
+ ResultSet rs = qe.execSelect();
+
+ List sl = new ArrayList();
+ while (rs.hasNext()) {
+ QuerySolution qs = rs.next();
+ RDFNode subject2 = qs.get("s");
+ RDFNode property = qs.get("p");
+ RDFNode object = qs.get("o");
+ Property property1 = result.createProperty(property.asNode().toString());
+ result.add(result.createStatement(subject2 != null ? subject2.asResource() : subject, property1, object));
+ }
+ result.add(sl);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Exception("error in query execution: " + e.getMessage());
+ } finally {
+ qe.close();
+ }
+ }
+ return result;
+ }
+
+ public Model extractLocalData(Model result, String IRI, Model m, List queries) throws Exception {
+
+ // logger.trace("executing query on IRI");
+ Resource subject = result.createResource(IRI);
+ for (String query : queries) {
+ QueryExecution qe = QueryExecutionFactory.create(parseQuery(query, IRI, null, -1, null), m);
+ try {
+ ResultSet rs = qe.execSelect();
+ List sl = new ArrayList();
+ while (rs.hasNext()) {
+ QuerySolution qs = rs.next();
+ RDFNode subject2 = qs.get("s");
+ RDFNode property = qs.get("p");
+ RDFNode object = qs.get("o");
+ Property property1 = result.createProperty(property.asNode().toString());
+ result.add(result.createStatement(subject2 != null ? subject2.asResource() : subject, property1, object));
+ }
+ result.add(sl);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Exception("error in query execution: " + e.getMessage());
+ } finally {
+ qe.close();
+ }
+ }
+ return result;
+ }
+
+ public String parseQuery(String query, String IRI, String property, int start, String filter) {
+ if (IRI != null) {
+ /* managing issues depending on "$" in some IRIs */
+ query = query.replaceAll("\\$\\{IRI\\}", IRI.replaceAll("\\$", "%24")).replaceAll("%24", "\\$");
+ }
+ if (property != null) {
+ query = query.replaceAll("\\$\\{PROPERTY\\}", property);
+ }
+ if (filter != null) {
+ query = query.replaceAll("\\$\\{FILTERPROPERTY\\}", filter);
+ }
+ if (query.indexOf("STARTFROM") > 0) {
+ query = query.replaceAll("\\$\\{STARTFROM\\}", "" + start);
+ } else if (start > 0) {
+ query = query.replaceAll("LIMIT (.+)$", "OFFSET " + start + " LIMIT $1");
+ }
+ return query;
+ }
+
+ public String testEndpoint(ConfigurationBean conf) {
+ logger.info("testing connection on " + conf.getEndPointUrl());
+ QueryExecution qe = QueryExecutionFactory.sparqlService(conf.getEndPointUrl(), "select ?s {?s ?p ?o} LIMIT 1");
+ String msg = "";
+ try {
+ ResultSet rs = qe.execSelect();
+ if (rs.hasNext()) {
+ logger.info("is online");
+ msg = "online";
+ } else {
+ logger.info("is offline");
+ msg = "offline";
+ }
+ } catch (Exception e) {
+ logger.info("is offline " + e.getMessage());
+ msg = "offline " + e.getMessage();
+ } finally {
+ qe.close();
+ }
+ return msg;
+ }
+
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/utils/Misc.java b/src/main/java/it/gov/innovazione/lodviewng/utils/Misc.java
new file mode 100644
index 0000000..8a8ca5e
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/utils/Misc.java
@@ -0,0 +1,143 @@
+package it.gov.innovazione.lodviewng.utils;
+
+
+import it.gov.innovazione.lodviewng.bean.OntologyBean;
+import it.gov.innovazione.lodviewng.bean.PropertyBean;
+import it.gov.innovazione.lodviewng.bean.TripleBean;
+import it.gov.innovazione.lodviewng.bean.ResultBean;
+import it.gov.innovazione.lodviewng.conf.ConfigurationBean;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.NodeIterator;
+import org.apache.jena.rdf.model.RDFNode;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+@Slf4j
+public class Misc {
+
+ public static String toNsResource(String iri, ConfigurationBean conf) {
+ if (iri != null && !iri.equals("")) {
+ return conf.getNsURIPrefix(iri.replaceAll("[^/#]+$", "")) + ":" + iri.replaceAll(".+[/|#]([^/#]+)$", "$1");
+
+ } else {
+ return null;
+ }
+ }
+
+ public static String toBrowsableUrl(String value, ConfigurationBean conf) {
+
+ if (!conf.getPublicUrlSuffix().equals("") && value.startsWith(conf.getIRInamespace())) {
+ return conf.getPublicUrlPrefix() + "?" + conf.getPublicUrlSuffix() + "IRI=" + java.net.URLEncoder.encode(value, StandardCharsets.UTF_8);
+ } else {
+ return value
+ .replaceAll("^" + conf.getIRInamespace() + "(.+)$", conf.getPublicUrlPrefix() + "$1")
+ .replaceAll("([^:])//", "$1/")
+ .replaceAll("^//", "/");
+ }
+ }
+
+ public static String guessColor(String colorPair, ResultBean r, ConfigurationBean conf) {
+ switch (conf.getColorStrategy()) {
+ case CLASS: {
+ try {
+ List m = r.getResources(r.getMainIRI()).get(r.getTypeProperty());
+ for (TripleBean tripleBean : m) {
+ colorPair = conf.getColorPairMatcher().get(tripleBean.getValue());
+ if (colorPair != null) return colorPair;
+ }
+ } catch (Exception e) {
+ }
+ return conf.getColorPairMatcher().get("http://lodview.it/conf#otherClasses");
+ }
+ case PREFIX: {
+ for (String prefix : conf.getColorPairMatcher().keySet()) {
+ if (r.getMainIRI().startsWith(prefix)) {
+ return conf.getColorPairMatcher().get(prefix);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return colorPair;
+ }
+
+ public static ResultBean guessClass(ResultBean r, ConfigurationBean conf, OntologyBean ontoBean) {
+ try {
+ if (!conf.getMainOntologiesPrefixes().isEmpty()) {
+ String mainIri = r.getMainIRI();
+ Map> mainResource = r.getResources(mainIri);
+ TreeMap> resultOrderedMap = new TreeMap<>();
+
+ List m = new ArrayList<>(mainResource.get(r.getTypeProperty()));
+ Model model = ontoBean.getModel();
+ for (TripleBean tripleBean : m) {
+ int dept = 0;
+ if (startsWithAtLeastOne(tripleBean.getValue(), conf.getMainOntologiesPrefixes())) {
+ dept = countFathers(tripleBean.getValue(), 0, model);
+ }
+ List l = null;
+ if (resultOrderedMap.get(dept) != null) {
+ l = resultOrderedMap.get(dept);
+ } else {
+ l = new ArrayList<>();
+ }
+ l.add(tripleBean);
+ resultOrderedMap.put(dept, l);
+ // removing types
+ r.removeResource(tripleBean, mainIri);
+ }
+ if (resultOrderedMap.size() > 0) {
+ for (Integer dept : resultOrderedMap.descendingKeySet()) {
+ List l = resultOrderedMap.get(dept);
+ for (TripleBean tripleBean : l) {
+ // adding ordered types
+ r.addResource(tripleBean, mainIri);
+ }
+ }
+ }
+ }
+ return r;
+ } catch (RuntimeException re) {
+ throw re;
+ } catch (Exception e) {
+ log.warn("Unable to guess class: " + e);
+ }
+ return r;
+ }
+
+ private static Integer countFathers(String value, int i, Model model) {
+ NodeIterator iter = model.listObjectsOfProperty(model.createResource(value), model.createProperty("http://www.w3.org/2000/01/rdf-schema#subClassOf"));
+ while (iter.hasNext()) {
+ RDFNode node = iter.next();
+ return countFathers(node.toString(), ++i, model);
+ }
+ return i;
+ }
+
+ private static boolean startsWithAtLeastOne(String value, List startsWithList) {
+ for (String string : startsWithList) {
+ if (value.startsWith(string)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static String stripHTML(String value) {
+
+ value = value.replaceAll("?\\w[^>]*>", "");
+
+ return value;
+ }
+
+}
diff --git a/src/main/java/it/gov/innovazione/lodviewng/utils/ResourceClassPathLoader.java b/src/main/java/it/gov/innovazione/lodviewng/utils/ResourceClassPathLoader.java
new file mode 100644
index 0000000..9f89a01
--- /dev/null
+++ b/src/main/java/it/gov/innovazione/lodviewng/utils/ResourceClassPathLoader.java
@@ -0,0 +1,47 @@
+package it.gov.innovazione.lodviewng.utils;
+
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.SneakyThrows;
+import org.apache.commons.io.FileUtils;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class ResourceClassPathLoader {
+
+ @SneakyThrows
+ public static File toFile(@NonNull Resource resource) {
+ String fileExtension = Optional.of(resource)
+ .map(Resource::getFilename)
+ .map(s -> s.substring(s.lastIndexOf(".")))
+ .orElse("");
+ InputStream initialStream = resource.getInputStream();
+ File tempFileName = File.createTempFile("lodview", fileExtension);
+ FileUtils.copyInputStreamToFile(initialStream, tempFileName);
+ return tempFileName;
+ }
+
+ public static File toFile(String resource) {
+ return toFile(new ClassPathResource(resource));
+ }
+
+ @SneakyThrows
+ public static List toFiles(String directory) {
+ PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
+ Resource[] resources = pathMatchingResourcePatternResolver.getResources("classpath*:" + directory + "/*");
+ return Arrays.stream(resources)
+ .map(ResourceClassPathLoader::toFile)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/org/dvcama/lodview/bean/OntologyBean.java b/src/main/java/org/dvcama/lodview/bean/OntologyBean.java
deleted file mode 100644
index f0eff64..0000000
--- a/src/main/java/org/dvcama/lodview/bean/OntologyBean.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.dvcama.lodview.bean;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-
-import org.apache.commons.lang3.StringEscapeUtils;
-import org.springframework.web.context.ServletContextAware;
-
-import com.hp.hpl.jena.rdf.model.Literal;
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.rdf.model.ModelFactory;
-import com.hp.hpl.jena.rdf.model.NodeIterator;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-import com.hp.hpl.jena.rdf.model.Resource;
-import com.hp.hpl.jena.util.FileManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class OntologyBean implements ServletContextAware {
-
- private String ontoDir;
- private ServletContext context;
- private Model model;
- final Logger logger = LoggerFactory.getLogger(OntologyBean.class);
-
- public void init() {
- File ontoDirFile = new File(ontoDir);
- if (!ontoDirFile.isAbsolute()) {
- ontoDirFile = new File(context.getRealPath("/") + "/WEB-INF/" + ontoDir);
- }
- model = ModelFactory.createDefaultModel();
- if (ontoDirFile.exists()) {
- logger.debug("ontologies dir founded!");
- File[] list = ontoDirFile.listFiles();
- for (File file : list) {
- if (!file.isDirectory()) {
- try {
- logger.debug("loading " + file.getCanonicalPath());
- FileManager.get().readModel(model, file.getAbsolutePath());
- logger.debug("read successfully!");
- } catch (Exception e) {
- logger.error("error loading " + e.getMessage());
- // e.printStackTrace();
- }
- }
- }
- } else {
- logger.debug("no ontologies founded " + ontoDirFile.getAbsolutePath());
- }
-
- // logger.debug("------------------- " + getHashResult("en",
- // "http://dati.camera.it/ocd/parentCountry"));
- // logger.debug("------------------- " + getHashResult("it",
- // "http://dati.camera.it/ocd/parentCountry"));
-
- }
-
- @Override
- public void setServletContext(ServletContext arg0) {
- this.context = arg0;
- try {
- init();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- public String getOntoDir() {
- return ontoDir;
- }
-
- public void setOntoDir(String ontoDir) {
- this.ontoDir = ontoDir;
- }
-
- public String getValue(String what, String preferredLanguage, String IRI) {
- Resource IRIresource = model.createResource(IRI);
- return getSingleValue(preferredLanguage, IRIresource, "http://www.w3.org/2000/01/rdf-schema#" + what, "");
- }
-
- public String getEscapedValue(String what, String preferredLanguage, String IRI) {
- return StringEscapeUtils.escapeHtml4(getValue(what, preferredLanguage, IRI));
- }
-
- public Map getHashResult(String preferredLanguage, String IRI) {
- Map result = new HashMap();
- Resource IRIresource = model.createResource(IRI);
- result.put("label", getSingleValue(preferredLanguage, IRIresource, "http://www.w3.org/2000/01/rdf-schema#label", ""));
- result.put("comment", getSingleValue(preferredLanguage, IRIresource, "http://www.w3.org/2000/01/rdf-schema#comment", ""));
- return result;
- }
-
- private String getSingleValue(String preferredLanguage, Resource IRI, String prop, String defaultValue) {
- NodeIterator iter = model.listObjectsOfProperty(IRI, model.createProperty(prop));
- String result = defaultValue;
- boolean betterTitleMatch = false;
- while (iter.hasNext()) {
- RDFNode node = iter.nextNode();
- Literal l = node.asLiteral();
- //logger.debug(IRI + " " + preferredLanguage + " --> " + l.getLanguage() + " --> " + l.getLexicalForm());
- if (!betterTitleMatch && (result.equals(defaultValue) || l.getLanguage().equals("en") || l.getLanguage().equals(preferredLanguage))) {
- if (preferredLanguage.equals(l.getLanguage())) {
- betterTitleMatch = true;
- }
- result = l.getLexicalForm();
- }
-
- }
- return result;
- }
-
- public Model getModel() {
- return model;
- }
-
- public void setModel(Model model) {
- this.model = model;
- }
-
-}
diff --git a/src/main/java/org/dvcama/lodview/bean/PropertyBean.java b/src/main/java/org/dvcama/lodview/bean/PropertyBean.java
deleted file mode 100644
index 7de314a..0000000
--- a/src/main/java/org/dvcama/lodview/bean/PropertyBean.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.dvcama.lodview.bean;
-
-public class PropertyBean {
-
- private String nsProperty = null, property = null, propertyUrl = null;
- private String label = "";
- private String comment = "";
-
- public String getPropertyUrl() {
- return propertyUrl;
- }
-
- public void setPropertyUrl(String propertyUrl) {
- this.propertyUrl = propertyUrl;
- }
-
- public String getNsProperty() {
- return nsProperty;
- }
-
- public void setNsProperty(String nsProperty) {
- this.nsProperty = nsProperty;
- }
-
- public String getProperty() {
- return property;
- }
-
- public void setProperty(String property) {
- this.property = property;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((nsProperty == null) ? 0 : nsProperty.hashCode());
- result = prime * result + ((property == null) ? 0 : property.hashCode());
- result = prime * result + ((propertyUrl == null) ? 0 : propertyUrl.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- PropertyBean other = (PropertyBean) obj;
- if (nsProperty == null) {
- if (other.nsProperty != null)
- return false;
- } else if (!nsProperty.equals(other.nsProperty))
- return false;
- if (property == null) {
- if (other.property != null)
- return false;
- } else if (!property.equals(other.property))
- return false;
- if (propertyUrl == null) {
- if (other.propertyUrl != null)
- return false;
- } else if (!propertyUrl.equals(other.propertyUrl))
- return false;
- return true;
- }
-
- public String getComment() {
- return comment;
- }
-
- public void setComment(String comment) {
- this.comment = comment;
- }
-
- public String getLabel() {
- return label;
- }
-
- public void setLabel(String label) {
- this.label = label;
- }
-
-}
diff --git a/src/main/java/org/dvcama/lodview/bean/ResultBean.java b/src/main/java/org/dvcama/lodview/bean/ResultBean.java
deleted file mode 100644
index 20b36dc..0000000
--- a/src/main/java/org/dvcama/lodview/bean/ResultBean.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package org.dvcama.lodview.bean;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ResultBean {
-
- private String title, latitude = null, longitude = null, mainIRI = null;
- private PropertyBean descriptionProperty = null, typeProperty = null;
- private List images = null, linking = null, videos = null, audios = null;
- private Map>> literals = new HashMap>>(), resources = new HashMap>>(), bnodes = new HashMap>>();
-
- private Map>> addEle(String IRI, TripleBean tripleBean, Map>> ele) {
- if (ele.get(IRI) == null || ele.get(IRI).get(tripleBean.getProperty()) == null) {
- LinkedHashMap> a = ele.get(IRI);
- if (a == null) {
- a = new LinkedHashMap>();
- }
- List b = new ArrayList();
- b.add(tripleBean);
- a.put(tripleBean.getProperty(), b);
- ele.put(IRI, a);
- } else {
- LinkedHashMap> a = ele.get(IRI);
- List b = a.get(tripleBean.getProperty());
- b.add(tripleBean);
- a.put(tripleBean.getProperty(), b);
- ele.put(IRI, a);
- }
- return ele;
- }
-
- private Map>> removeEle(String IRI, TripleBean tripleBean, Map>> ele) {
- if (ele.get(IRI) == null || ele.get(IRI).get(tripleBean.getProperty()) == null) {
-
- } else {
- LinkedHashMap> a = ele.get(IRI);
- List b = a.get(tripleBean.getProperty());
- b.remove(tripleBean);
- a.put(tripleBean.getProperty(), b);
- ele.put(IRI, a);
- }
- return ele;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public List getImages() {
- return images;
- }
-
- public void setImages(List images) {
- this.images = images;
- }
-
- public void setLiterals(String IRI, List localLiterals) {
- for (TripleBean tripleBean : localLiterals) {
- literals = addEle(IRI, tripleBean, literals);
- }
-
- }
-
- public void setBnodes(String IRI, List localBnodes) {
- for (TripleBean tripleBean : localBnodes) {
- bnodes = addEle(IRI, tripleBean, bnodes);
- }
-
- }
-
- public void setResources(String IRI, List Localresources) {
- for (TripleBean tripleBean : Localresources) {
- resources = addEle(IRI, tripleBean, resources);
- }
-
- }
-
- public LinkedHashMap> getResources(String IRI) {
- return resources.get(IRI);
- }
-
- public LinkedHashMap> getLiterals(String IRI) {
- return literals.get(IRI);
- }
-
- public Map>> getLiterals() {
- return literals;
- }
- public LinkedHashMap> getBnodes(String IRI) {
- return bnodes.get(IRI);
- }
-
- public String getLongitude() {
- return longitude;
- }
-
- public void setLongitude(String longitude) {
- this.longitude = longitude;
- }
-
- public String getLatitude() {
- return latitude;
- }
-
- public List getAudios() {
- return audios;
- }
-
- public List getVideos() {
- return videos;
- }
-
- public void setLatitude(String latitude) {
- this.latitude = latitude;
- }
-
- public List getLinking() {
- return linking;
- }
-
- public void setLinking(List linking) {
- this.linking = linking;
- }
-
- @Override
- public String toString() {
- return "ResultBean [title=" + title + ", \ndescriptionProperty=" + descriptionProperty + ", \nlatitude=" + latitude + ", \nlongitude=" + longitude + ", \nimages=" + images + ", \nlinking=" + linking + ", \nliterals=" + literals + ", \nresources=" + resources + ", \nbnodes=" + bnodes + "]";
- }
-
- public String getMainIRI() {
- return mainIRI;
- }
-
- public void setMainIRI(String mainIRI) {
- this.mainIRI = mainIRI;
- }
-
- public void addBnode(TripleBean tripleBean, String IRI) {
-
- bnodes = addEle(IRI, tripleBean, bnodes);
- }
-
- public void addLiteral(TripleBean tripleBean, String IRI) {
- literals = addEle(IRI, tripleBean, literals);
-
- }
-
- public void addResource(TripleBean tripleBean, String IRI) {
- resources = addEle(IRI, tripleBean, resources);
- }
-
- public void removeBnode(TripleBean tripleBean, String IRI) {
-
- bnodes = removeEle(IRI, tripleBean, bnodes);
- }
-
- public void removeLiteral(TripleBean tripleBean, String IRI) {
- literals = removeEle(IRI, tripleBean, literals);
-
- }
-
- public void removeResource(TripleBean tripleBean, String IRI) {
- resources = removeEle(IRI, tripleBean, resources);
- }
-
- public PropertyBean getDescriptionProperty() {
- return descriptionProperty;
- }
-
- public void setDescriptionProperty(PropertyBean descriptionProperty) {
- this.descriptionProperty = descriptionProperty;
- }
-
- public PropertyBean getTypeProperty() {
- return typeProperty;
- }
-
- public void setTypeProperty(PropertyBean typeProperty) {
- this.typeProperty = typeProperty;
- }
-
- public void setVideos(List videos) {
- this.videos = videos;
- }
-
- public void setAudios(List audios) {
- this.audios = audios;
- }
-
-}
diff --git a/src/main/java/org/dvcama/lodview/bean/TripleBean.java b/src/main/java/org/dvcama/lodview/bean/TripleBean.java
deleted file mode 100644
index 53bae1a..0000000
--- a/src/main/java/org/dvcama/lodview/bean/TripleBean.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.dvcama.lodview.bean;
-
-
-public class TripleBean {
- private String nsValue = null, type = null, IRI = null, nsIRI = null, value = null, dataType = null, nsDataType = null, lang = null, url = null;
- private boolean isLocal = false;
- PropertyBean property = null;
-
- public PropertyBean getProperty() {
- return property;
- }
-
- public void setProperty(PropertyBean property) {
- this.property = property;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public String getValue() {
- return value;
- }
-
- public String getNsValue() {
- return nsValue;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-
- public void setNsValue(String nsValue) {
- this.nsValue = nsValue;
- }
-
- public String getLang() {
- return lang;
- }
-
- public void setLang(String lang) {
- this.lang = lang;
- }
-
- public String getDataType() {
- return dataType;
- }
-
- public void setDataType(String dataType) {
- this.dataType = dataType;
- }
-
- @Override
- public String toString() {
- return "TripleBean [property=" + property + ", nsValue=" + nsValue + ", type=" + type + ", IRI=" + IRI + ", nsIRI=" + nsIRI + ", value=" + value + ", dataType=" + dataType + ", nsDataType=" + nsDataType + ", lang=" + lang + ", url=" + url + ", isLocal=" + isLocal + "]";
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public boolean isLocal() {
- return isLocal;
- }
-
- public void setLocal(boolean isLocal) {
- this.isLocal = isLocal;
- }
-
- public String getIRI() {
- return IRI;
- }
-
- public void setIRI(String iRI) {
- IRI = iRI;
- }
-
- public String getNsDataType() {
- return nsDataType;
- }
-
- public void setNsDataType(String nsDataType) {
- this.nsDataType = nsDataType;
- }
-
- public String getNsIRI() {
- return nsIRI;
- }
-
- public void setNsIRI(String nsIRI) {
- this.nsIRI = nsIRI;
- }
-}
diff --git a/src/main/java/org/dvcama/lodview/builder/ResourceBuilder.java b/src/main/java/org/dvcama/lodview/builder/ResourceBuilder.java
deleted file mode 100644
index e5de9d3..0000000
--- a/src/main/java/org/dvcama/lodview/builder/ResourceBuilder.java
+++ /dev/null
@@ -1,330 +0,0 @@
-package org.dvcama.lodview.builder;
-
-import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.jena.riot.Lang;
-import org.dvcama.lodview.bean.OntologyBean;
-import org.dvcama.lodview.bean.ResultBean;
-import org.dvcama.lodview.bean.TripleBean;
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.dvcama.lodview.endpoint.SPARQLEndPoint;
-import org.dvcama.lodview.utils.Misc;
-import org.springframework.context.MessageSource;
-
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.rdf.model.ModelFactory;
-import com.hp.hpl.jena.rdf.model.RDFWriter;
-
-public class ResourceBuilder {
-
- private MessageSource messageSource;
-
- public ResourceBuilder() {
- }
-
- public ResourceBuilder(MessageSource messageSource) {
- this.messageSource = messageSource;
- }
-
- public ResultBean buildHtmlResource(String IRI, Locale locale, ConfigurationBean conf, OntologyBean ontoBean) throws Exception {
- return buildHtmlResource(IRI, locale, conf, ontoBean, false);
- }
-
- public ResultBean buildHtmlResource(String IRI, Locale locale, ConfigurationBean conf, OntologyBean ontoBean, boolean localMode) throws Exception {
- ResultBean result = new ResultBean();
- List videos = new ArrayList();
- List audios = new ArrayList();
- List images = new ArrayList();
- List linking = new ArrayList();
- SPARQLEndPoint se = new SPARQLEndPoint(conf, ontoBean, locale.getLanguage());
- result.setMainIRI(IRI);
-
- String preferredLanguage = conf.getPreferredLanguage();
- if (preferredLanguage.equals("auto")) {
- preferredLanguage = locale.getLanguage();
- }
- List triples = new ArrayList();
- if (conf.getEndPointUrl() != null && conf.getEndPointUrl().equals("<>")) {
- localMode = true;
- }
- if (localMode) {
- /* looking for data via content negotiation */
- Model m = ModelFactory.createDefaultModel();
- try {
- m.read(IRI);
- } catch (Exception e) {
- throw new Exception(messageSource.getMessage("error.noContentNegotiation", null, "sorry but content negotiation is not supported by the IRI", locale));
- }
- triples = se.doLocalQuery(m, IRI, conf.getDefaultQueries());
- } else {
- triples = se.doQuery(IRI, conf.getDefaultQueries(), null);
- }
- boolean betterTitleMatch = false, betterDescrMatch = false;
- for (TripleBean tripleBean : triples) {
-
- if (tripleBean.getIRI() == null) {
- tripleBean.setIRI(IRI);
- tripleBean.setNsIRI(Misc.toNsResource(tripleBean.getIRI(), conf));
- }
-
- if (conf.getTitleProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getTitleProperties().contains(tripleBean.getProperty().getProperty())) {
- if (tripleBean.getIRI().equals(IRI) && !betterTitleMatch && (result.getTitle() == null || result.getTitle().trim().equals("") || (tripleBean.getLang() != null && (preferredLanguage.equals(tripleBean.getLang()) || tripleBean.getLang().equals("en"))))) {
- result.setTitle(Misc.stripHTML(tripleBean.getValue()));
- if (preferredLanguage.equals(tripleBean.getLang())) {
- betterTitleMatch = true;
- }
- }
- } else if (conf.getDescriptionProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getDescriptionProperties().contains(tripleBean.getProperty().getProperty())) {
- if (tripleBean.getIRI().equals(IRI) && !betterDescrMatch && (result.getDescriptionProperty() == null || (tripleBean.getLang() != null && (preferredLanguage.equals(tripleBean.getLang()) || tripleBean.getLang().equals("en"))))) {
- result.setDescriptionProperty(tripleBean.getProperty());
- if (preferredLanguage.equals(tripleBean.getLang())) {
- betterDescrMatch = true;
- }
- }
- } else if (conf.getLatitudeProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getLatitudeProperties().contains(tripleBean.getProperty().getProperty())) {
- result.setLatitude(tripleBean.getValue());
- } else if (conf.getLongitudeProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getLongitudeProperties().contains(tripleBean.getProperty().getProperty())) {
- result.setLongitude(tripleBean.getValue());
- } else if (conf.getImageProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getImageProperties().contains(tripleBean.getProperty().getProperty())) {
- images.add(tripleBean.getValue());
- } else if (conf.getAudioProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getAudioProperties().contains(tripleBean.getProperty().getProperty())) {
- audios.add(tripleBean.getValue());
- } else if (conf.getVideoProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getVideoProperties().contains(tripleBean.getProperty().getProperty())) {
- videos.add(tripleBean.getValue());
- } else if (conf.getLinkingProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getLinkingProperties().contains(tripleBean.getProperty().getProperty())) {
- linking.add(tripleBean.getValue());
- } else if (conf.getTypeProperties().contains(tripleBean.getProperty().getNsProperty()) || conf.getTypeProperties().contains(tripleBean.getProperty().getProperty())) {
- result.setTypeProperty(tripleBean.getProperty());
- }
-
- if (tripleBean.getType().equals("iri")) {
- tripleBean.setUrl(Misc.toBrowsableUrl(tripleBean.getValue(), conf));
- tripleBean.setNsValue(Misc.toNsResource(tripleBean.getValue(), conf));
- if (!tripleBean.getUrl().equals(tripleBean.getValue()) || tripleBean.getValue().startsWith(conf.getPublicUrlPrefix())) {
- tripleBean.setLocal(true);
- }
- result.addResource(tripleBean, tripleBean.getIRI());
- } else if (tripleBean.getType().equals("literal")) {
- result.addLiteral(tripleBean, tripleBean.getIRI());
- } else if (tripleBean.getType().equals("bnode")) {
- result.addBnode(tripleBean, tripleBean.getIRI());
- }
- }
-
- result.setImages(images);
- result.setLinking(linking);
- result.setVideos(videos);
- result.setAudios(audios);
-
- return result;
- }
-
- public String buildRDFResource(String IRI, String sparql, Lang lang, ConfigurationBean conf) throws Exception {
- String result = "empty content";
- Model model = ModelFactory.createDefaultModel();
- model.setNsPrefixes(conf.getPrefixes());
-
- SPARQLEndPoint se = new SPARQLEndPoint(conf, null, null);
- model = se.extractData(model, IRI, sparql, conf.getDefaultRawDataQueries());
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- RDFWriter rdfWriter = model.getWriter(lang.getName());
- rdfWriter.setProperty("showXMLDeclaration","true");
- rdfWriter.setProperty("relativeURIs","");
-
- rdfWriter.write(model, baos, conf.getIRInamespace());
-
- byte[] resultByteArray = baos.toByteArray();
- result = new String(resultByteArray);
-
- return result;
- }
-
- public String buildRDFResource(String IRI, Model m, Lang lang, ConfigurationBean conf) throws Exception {
- String result = "empty content";
- Model model = ModelFactory.createDefaultModel();
- model.setNsPrefixes(conf.getPrefixes());
-
- SPARQLEndPoint se = new SPARQLEndPoint(conf, null, null);
- model = se.extractLocalData(model, IRI, m, conf.getDefaultRawDataQueries());
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- RDFWriter rdfWriter = model.getWriter(lang.getName());
- rdfWriter.setProperty("showXMLDeclaration","true");
- rdfWriter.setProperty("relativeURIs","");
-
- rdfWriter.write(model, baos, conf.getIRInamespace());
- rdfWriter.setProperty("showXMLDeclaration","true");
- rdfWriter.setProperty("relativeURIs","");
-
- byte[] resultByteArray = baos.toByteArray();
- result = new String(resultByteArray);
-
- return result;
- }
-
- public ResultBean buildPartialHtmlResource(String IRI, String[] abouts, Locale locale, ConfigurationBean conf, OntologyBean ontoBean, List filterProperties) throws Exception {
-
- SPARQLEndPoint se = new SPARQLEndPoint(conf, ontoBean, locale.getLanguage());
- ResultBean result = new ResultBean();
- List literals = new ArrayList();
-
- String preferredLanguage = conf.getPreferredLanguage();
- if (preferredLanguage.equals("auto")) {
- preferredLanguage = locale.getLanguage();
- }
-
- List triples = new ArrayList();
-
- /*
- * FIXME: make more distinct queries to avoid length limits, eg
- * http://dati.camera.it/ocd/assemblea.rdf/a16
- */
-
- StringBuilder filter = new StringBuilder();
- for (String titleProperty : filterProperties) {
- if (titleProperty.toLowerCase().startsWith("http:")) {
- filter.append("(?filterProperty = <" + titleProperty + ">)");
- } else {
- filter.append("(?filterProperty = " + titleProperty + ")");
- }
- filter.append(" || ");
- }
-
- for (String about : abouts) {
- StringBuilder sparqlQuery = new StringBuilder("select distinct ?o ");
- sparqlQuery.append("{ <" + about + "> ?filterProperty ?o. FILTER (" + filter + "))} ");
- List sparqlQueries = new ArrayList();
- sparqlQueries.add(sparqlQuery.toString().replaceAll("\\|\\| \\)", ""));
- try {
-
- if (conf.getEndPointUrl().equals("<>")) {
- /* looking for data via content negotiation */
- Model m = ModelFactory.createDefaultModel();
- try {
- m.read(about);
- } catch (Exception e) {
- throw new Exception(messageSource.getMessage("error.noContentNegotiation", null, "sorry but content negotiation is not supported by the IRI", locale));
- }
- triples.addAll(se.doLocalQuery(m, about, sparqlQueries, about));
- } else {
- triples.addAll(se.doQuery(null, sparqlQueries, about));
- }
-
- } catch (Exception e) {
- }
- }
-
- Map> l = new HashMap>();
-
- for (TripleBean tripleBean : triples) {
- if (tripleBean.getType().equals("literal")) {
- List al = l.get(tripleBean.getProperty().getProperty());
- if (al == null) {
- al = new ArrayList();
- }
- al.add(tripleBean);
- l.put(tripleBean.getProperty().getProperty(), al);
- }
- }
- for (String about : l.keySet()) {
- List al = l.get(about);
- boolean betterTitleMatch = false;
- TripleBean title = null;
- for (TripleBean tripleBean : al) {
- if (!betterTitleMatch && (title == null || title.getValue() == null || title.getValue().trim().equals("") || preferredLanguage.equals(tripleBean.getLang()) || tripleBean.getLang().equals("en"))) {
- title = tripleBean;
- if (preferredLanguage.equals(tripleBean.getLang())) {
- betterTitleMatch = true;
- }
- }
- }
- if (title != null) {
- literals.add(title);
- }
- }
- result.setLiterals(IRI, literals);
- return result;
- }
-
- public ResultBean buildHtmlInverseResource(String IRI, String property, int start, Locale locale, ConfigurationBean conf, OntologyBean ontoBean) throws Exception {
- ResultBean result = new ResultBean();
-
- SPARQLEndPoint se = new SPARQLEndPoint(conf, ontoBean, locale.getLanguage());
- String preferredLanguage = conf.getPreferredLanguage();
- if (preferredLanguage.equals("auto")) {
- preferredLanguage = locale.getLanguage();
- }
- if (property == null) {
- /* counting */
- List resources = new ArrayList();
- List triples = new ArrayList();
-
- if (conf.getEndPointUrl().equals("<>")) {
- /* looking for data via content negotiation */
- Model m = ModelFactory.createDefaultModel();
- try {
- m.read(IRI);
- } catch (Exception e) {
- throw new Exception(messageSource.getMessage("error.noContentNegotiation", null, "sorry but content negotiation is not supported by the IRI", locale));
- }
- triples = se.doLocalQuery(m, IRI, conf.getDefaultInversesCountQueries());
- } else {
- triples = se.doQuery(IRI, conf.getDefaultInversesCountQueries(), null);
- }
-
- for (TripleBean tripleBean : triples) {
- if (tripleBean.getType().equals("literal")) {
- resources.add(tripleBean);
- }
- }
-
- result.setResources(IRI, resources);
-
- } else {
- /* listing */
- List resources = new ArrayList();
- List triples = new ArrayList();
-
- if (conf.getEndPointUrl().equals("<>")) {
- /* looking for data via content negotiation */
- Model m = ModelFactory.createDefaultModel();
- try {
- m.read(IRI);
- } catch (Exception e) {
- throw new Exception(messageSource.getMessage("error.noContentNegotiation", null, "sorry but content negotiation is not supported by the IRI", locale));
- }
- triples = se.doLocalQuery(m, IRI, property, start, conf.getDefaultInversesQueries(), null);
- } else {
- triples = se.doQuery(IRI, property, start, conf.getDefaultInversesQueries(), null, null);
- }
-
- Map controlList = new HashMap();
- for (TripleBean tripleBean : triples) {
- if (tripleBean.getType().equals("literal")) {
- if (controlList.get(tripleBean.getProperty().getProperty()) == null || preferredLanguage.equals(tripleBean.getLang())) {
- controlList.put(tripleBean.getProperty().getProperty(), tripleBean);
- }
- }
- }
-
- for (String at : controlList.keySet()) {
- resources.add(controlList.get(at));
- }
-
- result.setResources(IRI, resources);
-
- }
-
- return result;
- }
-
- public ResultBean buildHtmlInverseResource(String IRI, Locale locale, ConfigurationBean conf, OntologyBean ontoBean) throws Exception {
- return buildHtmlInverseResource(IRI, null, -1, locale, conf, ontoBean);
- }
-}
diff --git a/src/main/java/org/dvcama/lodview/conf/ConfigurationBean.java b/src/main/java/org/dvcama/lodview/conf/ConfigurationBean.java
deleted file mode 100644
index 87632c0..0000000
--- a/src/main/java/org/dvcama/lodview/conf/ConfigurationBean.java
+++ /dev/null
@@ -1,372 +0,0 @@
-package org.dvcama.lodview.conf;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-
-import javax.servlet.ServletContext;
-
-import org.apache.jena.riot.RDFDataMgr;
-import org.springframework.web.context.ServletContextAware;
-
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.rdf.model.NodeIterator;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-import com.hp.hpl.jena.rdf.model.ResIterator;
-import com.hp.hpl.jena.rdf.model.Resource;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ConfigurationBean implements ServletContextAware, Cloneable {
-
- final Logger logger = LoggerFactory.getLogger(ConfigurationBean.class);
-
- protected Model confModel = null;
- protected ServletContext context;
- protected String confFile;
- private String endPointType;
- private String redirectionStrategy;
- private String forceIriEncoding;
- private String httpRedirectExcludeList;
- private String homeUrl;
- private String license;
- private String httpRedirectSuffix;
- private String httpRedirectPrefix;
- private String endPointUrl;
- private String IRInamespace;
- private String contentEncoding;
- private String staticResourceURL;
- private String preferredLanguage;
- private String publicUrlPrefix = null;
- private String publicUrlSuffix = "";
- private String authUsername = null;
- private String authPassword = null;
- private String defaultInverseBehaviour = "collapse";
-
- public enum ColorStrategy {RANDOM, CLASS, PREFIX}
- private ColorStrategy colorStrategy = ColorStrategy.RANDOM;
- public ColorStrategy getColorStrategy() {return colorStrategy;}
-
- private List defaultQueries = null, defaultRawDataQueries = null, defaultInversesQueries = null, defaultInversesTest = null, defaultInversesCountQueries = null, typeProperties = null, audioProperties = null, imageProperties = null, videoProperties = null, linkingProperties = null, titleProperties = null, descriptionProperties = null, longitudeProperties = null, latitudeProperties = null;
- private List colorPair = null, skipDomains = null, mainOntologiesPrefixes = null;
- private Map colorPairMatcher = null;
-
- Random rand = new Random();
-
- public ConfigurationBean() throws IOException, Exception {
-
- }
-
- public void populateBean() throws IOException, Exception {
- logger.debug("Initializing configuration " + confFile);
- File configFile = new File(confFile);
- if (!configFile.isAbsolute()) {
- configFile = new File(context.getRealPath("/") + "/WEB-INF/" + confFile);
- }
- if (!configFile.exists()) {
- throw new Exception("Configuration file not found (" + configFile.getAbsolutePath() + ")");
- }
- confModel = RDFDataMgr.loadModel(configFile.getAbsolutePath());
-
- endPointUrl = getSingleConfValue("endpoint");
- endPointType = getSingleConfValue("endpointType", "");
- authPassword = getSingleConfValue("authPassword");
- authUsername = getSingleConfValue("authUsername");
- forceIriEncoding = getSingleConfValue("forceIriEncoding", "auto");
- redirectionStrategy = getSingleConfValue("redirectionStrategy", "");
-
- IRInamespace = getSingleConfValue("IRInamespace", "");
-
- httpRedirectSuffix = getSingleConfValue("httpRedirectSuffix", "");
- httpRedirectPrefix = getSingleConfValue("httpRedirectPrefix", "");
- httpRedirectExcludeList = getSingleConfValue("httpRedirectExcludeList", "");
-
- publicUrlPrefix = getSingleConfValue("publicUrlPrefix", "");
- publicUrlPrefix = publicUrlPrefix.replaceAll("^(.+/)?auto$", context.getContextPath() + "/");
-
- contentEncoding = getSingleConfValue("contentEncoding");
- staticResourceURL = getSingleConfValue("staticResourceURL", "");
- homeUrl = getSingleConfValue("homeUrl", "/");
- staticResourceURL = staticResourceURL.replaceAll("^(.+/)?auto$", context.getContextPath() + "/staticResources/");
-
- preferredLanguage = getSingleConfValue("preferredLanguage");
-
- typeProperties = getMultiConfValue("typeProperties");
- titleProperties = getMultiConfValue("titleProperties");
- descriptionProperties = getMultiConfValue("descriptionProperties");
- imageProperties = getMultiConfValue("imageProperties");
- audioProperties = getMultiConfValue("audioProperties");
- videoProperties = getMultiConfValue("videoProperties");
- linkingProperties = getMultiConfValue("linkingProperties");
- longitudeProperties = getMultiConfValue("longitudeProperties");
- latitudeProperties = getMultiConfValue("latitudeProperties");
-
- defaultQueries = getMultiConfValue("defaultQueries");
- defaultRawDataQueries = getMultiConfValue("defaultRawDataQueries");
-
- defaultInversesQueries = getMultiConfValue("defaultInversesQueries");
- defaultInversesTest = getMultiConfValue("defaultInversesTest");
- defaultInversesCountQueries = getMultiConfValue("defaultInversesCountQueries");
-
- defaultInverseBehaviour = getSingleConfValue("defaultInverseBehaviour", defaultInverseBehaviour);
- mainOntologiesPrefixes = getMultiConfValue("mainOntologiesPrefixes");
-
- license = getSingleConfValue("license", "");
-
- colorPair = getMultiConfValue("colorPair");
-
- if (colorPair != null && colorPair.size() == 1 && colorPair.get(0).startsWith("http://"))
- {
- switch(colorPair.get(0).replace("http://lodview.it/conf#", ""))
- {
- case "byClass": colorStrategy= ColorStrategy.CLASS; break;
- case "byPrefix": colorStrategy= ColorStrategy.PREFIX; break;
- }
- colorPairMatcher = populateColorPairMatcher();
- }
-
- skipDomains = getMultiConfValue("skipDomains");
- }
-
- private Map populateColorPairMatcher() {
- Map result = new HashMap();
- ResIterator iter = confModel.listSubjectsWithProperty(confModel.createProperty(confModel.getNsPrefixURI("conf"), "hasColorPair"));
- while (iter.hasNext()) {
- Resource res = iter.next();
- NodeIterator values = confModel.listObjectsOfProperty(res, confModel.createProperty(confModel.getNsPrefixURI("conf"), "hasColorPair"));
- while (values.hasNext()) {
- RDFNode node = values.next();
- result.put(res.toString(), node.toString());
- break;
- }
- }
- return result;
- }
-
- private String getSingleConfValue(String prop) {
- return getSingleConfValue(prop, null);
- }
-
- private String getSingleConfValue(String prop, String defaultValue) {
- String value = System.getenv("LodView"+prop);
- if(value!=null) {return value;}
- NodeIterator iter = confModel.listObjectsOfProperty(confModel.createProperty(confModel.getNsPrefixURI("conf"), prop));
- while (iter.hasNext()) {
- RDFNode node = iter.next();
- return node.toString();
- }
- return defaultValue;
- }
-
- private List getMultiConfValue(String prop) {
- List result = new ArrayList();
- NodeIterator iter = confModel.listObjectsOfProperty(confModel.createProperty(confModel.getNsPrefixURI("conf"), prop));
- while (iter.hasNext()) {
- RDFNode node = iter.next();
- result.add(node.toString());
- }
- return result;
- }
-
- @Override
- public void setServletContext(ServletContext arg0) {
- this.context = arg0;
- try {
- populateBean();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- public Model getConfModel() {
- return confModel;
- }
-
- public Map getPrefixes() {
- return confModel.getNsPrefixMap();
- }
-
- public String getRedirectionStrategy() {
- return redirectionStrategy;
- }
-
- public String getPreferredLanguage() {
- return preferredLanguage;
- }
-
- public String getNsPrefixURI(String prefix) {
- return confModel.getNsPrefixURI(prefix);
- }
-
- public String getNsURIPrefix(String IRI) {
- return confModel.getNsURIPrefix(IRI);
- }
-
- public String getEndPointUrl() {
- return endPointUrl;
- }
-
- public List getDefaultQueries() {
- return defaultQueries;
- }
-
- public List getTypeProperties() {
- return typeProperties;
- }
-
- public String getIRInamespace() {
- return IRInamespace;
- }
-
- public String getPublicUrlPrefix() {
- return publicUrlPrefix;
- }
-
- public String getPublicUrlSuffix() {
- return publicUrlSuffix;
- }
-
- public List getDefaultRawDataQueries() {
- return defaultRawDataQueries;
- }
-
- public List getDefaultInversesQueries() {
- return defaultInversesQueries;
- }
-
- public List getDefaultInversesTest() {
- return defaultInversesTest;
- }
-
- public List getDefaultInversesCountQueries() {
- return defaultInversesCountQueries;
- }
-
- public String getStaticResourceURL() {
- return staticResourceURL;
- }
-
- public String getContentEncoding() {
- return contentEncoding;
- }
-
- public List getTitleProperties() {
- return titleProperties;
- }
-
- public List getLongitudeProperties() {
- return longitudeProperties;
- }
-
- public List getLatitudeProperties() {
- return latitudeProperties;
- }
-
- public List getDescriptionProperties() {
- return descriptionProperties;
- }
-
- public List getImageProperties() {
- return imageProperties;
- }
-
- public List getAudioProperties() {
- return audioProperties;
- }
-
- public List getVideoProperties() {
- return videoProperties;
- }
-
- public List getLinkingProperties() {
- return linkingProperties;
- }
-
- public String getLicense() {
- return license;
- }
-
- public List getColorPair() {
- return colorPair;
- }
-
- public String getRandomColorPair() {
- if(colorStrategy!=ColorStrategy.RANDOM) {return "#914848-#7d3e3e";}
- int randomNum = rand.nextInt(colorPair.size());
- return colorPair.get(randomNum);
- }
-
- public List getSkipDomains() {
- return skipDomains;
- }
-
- public String getAuthPassword() {
- return authPassword;
- }
-
- public String getAuthUsername() {
- return authUsername;
- }
-
- public String getDefaultInverseBehaviour() {
- return defaultInverseBehaviour;
- }
-
- public Map getColorPairMatcher() {
- return colorPairMatcher;
- }
-
- @Override
- public Object clone() {
- try {
- return super.clone();
- } catch (CloneNotSupportedException e) {
- throw new Error("Something impossible just happened");
- }
- }
-
- @Override
- public String toString() {
- return "ConfigurationBean [confModel=" + confModel + ", context=" + context + ", confFile=" + confFile + ", endPointUrl=" + endPointUrl + ", IRInamespace=" + IRInamespace + ", contentEncoding=" + contentEncoding + ", staticResourceURL=" + staticResourceURL + ", preferredLanguage=" + preferredLanguage + ", publicUrlPrefix=" + publicUrlPrefix + ", authUsername=" + authUsername + ", authPassword=" + authPassword + ", defaultInverseBehaviour=" + defaultInverseBehaviour + ", defaultQueries=" + defaultQueries + ", defaultRawDataQueries=" + defaultRawDataQueries + ", defaultInversesQueries=" + defaultInversesQueries + ", defaultInversesTest=" + defaultInversesTest + ", defaultInversesCountQueries=" + defaultInversesCountQueries + ", typeProperties=" + typeProperties
- + ", imageProperties=" + imageProperties + ", audioProperties=" + audioProperties + ", videoProperties=" + videoProperties + ", linkingProperties=" + linkingProperties + ", titleProperties=" + titleProperties + ", descriptionProperties=" + descriptionProperties + ", longitudeProperties=" + longitudeProperties + ", latitudeProperties=" + latitudeProperties + ", colorPair=" + colorPair + ", skipDomains=" + skipDomains + ", rand=" + rand + "]";
- }
-
- public String getHomeUrl() {
- return homeUrl;
- }
-
- public String getHttpRedirectSuffix() {
- return httpRedirectSuffix;
- }
-
- public String getHttpRedirectPrefix() {
- return httpRedirectPrefix;
- }
-
- public String getHttpRedirectExcludeList() {
- return httpRedirectExcludeList;
- }
-
- public List getMainOntologiesPrefixes() {
- return mainOntologiesPrefixes;
- }
-
- public String getForceIriEncoding() {
- return forceIriEncoding;
- }
-
- public String getEndPointType() {
- return endPointType;
- }
-
- public void setConfFile(String confFile) {
- this.confFile = confFile;
- }
-
-}
diff --git a/src/main/java/org/dvcama/lodview/controllers/ErrorController.java b/src/main/java/org/dvcama/lodview/controllers/ErrorController.java
deleted file mode 100644
index 69d944f..0000000
--- a/src/main/java/org/dvcama/lodview/controllers/ErrorController.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.dvcama.lodview.controllers;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.CookieValue;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Controller
-public class ErrorController {
-
- final Logger logger = LoggerFactory.getLogger(ErrorController.class);
-
- @Autowired
- ConfigurationBean conf;
-
- public ErrorController(ConfigurationBean conf) {
- this.conf = conf;
- }
-
- public ErrorController() {
- }
-
- /* TODO: change the handler to send "error" param to the client */
- @ResponseStatus(value = HttpStatus.NOT_ACCEPTABLE, reason = "unhandled encoding")
- @RequestMapping(value = "/406")
- public String error406(HttpServletResponse res, ModelMap model, @CookieValue(value = "colorPair") String colorPair) {
- logger.error("not acceptable");
- model.addAttribute("statusCode", "406");
- model.addAttribute("conf", conf);
- colors(colorPair, res, model);
- res.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
- return "error";
- }
-
- @RequestMapping(value = "/404")
- public String error404(HttpServletResponse res, ModelMap model, @RequestParam(value = "error", defaultValue = "") String error, @CookieValue(value = "colorPair", defaultValue = "") String colorPair, @RequestParam(value = "IRI", defaultValue = "") String IRI, @RequestParam(value = "endpoint", defaultValue = "") String endpoint) {
- logger.error("not found " + error + " -- " + IRI + " -- " + endpoint);
- /* spring bug? */
- model.addAttribute("IRI", IRI);
- model.addAttribute("endpoint", endpoint);
- model.addAttribute("error", error);
- model.addAttribute("conf", conf);
- colors(colorPair, res, model);
- model.addAttribute("statusCode", "404");
- res.setStatus(HttpServletResponse.SC_NOT_FOUND);
- return "error";
- }
-
- @RequestMapping(value = "/400")
- public String error400(HttpServletResponse res, ModelMap model, @RequestParam(value = "IRI", defaultValue = "") String IRI, @CookieValue(value = "colorPair", defaultValue = "") String colorPair) {
- logger.error("error on " + IRI);
- /* spring bug? */
- model.addAttribute("IRI", IRI.replaceAll("(http://.+),http://.+", "$1"));
- model.addAttribute("conf", conf);
- colors(colorPair, res, model);
- model.addAttribute("statusCode", "400");
- res.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
- return "error";
- }
-
- @RequestMapping(value = { "/500", "/error" })
- public String error500(HttpServletResponse res, ModelMap model, @RequestParam(value = "error", defaultValue = "") String error, @CookieValue(value = "colorPair", defaultValue = "") String colorPair, @RequestParam(value = "IRI", defaultValue = "") String IRI, @RequestParam(value = "endpoint", defaultValue = "") String endpoint) {
- logger.error("error on " + error + " -- " + IRI + " -- " + endpoint);
- /* spring bug? */
- model.addAttribute("IRI", IRI);
- model.addAttribute("endpoint", endpoint);
- model.addAttribute("error", error);
- model.addAttribute("conf", conf);
- colors(colorPair, res, model);
- model.addAttribute("statusCode", "500");
- res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- return "error";
- }
-
- private void colors(String colorPair, HttpServletResponse res, ModelMap model) {
- if (colorPair.equals("")) {
- colorPair = conf.getRandomColorPair();
- Cookie c = new Cookie("colorPair", colorPair);
- c.setPath("/");
- res.addCookie(c);
- }
- if (conf != null && conf.getColorPairMatcher() != null && conf.getColorPairMatcher().size() > 0) {
- model.addAttribute("colorPair", conf.getColorPairMatcher().get("http://lodview.it/conf#otherClasses"));
- } else {
- model.addAttribute("colorPair", colorPair);
- }
-
- }
-}
diff --git a/src/main/java/org/dvcama/lodview/controllers/LinkedResourcesController.java b/src/main/java/org/dvcama/lodview/controllers/LinkedResourcesController.java
deleted file mode 100644
index de3c819..0000000
--- a/src/main/java/org/dvcama/lodview/controllers/LinkedResourcesController.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.dvcama.lodview.controllers;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringEscapeUtils;
-import org.dvcama.lodview.bean.OntologyBean;
-import org.dvcama.lodview.bean.PropertyBean;
-import org.dvcama.lodview.bean.ResultBean;
-import org.dvcama.lodview.bean.TripleBean;
-import org.dvcama.lodview.builder.ResourceBuilder;
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.dvcama.lodview.utils.Misc;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
-import org.springframework.context.MessageSourceAware;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Controller
-public class LinkedResourcesController implements MessageSourceAware {
-
- final Logger logger = LoggerFactory.getLogger(LinkedResourcesController.class);
-
- @Autowired
- private MessageSource messageSource;
-
- @Autowired
- ConfigurationBean conf;
-
- @Autowired
- OntologyBean ontoBean;
-
- public LinkedResourcesController() {
- }
-
- public LinkedResourcesController(MessageSource messageSource) {
- this.messageSource = messageSource;
- }
-
- @ResponseBody
- @RequestMapping(value = "/linkedResourceTitles", produces = "application/xml;charset=UTF-8")
- public String resourceTitles(ModelMap model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "IRI") String IRI, @RequestParam(value = "abouts[]") String[] abouts) throws IOException, Exception {
- return resourceTitles(model, conf, req, res, locale, IRI, abouts);
- }
-
- public String resourceTitles(ModelMap model, ConfigurationBean conf, HttpServletRequest req, HttpServletResponse res, Locale locale, String IRI, String[] abouts) throws IOException, Exception {
- // logger.trace("LinkedResourcesController.resourceTitles() locale: "
- // + locale.getLanguage());
- StringBuilder result = new StringBuilder("\n");
- try {
- ResultBean results = new ResourceBuilder(messageSource).buildPartialHtmlResource(IRI, abouts, locale, conf, null, conf.getTitleProperties());
- Map> literals = results.getLiterals(IRI);
- if (literals == null || literals.size() == 0) {
- return ("" + messageSource.getMessage("error.noLiteral", null, "no literal values where found", locale) + " ");
- }
- for (PropertyBean key : literals.keySet()) {
- for (TripleBean tripleBean : literals.get(key)) {
- result.append(" \n");
- }
- }
- result.append(" ");
- return result.toString();
- } catch (Exception e) {
- // 404?
- return ("" + messageSource.getMessage("error.linkedResourceUnavailable", null, "unable to retrieve data", locale) + " " + e.getMessage() + " ");
- }
- }
-
- @ResponseBody
- @RequestMapping(value = "/linkedResourceInverses", produces = "application/xml;charset=UTF-8")
- public String resourceInversesController(ModelMap model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "IRI") String IRI, @RequestParam(value = "property", defaultValue = "") String property, @RequestParam(value = "start", defaultValue = "-1") int start) throws IOException, Exception {
- return resourceInverses(model, conf, ontoBean, req, res, locale, IRI, property, start);
- }
-
- public String resourceInverses(ModelMap model, ConfigurationBean conf, OntologyBean ontoBean, HttpServletRequest req, HttpServletResponse res, Locale locale, String IRI, String property, int start) throws IOException, Exception {
- StringBuilder result = new StringBuilder("\n");
- // logger.trace("LinkedResourcesController.resourceInverses()");
- if (property.equals("")) {
- /* counting inverse relations */
- try {
-
- ResultBean results = new ResourceBuilder(messageSource).buildHtmlInverseResource(IRI, locale, conf, ontoBean);
- Map> resources = results.getResources(IRI);
- if (resources != null) {
- for (PropertyBean key : resources.keySet()) {
- for (TripleBean tripleBean : resources.get(key)) {
- if (tripleBean.getProperty().getProperty() == null || tripleBean.getProperty().getProperty().equals("")) {
- throw new Exception("no content");
- }
- result.append(" \n");
- }
- }
- }
-
- result.append(" ");
- return result.toString();
-
- } catch (Exception e) {
- // e.printStackTrace();
- return ("" + messageSource.getMessage("error.linkedResourceUnavailable", null, "unable to retrieve data", locale) + " " + e.getMessage() + " ");
- }
- } else {
-
- /* retrieving inverse relations */
- try {
- ResultBean results = new ResourceBuilder(messageSource).buildHtmlInverseResource(IRI, property, start, locale, conf, null);
- Map> resources = results.getResources(IRI);
- for (PropertyBean key : resources.keySet()) {
- for (TripleBean tripleBean : resources.get(key)) {
- result.append(" \n");
- }
- }
-
- result.append(" ");
- return result.toString();
-
- } catch (Exception e) {
- e.printStackTrace();
- return ("" + messageSource.getMessage("error.linkedResourceUnavailable", null, "unable to retrieve data", locale) + " ");
- }
- }
- }
-
- @Override
- public void setMessageSource(MessageSource arg0) {
- // TODO Auto-generated method stub
-
- }
-}
diff --git a/src/main/java/org/dvcama/lodview/controllers/LodController.java b/src/main/java/org/dvcama/lodview/controllers/LodController.java
deleted file mode 100644
index 7e3cc13..0000000
--- a/src/main/java/org/dvcama/lodview/controllers/LodController.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.dvcama.lodview.controllers;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Locale;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringEscapeUtils;
-import org.dvcama.lodview.bean.ResultBean;
-import org.dvcama.lodview.bean.TripleBean;
-import org.dvcama.lodview.builder.ResourceBuilder;
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Controller
-public class LodController {
-
- final Logger logger = LoggerFactory.getLogger(LodController.class);
-
- @Autowired
- ConfigurationBean confLinked;
-
- @Autowired
- private MessageSource messageSource;
-
-
- @ResponseBody
- @RequestMapping(value = { "/linkedResource", "/lodview/linkedResource" }, produces = "application/xml;charset=UTF-8")
- public String resource(HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "IRI") String IRI) throws IOException, Exception {
-
- if (confLinked.getSkipDomains().contains(IRI.replaceAll("http[s]*://([^/]+)/.*", "$1"))) {
- // logger.info("LodController.resource() - skip - " + IRI);
- return "" + //
- StringEscapeUtils.escapeXml11(messageSource.getMessage("error.skipedDomain", null, "skiping this URI", locale)) + //
- " ";
- }
- try {
- logger.info(" LodController.resource() - load - " + IRI);
- /* TODO: change this in UNION queries for better performance */
- ResultBean results = new ResourceBuilder(messageSource).buildHtmlResource(IRI, locale, confLinked, null, true);
-
- StringBuilder result = new StringBuilder("\n");
-
- result.append(" ");
-
- String lang = locale.getLanguage().toLowerCase();
- String descr = "";
- List descrProperties = results.getLiterals(IRI).get(results.getDescriptionProperty());
- if (descrProperties != null) {
- for (TripleBean tripleBean : descrProperties) {
- if (lang.equals(tripleBean.getLang())) {
- descr = tripleBean.getValue();
- lang = tripleBean.getLang();
- break;
- } else if (tripleBean.getLang().equals("en")) {
- lang = tripleBean.getLang();
- descr = tripleBean.getValue();
- } else if (descr.equals("")) {
- descr = tripleBean.getValue();
- lang = tripleBean.getLang();
- }
- }
- }
- /*
- * List descrProperties =
- * results.getLiterals(IRI).get(results.getDescriptionProperty());
- * if (descrProperties != null) { boolean betterDescrMatch = false;
- * for (TripleBean tripleBean : descrProperties) { if
- * (confLinked.getDescriptionProperties
- * ().contains(tripleBean.getProperty().getNsProperty()) ||
- * confLinked
- * .getDescriptionProperties().contains(tripleBean.getProperty
- * ().getProperty())) { if (!betterDescrMatch && (descr.equals("")
- * || preferredLanguage.equals(tripleBean.getLang()) ||
- * tripleBean.getLang().equals("en"))) { descr =
- * tripleBean.getValue(); lang = tripleBean.getLang(); if
- * (preferredLanguage.equals(tripleBean.getLang())) {
- * betterDescrMatch = true; } } } }
- *
- * }
- */
-
- result.append(" ");
-
- for (String img : results.getImages()) {
- result.append(" ");
- }
- for (String link : results.getLinking()) {
- result.append(" ");
- }
- result.append(" ");
- result.append(" ");
- result.append(" ");
-
- result.append(" ");
- return result.toString();
-
- } catch (Exception e) {
- // e.printStackTrace();
- logger.error(IRI + " unable to retrieve data " + e.getMessage());
- return "" + //
- messageSource.getMessage("error.linkedResourceUnavailable", null, "unable to retrieve data", locale) + //
- " ";
- }
- }
-}
diff --git a/src/main/java/org/dvcama/lodview/controllers/ResourceController.java b/src/main/java/org/dvcama/lodview/controllers/ResourceController.java
deleted file mode 100644
index 4bcca76..0000000
--- a/src/main/java/org/dvcama/lodview/controllers/ResourceController.java
+++ /dev/null
@@ -1,408 +0,0 @@
-package org.dvcama.lodview.controllers;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.jena.atlas.web.AcceptList;
-import org.apache.jena.atlas.web.MediaType;
-import org.apache.jena.riot.Lang;
-import org.apache.jena.riot.RDFLanguages;
-import org.dvcama.lodview.bean.OntologyBean;
-import org.dvcama.lodview.bean.ResultBean;
-import org.dvcama.lodview.bean.TripleBean;
-import org.dvcama.lodview.builder.ResourceBuilder;
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.dvcama.lodview.utils.Misc;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.CookieValue;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.servlet.view.RedirectView;
-import org.springframework.web.util.UrlPathHelper;
-
-import com.hp.hpl.jena.rdf.model.ModelFactory;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Controller
-@RequestMapping(value = "/")
-public class ResourceController {
-
- final Logger logger = LoggerFactory.getLogger(ResourceController.class);
-
- @Autowired
- private MessageSource messageSource;
-
- @Autowired
- ConfigurationBean conf;
-
- @Autowired
- OntologyBean ontoBean;
-
- final AcceptList offeringRDF = new AcceptList("text/turtle, application/turtle, " //
- + "application/x-turtle, application/rdf+xml, " //
- + "application/rdf+json, application/ld+json, " //
- + "text/plain, application/n-triples, text/trig, " //
- + "application/n-quads, application/x-trig, application/trig, " //
- + "text/n-quads, text/nquads, application/trix+xml, " //
- + "text/rdf+n3, application/n3, " //
- + "text/n3");
-
- final AcceptList offeringResources = new AcceptList("text/html, application/xhtml+xml");
-
- public ResourceController() {
-
- }
-
- public ResourceController(MessageSource messageSource, OntologyBean ontoBean) {
- this.messageSource = messageSource;
- this.ontoBean = ontoBean;
- }
-
- @RequestMapping(value = { "{path:(?!staticResources).*$}", "{path:(?!staticResources).*$}/**" })
- public Object resourceController(ModelMap model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "output", defaultValue = "") String output, @CookieValue(value = "colorPair", defaultValue = "") String colorPair) throws UnsupportedEncodingException {
- if (colorPair.equals("")) {
- colorPair = conf.getRandomColorPair();
- Cookie c = new Cookie("colorPair", colorPair);
- c.setPath("/");
- res.addCookie(c);
- }
- return resource(conf, model, req, res, locale, output, "", colorPair);
- }
-
- public Object resource(ConfigurationBean conf, ModelMap model, HttpServletRequest req, HttpServletResponse res, Locale locale, String output, String forceIRI, String colorPair) throws UnsupportedEncodingException {
-
- model.addAttribute("conf", conf);
-
- String IRIsuffix = new UrlPathHelper().getLookupPathForRequest(req).replaceAll("/lodview/", "/");
- String requestUrl = req.getRequestURI();
-
- logger.info("IRIsuffix " + IRIsuffix);
- logger.info("requestUrl " + requestUrl);
-
- model.addAttribute("path", new UrlPathHelper().getContextPath(req).replaceAll("/lodview/", "/"));
- model.addAttribute("locale", locale.getLanguage());
-
- boolean redirect = false;
- boolean redirected = false;
- boolean avoidRedirection = false;
-
- // managing redirections
- if (!conf.getHttpRedirectExcludeList().equals("")) {
- String[] excList = conf.getHttpRedirectExcludeList().split(",");
- for (String exclude : excList) {
- if (requestUrl.matches(exclude)) {
- avoidRedirection = true;
- break;
- }
- }
- }
- if (!avoidRedirection && !conf.getHttpRedirectSuffix().equals("")) {
- // 303 dereferencing mode
- if (IRIsuffix.matches(".+" + conf.getHttpRedirectSuffix() + "$")) {
- // after redirect
- IRIsuffix = IRIsuffix.replaceAll(conf.getHttpRedirectSuffix() + "$", "");
-
- redirected = true;
- } else {
- // before redirect
- redirect = true;
- }
- } else if (!avoidRedirection && !conf.getHttpRedirectPrefix().equals("")) {
- // 303 dereferencing mode
- if (IRIsuffix.matches("^" + conf.getHttpRedirectPrefix() + ".+")) {
- // after redirect
- IRIsuffix = IRIsuffix.replaceAll("^" + conf.getHttpRedirectPrefix(), "");
- if (conf.getRedirectionStrategy().equals("pubby")) {
- IRIsuffix = "/resource/" + IRIsuffix;
- IRIsuffix = IRIsuffix.replaceAll("//", "/");
- }
- redirected = true;
- } else {
- // before redirect
- redirect = true;
- }
- }
-
- IRIsuffix = IRIsuffix.replaceAll("^/", "");
-
- String IRIprefix = conf.getIRInamespace().replaceAll("/$", "");
- String IRI = IRIprefix + "/" + IRIsuffix.replaceAll(" ", "%20");
-
- if (forceIRI != null && !forceIRI.equals("")) {
- IRI = forceIRI;
- }
-
- if (conf.getForceIriEncoding().equals("encode")) {
- String[] IRItokens = IRI.split("/");
- for (int i = 0; i < IRItokens.length; i++) {
- IRItokens[i] = java.net.URLEncoder.encode(IRItokens[i], "UTF-8");
- }
- IRI = StringUtils.join("/");
- } else if (conf.getForceIriEncoding().equals("decode")) {
- String[] IRItokens = IRI.split("/");
- for (int i = 0; i < IRItokens.length; i++) {
- IRItokens[i] = java.net.URLDecoder.decode(IRItokens[i], "UTF-8");
- }
- IRI = StringUtils.join("/");
- }
-
- if (conf.getRedirectionStrategy().equals("pubby")) {
- /*
- * http://dbpedia.org/data/Barack_Obama.ntriples
- * http://dbpedia.org/data/Barack_Obama.n3
- * http://dbpedia.org/data/Barack_Obama.json
- * http://dbpedia.org/data/Barack_Obama.rdf
- */
- if (requestUrl.matches(".+\\.(ntriples|n3|json|rdf)")) {
- String outputType = "";
- String newUrl = requestUrl.replaceFirst("/data/", "/resource/").replaceAll("\\.(ntriples|n3|json|rdf)$", "");
- RedirectView r = new RedirectView();
- r.setExposeModelAttributes(false);
- if (requestUrl.endsWith(".ntriples")) {
- outputType = "text/plain";
- } else if (requestUrl.endsWith(".n3")) {
- outputType = "text/turtle";
- } else if (requestUrl.endsWith(".json")) {
- outputType = "application/rdf+json";
- } else if (requestUrl.endsWith(".rdf")) {
- outputType = "application/rdf+xml";
- }
- r.setUrl(newUrl + "?" + (req.getQueryString() != null ? req.getQueryString() + "&" : "") + "output=" + outputType);
- return r;
- }
- }
-
- logger.info("####################################################################");
- logger.info("################# looking for " + IRI + " ################# ");
-
- String[] acceptedContent = req.getHeader("Accept").split(",");
- if (redirected) {
- acceptedContent = "text/html".split(",");
- }
- // log.trace("Accept " + req.getHeader("Accept"));
-
- AcceptList a = AcceptList.create(acceptedContent);
- // log.trace("-- AcceptList: " + a);
- // log.trace("-- OffertList: " + offeringRDF);
-
- MediaType matchItem = AcceptList.match(offeringRDF, a);
- Lang lang = matchItem != null ? RDFLanguages.contentTypeToLang(matchItem.getContentType()) : null;
-
- // override content negotiation
- if (!output.equals("")) {
- try {
- output = output.replaceAll("([a-zA-Z]) ([a-zA-Z])", "$1+$2");
- a = AcceptList.create(output.split(","));
- matchItem = AcceptList.match(offeringRDF, a);
- lang = RDFLanguages.contentTypeToLang(matchItem.getContentType());
- } catch (Exception e) {
- return new ErrorController(conf).error406(res, model, colorPair);
- }
- logger.debug("override content type " + matchItem.getContentType());
- }
-
- try {
- if (lang == null) {
- matchItem = AcceptList.match(offeringResources, a);
- // probably you are asking for an HTML page
- if (matchItem != null) {
- if (redirect && !redirected) {
- return redirect(req, IRIsuffix);
- } else {
- return htmlResource(model, IRI, colorPair, locale, req, res);
- }
- } else {
- return new ErrorController(conf).error406(res, model, colorPair);
- }
- } else {
- return resourceRaw(conf, model, IRI, conf.getEndPointUrl(), matchItem.getContentType());
- }
- } catch (Exception e) {
- e.printStackTrace();
- if (e.getMessage() != null && e.getMessage().startsWith("404")) {
- return new ErrorController(conf).error404(res, model, e.getMessage(), colorPair, IRI, conf.getEndPointUrl());
- } else {
- return new ErrorController(conf).error500(res, model, e.getMessage(), colorPair, IRI, conf.getEndPointUrl());
- }
- }
-
- }
-
- private String htmlResource(ModelMap model, String IRI, String colorPair, Locale locale, HttpServletRequest req, HttpServletResponse res) throws Exception {
- model.addAttribute("contextPath", new UrlPathHelper().getContextPath(req));
- ResultBean r = new ResourceBuilder(messageSource).buildHtmlResource(IRI, locale, conf, ontoBean);
- model.addAttribute("colorPair", Misc.guessColor(colorPair, r, conf));
- model.addAttribute("results", Misc.guessClass(r, conf, ontoBean));
- model.addAttribute("ontoBean", ontoBean);
-
- addDataLinks(IRI, model, req, locale);
- addLodliveLink(locale, model, IRI);
- enrichResponse(model, r, req, res);
- return "resource";
- }
-
- private void addDataLinks(String IRI, ModelMap model, HttpServletRequest req, Locale locale) throws UnsupportedEncodingException {
-
- Map> rawdatalinks = new LinkedHashMap>();
- String queryString = (req.getQueryString() != null ? "&" + req.getQueryString().replaceAll("&", "&") : "");
-
- if (conf.getRedirectionStrategy().equals("pubby")) {
-
- Map list = new LinkedHashMap();
- list.put("xml", "?output=" + URLEncoder.encode("application/rdf+xml", "UTF-8") + queryString);
- list.put("ntriples", "?output=" + URLEncoder.encode("text/plain", "UTF-8") + queryString);
- list.put("turtle", "?output=" + URLEncoder.encode("text/turtle", "UTF-8") + queryString);
- list.put("json", "?output=" + URLEncoder.encode("application/rdf+json", "UTF-8") + queryString);
- list.put("ld+json", "?output=" + URLEncoder.encode("application/ld+json", "UTF-8") + queryString);
- rawdatalinks.put("rdf:", list);
-
- } else {
- Map list = new LinkedHashMap();
- list.put("xml", "?output=" + URLEncoder.encode("application/rdf+xml", "UTF-8") + queryString);
- list.put("ntriples", "?output=" + URLEncoder.encode("text/plain", "UTF-8") + queryString);
- list.put("turtle", "?output=" + URLEncoder.encode("text/turtle", "UTF-8") + queryString);
- list.put("ld+json", "?output=" + URLEncoder.encode("application/ld+json", "UTF-8") + queryString);
- rawdatalinks.put(messageSource.getMessage("footer.viewAs", null, "view as", locale), list);
- }
-
- if (conf.getEndPointType().equals("virtuoso")) {
- {
- Map list = new LinkedHashMap();
- list.put("atom", conf.getEndPointUrl() + "?output=application%2Fatom%2Bxml&query=DESCRIBE+%3C" + IRI + "%3E");
- list.put("json", conf.getEndPointUrl() + "?output=application%2Fodata%2Bjson&query=DESCRIBE+%3C" + IRI + "%3E");
- rawdatalinks.put("odata:", list);
- }
- {
- Map list = new LinkedHashMap();
- list.put("html", conf.getEndPointUrl() + "?output=text%2Fhtml&query=DESCRIBE+%3C" + IRI + "%3E");
- list.put("json", conf.getEndPointUrl() + "?output=application%2Fmicrodata%2Bjson&query=DESCRIBE+%3C" + IRI + "%3E");
- rawdatalinks.put("microdata:", list);
- }
- {
- Map list = new LinkedHashMap();
- list.put("csv", conf.getEndPointUrl() + "?output=text%2Fcsv&query=DESCRIBE+%3C" + IRI + "%3E");
- list.put("cxml", conf.getEndPointUrl() + "?output=format=text%2Fcxml&query=DESCRIBE+%3C" + IRI + "%3E");
- rawdatalinks.put("rawdata:", list);
- }
- }
- model.addAttribute("rawdatalinks", rawdatalinks);
-
- }
-
- private RedirectView redirect(HttpServletRequest req, String IRIsuffix) throws UnsupportedEncodingException {
-
- RedirectView r = new RedirectView();
- // preventing redirect of model attributes
- r.setExposeModelAttributes(false);
- r.setContentType("text/html");
- r.setHttp10Compatible(false);
- if (!conf.getHttpRedirectPrefix().equals("")) {
- // prefix mode
- String redirectUrl = conf.getHttpRedirectPrefix().replaceAll("^/", "");
- if (conf.getRedirectionStrategy().equals("pubby")) {
- r.setUrl(conf.getPublicUrlPrefix() + redirectUrl + IRIsuffix.replaceAll("^resource/", "") + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
- } else {
- r.setUrl(conf.getPublicUrlPrefix().replaceAll(IRIsuffix + "$", "") + redirectUrl + IRIsuffix + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
- }
- } else {
- // suffix mode
- String redirectUrl = conf.getHttpRedirectSuffix();
- // String[] redirectUrlArray = redirectUrl.split("/");
- // redirectUrl = "";
- // for (String string : redirectUrlArray) {
- // redirectUrl += URLEncoder.encode(string, "UTF-8") + "/";
- // }
- // redirectUrl = redirectUrl.replaceAll("/$", "");
- r.setUrl(req.getRequestURL() + redirectUrl + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
- }
-
- return r;
-
- }
-
- private void addLodliveLink(Locale locale, ModelMap model, String IRI) {
- if (locale.getLanguage().equals("it")) {
- model.addAttribute("lodliveUrl", "http://lodlive.it?" + IRI.replaceAll("#", "%23"));
- } else if (locale.getLanguage().equals("fr")) {
- model.addAttribute("lodliveUrl", "http://fr.lodlive.it?" + IRI.replaceAll("#", "%23"));
- } else if (locale.getLanguage().equals("gl")) {
- model.addAttribute("lodliveUrl", "http://gl.lodlive.it?" + IRI.replaceAll("#", "%23"));
- } else {
- model.addAttribute("lodliveUrl", "http://en.lodlive.it?" + IRI.replaceAll("#", "%23"));
- }
- }
-
- private void enrichResponse(ModelMap model, ResultBean r, HttpServletRequest req, HttpServletResponse res) {
-
- String publicUrl = r.getMainIRI();
- res.addHeader("Link", "<" + publicUrl + ">; rel=\"about\"");
-
- @SuppressWarnings("unchecked")
- Map> rawdatalinks = (LinkedHashMap>) model.get("rawdatalinks");
- for (String k : rawdatalinks.keySet()) {
- for (String k1 : rawdatalinks.get(k).keySet()) {
- res.addHeader("Link", "<" + rawdatalinks.get(k).get(k1) + ">; rel=\"alternate\"; type=\"application/rdf+xml\"; title=\"Structured Descriptor Document (" + k1 + ")\"");
- }
- }
- try {
- for (TripleBean t : r.getResources(r.getMainIRI()).get(r.getTypeProperty())) {
- res.addHeader("Link", "<" + t.getProperty().getProperty() + ">; rel=\"type\"");
- }
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
-
- @RequestMapping(value = "/rawdata")
- public ResponseEntity resourceRawController(ModelMap model, @RequestParam(value = "IRI") String IRI, @RequestParam(value = "sparql") String sparql, @RequestParam(value = "contentType", defaultValue = "application/rdf+xml") String contentType) {
- return resourceRaw(conf, model, IRI, sparql, contentType);
- }
-
- public ResponseEntity resourceRaw(ConfigurationBean conf, ModelMap model, @RequestParam(value = "IRI") String IRI, @RequestParam(value = "sparql") String sparql, @RequestParam(value = "contentType", defaultValue = "application/rdf+xml") String contentType) {
- // logger.trace("ResourceController.resourceRaw()");
- contentType = contentType.replaceAll("([a-zA-Z]) ([a-zA-Z])", "$1+$2");
- Lang lang = RDFLanguages.contentTypeToLang(contentType);
- try {
- HttpHeaders headers = new HttpHeaders();
- headers.add("Content-Type", contentType + "; charset=" + conf.getContentEncoding());
-
- if (sparql != null && sparql.equals("<>")) {
- com.hp.hpl.jena.rdf.model.Model m = ModelFactory.createDefaultModel();
- try {
- m.read(IRI);
- } catch (Exception e) {
- throw new Exception(messageSource.getMessage("error.noContentNegotiation", null, "sorry but content negotiation is not supported by the IRI", Locale.ENGLISH));
- }
- return new ResponseEntity(new ResourceBuilder(messageSource).buildRDFResource(IRI, m, lang, conf), headers, HttpStatus.OK);
- } else {
- return new ResponseEntity(new ResourceBuilder(messageSource).buildRDFResource(IRI, sparql, lang, conf), headers, HttpStatus.OK);
- }
-
- } catch (Exception e) {
- if (e.getMessage() != null && e.getMessage().startsWith("404")) {
- return new ResponseEntity(e.getMessage(), HttpStatus.NOT_FOUND);
- } else {
- return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
- }
- }
-
- }
-}
diff --git a/src/main/java/org/dvcama/lodview/controllers/SPARQLController.java b/src/main/java/org/dvcama/lodview/controllers/SPARQLController.java
deleted file mode 100644
index 0a04531..0000000
--- a/src/main/java/org/dvcama/lodview/controllers/SPARQLController.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.dvcama.lodview.controllers;
-
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-@Controller
-public class SPARQLController {
- @Autowired
- ConfigurationBean conf;
-
- @RequestMapping(value = { "/sparql", "/SPARQL" })
- public String sparql() {
-
- /* TODO: make this configurable allowing "proxy" features */
-
- return "redirect:" + conf.getEndPointUrl();
- }
-}
diff --git a/src/main/java/org/dvcama/lodview/controllers/StaticController.java b/src/main/java/org/dvcama/lodview/controllers/StaticController.java
deleted file mode 100644
index 1ba0149..0000000
--- a/src/main/java/org/dvcama/lodview/controllers/StaticController.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.dvcama.lodview.controllers;
-
-import java.util.Locale;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.CookieValue;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.util.UrlPathHelper;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Controller
-public class StaticController {
-
- final Logger logger = LoggerFactory.getLogger(StaticController.class);
-
- @Autowired
- ConfigurationBean conf;
-
- @Autowired
- private MessageSource messageSource;
-
- public StaticController() {
- // TODO Auto-generated constructor stub
- }
-
- public StaticController(MessageSource messageSource) {
- this.messageSource = messageSource;
- }
-
- @RequestMapping(value = "/")
- public String home(HttpServletRequest req, HttpServletResponse res, Model model, Locale locale, @CookieValue(value = "colorPair", defaultValue = "") String colorPair) {
- colorPair = conf.getRandomColorPair();
- Cookie c = new Cookie("colorPair", colorPair);
- c.setPath("/");
- res.addCookie(c);
- model.addAttribute("colorPair", colorPair);
- model.addAttribute("conf", conf);
- model.addAttribute("locale", locale.getLanguage());
- model.addAttribute("path", new UrlPathHelper().getContextPath(req).replaceAll("/lodview/", "/"));
- logger.debug("home controller");
- return "home";
- }
-
- @RequestMapping(value = "/lodviewmenu")
- public String lodviewmenu(Model model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "IRI") String IRI, @CookieValue(value = "colorPair", defaultValue = "") String colorPair) {
- if (colorPair.equals("")) {
- colorPair = conf.getRandomColorPair();
- Cookie c = new Cookie("colorPair", colorPair);
- c.setPath("/");
- res.addCookie(c);
- }
- return lodviewmenu(req, res, model, locale, IRI, conf, colorPair);
- }
-
- @RequestMapping(value = { "/lodviewcolor", "/**/lodviewcolor" })
- public ResponseEntity lodviewcolor(Model model, HttpServletRequest req, HttpServletResponse res, Locale locale, @RequestParam(value = "colorPair") String colorPair) {
- Cookie c = new Cookie("colorPair", colorPair);
- c.setPath("/");
- res.addCookie(c);
- return new ResponseEntity(HttpStatus.OK);
- }
-
- public String lodviewmenu(HttpServletRequest req, HttpServletResponse res, Model model, Locale locale, @RequestParam(value = "IRI", defaultValue = "") String IRI, ConfigurationBean conf, String colorPair) {
- model.addAttribute("conf", conf);
- model.addAttribute("locale", locale.getLanguage());
- model.addAttribute("IRI", IRI);
- model.addAttribute("colorPair", colorPair);
- model.addAttribute("path", new UrlPathHelper().getContextPath(req).replaceAll("/lodview/", "/"));
- return "menu";
- }
-
-}
diff --git a/src/main/java/org/dvcama/lodview/endpoint/SPARQLEndPoint.java b/src/main/java/org/dvcama/lodview/endpoint/SPARQLEndPoint.java
deleted file mode 100644
index f64166f..0000000
--- a/src/main/java/org/dvcama/lodview/endpoint/SPARQLEndPoint.java
+++ /dev/null
@@ -1,334 +0,0 @@
-package org.dvcama.lodview.endpoint;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.jena.atlas.web.auth.HttpAuthenticator;
-import org.apache.jena.atlas.web.auth.SimpleAuthenticator;
-import org.dvcama.lodview.bean.OntologyBean;
-import org.dvcama.lodview.bean.PropertyBean;
-import org.dvcama.lodview.bean.TripleBean;
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.dvcama.lodview.utils.Misc;
-
-import com.hp.hpl.jena.graph.Node;
-import com.hp.hpl.jena.query.QueryExecution;
-import com.hp.hpl.jena.query.QueryExecutionFactory;
-import com.hp.hpl.jena.query.QuerySolution;
-import com.hp.hpl.jena.query.ResultSet;
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.rdf.model.Property;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-import com.hp.hpl.jena.rdf.model.Resource;
-import com.hp.hpl.jena.rdf.model.Statement;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SPARQLEndPoint {
-
- private static Logger logger = LoggerFactory.getLogger(SPARQLEndPoint.class);
-
- OntologyBean ontoBean;
- String locale = "en";
- protected ConfigurationBean conf;
-
- public SPARQLEndPoint(ConfigurationBean conf, OntologyBean ontoBean, String locale) {
- this.locale = locale;
- this.ontoBean = ontoBean;
- this.conf = conf;
- // TODO Auto-generated constructor stub
- }
-
- public List doQuery(String IRI, String aProperty, int start, List queries, String filter, String overrideProperty) throws Exception {
- // logger.trace("executing query on " + conf.getEndPointUrl());
- List results = new ArrayList();
- HttpAuthenticator auth = null;
- if (conf.getAuthPassword() != null && !conf.getAuthPassword().equals("")) {
- auth = new SimpleAuthenticator(conf.getAuthUsername(), conf.getAuthPassword().toCharArray());
- }
- for (String query : queries) {
- // logger.trace("-- " + parseQuery(query, IRI, aProperty,
- // start, filter));
- QueryExecution qe = QueryExecutionFactory.sparqlService(conf.getEndPointUrl(), parseQuery(query, IRI, aProperty, start, filter), auth);
- results = moreThenOneQuery(qe, results, 0, overrideProperty);
- qe.close();
- }
-
- if (results.size() == 0) {
- if (IRI != null) {
- boolean hasInverses = false;
- for (String query : conf.getDefaultInversesTest()) {
- // logger.trace("query!!! " + parseQuery(query, IRI,
- // aProperty, start, filter));
- QueryExecution qe = QueryExecutionFactory.sparqlService(conf.getEndPointUrl(), parseQuery(query, IRI, aProperty, start, filter), auth);
- if (!hasInverses) {
- hasInverses = qe.execAsk();
- }
- qe.close();
- }
- if (!hasInverses) {
- throw new Exception("404 - not found");
- }
- }
- }
- return results;
- }
-
- private List moreThenOneQuery(QueryExecution qe, List results, int retry, String overrideProperty) throws Exception {
-
- try {
- ResultSet rs = qe.execSelect();
- while (rs.hasNext()) {
- TripleBean rb = new TripleBean();
- QuerySolution qs = rs.next();
- String property = "";
- if (overrideProperty != null) {
- property = overrideProperty;
- } else if (qs.get("p") != null) {
- property = qs.get("p").asNode().toString();
- }
-
- try {
- if (qs.get("s") != null && !qs.get("s").asNode().toString().startsWith("http://")) { // probably
- // a
- // bn
- rb.setIRI(qs.get("s").asNode().toString());
- rb.setNsIRI("_:" + rb.getIRI());
- } else if (qs.get("s") != null && qs.get("s").asNode().toString().startsWith("http://")) {
- rb.setIRI(qs.get("s").asNode().toString());
- rb.setNsIRI(Misc.toNsResource(rb.getIRI(), conf));
- rb.setUrl(Misc.toBrowsableUrl(rb.getIRI(), conf));
- }
-
- PropertyBean p = new PropertyBean();
- p.setNsProperty(Misc.toNsResource(property, conf));
- p.setProperty(property);
- if (ontoBean != null) {
- p.setLabel(ontoBean.getEscapedValue("label", locale, property));
- p.setComment(ontoBean.getEscapedValue("comment", locale, property));
- }
- p.setPropertyUrl(Misc.toBrowsableUrl(property, conf));
- rb.setProperty(p);
- if (qs.get("o") != null) {
- Node object = qs.get("o").asNode();
- if (object.isURI()) {
- rb.setType("iri");
- rb.setValue(object.toString(false));
- } else if (object.isLiteral()) {
- rb.setType("literal");
- rb.setDataType(object.getLiteralDatatypeURI());
- rb.setNsDataType(Misc.toNsResource(object.getLiteralDatatypeURI(), conf));
- rb.setLang(object.getLiteralLanguage());
- rb.setValue(object.getLiteralLexicalForm());
- } else if (object.isBlank()) {
- rb.setType("bnode");
- rb.setValue(object.toString(false));
- }
- } else {
- rb.setType("literal");
- rb.setValue("");
- }
- results.add(rb);
- } catch (Exception e) {
- logger.error("error? " + e.getMessage());
- // e.printStackTrace();
- }
- }
- } catch (Exception ez) {
- if (retry < 3) {
- retry++;
- // logger.trace("query failed (" + ez.getMessage() +
- // "), I'm giving another chance (" + retry + "/3)");
- return moreThenOneQuery(qe, results, retry, overrideProperty);
- }
- ez.printStackTrace();
- throw new Exception("connection refused");
- }
-
- return results;
- }
-
- public List doQuery(String IRI, List queries, String overrideProperty) throws Exception {
- return doQuery(IRI, null, -1, queries, null, overrideProperty);
- }
-
- public List doLocalQuery(Model m, String IRI, List queries, String about) throws Exception {
- return doLocalQuery(m, IRI, null, -1, queries, about);
- }
-
- public List doLocalQuery(Model model, String IRI, List queries) throws Exception {
- return doLocalQuery(model, IRI, null, -1, queries, null);
- }
-
- public List doLocalQuery(Model model, String IRI, String localProperty, int start, List queries, String overrideProperty) throws Exception {
- // logger.trace("executing query on model based on " + IRI);
- List results = new ArrayList();
-
- for (String query : queries) {
- QueryExecution qe = QueryExecutionFactory.create(parseQuery(query, IRI, localProperty, start, null), model);
- try {
- ResultSet rs = qe.execSelect();
- while (rs.hasNext()) {
- TripleBean rb = new TripleBean();
- QuerySolution qs = rs.next();
- String property = "";
- if (overrideProperty != null) {
- property = overrideProperty;
- } else if (qs.get("p") != null) {
- property = qs.get("p").asNode().toString();
- }
- try {
- if (qs.get("s") != null && !qs.get("s").asNode().toString().startsWith("http://")) { // probably
- // blanknode
- rb.setIRI(qs.get("s").asNode().toString());
- rb.setNsIRI("_:" + rb.getIRI());
- } else if (qs.get("s") != null && qs.get("s").asNode().toString().startsWith("http://")) {
- rb.setIRI(qs.get("s").asNode().toString());
- rb.setNsIRI(Misc.toNsResource(rb.getIRI(), conf));
- rb.setUrl(Misc.toBrowsableUrl(rb.getIRI(), conf));
- }
- PropertyBean p = new PropertyBean();
- p.setNsProperty(Misc.toNsResource(property, conf));
- p.setProperty(property);
- p.setPropertyUrl(Misc.toBrowsableUrl(property, conf));
- if (ontoBean != null) {
- p.setLabel(ontoBean.getEscapedValue("label", locale, property));
- p.setComment(ontoBean.getEscapedValue("comment", locale, property));
- }
- rb.setProperty(p);
- if (qs.get("o") != null) {
- Node object = qs.get("o").asNode();
- if (object.isURI()) {
- rb.setType("iri");
- rb.setValue(object.toString(false));
- } else if (object.isLiteral()) {
- rb.setType("literal");
- rb.setDataType(object.getLiteralDatatypeURI());
- rb.setNsDataType(Misc.toNsResource(object.getLiteralDatatypeURI(), conf));
- rb.setLang(object.getLiteralLanguage());
- rb.setValue(object.getLiteralLexicalForm());
- } else if (object.isBlank()) {
- rb.setType("bnode");
- rb.setValue(object.toString(false));
- }
- } else {
- rb.setType("literal");
- rb.setValue("");
- }
- results.add(rb);
- } catch (Exception e) {
- logger.error("error? " + e.getMessage());
- e.printStackTrace();
- }
- }
- } catch (Exception e) {
- throw new Exception("500 - " + e.getMessage());
- } finally {
- qe.close();
- }
- }
-
- if (results.size() == 0) {
- throw new Exception("404 - not found");
- }
- return results;
- }
-
- public Model extractData(Model result, String IRI, String sparql, List queries) throws Exception {
-
- // logger.trace("executing query on " + sparql);
- Resource subject = result.createResource(IRI);
- for (String query : queries) {
- QueryExecution qe = QueryExecutionFactory.sparqlService(sparql, parseQuery(query, IRI, null, -1, null));
- try {
- ResultSet rs = qe.execSelect();
-
- List sl = new ArrayList();
- while (rs.hasNext()) {
- QuerySolution qs = rs.next();
- RDFNode subject2 = qs.get("s");
- RDFNode property = qs.get("p");
- RDFNode object = qs.get("o");
- result.add(result.createStatement(subject2 != null ? subject2.asResource() : subject, property.as(Property.class), object));
- }
- result.add(sl);
- } catch (Exception e) {
- e.printStackTrace();
- throw new Exception("error in query execution: " + e.getMessage());
- } finally {
- qe.close();
- }
- }
- return result;
- }
-
- public Model extractLocalData(Model result, String IRI, Model m, List queries) throws Exception {
-
- // logger.trace("executing query on IRI");
- Resource subject = result.createResource(IRI);
- for (String query : queries) {
- QueryExecution qe = QueryExecutionFactory.create(parseQuery(query, IRI, null, -1, null), m);
- try {
- ResultSet rs = qe.execSelect();
- List sl = new ArrayList();
- while (rs.hasNext()) {
- QuerySolution qs = rs.next();
- RDFNode subject2 = qs.get("s");
- RDFNode property = qs.get("p");
- RDFNode object = qs.get("o");
- result.add(result.createStatement(subject2 != null ? subject2.asResource() : subject, property.as(Property.class), object));
- }
- result.add(sl);
- } catch (Exception e) {
- e.printStackTrace();
- throw new Exception("error in query execution: " + e.getMessage());
- } finally {
- qe.close();
- }
- }
- return result;
- }
-
- public String parseQuery(String query, String IRI, String property, int start, String filter) {
- if (IRI != null) {
- /* managing issues depending on "$" in some IRIs */
- query = query.replaceAll("\\$\\{IRI\\}", IRI.replaceAll("\\$", "%24")).replaceAll("%24", "\\$");
- }
- if (property != null) {
- query = query.replaceAll("\\$\\{PROPERTY\\}", property);
- }
- if (filter != null) {
- query = query.replaceAll("\\$\\{FILTERPROPERTY\\}", filter);
- }
- if (query.indexOf("STARTFROM") > 0) {
- query = query.replaceAll("\\$\\{STARTFROM\\}", "" + start);
- } else if (start > 0) {
- query = query.replaceAll("LIMIT (.+)$", "OFFSET " + start + " LIMIT $1");
- }
- return query;
- }
-
- public String testEndpoint(ConfigurationBean conf) {
- logger.info("testing connection on " + conf.getEndPointUrl());
- QueryExecution qe = QueryExecutionFactory.sparqlService(conf.getEndPointUrl(), "select ?s {?s ?p ?o} LIMIT 1");
- String msg = "";
- try {
- ResultSet rs = qe.execSelect();
- if (rs.hasNext()) {
- logger.info("is online");
- msg = "online";
- } else {
- logger.info("is offline");
- msg = "offline";
- }
- } catch (Exception e) {
- logger.info("is offline " + e.getMessage());
- msg = "offline " + e.getMessage();
- } finally {
- qe.close();
- }
- return msg;
- }
-
-}
diff --git a/src/main/java/org/dvcama/lodview/utils/Misc.java b/src/main/java/org/dvcama/lodview/utils/Misc.java
deleted file mode 100644
index 54f47e8..0000000
--- a/src/main/java/org/dvcama/lodview/utils/Misc.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package org.dvcama.lodview.utils;
-
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.dvcama.lodview.bean.OntologyBean;
-import org.dvcama.lodview.bean.PropertyBean;
-import org.dvcama.lodview.bean.ResultBean;
-import org.dvcama.lodview.bean.TripleBean;
-import org.dvcama.lodview.conf.ConfigurationBean;
-import org.dvcama.lodview.conf.ConfigurationBean.ColorStrategy;
-
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.rdf.model.NodeIterator;
-import com.hp.hpl.jena.rdf.model.RDFNode;
-
-public class Misc {
-
- public static String toNsResource(String iri, ConfigurationBean conf) {
- if (iri != null && !iri.equals("")) {
- // if (iri.startsWith(conf.getIRInamespace())) {
- // return conf.getNsURIPrefix(conf.getIRInamespace()) + ":" +
- // iri.replaceAll(conf.getIRInamespace() + "(.+)$", "$1");
- // } else {
- // }
- return conf.getNsURIPrefix(iri.replaceAll("[^/#]+$", "")) + ":" + iri.replaceAll(".+[/|#]([^/#]+)$", "$1");
-
- } else {
- return null;
- }
- }
-
- public static String toBrowsableUrl(String value, ConfigurationBean conf) {
-
- if (!conf.getPublicUrlSuffix().equals("") && value.startsWith(conf.getIRInamespace())) {
- try {
- return conf.getPublicUrlPrefix() + "?" + conf.getPublicUrlSuffix() + "IRI=" + java.net.URLEncoder.encode(value, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- return value;
- }
- } else {
- return value.replaceAll("^" + conf.getIRInamespace() + "(.+)$", conf.getPublicUrlPrefix() + "$1").replaceAll("([^:])//", "$1/");
- }
-
- }
-
- public static String guessColor(String colorPair, ResultBean r, ConfigurationBean conf) {
- switch(conf.getColorStrategy())
- {
- case CLASS: {
- try {
- List m = r.getResources(r.getMainIRI()).get(r.getTypeProperty());
- for (TripleBean tripleBean : m)
- {
- colorPair = conf.getColorPairMatcher().get(tripleBean.getValue());
- if(colorPair!=null) return colorPair;
- }
- } catch (Exception e) {
- }
- return conf.getColorPairMatcher().get("http://lodview.it/conf#otherClasses");
- }
- case PREFIX: {
- for (String prefix : conf.getColorPairMatcher().keySet()) {
- if(r.getMainIRI().startsWith(prefix))
- {
- return conf.getColorPairMatcher().get(prefix);
- }
- }
- }
- default: break;
- }
- return colorPair;
- }
-
- public static ResultBean guessClass(ResultBean r, ConfigurationBean conf, OntologyBean ontoBean) {
- try {
- if (conf.getMainOntologiesPrefixes().size() > 0) {
- String mainIri = r.getMainIRI();
- Map> mainResource = r.getResources(mainIri);
- TreeMap> resultOrderedMap = new TreeMap>();
-
- List m = new ArrayList(mainResource.get(r.getTypeProperty()));
- Model model = ontoBean.getModel();
- for (TripleBean tripleBean : m) {
- int dept = 0;
- if (startsWithAtLeastOne(tripleBean.getValue(), conf.getMainOntologiesPrefixes())) {
- dept = countFathers(tripleBean.getValue(), 0, model);
- }
- List l = null;
- if (resultOrderedMap.get(dept) != null) {
- l = resultOrderedMap.get(dept);
- } else {
- l = new ArrayList();
- }
- l.add(tripleBean);
- resultOrderedMap.put(dept, l);
- // removing types
- r.removeResource(tripleBean, mainIri);
- }
- if (resultOrderedMap.size() > 0) {
- for (Integer dept : resultOrderedMap.descendingKeySet()) {
- List l = resultOrderedMap.get(dept);
- for (TripleBean tripleBean : l) {
- // adding ordered types
- r.addResource(tripleBean, mainIri);
- }
- }
- }
- }
- return r;
-
- } catch (Exception e) {
- // e.printStackTrace();
- }
- return r;
- }
-
- private static Integer countFathers(String value, int i, Model model) {
- NodeIterator iter = model.listObjectsOfProperty(model.createResource(value), model.createProperty("http://www.w3.org/2000/01/rdf-schema#subClassOf"));
- while (iter.hasNext()) {
- RDFNode node = iter.next();
- return countFathers(node.toString(), ++i, model);
- }
- return i;
- }
-
- private static boolean startsWithAtLeastOne(String value, List startsWithList) {
- for (String string : startsWithList) {
- if (value.startsWith(string)) {
- return true;
- }
- }
- return false;
- }
-
- public static String stripHTML(String value) {
-
- value = value.replaceAll("?\\w[^>]*>", "");
-
- return value;
- }
-
-}
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..9dbe827
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+spring.mvc.pathmatch.matching-strategy=ant_path_matcher
+spring.mvc.view.prefix=/WEB-INF/views/
+spring.mvc.view.suffix=.jsp
+lode.ontoDir=ontologies
diff --git a/src/main/resources/conf/conf-linked.ttl b/src/main/resources/conf/conf-linked.ttl
new file mode 100644
index 0000000..f67dfd0
--- /dev/null
+++ b/src/main/resources/conf/conf-linked.ttl
@@ -0,0 +1,124 @@
+@prefix conf: .
+@prefix meta: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix xsd: .
+@prefix owl: .
+@prefix dc: .
+@prefix dcterms: .
+@prefix foaf: .
+@prefix skos: .
+@prefix geo: .
+@prefix ocd: .
+@prefix units: .
+@prefix geonames: .
+@prefix void: .
+@prefix dbpedia-owl: .
+@prefix yago: .
+@prefix gml: .
+@prefix dbpedia: .
+@prefix dbpprop: .
+@prefix metalex: .
+@prefix frbr: .
+@prefix gn: .
+@prefix schema-org: .
+@prefix dwc: .
+@prefix ibc: .
+@prefix bio: .
+@prefix ods: .
+@prefix shoah: .
+@prefix bibo: .
+@prefix org: .
+@prefix bbc: .
+
+<> a conf:Configuration;
+
+## EndPoint
+
+ conf:contentEncoding "UTF-8";
+
+
+## default query used to get direct properties, you can add a "FROM" clause here,
+## ${IRI} will be replaced, it's always recommended to specify a limit for the query
+
+ conf:defaultQueries "select distinct * {<${IRI}> ?p ?o} LIMIT 10000";
+
+
+## default query used to get resource to be included in serializations different
+## from HTML, it's always recommended to specify a limit for the query
+## ${IRI} will be replaced
+
+ conf:defaultRawDataQueries """select distinct * { {<${IRI}> ?p ?o}
+ UNION
+ {<${IRI}> ?p1 ?s . ?s ?p ?o FILTER(isBlank(?s))}
+ } LIMIT 10000""" ;
+
+## skip domains that are probably offline
+
+ conf:skipDomains "ace.dbpedia.org" , "af.dbpedia.org" , "als.dbpedia.org" , "am.dbpedia.org" , "an.dbpedia.org" ,
+ "ang.dbpedia.org" , "ar.dbpedia.org" , "arc.dbpedia.org" , "arz.dbpedia.org" , "ast.dbpedia.org" ,
+ "ay.dbpedia.org" , "az.dbpedia.org" , "ba.dbpedia.org" , "bar.dbpedia.org" , "bat_smg.dbpedia.org" ,
+ "bcl.dbpedia.org" , "be.dbpedia.org" , "be_x_old.dbpedia.org" , "bg.dbpedia.org" , "bi.dbpedia.org" ,
+ "bn.dbpedia.org" , "bo.dbpedia.org" , "br.dbpedia.org" , "bs.dbpedia.org" , "bxr.dbpedia.org" ,
+ "ca.dbpedia.org" , "cbk_zam.dbpedia.org" , "ce.dbpedia.org" , "ceb.dbpedia.org" , "chy.dbpedia.org" ,
+ "ckb.dbpedia.org" , "co.dbpedia.org" , "crh.dbpedia.org" , "csb.dbpedia.org" , "cu.dbpedia.org" ,
+ "cv.dbpedia.org" , "cy.dbpedia.org" , "da.dbpedia.org" , "diq.dbpedia.org" , "dsb.dbpedia.org" ,
+ "ee.dbpedia.org" , "eo.dbpedia.org" , "et.dbpedia.org" , "ext.dbpedia.org" , "fa.dbpedia.org" ,
+ "fi.dbpedia.org" , "fiu_vro.dbpedia.org" , "fo.dbpedia.org" , "frp.dbpedia.org" , "frr.dbpedia.org" ,
+ "fur.dbpedia.org" , "fy.dbpedia.org" , "ga.dbpedia.org" , "gag.dbpedia.org" , "gan.dbpedia.org" ,
+ "gd.dbpedia.org" , "gl.dbpedia.org" , "gn.dbpedia.org" , "got.dbpedia.org" , "gv.dbpedia.org" ,
+ "he.dbpedia.org" , "hi.dbpedia.org" , "hif.dbpedia.org" , "hr.dbpedia.org" , "hsb.dbpedia.org" ,
+ "ht.dbpedia.org" , "hu.dbpedia.org" , "hy.dbpedia.org" , "ia.dbpedia.org" , "ie.dbpedia.org" ,
+ "ilo.dbpedia.org" , "io.dbpedia.org" , "is.dbpedia.org" , "jbo.dbpedia.org" , "jv.dbpedia.org" ,
+ "ka.dbpedia.org" , "kaa.dbpedia.org" , "kg.dbpedia.org" , "kk.dbpedia.org" , "kl.dbpedia.org" ,
+ "km.dbpedia.org" , "kn.dbpedia.org" , "krc.dbpedia.org" , "ku.dbpedia.org" , "kv.dbpedia.org" ,
+ "kw.dbpedia.org" , "la.dbpedia.org" , "lad.dbpedia.org" , "lb.dbpedia.org" , "lez.dbpedia.org" ,
+ "li.dbpedia.org" , "lij.dbpedia.org" , "lmo.dbpedia.org" , "ln.dbpedia.org" , "lt.dbpedia.org" ,
+ "lv.dbpedia.org" , "mdf.dbpedia.org" , "mg.dbpedia.org" , "mhr.dbpedia.org" , "mi.dbpedia.org" ,
+ "mk.dbpedia.org" , "ml.dbpedia.org" , "mn.dbpedia.org" , "mr.dbpedia.org" , "ms.dbpedia.org" ,
+ "mt.dbpedia.org" , "mwl.dbpedia.org" , "my.dbpedia.org" , "na.dbpedia.org" , "nah.dbpedia.org" ,
+ "nap.dbpedia.org" , "nds.dbpedia.org" , "nds_nl.dbpedia.org" , "ne.dbpedia.org" , "new.dbpedia.org" ,
+ "nn.dbpedia.org" , "no.dbpedia.org" , "nov.dbpedia.org" , "nrm.dbpedia.org" , "oc.dbpedia.org" ,
+ "or.dbpedia.org" , "os.dbpedia.org" , "pa.dbpedia.org" , "pap.dbpedia.org" , "pcd.dbpedia.org" ,
+ "pdc.dbpedia.org" , "pms.dbpedia.org" , "pnb.dbpedia.org" , "pnt.dbpedia.org" , "qu.dbpedia.org" ,
+ "rm.dbpedia.org" , "rn.dbpedia.org" , "ro.dbpedia.org" , "roa_rup.dbpedia.org" , "roa_tara.dbpedia.org" ,
+ "ru.dbpedia.org" , "rue.dbpedia.org" , "rw.dbpedia.org" , "sa.dbpedia.org" , "sah.dbpedia.org" ,
+ "sc.dbpedia.org" , "scn.dbpedia.org" , "sco.dbpedia.org" , "se.dbpedia.org" , "sg.dbpedia.org" ,
+ "sh.dbpedia.org" , "si.dbpedia.org" , "simple.dbpedia.org" , "sk.dbpedia.org" , "sl.dbpedia.org" ,
+ "so.dbpedia.org" , "sq.dbpedia.org" , "sr.dbpedia.org" , "srn.dbpedia.org" , "stq.dbpedia.org" ,
+ "su.dbpedia.org" , "sv.dbpedia.org" , "sw.dbpedia.org" , "szl.dbpedia.org" , "ta.dbpedia.org" ,
+ "te.dbpedia.org" , "tg.dbpedia.org" , "th.dbpedia.org" , "tk.dbpedia.org" , "tl.dbpedia.org" ,
+ "tpi.dbpedia.org" , "tr.dbpedia.org" , "tt.dbpedia.org" , "ty.dbpedia.org" , "udm.dbpedia.org" ,
+ "ug.dbpedia.org" , "uk.dbpedia.org" , "ur.dbpedia.org" , "uz.dbpedia.org" , "ve.dbpedia.org" ,
+ "vec.dbpedia.org" , "vep.dbpedia.org" , "vi.dbpedia.org" , "vls.dbpedia.org" , "vo.dbpedia.org" ,
+ "war.dbpedia.org" , "wo.dbpedia.org" , "wuu.dbpedia.org" , "xmf.dbpedia.org" , "yi.dbpedia.org" ,
+ "yo.dbpedia.org" , "zea.dbpedia.org" , "zh.dbpedia.org" , "zh_classical.dbpedia.org" , "zh_min_nan.dbpedia.org" ,
+ "zh_yue.dbpedia.org" , "eml.dbpedia.org" , "ksh.dbpedia.org" , "pfl.dbpedia.org" , "zh-yue.dbpedia.org" ,
+ "zh-min-nan.dbpedia.org" , "be-x-old.dbpedia.org" , "bat-smg.dbpedia.org" ;
+
+
+########################################################################################
+######################## configuring the webapp ########################
+########################################################################################
+
+
+## document specific property used in the HTML resource page, it's possible to use
+## prefixes or not
+
+ conf:typeProperties rdf:type;
+ conf:titleProperties dc:title , dcterms:title, rdfs:label , , , , gn:officialName , gn:name , rdf:value , foaf:surname , , , schema-org:name, ;
+ conf:descriptionProperties rdfs:comment , skos:definition , dc:description , dcterms:description , dbpedia-owl:abstract ;
+ conf:imageProperties foaf:depiction;
+ conf:longitudeProperties geo:long;
+ conf:latitudeProperties geo:lat;
+ conf:linkingProperties owl:sameAs , skos:exactMatch , dbpedia-owl:wikiPageRedirects;
+
+
+## preferred language for title and description ("auto" for delegate to the client)
+
+ conf:preferredLanguage "auto"; ## eg. "en" or "it"
+
+
+## just a marker to insert a point on the last row
+
+ conf:last "." .
\ No newline at end of file
diff --git a/src/main/resources/conf/conf.ttl b/src/main/resources/conf/conf.ttl
new file mode 100644
index 0000000..1b01b53
--- /dev/null
+++ b/src/main/resources/conf/conf.ttl
@@ -0,0 +1,225 @@
+@prefix conf: .
+@prefix meta: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix xsd: .
+@prefix owl: .
+@prefix dc: .
+@prefix dcterms: .
+@prefix foaf: .
+@prefix skos: .
+@prefix geo: .
+@prefix ocd: .
+@prefix units: .
+@prefix geonames: .
+@prefix void: .
+@prefix dbpedia-owl: .
+@prefix yago: .
+@prefix gml: .
+@prefix dbpedia: .
+@prefix dbpprop: .
+@prefix metalex: .
+@prefix frbr: .
+@prefix gn: .
+@prefix schema-org: .
+@prefix dwc: .
+@prefix ibc: .
+@prefix bio: .
+@prefix ods: .
+@prefix shoah: .
+@prefix bibo: .
+@prefix org: .
+@prefix bbc: .
+@prefix npg: .
+@prefix prism21: .
+@prefix rso: .
+@prefix crm: .
+@prefix bmuseum: .
+@prefix bbc: .
+@prefix po: .
+@prefix lgdo: .
+@prefix oad: .
+@prefix crm-owl: .
+@prefix aemetonto: .
+@prefix bibleontology: .
+@prefix cdoc: .
+@prefix cc: .
+@prefix prov: .
+@prefix skos-xl: .
+@prefix muninn: .
+@prefix eac-cpf: .
+@prefix time: .
+@prefix claros: .
+@prefix crm120111: .
+@prefix rel: .
+
+
+<> a conf:Configuration;
+
+## first of all
+## IRIs namespace we use to replace the webapp base (eg. http://localhost:8080/lodview/), an
+## installation on dbpedia domain should use
+
+ conf:IRInamespace ;
+
+## EndPoint
+
+ conf:endpoint ;
+ conf:endpointType "virtuoso"; ## just "virtuoso" is handled right now, this will add some "rawdata"
+ ## options in the footer, leave this blank if you don't want these links
+
+########## give it a try opening http://localhost:8080/lodview/Rome
+
+
+## we don't like it so much, but you can set a prefix to activate 303 redirects
+## to the HTML representation of the resources, live it blank if you want to
+## use the "pure content negotiation mode", WARNING use suffix OR prefix, not both
+
+ conf:httpRedirectSuffix ".html"; ## or eg. ".html";
+ ##conf:httpRedirectPrefix "/page/"; ## or eg. "";
+
+ ##conf:httpRedirectExcludeList ""; ## a comma separeted list of regex to match which resources will use "pure content negotiation mode"
+ ## usually you have to leave this blank but if conf:redirectionStrategy is setted to "pubby" this could be
+ ## useful (eg. dbpedia uses /resource --> /page but leaves /ontology --> /ontology)
+
+ conf:redirectionStrategy ""; ## set it to "pubby" to use exactly the dbpedia redirection behaviour
+
+
+
+## mode configurations
+
+ conf:contentEncoding "UTF-8";
+
+ ## base64 HTTP authentication to the endpoint
+ conf:authUsername "";
+ conf:authPassword "";
+
+
+
+## default query used to get direct properties, you can add a "FROM" clause here,
+## ${IRI} will be replaced, it's always recommended to specify a limit for the query
+## the query can be seplified removing the last 2 unions to improve performance (usually not needed)
+
+ conf:defaultQueries """select distinct ?s ?p ?o {
+ {<${IRI}> ?p ?o}
+ UNION
+ {<${IRI}> ?p1 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
+ UNION
+ {<${IRI}> ?p1 ?s1 . FILTER(isBlank(?s1)) . ?s1 ?p2 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
+ UNION
+ {<${IRI}> ?p1 ?s1 . FILTER(isBlank(?s1)) . ?s1 ?p2 ?s2 . FILTER(isBlank(?s2)) . ?s2 ?p3 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
+ } LIMIT 10000""" ;
+
+
+## default query used to get resource to be included in serializations different
+## from HTML, it's always recommended to specify a limit for the query
+## ${IRI} will be replaced
+## the query can be seplified removing the last 2 unions to improve performance (usually not needed)
+
+ conf:defaultRawDataQueries """select distinct ?s ?p ?o {
+ {<${IRI}> ?p ?o}
+ UNION
+ {<${IRI}> ?p1 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
+ UNION
+ {<${IRI}> ?p1 ?s1 . FILTER(isBlank(?s1)) . ?s1 ?p2 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
+ UNION
+ {<${IRI}> ?p1 ?s1 . FILTER(isBlank(?s1)) . ?s1 ?p2 ?s2 . FILTER(isBlank(?s2)) . ?s2 ?p3 ?s . FILTER(isBlank(?s)) . ?s ?p ?o}
+ } LIMIT 10000""" ;
+
+
+## default query used to extract inverse relations
+
+ conf:defaultInversesQueries "select distinct ?p {?p <${PROPERTY}> <${IRI}>.} OFFSET ${STARTFROM} LIMIT 10";
+ conf:defaultInversesCountQueries "select (count(distinct ?s) AS ?o) ?p {?s ?p <${IRI}>. FILTER(!isBlank(?s))} GROUP BY ?p LIMIT 100";
+ conf:defaultInversesTest "ASK {?s ?p <${IRI}>}";
+
+## define if inverse relations have to be automatically opened (open|close)
+ conf:defaultInverseBehaviour "close";
+
+########################################################################################
+######################## configuring the webapp ########################
+########################################################################################
+
+## define how clients access your app, typically you have to specify your public domain
+## if you are using a proxy, set it at for testing, an installation on dbpedia
+## domain should use
+
+ conf:publicUrlPrefix ; ## or
+
+
+## solve IRI issues in particular environments (proxypass, etc.)
+
+ conf:forceIriEncoding "auto"; ## or "decode" or "encode"
+
+## home link (accessible from the banner)
+
+ conf:homeUrl ;
+
+
+## static resources publishing point, "staticResources/" is needed if you are going
+## to serve static content within the web application, probably on a production
+## environment you have to change "http://localhost:8080/lodview/" to something like
+## "http://data.yourdomain.com/staticResources/", on a test environment you can set it
+## at
+
+ conf:staticResourceURL ;
+
+## choosing the lower class in hierarchy to put it on the top right of the page
+## put in mainOntologies the prefixes you need to filter the resource's classes
+## you need also to add the ontology file in WEB-INF/ontologies
+## leave conf:mainOntologies blank if you don't want lodlive do this job
+
+## conf:mainOntologiesPrefixes YOUR-PREFIX:;
+
+## document specific property used in the HTML resource page, it's possible to use
+## prefixes or not
+
+ conf:typeProperties rdf:type;
+
+ conf:titleProperties dc:title , dcterms:title, rdfs:label , ,
+ , ,
+ gn:officialName , gn:name , rdf:value , foaf:surname , , ;
+
+ conf:descriptionProperties rdfs:comment , dc:description , dcterms:description ,
+ dc:description , skos:definition , ;
+
+ conf:imageProperties foaf:depiction , , crm-owl:P138i_has_representation ,
+ ;
+
+ conf:longitudeProperties geo:long;
+ conf:latitudeProperties geo:lat;
+ conf:linkingProperties owl:sameAs , skos:exactMatch , gn:locatedIn , ;
+
+ conf:videoProperties ;
+ conf:audioProperties ;
+
+## preferred language for title and description ("auto" for delegate to the client)
+
+ conf:preferredLanguage "auto"; ## eg. "en" or "it"
+
+
+## interface colors, choose a pair or a list for random colors
+
+ conf:colorPair "#06c-#0059b3" ;
+
+#### or bind classes and colors
+##
+## conf:colorPair conf:byClass;
+
+
+## license information (will be added at the very end of the page)
+
+ conf:license "" ; ## eg. "Licensed under Creative Commons Attribution 4.0 International (CC BY 4.0)" ;
+
+## just a marker to insert a point on the last row
+
+ conf:last ".".
+
+#### uncomment only if you have configured "colors by class"
+##
+## conf:hasColorPair "#c3a116-#ac8c13".
+## ontology:Place conf:hasColorPair "#715287-#624775".
+## conf:hasColorPair "#914848-#7d3e3e".
+## conf:hasColorPair "#6d8058-#5e6f4c".
+## conf:hasColorPair "#5b8a97-#4f7783".
+## conf:hasColorPair "#528775-#477565".
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
deleted file mode 100644
index 80e6c5c..0000000
--- a/src/main/resources/logback.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
- true
-
-
-
-
-
-
-
- %-5level %logger{0} - %msg%n
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties
deleted file mode 100644
index de515ef..0000000
--- a/src/main/resources/messages_en.properties
+++ /dev/null
@@ -1,37 +0,0 @@
-label.resource = resource
-label.resources = resources
-label.connectedResource = connected resource
-label.connectedResources = connected resources
-label.toTop = to top
-label.go = go
-label.inverseProperty = is {0} of
-label.moreExample = see more examples
-label.anEntityOfType = an entity of type
-
-title.colorPicker = pick a color
-title.blankNodes = blank nodes
-title.lodCloud = data from the linked data cloud
-title.inverse = inverse relations
-title.lookingAt = now looking at
-title.directRelations = direct relations
-title.pickExample = pick an example
-
-error.linkedResourceUnavailable = unable to retrieve data
-error.noContentNegotiation = sorry but content negotiation is not supported by the IRI
-error.unacceptable = you requested an unacceptable content
-error.somethingWrong = Oops! something went wrong
-
-message.loadingConnected = loading connected resource titles
-message.loadingInverses = loading inverse relations
-message.grabData = retrieving data from the LOD cloud ({0} of {1})
-message.grabDataTotal = Resource connected {0}
-message.grabDataTotalLoaded = Resource loaded {0}
-message.grabDataTotalErrors = Resource not online {0}
-message.noImage = image not available, broken URL?
-
-footer.noSparql = data from: dereferenceable IRI
-footer.yesSparql = data from:
-footer.viewLodlive = view on LodLive
-footer.viewAs = view as:
-footer.download = download lodview to publish your data
-
diff --git a/src/main/resources/messages_fr.properties b/src/main/resources/messages_fr.properties
deleted file mode 100644
index 6b65057..0000000
--- a/src/main/resources/messages_fr.properties
+++ /dev/null
@@ -1,50 +0,0 @@
-label.resource = ressource
-label.resources = ressources
-label.connectedResource = ressource connectée
-label.connectedResources = ressources connectées
-
-label.toTop = en haut
-label.go = go
-
-label.inverseProperty = is {0} of
-label.moreExample = voir plus d'exemples
-
-title.colorPicker = choisir une couleur
-title.blankNodes = nœuds anonymes
-title.lodCloud = donnée du "linked Data Cloud"
-title.inverse = relations inverses
-
-title.lookingAt = maintenant on observe
-title.directRelations = relations directes
-title.pickExample = choisir un exemple
-
-error.linkedResourceUnavailable = impossible de retrouver les données
-error.noContentNegotiation = désolé, la négociation de contenu n'est pas supportée par cette IRI
-error.unacceptable = vous avez demandé un contenu inacceptable
-error.somethingWrong = Oops! y'a un truc qui va pas.
-
-message.loadingConnected = chargement des titres de la ressource connectée
-message.loadingInverses = chargemement des relations inverses
-message.grabData = chargement des données depuis le cloud LOD({0} sur {1})
-message.grabDataTotal = Ressources connectées {0}
-message.grabDataTotalLoaded = Ressources chargées {0}
-message.grabDataTotalErrors = Ressources hors ligne {0}
-message.noImage = image non disponible. (lien cassé ?)
-
-footer.noSparql = donnée venant de : IRI déréférençable
-footer.yesSparql = donnée venant de:
-footer.viewLodlive = visualiser sur LodLive
-footer.viewAs = visualiser comme:
-footer.download = télécharger Lodview pour publier vos données
-
-home.iriInput = IRI (OBLIGATOIRE)
-home.sparqlInput = SPARQL ENDPOINT (OPTIONNEL)
-home.prefixInput = PREFIX (OPTIONNEL)
-
-home.iriInfo = mettre une IRI déréférençable ou une ressource publiée sur un point d'accès SPARQL
-home.sparqlInfo = URL du point d'accès SPARQL - ex http://dbpedia.org/sparql
-home.prefixInfo = Préfixe de la ressource, utile pour améliorer le rendu dans le navigateur - ex http://dbpedia.org/resource
-
-home.share = PARTAGER
-home.download = TELECHARGER
-home.examples = EXEMPLES
\ No newline at end of file
diff --git a/src/main/resources/messages_gl.properties b/src/main/resources/messages_gl.properties
deleted file mode 100644
index 8277d71..0000000
--- a/src/main/resources/messages_gl.properties
+++ /dev/null
@@ -1,49 +0,0 @@
-label.resource = recurso
-label.resources = recursos
-label.connectedResource = recurso conectado
-label.connectedResources = recursos conectados
-label.toTop = inicio da páxina
-label.inverseProperty = é {0} de
-label.go = vai
-label.moreExample = ver máis exemplos
-label.anEntityOfType = unha entidade de tipo
-
-title.colorPicker = seleccione unha cor
-title.blankNodes = nodos anónimos
-title.lodCloud = datos da Linked Data Cloud
-title.inverse = relacións inversas
-title.lookingAt = recurso actual
-title.directRelations = relacións directas
-title.pickExample = seleccione un exemplo
-
-error.linkedResourceUnavailable = non foi posíbel obter os datos
-error.noContentNegotiation = sentímolo, a IRI non permite a negociación de contidos
-error.unacceptable = solicitouse un contido inaceptábel
-error.somethingWrong = Oh! algo non funcionou
-
-message.loadingConnected = cargando os títulos dos recursos conectados
-message.loadingInverses = cargando as relacións inversas
-message.grabData = recuperando datos da LOD cloud ({0} de {1})
-message.grabDataTotal = recursos conectados {0}
-message.grabDataTotalLoaded = recursos cargados {0}
-message.grabDataTotalErrors = recursos que non están en liña {0}
-message.noImage = imaxe non dispoñíbel, erro na URL?
-
-footer.noSparql = datos de: IRI diferenciada
-footer.yesSparql = datos de:
-footer.viewLodlive = ver en LodLive
-footer.viewAs = ver como:
-footer.download = descargue lodview para publicar os seus datos
-
-
-home.iriInput = IRI (OBRIGATORIO)
-home.sparqlInput = PUNTO DE ACCESO SPARQL (OPCIONAL)
-home.prefixInput = PREFIXO (OPCIONAL)
-
-home.iriInfo = indique unha IRI diferenciábel ou un recurso publicado nun punto de acceso SPARQL
-home.sparqlInfo = enderezo URL do punto de acceso SPARQL; ex. http://dbpedia.org/sparql
-home.prefixInfo = prefixo do recurso, útil para mellorar a navegación; ex. http://dbpedia.org/resource
-
-home.share = COMPARTIR
-home.download = DESCARGAR
-home.examples = EXEMPLOS
diff --git a/src/main/resources/messages_it.properties b/src/main/resources/messages_it.properties
deleted file mode 100644
index f525a93..0000000
--- a/src/main/resources/messages_it.properties
+++ /dev/null
@@ -1,49 +0,0 @@
-label.resource = risorsa
-label.resources = risorse
-label.connectedResource = risorsa connessa
-label.connectedResources = risorse connesse
-label.toTop = inizio pagina
-label.inverseProperty = è {0} di
-label.go = vai
-label.moreExample = altri esempi di risorse
-label.anEntityOfType = entità di tipo
-
-title.colorPicker = scegli un colore
-title.blankNodes = blank nodes
-title.lodCloud = risorse dalla linked data cloud
-title.inverse = relazioni inverse
-title.lookingAt = risorsa corrente
-title.directRelations = relazioni dirette
-title.pickExample = scegli un esempio
-
-error.linkedResourceUnavailable = risorsa non disponibile online
-error.noContentNegotiation = spiacenti ma la IRI non supporta il content negotiation
-error.unacceptable = il content richiesto non è accetabile
-error.somethingWrong = Oops! qualcosa non ha funzionato
-
-message.loadingConnected = carico i titoli delle risorse collegate
-message.loadingInverses = seguo le relazioni inverse
-message.grabData = recupero dati dalla LOD cloud ({0} of {1})
-message.grabDataTotal = risorse connesse {0}
-message.grabDataTotalLoaded = risorse caricate {0}
-message.grabDataTotalErrors = risorse non online {0}
-message.noImage = immagine non disponibile, URL errata?
-
-footer.noSparql = dati da: IRI dereferenziata
-footer.yesSparql = dati da:
-footer.viewLodlive = visualizza su LodLive
-footer.viewAs = visualizza come:
-footer.download = scarica lodview per pubblicare i tuoi dati
-
-
-home.iriInput = IRI (OBBLIGATORIO)
-home.sparqlInput = SPARQL ENDPOINT (OPZIONALE)
-home.prefixInput = PREFIX (OPZIONALE)
-
-home.iriInfo = IRI deferenziabile o una risorsa pubblicata in uno SPARQL endpoint
-home.sparqlInfo = indirizzo dello SPARQL endpoint - es. http://dbpedia.org/sparql
-home.prefixInfo = prefisso delle risorse, utile per migliorare la navigazione - es. http://dbpedia.org/resource
-
-home.share = CONDIVIDI
-home.download = DOWNLOAD
-home.examples = ESEMPI
diff --git a/src/main/resources/messages_nl.properties b/src/main/resources/messages_nl.properties
deleted file mode 100644
index 2491370..0000000
--- a/src/main/resources/messages_nl.properties
+++ /dev/null
@@ -1,36 +0,0 @@
-label.resource = resource
-label.resources = resources
-label.connectedResource = connected resource
-label.connectedResources = connected resources
-label.toTop = naar boven
-label.go = start
-label.inverseProperty = is {0} van
-label.moreExample = zie meer voorbeelden
-label.anEntityOfType = type entiteit
-
-title.colorPicker = kies een kleur
-title.blankNodes = blank nodes
-title.lodCloud = data uit de linked data cloud
-title.inverse = inverse relaties
-title.lookingAt = nu in beeld
-title.directRelations = directe relaties
-title.pickExample = kies een voorbeeld
-
-error.linkedResourceUnavailable = data kan niet opgehaald worden
-error.noContentNegotiation = sorry, content negotiation wordt niet ondersteund door deze IRI
-error.unacceptable = content is niet geaccepteerd
-error.somethingWrong = Oeps, iets ging er mis!
-
-message.loadingConnected = verbonden resources worden opgehaald
-message.loadingInverses = inverse relaties ophalen
-message.grabData = ontvangen van data uit de LOD cloud ({0} van {1})
-message.grabDataTotal = Resource verbonden` {0}
-message.grabDataTotalLoaded = Resource opgehaald {0}
-message.grabDataTotalErrors = Resource niet online {0}
-message.noImage = afbeelding niet beschikbaar, foute URL?
-
-footer.noSparql = data van: herleidbare IRI
-footer.yesSparql = data from:
-footer.viewLodlive = bekijk in LodLive
-footer.viewAs = bekijk als:
-footer.download = download lodview om je data te publiceren
\ No newline at end of file
diff --git a/src/main/resources/messages_sk.properties b/src/main/resources/messages_sk.properties
deleted file mode 100644
index ceca3f1..0000000
--- a/src/main/resources/messages_sk.properties
+++ /dev/null
@@ -1,49 +0,0 @@
-label.resource = zdroj
-label.resources = zdroje
-label.connectedResource = prepojený zdroj
-label.connectedResources = prepojené zdroje
-label.toTop = nahor
-label.inverseProperty = je {0} z
-label.go = potvrdiť
-label.moreExample = viď iné príklady
-label.anEntityOfType = typ entity
-
-title.colorPicker = vyber farbu
-title.blankNodes = prázdne uzly
-title.lodCloud = zdroje linked dáta cloud
-title.inverse = inverzná relácia
-title.lookingAt = aktuálny zdroj
-title.directRelations = priama relácia
-title.pickExample = vyber príklad
-
-error.linkedResourceUnavailable = nedostupný zdroj
-error.noContentNegotiation = ľutujeme, iri nepodporuje content negotiation
-error.unacceptable = neprijateľný content
-error.somethingWrong = Ups, niečo sa pokazilo!
-
-message.loadingConnected = sťahujem názvy prepojených zdrojov
-message.loadingInverses = sťahujem inverzné relácie
-message.grabData = vyberám dáta z LOD cloud ({0} z {1})
-message.grabDataTotal = pripojené zdroje {0}
-message.grabDataTotalLoaded = stiahnuté zdroje {0}
-message.grabDataTotalErrors = nedostupné zdroje {0}
-message.noImage = obrázok nedostupný, chyba v URL?
-
-footer.noSparql = dáta od: IRI s nepriamym odkazom
-footer.yesSparql = dáta od:
-footer.viewLodlive = zobraz na LodLive
-footer.viewAs = zobraz ako:
-footer.download = stiahni lodview pre publikáciu tvojich dát
-
-
-home.iriInput = IRI (POVINNÝ)
-home.sparqlInput = SPARQL ENDPOINT (VOLITEĽNÝ)
-home.prefixInput = PREFIX (VOLITEĽNÝ)
-
-home.iriInfo = s nepriamym odkazom alebo zdroj publikovaný v SPARQL endpoint
-home.sparqlInfo = adresa SPARQL endpoint – napr. http://dbpedia.org/sparql
-home.prefixInfo = predvoľba zdrojov, užitočné pre zlepšenie navigovania – napr. http://dbpedia.org/resource
-
-home.share = ZDIEĽAJ
-home.download = DOWNLOAD
-home.examples = PRÍKLADY
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/ontologies/dbpedia_2014.owl b/src/main/resources/ontologies/dbpedia_2014.owl
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/dbpedia_2014.owl
rename to src/main/resources/ontologies/dbpedia_2014.owl
diff --git a/src/main/webapp/WEB-INF/ontologies/dcelements.rdf b/src/main/resources/ontologies/dcelements.rdf
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/dcelements.rdf
rename to src/main/resources/ontologies/dcelements.rdf
diff --git a/src/main/webapp/WEB-INF/ontologies/dcterms.rdf b/src/main/resources/ontologies/dcterms.rdf
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/dcterms.rdf
rename to src/main/resources/ontologies/dcterms.rdf
diff --git a/src/main/webapp/WEB-INF/ontologies/dctype.rdf b/src/main/resources/ontologies/dctype.rdf
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/dctype.rdf
rename to src/main/resources/ontologies/dctype.rdf
diff --git a/src/main/webapp/WEB-INF/ontologies/foaf.rdf b/src/main/resources/ontologies/foaf.rdf
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/foaf.rdf
rename to src/main/resources/ontologies/foaf.rdf
diff --git a/src/main/webapp/WEB-INF/ontologies/owl.ttl b/src/main/resources/ontologies/owl.ttl
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/owl.ttl
rename to src/main/resources/ontologies/owl.ttl
diff --git a/src/main/webapp/WEB-INF/ontologies/rdf.ttl b/src/main/resources/ontologies/rdf.ttl
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/rdf.ttl
rename to src/main/resources/ontologies/rdf.ttl
diff --git a/src/main/webapp/WEB-INF/ontologies/rdfs.ttl b/src/main/resources/ontologies/rdfs.ttl
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/rdfs.ttl
rename to src/main/resources/ontologies/rdfs.ttl
diff --git a/src/main/webapp/WEB-INF/ontologies/rel.rdf b/src/main/resources/ontologies/rel.rdf
similarity index 100%
rename from src/main/webapp/WEB-INF/ontologies/rel.rdf
rename to src/main/resources/ontologies/rel.rdf
diff --git a/src/main/resources/spring/application-config.xml b/src/main/resources/spring/application-config.xml
deleted file mode 100644
index 94f5c72..0000000
--- a/src/main/resources/spring/application-config.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/main/resources/static/staticResources/css/commons.css b/src/main/resources/static/staticResources/css/commons.css
new file mode 100644
index 0000000..657c65e
--- /dev/null
+++ b/src/main/resources/static/staticResources/css/commons.css
@@ -0,0 +1,1031 @@
+/* ********************************************** */
+/* DO NOT CHANGE THIS FILE USE custom.css INSTEAD */
+/* ********************************************** */
+.sp {
+ background-image: url(../img/lodview-sprite.png);
+ background-size: 1000px 600px;
+}
+
+div#logoBanner div#logo {
+ background-size: 134px 40px;
+ background-image: url(../img/logo-header-lodview.png);
+ height: 80px;
+ background-position: left center;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ width: 150px;
+}
+
+a {
+ text-decoration: none;
+}
+
+body {
+ font-family: 'Roboto', sans-serif;
+ font-weight: 300;
+ line-height: 20px;
+ font-size: 14px;
+ background-color: #212121;
+}
+
+strong {
+ font-weight: 500;
+}
+
+.value div.fixed, .valuecnt div.fixed, #abstract .c2 {
+ max-width: 760px;
+ overflow-x: hidden;
+}
+
+label {
+ display: inline-block;
+}
+
+label a {
+ font-weight: 300;
+ font-size: 14px;
+}
+
+label a span {
+ font-weight: 500;
+}
+
+div#logoBanner {
+ height: 80px;
+ background-color: #fff;
+ padding: 0 24px;
+}
+
+hgroup {
+ display: block;
+ min-height: 210px;
+ color: #fff;
+ padding: 0 24px;
+}
+
+hgroup h1 {
+ font-size: 32px;
+ padding-top: 120px;
+ line-height: 32px;
+ font-weight: 300;
+ margin-right: 100px;
+}
+
+hgroup h1 span {
+ display: inline-block;
+ padding-right: 250px;
+}
+
+#seeOnLodlive a {
+ display: inline-block;
+ width: 19px;
+ height: 27px;
+}
+
+#seeOnLodlive {
+ background-position: -130px 0;
+ width: 19px;
+ height: 27px;
+ position: absolute;
+ top: 116px;
+ right: 24px;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
+ filter: alpha(opacity=30);
+ opacity: 0.3;
+}
+
+#seeOnLodlive:hover {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ filter: alpha(opacity=100);
+ opacity: 1;
+}
+
+hgroup h2 > a.iri {
+ display: inline-block;
+ margin-bottom: 8px;
+ color: #fff;
+ margin-right: 8px;
+}
+
+hgroup h2 > a.iri:hover {
+ text-decoration: underline;
+}
+
+hgroup h2 > span.istance {
+ float: none;
+ display: inline-block;
+ margin-left: -8px;
+}
+
+
+hgroup h2 {
+ font-size: 16px;
+ padding: 8px 0 24px 0;
+ font-weight: 300;
+}
+
+hgroup h2 > span a {
+ color: #fff;
+ font-weight: 300;
+ display: inline-block;
+ margin-left: 8px;
+ margin-top: 2px;
+ /*text-transform: uppercase;*/
+ letter-spacing: .7;
+ font-size: 13px;
+}
+
+hgroup h2 > span a span {
+ color: #fff;
+ font-weight: 500;
+}
+
+hgroup h2 > span.istance a span.istanceOf {
+ font-size: 11px;
+ text-transform: uppercase;
+ font-weight: 300;
+}
+
+header div#abstract {
+ padding: 24px;
+ color: #fff;
+}
+
+header div#abstract .value a {
+ text-decoration: underline;
+ color: #fff;
+}
+
+header div#abstract .value a:hover {
+ text-decoration: none
+}
+
+header div#abstract label {
+ padding: 0 24px 0 0;
+}
+
+header div#abstract label a {
+ color: #fff;
+}
+
+header div#abstract label a span {
+ color: #fff;
+}
+
+aside {
+ display: block;
+ background-color: #eee;
+ color: #fff;
+ padding: 24px 24px 16px 24px;
+}
+
+#widgets > div#images > a:hover, #widgets > div#linking > a:hover {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
+ filter: alpha(opacity=90);
+ opacity: 0.9;
+}
+
+#widgets > div#images > a {
+ min-width: 136px;
+ height: 136px;
+ text-align: left;
+ display: inline-block;
+ background-image: url(../img/segnaposto-immagine.png);
+ background-size: 48px 48px;
+ background-position: center center;
+ background-repeat: no-repeat;
+ margin-right: 8px;
+ margin-bottom: 8px;
+}
+
+aside {
+ font-size: 0px
+}
+
+aside div.noImg {
+ width: 125px;
+ height: 125px;
+ display: inline-block;
+ background-position: 0 -105px;
+ background-size: 300px 250px;
+}
+
+aside div#linking, aside div#images, aside div#audio, aside div#video {
+ display: inline-block;
+}
+
+aside div#resourceMapCnt {
+ display: inline-block;
+ margin-right: 8px;
+}
+
+aside div#images a img, aside div#linking a span, aside div#resourceMapCnt map, aside div#audio .audio {
+ height: 136px;
+ display: inline-block;
+ width: auto;
+}
+
+aside div#video {
+ height: 144px;
+}
+
+aside div#video * {
+ height: 136px;
+ display: inline-block;
+ margin-right: 8px;
+}
+
+aside div#audio .audio {
+ height: 136px;
+ display: inline-block;
+ width: 136px;
+ margin-right: 8px;
+ margin-bottom: 8px;
+ background-position: -520px -65px;
+}
+
+aside div#linking {
+ margin-bottom: 8px;
+}
+
+aside div#linking a span {
+ width: 136px;
+ background-position: -280px -65px;
+}
+
+aside div#resourceMapCnt map {
+ width: 272px;
+ background-position: 0 -65px;
+}
+
+.leaflet-popup-content {
+ color: #000
+}
+
+.c1, .c3 {
+ position: absolute
+}
+
+h3 {
+ text-transform: uppercase;
+ letter-spacing: .7;
+ font-weight: 300;
+ color: #212121;
+ font-size: 11px;
+}
+
+div#directs {
+ padding: 24px;
+ background: #fff;
+ color: #212121;
+ line-height: 20px;
+ font-size: 14px;
+ overflow-x: hidden;
+}
+
+div#bnodes {
+ padding: 24px;
+ background: #eee;
+ color: #212121;
+ line-height: 20px;
+ font-size: 14px;
+}
+
+div#inverses {
+ padding: 24px;
+ background: #d4d4d4;
+ color: #212121;
+ line-height: 20px;
+ font-size: 14px;
+}
+
+.lloading {
+ background-image: url(../img/loading-new@2x.gif);
+ background-size: 22px 7px;
+ width: 22px;
+ height: 7px;
+ display: inline-block;
+ margin-right: 8px;
+}
+
+.lloadingb {
+ background-image: url(../img/loading-new-nero@2x.gif);
+ background-size: 22px 7px;
+ width: 22px;
+ height: 7px;
+ display: inline-block;
+ margin-left: 16px;
+}
+
+div#inverses .nextArrow {
+ display: inline-block;
+ width: 12px;
+ height: 14px;
+ margin-left: 8px;
+ background-position: -60px 3px;
+}
+
+div#inverses .prevArrow {
+ display: inline-block;
+ width: 12px;
+ height: 14px;
+ margin-left: 16px;
+ background-position: -45px 3px;
+}
+
+div#lodCloud {
+ padding: 24px 24px 16px 24px;
+ background: #fafafa;
+ color: #212121;
+ line-height: 16px;
+ font-size: 12px;
+ min-height: 64px;
+}
+
+div#lodCloud map {
+ background-position: -260px -210px;
+ display: inline-block;
+ width: 250px;
+ height: 250px;
+}
+
+div#lodCloud .connected div#counterBlock.content {
+ color: #fff;
+}
+
+div.toOneLine {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.value div, .valuecnt div {
+ min-height: 20px
+}
+
+.value div span.derivedTitle, .valuecnt div span.derivedTitle {
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ background-repeat: no-repeat;
+}
+
+.value div span.derivedTitle tt, .valuecnt div span.derivedTitle tt {
+ margin: 5px 0 0 2px;
+ background-position: -45px -20px;
+ width: 11px;
+ display: inline-block;
+ height: 10px;
+}
+
+div#directs .value a span.derivedTitle, div#bnodes .value a span.derivedTitle, div#inverses .value a span.derivedTitle {
+ font-weight: 300;
+}
+
+.value div a:hover span.derivedTitle {
+ text-decoration: none;
+}
+
+div#directs .value > div:not(.value), div#bnodes .valuecnt > div:not(.value), div#inverses .value > div:not(.value) {
+ padding-bottom: 12px;
+ margin-top: 12px;
+ background-image: url(../img/separatoreCorto.png);
+ background-repeat: no-repeat;
+ background-size: 16px 1px;
+ background-position: bottom left;
+}
+
+div#directs .c2.multiInLineBlock, div#directs .c4.multiInLineBlock {
+ padding-bottom: 8.5px;
+ padding-top: 8.5px;
+}
+
+.multiInLine {
+ display: inline-block;
+ margin-right: 20px;
+ line-height: 27px;
+}
+
+div#directs .value > div:not(.value):first-child, div#bnodes .valuecnt > div:not(.value):first-child, div#inverses .value > div:not(.value):first-child, div#inverses .value > div:not(.value):nth-of-type(n+2):not(.toOneLine):not(.toMultiLine), div#bnodes .valuecnt > div:not(.value):nth-of-type(n+2):not(.toOneLine):not(.toMultiLine) {
+ margin-top: 0;
+}
+
+div#directs .value > div:not(.value):last-child, div#bnodes .valuecnt > div:not(.value):last-child, div#inverses .value > div:not(.value):last-child {
+ padding: 0;
+ background: none;
+}
+
+div#directs label, div#bnodes label, div#inverses label {
+ padding: 0 24px 0 0;
+}
+
+div#directs label a, div#bnodes label a, div#inverses label a {
+ color: #212121;
+}
+
+div#directs label a span, div#bnodes label a span, div#inverses label a span {
+ color: #212121;
+}
+
+div#directs .dType, div#bnodes .dType {
+ font-size: 14px;
+ font-weight: 300;
+ color: #9e9e9e;
+ position: absolute;
+ right: 24px;
+ text-align: right;
+ padding-left: 16px;
+ background-color: #fff;
+}
+
+div#bnodes .dType {
+ background-color: #eee;
+}
+
+div#directs span.clang, div#abstract span.clang, div#bnodes span.clang, div#bnodes span.clang {
+ display: inline-block;
+ text-transform: uppercase;
+ letter-spacing: .7;
+ margin-right: 5px;
+ cursor: pointer;
+ margin-bottom: 12px;
+}
+
+div#directs span.clang.sel, div#abstract span.clang.sel, div#bnodes span.clang.sel {
+ text-decoration: underline;
+}
+
+div#directs .value a, div#directs .valuecnt a, div#bnodes .value a, div#bnodes .valuecnt a, div#inverses .value a, div#inverses .valuecnt a {
+ font-weight: 300;
+ font-size: 14px;
+ color: #212121;
+}
+
+div#directs .value a span, div#bnodes .value a span, div#inverses .value a span {
+ font-weight: 500;
+ color: #212121;
+}
+
+div#directs .value a:hover, div#bnodes .value a:hover, div#inverses .value a:hover, div#directs .valuecnt a:hover, div#bnodes .valuecnt a:hover, div#inverses .valuecnt a:hover {
+ text-decoration: underline;
+}
+
+div#directs .c2, div#directs .c4 {
+ border-bottom: 1px solid #dbdbdb;
+ padding-bottom: 12px;
+ padding-top: 12px;
+}
+
+div#bnodes .c2, div#bnodes .c4 {
+ border-bottom: 1px solid #d2d2d2;
+ padding-bottom: 12px;
+ padding-top: 12px;
+}
+
+div#inverses .c2, div#inverses .c4 {
+ padding-bottom: 12px;
+ padding-top: 12px;
+ border-bottom: 1px solid #b6b6b6;
+}
+
+div#inverses .c2 .toOneLine {
+ min-height: 40px;
+}
+
+div#inverses .c2.opened {
+ min-height: 648px;
+}
+
+div#bnodes .c2:last-child, div#directs .c2:last-child, div#inverses .c2:last-child, div#bnodes .c4:last-child, div#directs .c4:last-child, div#inverses .c4:last-child {
+ border-bottom: 0;
+ padding-bottom: 0;
+ padding-top: 12px;
+}
+
+div#directs label:nth-child(1), div#bnodes label:nth-child(1), div#inverses label:nth-child(1) {
+ padding-top: 0;
+}
+
+div#directs label, div#bnodes label, div#inverses label {
+ padding-top: 12px;
+}
+
+div#directs .c2:nth-child(2), div#bnodes .c2:nth-child(2), div#inverses .c2:nth-child(2), div#directs .c4:nth-child(2), div#bnodes .c4:nth-child(2), div#inverses .c4:nth-child(2) {
+ padding-top: 0;
+}
+
+div#lodCloud h3 {
+ margin-bottom: 24px;
+}
+
+div#lodCloud .lloading {
+ position: absolute;
+ right: 22px;
+ top: 28px;
+}
+
+div#lodCloud .connected {
+ width: 250px;
+ display: inline-block;
+ margin-right: 16px;
+ vertical-align: top;
+ margin-bottom: 16px;
+}
+
+div#lodCloud .connected .content {
+ padding: 24px;
+ background: #e9e9e9;
+}
+
+div#lodCloud .connected .content :last-child {
+ margin-bottom: 0;
+}
+
+div#lodCloud .connected h5 {
+ font-weight: 500;
+}
+
+div#lodCloud .connected .more {
+ margin-top: 1px;
+ font-weight: 300;
+ letter-spacing: .7;
+ font-size: 11px;
+ text-transform: uppercase;
+ padding: 24px;
+ background: #e9e9e9;
+}
+
+div#lodCloud .connected a.link {
+ color: #212121;
+ display: block;
+ margin-top: 8px;
+ margin-bottom: 24px;
+}
+
+div#lodCloud .connected a:hover {
+ text-decoration: underline;
+}
+
+div#lodCloud .connected span.imgCnt {
+ background-position: 0 -210px;
+ width: 250px;
+ display: block;
+}
+
+div#lodCloud .connected img.main {
+ width: 250px;
+ height: auto;
+ background: #ffffff;
+
+}
+
+.px1 {
+ width: 1px;
+ font-size: 1px;
+ line-height: 1px;
+}
+
+aside.empty, #bnodes.empty, #directs.empty, #inverses.empty, #abstract.empty {
+ padding: 0;
+ min-height: 10px;
+}
+
+#lodCloud.empty {
+ padding: 0;
+ min-height: 5px;
+}
+
+#inverses.empty {
+ padding: 0;
+ min-height: 20px;
+}
+
+footer {
+ min-height: 176px;
+ color: #fff;
+ padding: 24px;
+}
+
+#download {
+ float: left;
+ margin-bottom: 30px;
+}
+
+#download a#linkGit {
+ margin-top: 160px;
+ display: block;
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: .7;
+ color: #b4b4b4;
+ text-decoration: none;
+}
+
+#download a:hover {
+ text-decoration: underline
+}
+
+#endpoint {
+ position: relative;
+ top: -7px;
+ font-size: 12px;
+ line-height: 24px;
+}
+
+#endpoint {
+ float: right;
+ color: #fff;
+}
+
+#endpoint ul li {
+ min-height: 24px;
+}
+
+#endpoint ul {
+ list-style: none;
+}
+
+#endpoint a {
+ color: #fff;
+ cursor: pointer;
+}
+
+#endpoint a:hover {
+ text-decoration: underline
+}
+
+div#directs .value > div.lang, div#bnodes .value > div.lang, div#inverses .value > div.lang {
+ background: none;
+ padding-bottom: 0;
+ margin-top: 0
+}
+
+div#loadPanel {
+ position: fixed;
+ width: 100%;
+ bottom: 0;
+ left: 0;
+ line-height: 30px;
+ height: 30px;
+ padding-left: 24px;
+ overflow: hidden;
+ z-index: 1004;
+}
+
+div#loadPanel.cfix {
+ padding-left: 100%;
+ margin-left: -300px
+}
+
+div#loadPanel span.ok {
+ width: 17px;
+ height: 14px;
+ display: inline-block;
+ margin-left: 6px;
+}
+
+div#loadPanel span.ok img {
+ display: none
+}
+
+div#loadPanel > p {
+ font-family: 'Roboto', sans-serif;
+ font-weight: 300;
+ line-height: 30px;
+ font-size: 12px;
+ color: #fff;
+}
+
+#images .errorImg {
+ width: 136px;
+ height: 136px;
+ margin-right: 8px;
+}
+
+.connected .errorImg {
+ width: 250px;
+ height: 250px;
+}
+
+#errorPage hgroup h1 {
+ font-size: 150px;
+ font-weight: 100;
+ padding-left: 66px;
+ padding-top: 80px;
+}
+
+#errorPage.error404 div#owl {
+ background-image: url(../img/owl404.png);
+ background-size: 224px 283px;
+ width: 224px;
+ height: 283px;
+ position: absolute;
+ left: 660px;
+ top: 105px
+}
+
+#errorPage.error500 div#owl {
+ background-image: url(../img/owl500.png);
+ background-size: 224px 283px;
+ position: absolute;
+ width: 224px;
+ height: 283px;
+ left: 660px;
+ top: 105px
+}
+
+#errorPage div#abstract {
+ height: 65px;
+ padding: 0;
+}
+
+#errorPage div#bnodes {
+ font-size: 20px;
+ min-height: 186px;
+ padding: 0 24px 24px 90px;
+}
+
+#errorPage div#bnodes p {
+ font-size: 30px;
+ line-height: 40px;
+ padding-top: 60px;
+}
+
+footer {
+
+}
+
+footer #linkBack {
+ display: block;
+ background-size: 134px 25px;
+ background-image: url(../img/logo-footer-lodview.png);
+ background-position: 0 0;
+ height: 25px;
+ width: 134px;
+ background-repeat: no-repeat;
+}
+
+footer #linkBack:hover {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: alpha(opacity=6);
+ opacity: 0.6;
+}
+
+#navigator {
+ position: fixed;
+ right: 0;
+ top: 50%;
+ margin-top: -32px;
+ z-index: 5;
+ width: 40px;
+ height: 78px;
+}
+
+#navigator div {
+ width: 40px;
+ height: 20px;
+ cursor: pointer;
+ margin-bottom: 1px;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ filter: alpha(opacity=10);
+ opacity: 0.1;
+}
+
+#navigator div span {
+ display: none;
+}
+
+#navigator div.hover:hover {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ filter: alpha(opacity=10);
+ opacity: 1;
+ position: static;
+}
+
+#navigator div.hover:hover span {
+ display: inline-block;
+ position: fixed;
+ right: 41px;
+ background-color: #222;
+ padding: 0 8px;
+ height: 20px;
+ color: #fff;
+ line-height: 20px;
+ font-size: 12px;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ filter: alpha(opacity=10);
+ opacity: 1;
+}
+
+#navigator div a {
+ display: block;
+ width: 40px;
+ height: 20px;
+}
+
+#navigator div.down {
+ background-position: 0 -40px;
+}
+
+#navigator div.up {
+ background-position: 0 0;
+}
+
+#navigator div.top {
+ background-position: 0 -20px;
+}
+
+@media screen and (max-width: 768px) {
+ hgroup h1 span {
+ padding-right: 150px;
+ }
+}
+
+.iph {
+ width: 22px;
+ height: 20px;
+ position: absolute;
+ left: -20px;
+}
+
+.i {
+ background-position: -105px -35px;
+ width: 22px;
+ height: 20px;
+ position: absolute;
+ left: -20px;
+ z-index: 9;
+ display: none;
+ cursor: help;
+}
+
+.i span {
+ display: inline-block;
+ background-position: -105px -35px;
+ width: 11px;
+ height: 11px;
+ position: relative;
+ left: 4px;
+ top: 5px;
+ z-index: 9;
+}
+
+.tooltip {
+ display: none;
+ background-color: #212121;
+ font-family: 'Roboto', sans-serif;
+ font-weight: 300;
+ line-height: 15px;
+ font-size: 12px;
+ color: #fff;
+ padding: 10px;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ position: absolute;
+ left: 8px;
+ margin-top: 22px;
+ width: 250px;
+ z-index: 9;
+}
+
+#license {
+ padding: 12px 0;
+ line-height: 20px;
+ font-family: 'Roboto', sans-serif;
+ font-weight: 300;
+ font-size: 12px;
+ float: left;
+ width: 100%;
+ background: #fff;
+}
+
+#license div {
+ padding: 0 24px;
+}
+
+#license div a {
+ font-weight: 500;
+ color: #222222
+}
+
+#license div a:hover {
+ text-decoration: underline;
+}
+
+/* ********************************** */
+/* CUSTOM FOOTER, HIDDEN BY DEFAULT */
+/* ********************************** */
+#customFooter {
+ display: none;
+}
+
+/* useful to add information about the project partners (logo) */
+#customFooter #credits {
+ height: 86px;
+ background: #e9e9e9;
+}
+
+#customFooter #credits div {
+ padding: 24px 0 0 24px;
+}
+
+/* useful to add a custom navigation menu */
+#customFooter menu {
+ height: 43px;
+ background: #d4d4d4;
+}
+
+#customFooter menu li {
+ margin: 0 -8px 0 0;
+ padding: 0 0 0 24px;
+ font-family: 'Roboto', sans-serif;
+ font-weight: 300;
+ font-size: 12px;
+ display: inline-block;
+ line-height: 43px;
+}
+
+#customFooter menu li a {
+ color: #000;
+}
+
+#customFooter menu li a:hover {
+ text-decoration: underline;
+}
+
+/** image zoomer **/
+#hover {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ background: #fff;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
+ filter: alpha(opacity=90);
+ display: none;
+ z-index: 1006;
+}
+
+div.hover {
+ position: fixed;
+ z-index: 1007;
+}
+
+div.closemapzoom {
+ width: 14px;
+ height: 14px;
+ display: inline-block;
+ background-position: -120px -35px;
+ position: fixed;
+ right: 19px;
+ top: 19px;
+ cursor: pointer;
+
+}
+
+img.hover {
+ position: fixed;
+ z-index: 1007;
+ top: 100%;
+ left: 100%;
+ display: none;
+}
+
+.imgTools {
+ position: absolute;
+ overflow: hidden;
+ z-index: 999;
+ display: none;
+}
+
+.imgTools .zoom {
+ width: 29px;
+ height: 29px;
+ background-position: -430px -65px;
+ display: block;
+ cursor: pointer;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: alpha(opacity=60);
+ opacity: 0.6;
+}
+
+.imgTools .open:hover, .imgTools .zoom:hover {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ filter: alpha(opacity=100);
+ opacity: 1;
+}
+
+.imgTools .open {
+ margin-bottom: 5px;
+ cursor: pointer;
+ width: 14px;
+ height: 14px;
+ background-position: -430px -94px;
+ display: block;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: alpha(opacity=60);
+ opacity: 0.6;
+}
diff --git a/src/main/resources/static/staticResources/css/commons_2x.css b/src/main/resources/static/staticResources/css/commons_2x.css
new file mode 100644
index 0000000..7b640f5
--- /dev/null
+++ b/src/main/resources/static/staticResources/css/commons_2x.css
@@ -0,0 +1,36 @@
+/* **************************************** */
+/* SPECIAL DIRECTIVES FOR PIXEL RATIO > 1 */
+/* **************************************** */
+@media ( -webkit-min-device-pixel-ratio: 2) , ( min-resolution: 192dpi) {
+ .sp {
+ background-image: url(../img/lodview-sprite@2x.png);
+ }
+
+ div#logoBanner div#logo {
+ background-image: url(../img/logo-header-lodview@2x.png);
+ }
+
+ footer #linkBack {
+ background-image: url(../img/logo-footer-lodview@2x.png);
+ }
+
+ div#directs .value > div:not (.value ), div#bnodes .valuecnt > div:not (.value ), div#inverses .value > div:not (.value ) {
+ background-image: url("img/separatoreCorto@2x.png");
+ }
+
+ div#directs .value > div.lang, div#bnodes .value > div.lang, div#inverses .value > div.lang {
+ background: none
+ }
+
+ #errorPage.error404 div#owl {
+ background-image: url(../img/owl404@2x.png);
+ }
+
+ #errorPage.error500 div#owl {
+ background-image: url(../img/owl500@2x.png);
+ }
+
+ #widgets > div#images > a {
+ background-image: url(../img/segnaposto-immagine@2x.png);
+ }
+}
diff --git a/src/main/resources/static/staticResources/css/custom.css b/src/main/resources/static/staticResources/css/custom.css
new file mode 100644
index 0000000..1b7bede
--- /dev/null
+++ b/src/main/resources/static/staticResources/css/custom.css
@@ -0,0 +1,34 @@
+/* ***************** */
+/* CUSTOM CSS HERE */
+/* ***************** */
+div#logoBanner div#logo {
+ background-size: 134px 40px;
+ background-image: url(../img/logo-header-lodview.png) !important;
+ height: 80px;
+ background-position: left center;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ width: 150px;
+}
+
+@media ( -webkit-min-device-pixel-ratio: 2) , ( min-resolution: 192dpi) {
+ div#logoBanner div#logo {
+ background-image: url(../img/logo-header-lodview@2x.png) !important;
+ }
+}
+
+body {
+ background-color: #00264d !important;
+}
+
+div#inverses {
+ background: #cce6ff !important;
+}
+
+
+/* ********************************** */
+/* CUSTOM FOOTER, HIDDEN BY DEFAULT */
+/* ********************************** */
+#customFooter {
+ display: none;
+}
diff --git a/src/main/resources/static/staticResources/css/reset.css b/src/main/resources/static/staticResources/css/reset.css
new file mode 100644
index 0000000..21813d0
--- /dev/null
+++ b/src/main/resources/static/staticResources/css/reset.css
@@ -0,0 +1,78 @@
+/* html5doctor.com Reset v1.6.1 (http://html5doctor.com/html-5-reset-stylesheet/) - http://cssreset.com */
+html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ font-size: 100%;
+ vertical-align: baseline;
+ background: transparent
+}
+
+body {
+ line-height: 1
+}
+
+article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
+ display: block
+}
+
+nav ul {
+ list-style: none
+}
+
+blockquote, q {
+ quotes: none
+}
+
+blockquote:before, blockquote:after, q:before, q:after {
+ content: none
+}
+
+a {
+ margin: 0;
+ padding: 0;
+ font-size: 100%;
+ vertical-align: baseline;
+ background: transparent
+}
+
+ins {
+ background-color: #ff9;
+ color: #000;
+ text-decoration: none
+}
+
+mark {
+ background-color: #ff9;
+ color: #000;
+ font-style: italic;
+ font-weight: bold
+}
+
+del {
+ text-decoration: line-through
+}
+
+abbr[title], dfn[title] {
+ border-bottom: 1px dotted;
+ cursor: help
+}
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0
+}
+
+hr {
+ display: block;
+ height: 1px;
+ border: 0;
+ border-top: 1px solid #ccc;
+ margin: 1em 0;
+ padding: 0
+}
+
+input, select {
+ vertical-align: middle
+}
diff --git a/src/main/webapp/resources/img/favicon.png b/src/main/resources/static/staticResources/img/favicon.png
similarity index 100%
rename from src/main/webapp/resources/img/favicon.png
rename to src/main/resources/static/staticResources/img/favicon.png
diff --git a/src/main/webapp/resources/img/loading-new-nero@2x.gif b/src/main/resources/static/staticResources/img/loading-new-nero@2x.gif
similarity index 100%
rename from src/main/webapp/resources/img/loading-new-nero@2x.gif
rename to src/main/resources/static/staticResources/img/loading-new-nero@2x.gif
diff --git a/src/main/webapp/resources/img/loading-new@2x.gif b/src/main/resources/static/staticResources/img/loading-new@2x.gif
similarity index 100%
rename from src/main/webapp/resources/img/loading-new@2x.gif
rename to src/main/resources/static/staticResources/img/loading-new@2x.gif
diff --git a/src/main/webapp/resources/img/loading-newB-nero@2x.gif b/src/main/resources/static/staticResources/img/loading-newB-nero@2x.gif
similarity index 100%
rename from src/main/webapp/resources/img/loading-newB-nero@2x.gif
rename to src/main/resources/static/staticResources/img/loading-newB-nero@2x.gif
diff --git a/src/main/webapp/resources/img/lodview-sprite.png b/src/main/resources/static/staticResources/img/lodview-sprite.png
similarity index 100%
rename from src/main/webapp/resources/img/lodview-sprite.png
rename to src/main/resources/static/staticResources/img/lodview-sprite.png
diff --git a/src/main/webapp/resources/img/lodview-sprite@2x.png b/src/main/resources/static/staticResources/img/lodview-sprite@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/lodview-sprite@2x.png
rename to src/main/resources/static/staticResources/img/lodview-sprite@2x.png
diff --git a/src/main/webapp/resources/img/lodview_sharer.png b/src/main/resources/static/staticResources/img/lodview_sharer.png
similarity index 100%
rename from src/main/webapp/resources/img/lodview_sharer.png
rename to src/main/resources/static/staticResources/img/lodview_sharer.png
diff --git a/src/main/webapp/resources/img/logo-footer-lodview.png b/src/main/resources/static/staticResources/img/logo-footer-lodview.png
similarity index 100%
rename from src/main/webapp/resources/img/logo-footer-lodview.png
rename to src/main/resources/static/staticResources/img/logo-footer-lodview.png
diff --git a/src/main/webapp/resources/img/logo-footer-lodview@2x.png b/src/main/resources/static/staticResources/img/logo-footer-lodview@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/logo-footer-lodview@2x.png
rename to src/main/resources/static/staticResources/img/logo-footer-lodview@2x.png
diff --git a/src/main/webapp/resources/img/logo-header-lodview.png b/src/main/resources/static/staticResources/img/logo-header-lodview.png
similarity index 100%
rename from src/main/webapp/resources/img/logo-header-lodview.png
rename to src/main/resources/static/staticResources/img/logo-header-lodview.png
diff --git a/src/main/webapp/resources/img/logo-header-lodview@2x.png b/src/main/resources/static/staticResources/img/logo-header-lodview@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/logo-header-lodview@2x.png
rename to src/main/resources/static/staticResources/img/logo-header-lodview@2x.png
diff --git a/src/main/webapp/resources/img/no_image.png b/src/main/resources/static/staticResources/img/no_image.png
similarity index 100%
rename from src/main/webapp/resources/img/no_image.png
rename to src/main/resources/static/staticResources/img/no_image.png
diff --git a/src/main/webapp/resources/img/no_image@2x.png b/src/main/resources/static/staticResources/img/no_image@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/no_image@2x.png
rename to src/main/resources/static/staticResources/img/no_image@2x.png
diff --git a/src/main/webapp/resources/img/owl404.png b/src/main/resources/static/staticResources/img/owl404.png
similarity index 100%
rename from src/main/webapp/resources/img/owl404.png
rename to src/main/resources/static/staticResources/img/owl404.png
diff --git a/src/main/webapp/resources/img/owl404@2x.png b/src/main/resources/static/staticResources/img/owl404@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/owl404@2x.png
rename to src/main/resources/static/staticResources/img/owl404@2x.png
diff --git a/src/main/webapp/resources/img/owl500.png b/src/main/resources/static/staticResources/img/owl500.png
similarity index 100%
rename from src/main/webapp/resources/img/owl500.png
rename to src/main/resources/static/staticResources/img/owl500.png
diff --git a/src/main/webapp/resources/img/owl500@2x.png b/src/main/resources/static/staticResources/img/owl500@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/owl500@2x.png
rename to src/main/resources/static/staticResources/img/owl500@2x.png
diff --git a/src/main/webapp/resources/img/segnaposto-immagine.png b/src/main/resources/static/staticResources/img/segnaposto-immagine.png
similarity index 100%
rename from src/main/webapp/resources/img/segnaposto-immagine.png
rename to src/main/resources/static/staticResources/img/segnaposto-immagine.png
diff --git a/src/main/webapp/resources/img/segnaposto-immagine@2x.png b/src/main/resources/static/staticResources/img/segnaposto-immagine@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/segnaposto-immagine@2x.png
rename to src/main/resources/static/staticResources/img/segnaposto-immagine@2x.png
diff --git a/src/main/webapp/resources/img/separatoreCorto.png b/src/main/resources/static/staticResources/img/separatoreCorto.png
similarity index 100%
rename from src/main/webapp/resources/img/separatoreCorto.png
rename to src/main/resources/static/staticResources/img/separatoreCorto.png
diff --git a/src/main/webapp/resources/img/separatoreCorto@2x.png b/src/main/resources/static/staticResources/img/separatoreCorto@2x.png
similarity index 100%
rename from src/main/webapp/resources/img/separatoreCorto@2x.png
rename to src/main/resources/static/staticResources/img/separatoreCorto@2x.png
diff --git a/src/main/resources/static/staticResources/style.css b/src/main/resources/static/staticResources/style.css
new file mode 100644
index 0000000..6044476
--- /dev/null
+++ b/src/main/resources/static/staticResources/style.css
@@ -0,0 +1,7 @@
+@import url('css/reset.css');
+/* first of all, reset! */
+@import url('css/commons.css');
+/* do not touch this */
+@import url('css/commons_2x.css');
+/* pixel ratio > 1 */
+@import url('css/custom.css'); /* your style */
diff --git a/src/main/webapp/resources/vendor/jplayercircle/circle.skin/buffer.png b/src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/buffer.png
similarity index 100%
rename from src/main/webapp/resources/vendor/jplayercircle/circle.skin/buffer.png
rename to src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/buffer.png
diff --git a/src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/circle.player.css b/src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/circle.player.css
new file mode 100644
index 0000000..4437fb2
--- /dev/null
+++ b/src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/circle.player.css
@@ -0,0 +1,144 @@
+/*
+ * Project: CirclePlayer
+ * http://www.jplayer.org
+ *
+ * Copyright (c) 2011 Happyworm Ltd
+ *
+ * Author: Silvia Benvenuti
+ * Edited by: Mark J Panaghiston
+ * Date: 6th May 2011
+ * Artwork inspired by: http://forrst.com/posts/Untitled-CJz
+ */
+.cp-jplayer {
+ display: inline-block
+}
+
+.cp-container {
+ position: relative;
+ display: inline-block;
+ width: 70px; /* 200 - (2 * 48) */
+ height: 70px;
+ background-size: 70px 70px;
+ padding: 33px;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ margin-right: 8px;
+}
+
+.cp-container :focus {
+ border: none;
+ outline: 0;
+}
+
+.cp-buffer-1,
+.cp-buffer-2,
+.cp-progress-1,
+.cp-progress-2 {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 70px;
+ height: 70px;
+ clip: rect(0px, 35px, 70px, 0px);
+
+ -moz-border-radius: 35px;
+ -webkit-border-radius: 35px;
+ border-radius: 35px;
+}
+
+.cp-buffer-1,
+.cp-buffer-2 {
+ /*background: url("buffer.png") 0 0 no-repeat;
+ background-size:70px 70px;*/
+}
+
+
+/* FALLBACK for .progress
+ * (24 steps starting from 1hr filled progress, Decrease second value by 104px for next step)
+ * (It needs the container selector to work. Or use div)
+ */
+
+.cp-container .cp-fallback {
+ background: url("progress_sprite.png") no-repeat;
+ background-position: 0 70px;
+ background-size: 70px 1680px;
+}
+
+.cp-progress-1,
+.cp-progress-2 {
+ background: url("progress.png") 0 0 no-repeat;
+ background-size: 70px 70px;
+}
+
+.cp-buffer-holder,
+.cp-progress-holder,
+.cp-circle-control {
+ position: absolute;
+ width: 70px;
+ height: 70px;
+}
+
+.cp-circle-control {
+ cursor: pointer;
+}
+
+.cp-buffer-holder,
+.cp-progress-holder {
+ clip: rect(0px, 70px, 70px, 35px);
+ display: none;
+}
+
+
+/* This is needed when progress is greater than 50% or for fallback */
+
+.cp-buffer-holder.cp-gt50,
+.cp-progress-holder.cp-gt50,
+.cp-progress.cp-fallback {
+ clip: rect(auto, auto, auto, auto);
+}
+
+.cp-controls {
+ margin: 0;
+ padding: 15px;
+}
+
+.cp-controls li {
+ list-style-type: none;
+ display: block;
+
+ /*IE Fix*/
+ position: absolute;
+}
+
+.cp-controls li a {
+ position: relative;
+ display: block;
+ width: 40px;
+ height: 40px;
+ text-indent: -9999px;
+ z-index: 1;
+}
+
+.cp-controls .cp-play {
+ background: url("controls.png") 0 0 no-repeat;
+ background-size: 80px 80px;
+}
+
+.cp-controls .cp-play:hover {
+ background: url("controls.png") -40px 0 no-repeat;
+ background-size: 80px 80px;
+}
+
+.cp-controls .cp-pause {
+ background: url("controls.png") 0 -40px no-repeat;
+ background-size: 80px 80px;
+}
+
+.cp-controls .cp-pause:hover {
+ background: url("controls.png") -40px -40px no-repeat;
+ background-size: 80px 80px;
+}
+
+.cp-jplayer {
+ width: 0;
+ height: 0;
+}
diff --git a/src/main/webapp/resources/vendor/jplayercircle/circle.skin/controls.png b/src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/controls.png
similarity index 100%
rename from src/main/webapp/resources/vendor/jplayercircle/circle.skin/controls.png
rename to src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/controls.png
diff --git a/src/main/webapp/resources/vendor/jplayercircle/circle.skin/progress.png b/src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/progress.png
similarity index 100%
rename from src/main/webapp/resources/vendor/jplayercircle/circle.skin/progress.png
rename to src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/progress.png
diff --git a/src/main/webapp/resources/vendor/jplayercircle/circle.skin/progress_sprite.png b/src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/progress_sprite.png
similarity index 100%
rename from src/main/webapp/resources/vendor/jplayercircle/circle.skin/progress_sprite.png
rename to src/main/resources/static/staticResources/vendor/jplayercircle/circle.skin/progress_sprite.png
diff --git a/src/main/webapp/resources/vendor/jplayercircle/js/Jplayer.swf b/src/main/resources/static/staticResources/vendor/jplayercircle/js/Jplayer.swf
similarity index 100%
rename from src/main/webapp/resources/vendor/jplayercircle/js/Jplayer.swf
rename to src/main/resources/static/staticResources/vendor/jplayercircle/js/Jplayer.swf
diff --git a/src/main/resources/static/staticResources/vendor/jplayercircle/js/circle.player.js b/src/main/resources/static/staticResources/vendor/jplayercircle/js/circle.player.js
new file mode 100644
index 0000000..acd90b0
--- /dev/null
+++ b/src/main/resources/static/staticResources/vendor/jplayercircle/js/circle.player.js
@@ -0,0 +1,241 @@
+/*
+ * CirclePlayer for the jPlayer Plugin (jQuery)
+ * http://www.jplayer.org
+ *
+ * Copyright (c) 2009 - 2011 Happyworm Ltd
+ * Dual licensed under the MIT and GPL licenses.
+ * - http://www.opensource.org/licenses/mit-license.php
+ * - http://www.gnu.org/copyleft/gpl.html
+ *
+ * Version: 1.0.1 (jPlayer 2.0.9)
+ * Date: 30th May 2011
+ *
+ * Author: Mark J Panaghiston @thepag
+ *
+ * CirclePlayer prototype developed by:
+ * Mark Boas @maboa
+ * Silvia Benvenuti @aulentina
+ * Jussi Kalliokoski @quinirill
+ *
+ * Inspired by :
+ * Neway @imneway http://imneway.net/ http://forrst.com/posts/Untitled-CPt
+ * and
+ * Liam McKay @liammckay http://dribbble.com/shots/50882-Purple-Play-Pause
+ *
+ * Standing on the shoulders of :
+ * John Resig @jresig
+ * Mark Panaghiston @thepag
+ * Louis-Rémi Babé @Louis_Remi
+ */
+
+
+var CirclePlayer = function (jPlayerSelector, media, options) {
+ var self = this,
+
+ defaults = {
+ // solution: "flash, html", // For testing Flash with CSS3
+ supplied: "m4a, oga",
+ // Android 2.3 corrupts media element if preload:"none" is used.
+ // preload: "none", // No point preloading metadata since no times are displayed. It helps keep the buffer state correct too.
+ cssSelectorAncestor: "#cp_container_1",
+ cssSelector: {
+ play: ".cp-play",
+ pause: ".cp-pause"
+ }
+ },
+
+ cssSelector = {
+ bufferHolder: ".cp-buffer-holder",
+ buffer1: ".cp-buffer-1",
+ buffer2: ".cp-buffer-2",
+ progressHolder: ".cp-progress-holder",
+ progress1: ".cp-progress-1",
+ progress2: ".cp-progress-2",
+ circleControl: ".cp-circle-control"
+ };
+
+ this.cssClass = {
+ gt50: "cp-gt50",
+ fallback: "cp-fallback"
+ };
+
+ this.spritePitch = 104;
+ this.spriteRatio = 0.24; // Number of steps / 100
+
+ this.player = $(jPlayerSelector);
+ this.media = $.extend({}, media);
+ this.options = $.extend(true, {}, defaults, options); // Deep copy
+
+ this.cssTransforms = Modernizr.csstransforms;
+ this.audio = {};
+ this.dragging = false; // Indicates if the progressbar is being 'dragged'.
+
+ this.eventNamespace = ".CirclePlayer"; // So the events can easily be removed in destroy.
+
+ this.jq = {};
+ $.each(cssSelector, function (entity, cssSel) {
+ self.jq[entity] = $(self.options.cssSelectorAncestor + " " + cssSel);
+ });
+
+ this._initSolution();
+ this._initPlayer();
+};
+
+CirclePlayer.prototype = {
+ _createHtml: function () {
+ },
+ _initPlayer: function () {
+ var self = this;
+ this.player.jPlayer(this.options);
+
+ this.player.bind($.jPlayer.event.ready + this.eventNamespace, function (event) {
+ if (event.jPlayer.html.used && event.jPlayer.html.audio.available) {
+ self.audio = $(this).data("jPlayer").htmlElement.audio;
+ }
+ $(this).jPlayer("setMedia", self.media);
+ self._initCircleControl();
+ });
+
+ this.player.bind($.jPlayer.event.play + this.eventNamespace, function (event) {
+ $(this).jPlayer("pauseOthers");
+ });
+
+ // This event fired as play time increments
+ this.player.bind($.jPlayer.event.timeupdate + this.eventNamespace, function (event) {
+ if (!self.dragging) {
+ self._timeupdate(event.jPlayer.status.currentPercentAbsolute);
+ }
+ });
+
+ // This event fired as buffered time increments
+ this.player.bind($.jPlayer.event.progress + this.eventNamespace, function (event) {
+ var percent = 0;
+ if ((typeof self.audio.buffered === "object") && (self.audio.buffered.length > 0)) {
+ if (self.audio.duration > 0) {
+ var bufferTime = 0;
+ for (var i = 0; i < self.audio.buffered.length; i++) {
+ bufferTime += self.audio.buffered.end(i) - self.audio.buffered.start(i);
+ // console.log(i + " | start = " + self.audio.buffered.start(i) + " | end = " + self.audio.buffered.end(i) + " | bufferTime = " + bufferTime + " | duration = " + self.audio.duration);
+ }
+ percent = 100 * bufferTime / self.audio.duration;
+ } // else the Metadata has not been read yet.
+ // console.log("percent = " + percent);
+ } else { // Fallback if buffered not supported
+ // percent = event.jPlayer.status.seekPercent;
+ percent = 0; // Cleans up the inital conditions on all browsers, since seekPercent defaults to 100 when object is undefined.
+ }
+ self._progress(percent); // Problem here at initial condition. Due to the Opera clause above of buffered.length > 0 above... Removing it means Opera's white buffer ring never shows like with polyfill.
+ // Firefox 4 does not always give the final progress event when buffered = 100%
+ });
+
+ this.player.bind($.jPlayer.event.ended + this.eventNamespace, function (event) {
+ self._resetSolution();
+ });
+ },
+ _initSolution: function () {
+ if (this.cssTransforms) {
+ this.jq.progressHolder.show();
+ this.jq.bufferHolder.show();
+ } else {
+ this.jq.progressHolder.addClass(this.cssClass.gt50).show();
+ this.jq.progress1.addClass(this.cssClass.fallback);
+ this.jq.progress2.hide();
+ this.jq.bufferHolder.hide();
+ }
+ this._resetSolution();
+ },
+ _resetSolution: function () {
+ if (this.cssTransforms) {
+ this.jq.progressHolder.removeClass(this.cssClass.gt50);
+ this.jq.progress1.css({'transform': 'rotate(0deg)'});
+ this.jq.progress2.css({'transform': 'rotate(0deg)'}).hide();
+ } else {
+ this.jq.progress1.css('background-position', '0 ' + this.spritePitch + 'px');
+ }
+ },
+ _initCircleControl: function () {
+ var self = this;
+ this.jq.circleControl.grab({
+ onstart: function () {
+ self.dragging = true;
+ }, onmove: function (event) {
+ var pc = self._getArcPercent(event.position.x, event.position.y);
+ self.player.jPlayer("playHead", pc).jPlayer("play");
+ self._timeupdate(pc);
+ }, onfinish: function (event) {
+ self.dragging = false;
+ var pc = self._getArcPercent(event.position.x, event.position.y);
+ self.player.jPlayer("playHead", pc).jPlayer("play");
+ }
+ });
+ },
+ _timeupdate: function (percent) {
+ var degs = percent * 3.6 + "deg";
+
+ var spriteOffset = (Math.floor((Math.round(percent)) * this.spriteRatio) - 1) * -this.spritePitch;
+
+ if (percent <= 50) {
+ if (this.cssTransforms) {
+ this.jq.progressHolder.removeClass(this.cssClass.gt50);
+ this.jq.progress1.css({'transform': 'rotate(' + degs + ')'});
+ this.jq.progress2.hide();
+ } else { // fall back
+ this.jq.progress1.css('background-position', '0 ' + spriteOffset + 'px');
+ }
+ } else if (percent <= 100) {
+ if (this.cssTransforms) {
+ this.jq.progressHolder.addClass(this.cssClass.gt50);
+ this.jq.progress1.css({'transform': 'rotate(180deg)'});
+ this.jq.progress2.css({'transform': 'rotate(' + degs + ')'});
+ this.jq.progress2.show();
+ } else { // fall back
+ this.jq.progress1.css('background-position', '0 ' + spriteOffset + 'px');
+ }
+ }
+ },
+ _progress: function (percent) {
+ var degs = percent * 3.6 + "deg";
+
+ if (this.cssTransforms) {
+ if (percent <= 50) {
+ this.jq.bufferHolder.removeClass(this.cssClass.gt50);
+ this.jq.buffer1.css({'transform': 'rotate(' + degs + ')'});
+ this.jq.buffer2.hide();
+ } else if (percent <= 100) {
+ this.jq.bufferHolder.addClass(this.cssClass.gt50);
+ this.jq.buffer1.css({'transform': 'rotate(180deg)'});
+ this.jq.buffer2.show();
+ this.jq.buffer2.css({'transform': 'rotate(' + degs + ')'});
+ }
+ }
+ },
+ _getArcPercent: function (pageX, pageY) {
+ var offset = this.jq.circleControl.offset(),
+ x = pageX - offset.left - this.jq.circleControl.width() / 2,
+ y = pageY - offset.top - this.jq.circleControl.height() / 2,
+ theta = Math.atan2(y, x);
+
+ if (theta > -1 * Math.PI && theta < -0.5 * Math.PI) {
+ theta = 2 * Math.PI + theta;
+ }
+
+ // theta is now value between -0.5PI and 1.5PI
+ // ready to be normalized and applied
+
+ return (theta + Math.PI / 2) / 2 * Math.PI * 10;
+ },
+ setMedia: function (media) {
+ this.media = $.extend({}, media);
+ this.player.jPlayer("setMedia", this.media);
+ },
+ play: function (time) {
+ this.player.jPlayer("play", time);
+ },
+ pause: function (time) {
+ this.player.jPlayer("pause", time);
+ },
+ destroy: function () {
+ this.player.unbind(this.eventNamespace);
+ this.player.jPlayer("destroy");
+ }
+};
diff --git a/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.grab.js b/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.grab.js
new file mode 100644
index 0000000..2d0e053
--- /dev/null
+++ b/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.grab.js
@@ -0,0 +1,209 @@
+/*
+jQuery grab
+https://github.com/jussi-kalliokoski/jQuery.grab
+Ported from Jin.js::gestures
+https://github.com/jussi-kalliokoski/jin.js/
+Created by Jussi Kalliokoski
+Licensed under MIT License.
+
+Includes fix for IE
+*/
+
+
+(function ($) {
+ var extend = $.extend,
+ mousedown = 'mousedown',
+ mousemove = 'mousemove',
+ mouseup = 'mouseup',
+ touchstart = 'touchstart',
+ touchmove = 'touchmove',
+ touchend = 'touchend',
+ touchcancel = 'touchcancel';
+
+ function unbind(elem, type, func) {
+ if (type.substr(0, 5) !== 'touch') { // A temporary fix for IE8 data passing problem in Jin.
+ return $(elem).unbind(type, func);
+ }
+ var fnc, i;
+ for (i = 0; i < bind._binds.length; i++) {
+ if (bind._binds[i].elem === elem && bind._binds[i].type === type && bind._binds[i].func === func) {
+ if (document.addEventListener) {
+ elem.removeEventListener(type, bind._binds[i].fnc, false);
+ } else {
+ elem.detachEvent('on' + type, bind._binds[i].fnc);
+ }
+ bind._binds.splice(i--, 1);
+ }
+ }
+ }
+
+ function bind(elem, type, func, pass) {
+ if (type.substr(0, 5) !== 'touch') { // A temporary fix for IE8 data passing problem in Jin.
+ return $(elem).bind(type, pass, func);
+ }
+ var fnc, i;
+ if (bind[type]) {
+ return bind[type].bind(elem, type, func, pass);
+ }
+ fnc = function (e) {
+ if (!e) { // Fix some ie bugs...
+ e = window.event;
+ }
+ if (!e.stopPropagation) {
+ e.stopPropagation = function () {
+ this.cancelBubble = true;
+ };
+ }
+ e.data = pass;
+ func.call(elem, e);
+ };
+ if (document.addEventListener) {
+ elem.addEventListener(type, fnc, false);
+ } else {
+ elem.attachEvent('on' + type, fnc);
+ }
+ bind._binds.push({elem: elem, type: type, func: func, fnc: fnc});
+ }
+
+ function grab(elem, options) {
+ var data = {
+ move: {x: 0, y: 0},
+ offset: {x: 0, y: 0},
+ position: {x: 0, y: 0},
+ start: {x: 0, y: 0},
+ affects: document.documentElement,
+ stopPropagation: false,
+ preventDefault: true,
+ touch: true // Implementation unfinished, and doesn't support multitouch
+ };
+ extend(data, options);
+ data.element = elem;
+ bind(elem, mousedown, mouseDown, data);
+ if (data.touch) {
+ bind(elem, touchstart, touchStart, data);
+ }
+ }
+
+ function ungrab(elem) {
+ unbind(elem, mousedown, mousedown);
+ }
+
+ function mouseDown(e) {
+ e.data.position.x = e.pageX;
+ e.data.position.y = e.pageY;
+ e.data.start.x = e.pageX;
+ e.data.start.y = e.pageY;
+ e.data.event = e;
+ if (e.data.onstart && e.data.onstart.call(e.data.element, e.data)) {
+ return;
+ }
+ if (e.preventDefault && e.data.preventDefault) {
+ e.preventDefault();
+ }
+ if (e.stopPropagation && e.data.stopPropagation) {
+ e.stopPropagation();
+ }
+ bind(e.data.affects, mousemove, mouseMove, e.data);
+ bind(e.data.affects, mouseup, mouseUp, e.data);
+ }
+
+ function mouseMove(e) {
+ if (e.preventDefault && e.data.preventDefault) {
+ e.preventDefault();
+ }
+ if (e.stopPropagation && e.data.preventDefault) {
+ e.stopPropagation();
+ }
+ e.data.move.x = e.pageX - e.data.position.x;
+ e.data.move.y = e.pageY - e.data.position.y;
+ e.data.position.x = e.pageX;
+ e.data.position.y = e.pageY;
+ e.data.offset.x = e.pageX - e.data.start.x;
+ e.data.offset.y = e.pageY - e.data.start.y;
+ e.data.event = e;
+ if (e.data.onmove) {
+ e.data.onmove.call(e.data.element, e.data);
+ }
+ }
+
+ function mouseUp(e) {
+ if (e.preventDefault && e.data.preventDefault) {
+ e.preventDefault();
+ }
+ if (e.stopPropagation && e.data.stopPropagation) {
+ e.stopPropagation();
+ }
+ unbind(e.data.affects, mousemove, mouseMove);
+ unbind(e.data.affects, mouseup, mouseUp);
+ e.data.event = e;
+ if (e.data.onfinish) {
+ e.data.onfinish.call(e.data.element, e.data);
+ }
+ }
+
+ function touchStart(e) {
+ e.data.position.x = e.touches[0].pageX;
+ e.data.position.y = e.touches[0].pageY;
+ e.data.start.x = e.touches[0].pageX;
+ e.data.start.y = e.touches[0].pageY;
+ e.data.event = e;
+ if (e.data.onstart && e.data.onstart.call(e.data.element, e.data)) {
+ return;
+ }
+ if (e.preventDefault && e.data.preventDefault) {
+ e.preventDefault();
+ }
+ if (e.stopPropagation && e.data.stopPropagation) {
+ e.stopPropagation();
+ }
+ bind(e.data.affects, touchmove, touchMove, e.data);
+ bind(e.data.affects, touchend, touchEnd, e.data);
+ }
+
+ function touchMove(e) {
+ if (e.preventDefault && e.data.preventDefault) {
+ e.preventDefault();
+ }
+ if (e.stopPropagation && e.data.stopPropagation) {
+ e.stopPropagation();
+ }
+ e.data.move.x = e.touches[0].pageX - e.data.position.x;
+ e.data.move.y = e.touches[0].pageY - e.data.position.y;
+ e.data.position.x = e.touches[0].pageX;
+ e.data.position.y = e.touches[0].pageY;
+ e.data.offset.x = e.touches[0].pageX - e.data.start.x;
+ e.data.offset.y = e.touches[0].pageY - e.data.start.y;
+ e.data.event = e;
+ if (e.data.onmove) {
+ e.data.onmove.call(e.data.elem, e.data);
+ }
+ }
+
+ function touchEnd(e) {
+ if (e.preventDefault && e.data.preventDefault) {
+ e.preventDefault();
+ }
+ if (e.stopPropagation && e.data.stopPropagation) {
+ e.stopPropagation();
+ }
+ unbind(e.data.affects, touchmove, touchMove);
+ unbind(e.data.affects, touchend, touchEnd);
+ e.data.event = e;
+ if (e.data.onfinish) {
+ e.data.onfinish.call(e.data.element, e.data);
+ }
+ }
+
+ bind._binds = [];
+
+ $.fn.grab = function (a, b) {
+ return this.each(function () {
+ return grab(this, a, b);
+ });
+ };
+ $.fn.ungrab = function (a) {
+ return this.each(function () {
+ return ungrab(this, a);
+ });
+ };
+})(jQuery);
diff --git a/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.jplayer.min.js b/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.jplayer.min.js
new file mode 100644
index 0000000..99f64d7
--- /dev/null
+++ b/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.jplayer.min.js
@@ -0,0 +1,3 @@
+/*! jPlayer 2.9.2 for jQuery ~ (c) 2009-2014 Happyworm Ltd ~ MIT License */
+!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],b):b("object"==typeof exports?require("jquery"):a.jQuery?a.jQuery:a.Zepto)}(this,function(a,b){a.fn.jPlayer=function(c){var d="jPlayer",e="string"==typeof c,f=Array.prototype.slice.call(arguments,1),g=this;return c=!e&&f.length?a.extend.apply(null,[!0,c].concat(f)):c,e&&"_"===c.charAt(0)?g:(this.each(e?function(){var e=a(this).data(d),h=e&&a.isFunction(e[c])?e[c].apply(e,f):e;return h!==e&&h!==b?(g=h,!1):void 0}:function(){var b=a(this).data(d);b?b.option(c||{}):a(this).data(d,new a.jPlayer(c,this))}),g)},a.jPlayer=function(b,c){if(arguments.length){this.element=a(c),this.options=a.extend(!0,{},this.options,b);var d=this;this.element.bind("remove.jPlayer",function(){d.destroy()}),this._init()}},"function"!=typeof a.fn.stop&&(a.fn.stop=function(){}),a.jPlayer.emulateMethods="load play pause",a.jPlayer.emulateStatus="src readyState networkState currentTime duration paused ended playbackRate",a.jPlayer.emulateOptions="muted volume",a.jPlayer.reservedEvent="ready flashreset resize repeat error warning",a.jPlayer.event={},a.each(["ready","setmedia","flashreset","resize","repeat","click","error","warning","loadstart","progress","suspend","abort","emptied","stalled","play","pause","loadedmetadata","loadeddata","waiting","playing","canplay","canplaythrough","seeking","seeked","timeupdate","ended","ratechange","durationchange","volumechange"],function(){a.jPlayer.event[this]="jPlayer_"+this}),a.jPlayer.htmlEvent=["loadstart","abort","emptied","stalled","loadedmetadata","canplay","canplaythrough"],a.jPlayer.pause=function(){a.jPlayer.prototype.destroyRemoved(),a.each(a.jPlayer.prototype.instances,function(a,b){b.data("jPlayer").status.srcSet&&b.jPlayer("pause")})},a.jPlayer.timeFormat={showHour:!1,showMin:!0,showSec:!0,padHour:!1,padMin:!0,padSec:!0,sepHour:":",sepMin:":",sepSec:""};var c=function(){this.init()};c.prototype={init:function(){this.options={timeFormat:a.jPlayer.timeFormat}},time:function(a){a=a&&"number"==typeof a?a:0;var b=new Date(1e3*a),c=b.getUTCHours(),d=this.options.timeFormat.showHour?b.getUTCMinutes():b.getUTCMinutes()+60*c,e=this.options.timeFormat.showMin?b.getUTCSeconds():b.getUTCSeconds()+60*d,f=this.options.timeFormat.padHour&&10>c?"0"+c:c,g=this.options.timeFormat.padMin&&10>d?"0"+d:d,h=this.options.timeFormat.padSec&&10>e?"0"+e:e,i="";return i+=this.options.timeFormat.showHour?f+this.options.timeFormat.sepHour:"",i+=this.options.timeFormat.showMin?g+this.options.timeFormat.sepMin:"",i+=this.options.timeFormat.showSec?h+this.options.timeFormat.sepSec:""}};var d=new c;a.jPlayer.convertTime=function(a){return d.time(a)},a.jPlayer.uaBrowser=function(a){var b=a.toLowerCase(),c=/(webkit)[ \/]([\w.]+)/,d=/(opera)(?:.*version)?[ \/]([\w.]+)/,e=/(msie) ([\w.]+)/,f=/(mozilla)(?:.*? rv:([\w.]+))?/,g=c.exec(b)||d.exec(b)||e.exec(b)||b.indexOf("compatible")<0&&f.exec(b)||[];return{browser:g[1]||"",version:g[2]||"0"}},a.jPlayer.uaPlatform=function(a){var b=a.toLowerCase(),c=/(ipad|iphone|ipod|android|blackberry|playbook|windows ce|webos)/,d=/(ipad|playbook)/,e=/(android)/,f=/(mobile)/,g=c.exec(b)||[],h=d.exec(b)||!f.exec(b)&&e.exec(b)||[];return g[1]&&(g[1]=g[1].replace(/\s/g,"_")),{platform:g[1]||"",tablet:h[1]||""}},a.jPlayer.browser={},a.jPlayer.platform={};var e=a.jPlayer.uaBrowser(navigator.userAgent);e.browser&&(a.jPlayer.browser[e.browser]=!0,a.jPlayer.browser.version=e.version);var f=a.jPlayer.uaPlatform(navigator.userAgent);f.platform&&(a.jPlayer.platform[f.platform]=!0,a.jPlayer.platform.mobile=!f.tablet,a.jPlayer.platform.tablet=!!f.tablet),a.jPlayer.getDocMode=function(){var b;return a.jPlayer.browser.msie&&(document.documentMode?b=document.documentMode:(b=5,document.compatMode&&"CSS1Compat"===document.compatMode&&(b=7))),b},a.jPlayer.browser.documentMode=a.jPlayer.getDocMode(),a.jPlayer.nativeFeatures={init:function(){var a,b,c,d=document,e=d.createElement("video"),f={w3c:["fullscreenEnabled","fullscreenElement","requestFullscreen","exitFullscreen","fullscreenchange","fullscreenerror"],moz:["mozFullScreenEnabled","mozFullScreenElement","mozRequestFullScreen","mozCancelFullScreen","mozfullscreenchange","mozfullscreenerror"],webkit:["","webkitCurrentFullScreenElement","webkitRequestFullScreen","webkitCancelFullScreen","webkitfullscreenchange",""],webkitVideo:["webkitSupportsFullscreen","webkitDisplayingFullscreen","webkitEnterFullscreen","webkitExitFullscreen","",""],ms:["","msFullscreenElement","msRequestFullscreen","msExitFullscreen","MSFullscreenChange","MSFullscreenError"]},g=["w3c","moz","webkit","webkitVideo","ms"];for(this.fullscreen=a={support:{w3c:!!d[f.w3c[0]],moz:!!d[f.moz[0]],webkit:"function"==typeof d[f.webkit[3]],webkitVideo:"function"==typeof e[f.webkitVideo[2]],ms:"function"==typeof e[f.ms[2]]},used:{}},b=0,c=g.length;c>b;b++){var h=g[b];if(a.support[h]){a.spec=h,a.used[h]=!0;break}}if(a.spec){var i=f[a.spec];a.api={fullscreenEnabled:!0,fullscreenElement:function(a){return a=a?a:d,a[i[1]]},requestFullscreen:function(a){return a[i[2]]()},exitFullscreen:function(a){return a=a?a:d,a[i[3]]()}},a.event={fullscreenchange:i[4],fullscreenerror:i[5]}}else a.api={fullscreenEnabled:!1,fullscreenElement:function(){return null},requestFullscreen:function(){},exitFullscreen:function(){}},a.event={}}},a.jPlayer.nativeFeatures.init(),a.jPlayer.focus=null,a.jPlayer.keyIgnoreElementNames="A INPUT TEXTAREA SELECT BUTTON";var g=function(b){var c,d=a.jPlayer.focus;d&&(a.each(a.jPlayer.keyIgnoreElementNames.split(/\s+/g),function(a,d){return b.target.nodeName.toUpperCase()===d.toUpperCase()?(c=!0,!1):void 0}),c||a.each(d.options.keyBindings,function(c,e){return e&&a.isFunction(e.fn)&&("number"==typeof e.key&&b.which===e.key||"string"==typeof e.key&&b.key===e.key)?(b.preventDefault(),e.fn(d),!1):void 0}))};a.jPlayer.keys=function(b){var c="keydown.jPlayer";a(document.documentElement).unbind(c),b&&a(document.documentElement).bind(c,g)},a.jPlayer.keys(!0),a.jPlayer.prototype={count:0,version:{script:"2.9.2",needFlash:"2.9.0",flash:"unknown"},options:{swfPath:"js",solution:"html, flash",supplied:"mp3",auroraFormats:"wav",preload:"metadata",volume:.8,muted:!1,remainingDuration:!1,toggleDuration:!1,captureDuration:!0,playbackRate:1,defaultPlaybackRate:1,minPlaybackRate:.5,maxPlaybackRate:4,wmode:"opaque",backgroundColor:"#000000",cssSelectorAncestor:"#jp_container_1",cssSelector:{videoPlay:".jp-video-play",play:".jp-play",pause:".jp-pause",stop:".jp-stop",seekBar:".jp-seek-bar",playBar:".jp-play-bar",mute:".jp-mute",unmute:".jp-unmute",volumeBar:".jp-volume-bar",volumeBarValue:".jp-volume-bar-value",volumeMax:".jp-volume-max",playbackRateBar:".jp-playback-rate-bar",playbackRateBarValue:".jp-playback-rate-bar-value",currentTime:".jp-current-time",duration:".jp-duration",title:".jp-title",fullScreen:".jp-full-screen",restoreScreen:".jp-restore-screen",repeat:".jp-repeat",repeatOff:".jp-repeat-off",gui:".jp-gui",noSolution:".jp-no-solution"},stateClass:{playing:"jp-state-playing",seeking:"jp-state-seeking",muted:"jp-state-muted",looped:"jp-state-looped",fullScreen:"jp-state-full-screen",noVolume:"jp-state-no-volume"},useStateClassSkin:!1,autoBlur:!0,smoothPlayBar:!1,fullScreen:!1,fullWindow:!1,autohide:{restored:!1,full:!0,fadeIn:200,fadeOut:600,hold:1e3},loop:!1,repeat:function(b){b.jPlayer.options.loop?a(this).unbind(".jPlayerRepeat").bind(a.jPlayer.event.ended+".jPlayer.jPlayerRepeat",function(){a(this).jPlayer("play")}):a(this).unbind(".jPlayerRepeat")},nativeVideoControls:{},noFullWindow:{msie:/msie [0-6]\./,ipad:/ipad.*?os [0-4]\./,iphone:/iphone/,ipod:/ipod/,android_pad:/android [0-3]\.(?!.*?mobile)/,android_phone:/(?=.*android)(?!.*chrome)(?=.*mobile)/,blackberry:/blackberry/,windows_ce:/windows ce/,iemobile:/iemobile/,webos:/webos/},noVolume:{ipad:/ipad/,iphone:/iphone/,ipod:/ipod/,android_pad:/android(?!.*?mobile)/,android_phone:/android.*?mobile/,blackberry:/blackberry/,windows_ce:/windows ce/,iemobile:/iemobile/,webos:/webos/,playbook:/playbook/},timeFormat:{},keyEnabled:!1,audioFullScreen:!1,keyBindings:{play:{key:80,fn:function(a){a.status.paused?a.play():a.pause()}},fullScreen:{key:70,fn:function(a){(a.status.video||a.options.audioFullScreen)&&a._setOption("fullScreen",!a.options.fullScreen)}},muted:{key:77,fn:function(a){a._muted(!a.options.muted)}},volumeUp:{key:190,fn:function(a){a.volume(a.options.volume+.1)}},volumeDown:{key:188,fn:function(a){a.volume(a.options.volume-.1)}},loop:{key:76,fn:function(a){a._loop(!a.options.loop)}}},verticalVolume:!1,verticalPlaybackRate:!1,globalVolume:!1,idPrefix:"jp",noConflict:"jQuery",emulateHtml:!1,consoleAlerts:!0,errorAlerts:!1,warningAlerts:!1},optionsAudio:{size:{width:"0px",height:"0px",cssClass:""},sizeFull:{width:"0px",height:"0px",cssClass:""}},optionsVideo:{size:{width:"480px",height:"270px",cssClass:"jp-video-270p"},sizeFull:{width:"100%",height:"100%",cssClass:"jp-video-full"}},instances:{},status:{src:"",media:{},paused:!0,format:{},formatType:"",waitForPlay:!0,waitForLoad:!0,srcSet:!1,video:!1,seekPercent:0,currentPercentRelative:0,currentPercentAbsolute:0,currentTime:0,duration:0,remaining:0,videoWidth:0,videoHeight:0,readyState:0,networkState:0,playbackRate:1,ended:0},internal:{ready:!1},solution:{html:!0,aurora:!0,flash:!0},format:{mp3:{codec:"audio/mpeg",flashCanPlay:!0,media:"audio"},m4a:{codec:'audio/mp4; codecs="mp4a.40.2"',flashCanPlay:!0,media:"audio"},m3u8a:{codec:'application/vnd.apple.mpegurl; codecs="mp4a.40.2"',flashCanPlay:!1,media:"audio"},m3ua:{codec:"audio/mpegurl",flashCanPlay:!1,media:"audio"},oga:{codec:'audio/ogg; codecs="vorbis, opus"',flashCanPlay:!1,media:"audio"},flac:{codec:"audio/x-flac",flashCanPlay:!1,media:"audio"},wav:{codec:'audio/wav; codecs="1"',flashCanPlay:!1,media:"audio"},webma:{codec:'audio/webm; codecs="vorbis"',flashCanPlay:!1,media:"audio"},fla:{codec:"audio/x-flv",flashCanPlay:!0,media:"audio"},rtmpa:{codec:'audio/rtmp; codecs="rtmp"',flashCanPlay:!0,media:"audio"},m4v:{codec:'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',flashCanPlay:!0,media:"video"},m3u8v:{codec:'application/vnd.apple.mpegurl; codecs="avc1.42E01E, mp4a.40.2"',flashCanPlay:!1,media:"video"},m3uv:{codec:"audio/mpegurl",flashCanPlay:!1,media:"video"},ogv:{codec:'video/ogg; codecs="theora, vorbis"',flashCanPlay:!1,media:"video"},webmv:{codec:'video/webm; codecs="vorbis, vp8"',flashCanPlay:!1,media:"video"},flv:{codec:"video/x-flv",flashCanPlay:!0,media:"video"},rtmpv:{codec:'video/rtmp; codecs="rtmp"',flashCanPlay:!0,media:"video"}},_init:function(){var c=this;if(this.element.empty(),this.status=a.extend({},this.status),this.internal=a.extend({},this.internal),this.options.timeFormat=a.extend({},a.jPlayer.timeFormat,this.options.timeFormat),this.internal.cmdsIgnored=a.jPlayer.platform.ipad||a.jPlayer.platform.iphone||a.jPlayer.platform.ipod,this.internal.domNode=this.element.get(0),this.options.keyEnabled&&!a.jPlayer.focus&&(a.jPlayer.focus=this),this.androidFix={setMedia:!1,play:!1,pause:!1,time:0/0},a.jPlayer.platform.android&&(this.options.preload="auto"!==this.options.preload?"metadata":"auto"),this.formats=[],this.solutions=[],this.require={},this.htmlElement={},this.html={},this.html.audio={},this.html.video={},this.aurora={},this.aurora.formats=[],this.aurora.properties=[],this.flash={},this.css={},this.css.cs={},this.css.jq={},this.ancestorJq=[],this.options.volume=this._limitValue(this.options.volume,0,1),a.each(this.options.supplied.toLowerCase().split(","),function(b,d){var e=d.replace(/^\s+|\s+$/g,"");if(c.format[e]){var f=!1;a.each(c.formats,function(a,b){return e===b?(f=!0,!1):void 0}),f||c.formats.push(e)}}),a.each(this.options.solution.toLowerCase().split(","),function(b,d){var e=d.replace(/^\s+|\s+$/g,"");if(c.solution[e]){var f=!1;a.each(c.solutions,function(a,b){return e===b?(f=!0,!1):void 0}),f||c.solutions.push(e)}}),a.each(this.options.auroraFormats.toLowerCase().split(","),function(b,d){var e=d.replace(/^\s+|\s+$/g,"");if(c.format[e]){var f=!1;a.each(c.aurora.formats,function(a,b){return e===b?(f=!0,!1):void 0}),f||c.aurora.formats.push(e)}}),this.internal.instance="jp_"+this.count,this.instances[this.internal.instance]=this.element,this.element.attr("id")||this.element.attr("id",this.options.idPrefix+"_jplayer_"+this.count),this.internal.self=a.extend({},{id:this.element.attr("id"),jq:this.element}),this.internal.audio=a.extend({},{id:this.options.idPrefix+"_audio_"+this.count,jq:b}),this.internal.video=a.extend({},{id:this.options.idPrefix+"_video_"+this.count,jq:b}),this.internal.flash=a.extend({},{id:this.options.idPrefix+"_flash_"+this.count,jq:b,swf:this.options.swfPath+(".swf"!==this.options.swfPath.toLowerCase().slice(-4)?(this.options.swfPath&&"/"!==this.options.swfPath.slice(-1)?"/":"")+"jquery.jplayer.swf":"")}),this.internal.poster=a.extend({},{id:this.options.idPrefix+"_poster_"+this.count,jq:b}),a.each(a.jPlayer.event,function(a,d){c.options[a]!==b&&(c.element.bind(d+".jPlayer",c.options[a]),c.options[a]=b)}),this.require.audio=!1,this.require.video=!1,a.each(this.formats,function(a,b){c.require[c.format[b].media]=!0}),this.options=this.require.video?a.extend(!0,{},this.optionsVideo,this.options):a.extend(!0,{},this.optionsAudio,this.options),this._setSize(),this.status.nativeVideoControls=this._uaBlocklist(this.options.nativeVideoControls),this.status.noFullWindow=this._uaBlocklist(this.options.noFullWindow),this.status.noVolume=this._uaBlocklist(this.options.noVolume),a.jPlayer.nativeFeatures.fullscreen.api.fullscreenEnabled&&this._fullscreenAddEventListeners(),this._restrictNativeVideoControls(),this.htmlElement.poster=document.createElement("img"),this.htmlElement.poster.id=this.internal.poster.id,this.htmlElement.poster.onload=function(){(!c.status.video||c.status.waitForPlay)&&c.internal.poster.jq.show()},this.element.append(this.htmlElement.poster),this.internal.poster.jq=a("#"+this.internal.poster.id),this.internal.poster.jq.css({width:this.status.width,height:this.status.height}),this.internal.poster.jq.hide(),this.internal.poster.jq.bind("click.jPlayer",function(){c._trigger(a.jPlayer.event.click)}),this.html.audio.available=!1,this.require.audio&&(this.htmlElement.audio=document.createElement("audio"),this.htmlElement.audio.id=this.internal.audio.id,this.html.audio.available=!!this.htmlElement.audio.canPlayType&&this._testCanPlayType(this.htmlElement.audio)),this.html.video.available=!1,this.require.video&&(this.htmlElement.video=document.createElement("video"),this.htmlElement.video.id=this.internal.video.id,this.html.video.available=!!this.htmlElement.video.canPlayType&&this._testCanPlayType(this.htmlElement.video)),this.flash.available=this._checkForFlash(10.1),this.html.canPlay={},this.aurora.canPlay={},this.flash.canPlay={},a.each(this.formats,function(b,d){c.html.canPlay[d]=c.html[c.format[d].media].available&&""!==c.htmlElement[c.format[d].media].canPlayType(c.format[d].codec),c.aurora.canPlay[d]=a.inArray(d,c.aurora.formats)>-1,c.flash.canPlay[d]=c.format[d].flashCanPlay&&c.flash.available}),this.html.desired=!1,this.aurora.desired=!1,this.flash.desired=!1,a.each(this.solutions,function(b,d){if(0===b)c[d].desired=!0;else{var e=!1,f=!1;a.each(c.formats,function(a,b){c[c.solutions[0]].canPlay[b]&&("video"===c.format[b].media?f=!0:e=!0)}),c[d].desired=c.require.audio&&!e||c.require.video&&!f}}),this.html.support={},this.aurora.support={},this.flash.support={},a.each(this.formats,function(a,b){c.html.support[b]=c.html.canPlay[b]&&c.html.desired,c.aurora.support[b]=c.aurora.canPlay[b]&&c.aurora.desired,c.flash.support[b]=c.flash.canPlay[b]&&c.flash.desired}),this.html.used=!1,this.aurora.used=!1,this.flash.used=!1,a.each(this.solutions,function(b,d){a.each(c.formats,function(a,b){return c[d].support[b]?(c[d].used=!0,!1):void 0})}),this._resetActive(),this._resetGate(),this._cssSelectorAncestor(this.options.cssSelectorAncestor),this.html.used||this.aurora.used||this.flash.used?this.css.jq.noSolution.length&&this.css.jq.noSolution.hide():(this._error({type:a.jPlayer.error.NO_SOLUTION,context:"{solution:'"+this.options.solution+"', supplied:'"+this.options.supplied+"'}",message:a.jPlayer.errorMsg.NO_SOLUTION,hint:a.jPlayer.errorHint.NO_SOLUTION}),this.css.jq.noSolution.length&&this.css.jq.noSolution.show()),this.flash.used){var d,e="jQuery="+encodeURI(this.options.noConflict)+"&id="+encodeURI(this.internal.self.id)+"&vol="+this.options.volume+"&muted="+this.options.muted;if(a.jPlayer.browser.msie&&(Number(a.jPlayer.browser.version)<9||a.jPlayer.browser.documentMode<9)){var f=' ',g=[' ',' ',' ',' ',' '];d=document.createElement(f);for(var h=0;h0&&(d.internal.cmdsIgnored=!1),d._getHtmlStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.progress))},!1),b.addEventListener("loadeddata",function(){c.gate&&(d.androidFix.setMedia=!1,d.androidFix.play&&(d.androidFix.play=!1,d.play(d.androidFix.time)),d.androidFix.pause&&(d.androidFix.pause=!1,d.pause(d.androidFix.time)),d._trigger(a.jPlayer.event.loadeddata))},!1),b.addEventListener("timeupdate",function(){c.gate&&(d._getHtmlStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.timeupdate))},!1),b.addEventListener("durationchange",function(){c.gate&&(d._getHtmlStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.durationchange))},!1),b.addEventListener("play",function(){c.gate&&(d._updateButtons(!0),d._html_checkWaitForPlay(),d._trigger(a.jPlayer.event.play))},!1),b.addEventListener("playing",function(){c.gate&&(d._updateButtons(!0),d._seeked(),d._trigger(a.jPlayer.event.playing))},!1),b.addEventListener("pause",function(){c.gate&&(d._updateButtons(!1),d._trigger(a.jPlayer.event.pause))},!1),b.addEventListener("waiting",function(){c.gate&&(d._seeking(),d._trigger(a.jPlayer.event.waiting))},!1),b.addEventListener("seeking",function(){c.gate&&(d._seeking(),d._trigger(a.jPlayer.event.seeking))},!1),b.addEventListener("seeked",function(){c.gate&&(d._seeked(),d._trigger(a.jPlayer.event.seeked))},!1),b.addEventListener("volumechange",function(){c.gate&&(d.options.volume=b.volume,d.options.muted=b.muted,d._updateMute(),d._updateVolume(),d._trigger(a.jPlayer.event.volumechange))},!1),b.addEventListener("ratechange",function(){c.gate&&(d.options.defaultPlaybackRate=b.defaultPlaybackRate,d.options.playbackRate=b.playbackRate,d._updatePlaybackRate(),d._trigger(a.jPlayer.event.ratechange))},!1),b.addEventListener("suspend",function(){c.gate&&(d._seeked(),d._trigger(a.jPlayer.event.suspend))},!1),b.addEventListener("ended",function(){c.gate&&(a.jPlayer.browser.webkit||(d.htmlElement.media.currentTime=0),d.htmlElement.media.pause(),d._updateButtons(!1),d._getHtmlStatus(b,!0),d._updateInterface(),d._trigger(a.jPlayer.event.ended))},!1),b.addEventListener("error",function(){c.gate&&(d._updateButtons(!1),d._seeked(),d.status.srcSet&&(clearTimeout(d.internal.htmlDlyCmdId),d.status.waitForLoad=!0,d.status.waitForPlay=!0,d.status.video&&!d.status.nativeVideoControls&&d.internal.video.jq.css({width:"0px",height:"0px"}),d._validString(d.status.media.poster)&&!d.status.nativeVideoControls&&d.internal.poster.jq.show(),d.css.jq.videoPlay.length&&d.css.jq.videoPlay.show(),d._error({type:a.jPlayer.error.URL,context:d.status.src,message:a.jPlayer.errorMsg.URL,hint:a.jPlayer.errorHint.URL})))},!1),a.each(a.jPlayer.htmlEvent,function(e,f){b.addEventListener(this,function(){c.gate&&d._trigger(a.jPlayer.event[f])},!1)})},_addAuroraEventListeners:function(b,c){var d=this;b.volume=100*this.options.volume,b.on("progress",function(){c.gate&&(d.internal.cmdsIgnored&&this.readyState>0&&(d.internal.cmdsIgnored=!1),d._getAuroraStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.progress),b.duration>0&&d._trigger(a.jPlayer.event.timeupdate))},!1),b.on("ready",function(){c.gate&&d._trigger(a.jPlayer.event.loadeddata)},!1),b.on("duration",function(){c.gate&&(d._getAuroraStatus(b),d._updateInterface(),d._trigger(a.jPlayer.event.durationchange))},!1),b.on("end",function(){c.gate&&(d._updateButtons(!1),d._getAuroraStatus(b,!0),d._updateInterface(),d._trigger(a.jPlayer.event.ended))},!1),b.on("error",function(){c.gate&&(d._updateButtons(!1),d._seeked(),d.status.srcSet&&(d.status.waitForLoad=!0,d.status.waitForPlay=!0,d.status.video&&!d.status.nativeVideoControls&&d.internal.video.jq.css({width:"0px",height:"0px"}),d._validString(d.status.media.poster)&&!d.status.nativeVideoControls&&d.internal.poster.jq.show(),d.css.jq.videoPlay.length&&d.css.jq.videoPlay.show(),d._error({type:a.jPlayer.error.URL,context:d.status.src,message:a.jPlayer.errorMsg.URL,hint:a.jPlayer.errorHint.URL})))},!1)},_getHtmlStatus:function(a,b){var c=0,d=0,e=0,f=0;isFinite(a.duration)&&(this.status.duration=a.duration),c=a.currentTime,d=this.status.duration>0?100*c/this.status.duration:0,"object"==typeof a.seekable&&a.seekable.length>0?(e=this.status.duration>0?100*a.seekable.end(a.seekable.length-1)/this.status.duration:100,f=this.status.duration>0?100*a.currentTime/a.seekable.end(a.seekable.length-1):0):(e=100,f=d),b&&(c=0,f=0,d=0),this.status.seekPercent=e,this.status.currentPercentRelative=f,this.status.currentPercentAbsolute=d,this.status.currentTime=c,this.status.remaining=this.status.duration-this.status.currentTime,this.status.videoWidth=a.videoWidth,this.status.videoHeight=a.videoHeight,this.status.readyState=a.readyState,this.status.networkState=a.networkState,this.status.playbackRate=a.playbackRate,this.status.ended=a.ended},_getAuroraStatus:function(a,b){var c=0,d=0,e=0,f=0;this.status.duration=a.duration/1e3,c=a.currentTime/1e3,d=this.status.duration>0?100*c/this.status.duration:0,a.buffered>0?(e=this.status.duration>0?a.buffered*this.status.duration/this.status.duration:100,f=this.status.duration>0?c/(a.buffered*this.status.duration):0):(e=100,f=d),b&&(c=0,f=0,d=0),this.status.seekPercent=e,this.status.currentPercentRelative=f,this.status.currentPercentAbsolute=d,this.status.currentTime=c,this.status.remaining=this.status.duration-this.status.currentTime,this.status.readyState=4,this.status.networkState=0,this.status.playbackRate=1,this.status.ended=!1},_resetStatus:function(){this.status=a.extend({},this.status,a.jPlayer.prototype.status)},_trigger:function(b,c,d){var e=a.Event(b);e.jPlayer={},e.jPlayer.version=a.extend({},this.version),e.jPlayer.options=a.extend(!0,{},this.options),e.jPlayer.status=a.extend(!0,{},this.status),e.jPlayer.html=a.extend(!0,{},this.html),e.jPlayer.aurora=a.extend(!0,{},this.aurora),e.jPlayer.flash=a.extend(!0,{},this.flash),c&&(e.jPlayer.error=a.extend({},c)),d&&(e.jPlayer.warning=a.extend({},d)),this.element.trigger(e)},jPlayerFlashEvent:function(b,c){if(b===a.jPlayer.event.ready)if(this.internal.ready){if(this.flash.gate){if(this.status.srcSet){var d=this.status.currentTime,e=this.status.paused;this.setMedia(this.status.media),this.volumeWorker(this.options.volume),d>0&&(e?this.pause(d):this.play(d))}this._trigger(a.jPlayer.event.flashreset)}}else this.internal.ready=!0,this.internal.flash.jq.css({width:"0px",height:"0px"}),this.version.flash=c.version,this.version.needFlash!==this.version.flash&&this._error({type:a.jPlayer.error.VERSION,context:this.version.flash,message:a.jPlayer.errorMsg.VERSION+this.version.flash,hint:a.jPlayer.errorHint.VERSION}),this._trigger(a.jPlayer.event.repeat),this._trigger(b);if(this.flash.gate)switch(b){case a.jPlayer.event.progress:this._getFlashStatus(c),this._updateInterface(),this._trigger(b);break;case a.jPlayer.event.timeupdate:this._getFlashStatus(c),this._updateInterface(),this._trigger(b);break;case a.jPlayer.event.play:this._seeked(),this._updateButtons(!0),this._trigger(b);break;case a.jPlayer.event.pause:this._updateButtons(!1),this._trigger(b);break;case a.jPlayer.event.ended:this._updateButtons(!1),this._trigger(b);break;case a.jPlayer.event.click:this._trigger(b);break;case a.jPlayer.event.error:this.status.waitForLoad=!0,this.status.waitForPlay=!0,this.status.video&&this.internal.flash.jq.css({width:"0px",height:"0px"}),this._validString(this.status.media.poster)&&this.internal.poster.jq.show(),this.css.jq.videoPlay.length&&this.status.video&&this.css.jq.videoPlay.show(),this.status.video?this._flash_setVideo(this.status.media):this._flash_setAudio(this.status.media),this._updateButtons(!1),this._error({type:a.jPlayer.error.URL,context:c.src,message:a.jPlayer.errorMsg.URL,hint:a.jPlayer.errorHint.URL});break;case a.jPlayer.event.seeking:this._seeking(),this._trigger(b);break;case a.jPlayer.event.seeked:this._seeked(),this._trigger(b);break;case a.jPlayer.event.ready:break;default:this._trigger(b)}return!1},_getFlashStatus:function(a){this.status.seekPercent=a.seekPercent,this.status.currentPercentRelative=a.currentPercentRelative,this.status.currentPercentAbsolute=a.currentPercentAbsolute,this.status.currentTime=a.currentTime,this.status.duration=a.duration,this.status.remaining=a.duration-a.currentTime,this.status.videoWidth=a.videoWidth,this.status.videoHeight=a.videoHeight,this.status.readyState=4,this.status.networkState=0,this.status.playbackRate=1,this.status.ended=!1},_updateButtons:function(a){a===b?a=!this.status.paused:this.status.paused=!a,a?this.addStateClass("playing"):this.removeStateClass("playing"),!this.status.noFullWindow&&this.options.fullWindow?this.addStateClass("fullScreen"):this.removeStateClass("fullScreen"),this.options.loop?this.addStateClass("looped"):this.removeStateClass("looped"),this.css.jq.play.length&&this.css.jq.pause.length&&(a?(this.css.jq.play.hide(),this.css.jq.pause.show()):(this.css.jq.play.show(),this.css.jq.pause.hide())),this.css.jq.restoreScreen.length&&this.css.jq.fullScreen.length&&(this.status.noFullWindow?(this.css.jq.fullScreen.hide(),this.css.jq.restoreScreen.hide()):this.options.fullWindow?(this.css.jq.fullScreen.hide(),this.css.jq.restoreScreen.show()):(this.css.jq.fullScreen.show(),this.css.jq.restoreScreen.hide())),this.css.jq.repeat.length&&this.css.jq.repeatOff.length&&(this.options.loop?(this.css.jq.repeat.hide(),this.css.jq.repeatOff.show()):(this.css.jq.repeat.show(),this.css.jq.repeatOff.hide()))},_updateInterface:function(){this.css.jq.seekBar.length&&this.css.jq.seekBar.width(this.status.seekPercent+"%"),this.css.jq.playBar.length&&(this.options.smoothPlayBar?this.css.jq.playBar.stop().animate({width:this.status.currentPercentAbsolute+"%"},250,"linear"):this.css.jq.playBar.width(this.status.currentPercentRelative+"%"));var a="";this.css.jq.currentTime.length&&(a=this._convertTime(this.status.currentTime),a!==this.css.jq.currentTime.text()&&this.css.jq.currentTime.text(this._convertTime(this.status.currentTime)));var b="",c=this.status.duration,d=this.status.remaining;this.css.jq.duration.length&&("string"==typeof this.status.media.duration?b=this.status.media.duration:("number"==typeof this.status.media.duration&&(c=this.status.media.duration,d=c-this.status.currentTime),b=this.options.remainingDuration?(d>0?"-":"")+this._convertTime(d):this._convertTime(c)),b!==this.css.jq.duration.text()&&this.css.jq.duration.text(b))},_convertTime:c.prototype.time,_seeking:function(){this.css.jq.seekBar.length&&this.css.jq.seekBar.addClass("jp-seeking-bg"),this.addStateClass("seeking")},_seeked:function(){this.css.jq.seekBar.length&&this.css.jq.seekBar.removeClass("jp-seeking-bg"),this.removeStateClass("seeking")},_resetGate:function(){this.html.audio.gate=!1,this.html.video.gate=!1,this.aurora.gate=!1,this.flash.gate=!1},_resetActive:function(){this.html.active=!1,this.aurora.active=!1,this.flash.active=!1},_escapeHtml:function(a){return a.split("&").join("&").split("<").join("<").split(">").join(">").split('"').join(""")},_qualifyURL:function(a){var b=document.createElement("div");
+return b.innerHTML='x ',b.firstChild.href},_absoluteMediaUrls:function(b){var c=this;return a.each(b,function(a,d){d&&c.format[a]&&"data:"!==d.substr(0,5)&&(b[a]=c._qualifyURL(d))}),b},addStateClass:function(a){this.ancestorJq.length&&this.ancestorJq.addClass(this.options.stateClass[a])},removeStateClass:function(a){this.ancestorJq.length&&this.ancestorJq.removeClass(this.options.stateClass[a])},setMedia:function(b){var c=this,d=!1,e=this.status.media.poster!==b.poster;this._resetMedia(),this._resetGate(),this._resetActive(),this.androidFix.setMedia=!1,this.androidFix.play=!1,this.androidFix.pause=!1,b=this._absoluteMediaUrls(b),a.each(this.formats,function(e,f){var g="video"===c.format[f].media;return a.each(c.solutions,function(e,h){if(c[h].support[f]&&c._validString(b[f])){var i="html"===h,j="aurora"===h;return g?(i?(c.html.video.gate=!0,c._html_setVideo(b),c.html.active=!0):(c.flash.gate=!0,c._flash_setVideo(b),c.flash.active=!0),c.css.jq.videoPlay.length&&c.css.jq.videoPlay.show(),c.status.video=!0):(i?(c.html.audio.gate=!0,c._html_setAudio(b),c.html.active=!0,a.jPlayer.platform.android&&(c.androidFix.setMedia=!0)):j?(c.aurora.gate=!0,c._aurora_setAudio(b),c.aurora.active=!0):(c.flash.gate=!0,c._flash_setAudio(b),c.flash.active=!0),c.css.jq.videoPlay.length&&c.css.jq.videoPlay.hide(),c.status.video=!1),d=!0,!1}}),d?!1:void 0}),d?(this.status.nativeVideoControls&&this.html.video.gate||this._validString(b.poster)&&(e?this.htmlElement.poster.src=b.poster:this.internal.poster.jq.show()),"string"==typeof b.title&&(this.css.jq.title.length&&this.css.jq.title.html(b.title),this.htmlElement.audio&&this.htmlElement.audio.setAttribute("title",b.title),this.htmlElement.video&&this.htmlElement.video.setAttribute("title",b.title)),this.status.srcSet=!0,this.status.media=a.extend({},b),this._updateButtons(!1),this._updateInterface(),this._trigger(a.jPlayer.event.setmedia)):this._error({type:a.jPlayer.error.NO_SUPPORT,context:"{supplied:'"+this.options.supplied+"'}",message:a.jPlayer.errorMsg.NO_SUPPORT,hint:a.jPlayer.errorHint.NO_SUPPORT})},_resetMedia:function(){this._resetStatus(),this._updateButtons(!1),this._updateInterface(),this._seeked(),this.internal.poster.jq.hide(),clearTimeout(this.internal.htmlDlyCmdId),this.html.active?this._html_resetMedia():this.aurora.active?this._aurora_resetMedia():this.flash.active&&this._flash_resetMedia()},clearMedia:function(){this._resetMedia(),this.html.active?this._html_clearMedia():this.aurora.active?this._aurora_clearMedia():this.flash.active&&this._flash_clearMedia(),this._resetGate(),this._resetActive()},load:function(){this.status.srcSet?this.html.active?this._html_load():this.aurora.active?this._aurora_load():this.flash.active&&this._flash_load():this._urlNotSetError("load")},focus:function(){this.options.keyEnabled&&(a.jPlayer.focus=this)},play:function(a){var b="object"==typeof a;b&&this.options.useStateClassSkin&&!this.status.paused?this.pause(a):(a="number"==typeof a?a:0/0,this.status.srcSet?(this.focus(),this.html.active?this._html_play(a):this.aurora.active?this._aurora_play(a):this.flash.active&&this._flash_play(a)):this._urlNotSetError("play"))},videoPlay:function(){this.play()},pause:function(a){a="number"==typeof a?a:0/0,this.status.srcSet?this.html.active?this._html_pause(a):this.aurora.active?this._aurora_pause(a):this.flash.active&&this._flash_pause(a):this._urlNotSetError("pause")},tellOthers:function(b,c){var d=this,e="function"==typeof c,f=Array.prototype.slice.call(arguments);"string"==typeof b&&(e&&f.splice(1,1),a.jPlayer.prototype.destroyRemoved(),a.each(this.instances,function(){d.element!==this&&(!e||c.call(this.data("jPlayer"),d))&&this.jPlayer.apply(this,f)}))},pauseOthers:function(a){this.tellOthers("pause",function(){return this.status.srcSet},a)},stop:function(){this.status.srcSet?this.html.active?this._html_pause(0):this.aurora.active?this._aurora_pause(0):this.flash.active&&this._flash_pause(0):this._urlNotSetError("stop")},playHead:function(a){a=this._limitValue(a,0,100),this.status.srcSet?this.html.active?this._html_playHead(a):this.aurora.active?this._aurora_playHead(a):this.flash.active&&this._flash_playHead(a):this._urlNotSetError("playHead")},_muted:function(a){this.mutedWorker(a),this.options.globalVolume&&this.tellOthers("mutedWorker",function(){return this.options.globalVolume},a)},mutedWorker:function(b){this.options.muted=b,this.html.used&&this._html_setProperty("muted",b),this.aurora.used&&this._aurora_mute(b),this.flash.used&&this._flash_mute(b),this.html.video.gate||this.html.audio.gate||(this._updateMute(b),this._updateVolume(this.options.volume),this._trigger(a.jPlayer.event.volumechange))},mute:function(a){var c="object"==typeof a;c&&this.options.useStateClassSkin&&this.options.muted?this._muted(!1):(a=a===b?!0:!!a,this._muted(a))},unmute:function(a){a=a===b?!0:!!a,this._muted(!a)},_updateMute:function(a){a===b&&(a=this.options.muted),a?this.addStateClass("muted"):this.removeStateClass("muted"),this.css.jq.mute.length&&this.css.jq.unmute.length&&(this.status.noVolume?(this.css.jq.mute.hide(),this.css.jq.unmute.hide()):a?(this.css.jq.mute.hide(),this.css.jq.unmute.show()):(this.css.jq.mute.show(),this.css.jq.unmute.hide()))},volume:function(a){this.volumeWorker(a),this.options.globalVolume&&this.tellOthers("volumeWorker",function(){return this.options.globalVolume},a)},volumeWorker:function(b){b=this._limitValue(b,0,1),this.options.volume=b,this.html.used&&this._html_setProperty("volume",b),this.aurora.used&&this._aurora_volume(b),this.flash.used&&this._flash_volume(b),this.html.video.gate||this.html.audio.gate||(this._updateVolume(b),this._trigger(a.jPlayer.event.volumechange))},volumeBar:function(b){if(this.css.jq.volumeBar.length){var c=a(b.currentTarget),d=c.offset(),e=b.pageX-d.left,f=c.width(),g=c.height()-b.pageY+d.top,h=c.height();this.volume(this.options.verticalVolume?g/h:e/f)}this.options.muted&&this._muted(!1)},_updateVolume:function(a){a===b&&(a=this.options.volume),a=this.options.muted?0:a,this.status.noVolume?(this.addStateClass("noVolume"),this.css.jq.volumeBar.length&&this.css.jq.volumeBar.hide(),this.css.jq.volumeBarValue.length&&this.css.jq.volumeBarValue.hide(),this.css.jq.volumeMax.length&&this.css.jq.volumeMax.hide()):(this.removeStateClass("noVolume"),this.css.jq.volumeBar.length&&this.css.jq.volumeBar.show(),this.css.jq.volumeBarValue.length&&(this.css.jq.volumeBarValue.show(),this.css.jq.volumeBarValue[this.options.verticalVolume?"height":"width"](100*a+"%")),this.css.jq.volumeMax.length&&this.css.jq.volumeMax.show())},volumeMax:function(){this.volume(1),this.options.muted&&this._muted(!1)},_cssSelectorAncestor:function(b){var c=this;this.options.cssSelectorAncestor=b,this._removeUiClass(),this.ancestorJq=b?a(b):[],b&&1!==this.ancestorJq.length&&this._warning({type:a.jPlayer.warning.CSS_SELECTOR_COUNT,context:b,message:a.jPlayer.warningMsg.CSS_SELECTOR_COUNT+this.ancestorJq.length+" found for cssSelectorAncestor.",hint:a.jPlayer.warningHint.CSS_SELECTOR_COUNT}),this._addUiClass(),a.each(this.options.cssSelector,function(a,b){c._cssSelector(a,b)}),this._updateInterface(),this._updateButtons(),this._updateAutohide(),this._updateVolume(),this._updateMute()},_cssSelector:function(b,c){var d=this;if("string"==typeof c)if(a.jPlayer.prototype.options.cssSelector[b]){if(this.css.jq[b]&&this.css.jq[b].length&&this.css.jq[b].unbind(".jPlayer"),this.options.cssSelector[b]=c,this.css.cs[b]=this.options.cssSelectorAncestor+" "+c,this.css.jq[b]=c?a(this.css.cs[b]):[],this.css.jq[b].length&&this[b]){var e=function(c){c.preventDefault(),d[b](c),d.options.autoBlur?a(this).blur():a(this).focus()};this.css.jq[b].bind("click.jPlayer",e)}c&&1!==this.css.jq[b].length&&this._warning({type:a.jPlayer.warning.CSS_SELECTOR_COUNT,context:this.css.cs[b],message:a.jPlayer.warningMsg.CSS_SELECTOR_COUNT+this.css.jq[b].length+" found for "+b+" method.",hint:a.jPlayer.warningHint.CSS_SELECTOR_COUNT})}else this._warning({type:a.jPlayer.warning.CSS_SELECTOR_METHOD,context:b,message:a.jPlayer.warningMsg.CSS_SELECTOR_METHOD,hint:a.jPlayer.warningHint.CSS_SELECTOR_METHOD});else this._warning({type:a.jPlayer.warning.CSS_SELECTOR_STRING,context:c,message:a.jPlayer.warningMsg.CSS_SELECTOR_STRING,hint:a.jPlayer.warningHint.CSS_SELECTOR_STRING})},duration:function(a){this.options.toggleDuration&&(this.options.captureDuration&&a.stopPropagation(),this._setOption("remainingDuration",!this.options.remainingDuration))},seekBar:function(b){if(this.css.jq.seekBar.length){var c=a(b.currentTarget),d=c.offset(),e=b.pageX-d.left,f=c.width(),g=100*e/f;this.playHead(g)}},playbackRate:function(a){this._setOption("playbackRate",a)},playbackRateBar:function(b){if(this.css.jq.playbackRateBar.length){var c,d,e=a(b.currentTarget),f=e.offset(),g=b.pageX-f.left,h=e.width(),i=e.height()-b.pageY+f.top,j=e.height();c=this.options.verticalPlaybackRate?i/j:g/h,d=c*(this.options.maxPlaybackRate-this.options.minPlaybackRate)+this.options.minPlaybackRate,this.playbackRate(d)}},_updatePlaybackRate:function(){var a=this.options.playbackRate,b=(a-this.options.minPlaybackRate)/(this.options.maxPlaybackRate-this.options.minPlaybackRate);this.status.playbackRateEnabled?(this.css.jq.playbackRateBar.length&&this.css.jq.playbackRateBar.show(),this.css.jq.playbackRateBarValue.length&&(this.css.jq.playbackRateBarValue.show(),this.css.jq.playbackRateBarValue[this.options.verticalPlaybackRate?"height":"width"](100*b+"%"))):(this.css.jq.playbackRateBar.length&&this.css.jq.playbackRateBar.hide(),this.css.jq.playbackRateBarValue.length&&this.css.jq.playbackRateBarValue.hide())},repeat:function(a){var b="object"==typeof a;this._loop(b&&this.options.useStateClassSkin&&this.options.loop?!1:!0)},repeatOff:function(){this._loop(!1)},_loop:function(b){this.options.loop!==b&&(this.options.loop=b,this._updateButtons(),this._trigger(a.jPlayer.event.repeat))},option:function(c,d){var e=c;if(0===arguments.length)return a.extend(!0,{},this.options);if("string"==typeof c){var f=c.split(".");if(d===b){for(var g=a.extend(!0,{},this.options),h=0;h0||Math.floor(d)>0):e=!0,a.internal.mouse={x:b.pageX,y:b.pageY},e&&a.css.jq.gui.fadeIn(a.options.autohide.fadeIn,function(){clearTimeout(a.internal.autohideId),a.internal.autohideId=setTimeout(function(){a.css.jq.gui.fadeOut(a.options.autohide.fadeOut)},a.options.autohide.hold)})};this.css.jq.gui.length&&(this.css.jq.gui.stop(!0,!0),clearTimeout(this.internal.autohideId),delete this.internal.mouse,this.element.unbind(c),this.css.jq.gui.unbind(c),this.status.nativeVideoControls?this.css.jq.gui.hide():this.options.fullWindow&&this.options.autohide.full||!this.options.fullWindow&&this.options.autohide.restored?(this.element.bind(d,e),this.css.jq.gui.bind(d,e),this.css.jq.gui.hide()):this.css.jq.gui.show())},fullScreen:function(a){var b="object"==typeof a;b&&this.options.useStateClassSkin&&this.options.fullScreen?this._setOption("fullScreen",!1):this._setOption("fullScreen",!0)},restoreScreen:function(){this._setOption("fullScreen",!1)},_fullscreenAddEventListeners:function(){var b=this,c=a.jPlayer.nativeFeatures.fullscreen;c.api.fullscreenEnabled&&c.event.fullscreenchange&&("function"!=typeof this.internal.fullscreenchangeHandler&&(this.internal.fullscreenchangeHandler=function(){b._fullscreenchange()}),document.addEventListener(c.event.fullscreenchange,this.internal.fullscreenchangeHandler,!1))},_fullscreenRemoveEventListeners:function(){var b=a.jPlayer.nativeFeatures.fullscreen;this.internal.fullscreenchangeHandler&&document.removeEventListener(b.event.fullscreenchange,this.internal.fullscreenchangeHandler,!1)},_fullscreenchange:function(){this.options.fullScreen&&!a.jPlayer.nativeFeatures.fullscreen.api.fullscreenElement()&&this._setOption("fullScreen",!1)},_requestFullscreen:function(){var b=this.ancestorJq.length?this.ancestorJq[0]:this.element[0],c=a.jPlayer.nativeFeatures.fullscreen;c.used.webkitVideo&&(b=this.htmlElement.video),c.api.fullscreenEnabled&&c.api.requestFullscreen(b)},_exitFullscreen:function(){var b,c=a.jPlayer.nativeFeatures.fullscreen;c.used.webkitVideo&&(b=this.htmlElement.video),c.api.fullscreenEnabled&&c.api.exitFullscreen(b)},_html_initMedia:function(b){var c=a(this.htmlElement.media).empty();a.each(b.track||[],function(a,b){var d=document.createElement("track");d.setAttribute("kind",b.kind?b.kind:""),d.setAttribute("src",b.src?b.src:""),d.setAttribute("srclang",b.srclang?b.srclang:""),d.setAttribute("label",b.label?b.label:""),b.def&&d.setAttribute("default",b.def),c.append(d)}),this.htmlElement.media.src=this.status.src,"none"!==this.options.preload&&this._html_load(),this._trigger(a.jPlayer.event.timeupdate)},_html_setFormat:function(b){var c=this;a.each(this.formats,function(a,d){return c.html.support[d]&&b[d]?(c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1):void 0})},_html_setAudio:function(a){this._html_setFormat(a),this.htmlElement.media=this.htmlElement.audio,this._html_initMedia(a)},_html_setVideo:function(a){this._html_setFormat(a),this.status.nativeVideoControls&&(this.htmlElement.video.poster=this._validString(a.poster)?a.poster:""),this.htmlElement.media=this.htmlElement.video,this._html_initMedia(a)},_html_resetMedia:function(){this.htmlElement.media&&(this.htmlElement.media.id!==this.internal.video.id||this.status.nativeVideoControls||this.internal.video.jq.css({width:"0px",height:"0px"}),this.htmlElement.media.pause())},_html_clearMedia:function(){this.htmlElement.media&&(this.htmlElement.media.src="about:blank",this.htmlElement.media.load())},_html_load:function(){this.status.waitForLoad&&(this.status.waitForLoad=!1,this.htmlElement.media.load()),clearTimeout(this.internal.htmlDlyCmdId)},_html_play:function(a){var b=this,c=this.htmlElement.media;if(this.androidFix.pause=!1,this._html_load(),this.androidFix.setMedia)this.androidFix.play=!0,this.androidFix.time=a;else if(isNaN(a))c.play();else{this.internal.cmdsIgnored&&c.play();try{if(c.seekable&&!("object"==typeof c.seekable&&c.seekable.length>0))throw 1;c.currentTime=a,c.play()}catch(d){return void(this.internal.htmlDlyCmdId=setTimeout(function(){b.play(a)},250))}}this._html_checkWaitForPlay()},_html_pause:function(a){var b=this,c=this.htmlElement.media;if(this.androidFix.play=!1,a>0?this._html_load():clearTimeout(this.internal.htmlDlyCmdId),c.pause(),this.androidFix.setMedia)this.androidFix.pause=!0,this.androidFix.time=a;else if(!isNaN(a))try{if(c.seekable&&!("object"==typeof c.seekable&&c.seekable.length>0))throw 1;c.currentTime=a}catch(d){return void(this.internal.htmlDlyCmdId=setTimeout(function(){b.pause(a)},250))}a>0&&this._html_checkWaitForPlay()},_html_playHead:function(a){var b=this,c=this.htmlElement.media;this._html_load();try{if("object"==typeof c.seekable&&c.seekable.length>0)c.currentTime=a*c.seekable.end(c.seekable.length-1)/100;else{if(!(c.duration>0)||isNaN(c.duration))throw"e";c.currentTime=a*c.duration/100}}catch(d){return void(this.internal.htmlDlyCmdId=setTimeout(function(){b.playHead(a)},250))}this.status.waitForLoad||this._html_checkWaitForPlay()},_html_checkWaitForPlay:function(){this.status.waitForPlay&&(this.status.waitForPlay=!1,this.css.jq.videoPlay.length&&this.css.jq.videoPlay.hide(),this.status.video&&(this.internal.poster.jq.hide(),this.internal.video.jq.css({width:this.status.width,height:this.status.height})))},_html_setProperty:function(a,b){this.html.audio.available&&(this.htmlElement.audio[a]=b),this.html.video.available&&(this.htmlElement.video[a]=b)},_aurora_setAudio:function(b){var c=this;a.each(this.formats,function(a,d){return c.aurora.support[d]&&b[d]?(c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1):void 0}),this.aurora.player=new AV.Player.fromURL(this.status.src),this._addAuroraEventListeners(this.aurora.player,this.aurora),"auto"===this.options.preload&&(this._aurora_load(),this.status.waitForLoad=!1)},_aurora_resetMedia:function(){this.aurora.player&&this.aurora.player.stop()},_aurora_clearMedia:function(){},_aurora_load:function(){this.status.waitForLoad&&(this.status.waitForLoad=!1,this.aurora.player.preload())},_aurora_play:function(b){this.status.waitForLoad||isNaN(b)||this.aurora.player.seek(b),this.aurora.player.playing||this.aurora.player.play(),this.status.waitForLoad=!1,this._aurora_checkWaitForPlay(),this._updateButtons(!0),this._trigger(a.jPlayer.event.play)},_aurora_pause:function(b){isNaN(b)||this.aurora.player.seek(1e3*b),this.aurora.player.pause(),b>0&&this._aurora_checkWaitForPlay(),this._updateButtons(!1),this._trigger(a.jPlayer.event.pause)},_aurora_playHead:function(a){this.aurora.player.duration>0&&this.aurora.player.seek(a*this.aurora.player.duration/100),this.status.waitForLoad||this._aurora_checkWaitForPlay()},_aurora_checkWaitForPlay:function(){this.status.waitForPlay&&(this.status.waitForPlay=!1)},_aurora_volume:function(a){this.aurora.player.volume=100*a},_aurora_mute:function(a){a?(this.aurora.properties.lastvolume=this.aurora.player.volume,this.aurora.player.volume=0):this.aurora.player.volume=this.aurora.properties.lastvolume,this.aurora.properties.muted=a},_flash_setAudio:function(b){var c=this;try{a.each(this.formats,function(a,d){if(c.flash.support[d]&&b[d]){switch(d){case"m4a":case"fla":c._getMovie().fl_setAudio_m4a(b[d]);break;case"mp3":c._getMovie().fl_setAudio_mp3(b[d]);break;case"rtmpa":c._getMovie().fl_setAudio_rtmp(b[d])}return c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1}}),"auto"===this.options.preload&&(this._flash_load(),this.status.waitForLoad=!1)}catch(d){this._flashError(d)}},_flash_setVideo:function(b){var c=this;try{a.each(this.formats,function(a,d){if(c.flash.support[d]&&b[d]){switch(d){case"m4v":case"flv":c._getMovie().fl_setVideo_m4v(b[d]);break;case"rtmpv":c._getMovie().fl_setVideo_rtmp(b[d])}return c.status.src=b[d],c.status.format[d]=!0,c.status.formatType=d,!1}}),"auto"===this.options.preload&&(this._flash_load(),this.status.waitForLoad=!1)}catch(d){this._flashError(d)}},_flash_resetMedia:function(){this.internal.flash.jq.css({width:"0px",height:"0px"}),this._flash_pause(0/0)},_flash_clearMedia:function(){try{this._getMovie().fl_clearMedia()}catch(a){this._flashError(a)}},_flash_load:function(){try{this._getMovie().fl_load()}catch(a){this._flashError(a)}this.status.waitForLoad=!1},_flash_play:function(a){try{this._getMovie().fl_play(a)}catch(b){this._flashError(b)}this.status.waitForLoad=!1,this._flash_checkWaitForPlay()},_flash_pause:function(a){try{this._getMovie().fl_pause(a)}catch(b){this._flashError(b)}a>0&&(this.status.waitForLoad=!1,this._flash_checkWaitForPlay())},_flash_playHead:function(a){try{this._getMovie().fl_play_head(a)}catch(b){this._flashError(b)}this.status.waitForLoad||this._flash_checkWaitForPlay()},_flash_checkWaitForPlay:function(){this.status.waitForPlay&&(this.status.waitForPlay=!1,this.css.jq.videoPlay.length&&this.css.jq.videoPlay.hide(),this.status.video&&(this.internal.poster.jq.hide(),this.internal.flash.jq.css({width:this.status.width,height:this.status.height})))},_flash_volume:function(a){try{this._getMovie().fl_volume(a)}catch(b){this._flashError(b)}},_flash_mute:function(a){try{this._getMovie().fl_mute(a)}catch(b){this._flashError(b)}},_getMovie:function(){return document[this.internal.flash.id]},_getFlashPluginVersion:function(){var a,b=0;if(window.ActiveXObject)try{if(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")){var c=a.GetVariable("$version");c&&(c=c.split(" ")[1].split(","),b=parseInt(c[0],10)+"."+parseInt(c[1],10))}}catch(d){}else navigator.plugins&&navigator.mimeTypes.length>0&&(a=navigator.plugins["Shockwave Flash"],a&&(b=navigator.plugins["Shockwave Flash"].description.replace(/.*\s(\d+\.\d+).*/,"$1")));return 1*b},_checkForFlash:function(a){var b=!1;return this._getFlashPluginVersion()>=a&&(b=!0),b},_validString:function(a){return a&&"string"==typeof a},_limitValue:function(a,b,c){return b>a?b:a>c?c:a},_urlNotSetError:function(b){this._error({type:a.jPlayer.error.URL_NOT_SET,context:b,message:a.jPlayer.errorMsg.URL_NOT_SET,hint:a.jPlayer.errorHint.URL_NOT_SET})},_flashError:function(b){var c;c=this.internal.ready?"FLASH_DISABLED":"FLASH",this._error({type:a.jPlayer.error[c],context:this.internal.flash.swf,message:a.jPlayer.errorMsg[c]+b.message,hint:a.jPlayer.errorHint[c]}),this.internal.flash.jq.css({width:"1px",height:"1px"})},_error:function(b){this._trigger(a.jPlayer.event.error,b),this.options.errorAlerts&&this._alert("Error!"+(b.message?"\n"+b.message:"")+(b.hint?"\n"+b.hint:"")+"\nContext: "+b.context)},_warning:function(c){this._trigger(a.jPlayer.event.warning,b,c),this.options.warningAlerts&&this._alert("Warning!"+(c.message?"\n"+c.message:"")+(c.hint?"\n"+c.hint:"")+"\nContext: "+c.context)},_alert:function(a){var b="jPlayer "+this.version.script+" : id='"+this.internal.self.id+"' : "+a;this.options.consoleAlerts?window.console&&window.console.log&&window.console.log(b):alert(b)},_emulateHtmlBridge:function(){var b=this;a.each(a.jPlayer.emulateMethods.split(/\s+/g),function(a,c){b.internal.domNode[c]=function(a){b[c](a)}}),a.each(a.jPlayer.event,function(c,d){var e=!0;a.each(a.jPlayer.reservedEvent.split(/\s+/g),function(a,b){return b===c?(e=!1,!1):void 0}),e&&b.element.bind(d+".jPlayer.jPlayerHtml",function(){b._emulateHtmlUpdate();var a=document.createEvent("Event");a.initEvent(c,!1,!0),b.internal.domNode.dispatchEvent(a)})})},_emulateHtmlUpdate:function(){var b=this;a.each(a.jPlayer.emulateStatus.split(/\s+/g),function(a,c){b.internal.domNode[c]=b.status[c]}),a.each(a.jPlayer.emulateOptions.split(/\s+/g),function(a,c){b.internal.domNode[c]=b.options[c]})},_destroyHtmlBridge:function(){var b=this;this.element.unbind(".jPlayerHtml");var c=a.jPlayer.emulateMethods+" "+a.jPlayer.emulateStatus+" "+a.jPlayer.emulateOptions;a.each(c.split(/\s+/g),function(a,c){delete b.internal.domNode[c]})}},a.jPlayer.error={FLASH:"e_flash",FLASH_DISABLED:"e_flash_disabled",NO_SOLUTION:"e_no_solution",NO_SUPPORT:"e_no_support",URL:"e_url",URL_NOT_SET:"e_url_not_set",VERSION:"e_version"},a.jPlayer.errorMsg={FLASH:"jPlayer's Flash fallback is not configured correctly, or a command was issued before the jPlayer Ready event. Details: ",FLASH_DISABLED:"jPlayer's Flash fallback has been disabled by the browser due to the CSS rules you have used. Details: ",NO_SOLUTION:"No solution can be found by jPlayer in this browser. Neither HTML nor Flash can be used.",NO_SUPPORT:"It is not possible to play any media format provided in setMedia() on this browser using your current options.",URL:"Media URL could not be loaded.",URL_NOT_SET:"Attempt to issue media playback commands, while no media url is set.",VERSION:"jPlayer "+a.jPlayer.prototype.version.script+" needs Jplayer.swf version "+a.jPlayer.prototype.version.needFlash+" but found "},a.jPlayer.errorHint={FLASH:"Check your swfPath option and that Jplayer.swf is there.",FLASH_DISABLED:"Check that you have not display:none; the jPlayer entity or any ancestor.",NO_SOLUTION:"Review the jPlayer options: support and supplied.",NO_SUPPORT:"Video or audio formats defined in the supplied option are missing.",URL:"Check media URL is valid.",URL_NOT_SET:"Use setMedia() to set the media URL.",VERSION:"Update jPlayer files."},a.jPlayer.warning={CSS_SELECTOR_COUNT:"e_css_selector_count",CSS_SELECTOR_METHOD:"e_css_selector_method",CSS_SELECTOR_STRING:"e_css_selector_string",OPTION_KEY:"e_option_key"},a.jPlayer.warningMsg={CSS_SELECTOR_COUNT:"The number of css selectors found did not equal one: ",CSS_SELECTOR_METHOD:"The methodName given in jPlayer('cssSelector') is not a valid jPlayer method.",CSS_SELECTOR_STRING:"The methodCssSelector given in jPlayer('cssSelector') is not a String or is empty.",OPTION_KEY:"The option requested in jPlayer('option') is undefined."},a.jPlayer.warningHint={CSS_SELECTOR_COUNT:"Check your css selector and the ancestor.",CSS_SELECTOR_METHOD:"Check your method name.",CSS_SELECTOR_STRING:"Check your css selector is a string.",OPTION_KEY:"Check your option name."}});
\ No newline at end of file
diff --git a/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.transform.js b/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.transform.js
new file mode 100644
index 0000000..4683de8
--- /dev/null
+++ b/src/main/resources/static/staticResources/vendor/jplayercircle/js/jquery.transform.js
@@ -0,0 +1,532 @@
+/*
+ * transform: A jQuery cssHooks adding cross-browser 2d transform capabilities to $.fn.css() and $.fn.animate()
+ *
+ * limitations:
+ * - requires jQuery 1.4.3+
+ * - Should you use the *translate* property, then your elements need to be absolutely positionned in a relatively positionned wrapper **or it will fail in IE678**.
+ * - transformOrigin is not accessible
+ *
+ * latest version and complete README available on Github:
+ * https://github.com/louisremi/jquery.transform.js
+ *
+ * Copyright 2011 @louis_remi
+ * Licensed under the MIT license.
+ *
+ * This saved you an hour of work?
+ * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON
+ *
+ */
+(function ($) {
+
+ /*
+ * Feature tests and global variables
+ */
+ var div = document.createElement('div'),
+ divStyle = div.style,
+ propertyName = 'transform',
+ suffix = 'Transform',
+ testProperties = [
+ 'O' + suffix,
+ 'ms' + suffix,
+ 'Webkit' + suffix,
+ 'Moz' + suffix,
+ // prefix-less property
+ propertyName
+ ],
+ i = testProperties.length,
+ supportProperty,
+ supportMatrixFilter,
+ propertyHook,
+ propertyGet,
+ rMatrix = /Matrix([^)]*)/;
+
+// test different vendor prefixes of this property
+ while (i--) {
+ if (testProperties[i] in divStyle) {
+ $.support[propertyName] = supportProperty = testProperties[i];
+
+ }
+ }
+// IE678 alternative
+ if (!supportProperty) {
+ $.support.matrixFilter = supportMatrixFilter = divStyle.filter === '';
+ }
+// prevent IE memory leak
+ div = divStyle = null;
+
+// px isn't the default unit of this property
+ $.cssNumber[propertyName] = true;
+
+ /*
+ * fn.css() hooks
+ */
+ if (supportProperty && supportProperty != propertyName) {
+ // Modern browsers can use jQuery.cssProps as a basic hook
+ $.cssProps[propertyName] = supportProperty;
+
+ // Firefox needs a complete hook because it stuffs matrix with 'px'
+ if (supportProperty == 'Moz' + suffix) {
+ propertyHook = {
+ get: function (elem, computed) {
+ return (computed ?
+ // remove 'px' from the computed matrix
+ $.css(elem, supportProperty).split('px').join('') :
+ elem.style[supportProperty]
+ )
+ },
+ set: function (elem, value) {
+ // remove 'px' from matrices
+ elem.style[supportProperty] = /matrix[^)p]*\)/.test(value) ?
+ value.replace(/matrix((?:[^,]*,){4})([^,]*),([^)]*)/, 'matrix$1$2px,$3px') :
+ value;
+ }
+ }
+ /* Fix two jQuery bugs still present in 1.5.1
+ * - rupper is incompatible with IE9, see http://jqbug.com/8346
+ * - jQuery.css is not really jQuery.cssProps aware, see http://jqbug.com/8402
+ */
+ } else if (/^1\.[0-5](?:\.|$)/.test($.fn.jquery)) {
+ propertyHook = {
+ get: function (elem, computed) {
+ return (computed ?
+ $.css(elem, supportProperty.replace(/^ms/, 'Ms')) :
+ elem.style[supportProperty]
+ )
+ }
+ }
+ }
+ /* TODO: leverage hardware acceleration of 3d transform in Webkit only
+ else if ( supportProperty == 'Webkit' + suffix && support3dTransform ) {
+ propertyHook = {
+ set: function( elem, value ) {
+ elem.style[supportProperty] =
+ value.replace();
+ }
+ }
+ }*/
+
+ } else if (supportMatrixFilter) {
+ propertyHook = {
+ get: function (elem, computed) {
+ var elemStyle = (computed && elem.currentStyle ? elem.currentStyle : elem.style),
+ matrix;
+
+ if (elemStyle && rMatrix.test(elemStyle.filter)) {
+ matrix = RegExp.$1.split(',');
+ matrix = [
+ matrix[0].split('=')[1],
+ matrix[2].split('=')[1],
+ matrix[1].split('=')[1],
+ matrix[3].split('=')[1]
+ ];
+ } else {
+ matrix = [1, 0, 0, 1];
+ }
+ matrix[4] = elemStyle ? elemStyle.left : 0;
+ matrix[5] = elemStyle ? elemStyle.top : 0;
+ return "matrix(" + matrix + ")";
+ },
+ set: function (elem, value, animate) {
+ var elemStyle = elem.style,
+ currentStyle,
+ Matrix,
+ filter;
+
+ if (!animate) {
+ elemStyle.zoom = 1;
+ }
+
+ value = matrix(value);
+
+ // rotate, scale and skew
+ if (!animate || animate.M) {
+ Matrix = [
+ "Matrix(" +
+ "M11=" + value[0],
+ "M12=" + value[2],
+ "M21=" + value[1],
+ "M22=" + value[3],
+ "SizingMethod='auto expand'"
+ ].join();
+ filter = (currentStyle = elem.currentStyle) && currentStyle.filter || elemStyle.filter || "";
+
+ elemStyle.filter = rMatrix.test(filter) ?
+ filter.replace(rMatrix, Matrix) :
+ filter + " progid:DXImageTransform.Microsoft." + Matrix + ")";
+
+ // center the transform origin, from pbakaus's Transformie http://github.com/pbakaus/transformie
+ if ((centerOrigin = $.transform.centerOrigin)) {
+ elemStyle[centerOrigin == 'margin' ? 'marginLeft' : 'left'] = -(elem.offsetWidth / 2) + (elem.clientWidth / 2) + 'px';
+ elemStyle[centerOrigin == 'margin' ? 'marginTop' : 'top'] = -(elem.offsetHeight / 2) + (elem.clientHeight / 2) + 'px';
+ }
+ }
+
+ // translate
+ if (!animate || animate.T) {
+ // We assume that the elements are absolute positionned inside a relative positionned wrapper
+ elemStyle.left = value[4] + 'px';
+ elemStyle.top = value[5] + 'px';
+ }
+ }
+ }
+ }
+// populate jQuery.cssHooks with the appropriate hook if necessary
+ if (propertyHook) {
+ $.cssHooks[propertyName] = propertyHook;
+ }
+// we need a unique setter for the animation logic
+ propertyGet = propertyHook && propertyHook.get || $.css;
+
+ /*
+ * fn.animate() hooks
+ */
+ $.fx.step.transform = function (fx) {
+ var elem = fx.elem,
+ start = fx.start,
+ end = fx.end,
+ split,
+ pos = fx.pos,
+ transform,
+ translate,
+ rotate,
+ scale,
+ skew,
+ T = false,
+ M = false,
+ prop;
+ translate = rotate = scale = skew = '';
+
+ // fx.end and fx.start need to be converted to their translate/rotate/scale/skew components
+ // so that we can interpolate them
+ if (!start || typeof start === "string") {
+ // the following block can be commented out with jQuery 1.5.1+, see #7912
+ if (!start) {
+ start = propertyGet(elem, supportProperty);
+ }
+
+ // force layout only once per animation
+ if (supportMatrixFilter) {
+ elem.style.zoom = 1;
+ }
+
+ // if the start computed matrix is in end, we are doing a relative animation
+ split = end.split(start);
+ if (split.length == 2) {
+ // remove the start computed matrix to make animations more accurate
+ end = split.join('');
+ fx.origin = start;
+ start = 'none';
+ }
+
+ // start is either 'none' or a matrix(...) that has to be parsed
+ fx.start = start = start == 'none' ?
+ {
+ translate: [0, 0],
+ rotate: 0,
+ scale: [1, 1],
+ skew: [0, 0]
+ } :
+ unmatrix(toArray(start));
+
+ // fx.end has to be parsed and decomposed
+ fx.end = end = ~end.indexOf('matrix') ?
+ // bullet-proof parser
+ unmatrix(matrix(end)) :
+ // faster and more precise parser
+ components(end);
+
+ // get rid of properties that do not change
+ for (prop in start) {
+ if (prop == 'rotate' ?
+ start[prop] == end[prop] :
+ start[prop][0] == end[prop][0] && start[prop][1] == end[prop][1]
+ ) {
+ delete start[prop];
+ }
+ }
+ }
+
+ /*
+ * We want a fast interpolation algorithm.
+ * This implies avoiding function calls and sacrifying DRY principle:
+ * - avoid $.each(function(){})
+ * - round values using bitewise hacks, see http://jsperf.com/math-round-vs-hack/3
+ */
+ if (start.translate) {
+ // round translate to the closest pixel
+ translate = ' translate(' +
+ ((start.translate[0] + (end.translate[0] - start.translate[0]) * pos + .5) | 0) + 'px,' +
+ ((start.translate[1] + (end.translate[1] - start.translate[1]) * pos + .5) | 0) + 'px' +
+ ')';
+ T = true;
+ }
+ if (start.rotate != undefined) {
+ rotate = ' rotate(' + (start.rotate + (end.rotate - start.rotate) * pos) + 'rad)';
+ M = true;
+ }
+ if (start.scale) {
+ scale = ' scale(' +
+ (start.scale[0] + (end.scale[0] - start.scale[0]) * pos) + ',' +
+ (start.scale[1] + (end.scale[1] - start.scale[1]) * pos) +
+ ')';
+ M = true;
+ }
+ if (start.skew) {
+ skew = ' skew(' +
+ (start.skew[0] + (end.skew[0] - start.skew[0]) * pos) + 'rad,' +
+ (start.skew[1] + (end.skew[1] - start.skew[1]) * pos) + 'rad' +
+ ')';
+ M = true;
+ }
+
+ // In case of relative animation, restore the origin computed matrix here.
+ transform = fx.origin ?
+ fx.origin + translate + skew + scale + rotate :
+ translate + rotate + scale + skew;
+
+ propertyHook && propertyHook.set ?
+ propertyHook.set(elem, transform, {M: M, T: T}) :
+ elem.style[supportProperty] = transform;
+ };
+
+ /*
+ * Utility functions
+ */
+
+// turns a transform string into its 'matrix(A,B,C,D,X,Y)' form (as an array, though)
+ function matrix(transform) {
+ transform = transform.split(')');
+ var
+ trim = $.trim
+ // last element of the array is an empty string, get rid of it
+ , i = transform.length - 1
+ , split, prop, val
+ , A = 1
+ , B = 0
+ , C = 0
+ , D = 1
+ , A_, B_, C_, D_
+ , tmp1, tmp2
+ , X = 0
+ , Y = 0
+ ;
+ // Loop through the transform properties, parse and multiply them
+ while (i--) {
+ split = transform[i].split('(');
+ prop = trim(split[0]);
+ val = split[1];
+ A_ = B_ = C_ = D_ = 0;
+
+ switch (prop) {
+ case 'translateX':
+ X += parseInt(val, 10);
+ continue;
+
+ case 'translateY':
+ Y += parseInt(val, 10);
+ continue;
+
+ case 'translate':
+ val = val.split(',');
+ X += parseInt(val[0], 10);
+ Y += parseInt(val[1] || 0, 10);
+ continue;
+
+ case 'rotate':
+ val = toRadian(val);
+ A_ = Math.cos(val);
+ B_ = Math.sin(val);
+ C_ = -Math.sin(val);
+ D_ = Math.cos(val);
+ break;
+
+ case 'scaleX':
+ A_ = val;
+ D_ = 1;
+ break;
+
+ case 'scaleY':
+ A_ = 1;
+ D_ = val;
+ break;
+
+ case 'scale':
+ val = val.split(',');
+ A_ = val[0];
+ D_ = val.length > 1 ? val[1] : val[0];
+ break;
+
+ case 'skewX':
+ A_ = D_ = 1;
+ C_ = Math.tan(toRadian(val));
+ break;
+
+ case 'skewY':
+ A_ = D_ = 1;
+ B_ = Math.tan(toRadian(val));
+ break;
+
+ case 'skew':
+ A_ = D_ = 1;
+ val = val.split(',');
+ C_ = Math.tan(toRadian(val[0]));
+ B_ = Math.tan(toRadian(val[1] || 0));
+ break;
+
+ case 'matrix':
+ val = val.split(',');
+ A_ = +val[0];
+ B_ = +val[1];
+ C_ = +val[2];
+ D_ = +val[3];
+ X += parseInt(val[4], 10);
+ Y += parseInt(val[5], 10);
+ }
+ // Matrix product
+ tmp1 = A * A_ + B * C_;
+ B = A * B_ + B * D_;
+ tmp2 = C * A_ + D * C_;
+ D = C * B_ + D * D_;
+ A = tmp1;
+ C = tmp2;
+ }
+ return [A, B, C, D, X, Y];
+ }
+
+// turns a matrix into its rotate, scale and skew components
+// algorithm from http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp
+ function unmatrix(matrix) {
+ var
+ scaleX
+ , scaleY
+ , skew
+ , A = matrix[0]
+ , B = matrix[1]
+ , C = matrix[2]
+ , D = matrix[3]
+ ;
+
+ // Make sure matrix is not singular
+ if (A * D - B * C) {
+ // step (3)
+ scaleX = Math.sqrt(A * A + B * B);
+ A /= scaleX;
+ B /= scaleX;
+ // step (4)
+ skew = A * C + B * D;
+ C -= A * skew;
+ D -= B * skew;
+ // step (5)
+ scaleY = Math.sqrt(C * C + D * D);
+ C /= scaleY;
+ D /= scaleY;
+ skew /= scaleY;
+ // step (6)
+ if (A * D < B * C) {
+ //scaleY = -scaleY;
+ //skew = -skew;
+ A = -A;
+ B = -B;
+ skew = -skew;
+ scaleX = -scaleX;
+ }
+
+ // matrix is singular and cannot be interpolated
+ } else {
+ rotate = scaleX = scaleY = skew = 0;
+ }
+
+ return {
+ translate: [+matrix[4], +matrix[5]],
+ rotate: Math.atan2(B, A),
+ scale: [scaleX, scaleY],
+ skew: [skew, 0]
+ }
+ }
+
+// parse tranform components of a transform string not containing 'matrix(...)'
+ function components(transform) {
+ // split the != transforms
+ transform = transform.split(')');
+
+ var translate = [0, 0],
+ rotate = 0,
+ scale = [1, 1],
+ skew = [0, 0],
+ i = transform.length - 1,
+ trim = $.trim,
+ split, name, value;
+
+ // add components
+ while (i--) {
+ split = transform[i].split('(');
+ name = trim(split[0]);
+ value = split[1];
+
+ if (name == 'translateX') {
+ translate[0] += parseInt(value, 10);
+
+ } else if (name == 'translateY') {
+ translate[1] += parseInt(value, 10);
+
+ } else if (name == 'translate') {
+ value = value.split(',');
+ translate[0] += parseInt(value[0], 10);
+ translate[1] += parseInt(value[1] || 0, 10);
+
+ } else if (name == 'rotate') {
+ rotate += toRadian(value);
+
+ } else if (name == 'scaleX') {
+ scale[0] *= value;
+
+ } else if (name == 'scaleY') {
+ scale[1] *= value;
+
+ } else if (name == 'scale') {
+ value = value.split(',');
+ scale[0] *= value[0];
+ scale[1] *= (value.length > 1 ? value[1] : value[0]);
+
+ } else if (name == 'skewX') {
+ skew[0] += toRadian(value);
+
+ } else if (name == 'skewY') {
+ skew[1] += toRadian(value);
+
+ } else if (name == 'skew') {
+ value = value.split(',');
+ skew[0] += toRadian(value[0]);
+ skew[1] += toRadian(value[1] || '0');
+ }
+ }
+
+ return {
+ translate: translate,
+ rotate: rotate,
+ scale: scale,
+ skew: skew
+ };
+ }
+
+// converts an angle string in any unit to a radian Float
+ function toRadian(value) {
+ return ~value.indexOf('deg') ?
+ parseInt(value, 10) * (Math.PI * 2 / 360) :
+ ~value.indexOf('grad') ?
+ parseInt(value, 10) * (Math.PI / 200) :
+ parseFloat(value);
+ }
+
+// Converts 'matrix(A,B,C,D,X,Y)' to [A,B,C,D,X,Y]
+ function toArray(matrix) {
+ // Fremove the unit of X and Y for Firefox
+ matrix = /\(([^,]*),([^,]*),([^,]*),([^,]*),([^,p]*)(?:px)?,([^)p]*)(?:px)?/.exec(matrix);
+ return [matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6]];
+ }
+
+ $.transform = {
+ centerOrigin: 'margin'
+ };
+
+})(jQuery);
diff --git a/src/main/webapp/resources/vendor/jplayercircle/js/mod.csstransforms.min.js b/src/main/resources/static/staticResources/vendor/jplayercircle/js/mod.csstransforms.min.js
similarity index 100%
rename from src/main/webapp/resources/vendor/jplayercircle/js/mod.csstransforms.min.js
rename to src/main/resources/static/staticResources/vendor/jplayercircle/js/mod.csstransforms.min.js
diff --git a/src/main/resources/static/staticResources/vendor/jquery-1.12.4.min.js b/src/main/resources/static/staticResources/vendor/jquery-1.12.4.min.js
new file mode 100644
index 0000000..e836475
--- /dev/null
+++ b/src/main/resources/static/staticResources/vendor/jquery-1.12.4.min.js
@@ -0,0 +1,5 @@
+/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML=" ",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML=" ","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML=" ",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0;
+}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" a ",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""," "],legend:[1,""," "],area:[1,""," "],param:[1,""," "],thead:[1,""],tr:[2,""],col:[2,""],td:[3,""],_default:l.htmlSerialize?[0,"",""]:[1,"X","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h ]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/
-
-
-
-
-
+
-
+
-
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has
+ been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type
+ and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap
+ into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the
+ release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
+ software like Aldus PageMaker including versions of Lorem Ipsum.
+
-
+
-
-
-
-
+
+
+
+