Merge remote-tracking branch 'alfresco-data-model/support/HF/8.25.11.N' into release/6.1.1

This commit is contained in:
Chris Shields
2020-07-21 10:45:18 +01:00
484 changed files with 147813 additions and 0 deletions

8
data-model/.gitattributes vendored Normal file
View File

@@ -0,0 +1,8 @@
.* eol=crlf
*.html eol=crlf
*.java eol=crlf
*.txt eol=crlf
*.css eol=crlf
*.xml eol=crlf
*.js eol=crlf
*.properties eol=crlf

4
data-model/.gitbugtraq Normal file
View File

@@ -0,0 +1,4 @@
# For SmartGit
[bugtraq "jira"]
url = https://issues.alfresco.com/jira/browse/%BUGID%
logRegex = ([A-Z]+-\\d+)

37
data-model/.gitignore vendored Normal file
View File

@@ -0,0 +1,37 @@
*.class
# Eclipse
.classpath
.settings
.project
# Intellij
.idea/
*.iml
*.iws
# Vscode
.vscode/
# Mac
.DS_Store
# Maven
target
*.log
*.log.*
# Mobile Tools for Java (J2ME)
.mtj
.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

View File

@@ -0,0 +1,10 @@
<settings>
<!-- required to push artifacts to repositories -->
<servers>
<server>
<id>alfresco-public</id>
<username>${env.MAVEN_USERNAME}</username>
<password>${env.MAVEN_PASSWORD}</password>
</server>
</servers>
</settings>

46
data-model/.travis.yml Normal file
View File

@@ -0,0 +1,46 @@
dist: trusty
sudo: required
language: java
jdk:
- openjdk11
cache:
directories:
- $HOME/.m2
branches:
only:
- master
- /support\/.*/
install: travis_retry mvn install -DskipTests=true -B -V
stages:
- test
- release
jobs:
include:
- stage: test
name: "Build and test"
script: travis_retry mvn test
- name: "WhiteSource scan"
# only on SP branches or master and if it is not a PR
if: fork = false AND (branch = master OR branch =~ /support\/SP\/.*/) AND type != pull_request
script:
# Download the latest version of WhiteSource Unified Agent
- curl -LJO https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/wss-unified-agent.jar
# Run WhiteSource Unified Agent
- java -jar wss-unified-agent.jar -apiKey ${WHITESOURCE_API_KEY} -c .wss-unified-agent.config
- stage: release
name: "Push to Nexus"
if: fork = false AND (branch = master OR branch =~ /support\/.*/) AND type != pull_request AND commit_message !~ /\[no-release\]/
before_install:
- "cp .travis.settings.xml $HOME/.m2/settings.xml"
script:
# Use full history for release
- git checkout -B "${TRAVIS_BRANCH}"
# Add email to link commits to user
- git config user.email "${GIT_EMAIL}"
# Skip building of release commits
- mvn --batch-mode -q -DscmCommentPrefix="[maven-release-plugin][skip ci] " -Dusername="${GIT_USERNAME}" -Dpassword="${GIT_PASSWORD}" -DskipTests -Darguments=-DskipTests release:clean release:prepare release:perform

View File

@@ -0,0 +1,228 @@
####################################################################
# WhiteSource Unified-Agent configuration file
####################################################################
##########################################
# GENERAL SCAN MODE: Files and Package Managers
##########################################
checkPolicies=true
forceCheckAllDependencies=true
forceUpdate=true
forceUpdate.failBuildOnPolicyViolation=true
offline=false
#ignoreSourceFiles=true
#scanComment=
#updateInventory=false
#resolveAllDependencies=false
#failErrorLevel=ALL
#requireKnownSha1=false
#generateScanReport=true
#scanReportTimeoutMinutes=10
#excludeDependenciesFromNodes=.*commons-io.*,.*maven-model
#projectPerFolder=true
#projectPerFolderIncludes=
#projectPerFolderExcludes=
#wss.connectionTimeoutMinutes=60
# Change the below URL to your WhiteSource server.
# Use the 'WhiteSource Server URL' which can be retrieved
# from your 'Profile' page on the 'Server URLs' panel.
# Then, add the '/agent' path to it.
wss.url=https://saas.whitesourcesoftware.com/agent
#npm.resolveDependencies=false
#npm.ignoreSourceFiles=false
#npm.includeDevDependencies=true
#npm.runPreStep=true
#npm.ignoreNpmLsErrors=true
#npm.ignoreScripts=true
#npm.yarnProject=true
#npm.accessToken=
#npm.identifyByNameAndVersion=true
#bower.resolveDependencies=false
#bower.ignoreSourceFiles=true
#bower.runPreStep=true
#nuget.resolvePackagesConfigFiles=false
#nuget.resolveCsProjFiles=false
#nuget.resolveDependencies=false
#nuget.restoreDependencies=true
#nuget.ignoreSourceFiles=true
#nuget.runPreStep=true
#nuget.resolveNuspecFiles=false
#python.resolveDependencies=false
#python.ignoreSourceFiles=false
#python.ignorePipInstallErrors=true
#python.installVirtualenv=true
#python.resolveHierarchyTree=false
#python.requirementsFileIncludes=requirements.txt
#python.resolveSetupPyFiles=true
#python.runPipenvPreStep=true
#python.pipenvDevDependencies=true
#python.IgnorePipenvInstallErrors=true
#maven.ignoredScopes=test provided
maven.resolveDependencies=true
#maven.ignoreSourceFiles=true
#maven.aggregateModules=true
maven.ignorePomModules=false
#maven.runPreStep=true
#maven.ignoreMvnTreeErrors=true
#maven.environmentPath=
#maven.m2RepositoryPath=
#gradle.ignoredScopes=
#gradle.resolveDependencies=false
#gradle.runAssembleCommand=false
#gradle.runPreStep=true
#gradle.ignoreSourceFiles=true
#gradle.aggregateModules=true
#gradle.preferredEnvironment=wrapper
#gradle.localRepositoryPath=
#paket.resolveDependencies=false
#paket.ignoredGroups=
#paket.ignoreSourceFiles=false
#paket.runPreStep=true
#paket.exePath=
#go.resolveDependencies=false
#go.collectDependenciesAtRuntime=true
#go.dependencyManager=
#go.ignoreSourceFiles=true
#go.glide.ignoreTestPackages=false
#go.gogradle.enableTaskAlias=true
#ruby.resolveDependencies = false
#ruby.ignoreSourceFiles = false
#ruby.installMissingGems = true
#ruby.runBundleInstall = true
#ruby.overwriteGemFile = true
#sbt.resolveDependencies=false
#sbt.ignoreSourceFiles=true
#sbt.aggregateModules=true
#sbt.runPreStep=true
#sbt.targetFolder=
#php.resolveDependencies=false
#php.runPreStep=true
#php.includeDevDependencies=true
#html.resolveDependencies=false
#cocoapods.resolveDependencies=false
#cocoapods.runPreStep=true
#cocoapods.ignoreSourceFiles=false
#hex.resolveDependencies=false
#hex.runPreStep=true
#hex.ignoreSourceFiles=false
#hex.aggregateModules=true
##################################
# Organization tokens:
##################################
apiKey=
#userKey is required if WhiteSource administrator has enabled "Enforce user level access" option
#userKey=
projectName=alfresco-data-model
projectVersion=8.25.N
projectToken=
productName=ACS Community
productVersion=
productToken=
#updateType=APPEND
#requesterEmail=user@provider.com
#########################################################################################
# Includes/Excludes Glob patterns - PLEASE USE ONLY ONE EXCLUDE LINE AND ONE INCLUDE LINE
#########################################################################################
#includes=**/*.c **/*.cc **/*.cp **/*.cpp **/*.cxx **/*.c++ **/*.h **/*.hpp **/*.hxx
#includes=**/*.m **/*.mm **/*.js **/*.php
includes=**/*.jar
#includes=**/*.gem **/*.rb
#includes=**/*.dll **/*.cs **/*.nupkg
#includes=**/*.tgz **/*.deb **/*.gzip **/*.rpm **/*.tar.bz2
#includes=**/*.zip **/*.tar.gz **/*.egg **/*.whl **/*.py
## Exclude file extensions or specific directories by adding **/*.<extension> or **<excluded_dir>/**
excludes=**/*sources.jar **/*javadoc.jar
case.sensitive.glob=false
followSymbolicLinks=true
##################################
# Archive properties
##################################
#archiveExtractionDepth=2
#archiveIncludes=**/*.war **/*.ear
#archiveExcludes=**/*sources.jar
##################################
# Proxy settings
##################################
#proxy.host=
#proxy.port=
#proxy.user=
#proxy.pass=
##################################
# SCM settings
##################################
#scm.type=
#scm.user=
#scm.pass=
#scm.ppk=
#scm.url=
#scm.branch=
#scm.tag=
#scm.npmInstall=
#scm.npmInstallTimeoutMinutes=
#scm.repositoriesFile=
##############################################
# SCAN MODE: Linux package manager settings
##############################################
#scanPackageManager=true
##################################
# SCAN MODE: Docker images
##################################
#docker.scanImages=true
#docker.includes=.*.*
#docker.excludes=
#docker.pull.enable=true
#docker.pull.images=.*.*
#docker.pull.maxImages=10
#docker.pull.tags=.*.*
#docker.pull.digest=
#docker.delete.force=true
#docker.login.sudo=false
#docker.aws.enable=true
#docker.aws.registryIds=
##################################
# SCAN MODE: Docker containers
##################################
#docker.scanContainers=true
#docker.containerIncludes=.*.*
#docker.containerExcludes=
################################
# Serverless settings
################################
#serverless.provider=
#serverless.scanFunctions=true
#serverless.includes=
#serverless.excludes=
#serverless.region=
#serverless.maxFunctions=10

View File

@@ -0,0 +1,16 @@
### Contributing
Thanks for your interest in contributing to this project!
The following is a set of guidelines for contributing to this library. Most of them will make the life of the reviewer easier and therefore decrease the time required for the patch be included in the next version.
Because this project forms a part of Alfresco Content Services, the guidelines are hosted in the [Alfresco Social Community](http://community.alfresco.com/community/ecm) where they can be referenced from multiple projects.
Read an [overview on how this project is goverened](https://community.alfresco.com/docs/DOC-6385-project-overview-repository).
You can report an issue in the ALF project of the [Alfresco issue tracker](http://issues.alfresco.com).
Read [instructions for a good issue report](https://community.alfresco.com/docs/DOC-6263-reporting-an-issue).
Read [instructions for making a contribution](https://community.alfresco.com/docs/DOC-6269-submitting-contributions).
Please follow [the coding standards](https://community.alfresco.com/docs/DOC-4658-coding-standards).

165
data-model/LICENSE.txt Normal file
View File

@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

47
data-model/README.md Normal file
View File

@@ -0,0 +1,47 @@
### Alfresco Data Model
[![Build Status](https://travis-ci.com/Alfresco/alfresco-data-model.svg?branch=master)](https://travis-ci.com/Alfresco/alfresco-data-model)
Data model is a library packaged as a jar file which is part of [Alfresco Content Services Repository](https://community.alfresco.com/docs/DOC-6385-project-overview-repository).
The library contains the following:
* Dictionary, Repository and Search Services interfaces
* Models for data types and Dictionary implementation
* Parsers
Please note that the data model uses version 2 of the Jackson libraries.
The upgrade from version 1 was not backward compatible, any projects
that are dependent on data model using Jackson 1.x should use the data-model 6.N branch.
Version 8.0 of data-model depends on alfresco-core 7.0 which is based on Spring 5.
### Building and testing
The project can be built and tested by running Maven command:
~~~
mvn clean install
~~~
### Artifacts
The artifacts can be obtained by:
* downloading from [Alfresco repository](https://artifacts.alfresco.com/nexus/content/groups/public)
* getting as Maven dependency by adding the dependency to your pom file:
~~~
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-data-model</artifactId>
<version>version</version>
</dependency>
~~~
and Alfresco repository:
~~~
<repository>
<id>alfresco-maven-repo</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</repository>
~~~
The SNAPSHOT version of the artifact is **never** published.
### Old version history
The history for older versions can be found in [Alfresco SVN](https://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/projects/data-model)
### Contributing guide
Please use [this guide](CONTRIBUTING.md) to make a contribution to the project.

View File

@@ -0,0 +1,6 @@
# Branch specific configuration file for localisation scripts
MESSAGE_SEARCH_PATH="src/main/resources/alfresco/messages/dictionary-model*.properties"
EXCLUDED_FILES="src/main/resources/alfresco/messages/dictionary-messages.properties src/main/resources/alfresco/model/dataTypeAnalyzers.properties src/main/resources/alfresco/model/dataTypeAnalyzers_cs.properties src/main/resources/alfresco/model/dataTypeAnalyzers_da.properties src/main/resources/alfresco/model/dataTypeAnalyzers_de.properties src/main/resources/alfresco/model/dataTypeAnalyzers_el.properties src/main/resources/alfresco/model/dataTypeAnalyzers_en.properties src/main/resources/alfresco/model/dataTypeAnalyzers_es.properties src/main/resources/alfresco/model/dataTypeAnalyzers_fi.properties src/main/resources/alfresco/model/dataTypeAnalyzers_fr.properties src/main/resources/alfresco/model/dataTypeAnalyzers_it.properties src/main/resources/alfresco/model/dataTypeAnalyzers_ja.properties src/main/resources/alfresco/model/dataTypeAnalyzers_ko.properties src/main/resources/alfresco/model/dataTypeAnalyzers_nl.properties src/main/resources/alfresco/model/dataTypeAnalyzers_no.properties src/main/resources/alfresco/model/dataTypeAnalyzers_pt.properties src/main/resources/alfresco/model/dataTypeAnalyzers_pt_BR.properties src/main/resources/alfresco/model/dataTypeAnalyzers_ru.properties src/main/resources/alfresco/model/dataTypeAnalyzers_sv.properties src/main/resources/alfresco/model/dataTypeAnalyzers_th.properties src/main/resources/alfresco/model/dataTypeAnalyzers_zh.properties"

361
data-model/pom.xml Normal file
View File

@@ -0,0 +1,361 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-super-pom</artifactId>
<version>10</version>
</parent>
<artifactId>alfresco-data-model</artifactId>
<name>Alfresco Data Model</name>
<description>Alfresco Data Model classes</description>
<version>8.25.11.1-SNAPSHOT</version>
<scm>
<connection>scm:git:https://github.com/Alfresco/alfresco-data-model.git</connection>
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-data-model.git</developerConnection>
<url>https://github.com/Alfresco/alfresco-data-model</url>
<tag>HEAD</tag>
</scm>
<distributionManagement>
<repository>
<id>alfresco-public</id>
<url>https://artifacts.alfresco.com/nexus/content/repositories/releases</url>
</repository>
</distributionManagement>
<properties>
<dependency.alfresco-core.version>7.5.7.0</dependency.alfresco-core.version>
<dependency.cxf.version>3.3.2</dependency.cxf.version>
<!-- Files to exclude from SonarQube aalysis -->
<sonar.exclusions>
source/java/org/alfresco/repo/search/impl/parsers/CMIS*er.java,
source/java/org/alfresco/repo/search/impl/parsers/FTSParser.java,
source/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java
</sonar.exclusions>
<maven.build.sourceVersion>11</maven.build.sourceVersion>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jibx</groupId>
<artifactId>maven-jibx-plugin</artifactId>
<configuration>
<load>true</load>
<schemaBindingDirectory>${project.build.sourceDirectory}/org/alfresco/repo/dictionary</schemaBindingDirectory>
<includeSchemaBindings>
<includeSchemaBinding>m2binding.xml</includeSchemaBinding>
</includeSchemaBindings>
</configuration>
<executions>
<execution>
<id>bind-sources</id>
<goals>
<goal>bind</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- ACE-3329 Create _en.properties message files -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>duplicate-english-messages</id>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<target>
<copy todir="${project.build.outputDirectory}">
<fileset dir="${basedir}/src/main/resources" includes="alfresco/messages/**/*.properties" />
<mapper type="regexp" from="^([^_]*).properties$" to="\1_en.properties" />
</copy>
</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.jibx</groupId>
<artifactId>
maven-jibx-plugin
</artifactId>
<versionRange>
[1.2.5,)
</versionRange>
<goals>
<goal>bind</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnConfiguration>true</runOnConfiguration>
<runOnIncremental>true</runOnIncremental>
</execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<tagNameFormat>@{project.version}</tagNameFormat>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencyManagement>
<dependencies>
<!-- Newer cxf libs, see REPO-3131 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${dependency.cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${dependency.cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>${dependency.cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${dependency.cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-ws-policy</artifactId>
<version>${dependency.cxf.version}</version>
</dependency>
<!-- upgrade dependency from TIKA -->
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>4.0.0</version>
</dependency>
<!-- upgrade dependency from TIKA -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<!-- upgrade dependency from TIKA -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>1.8.16-alfresco-patched</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>1.61</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-core</artifactId>
<version>${dependency.alfresco-core.version}</version>
</dependency>
<!--
| provided dependencies (are not transitive and not included in webapps)
| see http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!--
| compile dependencies
-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>org.jibx</groupId>
<artifactId>jibx-run</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr</artifactId>
<version>3.5.2</version>
</dependency>
<!-- the cxf libs were updated, see dependencyManagement section -->
<dependency>
<groupId>org.apache.chemistry.opencmis</groupId>
<artifactId>chemistry-opencmis-client-impl</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.chemistry.opencmis</groupId>
<artifactId>chemistry-opencmis-commons-impl</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.chemistry.opencmis</groupId>
<artifactId>chemistry-opencmis-server-bindings</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.2.0</version>
</dependency>
<!-- This is now deployed at:
| http://artifacts.alfresco.com/nexus/content/repositories/thirdparty/org/acegisecurity/acegi-security/0.8.2_patched/
-->
<dependency>
<groupId>org.acegisecurity</groupId>
<artifactId>acegi-security</artifactId>
<version>0.8.2_patched</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-xmlfactory</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0-alfresco-patched-20180402</version>
</dependency>
<dependency>
<groupId>xpp3</groupId>
<artifactId>xpp3</artifactId>
<version>1.1.3_8</version>
</dependency>
<!-- Tika -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.21-20190624-alfresco-patched</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>1.21-20190624-alfresco-patched</version>
<exclusions>
<exclusion>
<groupId>com.tdunning</groupId>
<artifactId>json</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.gagravarr</groupId>
<artifactId>vorbis-java-core</artifactId>
<version>0.8</version>
</dependency>
<dependency>
<groupId>org.gagravarr</groupId>
<artifactId>vorbis-java-tika</artifactId>
<version>0.8</version>
</dependency>
<dependency>
<groupId>com.googlecode.juniversalchardet</groupId>
<artifactId>juniversalchardet</artifactId>
<version>1.0.3</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>gunit</artifactId>
<version>3.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,95 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.encoding;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.parser.txt.CharsetDetector;
import org.apache.tika.parser.txt.CharsetMatch;
/**
* Uses Apache Tika as a fallback encoding detector
*
* @since 3.4
* @author Nick Burch
*/
public class TikaCharsetFinder extends AbstractCharactersetFinder
{
private static Log logger = LogFactory.getLog(TikaCharsetFinder.class);
private int threshold = 35;
@Override
protected Charset detectCharsetImpl(byte[] buffer) throws Exception
{
CharsetDetector detector = new CharsetDetector();
detector.setText(buffer);
CharsetMatch match = detector.detect();
if(match != null && match.getConfidence() > threshold)
{
try
{
return Charset.forName(match.getName());
}
catch(UnsupportedCharsetException e)
{
logger.info("Charset detected as " + match.getName() + " but the JVM does not support this, detection skipped");
}
}
return null;
}
/**
* Return the matching threshold before we decide that
* what we detected is a good match. In the range
* 0-100.
*/
public int getThreshold()
{
return threshold;
}
/**
* At what point do we decide our match is good enough?
* In the range 0-100. If we don't reach the threshold,
* we'll decline, and either another finder will work on
* it or the fallback encoding will be taken.
*/
public void setThreshold(int threshold)
{
if(threshold < 0)
threshold = 0;
if(threshold > 100)
threshold = 100;
this.threshold = threshold;
}
}

View File

@@ -0,0 +1,470 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.model;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Content Model Constants
*/
@AlfrescoPublicApi
public interface ContentModel
{
//
// System Model Definitions
//
// type for deleted nodes
static final QName TYPE_DELETED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "deleted");
static final QName PROP_ORIGINAL_ID = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "originalId");
// base type constants
static final QName TYPE_BASE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "base");
static final QName ASPECT_REFERENCEABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "referenceable");
static final QName PROP_STORE_PROTOCOL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "store-protocol");
static final QName PROP_STORE_IDENTIFIER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "store-identifier");
static final QName PROP_NODE_UUID = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-uuid");
static final QName PROP_NODE_DBID = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid");
// tag for incomplete nodes
static final QName ASPECT_INCOMPLETE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "incomplete");
// tag for temporary nodes
static final QName ASPECT_TEMPORARY = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "temporary");
// tag for nodes being formed (CIFS)
static final QName ASPECT_NO_CONTENT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "noContent");
// tag for nodes being formed (WebDAV)
static final QName ASPECT_WEBDAV_NO_CONTENT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "webdavNoContent");
static final QName ASPECT_WEBDAV_OBJECT = QName.createQName(NamespaceService.WEBDAV_MODEL_1_0_URI, "object");
static final QName PROP_DEAD_PROPERTIES = QName.createQName(NamespaceService.WEBDAV_MODEL_1_0_URI, "deadproperties");
// tag for localized nodes
static final QName ASPECT_LOCALIZED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "localized");
static final QName PROP_LOCALE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "locale");
// tag for hidden nodes
static final QName ASPECT_HIDDEN = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "hidden");
static final QName PROP_VISIBILITY_MASK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "clientVisibilityMask");
static final QName PROP_HIDDEN_FLAG = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "hiddenFlag");
static final QName PROP_CASCADE_HIDDEN = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeHidden");
static final QName PROP_CASCADE_INDEX_CONTROL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeIndexControl");
static final QName PROP_CLIENT_CONTROLLED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "clientControlled");
// tag for soft delete (CIFS rename shuffle)
static final QName ASPECT_SOFT_DELETE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "softDelete");
// archived nodes aspect constants
static final QName ASPECT_ARCHIVE_ROOT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archiveRoot");
static final QName ASSOC_ARCHIVE_USER_LINK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archiveUserLink");
static final QName TYPE_ARCHIVE_USER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archiveUser");
static final QName ASSOC_ARCHIVED_LINK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLink");
static final QName ASPECT_ARCHIVED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archived");
static final QName PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedOriginalParentAssoc");
static final QName PROP_ARCHIVED_BY = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedBy");
static final QName PROP_ARCHIVED_DATE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedDate");
static final QName PROP_ARCHIVED_ORIGINAL_OWNER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedOriginalOwner");
static final QName ASPECT_ARCHIVED_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archived-assocs");
static final QName PROP_ARCHIVED_PARENT_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedParentAssocs");
static final QName PROP_ARCHIVED_CHILD_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedChildAssocs");
static final QName PROP_ARCHIVED_SOURCE_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedSourceAssocs");
static final QName PROP_ARCHIVED_TARGET_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedTargetAssocs");
static final QName ASPECT_ARCHIVE_LOCKABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockable");
static final QName PROP_ARCHIVED_LOCK_OWNER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockOwner");
static final QName PROP_ARCHIVED_LOCK_TYPE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockType");
static final QName PROP_ARCHIVED_LOCK_LIFETIME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockLifetime");
static final QName PROP_ARCHIVED_EXPIRY_DATE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedExpiryDate");
static final QName PROP_ARCHIVED_LOCK_ADDITIONAL_INFO = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockAdditionalInfo");
// referenceable aspect constants
static final QName TYPE_REFERENCE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "reference");
static final QName PROP_REFERENCE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "reference");
// container type constants
static final QName TYPE_CONTAINER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "container");
/** child association type supported by {@link #TYPE_CONTAINER} */
static final QName ASSOC_CHILDREN =QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "children");
// roots
static final QName ASPECT_ROOT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "aspect_root");
static final QName TYPE_STOREROOT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "store_root");
// for internal use only: see ALF-13066 / ALF-12358
static final QName TYPE_LOST_AND_FOUND = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "lost_found");
static final QName ASSOC_LOST_AND_FOUND = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "lost_found");
// descriptor properties
static final QName PROP_SYS_NAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "name");
static final QName PROP_SYS_VERSION_MAJOR = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionMajor");
static final QName PROP_SYS_VERSION_MINOR = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionMinor");
static final QName PROP_SYS_VERSION_REVISION = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionRevision");
static final QName PROP_SYS_VERSION_LABEL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionLabel");
static final QName PROP_SYS_VERSION_BUILD = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionBuild");
static final QName PROP_SYS_VERSION_SCHEMA = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionSchema");
static final QName PROP_SYS_VERSION_EDITION = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionEdition");
static final QName PROP_SYS_VERSION_PROPERTIES = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionProperties");
static final QName PROP_SYS_LICENSE_MODE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "licenseMode");
/**
* Aspect for nodes which are by default not deletable.
* @since 3.5.0
*/
static final QName ASPECT_UNDELETABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "undeletable");
/**
* Aspect for nodes which are by default not movable.
*/
static final QName ASPECT_UNMOVABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "unmovable");
/**
* Aspects marking nodes that are pending deletion.
* This aspect is applied to all nodes that are about to be deleted within a transaction.
* The aspect survives only for the duration of calls to delete nodes and their children.
*/
static final QName ASPECT_PENDING_DELETE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "pendingDelete");
/**
* Aspect marking nodes for pending set fixed ACL operation and it's contants
*/
static final QName ASPECT_PENDING_FIX_ACL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "pendingFixAcl");
static final QName PROP_SHARED_ACL_TO_REPLACE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "sharedAclToReplace");
static final QName PROP_INHERIT_FROM_ACL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "inheritFromAcl");
//
// Content Model Definitions
//
// content management type constants
static final QName TYPE_CMOBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "cmobject");
static final QName PROP_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "name");
// copy aspect constants
static final QName ASPECT_COPIEDFROM = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copiedfrom");
static final QName ASSOC_ORIGINAL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "original");
// working copy aspect contants
static final QName ASPECT_CHECKED_OUT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "checkedOut");
static final QName ASSOC_WORKING_COPY_LINK = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingcopylink");
static final QName ASPECT_WORKING_COPY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingcopy");
static final QName PROP_WORKING_COPY_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingCopyOwner");
static final QName PROP_WORKING_COPY_MODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingCopyMode");
static final QName PROP_WORKING_COPY_LABEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingCopyLabel");
// content type and aspect constants
static final QName TYPE_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content");
static final QName PROP_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content");
// title aspect
static final QName ASPECT_TITLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "titled");
static final QName PROP_TITLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "title");
static final QName PROP_DESCRIPTION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "description");
// auditable aspect
static final QName ASPECT_AUDITABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "auditable");
static final QName PROP_CREATED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "created");
static final QName PROP_CREATOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "creator");
static final QName PROP_MODIFIED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modified");
static final QName PROP_MODIFIER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modifier");
static final QName PROP_ACCESSED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "accessed");
// author aspect
static final QName ASPECT_AUTHOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "author");
static final QName PROP_AUTHOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "author");
// categories
static final QName TYPE_CATEGORYROOT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "category_root");
static final QName ASPECT_CLASSIFIABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "classifiable");
//static final QName ASPECT_CATEGORISATION = QName.createQName(NamespaceService.ALFRESCO_URI, "aspect_categorisation");
static final QName ASPECT_GEN_CLASSIFIABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "generalclassifiable");
static final QName TYPE_CATEGORY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "category");
static final QName PROP_CATEGORIES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "categories");
static final QName ASSOC_CATEGORIES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "categories");
static final QName ASSOC_SUBCATEGORIES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subcategories");
// tags - a subsection of categories
static final QName ASPECT_TAGGABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "taggable");
static final QName PROP_TAGS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "taggable");
// tagscope aspect
static final QName ASPECT_TAGSCOPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "tagscope");
static final QName PROP_TAGSCOPE_CACHE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "tagScopeCache");
static final QName PROP_TAGSCOPE_SUMMARY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "tagScopeSummary");
// ratings
static final QName ASPECT_RATEABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "rateable");
static final QName ASPECT_LIKES_RATING_SCHEME_ROLLUPS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "likesRatingSchemeRollups");
static final QName ASPECT_FIVESTAR_RATING_SCHEME_ROLLUPS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "fiveStarRatingSchemeRollups");
static final QName ASSOC_RATINGS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratings");
static final QName TYPE_RATING = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "rating");
static final QName PROP_RATING_SCORE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratingScore");
static final QName PROP_RATING_SCHEME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratingScheme");
static final QName PROP_RATED_AT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratedAt");
// lock aspect
public final static QName ASPECT_LOCKABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockable");
public final static QName PROP_LOCK_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockOwner");
public final static QName PROP_LOCK_TYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockType");
public final static QName PROP_LOCK_LIFETIME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockLifetime");
public final static QName PROP_EXPIRY_DATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "expiryDate");
public final static QName PROP_LOCK_ADDITIONAL_INFO = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockAdditionalInfo");
// version aspect
static final QName ASPECT_VERSIONABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionable");
static final QName PROP_VERSION_LABEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionLabel");
static final QName PROP_INITIAL_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "initialVersion");
static final QName PROP_AUTO_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "autoVersion");
static final QName PROP_AUTO_VERSION_PROPS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "autoVersionOnUpdateProps");
static final QName PROP_VERSION_TYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionType");
// folders
static final QName TYPE_SYSTEM_FOLDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "systemfolder");
static final QName TYPE_FOLDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "folder");
/** child association type supported by {@link #TYPE_FOLDER} */
static final QName ASSOC_CONTAINS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "contains");
// person
static final QName TYPE_PERSON = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "person");
static final QName PROP_USERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userName");
static final QName PROP_HOMEFOLDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "homeFolder");
static final QName PROP_FIRSTNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "firstName");
static final QName PROP_LASTNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lastName");
static final QName PROP_EMAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "email");
static final QName PROP_ORGID = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "organizationId");
static final QName PROP_HOME_FOLDER_PROVIDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "homeFolderProvider");
static final QName PROP_DEFAULT_HOME_FOLDER_PATH = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "defaultHomeFolderPath");
static final QName PROP_PRESENCEPROVIDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "presenceProvider");
static final QName PROP_PRESENCEUSERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "presenceUsername");
static final QName PROP_ORGANIZATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "organization");
static final QName PROP_JOBTITLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "jobtitle");
static final QName PROP_LOCATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "location");
static final QName PROP_PERSONDESC = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "persondescription");
static final QName PROP_TELEPHONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "telephone");
static final QName PROP_MOBILE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mobile");
static final QName PROP_COMPANYADDRESS1 = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyaddress1");
static final QName PROP_COMPANYADDRESS2 = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyaddress2");
static final QName PROP_COMPANYADDRESS3 = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyaddress3");
static final QName PROP_COMPANYPOSTCODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companypostcode");
static final QName PROP_COMPANYTELEPHONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companytelephone");
static final QName PROP_COMPANYFAX = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyfax");
static final QName PROP_COMPANYEMAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyemail");
static final QName PROP_SKYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "skype");
static final QName PROP_GOOGLEUSERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "googleusername");
static final QName PROP_INSTANTMSG = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "instantmsg");
static final QName PROP_USER_STATUS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userStatus");
static final QName PROP_USER_STATUS_TIME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userStatusTime");
static final QName PROP_SIZE_CURRENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sizeCurrent"); // system-maintained
static final QName PROP_SIZE_QUOTA = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sizeQuota");
static final QName PROP_EMAIL_FEED_ID = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "emailFeedId"); // system-maintained
static final QName PROP_EMAIL_FEED_DISABLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "emailFeedDisabled");
static final QName PROP_SUBSCRIPTIONS_PRIVATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subscriptionsPrivate");
static final QName ASPECT_PERSON_DISABLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "personDisabled");
static final QName ASPECT_ANULLABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "annullable");
static final QName ASSOC_AVATAR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avatar");
// Authority
static final QName TYPE_AUTHORITY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authority");
static final QName TYPE_AUTHORITY_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authorityContainer");
static final QName PROP_AUTHORITY_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authorityName");
static final QName PROP_AUTHORITY_DISPLAY_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authorityDisplayName");
static final QName ASSOC_MEMBER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "member");
// Zone
static final QName TYPE_ZONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "zone");
static final QName ASSOC_IN_ZONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "inZone");
// Ownable aspect
static final QName ASPECT_OWNABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ownable");
static final QName PROP_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "owner");
// Templatable aspect
static final QName ASPECT_TEMPLATABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "templatable");
static final QName PROP_TEMPLATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "template");
// Webscriptable aspect
static final QName ASPECT_WEBSCRIPTABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "webscriptable");
static final QName PROP_WEBSCRIPT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "webscript");
// Dictionary model
static final QName TYPE_DICTIONARY_MODEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "dictionaryModel");
static final QName PROP_MODEL_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelName");
static final QName PROP_MODEL_DESCRIPTION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelDescription");
static final QName PROP_MODEL_AUTHOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelAuthor");
static final QName PROP_MODEL_PUBLISHED_DATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelPublishedDate");
static final QName PROP_MODEL_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelVersion");
static final QName PROP_MODEL_ACTIVE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelActive");
// referencing aspect
static final QName ASPECT_REFERENCING = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "referencing");
static final QName ASSOC_REFERENCES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "references");
// link object
static final QName TYPE_LINK = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "link");
static final QName PROP_LINK_DESTINATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "destination");
// attachable aspect
static final QName ASPECT_ATTACHABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "attachable");
static final QName ASSOC_ATTACHMENTS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "attachments");
// emailed aspect
static final QName ASPECT_EMAILED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "emailed");
static final QName PROP_SENTDATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sentdate");
static final QName PROP_ORIGINATOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "originator");
static final QName PROP_ADDRESSEE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "addressee");
static final QName PROP_ADDRESSEES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "addressees");
static final QName PROP_SUBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subjectline");
// countable aspect
static final QName ASPECT_COUNTABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "countable");
static final QName PROP_HITS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "hits");
static final QName PROP_COUNTER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "counter");
// References Node Aspect.
static final QName ASPECT_REFERENCES_NODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "referencesnode");
static final QName PROP_NODE_REF = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "noderef");
// Geographic Aspect.
static final QName ASPECT_GEOGRAPHIC = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "geographic");
static final QName PROP_LATITUDE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "latitude");
static final QName PROP_LONGITUDE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "longitude");
// Multilingual Type
static final QName TYPE_MULTILINGUAL_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlContainer");
static final QName ASSOC_MULTILINGUAL_CHILD = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlChild");
static final QName ASPECT_MULTILINGUAL_DOCUMENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlDocument");
static final QName ASPECT_MULTILINGUAL_EMPTY_TRANSLATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlEmptyTranslation");
// Thumbnail Type
static final QName TYPE_THUMBNAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnail");
static final QName PROP_THUMBNAIL_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnailName");
static final QName PROP_CONTENT_PROPERTY_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "contentPropertyName");
static final QName PROP_AUTOMATIC_UPDATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "automaticUpdate");
// Thumbnail modification handling
public static final QName ASPECT_THUMBNAIL_MODIFICATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnailModification");
public static final QName PROP_LAST_THUMBNAIL_MODIFICATION_DATA = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lastThumbnailModification");
// The below content entities can be used to manage 'failed' thumbnails. These are thumbnails that execute and fail with an
// exception that likely means a reattempt will fail. The failedThumbnailSource aspect can be used to mark a node as
// having tried and failed to use a particular thumbnail definition. This can then be checked and reattempts at that thumbnail
// can be prevented or throttled.
static final QName ASPECT_FAILED_THUMBNAIL_SOURCE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnailSource");
static final QName ASSOC_FAILED_THUMBNAIL= QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnail");
static final QName TYPE_FAILED_THUMBNAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnail");
static final QName PROP_FAILED_THUMBNAIL_TIME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnailTime");
static final QName PROP_FAILURE_COUNT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failureCount");
// Thumbnailed Aspect
/**
* This aspect type has been deprecated.
* From Alfresco 3.3 the {@link RenditionModel#ASPECT_RENDITIONED rn:renditioned}
* (which is a child of cm:thumbnailed) should be used instead.
*/
@Deprecated
static final QName ASPECT_THUMBNAILED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnailed");
/**
* This association type has been deprecated.
* From Alfresco 3.3 this association no longer exists and has been replaced with
* {@link RenditionModel#ASSOC_RENDITION rn:rendition} association. From Alfresco
* 3.3 onwards a patch is executed at startup which renames
* the cm:thumbnails QName to rn:rendition in the database.
* <P/>
* This field has been updated to point to that association and references to this
* field should be updated to use the new field.
*/
@Deprecated
static final QName ASSOC_THUMBNAILS = RenditionModel.ASSOC_RENDITION;
// StoreSelector Aspect
static final QName ASPECT_STORE_SELECTOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "storeSelector");
static final QName PROP_STORE_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "storeName");
// Preference Aspect
static final QName ASPECT_PREFERENCES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "preferences");
static final QName PROP_PREFERENCE_VALUES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "preferenceValues");
static final QName ASSOC_PREFERENCE_IMAGE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "preferenceImage");
// Syndication Aspect
static final QName ASPECT_SYNDICATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "syndication");
static final QName PROP_PUBLISHED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "published");
static final QName PROP_UPDATED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "updated");
// Dublin core aspect
static final QName ASPECT_DUBLINCORE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "dublincore");
//
// User Model Definitions
//
static final String USER_MODEL_URI = "http://www.alfresco.org/model/user/1.0";
static final String USER_MODEL_PREFIX = "usr";
static final QName TYPE_USER = QName.createQName(USER_MODEL_URI, "user");
static final QName PROP_USER_USERNAME = QName.createQName(USER_MODEL_URI, "username");
static final QName PROP_PASSWORD = QName.createQName(USER_MODEL_URI, "password");
static final QName PROP_PASSWORD_SHA256 = QName.createQName(USER_MODEL_URI, "password2");
static final QName PROP_PASSWORD_HASH = QName.createQName(USER_MODEL_URI, "passwordHash");
static final QName PROP_ENABLED = QName.createQName(USER_MODEL_URI, "enabled");
static final QName PROP_ACCOUNT_EXPIRES = QName.createQName(USER_MODEL_URI, "accountExpires");
static final QName PROP_ACCOUNT_EXPIRY_DATE = QName.createQName(USER_MODEL_URI, "accountExpiryDate");
static final QName PROP_CREDENTIALS_EXPIRE = QName.createQName(USER_MODEL_URI, "credentialsExpire");
static final QName PROP_CREDENTIALS_EXPIRY_DATE = QName.createQName(USER_MODEL_URI, "credentialsExpiryDate");
static final QName PROP_ACCOUNT_LOCKED = QName.createQName(USER_MODEL_URI, "accountLocked");
static final QName PROP_SALT = QName.createQName(USER_MODEL_URI, "salt");
static final QName PROP_HASH_INDICATOR = QName.createQName(USER_MODEL_URI, "hashIndicator");
//
// Indexing control
//
static final QName ASPECT_INDEX_CONTROL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "indexControl");
static final QName PROP_IS_INDEXED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "isIndexed");
static final QName PROP_IS_CONTENT_INDEXED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "isContentIndexed");
// CMIS aspects
static final QName ASPECT_CMIS_UPDATE_CONTEXT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "CMISUpdateContext");
static final QName PROP_GOT_FIRST_CHUNK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "gotFirstChunk");
static final QName ASPECT_CMIS_CREATED_CHECKEDOUT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "cmisCreatedCheckedOut");
// Cascade Update
static final QName ASPECT_CASCADE_UPDATE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeUpdate");
static final QName PROP_CASCADE_CRC = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeCRC");
static final QName PROP_CASCADE_TX = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeTx");
}

View File

@@ -0,0 +1,76 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.model;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Rendition Model Constants
*/
@AlfrescoPublicApi
public interface RenditionModel
{
/**
* Aspect added to renditions created by RenditionService2.
* Initially used to avoid duplicate rendition requests via the original RenditionService and the new one.
*/
static final QName ASPECT_RENDITION2 = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "rendition2");
/**
* The source node's content hash code. Used to work out if a transform should replace the existing rendition,
* as transforms may be provided out of order.
*/
static final QName PROP_RENDITION_CONTENT_HASH_CODE = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "contentHashCode");
/**
* @deprecated This rendition aspect will no longger be needed once the original RenditionService has been
* replaced by RenditionService2 which additionally uses a rendition2 aspect to mark its renditions.
*/
@Deprecated
static final QName ASPECT_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "rendition");
/**
* @deprecated obsolete when RenditionService is removed.
*/
@Deprecated
static final QName ASPECT_HIDDEN_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "hiddenRendition");
/**
* @deprecated obsolete when RenditionService is removed.
*/
@Deprecated
static final QName ASPECT_VISIBLE_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "visibleRendition");
static final QName ASPECT_RENDITIONED = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "renditioned");
static final QName ASSOC_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "rendition");
/**
* @since 4.0.1
*/
static final QName ASPECT_PREVENT_RENDITIONS = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "preventRenditions");
}

View File

@@ -0,0 +1,71 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis;
/**
* @author andyh
*
*/
public enum CMISAccessControlFormatEnum implements EnumLabel
{
/**
* Report only CMIS basic permissions
*/
CMIS_BASIC_PERMISSIONS("onlyBasicPermissions"),
/**
* May report CMIS basic permission, repository specific permissions or a mixture of both.
*/
REPOSITORY_SPECIFIC_PERMISSIONS("repositorySpecificPermissions");
private String label;
/**
* Construct
*
* @param label String
*/
CMISAccessControlFormatEnum(String label)
{
this.label = label;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.cmis.EnumLabel#label()
*/
public String getLabel()
{
return label;
}
/**
* Factory for CMISAclPropagationEnum
*/
public static EnumFactory<CMISAccessControlFormatEnum> FACTORY = new EnumFactory<CMISAccessControlFormatEnum>(CMISAccessControlFormatEnum.class, CMIS_BASIC_PERMISSIONS, true);
}

View File

@@ -0,0 +1,169 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
public class CMISUtils
{
@SuppressWarnings("unchecked")
public static <T> T copy(T source)
{
T target = null;
try ( CopyOutputStream cos = new CopyOutputStream();
ObjectOutputStream out = new ObjectOutputStream(cos) )
{
out.writeObject(source);
out.flush();
try (ObjectInputStream in = new ObjectInputStream(cos.getInputStream()))
{
target = (T) in.readObject();
}
} catch (Exception e)
{
throw new CmisRuntimeException("Object copy failed!", e);
}
return target;
}
private static class CopyOutputStream extends OutputStream
{
protected byte[] buf = null;
protected int size = 0;
public CopyOutputStream()
{
this(16 * 1024);
}
public CopyOutputStream(int initSize)
{
this.size = 0;
this.buf = new byte[initSize];
}
private void verifyBufferSize(int sz)
{
if (sz > buf.length)
{
byte[] old = buf;
buf = new byte[Math.max(sz, 2 * buf.length)];
System.arraycopy(old, 0, buf, 0, old.length);
old = null;
}
}
public final void write(byte b[])
{
verifyBufferSize(size + b.length);
System.arraycopy(b, 0, buf, size, b.length);
size += b.length;
}
public final void write(byte b[], int off, int len)
{
verifyBufferSize(size + len);
System.arraycopy(b, off, buf, size, len);
size += len;
}
public final void write(int b)
{
verifyBufferSize(size + 1);
buf[size++] = (byte) b;
}
public InputStream getInputStream()
{
return new CopyInputStream(buf, size);
}
}
private static class CopyInputStream extends InputStream
{
protected byte[] buf = null;
protected int count = 0;
protected int pos = 0;
public CopyInputStream(byte[] buf, int count)
{
this.buf = buf;
this.count = count;
}
public final int available()
{
return count - pos;
}
public final int read()
{
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
public final int read(byte[] b, int off, int len)
{
if (pos >= count)
{
return -1;
}
if ((pos + len) > count)
{
len = (count - pos);
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
public final long skip(long n)
{
if ((pos + n) > count)
{
n = count - pos;
}
if (n < 0)
{
return 0;
}
pos += n;
return n;
}
}
}

View File

@@ -0,0 +1,151 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
/**
* Enum Factory for managing mapping between Enum name and Enum label
*
* @author dcaruana
*
*/
public class EnumFactory<E extends Enum<E>>
{
private E defaultEnum;
private Map<String, E> labelMap = new HashMap<String, E>(10);
public EnumFactory(Class<E> enumClass)
{
this(enumClass, null, false);
}
public EnumFactory(Class<E> enumClass, E defaultEnum)
{
this(enumClass, defaultEnum, false);
}
/**
* @param caseSensitive case-sensitive lookup for Enum label
*/
public EnumFactory(Class<E> enumClass, E defaultEnum, boolean caseSensitive)
{
this.defaultEnum = defaultEnum;
// setup label map
labelMap = caseSensitive ? new HashMap<String, E>(10) : new TreeMap<String, E>(String.CASE_INSENSITIVE_ORDER);
EnumSet<E> enumSet = EnumSet.allOf(enumClass);
Iterator<E> iter = enumSet.iterator();
while(iter.hasNext())
{
E e = iter.next();
if (e instanceof EnumLabel)
{
labelMap.put(((EnumLabel)e).getLabel(), e);
}
}
}
/**
* Gets the default enum
*
* @return default enum (or null, if no default specified)
*/
public Enum<E> getDefaultEnum()
{
return defaultEnum;
}
/**
* Gets the default label
*
* @return label of default enum (or null, if no default specified)
*/
public String getDefaultLabel()
{
return label(defaultEnum);
}
/**
* Gets the label for the specified enum
*
* @param e enum
* @return label (or null, if no label specified)
*/
public String label(E e)
{
if (e instanceof EnumLabel)
{
return ((EnumLabel)e).getLabel();
}
return null;
}
/**
* Is valid label?
*
* @param label String
* @return true => valid, false => does not exist for this enum
*/
public boolean validLabel(String label)
{
return fromLabel(label) == null ? false : true;
}
/**
* Gets enum from label
*
* @param label String
* @return enum (or null, if no enum has specified label)
*/
public E fromLabel(String label)
{
return labelMap.get(label);
}
/**
* Gets enum from label
*
* NOTE: If specified label is invalid, the default enum is returned
*
* @param label String
* @return enum (or default enum, if label is invalid)
*/
public E toEnum(String label)
{
E e = (label == null) ? null : fromLabel(label);
if (e == null)
{
e = defaultEnum;
}
return e;
}
}

View File

@@ -0,0 +1,41 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis;
/**
* Enum label (mapping from Enum name to CMIS name)
*
* @author davidc
*/
public interface EnumLabel
{
/**
* Gets the enum label (as defined by CMIS)
*
* @return enum label
*/
public String getLabel();
}

View File

@@ -0,0 +1,813 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.repo.dictionary.IndexTokenisationMode;
import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint;
import org.alfresco.repo.dictionary.constraint.StringLengthConstraint;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.Constraint;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO8601DateFormat;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.definitions.Choice;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.Cardinality;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.PropertyType;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyDefinition;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractTypeDefinition;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ChoiceImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyHtmlDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriDefinitionImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class for type definition wrappers.
*
* @author florian.mueller
*/
public abstract class AbstractTypeDefinitionWrapper implements TypeDefinitionWrapper, Serializable
{
private static final long serialVersionUID = 1L;
private Log logger = LogFactory.getLog(AbstractTypeDefinitionWrapper.class);
protected AbstractTypeDefinition typeDef;
protected AbstractTypeDefinition typeDefInclProperties;
protected TypeDefinitionWrapper parent;
// protected List<TypeDefinitionWrapper> children;
private String tenantId;
private ReadWriteLock lock = new ReentrantReadWriteLock();
@Override
public String getTenantId()
{
return tenantId;
}
protected QName alfrescoName = null;
protected QName alfrescoClass = null;
protected Map<Action, CMISActionEvaluator> actionEvaluators;
protected Map<String, PropertyDefinitionWrapper> propertiesById = new HashMap<String, PropertyDefinitionWrapper>();
protected Map<String, PropertyDefinitionWrapper> propertiesByQueryName = new HashMap<String, PropertyDefinitionWrapper>();
protected Map<QName, PropertyDefinitionWrapper> propertiesByQName = new HashMap<QName, PropertyDefinitionWrapper>();
// interface
public TypeDefinition getTypeDefinition(boolean includePropertyDefinitions)
{
lock.readLock().lock();
try
{
if (includePropertyDefinitions)
{
return typeDefInclProperties;
}
else
{
return typeDef;
}
}
finally
{
lock.readLock().unlock();
}
}
protected void setTypeDefinition(AbstractTypeDefinition typeDef, AbstractTypeDefinition typeDefInclProperties)
{
this.typeDef = typeDef;
this.typeDefInclProperties = typeDefInclProperties;
}
@Override
public String getTypeId()
{
return typeDef.getId();
}
@Override
public BaseTypeId getBaseTypeId()
{
return typeDef.getBaseTypeId();
}
@Override
public boolean isBaseType()
{
return typeDef.getId().equals(typeDef.getBaseTypeId().value());
}
@Override
public QName getAlfrescoName()
{
return alfrescoName;
}
@Override
public QName getAlfrescoClass()
{
return alfrescoClass;
}
@Override
public TypeDefinitionWrapper getParent()
{
return parent;
}
// @Override
// public List<TypeDefinitionWrapper> getChildren()
// {
// return children;
// }
@Override
public Map<Action, CMISActionEvaluator> getActionEvaluators()
{
return actionEvaluators;
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties()
{
return propertiesById.values();
}
@Override
public PropertyDefinitionWrapper getPropertyById(String propertyId)
{
return propertiesById.get(propertyId);
}
@Override
public PropertyDefinitionWrapper getPropertyByQueryName(String queryName)
{
return propertiesByQueryName.get(queryName);
}
@Override
public PropertyDefinitionWrapper getPropertyByQName(QName name)
{
return propertiesByQName.get(name);
}
@Override
public void updateDefinition(DictionaryService dictionaryService)
{
String name = null;
String description = null;
ClassDefinition definition = dictionaryService.getClass(alfrescoName);
if (definition != null)
{
name = definition.getTitle(dictionaryService);
description = definition.getDescription(dictionaryService);
}
setTypeDefDisplayName(name);
setTypeDefDescription(description);
}
public void updateProperties(DictionaryService dictionaryService)
{
for (PropertyDefinitionWrapper propertyDefWrap : propertiesById.values())
{
updateProperty(dictionaryService, propertyDefWrap);
}
}
public void updateProperty(DictionaryService dictionaryService, PropertyDefinitionWrapper propertyDefWrap)
{
if (propertyDefWrap != null && propertyDefWrap.getPropertyDefinition().getDisplayName() == null)
{
AbstractPropertyDefinition<?> property = (AbstractPropertyDefinition<?>) propertyDefWrap.getPropertyDefinition();
org.alfresco.service.cmr.dictionary.PropertyDefinition propDef = dictionaryService
.getProperty(QName.createQName(property.getLocalNamespace(), property.getLocalName()));
if (propDef != null)
{
String displayName = propDef.getTitle(dictionaryService);
String description = propDef.getDescription(dictionaryService);
property.setDisplayName(displayName == null ? property.getId() : displayName);
property.setDescription(description == null ? property.getDisplayName() : description);
}
}
}
public void updateTypeDefInclProperties()
{
for (PropertyDefinition<?> property : typeDefInclProperties.getPropertyDefinitions().values())
{
if (property.getDisplayName() == null)
{
typeDefInclProperties.addPropertyDefinition(getPropertyById(property.getId()).getPropertyDefinition());
}
}
}
public void setTypeDefDisplayName(String name)
{
lock.writeLock().lock();
try
{
typeDef.setDisplayName(name != null ? name : typeDef.getId());
typeDefInclProperties.setDisplayName(name != null ? name : typeDef.getId());
}
finally
{
lock.writeLock().unlock();
}
}
public void setTypeDefDescription(String desc)
{
lock.writeLock().lock();
try
{
typeDef.setDescription(desc != null ? desc : typeDef.getId());
typeDefInclProperties.setDescription(desc != null ? desc : typeDef.getId());
}
finally
{
lock.writeLock().unlock();
}
}
// create
public abstract List<TypeDefinitionWrapper> connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry,
DictionaryService dictionaryService);
public abstract void resolveInheritance(CMISMapping cmisMapping, CMISDictionaryRegistry registry,
DictionaryService dictionaryService);
public void assertComplete()
{
if (typeDef == null)
throw new IllegalStateException("typeDef is not set");
if (typeDefInclProperties == null)
throw new IllegalStateException("typeDefInclProperties is not set");
if (alfrescoName == null)
throw new IllegalStateException("alfrescoName is not set");
if (alfrescoClass == null)
throw new IllegalStateException("alfrescoClass is not set");
if (propertiesById == null)
throw new IllegalStateException("propertiesById is not set");
if (propertiesByQueryName == null)
throw new IllegalStateException("propertiesByQueryName is not set");
if (propertiesByQName == null)
throw new IllegalStateException("propertiesByQName is not set");
// if (propertiesById.size() == 0)
// throw new IllegalStateException("property map empty");
if (propertiesById.size() != propertiesByQueryName.size())
throw new IllegalStateException("property map mismatch");
if (propertiesById.size() != propertiesByQName.size())
throw new IllegalStateException("property map mismatch");
}
/**
* Adds all property definitions owned by that type.
*/
protected void createOwningPropertyDefinitions(CMISMapping cmisMapping,
PropertyAccessorMapping propertyAccessorMapping, PropertyLuceneBuilderMapping luceneBuilderMapping,
DictionaryService dictionaryService, ClassDefinition cmisClassDef)
{
PropertyDefinition<?> propertyDefintion;
for (org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef : cmisClassDef.getProperties()
.values())
{
if (!isBaseType())
{
if (!alfrescoPropDef.getContainerClass().equals(cmisClassDef))
{
continue;
}
}
// compile property id
String propertyId = cmisMapping.buildPrefixEncodedString(alfrescoPropDef.getName());
if(propertyId.equals("cmis:secondaryObjectTypeIds") && cmisMapping.getCmisVersion() == CmisVersion.CMIS_1_0)
{
continue;
}
// create property definition
propertyDefintion = createPropertyDefinition(cmisMapping, propertyId, alfrescoPropDef.getName(),
dictionaryService, alfrescoPropDef, false);
// if the datatype is not supported, the property defintion will be
// null
if (propertyDefintion != null)
{
CMISPropertyAccessor propertyAccessor = null;
if (propertyAccessorMapping != null)
{
propertyAccessor = propertyAccessorMapping.getPropertyAccessor(propertyId);
if (propertyAccessor == null)
{
propertyAccessor = propertyAccessorMapping.createDirectPropertyAccessor(propertyId,
alfrescoPropDef.getName());
}
}
CMISPropertyLuceneBuilder luceneBuilder = null;
if (luceneBuilderMapping != null)
{
luceneBuilder = luceneBuilderMapping.getPropertyLuceneBuilder(propertyId);
if (luceneBuilder == null)
{
luceneBuilder = luceneBuilderMapping.createDirectPropertyLuceneBuilder(alfrescoPropDef
.getName());
}
}
registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(), this,
propertyAccessor, luceneBuilder));
}
}
}
/**
* Registers a property definition with this type
*/
protected void registerProperty(PropertyDefinitionWrapper propDefWrapper)
{
if (propDefWrapper == null)
{
return;
}
if (propertiesById.containsKey(propDefWrapper.getPropertyId()))
{
throw new AlfrescoRuntimeException("Property defintion " + propDefWrapper.getPropertyId()
+ " already exists on type " + typeDef.getId());
}
propertiesById.put(propDefWrapper.getPropertyId(), propDefWrapper);
propertiesByQueryName.put(propDefWrapper.getPropertyDefinition().getQueryName(), propDefWrapper);
propertiesByQName.put(propDefWrapper.getAlfrescoName(), propDefWrapper);
typeDefInclProperties.addPropertyDefinition(propDefWrapper.getPropertyDefinition());
}
/**
* Creates a property definition object.
*/
protected PropertyDefinition<?> createPropertyDefinition(CMISMapping cmisMapping, String id,
QName alfrescoPropName, DictionaryService dictionaryService, org.alfresco.service.cmr.dictionary.PropertyDefinition propDef, boolean inherited)
{
PropertyType datatype = cmisMapping.getDataType(propDef.getDataType());
if (datatype == null)
{
return null;
}
AbstractPropertyDefinition<?> result = null;
switch (datatype)
{
case BOOLEAN:
result = new PropertyBooleanDefinitionImpl();
break;
case DATETIME:
result = new PropertyDateTimeDefinitionImpl();
break;
case DECIMAL:
result = new PropertyDecimalDefinitionImpl();
break;
case HTML:
result = new PropertyHtmlDefinitionImpl();
break;
case ID:
result = new PropertyIdDefinitionImpl();
break;
case INTEGER:
result = new PropertyIntegerDefinitionImpl();
break;
case STRING:
result = new PropertyStringDefinitionImpl();
break;
case URI:
result = new PropertyUriDefinitionImpl();
break;
default:
throw new RuntimeException("Unknown datatype! Spec change?");
}
if (id.equals(PropertyIds.OBJECT_TYPE_ID) || id.equals(PropertyIds.SOURCE_ID)
|| id.equals(PropertyIds.TARGET_ID))
{
// the CMIS spec requirement
result.setUpdatability(Updatability.ONCREATE);
} else
{
result.setUpdatability(propDef.isProtected() ? Updatability.READONLY : Updatability.READWRITE);
}
result.setId(id);
result.setLocalName(alfrescoPropName.getLocalName());
result.setLocalNamespace(alfrescoPropName.getNamespaceURI());
result.setDisplayName(null);
result.setDescription(null);
result.setPropertyType(datatype);
result.setCardinality(propDef.isMultiValued() ? Cardinality.MULTI : Cardinality.SINGLE);
result.setIsInherited(inherited);
result.setIsRequired(propDef.isMandatory());
addDefaultValue(propDef.getDefaultValue(), result);
// query and order
result.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoPropName)));
result.setIsQueryable(propDef.isIndexed());
result.setIsOrderable(false);
if (result.isQueryable())
{
if (result.getCardinality() == Cardinality.SINGLE)
{
IndexTokenisationMode indexTokenisationMode = IndexTokenisationMode.TRUE;
if (propDef.getIndexTokenisationMode() != null)
{
indexTokenisationMode = propDef.getIndexTokenisationMode();
}
switch (indexTokenisationMode)
{
case BOTH:
case FALSE:
result.setIsOrderable(true);
break;
case TRUE:
default:
if (propDef.getDataType().getName().equals(DataTypeDefinition.BOOLEAN)
|| propDef.getDataType().getName().equals(DataTypeDefinition.DATE)
|| propDef.getDataType().getName().equals(DataTypeDefinition.DATETIME)
|| propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE)
|| propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT)
|| propDef.getDataType().getName().equals(DataTypeDefinition.INT)
|| propDef.getDataType().getName().equals(DataTypeDefinition.LONG)
|| propDef.getDataType().getName().equals(DataTypeDefinition.PATH)
)
{
result.setIsOrderable(true);
}
}
}
}
// MNT-9089 fix, set min/max values for numeric properties
// MNT-11304 fix, use default boundaries only for numeric types
if (result instanceof PropertyIntegerDefinitionImpl)
{
if (propDef.getDataType().getName().equals(DataTypeDefinition.INT))
{
((PropertyIntegerDefinitionImpl) result).setMinValue(BigInteger.valueOf(Integer.MIN_VALUE));
((PropertyIntegerDefinitionImpl) result).setMaxValue(BigInteger.valueOf(Integer.MAX_VALUE));
}
if (propDef.getDataType().getName().equals(DataTypeDefinition.LONG))
{
((PropertyIntegerDefinitionImpl) result).setMinValue(BigInteger.valueOf(Long.MIN_VALUE));
((PropertyIntegerDefinitionImpl) result).setMaxValue(BigInteger.valueOf(Long.MAX_VALUE));
}
}
// end MNT-9089
// constraints and choices
for (ConstraintDefinition constraintDef : propDef.getConstraints())
{
Constraint constraint = constraintDef.getConstraint();
if (constraint instanceof ListOfValuesConstraint)
{
addChoiceList((ListOfValuesConstraint) constraint, result);
}
if ((constraint instanceof StringLengthConstraint) && (result instanceof PropertyStringDefinitionImpl))
{
StringLengthConstraint slc = (StringLengthConstraint) constraint;
((PropertyStringDefinitionImpl) result).setMaxLength(BigInteger.valueOf(slc.getMaxLength()));
}
if (constraint instanceof NumericRangeConstraint)
{
NumericRangeConstraint nrc = (NumericRangeConstraint) constraint;
if (result instanceof PropertyIntegerDefinitionImpl)
{
((PropertyIntegerDefinitionImpl) result)
.setMinValue(BigInteger.valueOf(((Double) nrc.getMinValue()).longValue()));
((PropertyIntegerDefinitionImpl) result)
.setMaxValue(BigInteger.valueOf(((Double) nrc.getMaxValue()).longValue()));
}
if (result instanceof PropertyDecimalDefinitionImpl)
{
((PropertyDecimalDefinitionImpl) result).setMinValue(BigDecimal.valueOf(nrc.getMinValue()));
((PropertyDecimalDefinitionImpl) result).setMaxValue(BigDecimal.valueOf(nrc.getMaxValue()));
}
}
}
return result;
}
protected void createActionEvaluators(PropertyAccessorMapping propertyAccessorMapping, BaseTypeId baseTypeId)
{
if (propertyAccessorMapping != null)
{
actionEvaluators = propertyAccessorMapping.getActionEvaluators(baseTypeId);
} else
{
actionEvaluators = Collections.emptyMap();
}
}
@SuppressWarnings("unchecked")
private <T> T convertValueFromString(String value, PropertyType datatype)
{
if (value == null)
{
return null;
}
try
{
switch (datatype)
{
case BOOLEAN:
return (T) Boolean.valueOf(value);
case DATETIME:
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(ISO8601DateFormat.parse(value));
return (T) cal;
case DECIMAL:
return (T) new BigDecimal(value);
case HTML:
return (T) value;
case ID:
return (T) value;
case INTEGER:
return (T) new BigInteger(value);
case STRING:
return (T) value;
case URI:
return (T) value;
default: ;
}
}
catch (Exception e)
{
logger.error("Failed to convert value " + value + " to " + datatype, e);
return null;
}
throw new RuntimeException("Unknown datatype! Spec change?");
}
/**
* Adds the default value to a property definition.
*/
private void addDefaultValue(String value, PropertyDefinition<?> propDef)
{
if (value == null)
{
return;
}
if (propDef instanceof PropertyBooleanDefinitionImpl)
{
PropertyBooleanDefinitionImpl propDefImpl = (PropertyBooleanDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((Boolean) convertValueFromString(value,
PropertyType.BOOLEAN)));
} else if (propDef instanceof PropertyDateTimeDefinitionImpl)
{
PropertyDateTimeDefinitionImpl propDefImpl = (PropertyDateTimeDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((GregorianCalendar) convertValueFromString(value,
PropertyType.DATETIME)));
} else if (propDef instanceof PropertyDecimalDefinitionImpl)
{
PropertyDecimalDefinitionImpl propDefImpl = (PropertyDecimalDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((BigDecimal) convertValueFromString(value,
PropertyType.DECIMAL)));
} else if (propDef instanceof PropertyHtmlDefinitionImpl)
{
PropertyHtmlDefinitionImpl propDefImpl = (PropertyHtmlDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value,
PropertyType.HTML)));
} else if (propDef instanceof PropertyIdDefinitionImpl)
{
PropertyIdDefinitionImpl propDefImpl = (PropertyIdDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value,
PropertyType.ID)));
} else if (propDef instanceof PropertyIntegerDefinitionImpl)
{
PropertyIntegerDefinitionImpl propDefImpl = (PropertyIntegerDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((BigInteger) convertValueFromString(value,
PropertyType.INTEGER)));
} else if (propDef instanceof PropertyStringDefinitionImpl)
{
PropertyStringDefinitionImpl propDefImpl = (PropertyStringDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value,
PropertyType.STRING)));
} else if (propDef instanceof PropertyUriDefinitionImpl)
{
PropertyUriDefinitionImpl propDefImpl = (PropertyUriDefinitionImpl) propDef;
propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value,
PropertyType.URI)));
}
}
/**
* Adds choices to the property defintion.
*/
private void addChoiceList(ListOfValuesConstraint lovc, PropertyDefinition<?> propDef)
{
if (propDef instanceof PropertyBooleanDefinitionImpl)
{
PropertyBooleanDefinitionImpl propDefImpl = (PropertyBooleanDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<Boolean>> choiceList = new ArrayList<Choice<Boolean>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<Boolean> choice = new ChoiceImpl<Boolean>();
choice.setDisplayName(allowed);
choice.setValue(Collections.singletonList((Boolean) convertValueFromString(allowed,
PropertyType.BOOLEAN)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
} else if (propDef instanceof PropertyDateTimeDefinitionImpl)
{
PropertyDateTimeDefinitionImpl propDefImpl = (PropertyDateTimeDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<GregorianCalendar>> choiceList = new ArrayList<Choice<GregorianCalendar>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<GregorianCalendar> choice = new ChoiceImpl<GregorianCalendar>();
choice.setDisplayName(allowed);
choice.setValue(Collections.singletonList((GregorianCalendar) convertValueFromString(allowed,
PropertyType.DATETIME)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
} else if (propDef instanceof PropertyDecimalDefinitionImpl)
{
PropertyDecimalDefinitionImpl propDefImpl = (PropertyDecimalDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<BigDecimal>> choiceList = new ArrayList<Choice<BigDecimal>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<BigDecimal> choice = new ChoiceImpl<BigDecimal>();
choice.setDisplayName(allowed);
choice.setValue(Collections.singletonList((BigDecimal) convertValueFromString(allowed,
PropertyType.DECIMAL)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
} else if (propDef instanceof PropertyHtmlDefinitionImpl)
{
PropertyHtmlDefinitionImpl propDefImpl = (PropertyHtmlDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<String>> choiceList = new ArrayList<Choice<String>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<String> choice = new ChoiceImpl<String>();
choice.setDisplayName(allowed);
choice.setValue(Collections.singletonList((String) convertValueFromString(allowed, PropertyType.HTML)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
} else if (propDef instanceof PropertyIdDefinitionImpl)
{
PropertyIdDefinitionImpl propDefImpl = (PropertyIdDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<String>> choiceList = new ArrayList<Choice<String>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<String> choice = new ChoiceImpl<String>();
choice.setDisplayName(allowed);
choice.setValue(Collections.singletonList((String) convertValueFromString(allowed, PropertyType.ID)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
} else if (propDef instanceof PropertyIntegerDefinitionImpl)
{
PropertyIntegerDefinitionImpl propDefImpl = (PropertyIntegerDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<BigInteger>> choiceList = new ArrayList<Choice<BigInteger>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<BigInteger> choice = new ChoiceImpl<BigInteger>();
choice.setDisplayName(allowed);
choice.setValue(Collections.singletonList((BigInteger) convertValueFromString(allowed,
PropertyType.INTEGER)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
} else if (propDef instanceof PropertyStringDefinitionImpl)
{
PropertyStringDefinitionImpl propDefImpl = (PropertyStringDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<String>> choiceList = new ArrayList<Choice<String>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<String> choice = new ChoiceImpl<String>();
choice.setDisplayName(allowed);
choice.setValue(Collections
.singletonList((String) convertValueFromString(allowed, PropertyType.STRING)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
} else if (propDef instanceof PropertyUriDefinitionImpl)
{
PropertyUriDefinitionImpl propDefImpl = (PropertyUriDefinitionImpl) propDef;
propDefImpl.setIsOpenChoice(false);
List<Choice<String>> choiceList = new ArrayList<Choice<String>>();
for (String allowed : lovc.getAllowedValues())
{
ChoiceImpl<String> choice = new ChoiceImpl<String>();
choice.setDisplayName(allowed);
choice.setValue(Collections.singletonList((String) convertValueFromString(allowed, PropertyType.URI)));
choiceList.add(choice);
}
propDefImpl.setChoices(choiceList);
}
}
}

View File

@@ -0,0 +1,89 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.io.Serializable;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
public class BasePropertyDefintionWrapper implements PropertyDefinitionWrapper, Serializable
{
private static final long serialVersionUID = 1L;
private PropertyDefinition<?> propDef;
private QName alfrescoName;
private TypeDefinitionWrapper owningType;
private CMISPropertyAccessor accessor;
private CMISPropertyLuceneBuilder luceneBuilder;
public BasePropertyDefintionWrapper(PropertyDefinition<?> propDef, QName alfrescoName,
TypeDefinitionWrapper owningType, CMISPropertyAccessor accessor, CMISPropertyLuceneBuilder luceneBuilder)
{
this.propDef = propDef;
this.alfrescoName = alfrescoName;
this.owningType = owningType;
this.accessor = accessor;
this.luceneBuilder = luceneBuilder;
}
@Override
public PropertyDefinition<?> getPropertyDefinition()
{
return propDef;
}
@Override
public String getPropertyId()
{
return propDef.getId();
}
@Override
public QName getAlfrescoName()
{
return alfrescoName;
}
@Override
public TypeDefinitionWrapper getOwningType()
{
return owningType;
}
@Override
public CMISPropertyAccessor getPropertyAccessor()
{
return accessor;
}
@Override
public CMISPropertyLuceneBuilder getPropertyLuceneBuilder()
{
return luceneBuilder;
}
}

View File

@@ -0,0 +1,505 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.dictionary.CompiledModel;
import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.dictionary.ExtendedDictionaryListener;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.PropertyType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
/**
* Common CMIS Dictionary Support including registry of Types.
*
* @author davidc
* @author florian.mueller
*/
public abstract class CMISAbstractDictionaryService extends AbstractLifecycleBean implements CMISDictionaryService,
ExtendedDictionaryListener
{
// Logger
protected static final Log logger = LogFactory.getLog(CMISAbstractDictionaryService.class);
// service dependencies
protected DictionaryDAO dictionaryDAO;
protected DictionaryService dictionaryService;
protected CMISMapping cmisMapping;
protected PropertyAccessorMapping accessorMapping;
protected PropertyLuceneBuilderMapping luceneBuilderMapping;
protected TenantService tenantService;
private final ReentrantReadWriteLock registryLock = new ReentrantReadWriteLock();
private final WriteLock registryWriteLock = registryLock.writeLock();
private final ReadLock registryReadLock = registryLock.readLock();
// note: cache is tenant-aware (if using TransctionalCache impl)
private SimpleCache<String, CMISDictionaryRegistry> cmisRegistryCache;
private final String KEY_OPENCMIS_DICTIONARY_REGISTRY = "key.openCmisDictionaryRegistry";
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
/**
* Set the mapping service
*
* @param cmisMapping
* CMISMapping
*/
public void setCmisMapping(CMISMapping cmisMapping)
{
this.cmisMapping = cmisMapping;
}
/**
* Set the property accessor mapping service
*
* @param accessorMapping
* mapping
*/
public void setPropertyAccessorMapping(PropertyAccessorMapping accessorMapping)
{
this.accessorMapping = accessorMapping;
}
/**
* Set the property lucene mapping service
*
* @param luceneBuilderMapping
* mapping
*/
public void setPropertyLuceneBuilderMapping(PropertyLuceneBuilderMapping luceneBuilderMapping)
{
this.luceneBuilderMapping = luceneBuilderMapping;
}
/**
* Set the dictionary Service
*
* @param dictionaryService
* DictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Set the dictionary DAO
*
* @param dictionaryDAO
* DictionaryDAO
*/
public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
public void setSingletonCache(SimpleCache<String, CMISDictionaryRegistry> singletonCache)
{
this.cmisRegistryCache = singletonCache;
}
protected interface DictionaryInitializer
{
Collection<AbstractTypeDefinitionWrapper> createDefinitions(CMISDictionaryRegistry cmisRegistry);
Collection<AbstractTypeDefinitionWrapper> createDefinitions(CMISDictionaryRegistry cmisRegistry,
CompiledModel model);
}
protected abstract DictionaryInitializer getCoreDictionaryInitializer();
protected abstract DictionaryInitializer getTenantDictionaryInitializer();
protected CMISDictionaryRegistry getRegistry()
{
String tenant = TenantUtil.getCurrentDomain();
return getRegistry(tenant);
}
CMISDictionaryRegistry getRegistry(String tenant)
{
CMISDictionaryRegistry cmisRegistry = null;
String cacheKey = getCacheKey(tenant);
registryReadLock.lock();
try
{
cmisRegistry = cmisRegistryCache.get(cacheKey);
}
finally
{
registryReadLock.unlock();
}
if (cmisRegistry == null)
{
cmisRegistry = createDictionaryRegistry(tenant);
registryWriteLock.lock();
try
{
cmisRegistryCache.put(cacheKey, cmisRegistry);
}
finally
{
registryWriteLock.unlock();
}
}
return cmisRegistry;
}
/*
* (non-Javadoc)
*
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#
* onBootstrap (org.springframework.context.ApplicationEvent)
*/
@Override
protected void onBootstrap(ApplicationEvent event)
{
afterDictionaryInit();
// TODO revisit (for KS and/or 1.1)
if (dictionaryDAO != null)
{
dictionaryDAO.registerListener(this);
}
else
{
logger.error("DictionaryDAO is null - hence CMIS Dictionary not registered for updates");
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.extensions.surf.util.AbstractLifecycleBean#onShutdown
* (org.springframework.context.ApplicationEvent)
*/
@Override
protected void onShutdown(ApplicationEvent event)
{
}
private String getCacheKey()
{
String tenant = tenantService.getCurrentUserDomain();
return getCacheKey(tenant);
}
private String getCacheKey(String tenant)
{
String cacheKey = KEY_OPENCMIS_DICTIONARY_REGISTRY + "." + tenant + "."
+ cmisMapping.getCmisVersion().toString();
return cacheKey;
}
protected CMISDictionaryRegistry createCoreDictionaryRegistry()
{
CMISDictionaryRegistryImpl cmisRegistry = new CMISDictionaryRegistryImpl(this, cmisMapping, dictionaryService,
getCoreDictionaryInitializer());
cmisRegistry.init();
return cmisRegistry;
}
protected CMISDictionaryRegistry createTenantDictionaryRegistry(String tenant)
{
CMISDictionaryRegistryImpl cmisRegistry = new CMISDictionaryRegistryImpl(this, tenant, "", cmisMapping,
dictionaryService, getTenantDictionaryInitializer());
cmisRegistry.init();
return cmisRegistry;
}
protected CMISDictionaryRegistry createDictionaryRegistryWithWriteLock()
{
String tenant = TenantUtil.getCurrentDomain();
CMISDictionaryRegistry cmisRegistry = createDictionaryRegistry(tenant);
String cacheKey = getCacheKey(tenant);
registryWriteLock.lock();
try
{
// publish new registry
cmisRegistryCache.put(cacheKey, cmisRegistry);
}
finally
{
registryWriteLock.unlock();
}
return cmisRegistry;
}
protected CMISDictionaryRegistry createDictionaryRegistry(String tenant)
{
CMISDictionaryRegistry cmisRegistry = null;
if (tenant.equals(TenantService.DEFAULT_DOMAIN))
{
cmisRegistry = createCoreDictionaryRegistry();
}
else
{
cmisRegistry = createTenantDictionaryRegistry(tenant);
}
return cmisRegistry;
}
@Override
public TypeDefinitionWrapper findType(String typeId)
{
TypeDefinitionWrapper typeDef = getRegistry().getTypeDefByTypeId(typeId);
if (typeDef != null && typeDef.getTypeDefinition(false).getDisplayName() == null)
{
typeDef.updateDefinition(dictionaryService);
}
return typeDef;
}
@Override
public boolean isExcluded(QName qname)
{
return cmisMapping.isExcluded(qname);
}
@Override
public TypeDefinitionWrapper findTypeForClass(QName clazz, BaseTypeId... matchingScopes)
{
// searching for relationship
boolean scopeByRelationship = false;
for (BaseTypeId scope : matchingScopes)
{
if (scope == BaseTypeId.CMIS_RELATIONSHIP)
{
scopeByRelationship = true;
break;
}
}
// locate type in registry
clazz = cmisMapping.getCmisType(clazz);
TypeDefinitionWrapper typeDef = null;
if (scopeByRelationship)
{
typeDef = getRegistry().getAssocDefByQName(clazz);
}
else
{
typeDef = getRegistry().getTypeDefByQName(clazz);
if (typeDef == null)
{
typeDef = getRegistry().getAssocDefByQName(clazz);
}
}
// ensure matches one of provided matching scopes
TypeDefinitionWrapper matchingTypeDef = (matchingScopes.length == 0) ? typeDef : null;
if (typeDef != null)
{
for (BaseTypeId scope : matchingScopes)
{
if (typeDef.getBaseTypeId() == scope)
{
matchingTypeDef = typeDef;
break;
}
}
}
return matchingTypeDef;
}
@Override
public TypeDefinitionWrapper findNodeType(QName clazz)
{
return getRegistry().getTypeDefByQName(cmisMapping.getCmisType(clazz));
}
@Override
public TypeDefinitionWrapper findAssocType(QName clazz)
{
return getRegistry().getAssocDefByQName(cmisMapping.getCmisType(clazz));
}
@Override
public TypeDefinitionWrapper findTypeByQueryName(String queryName)
{
// ISO 9075 name look up should be lower case.
return getRegistry().getTypeDefByQueryName(ISO9075.lowerCaseEncodedSQL(queryName));
}
@Override
public PropertyDefinitionWrapper findProperty(String propId)
{
return getRegistry().getPropDefByPropId(propId);
}
@Override
public PropertyDefinitionWrapper findPropertyByQueryName(String queryName)
{
return getRegistry().getPropDefByQueryName(ISO9075.lowerCaseEncodedSQL(queryName));
}
@Override
public List<TypeDefinitionWrapper> getBaseTypes()
{
return getBaseTypes(true);
}
@Override
public List<TypeDefinitionWrapper> getBaseTypes(boolean includeParent)
{
List<TypeDefinitionWrapper> types = getRegistry().getBaseTypes(includeParent);
for (TypeDefinitionWrapper typeDef : types)
{
if (typeDef != null && typeDef.getTypeDefinition(false).getDisplayName() == null)
{
typeDef.updateDefinition(dictionaryService);
}
}
return Collections.unmodifiableList(types);
}
@Override
public List<TypeDefinitionWrapper> getAllTypes()
{
// TODO is there a way of not having to reconstruct this every time?
return Collections.unmodifiableList(new ArrayList<TypeDefinitionWrapper>(getRegistry().getTypeDefs()));
}
@Override
public List<TypeDefinitionWrapper> getAllTypes(boolean includeParent)
{
// TODO is there a way of not having to reconstruct this every time?
return Collections
.unmodifiableList(new ArrayList<TypeDefinitionWrapper>(getRegistry().getTypeDefs(includeParent)));
}
@Override
public PropertyType findDataType(QName dataType)
{
return cmisMapping.getDataType(dataType);
}
@Override
public QName findAlfrescoDataType(PropertyType propertyType)
{
return cmisMapping.getAlfrescoDataType(propertyType);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.dictionary.DictionaryListener#onInit()
*/
@Override
public void onDictionaryInit()
{
}
@Override
public void modelAdded(CompiledModel model, String tenantDomain)
{
getRegistry(tenantDomain).addModel(model);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.dictionary.DictionaryListener#afterInit()
*/
@Override
public void afterDictionaryInit()
{
createDictionaryRegistryWithWriteLock();
}
/*
* (non-Javadoc)
*
* @see
* org.alfresco.repo.dictionary.DictionaryListener#afterDictionaryDestroy()
*/
@Override
public void afterDictionaryDestroy()
{
registryWriteLock.lock();
try
{
String cacheKey = getCacheKey();
cmisRegistryCache.remove(cacheKey);
}
finally
{
registryWriteLock.unlock();
}
}
@Override
public List<TypeDefinitionWrapper> getChildren(String typeId)
{
List<TypeDefinitionWrapper> children = getRegistry().getChildren(typeId);
for (TypeDefinitionWrapper child : children)
{
if (child != null && child.getTypeDefinition(false).getDisplayName() == null)
{
child.updateDefinition(dictionaryService);
}
}
return children;
}
}

View File

@@ -0,0 +1,46 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import org.apache.chemistry.opencmis.commons.enums.Action;
public interface CMISActionEvaluator
{
/**
* Gets the CMIS Allowed Action
*
* @return Action
*/
public Action getAction();
/**
* Determines if an action is allowed on an object
*
* @param nodeInfo CMISNodeInfo
* @return boolean
*/
public boolean isAllowed(CMISNodeInfo nodeInfo);
}

View File

@@ -0,0 +1,63 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import java.util.List;
import org.alfresco.repo.dictionary.CompiledModel;
import org.alfresco.service.namespace.QName;
/**
*
* @author sglover
*
*/
public interface CMISDictionaryRegistry
{
TypeDefinitionWrapper getTypeDefByTypeId(String typeId);
TypeDefinitionWrapper getTypeDefByTypeId(String typeId, boolean includeParent);
TypeDefinitionWrapper getAssocDefByQName(QName qname);
TypeDefinitionWrapper getTypeDefByQueryName(Object queryName);
TypeDefinitionWrapper getTypeDefByQName(QName qname);
PropertyDefinitionWrapper getPropDefByPropId(String propId);
PropertyDefinitionWrapper getPropDefByQueryName(Object queryName);
List<TypeDefinitionWrapper> getBaseTypes();
List<TypeDefinitionWrapper> getBaseTypes(boolean includeParent);
Collection<AbstractTypeDefinitionWrapper> getTypeDefs();
Collection<AbstractTypeDefinitionWrapper> getTypeDefs(boolean includeParent);
Collection<AbstractTypeDefinitionWrapper> getAssocDefs();
Collection<AbstractTypeDefinitionWrapper> getAssocDefs(boolean includeParent);
void registerTypeDefinition(AbstractTypeDefinitionWrapper typeDef);
String getTenant();
List<TypeDefinitionWrapper> getChildren(String typeId);
void setChildren(String typeId, List<TypeDefinitionWrapper> children);
void addChild(String typeId, TypeDefinitionWrapper child);
void addModel(CompiledModel model);
void updateModel(CompiledModel model);
void removeModel(CompiledModel model);
}

View File

@@ -0,0 +1,537 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.alfresco.opencmis.dictionary.CMISAbstractDictionaryService.DictionaryInitializer;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.repo.dictionary.CompiledModel;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* CMIS Dictionary registry
*
* Index of CMIS Type Definitions
*
* @author sglover
*/
public class CMISDictionaryRegistryImpl implements CMISDictionaryRegistry
{
public static final String ALFRESCO_EXTENSION_NAMESPACE = "http://www.alfresco.org";
public static final String MANDATORY_ASPECTS = "mandatoryAspects";
public static final String MANDATORY_ASPECT = "mandatoryAspect";
// Logger
protected static final Log logger = LogFactory.getLog(CMISDictionaryRegistryImpl.class);
private CMISMapping cmisMapping;
private DictionaryService dictionaryService;
private String tenant;
protected CMISAbstractDictionaryService cmisDictionaryService;
private String parentTenant;
private DictionaryInitializer dictionaryInitializer;
// Type Definitions Index
private Map<QName, TypeDefinitionWrapper> typeDefsByQName = new HashMap<QName, TypeDefinitionWrapper>();
private Map<QName, AbstractTypeDefinitionWrapper> assocDefsByQName = new HashMap<QName, AbstractTypeDefinitionWrapper>();
private Map<String, AbstractTypeDefinitionWrapper> typeDefsByTypeId = new HashMap<String, AbstractTypeDefinitionWrapper>();
private Map<String, TypeDefinitionWrapper> typeDefsByQueryName = new HashMap<String, TypeDefinitionWrapper>();
private List<TypeDefinitionWrapper> baseTypes = new ArrayList<TypeDefinitionWrapper>();
private Map<String, PropertyDefinitionWrapper> propDefbyPropId = new HashMap<String, PropertyDefinitionWrapper>();
private Map<String, PropertyDefinitionWrapper> propDefbyQueryName = new HashMap<String, PropertyDefinitionWrapper>();
private Map<String, List<TypeDefinitionWrapper>> children = new HashMap<String, List<TypeDefinitionWrapper>>();
public CMISDictionaryRegistryImpl(CMISAbstractDictionaryService cmisDictionaryService, CMISMapping cmisMapping,
DictionaryService dictionaryService, DictionaryInitializer dictionaryInitializer)
{
this(cmisDictionaryService, "", null, cmisMapping, dictionaryService, dictionaryInitializer);
}
/*
* Testing only.
*/
CMISDictionaryRegistryImpl()
{
}
public CMISDictionaryRegistryImpl(CMISAbstractDictionaryService cmisDictionaryService, String tenant, String parentTenant,
CMISMapping cmisMapping, DictionaryService dictionaryService, DictionaryInitializer dictionaryInitializer)
{
this.cmisDictionaryService = cmisDictionaryService;
this.tenant = tenant;
this.parentTenant = parentTenant;
this.cmisMapping = cmisMapping;
this.dictionaryService = dictionaryService;
this.dictionaryInitializer = dictionaryInitializer;
}
protected CMISDictionaryRegistry getParent()
{
CMISDictionaryRegistry registry = null;
if(parentTenant != null)
{
return cmisDictionaryService.getRegistry(parentTenant);
}
return registry;
}
@Override
public String getTenant()
{
return tenant;
}
private List<TypeDefinitionWrapper> getChildrenImpl(String typeId)
{
return children.get(typeId);
}
@Override
public List<TypeDefinitionWrapper> getChildren(String typeId)
{
List<TypeDefinitionWrapper> ret = new LinkedList<>();
List<TypeDefinitionWrapper> children = getChildrenImpl(typeId);
if(children != null)
{
ret.addAll(children);
}
if(getParent() != null)
{
children = getParent().getChildren(typeId);
if(children != null)
{
ret.addAll(children);
}
}
return ret;
}
@Override
public void setChildren(String typeId, List<TypeDefinitionWrapper> children)
{
this.children.put(typeId, children);
}
@Override
public void addChild(String typeId, TypeDefinitionWrapper child)
{
List<TypeDefinitionWrapper> children = this.children.get(typeId);
if(children == null)
{
children = new LinkedList<TypeDefinitionWrapper>();
this.children.put(typeId, children);
}
children.add(child);
}
@Override
public TypeDefinitionWrapper getTypeDefByTypeId(String typeId)
{
return getTypeDefByTypeId(typeId, true);
}
@Override
public TypeDefinitionWrapper getTypeDefByTypeId(String typeId, boolean includeParent)
{
TypeDefinitionWrapper typeDef = typeDefsByTypeId.get(typeId);
if(typeDef == null && includeParent && getParent() != null)
{
typeDef = getParent().getTypeDefByTypeId(typeId);
}
return typeDef;
}
@Override
public TypeDefinitionWrapper getAssocDefByQName(QName qname)
{
TypeDefinitionWrapper typeDef = assocDefsByQName.get(qname);
if(typeDef == null && getParent() != null)
{
typeDef = getParent().getAssocDefByQName(qname);
}
return typeDef;
}
@Override
public TypeDefinitionWrapper getTypeDefByQueryName(Object queryName)
{
TypeDefinitionWrapper typeDef = typeDefsByQueryName.get(queryName);
if(typeDef == null && getParent() != null)
{
typeDef = getParent().getTypeDefByQueryName(queryName);
}
return typeDef;
}
@Override
public TypeDefinitionWrapper getTypeDefByQName(QName qname)
{
TypeDefinitionWrapper typeDef = typeDefsByQName.get(qname);
if(typeDef == null && getParent() != null)
{
typeDef = getParent().getTypeDefByQName(qname);
}
return typeDef;
}
@Override
public PropertyDefinitionWrapper getPropDefByPropId(String propId)
{
PropertyDefinitionWrapper propDef = propDefbyPropId.get(propId);
if(propDef == null && getParent() != null)
{
propDef = getParent().getPropDefByPropId(propId);
}
return propDef;
}
@Override
public PropertyDefinitionWrapper getPropDefByQueryName(Object queryName)
{
PropertyDefinitionWrapper propDef = propDefbyQueryName.get(queryName);
if(propDef == null && getParent() != null)
{
propDef = getParent().getPropDefByQueryName(queryName);
}
return propDef;
}
private Collection<AbstractTypeDefinitionWrapper> getTypeDefsImpl()
{
return typeDefsByTypeId.values();
}
@Override
public Collection<AbstractTypeDefinitionWrapper> getTypeDefs()
{
return getTypeDefs(true);
}
@Override
public Collection<AbstractTypeDefinitionWrapper> getTypeDefs(boolean includeParent)
{
Collection<AbstractTypeDefinitionWrapper> ret = new LinkedList<>();
ret.addAll(getTypeDefsImpl());
if(includeParent && getParent() != null)
{
ret.addAll(getParent().getTypeDefs());
}
return Collections.unmodifiableCollection(ret);
}
private Collection<AbstractTypeDefinitionWrapper> getAssocDefsImpl()
{
return assocDefsByQName.values();
}
@Override
public Collection<AbstractTypeDefinitionWrapper> getAssocDefs()
{
return getAssocDefs(true);
}
@Override
public Collection<AbstractTypeDefinitionWrapper> getAssocDefs(boolean includeParent)
{
Collection<AbstractTypeDefinitionWrapper> ret = new LinkedList<>();
ret.addAll(getAssocDefsImpl());
if(includeParent && getParent() != null)
{
ret.addAll(getParent().getAssocDefs());
}
return Collections.unmodifiableCollection(ret);
}
private void addTypeExtensions(TypeDefinitionWrapper td)
{
QName classQName = td.getAlfrescoClass();
ClassDefinition classDef = dictionaryService.getClass(classQName);
if(classDef != null)
{
// add mandatory/default aspects
List<AspectDefinition> defaultAspects = classDef.getDefaultAspects(true);
if(defaultAspects != null && defaultAspects.size() > 0)
{
List<CmisExtensionElement> mandatoryAspectsExtensions = new ArrayList<CmisExtensionElement>();
for(AspectDefinition aspectDef : defaultAspects)
{
QName aspectQName = aspectDef.getName();
TypeDefinitionWrapper aspectType = getTypeDefByQName(cmisMapping.getCmisType(aspectQName));
if (aspectType == null)
{
continue;
}
mandatoryAspectsExtensions.add(new CmisExtensionElementImpl(ALFRESCO_EXTENSION_NAMESPACE, MANDATORY_ASPECT, null, aspectType.getTypeId()));
}
if(!mandatoryAspectsExtensions.isEmpty())
{
td.getTypeDefinition(true).setExtensions(
Collections.singletonList((CmisExtensionElement) new CmisExtensionElementImpl(
ALFRESCO_EXTENSION_NAMESPACE, MANDATORY_ASPECTS, null, mandatoryAspectsExtensions)));
}
}
}
}
@Override
public void addModel(CompiledModel model)
{
Collection<AbstractTypeDefinitionWrapper> types = dictionaryInitializer.createDefinitions(this, model);
addTypes(types);
for(AbstractTypeDefinitionWrapper type : types)
{
type.resolveInheritance(cmisMapping, this, dictionaryService);
}
}
@Override
public void updateModel(CompiledModel model)
{
// TODO
}
@Override
public void removeModel(CompiledModel model)
{
// TODO
}
private void clear()
{
typeDefsByQName.clear();
assocDefsByQName.clear();
typeDefsByTypeId.clear();
typeDefsByQueryName.clear();
baseTypes.clear();
propDefbyPropId.clear();
propDefbyQueryName.clear();
children.clear();
}
private void addTypes(Collection<AbstractTypeDefinitionWrapper> types)
{
// phase 1: construct type definitions and link them together
for (AbstractTypeDefinitionWrapper objectTypeDef : types)
{
List<TypeDefinitionWrapper> children = objectTypeDef.connectParentAndSubTypes(cmisMapping, this, dictionaryService);
setChildren(objectTypeDef.getTypeId(), children);
}
// phase 2: register base types and inherit property definitions
for (AbstractTypeDefinitionWrapper typeDef : types)
{
if (typeDef.getTypeDefinition(false).getParentTypeId() == null ||
!tenant.equals(TenantService.DEFAULT_DOMAIN))
{
if(tenant.equals(TenantService.DEFAULT_DOMAIN))
{
baseTypes.add(typeDef);
}
typeDef.resolveInheritance(cmisMapping, this, dictionaryService);
}
}
// phase 3: register properties
for (AbstractTypeDefinitionWrapper typeDef : types)
{
registerPropertyDefinitions(typeDef);
}
// phase 4: assert valid
for (AbstractTypeDefinitionWrapper typeDef : types)
{
typeDef.assertComplete();
addTypeExtensions(typeDef);
}
}
public void init()
{
long start = System.currentTimeMillis();
if (logger.isDebugEnabled())
{
logger.debug("Creating type definitions...");
}
Collection<AbstractTypeDefinitionWrapper> types = dictionaryInitializer.createDefinitions(this);
addTypes(types);
long end = System.currentTimeMillis();
if (logger.isInfoEnabled())
{
logger.info("Initialized CMIS Dictionary " + cmisMapping.getCmisVersion() + " tenant " + tenant + " in " + (end - start) + "ms. Types:"
+ typeDefsByTypeId.size() + ", Base Types:" + baseTypes.size());
}
}
private List<TypeDefinitionWrapper> getBaseTypesImpl()
{
return baseTypes;
}
@Override
public List<TypeDefinitionWrapper> getBaseTypes()
{
return getBaseTypes(true);
}
@Override
public List<TypeDefinitionWrapper> getBaseTypes(boolean includeParent)
{
List<TypeDefinitionWrapper> ret = new LinkedList<TypeDefinitionWrapper>();
List<TypeDefinitionWrapper> baseTypes = getBaseTypesImpl();
if(baseTypes != null)
{
ret.addAll(baseTypes);
}
if(includeParent && getParent() != null)
{
baseTypes = getParent().getBaseTypes();
if(baseTypes != null)
{
ret.addAll(baseTypes);
}
}
return Collections.unmodifiableList(ret);
}
/**
* Register type definition.
*
* @param typeDef AbstractTypeDefinitionWrapper
*/
@Override
public void registerTypeDefinition(AbstractTypeDefinitionWrapper typeDef)
{
TypeDefinitionWrapper existingTypeDef = typeDefsByTypeId.get(typeDef.getTypeId());
if (existingTypeDef != null)
{
// throw new AlfrescoRuntimeException("Type " + typeDef.getTypeId() + " already registered");
if(logger.isWarnEnabled())
{
logger.warn("Type " + typeDef.getTypeId() + " already registered");
}
}
typeDefsByTypeId.put(typeDef.getTypeId(), typeDef);
QName typeQName = typeDef.getAlfrescoName();
if (typeQName != null)
{
if ((typeDef instanceof RelationshipTypeDefintionWrapper) && !typeDef.isBaseType())
{
assocDefsByQName.put(typeQName, typeDef);
} else
{
typeDefsByQName.put(typeQName, typeDef);
}
}
typeDefsByQueryName.put(typeDef.getTypeDefinition(false).getQueryName(), typeDef);
if (logger.isDebugEnabled())
{
logger.debug("Registered type " + typeDef.getTypeId() + " (scope=" + typeDef.getBaseTypeId() + ")");
logger.debug(" QName: " + typeDef.getAlfrescoName());
logger.debug(" Table: " + typeDef.getTypeDefinition(false).getQueryName());
logger.debug(" Action Evaluators: " + typeDef.getActionEvaluators().size());
}
}
/**
* Register property definitions.
*
* @param typeDef AbstractTypeDefinitionWrapper
*/
public void registerPropertyDefinitions(AbstractTypeDefinitionWrapper typeDef)
{
for (PropertyDefinitionWrapper propDef : typeDef.getProperties(false))
{
if (propDef.getPropertyDefinition().isInherited())
{
continue;
}
propDefbyPropId.put(propDef.getPropertyId(), propDef);
propDefbyQueryName.put(propDef.getPropertyDefinition().getQueryName(), propDef);
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("DictionaryRegistry[");
builder.append("Types=").append(typeDefsByTypeId.size()).append(", ");
builder.append("Base Types=").append(baseTypes.size()).append(", ");
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,103 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.List;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.PropertyType;
/**
* Service to query the CMIS meta model
*
* @author davidc
*/
public interface CMISDictionaryService
{
/**
* Find type for type id
*
* @param typeId String
* @return TypeDefinitionWrapper
*/
TypeDefinitionWrapper findType(String typeId);
List<TypeDefinitionWrapper> getChildren(String typeId);
/**
* Find type for Alfresco class name. Optionally, constrain match to one of
* specified CMIS scopes
*
* @param clazz QName
* @param matchingScopes BaseTypeId...
* @return TypeDefinitionWrapper
*/
TypeDefinitionWrapper findTypeForClass(QName clazz, BaseTypeId... matchingScopes);
TypeDefinitionWrapper findNodeType(QName clazz);
TypeDefinitionWrapper findAssocType(QName clazz);
PropertyDefinitionWrapper findProperty(String propId);
PropertyDefinitionWrapper findPropertyByQueryName(String queryName);
/**
* Find a type by its query name
*
* @param queryName String
* @return TypeDefinitionWrapper
*/
TypeDefinitionWrapper findTypeByQueryName(String queryName);
/**
* Get Base Types
*/
List<TypeDefinitionWrapper> getBaseTypes();
List<TypeDefinitionWrapper> getBaseTypes(boolean includeParent);
/**
* Get all Types
*
*/
List<TypeDefinitionWrapper> getAllTypes();
List<TypeDefinitionWrapper> getAllTypes(boolean includeParent);
/**
* Find data type
*
* @param dataType QName
* @return PropertyType
*/
PropertyType findDataType(QName dataType);
QName findAlfrescoDataType(PropertyType propertyType);
boolean isExcluded(QName qname);
}

View File

@@ -0,0 +1,104 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
public interface CMISNodeInfo
{
String getObjectId();
CMISObjectVariant getObjectVariant();
boolean isVariant(CMISObjectVariant var);
NodeRef getNodeRef();
String getCurrentNodeId();
NodeRef getCurrentNodeNodeRef();
String getCurrentObjectId();
boolean isCurrentVersion();
boolean isPWC();
boolean hasPWC();
boolean isVersion();
boolean isLatestVersion();
boolean isLatestMajorVersion();
boolean isMajorVersion();
String getVersionLabel();
String getCheckinComment();
AssociationRef getAssociationRef();
TypeDefinitionWrapper getType();
boolean isFolder();
boolean isRootFolder();
boolean isDocument();
boolean isRelationship();
boolean isItem();
String getName();
String getPath();
Serializable getCreationDate();
Serializable getModificationDate();
Serializable getPropertyValue(String id);
boolean containsPropertyValue(String id);
void putPropertyValue(String id, Serializable value);
List<CMISNodeInfo> getParents();
Map<QName, Serializable> getNodeProps();
Set<QName> getNodeAspects();
}

View File

@@ -0,0 +1,41 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
public enum CMISObjectVariant
{
INVALID_ID, // not a valid object id
NOT_EXISTING, // valid id but object doesn't exist
NOT_A_CMIS_OBJECT, // object is not mapped to CMIS
FOLDER, // object is a folder
ITEM, // object is an item
CURRENT_VERSION, // object is a document (current version)
VERSION, // object is a version (not updatable)
PWC, // object is a PWC
ASSOC, // object is a relationship
PERMISSION_DENIED
// user has no permissions
}

View File

@@ -0,0 +1,80 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.io.Serializable;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* CMIS Property Accessor (get and set property values)
*
* @author davidc
*/
public interface CMISPropertyAccessor
{
/**
* Get the CMIS Property Name
*
* @return String
*/
String getName();
/**
* Get the (directly) mapped Alfresco property (if a direct mapping exists)
*
* @return QName
*/
QName getMappedProperty();
/**
* Set the property value for a node
*
* @param nodeRef NodeRef
* @param value Serializable
*/
void setValue(NodeRef nodeRef, Serializable value);
/**
* Get the property value for a node or an association
*
* @param nodeInfo CMISNodeInfo
* @return Serializable
*/
Serializable getValue(CMISNodeInfo nodeInfo);
/**
* Creates a node info object form the given node ref.
*/
CMISNodeInfo createNodeInfo(NodeRef nodeRef);
/**
* Creates a node info object form the given association ref.
*/
CMISNodeInfo createNodeInfo(AssociationRef assocRef);
}

View File

@@ -0,0 +1,130 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.io.Serializable;
import java.util.Collection;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
/**
* Encapsulate the building of lucene queries for property predicates
*/
public interface CMISPropertyLuceneBuilder
{
/**
* @param value Serializable
* @param mode PredicateMode
* @param luceneFunction LuceneFunction
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E;
/**
* @param not Boolean
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E;
/**
* @param value Serializable
* @param mode PredicateMode
* @param luceneFunction LuceneFunction
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneGreaterThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E;
/**
* @param value Serializable
* @param mode PredicateMode
* @param luceneFunction LuceneFunction
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E;
/**
* @param not Boolean
* @param mode PredicateMode
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneIn(LuceneQueryParserAdaptor<Q, S, E> lqpa, Collection<Serializable> values, Boolean not, PredicateMode mode) throws E;
/**
* @param value PredicateMode
* @param mode PredicateMode
* @param luceneFunction LuceneFunction
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneInequality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E;
/**
* @param value Serializable
* @param mode PredicateMode
* @param luceneFunction LuceneFunction
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneLessThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E;
/**
* @param value Serializable
* @param mode PredicateMode
* @param luceneFunction LuceneFunction
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E;
/**
* @param value Serializable
* @param not Boolean
* @return the query - may be null if no query is required
* @throws E
*/
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, Boolean not) throws E;
/**
* @param lqpa TODO
* @return the sort field
* @throws E
*/
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa) throws E;
/**
* @return the field name
*
*/
public String getLuceneFieldName();
}

View File

@@ -0,0 +1,319 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import java.util.LinkedList;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.repo.dictionary.CompiledModel;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* CMIS Dictionary which provides Types that strictly conform to the CMIS
* specification.
*
* That is, only maps types to one of root Document, Folder, Relationship and
* Policy.
*
* And Item which is pretty much anything that is not a Document, Folder, Relationship or Policy.
*
* @author steveglover
* @author davidc
* @author mrogers
*/
public class CMISStrictDictionaryService extends CMISAbstractDictionaryService
{
private Log logger = LogFactory.getLog(CMISStrictDictionaryService.class);
public static final String DEFAULT = "DEFAULT_DICTIONARY";
private DictionaryInitializer coreDictionaryInitializer;
private DictionaryInitializer tenantDictionaryInitializer;
public void init()
{
this.coreDictionaryInitializer = new DictionaryInitializer()
{
@Override
public Collection<AbstractTypeDefinitionWrapper> createDefinitions(CMISDictionaryRegistry cmisRegistry)
{
Collection<AbstractTypeDefinitionWrapper> ret = new LinkedList<>();
ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllTypes(true)));
Collection<QName> assocQNames = dictionaryService.getAllAssociations(true);
// register base type
String typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, CMISMapping.RELATIONSHIP_QNAME);
ClassDefinition classDef = dictionaryService.getClass(CMISMapping.RELATIONSHIP_QNAME);
// from Thor
if (classDef == null)
{
if (assocQNames.size() != 0)
{
logger.warn("Unexpected - no class for "+CMISMapping.RELATIONSHIP_QNAME+" - cannot create assocDefs for: "+assocQNames);
}
}
else
{
RelationshipTypeDefintionWrapper objectTypeDef = new RelationshipTypeDefintionWrapper(cmisMapping,
accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef);
cmisRegistry.registerTypeDefinition(objectTypeDef);
ret.add(objectTypeDef);
ret.addAll(createAssocDefs(cmisRegistry, assocQNames));
}
ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllAspects(true)));
return ret;
}
@Override
public Collection<AbstractTypeDefinitionWrapper> createDefinitions(CMISDictionaryRegistry cmisRegistry,
CompiledModel model)
{
Collection<AbstractTypeDefinitionWrapper> ret = new LinkedList<>();
model.getClass(model.getTypes().iterator().next().getName());
for(TypeDefinition typeDef : model.getTypes())
{
QName classQName = typeDef.getName();
AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName);
if(objectTypeDef != null)
{
cmisRegistry.registerTypeDefinition(objectTypeDef);
ret.add(objectTypeDef);
}
}
for(AssociationDefinition assocDef : model.getAssociations())
{
QName classQName = assocDef.getName();
RelationshipTypeDefintionWrapper assocTypeDef = createAssocDef(classQName);
if(assocTypeDef != null)
{
cmisRegistry.registerTypeDefinition(assocTypeDef);
ret.add(assocTypeDef);
}
}
for(AspectDefinition aspectDef : model.getAspects())
{
QName classQName = aspectDef.getName();
AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName);
if(objectTypeDef != null)
{
cmisRegistry.registerTypeDefinition(objectTypeDef);
ret.add(objectTypeDef);
}
}
return ret;
}
};
this.tenantDictionaryInitializer = new DictionaryInitializer()
{
@Override
public Collection<AbstractTypeDefinitionWrapper> createDefinitions(CMISDictionaryRegistry cmisRegistry)
{
Collection<AbstractTypeDefinitionWrapper> ret = new LinkedList<>();
ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllTypes(false)));
ret.addAll(createAssocDefs(cmisRegistry, dictionaryService.getAllAssociations(false)));
ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllAspects(false)));
return ret;
}
@Override
public Collection<AbstractTypeDefinitionWrapper> createDefinitions(CMISDictionaryRegistry cmisRegistry,
CompiledModel model)
{
Collection<AbstractTypeDefinitionWrapper> ret = new LinkedList<>();
for(TypeDefinition typeDef : model.getTypes())
{
QName classQName = typeDef.getName();
AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName);
if(objectTypeDef != null)
{
cmisRegistry.registerTypeDefinition(objectTypeDef);
ret.add(objectTypeDef);
}
}
for(AssociationDefinition assocDef : model.getAssociations())
{
QName classQName = assocDef.getName();
RelationshipTypeDefintionWrapper assocTypeDef = createAssocDef(classQName);
if(assocTypeDef != null)
{
cmisRegistry.registerTypeDefinition(assocTypeDef);
ret.add(assocTypeDef);
}
}
for(AspectDefinition aspectDef : model.getAspects())
{
QName classQName = aspectDef.getName();
AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName);
if(objectTypeDef != null)
{
cmisRegistry.registerTypeDefinition(objectTypeDef);
ret.add(objectTypeDef);
}
}
return ret;
}
};
}
/**
* Create Type Definitions
*
* @param classQName QName
*/
private AbstractTypeDefinitionWrapper createTypeDef(QName classQName)
{
AbstractTypeDefinitionWrapper objectTypeDef = null;
// skip items that are remapped to CMIS model
if(!cmisMapping.isRemappedType(classQName))
{
// create appropriate kind of type definition
ClassDefinition classDef = dictionaryService.getClass(classQName);
String typeId = null;
if (cmisMapping.isValidCmisDocument(classQName))
{
typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, classQName);
objectTypeDef = new DocumentTypeDefinitionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef);
}
else if (cmisMapping.isValidCmisFolder(classQName))
{
typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_FOLDER, classQName);
objectTypeDef = new FolderTypeDefintionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef);
}
else if (cmisMapping.getCmisVersion().equals(CmisVersion.CMIS_1_1) && cmisMapping.isValidCmisSecondaryType(classQName))
{
typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_SECONDARY, classQName);
objectTypeDef = new SecondaryTypeDefinitionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef);
}
else if (cmisMapping.isValidCmisPolicy(classQName))
{
typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName);
objectTypeDef = new PolicyTypeDefintionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef);
}
else if (cmisMapping.isValidCmisItem(classQName))
{
typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_ITEM, classQName);
objectTypeDef = new ItemTypeDefinitionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef);
}
}
return objectTypeDef;
}
private Collection<AbstractTypeDefinitionWrapper> createTypeDefs(CMISDictionaryRegistry registry,
Collection<QName> classQNames)
{
Collection<AbstractTypeDefinitionWrapper> ret = new LinkedList<>();
for (QName classQName : classQNames)
{
AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName);
if (objectTypeDef != null)
{
registry.registerTypeDefinition(objectTypeDef);
ret.add(objectTypeDef);
}
}
return ret;
}
private RelationshipTypeDefintionWrapper createAssocDef(QName classQName)
{
RelationshipTypeDefintionWrapper assocTypeDef = null;
if(cmisMapping.isValidCmisRelationship(classQName))
{
// create appropriate kind of type definition
AssociationDefinition assocDef = dictionaryService.getAssociation(classQName);
String typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, classQName);
assocTypeDef = new RelationshipTypeDefintionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping,
typeId, dictionaryService, assocDef);
}
return assocTypeDef;
}
/**
* Create Relationship Definitions
*
* @param registry CMISDictionaryRegistry
* @param classQNames Collection<QName
*/
private Collection<RelationshipTypeDefintionWrapper> createAssocDefs(CMISDictionaryRegistry registry,
Collection<QName> classQNames)
{
Collection<RelationshipTypeDefintionWrapper> ret = new LinkedList<>();
// register all other relationships
for (QName classQName : classQNames)
{
RelationshipTypeDefintionWrapper assocTypeDef = createAssocDef(classQName);
if(assocTypeDef != null)
{
registry.registerTypeDefinition(assocTypeDef);
ret.add(assocTypeDef);
}
}
return ret;
}
@Override
protected DictionaryInitializer getCoreDictionaryInitializer()
{
return coreDictionaryInitializer;
}
@Override
protected DictionaryInitializer getTenantDictionaryInitializer()
{
return tenantDictionaryInitializer;
}
}

View File

@@ -0,0 +1,141 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import org.alfresco.opencmis.CMISUtils;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.ContentStreamAllowed;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.DocumentTypeDefinitionImpl;
public class DocumentTypeDefinitionWrapper extends ShadowTypeDefinitionWrapper
{
private static final long serialVersionUID = 1L;
private DocumentTypeDefinitionImpl typeDef;
private DocumentTypeDefinitionImpl typeDefInclProperties;
private DictionaryService dictionaryService;
public DocumentTypeDefinitionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping,
PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef)
{
this.dictionaryService = dictionaryService;
alfrescoName = cmisClassDef.getName();
alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName);
typeDef = new DocumentTypeDefinitionImpl();
typeDef.setBaseTypeId(BaseTypeId.CMIS_DOCUMENT);
typeDef.setId(typeId);
typeDef.setLocalName(alfrescoName.getLocalName());
typeDef.setLocalNamespace(alfrescoName.getNamespaceURI());
if (BaseTypeId.CMIS_DOCUMENT.value().equals(typeId))
{
typeDef.setQueryName(ISO9075.encodeSQL(typeId));
typeDef.setParentTypeId(null);
} else
{
typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName)));
QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName());
if (cmisMapping.isValidCmisDocument(parentQName))
{
typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, parentQName));
}
}
typeDef.setDisplayName(null);
typeDef.setDescription(null);
typeDef.setIsCreatable(true);
typeDef.setIsQueryable(true);
typeDef.setIsFulltextIndexed(true);
typeDef.setIsControllablePolicy(false);
typeDef.setIsControllableAcl(true);
typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery());
typeDef.setIsFileable(true);
typeDef.setContentStreamAllowed(ContentStreamAllowed.ALLOWED);
typeDef.setIsVersionable(true);
typeDefInclProperties = CMISUtils.copy(typeDef);
setTypeDefinition(typeDef, typeDefInclProperties);
createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef);
createActionEvaluators(accessorMapping, BaseTypeId.CMIS_DOCUMENT);
}
@Override
public void updateDefinition(DictionaryService dictionaryService)
{
TypeDefinition typeDef = dictionaryService.getType(alfrescoName);
if (typeDef != null)
{
setTypeDefDisplayName(typeDef.getTitle(dictionaryService));
setTypeDefDescription(typeDef.getDescription(dictionaryService));
}
else
{
super.updateDefinition(dictionaryService);
}
updateTypeDefInclProperties();
}
@Override
public PropertyDefinitionWrapper getPropertyById(String propertyId)
{
updateProperty(dictionaryService, propertiesById.get(propertyId));
return propertiesById.get(propertyId);
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties()
{
updateProperties(dictionaryService);
return propertiesById.values();
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties(boolean update)
{
if (update)
{
return getProperties();
}
else
{
return propertiesById.values();
}
}
}

View File

@@ -0,0 +1,93 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import org.alfresco.repo.dictionary.DictionaryComponent;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
/**
* A DictionaryComponent that uses a QNameFilter to constrain what is returned.
*
* @author Gethin James
*/
public class FilteredDictionaryComponent extends DictionaryComponent
{
QNameFilter filter;
@Override
public Collection<QName> getAllTypes()
{
return filter.filterQName(super.getAllTypes());
}
@Override
public Collection<QName> getSubTypes(QName superType, boolean follow)
{
return filter.filterQName(super.getSubTypes(superType, follow));
}
@Override
public Collection<QName> getAllAspects()
{
return filter.filterQName(super.getAllAspects());
}
@Override
public Collection<QName> getAllAssociations()
{
return filter.filterQName(super.getAllAssociations());
}
@Override
public Collection<QName> getSubAspects(QName superAspect, boolean follow)
{
return filter.filterQName(super.getSubAspects(superAspect, follow));
}
@Override
public TypeDefinition getType(QName name)
{
if (filter.isExcluded(name)) return null; //Don't return an excluded type
return super.getType(name);
}
@Override
public AspectDefinition getAspect(QName name)
{
if (filter.isExcluded(name)) return null; //Don't return an excluded type
return super.getAspect(name);
}
public void setFilter(QNameFilter filter)
{
this.filter = filter;
}
}

View File

@@ -0,0 +1,147 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import org.alfresco.model.ContentModel;
import org.alfresco.opencmis.CMISUtils;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.FolderTypeDefinitionImpl;
public class FolderTypeDefintionWrapper extends ShadowTypeDefinitionWrapper
{
private static final long serialVersionUID = 1L;
private FolderTypeDefinitionImpl typeDef;
private FolderTypeDefinitionImpl typeDefInclProperties;
private DictionaryService dictionaryService;
public FolderTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping,
PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef)
{
this.dictionaryService = dictionaryService;
alfrescoName = cmisClassDef.getName();
alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName);
typeDef = new FolderTypeDefinitionImpl();
typeDef.setBaseTypeId(BaseTypeId.CMIS_FOLDER);
typeDef.setId(typeId);
typeDef.setLocalName(alfrescoName.getLocalName());
typeDef.setLocalNamespace(alfrescoName.getNamespaceURI());
boolean isSystemFolder = false;
if (BaseTypeId.CMIS_FOLDER.value().equals(typeId))
{
typeDef.setQueryName(ISO9075.encodeSQL(typeId));
typeDef.setParentTypeId(null);
} else
{
typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName)));
QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName());
if (cmisMapping.isValidCmisFolder(parentQName))
{
typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_FOLDER, parentQName));
}
if (alfrescoName.equals(ContentModel.TYPE_SYSTEM_FOLDER)
|| cmisMapping.getDictionaryService().isSubClass(alfrescoName, ContentModel.TYPE_SYSTEM_FOLDER))
{
isSystemFolder = true;
}
}
typeDef.setDisplayName(null);
typeDef.setDescription(null);
typeDef.setIsCreatable(!isSystemFolder);
typeDef.setIsQueryable(true);
typeDef.setIsFulltextIndexed(true);
typeDef.setIsControllablePolicy(false);
typeDef.setIsControllableAcl(true);
typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery());
typeDef.setIsFileable(true);
typeDefInclProperties = CMISUtils.copy(typeDef);
setTypeDefinition(typeDef, typeDefInclProperties);
createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef);
createActionEvaluators(accessorMapping, BaseTypeId.CMIS_FOLDER);
}
@Override
public void updateDefinition(DictionaryService dictionaryService)
{
TypeDefinition typeDef = dictionaryService.getType(alfrescoName);
if (typeDef != null)
{
setTypeDefDisplayName(typeDef.getTitle(dictionaryService));
setTypeDefDescription(typeDef.getDescription(dictionaryService));
}
else
{
super.updateDefinition(dictionaryService);
}
updateTypeDefInclProperties();
}
@Override
public PropertyDefinitionWrapper getPropertyById(String propertyId)
{
updateProperty(dictionaryService, propertiesById.get(propertyId));
return propertiesById.get(propertyId);
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties()
{
updateProperties(dictionaryService);
return propertiesById.values();
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties(boolean update)
{
if (update)
{
return getProperties();
}
else
{
return propertiesById.values();
}
}
}

View File

@@ -0,0 +1,149 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import org.alfresco.opencmis.CMISUtils;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ItemTypeDefinitionImpl;
public class ItemTypeDefinitionWrapper extends ShadowTypeDefinitionWrapper
{
private static final long serialVersionUID = 1L;
private ItemTypeDefinitionImpl typeDef;
private ItemTypeDefinitionImpl typeDefInclProperties;
private DictionaryService dictionaryService;
public ItemTypeDefinitionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping,
PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef)
{
this.dictionaryService = dictionaryService;
alfrescoName = cmisClassDef.getName();
alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName);
typeDef = new ItemTypeDefinitionImpl();
typeDef.setBaseTypeId(BaseTypeId.CMIS_ITEM);
typeDef.setId(typeId);
typeDef.setLocalName(alfrescoName.getLocalName());
typeDef.setLocalNamespace(alfrescoName.getNamespaceURI());
if (BaseTypeId.CMIS_ITEM.value().equals(typeId) )
{
typeDef.setQueryName(ISO9075.encodeSQL(typeId));
typeDef.setParentTypeId(null);
}
else
{
typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName)));
QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName());
if(parentQName != null)
{
typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_ITEM, parentQName));
}
}
typeDef.setDisplayName(null);
typeDef.setDescription(null);
if (BaseTypeId.CMIS_ITEM.value().equals(typeId) )
{
typeDef.setIsCreatable(false); // cmis:item is abstract
// TEMP work around for select * from cmis:item which lists folders and files
typeDef.setIsQueryable(false);
}
else
{
typeDef.setIsCreatable(true);
typeDef.setIsQueryable(true);
}
typeDef.setIsFulltextIndexed(true);
typeDef.setIsControllablePolicy(true);
typeDef.setIsControllableAcl(true);
typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery());
typeDef.setIsFileable(false);
typeDefInclProperties = CMISUtils.copy(typeDef);
setTypeDefinition(typeDef, typeDefInclProperties);
createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef);
createActionEvaluators(accessorMapping, BaseTypeId.CMIS_ITEM);
}
@Override
public void updateDefinition(DictionaryService dictionaryService)
{
TypeDefinition typeDef = dictionaryService.getType(alfrescoName);
if (typeDef != null)
{
setTypeDefDisplayName(typeDef.getTitle(dictionaryService));
setTypeDefDescription(typeDef.getDescription(dictionaryService));
}
else
{
super.updateDefinition(dictionaryService);
}
updateTypeDefInclProperties();
}
@Override
public PropertyDefinitionWrapper getPropertyById(String propertyId)
{
updateProperty(dictionaryService, propertiesById.get(propertyId));
return propertiesById.get(propertyId);
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties()
{
updateProperties(dictionaryService);
return propertiesById.values();
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties(boolean update)
{
if (update)
{
return getProperties();
}
else
{
return propertiesById.values();
}
}
}

View File

@@ -0,0 +1,277 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.opencmis.CMISUtils;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PolicyTypeDefinitionImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class PolicyTypeDefintionWrapper extends AbstractTypeDefinitionWrapper
{
private static final long serialVersionUID = 1L;
// Logger
protected static final Log logger = LogFactory.getLog(PolicyTypeDefintionWrapper.class);
private PolicyTypeDefinitionImpl typeDef;
private PolicyTypeDefinitionImpl typeDefInclProperties;
private DictionaryService dictionaryService;
public PolicyTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping propertyAccessorMapping,
PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef)
{
this.dictionaryService = dictionaryService;
alfrescoName = cmisClassDef.getName();
alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName);
typeDef = new PolicyTypeDefinitionImpl();
typeDef.setBaseTypeId(BaseTypeId.CMIS_POLICY);
typeDef.setId(typeId);
typeDef.setLocalName(alfrescoName.getLocalName());
typeDef.setLocalNamespace(alfrescoName.getNamespaceURI());
if (BaseTypeId.CMIS_POLICY.value().equals(typeId))
{
typeDef.setQueryName(ISO9075.encodeSQL(typeId));
typeDef.setParentTypeId(null);
} else
{
typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName)));
QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName());
if (parentQName == null)
{
typeDef.setParentTypeId(cmisMapping.getCmisTypeId(CMISMapping.ASPECTS_QNAME));
} else if (cmisMapping.isValidCmisPolicy(parentQName))
{
typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_POLICY, parentQName));
} else
{
throw new IllegalStateException("The CMIS type model should ignore aspects that inherit from excluded aspects");
}
}
typeDef.setDisplayName(null);
typeDef.setDescription(null);
typeDef.setIsCreatable(false);
typeDef.setIsQueryable(true);
typeDef.setIsFulltextIndexed(true);
typeDef.setIsControllablePolicy(false);
typeDef.setIsControllableAcl(false);
typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery());
typeDef.setIsFileable(false);
typeDefInclProperties = CMISUtils.copy(typeDef);
setTypeDefinition(typeDef, typeDefInclProperties);
createOwningPropertyDefinitions(cmisMapping, propertyAccessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef);
createActionEvaluators(propertyAccessorMapping, BaseTypeId.CMIS_POLICY);
}
@Override
public List<TypeDefinitionWrapper> connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry,
DictionaryService dictionaryService)
{
String parentTypeId = typeDef.getParentTypeId();
// find parent
if (typeDef.getParentTypeId() != null)
{
parent = registry.getTypeDefByTypeId(parentTypeId);
// if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null)
// {
// // this is a tenant registry and the parent is not defined locally so add this type as a child of it
// registry.addChild(parent.getTypeId(), this);
// }
}
else
{
if (!isBaseType())
{
throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!");
}
parent = null;
}
// find children
Collection<QName> childrenNames = null;
if (isBaseType())
{
// add the "Aspects" type to the CMIS Policy type
childrenNames = new ArrayList<QName>();
childrenNames.add(CMISMapping.ASPECTS_QNAME);
}
else if (getAlfrescoName().equals(CMISMapping.ASPECTS_QNAME))
{
// add all root aspects to the "Aspects" type
childrenNames = new ArrayList<QName>();
String aspectsTypeId = cmisMapping.getCmisTypeId(CMISMapping.ASPECTS_QNAME);
for (AbstractTypeDefinitionWrapper tdw : registry.getTypeDefs(false))
{
// TypeDefinitionWrapper parent = tdw.getParent();
// if(tdw.getTenantId().equals(parent.getTenantId()))
// {
// type and parent in same tenant
// }
String parentId = tdw.getTypeDefinition(false).getParentTypeId();
if ((parentId != null) && parentId.equals(aspectsTypeId))
{
childrenNames.add(tdw.getAlfrescoName());
}
}
}
else
{
// add all non-root aspects in this tenant to their parent
childrenNames = dictionaryService.getSubAspects(cmisMapping.getAlfrescoClass(getAlfrescoName()), false);
}
List<TypeDefinitionWrapper> children = new LinkedList<TypeDefinitionWrapper>();
for (QName childName : childrenNames)
{
if (cmisMapping.isValidCmisPolicy(childName))
{
TypeDefinitionWrapper child = registry.getTypeDefByQName(childName);
if (child == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve sub type for type id " + childName
+ " for parent type " + getAlfrescoName() + "!");
}
children.add(child);
}
else
{
logger.info("Not a policy: " + childName);
}
}
return children;
// registry.setChildren(typeDef.getId(), children);
}
public void resolveInheritance(CMISMapping cmisMapping,
CMISDictionaryRegistry registry, DictionaryService dictionaryService)
{
PropertyDefinition<?> propertyDefintion;
if (parent != null)
{
for (PropertyDefinitionWrapper propDef : parent.getProperties(false))
{
if (propertiesById.containsKey(propDef.getPropertyId()))
{
continue;
}
org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty(
propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName());
propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(),
alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true);
if (propertyDefintion != null)
{
registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(),
propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder()));
}
}
}
List<TypeDefinitionWrapper> children = registry.getChildren(typeDef.getId());
for (TypeDefinitionWrapper child : children)
{
if (child instanceof AbstractTypeDefinitionWrapper)
{
((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry,
dictionaryService);
}
}
}
@Override
public void updateDefinition(DictionaryService dictionaryService)
{
AspectDefinition aspectDef = dictionaryService.getAspect(alfrescoName);
if (aspectDef != null)
{
setTypeDefDisplayName(aspectDef.getTitle(dictionaryService));
setTypeDefDescription(aspectDef.getDescription(dictionaryService));
}
else
{
super.updateDefinition(dictionaryService);
}
updateTypeDefInclProperties();
}
@Override
public PropertyDefinitionWrapper getPropertyById(String propertyId)
{
updateProperty(dictionaryService, propertiesById.get(propertyId));
return propertiesById.get(propertyId);
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties()
{
updateProperties(dictionaryService);
return propertiesById.values();
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties(boolean update)
{
if (update)
{
return getProperties();
}
else
{
return propertiesById.values();
}
}
}

View File

@@ -0,0 +1,65 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Map;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
/**
* Encapsulate the mapping of property to property accessor
*
* @author davidc
*/
public interface PropertyAccessorMapping
{
/**
* Gets a property accessor
*
* @param propertyId property id
* @return property accessor
*/
public CMISPropertyAccessor getPropertyAccessor(String propertyId);
/**
* Create a direct node property accessor
*
* @param propertyId property id
* @param propertyName node property name
* @return property accessor
*/
public CMISPropertyAccessor createDirectPropertyAccessor(String propertyId, QName propertyName);
/**
* Gets the Action Evaluators applicable for the given CMIS Scope
*
* @param scope BaseTypeId
*/
public Map<Action, CMISActionEvaluator> getActionEvaluators(BaseTypeId scope);
}

View File

@@ -0,0 +1,44 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
public interface PropertyDefinitionWrapper
{
PropertyDefinition<?> getPropertyDefinition();
String getPropertyId();
QName getAlfrescoName();
TypeDefinitionWrapper getOwningType();
CMISPropertyAccessor getPropertyAccessor();
CMISPropertyLuceneBuilder getPropertyLuceneBuilder();
}

View File

@@ -0,0 +1,52 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import org.alfresco.service.namespace.QName;
/**
* Encapsulate the mapping of property to lucene builder
*
* @author davidc
*/
public interface PropertyLuceneBuilderMapping
{
/**
* Gets a property lucene builder
*
* @param propertyId property id
* @return property builder
*/
public CMISPropertyLuceneBuilder getPropertyLuceneBuilder(String propertyId);
/**
* Create a direct node property lucene builder
*
* @param propertyName node property name
* @return property lucene builder
*/
public CMISPropertyLuceneBuilder createDirectPropertyLuceneBuilder(QName propertyName);
}

View File

@@ -0,0 +1,67 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import org.alfresco.service.namespace.QName;
/**
* Filters QNames and excludes any
* that are in a predefined list.
*
* @author steveglover
* @author Gethin James
*/
public interface QNameFilter
{
public static final String WILDCARD = "*";
/**
* Filters out any QName defined in the "excludedTypes" property
*
* @param typesToFilter - original list
* @return the filtered list
*/
Collection<QName> filterQName(Collection<QName> typesToFilter);
/**
* Indicates that this QName should be excluded.
* @param typeQName QName
* @return boolean true if it is excluded
*/
boolean isExcluded(QName typeQName);
/**
* Exclude the type
*
* @param typeQName the type to exclude
*
*/
void setExcluded(QName typeQName, boolean excluded);
void initFilter();
}

View File

@@ -0,0 +1,192 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.namespace.QName;
/**
* Filters a QName and excludes any
* that are defined using the excludedTypes parameter.
* The list of types can either be defined using a property name such as "cm:name" or with a wildcard: "cm:*"
* It validates the definitions against the DataDictionary.
*
* @author steveglover
* @author Gethin James
*/
public class QNameFilterImpl implements QNameFilter
{
private Map<QName, Boolean> excludedQNames;
private Set<String> excludedModels;
private List<String> excludedTypes;
/**
* Filters out any QName defined in the "excludedModels" property
*
* @param typesToFilter - original list
* @return the filtered list
*/
public Collection<QName> filterQName(Collection<QName> typesToFilter)
{
Collection<QName> filteredTypes = new ArrayList<QName>();
if (!excludedQNames.isEmpty() || !excludedModels.isEmpty())
{
//If we have a exclusion list then loop through and exclude models /types
//that are in this list.
for (QName classQName : typesToFilter)
{
if(!isExcluded(classQName))
// if (!excludedQNames.contains(classQName) && !excludedModels.contains(classQName.getNamespaceURI()))
{
//Not excluded so add it
filteredTypes.add(classQName);
}
}
}
else
{
filteredTypes = typesToFilter;
}
return filteredTypes;
}
/**
* Processes the user-defined list of types into valid QNames and models, it validates them
* against the dictionary and also supports wildcards
*/
protected void preprocessExcludedTypes(List<String> excludeTypeNames)
{
if (excludeTypeNames == null || excludeTypeNames.isEmpty()) return;
Map<QName, Boolean> qNamesToExclude = new HashMap<QName, Boolean>();
Set<String> modelsToExclude = new HashSet<String>();
for (String typeDefinition : excludeTypeNames)
{
final QName typeDef = QName.createQName(typeDefinition);
if (WILDCARD.equals(typeDef.getLocalName()))
{
modelsToExclude.add(typeDef.getNamespaceURI());
}
else
{
qNamesToExclude.put(typeDef, Boolean.TRUE); // valid so add it to the list
}
}
this.excludedModels = modelsToExclude;
this.excludedQNames = qNamesToExclude;
}
/**
* Indicates that this QName should be excluded.
* @param typeQName QName
* @return boolean true if it is excluded
*/
public boolean isExcluded(QName typeQName)
{
Boolean isExcluded = excludedQNames.get(typeQName);
return (isExcluded != null && isExcluded.booleanValue() || excludedModels.contains(typeQName.getNamespaceURI()));
}
@Override
public void initFilter()
{
if (excludedTypes == null || excludedTypes.isEmpty())
{
excludedTypes = listOfHardCodedExcludedTypes();
}
preprocessExcludedTypes(excludedTypes);
}
public void setExcludedTypes(List<String> excludedTypes)
{
this.excludedTypes = excludedTypes;
}
/**
* I don't like hard code values, but have been persuaded its less pain
* than having to keep a config file in sync with both sides of SOLR.
*
*/
public static List<String> listOfHardCodedExcludedTypes() {
List<String> hardCodeListOfTypes = new ArrayList<String>();
hardCodeListOfTypes.add("{http://www.alfresco.org/model/imap/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishingworkflow/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/twitter/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/slideshare/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/facebook/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/youtube/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/linkedin/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/flickr/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/transfer/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/emailserver/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/calendar}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/blogintegration/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/linksmodel/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/datalist/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/forum/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/cloud/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/bpm/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/invite/moderated/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/invite/nominated/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/cloud/resetpassword/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/cloud/siteinvitation/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/signup/selfsignup/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/versionstore/2.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/versionstore/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/action/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/application/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/rule/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/rendition/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/qshare/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/sync/1.0}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/content/1.0}thumbnailed");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/content/1.0}failedThumbnailSource");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/cmis/custom}*");
hardCodeListOfTypes.add("{http://www.alfresco.org/model/hybridworkflow/1.0}*");
return hardCodeListOfTypes;
}
@Override
public void setExcluded(QName typeQName, boolean excluded)
{
excludedQNames.put(typeQName, Boolean.valueOf(excluded));
}
}

View File

@@ -0,0 +1,272 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.opencmis.CMISUtils;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.RelationshipTypeDefinitionImpl;
public class RelationshipTypeDefintionWrapper extends AbstractTypeDefinitionWrapper
{
private static final long serialVersionUID = 1L;
private RelationshipTypeDefinitionImpl typeDef;
private RelationshipTypeDefinitionImpl typeDefInclProperties;
private DictionaryService dictionaryService;
public RelationshipTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping,
PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef)
{
this.dictionaryService = dictionaryService;
alfrescoName = cmisClassDef.getName();
alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName);
typeDef = new RelationshipTypeDefinitionImpl();
typeDef.setBaseTypeId(BaseTypeId.CMIS_RELATIONSHIP);
typeDef.setId(typeId);
typeDef.setLocalName(alfrescoName.getLocalName());
typeDef.setLocalNamespace(alfrescoName.getNamespaceURI());
if (BaseTypeId.CMIS_RELATIONSHIP.value().equals(typeId))
{
typeDef.setQueryName(ISO9075.encodeSQL(typeId));
typeDef.setParentTypeId(null);
typeDef.setIsCreatable(false);
} else
{
typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName)));
typeDef.setParentTypeId(BaseTypeId.CMIS_RELATIONSHIP.value());
typeDef.setIsCreatable(true);
}
typeDef.setDisplayName(null);
typeDef.setDescription(null);
typeDef.setIsQueryable(false);
typeDef.setIsFulltextIndexed(false);
typeDef.setIsControllablePolicy(false);
typeDef.setIsControllableAcl(false);
typeDef.setIsIncludedInSupertypeQuery(true);
typeDef.setIsFileable(false);
typeDefInclProperties = CMISUtils.copy(typeDef);
setTypeDefinition(typeDef, typeDefInclProperties);
createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef);
createActionEvaluators(accessorMapping, BaseTypeId.CMIS_RELATIONSHIP);
}
public RelationshipTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping,
PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, AssociationDefinition cmisAssocDef)
{
this.dictionaryService = dictionaryService;
alfrescoName = cmisAssocDef.getName();
alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName);
typeDef = new RelationshipTypeDefinitionImpl();
typeDef.setBaseTypeId(BaseTypeId.CMIS_RELATIONSHIP);
typeDef.setId(typeId);
typeDef.setLocalName(alfrescoName.getLocalName());
typeDef.setLocalNamespace(alfrescoName.getNamespaceURI());
typeDef.setQueryName(cmisMapping.buildPrefixEncodedString(alfrescoName));
typeDef.setParentTypeId(BaseTypeId.CMIS_RELATIONSHIP.value());
typeDef.setDisplayName(null);
typeDef.setDescription(null);
typeDef.setIsCreatable(true);
typeDef.setIsQueryable(false);
typeDef.setIsFulltextIndexed(false);
typeDef.setIsControllablePolicy(false);
typeDef.setIsControllableAcl(false);
typeDef.setIsIncludedInSupertypeQuery(true);
typeDef.setIsFileable(false);
ArrayList<String> both = new ArrayList<String>(2);
both.add(BaseTypeId.CMIS_DOCUMENT.value());
both.add(BaseTypeId.CMIS_FOLDER.value());
String sourceTypeId = cmisMapping.getCmisTypeId(cmisMapping
.getCmisType(cmisAssocDef.getSourceClass().getName()));
if (sourceTypeId != null)
{
typeDef.setAllowedSourceTypes(Collections.singletonList(sourceTypeId));
}
else
{
typeDef.setAllowedSourceTypes(both);
}
String targetTypeId = cmisMapping.getCmisTypeId(cmisMapping
.getCmisType(cmisAssocDef.getTargetClass().getName()));
if (targetTypeId != null)
{
typeDef.setAllowedTargetTypes(Collections.singletonList(targetTypeId));
}
else
{
typeDef.setAllowedTargetTypes(both);
}
typeDefInclProperties = CMISUtils.copy(typeDef);
setTypeDefinition(typeDef, typeDefInclProperties);
createActionEvaluators(accessorMapping, BaseTypeId.CMIS_RELATIONSHIP);
}
@Override
public List<TypeDefinitionWrapper> connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry,
DictionaryService dictionaryService)
{
String parentTypeId = typeDef.getParentTypeId();
// find parent
if (parentTypeId != null)
{
parent = registry.getTypeDefByTypeId(parentTypeId);
if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null)
{
// this is a tenant registry and the parent is not defined locally so add this type as a child of it
registry.addChild(parent.getTypeId(), this);
}
}
else
{
if (!isBaseType())
{
throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!");
}
parent = null;
}
// find children
List<TypeDefinitionWrapper> children = new LinkedList<TypeDefinitionWrapper>();
if (isBaseType())
{
for (TypeDefinitionWrapper child : registry.getAssocDefs())
{
children.add(child);
}
}
return children;
// registry.setChildren(typeDef.getId(), children);
}
public void resolveInheritance(CMISMapping cmisMapping, CMISDictionaryRegistry registry,
DictionaryService dictionaryService)
{
PropertyDefinition<?> propertyDefintion;
if (parent != null)
{
for (PropertyDefinitionWrapper propDef : parent.getProperties(false))
{
org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty(
propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName());
propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(),
alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true);
if (propertyDefintion != null)
{
registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(),
propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder()));
}
}
}
List<TypeDefinitionWrapper> children = registry.getChildren(typeDef.getId());
for (TypeDefinitionWrapper child : children)
{
if (child instanceof AbstractTypeDefinitionWrapper)
{
((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry, dictionaryService);
}
}
}
@Override
public void updateDefinition(DictionaryService dictionaryService)
{
AssociationDefinition assocDef = dictionaryService.getAssociation(alfrescoName);
if (assocDef != null)
{
setTypeDefDisplayName(assocDef.getTitle(dictionaryService));
setTypeDefDescription(assocDef.getDescription(dictionaryService));
}
else
{
super.updateDefinition(dictionaryService);
}
updateTypeDefInclProperties();
}
@Override
public PropertyDefinitionWrapper getPropertyById(String propertyId)
{
updateProperty(dictionaryService, propertiesById.get(propertyId));
return propertiesById.get(propertyId);
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties()
{
updateProperties(dictionaryService);
return propertiesById.values();
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties(boolean update)
{
if (update)
{
return getProperties();
}
else
{
return propertiesById.values();
}
}
}

View File

@@ -0,0 +1,272 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.opencmis.CMISUtils;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.SecondaryTypeDefinitionImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class SecondaryTypeDefinitionWrapper extends AbstractTypeDefinitionWrapper
{
private static final long serialVersionUID = 1L;
// Logger
protected static final Log logger = LogFactory.getLog(SecondaryTypeDefinitionWrapper.class);
private SecondaryTypeDefinitionImpl typeDef;
private SecondaryTypeDefinitionImpl typeDefInclProperties;
private DictionaryService dictionaryService;
public SecondaryTypeDefinitionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping propertyAccessorMapping,
PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef)
{
this.dictionaryService = dictionaryService;
alfrescoName = cmisClassDef.getName();
alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName);
typeDef = new SecondaryTypeDefinitionImpl();
typeDef.setBaseTypeId(BaseTypeId.CMIS_SECONDARY);
typeDef.setId(typeId);
typeDef.setLocalName(alfrescoName.getLocalName());
typeDef.setLocalNamespace(alfrescoName.getNamespaceURI());
if (BaseTypeId.CMIS_SECONDARY.value().equals(typeId))
{
typeDef.setQueryName(ISO9075.encodeSQL(typeId));
typeDef.setParentTypeId(null);
}
else
{
typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName)));
QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName());
if (parentQName == null)
{
typeDef.setParentTypeId(cmisMapping.getCmisTypeId(CMISMapping.SECONDARY_TYPES_QNAME));
} else if (cmisMapping.isValidCmisSecondaryType(parentQName))
{
typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_SECONDARY, parentQName));
} else
{
throw new IllegalStateException("The CMIS type model should ignore aspects that inherit from excluded aspects");
}
}
typeDef.setDisplayName(null);
typeDef.setDescription(null);
typeDef.setIsCreatable(false);
typeDef.setIsQueryable(true);
typeDef.setIsFulltextIndexed(true);
typeDef.setIsControllablePolicy(false);
typeDef.setIsControllableAcl(false);
typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery());
typeDef.setIsFileable(false);
typeDefInclProperties = CMISUtils.copy(typeDef);
setTypeDefinition(typeDef, typeDefInclProperties);
createOwningPropertyDefinitions(cmisMapping, propertyAccessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef);
createActionEvaluators(propertyAccessorMapping, BaseTypeId.CMIS_SECONDARY);
}
@Override
public List<TypeDefinitionWrapper> connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry,
DictionaryService dictionaryService)
{
String parentTypeId = typeDef.getParentTypeId();
// find parent
if (parentTypeId != null)
{
parent = registry.getTypeDefByTypeId(parentTypeId);
if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null)
{
// this is a tenant registry and the parent is not defined locally so add this type as a child of it
registry.addChild(parent.getTypeId(), this);
}
}
else
{
if (!isBaseType())
{
throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!");
}
parent = null;
}
// find children
// children = new ArrayList<TypeDefinitionWrapper>();
Collection<QName> childrenNames = null;
if (isBaseType())
{
// // add the "Aspects" type to the CMIS secondary type
// childrenNames = new ArrayList<QName>();
// childrenNames.add(CMISMapping.SECONDARY_TYPES_QNAME);
// } else if (getAlfrescoName().equals(CMISMapping.SECONDARY_TYPES_QNAME))
// {
// add all root aspects to the "Aspects" type
childrenNames = new ArrayList<QName>();
String aspectsTypeId = cmisMapping.getCmisTypeId(CMISMapping.SECONDARY_TYPES_QNAME);
for (AbstractTypeDefinitionWrapper tdw : registry.getTypeDefs())
{
String parentId = tdw.getTypeDefinition(false).getParentTypeId();
if ((parentId != null) && parentId.equals(aspectsTypeId))
{
childrenNames.add(tdw.getAlfrescoName());
}
}
} else
{
// add all non-root aspects to their parent
childrenNames = dictionaryService.getSubAspects(cmisMapping.getAlfrescoClass(getAlfrescoName()), false);
}
List<TypeDefinitionWrapper> children = new LinkedList<TypeDefinitionWrapper>();
for (QName childName : childrenNames)
{
if (cmisMapping.isValidCmisSecondaryType(childName))
{
TypeDefinitionWrapper child = registry.getTypeDefByQName(childName);
if (child == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve sub type for type id " + childName
+ " for parent type " + getAlfrescoName() + "!");
}
children.add(child);
}
else
{
logger.info("Not a secondary type: " + childName);
}
}
return children;
// registry.setChildren(typeDef.getId(), children);
}
public void resolveInheritance(CMISMapping cmisMapping,
CMISDictionaryRegistry registry, DictionaryService dictionaryService)
{
PropertyDefinition<?> propertyDefintion;
if (parent != null)
{
for (PropertyDefinitionWrapper propDef : parent.getProperties(false))
{
if (propertiesById.containsKey(propDef.getPropertyId()))
{
continue;
}
org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty(
propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName());
propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(),
alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true);
if (propertyDefintion != null)
{
registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(),
propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder()));
}
}
}
List<TypeDefinitionWrapper> children = registry.getChildren(typeDef.getId());
for (TypeDefinitionWrapper child : children)
{
if (child instanceof AbstractTypeDefinitionWrapper)
{
((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry,
dictionaryService);
}
}
}
@Override
public void updateDefinition(DictionaryService dictionaryService)
{
AspectDefinition aspectDef = dictionaryService.getAspect(alfrescoName);
if (aspectDef != null)
{
setTypeDefDisplayName(aspectDef.getTitle(dictionaryService));
setTypeDefDescription(aspectDef.getDescription(dictionaryService));
}
else
{
super.updateDefinition(dictionaryService);
}
updateTypeDefInclProperties();
}
@Override
public PropertyDefinitionWrapper getPropertyById(String propertyId)
{
updateProperty(dictionaryService, propertiesById.get(propertyId));
return propertiesById.get(propertyId);
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties()
{
updateProperties(dictionaryService);
return propertiesById.values();
}
@Override
public Collection<PropertyDefinitionWrapper> getProperties(boolean update)
{
if (update)
{
return getProperties();
}
else
{
return propertiesById.values();
}
}
}

View File

@@ -0,0 +1,137 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.opencmis.mapping.CMISMapping;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
public abstract class ShadowTypeDefinitionWrapper extends AbstractTypeDefinitionWrapper
{
private static final long serialVersionUID = 1L;
@Override
public List<TypeDefinitionWrapper> connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry,
DictionaryService dictionaryService)
{
String parentTypeId = typeDef.getParentTypeId();
// find parent
if (parentTypeId != null)
{
parent = registry.getTypeDefByTypeId(parentTypeId);
if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null)
{
// this is a tenant registry and the parent is not defined locally so add this type as a child of it
registry.addChild(parent.getTypeId(), this);
}
}
else
{
if (!isBaseType())
{
throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!");
}
parent = null;
}
// if(parent != null)
// {
// List<TypeDefinitionWrapper> children = new LinkedList<TypeDefinitionWrapper>();
// children.add(this);
// registry.setChildren(parent.getTypeId(), children);
// }
// find children
// children = new ArrayList<TypeDefinitionWrapper>();
List<TypeDefinitionWrapper> children = new LinkedList<TypeDefinitionWrapper>();
Collection<QName> childrenNames = dictionaryService.getSubTypes(cmisMapping.getAlfrescoClass(getAlfrescoName()),
false);
for (QName childName : childrenNames)
{
if (cmisMapping.isValidCmisObject(getBaseTypeId(), childName))
{
TypeDefinitionWrapper child = registry.getTypeDefByQName(childName);
if (child == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve sub type for type id " + childName
+ " for parent type " + getAlfrescoName() + "!");
}
children.add(child);
}
}
return children;
// registry.setChildren(typeDef.getId(), children);
}
public void resolveInheritance(CMISMapping cmisMapping,
CMISDictionaryRegistry registry, DictionaryService dictionaryService)
{
PropertyDefinition<?> propertyDefintion;
if (parent != null)
{
for (PropertyDefinitionWrapper propDef : parent.getProperties(false))
{
if (propertiesById.containsKey(propDef.getPropertyId()))
{
continue;
}
org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty(
propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName());
propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(),
alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true);
if (propertyDefintion != null)
{
registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(),
propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder()));
}
}
}
List<TypeDefinitionWrapper> children = registry.getChildren(typeDef.getId());
for (TypeDefinitionWrapper child : children)
{
if (child instanceof AbstractTypeDefinitionWrapper)
{
((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry,
dictionaryService);
}
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.dictionary;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
public interface TypeDefinitionWrapper
{
TypeDefinition getTypeDefinition(boolean includePropertyDefinitions);
String getTypeId();
BaseTypeId getBaseTypeId();
boolean isBaseType();
QName getAlfrescoName();
QName getAlfrescoClass();
String getTenantId();
TypeDefinitionWrapper getParent();
// List<TypeDefinitionWrapper> getChildren();
Collection<PropertyDefinitionWrapper> getProperties();
Collection<PropertyDefinitionWrapper> getProperties(boolean update);
PropertyDefinitionWrapper getPropertyById(String propertyId);
PropertyDefinitionWrapper getPropertyByQueryName(String queryName);
PropertyDefinitionWrapper getPropertyByQName(QName name);
Map<Action, CMISActionEvaluator> getActionEvaluators();
void updateDefinition(DictionaryService dictionaryService);
}

View File

@@ -0,0 +1,138 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import org.alfresco.repo.search.adaptor.lucene.AnalysisMode;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.namespace.QName;
/**
* Common support for lucene query building.
*
* @author davidc
*/
public abstract class AbstractSimpleLuceneBuilder extends BaseLuceneBuilder
{
/**
* Construct
*/
protected AbstractSimpleLuceneBuilder()
{
super();
}
protected abstract String getValueAsString(Serializable value);
protected String getRangeMax()
{
return "\uFFFF";
}
protected String getRangeMin()
{
return "\u0000";
}
protected abstract DataTypeDefinition getInDataType();
protected abstract QName getQNameForExists();
@Override
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
return lqpa.getFieldQuery(getLuceneFieldName(), getValueAsString(value), AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E
{
if (not)
{
return lqpa.getFieldQuery("ISNULL", getQNameForExists().toString(), AnalysisMode.DEFAULT, LuceneFunction.FIELD);
}
else
{
return lqpa.getFieldQuery("ISNOTNULL", getQNameForExists().toString(), AnalysisMode.DEFAULT, LuceneFunction.FIELD);
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(value);
return lqpa.getRangeQuery(field, stringValue, getRangeMax(), false, true, AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(value);
return lqpa.getRangeQuery(field, stringValue, getRangeMax(), true, true, AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(value);
return lqpa.getRangeQuery(field, getRangeMin(), stringValue, true, false, AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(value);
return lqpa.getRangeQuery(field, getRangeMin(), stringValue, true, true, AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, Boolean not) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(value);
Q q = lqpa.getLikeQuery(field, stringValue, AnalysisMode.IDENTIFIER);
if (not)
{
q = lqpa.getNegatedQuery(q);
}
return q;
}
@Override
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa) throws E
{
return getLuceneFieldName();
}
}

View File

@@ -0,0 +1,129 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import java.util.Collection;
import org.alfresco.opencmis.dictionary.CMISPropertyLuceneBuilder;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserExpressionAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
/**
* Base class for all property lucene builders
*
* @author davidc
*/
public class BaseLuceneBuilder implements CMISPropertyLuceneBuilder
{
/**
* Construct
*
*/
protected BaseLuceneBuilder()
{
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
throw new UnsupportedOperationException();
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E
{
throw new UnsupportedOperationException();
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
throw new UnsupportedOperationException();
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
throw new UnsupportedOperationException();
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneIn(LuceneQueryParserAdaptor<Q, S, E> lqpa, Collection<Serializable> values, Boolean not, PredicateMode mode) throws E
{
LuceneQueryParserExpressionAdaptor<Q, E> expressionAdaptor = lqpa.getExpressionAdaptor();
for(Serializable value : values)
{
expressionAdaptor.addOptional(buildLuceneEquality(lqpa, value, mode, LuceneFunction.FIELD));
}
if(not)
{
return expressionAdaptor.getNegatedQuery();
}
else
{
return expressionAdaptor.getQuery();
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneInequality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
return lqpa.getNegatedQuery(buildLuceneEquality(lqpa, value, mode, luceneFunction));
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
throw new UnsupportedOperationException();
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
throw new UnsupportedOperationException();
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, Boolean not) throws E
{
throw new UnsupportedOperationException();
}
@Override
public String getLuceneFieldName()
{
throw new UnsupportedOperationException();
}
@Override
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa) throws E
{
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,100 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import org.alfresco.opencmis.dictionary.CMISDictionaryService;
import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper;
import org.alfresco.repo.search.adaptor.lucene.AnalysisMode;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
/**
* Get the CMIS object type id property
*
* @author andyh
*/
public class BaseTypeIdLuceneBuilder extends BaseLuceneBuilder
{
private CMISDictionaryService dictionaryService;
/**
* Construct
*/
public BaseTypeIdLuceneBuilder(CMISDictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
return lqpa.getFieldQuery("TYPE", getType(getValueAsString(value)), AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E
{
if (not)
{
return lqpa.getMatchNoneQuery();
}
else
{
return lqpa.getMatchAllQuery();
}
}
private String getType(String tableName)
{
TypeDefinitionWrapper typeDef = dictionaryService.findTypeByQueryName(tableName);
if (typeDef == null)
{
throw new CmisInvalidArgumentException("Unknown type: " + tableName);
}
if(!typeDef.isBaseType())
{
throw new CmisInvalidArgumentException("Not a base type: " + tableName);
}
if(!typeDef.getTypeDefinition(false).isQueryable())
{
throw new CmisInvalidArgumentException("Type is not queryable: " + tableName);
}
return typeDef.getAlfrescoClass().toString();
}
private String getValueAsString(Serializable value)
{
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, value);
return asString;
}
}

View File

@@ -0,0 +1,860 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.opencmis.CMISAccessControlFormatEnum;
import org.alfresco.opencmis.dictionary.QNameFilter;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.PropertyType;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.springframework.beans.factory.InitializingBean;
/**
* CMIS <-> Alfresco mappings. It additionally excludes a list of QNames based
* on a user defined list
*
* @author andyh
*/
public class CMISMapping implements InitializingBean
{
/**
* The Alfresco CMIS Namespace
*/
public static String CMIS_MODEL_NS = "cmis";
public static String CMIS_MODEL_URI = "http://www.alfresco.org/model/cmis/1.0/cs01";
public static String CMIS_EXT_NS = "cmisext";
public static String CMIS_EXT_URI = "http://www.alfresco.org/model/cmis/1.0/cs01ext";
/**
* The Alfresco CMIS Model name.
*/
public static String CMIS_MODEL_NAME = "cmismodel";
/**
* The QName for the Alfresco CMIS Model.
*/
public static QName CMIS_MODEL_QNAME = QName.createQName(CMIS_MODEL_URI, CMIS_MODEL_NAME);
// CMIS Data Types
public static QName CMIS_DATATYPE_ID = QName.createQName(CMIS_MODEL_URI, "id");
public static QName CMIS_DATATYPE_URI = QName.createQName(CMIS_MODEL_URI, "uri");
public static QName CMIS_DATATYPE_XML = QName.createQName(CMIS_MODEL_URI, "xml");
public static QName CMIS_DATATYPE_HTML = QName.createQName(CMIS_MODEL_URI, "html");
// CMIS Types
public static QName OBJECT_QNAME = QName.createQName(CMIS_EXT_URI, "object");
public static QName DOCUMENT_QNAME = QName.createQName(CMIS_MODEL_URI, "document");
public static QName FOLDER_QNAME = QName.createQName(CMIS_MODEL_URI, "folder");
public static QName RELATIONSHIP_QNAME = QName.createQName(CMIS_MODEL_URI, "relationship");
public static QName POLICY_QNAME = QName.createQName(CMIS_MODEL_URI, "policy");
public static QName SECONDARY_TYPES_QNAME = QName.createQName(CMIS_MODEL_URI, "secondary"); // cmis 1.1
public static QName ASPECTS_QNAME = QName.createQName(CMIS_EXT_URI, "aspects"); // cmis 1.0
public static QName ITEM_QNAME = QName.createQName(CMIS_MODEL_URI, "item"); // cmis 1.1
// CMIS Internal Type Ids
public static String OBJECT_TYPE_ID = "cmisext:object";
/**
* Basic permissions.
*/
public static final String CMIS_READ = "cmis:read";
public static final String CMIS_WRITE = "cmis:write";
public static final String CMIS_ALL = "cmis:all";
// Service Dependencies
protected DictionaryService dictionaryService;
protected NamespaceService namespaceService;
// Mappings
private Map<QName, String> mapAlfrescoQNameToTypeId = new HashMap<QName, String>();
private Map<QName, QName> mapCmisQNameToAlfrescoQName = new HashMap<QName, QName>();
private Map<QName, QName> mapAlfrescoQNameToCmisQName = new HashMap<QName, QName>();
private Map<QName, PropertyType> mapAlfrescoToCmisDataType = new HashMap<QName, PropertyType>();
private Map<PropertyType, QName> mapCmisDataTypeToAlfresco = new HashMap<PropertyType, QName>();
private QNameFilter filter;
private CmisVersion cmisVersion;
public void setCmisVersion(CmisVersion cmisVersion)
{
this.cmisVersion = cmisVersion;
}
public CmisVersion getCmisVersion()
{
return cmisVersion;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet()
{
//
// Type Mappings
//
mapAlfrescoQNameToTypeId.put(OBJECT_QNAME, OBJECT_TYPE_ID);
mapAlfrescoQNameToTypeId.put(DOCUMENT_QNAME, BaseTypeId.CMIS_DOCUMENT.value());
mapAlfrescoQNameToTypeId.put(FOLDER_QNAME, BaseTypeId.CMIS_FOLDER.value());
mapAlfrescoQNameToTypeId.put(RELATIONSHIP_QNAME, BaseTypeId.CMIS_RELATIONSHIP.value());
mapAlfrescoQNameToTypeId.put(SECONDARY_TYPES_QNAME, BaseTypeId.CMIS_SECONDARY.value());
mapAlfrescoQNameToTypeId.put(ITEM_QNAME, BaseTypeId.CMIS_ITEM.value());
mapAlfrescoQNameToTypeId.put(POLICY_QNAME, BaseTypeId.CMIS_POLICY.value());
mapAlfrescoQNameToCmisQName.put(ContentModel.TYPE_CONTENT, DOCUMENT_QNAME);
mapAlfrescoQNameToCmisQName.put(ContentModel.TYPE_FOLDER, FOLDER_QNAME);
mapAlfrescoQNameToCmisQName.put(ContentModel.TYPE_BASE, ITEM_QNAME);
mapCmisQNameToAlfrescoQName.put(DOCUMENT_QNAME, ContentModel.TYPE_CONTENT);
mapCmisQNameToAlfrescoQName.put(FOLDER_QNAME, ContentModel.TYPE_FOLDER);
mapCmisQNameToAlfrescoQName.put(ITEM_QNAME, ContentModel.TYPE_BASE);
mapCmisQNameToAlfrescoQName.put(RELATIONSHIP_QNAME, null);
mapCmisQNameToAlfrescoQName.put(POLICY_QNAME, null);
//
// Data Type Mappings
//
mapAlfrescoToCmisDataType.put(DataTypeDefinition.ANY, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.ENCRYPTED, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.ASSOC_REF, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.BOOLEAN, PropertyType.BOOLEAN);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.CATEGORY, PropertyType.ID);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.CHILD_ASSOC_REF, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.CONTENT, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.DATE, PropertyType.DATETIME);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.DATETIME, PropertyType.DATETIME);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.DOUBLE, PropertyType.DECIMAL);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.FLOAT, PropertyType.DECIMAL);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.INT, PropertyType.INTEGER);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.LOCALE, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.PERIOD, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.LONG, PropertyType.INTEGER);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.MLTEXT, PropertyType.STRING);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.NODE_REF, PropertyType.ID);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.PATH, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.QNAME, null);
mapAlfrescoToCmisDataType.put(DataTypeDefinition.TEXT, PropertyType.STRING);
mapAlfrescoToCmisDataType.put(CMIS_DATATYPE_ID, PropertyType.ID);
mapAlfrescoToCmisDataType.put(CMIS_DATATYPE_URI, PropertyType.URI);
mapAlfrescoToCmisDataType.put(CMIS_DATATYPE_HTML, PropertyType.HTML);
mapCmisDataTypeToAlfresco.put(PropertyType.ID, DataTypeDefinition.TEXT);
mapCmisDataTypeToAlfresco.put(PropertyType.INTEGER, DataTypeDefinition.LONG);
mapCmisDataTypeToAlfresco.put(PropertyType.STRING, DataTypeDefinition.TEXT);
mapCmisDataTypeToAlfresco.put(PropertyType.DECIMAL, DataTypeDefinition.DOUBLE);
mapCmisDataTypeToAlfresco.put(PropertyType.BOOLEAN, DataTypeDefinition.BOOLEAN);
mapCmisDataTypeToAlfresco.put(PropertyType.DATETIME, DataTypeDefinition.DATETIME);
mapCmisDataTypeToAlfresco.put(PropertyType.URI, DataTypeDefinition.TEXT);
mapCmisDataTypeToAlfresco.put(PropertyType.HTML, DataTypeDefinition.TEXT);
}
public void setFilter(QNameFilter filter)
{
this.filter = filter;
}
/**
* @param dictionaryService dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @param namespaceService service
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @return namespaceService
*/
public NamespaceService getNamespaceService()
{
return namespaceService;
}
/**
* @return dictionaryService
*/
public DictionaryService getDictionaryService()
{
return dictionaryService;
}
/*
* Is the type excluded from the CMIS dictionary and therefore not visible to clients?
*/
public boolean isExcluded(QName typeQName)
{
boolean isExcluded = false;
// check for exclusion of the type and, if necessary, its parents
if(filter != null && typeQName != null)
{
isExcluded = filter.isExcluded(typeQName);
if(!isExcluded)
{
// check parent, if any
AspectDefinition aspectDef = dictionaryService.getAspect(typeQName);
QName parentType = null;
if(aspectDef != null)
{
parentType = aspectDef.getParentName();
}
else
{
TypeDefinition typeDef = dictionaryService.getType(typeQName);
if(typeDef != null)
{
parentType = typeDef.getParentName();
}
else
{
parentType = null;
}
}
if(parentType != null)
{
isExcluded = isExcluded(parentType);
}
}
filter.setExcluded(typeQName, Boolean.valueOf(isExcluded));
}
return isExcluded;
}
/**
* Gets the CMIS Type Id given the Alfresco QName for the type in any
* Alfresco model
*
* @param scope BaseTypeId
* @param typeQName QName
* @return String
*/
public String getCmisTypeId(BaseTypeId scope, QName typeQName)
{
String typeId = mapAlfrescoQNameToTypeId.get(typeQName);
if (typeId == null)
{
String p = null;
switch (scope)
{
case CMIS_DOCUMENT:
p = "D";
break;
case CMIS_FOLDER:
p = "F";
break;
case CMIS_RELATIONSHIP:
p = "R";
break;
case CMIS_SECONDARY:
p = "P";
break;
case CMIS_POLICY:
p = "P";
break;
case CMIS_ITEM:
p = "I";
break;
default:
throw new CmisRuntimeException("Invalid base type!");
}
return p + ":" + typeQName.toPrefixString(namespaceService);
}
else
{
return typeId;
}
}
public String getCmisTypeId(QName classQName)
{
if (classQName.equals(ContentModel.TYPE_CONTENT))
{
return getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, classQName);
}
if (classQName.equals(ContentModel.TYPE_FOLDER))
{
return getCmisTypeId(BaseTypeId.CMIS_FOLDER, classQName);
}
if (classQName.equals(CMISMapping.RELATIONSHIP_QNAME))
{
return getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, classQName);
}
if (classQName.equals(CMISMapping.POLICY_QNAME))
{
return getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName);
}
if (classQName.equals(CMISMapping.ASPECTS_QNAME))
{
return getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName);
}
if (isValidCmisDocument(classQName))
{
return getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, classQName);
}
if (isValidCmisFolder(classQName))
{
return getCmisTypeId(BaseTypeId.CMIS_FOLDER, classQName);
}
if (isValidCmisRelationship(classQName))
{
return getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, classQName);
}
if (cmisVersion.equals(CmisVersion.CMIS_1_1) && isValidCmisSecondaryType(classQName))
{
return getCmisTypeId(BaseTypeId.CMIS_SECONDARY, classQName);
}
if (cmisVersion.equals(CmisVersion.CMIS_1_1) && isValidCmisItem(classQName))
{
return getCmisTypeId(BaseTypeId.CMIS_ITEM, classQName);
}
if (cmisVersion.equals(CmisVersion.CMIS_1_0) && isValidCmisPolicy(classQName))
{
return getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName);
}
return null;
}
public String buildPrefixEncodedString(QName qname)
{
return qname.toPrefixString(namespaceService);
}
public QName getAlfrescoName(String typeId)
{
// Is it an Alfresco type id?
if (typeId.length() < 4 || typeId.charAt(1) != ':')
{
throw new CmisInvalidArgumentException("Malformed type id '" + typeId + "'");
}
return QName.createQName(typeId.substring(2), namespaceService);
}
public boolean isValidCmisObject(BaseTypeId scope, QName qname)
{
switch (scope)
{
case CMIS_DOCUMENT:
return isValidCmisDocument(qname);
case CMIS_FOLDER:
return isValidCmisFolder(qname);
case CMIS_POLICY:
return isValidCmisPolicy(qname);
case CMIS_RELATIONSHIP:
return isValidCmisRelationship(qname);
case CMIS_SECONDARY:
return isValidCmisSecondaryType(qname);
case CMIS_ITEM:
return isValidCmisItem(qname);
}
return false;
}
/**
* Is this a valid CMIS folder type?
*
* @param typeQName QName
* @return boolean
*/
public boolean isValidCmisFolder(QName typeQName)
{
if(isExcluded(typeQName))
{
return false;
}
if (typeQName == null)
{
return false;
}
if (typeQName.equals(FOLDER_QNAME))
{
return true;
}
if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_FOLDER))
{
if (typeQName.equals(ContentModel.TYPE_FOLDER))
{
return false;
} else
{
return true;
}
}
return false;
}
/**
* Is this a valid CMIS document type?
*
* @param typeQName QName
* @return boolean
*/
public boolean isValidCmisDocument(QName typeQName)
{
if(isExcluded(typeQName))
{
return false;
}
if (typeQName == null)
{
return false;
}
if (typeQName.equals(DOCUMENT_QNAME))
{
return true;
}
if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT))
{
if (typeQName.equals(ContentModel.TYPE_CONTENT))
{
return false;
} else
{
return true;
}
}
return false;
}
/**
* Is this a valid CMIS secondary type?
*
* @param typeQName QName
* @return boolean
*/
public boolean isValidCmisSecondaryType(QName typeQName)
{
if(isExcluded(typeQName))
{
return false;
}
if (typeQName == null)
{
return false;
}
if (typeQName.equals(SECONDARY_TYPES_QNAME))
{
return true;
}
AspectDefinition aspectDef = dictionaryService.getAspect(typeQName);
if (aspectDef == null)
{
return false;
}
// Anything derived from the aspects here would at some point have to linked up with an invalid parent so exclude these aspects
// AND any that are derived from them.
if ( dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_VERSIONABLE)
|| dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_AUDITABLE)
|| dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_REFERENCEABLE))
{
return false;
}
return true;
}
/**
* Is this a valid CMIS policy type?
*
* @param typeQName QName
* @return boolean
*/
public boolean isValidCmisPolicy(QName typeQName)
{ if (typeQName == null)
{
return false;
}
if (typeQName.equals(POLICY_QNAME))
{
return true;
}
if(cmisVersion.equals(CmisVersion.CMIS_1_0))
{
if (typeQName.equals(ASPECTS_QNAME))
{
return true;
}
AspectDefinition aspectDef = dictionaryService.getAspect(typeQName);
if (aspectDef == null)
{
return false;
}
// Anything derived from the aspects here would at some point have to linked up with an invalid parent so exclude these aspects
// AND any that are derived from them.
if ( dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_VERSIONABLE)
|| dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_AUDITABLE)
|| dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_REFERENCEABLE))
{
return false;
}
return true;
}
else
{
return false;
}
}
/**
* Is an association valid in CMIS? It must be a non-child relationship and
* the source and target must both be valid CMIS types.
*
* @param associationQName QName
* @return boolean
*/
public boolean isValidCmisRelationship(QName associationQName)
{
if (associationQName == null)
{
return false;
}
if (associationQName.equals(RELATIONSHIP_QNAME))
{
return true;
}
AssociationDefinition associationDefinition = dictionaryService.getAssociation(
associationQName);
if (associationDefinition == null)
{
return false;
}
if (associationDefinition.isChild())
{
return false;
}
if(!isValidCmisRelationshipEndPoint(associationDefinition.getTargetClass().getName()))
{
return false;
}
if(!isValidCmisRelationshipEndPoint(associationDefinition.getSourceClass().getName()))
{
return false;
}
return true;
}
public boolean isValidCmisRelationshipEndPoint(QName typeQName)
{
if(dictionaryService.getClass(typeQName).isAspect())
{
return true;
}
if (typeQName.equals(FOLDER_QNAME))
{
return true;
}
if (typeQName.equals(DOCUMENT_QNAME))
{
return true;
}
if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_BASE))
{
return true;
}
return false;
}
/**
* Is this a valid CMIS item type?
*
* @param typeQName QName
* @return boolean
*/
public boolean isValidCmisItem(QName typeQName)
{
if(isExcluded(typeQName))
{
return false;
}
if (typeQName == null)
{
return false;
}
if(typeQName.equals(ITEM_QNAME))
{
return true;
}
if(typeQName.equals(ContentModel.TYPE_BASE))
{
return false;
}
AspectDefinition aspectDef = dictionaryService.getAspect(typeQName);
if (aspectDef != null)
{
// aspects are not items - this stops warning from getType
return false;
}
TypeDefinition typeDef = dictionaryService.getType(typeQName);
if (typeDef == null)
{
// type does not exist
return false;
}
if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_BASE))
{
if(dictionaryService.isSubClass(typeQName, ContentModel.TYPE_FOLDER))
{
return false;
}
if(dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT))
{
return false;
}
return true;
}
return false;
}
/**
* Given an Alfresco model type map it to the appropriate type. Maps
* cm:folder and cm:content to the CMIS definitions
*/
public QName getCmisType(QName typeQName)
{
QName mapped = mapAlfrescoQNameToCmisQName.get(typeQName);
if (mapped != null)
{
return mapped;
}
return typeQName;
}
/**
* Is Alfresco Type mapped to an alternative CMIS Type?
*/
public boolean isRemappedType(QName typeQName)
{
return mapAlfrescoQNameToCmisQName.containsKey(typeQName);
}
/**
* Given a CMIS model type map it to the appropriate Alfresco type.
*
* @param cmisTypeQName QName
* @return QName
*/
public QName getAlfrescoClass(QName cmisTypeQName)
{
QName mapped = mapCmisQNameToAlfrescoQName.get(cmisTypeQName);
if (mapped != null)
{
return mapped;
}
return cmisTypeQName;
}
/**
* Get the CMIS property type for a property
*
* @param datatype DataTypeDefinition
* @return PropertyType
*/
public PropertyType getDataType(DataTypeDefinition datatype)
{
return getDataType(datatype.getName());
}
public PropertyType getDataType(QName dataType)
{
return mapAlfrescoToCmisDataType.get(dataType);
}
public QName getAlfrescoDataType(PropertyType propertyType)
{
return mapCmisDataTypeToAlfresco.get(propertyType);
}
/**
* @param propertyQName QName
* @return String
*/
public String getCmisPropertyId(QName propertyQName)
{
return propertyQName.toPrefixString(namespaceService);
}
public Collection<Pair<String, Boolean>> getReportedPermissions(String permission, Set<String> permissions,
boolean hasFull, boolean isDirect, CMISAccessControlFormatEnum format)
{
ArrayList<Pair<String, Boolean>> answer = new ArrayList<Pair<String, Boolean>>(20);
// indirect
if (hasFull)
{
answer.add(new Pair<String, Boolean>(CMIS_READ, false));
answer.add(new Pair<String, Boolean>(CMIS_WRITE, false));
answer.add(new Pair<String, Boolean>(CMIS_ALL, false));
}
for (String perm : permissions)
{
if (PermissionService.READ.equals(perm))
{
answer.add(new Pair<String, Boolean>(CMIS_READ, false));
} else if (PermissionService.WRITE.equals(perm))
{
answer.add(new Pair<String, Boolean>(CMIS_WRITE, false));
} else if (PermissionService.ALL_PERMISSIONS.equals(perm))
{
answer.add(new Pair<String, Boolean>(CMIS_READ, false));
answer.add(new Pair<String, Boolean>(CMIS_WRITE, false));
answer.add(new Pair<String, Boolean>(CMIS_ALL, false));
}
if (hasFull)
{
answer.add(new Pair<String, Boolean>(CMIS_READ, false));
answer.add(new Pair<String, Boolean>(CMIS_WRITE, false));
answer.add(new Pair<String, Boolean>(CMIS_ALL, false));
}
}
// permission
if (format == CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS)
{
if (PermissionService.READ.equals(permission))
{
answer.add(new Pair<String, Boolean>(CMIS_READ, false));
answer.add(new Pair<String, Boolean>(permission, isDirect));
} else if (PermissionService.WRITE.equals(permission))
{
answer.add(new Pair<String, Boolean>(CMIS_WRITE, false));
answer.add(new Pair<String, Boolean>(permission, isDirect));
} else if (PermissionService.ALL_PERMISSIONS.equals(permission))
{
answer.add(new Pair<String, Boolean>(CMIS_ALL, false));
answer.add(new Pair<String, Boolean>(permission, isDirect));
} else
{
answer.add(new Pair<String, Boolean>(permission, isDirect));
}
} else if (format == CMISAccessControlFormatEnum.CMIS_BASIC_PERMISSIONS)
{
if (PermissionService.READ.equals(permission))
{
answer.add(new Pair<String, Boolean>(CMIS_READ, isDirect));
} else if (PermissionService.WRITE.equals(permission))
{
answer.add(new Pair<String, Boolean>(CMIS_WRITE, isDirect));
} else if (PermissionService.ALL_PERMISSIONS.equals(permission))
{
answer.add(new Pair<String, Boolean>(CMIS_ALL, isDirect));
} else
{
// else nothing
}
}
return answer;
}
/**
* @param permission String
* @return permission to set
*/
public String getSetPermission(String permission)
{
if (permission.equals(CMIS_READ))
{
return PermissionService.READ;
} else if (permission.equals(CMIS_WRITE))
{
return PermissionService.WRITE;
} else if (permission.equals(CMIS_ALL))
{
return PermissionService.ALL_PERMISSIONS;
} else
{
return permission;
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
/**
* Lucene Builder for CMIS content stream length property
*
* @author andyh
*/
public class ContentStreamLengthLuceneBuilder extends AbstractSimpleLuceneBuilder
{
private DictionaryService dictionaryService;
/**
* Construct
*
* @param dictionaryService DictionaryService
*/
public ContentStreamLengthLuceneBuilder(DictionaryService dictionaryService)
{
super();
this.dictionaryService = dictionaryService;
}
@Override
public String getLuceneFieldName()
{
StringBuilder field = new StringBuilder(128);
field.append("@");
field.append(ContentModel.PROP_CONTENT);
field.append(".size");
return field.toString();
}
@Override
protected String getValueAsString(Serializable value)
{
Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.LONG), value);
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted);
return asString;
}
@Override
protected QName getQNameForExists()
{
return ContentModel.PROP_CONTENT;
}
@Override
protected DataTypeDefinition getInDataType()
{
return dictionaryService.getDataType(DataTypeDefinition.LONG);
}
}

View File

@@ -0,0 +1,85 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
/**
* Lucene Builder for CMIS content stream mimetype property
*
* @author andyh
*/
public class ContentStreamMimetypeLuceneBuilder extends AbstractSimpleLuceneBuilder
{
private DictionaryService dictionaryService;
/**
* Construct
*
* @param dictionaryService DictionaryService
*/
public ContentStreamMimetypeLuceneBuilder(DictionaryService dictionaryService)
{
super();
this.dictionaryService = dictionaryService;
}
@Override
public String getLuceneFieldName()
{
StringBuilder field = new StringBuilder(128);
field.append("@");
field.append(ContentModel.PROP_CONTENT);
field.append(".mimetype");
return field.toString();
}
@Override
protected String getValueAsString(Serializable value)
{
Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.TEXT), value);
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted);
return asString;
}
@Override
protected QName getQNameForExists()
{
return ContentModel.PROP_CONTENT;
}
@Override
protected DataTypeDefinition getInDataType()
{
return dictionaryService.getDataType(DataTypeDefinition.TEXT);
}
}

View File

@@ -0,0 +1,143 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
/**
* A simple 1-1 property lucene builder mapping from a CMIS property name to an alfresco property
*
* @author andyh
*/
public class DirectLuceneBuilder extends AbstractSimpleLuceneBuilder
{
private DictionaryService dictionaryService;
private QName alfrescoName;
public DirectLuceneBuilder(DictionaryService dictionaryService, QName alfrescoName)
{
this.dictionaryService = dictionaryService;
this.alfrescoName = alfrescoName;
}
@Override
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa) throws E
{
String field = getLuceneFieldName();
// need to find the real field to use
PropertyDefinition propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1)));
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
throw new CmisInvalidArgumentException("Order on content properties is not curently supported");
}
else if ((propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) || (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)))
{
field = lqpa.getSortField(field);
}
else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
{
field = lqpa.getDatetimeSortField(field, propertyDef);
}
return field;
}
@Override
public String getLuceneFieldName()
{
StringBuilder field = new StringBuilder(64);
field.append("@");
field.append(alfrescoName);
return field.toString();
}
@Override
protected String getValueAsString(Serializable value)
{
PropertyDefinition pd = dictionaryService.getProperty(alfrescoName);
Object converted = DefaultTypeConverter.INSTANCE.convert(pd.getDataType(), value);
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted);
return asString;
}
@Override
protected QName getQNameForExists()
{
return alfrescoName;
}
@Override
protected DataTypeDefinition getInDataType()
{
PropertyDefinition pd = dictionaryService.getProperty(alfrescoName);
return pd.getDataType();
}
@Override
protected String getRangeMax()
{
if(getInDataType().getName().equals(DataTypeDefinition.DATE))
{
return "MAX";
}
else if(getInDataType().getName().equals(DataTypeDefinition.DATETIME))
{
return "MAX";
}
else
{
return super.getRangeMax();
}
}
@Override
protected String getRangeMin()
{
if(getInDataType().getName().equals(DataTypeDefinition.DATE))
{
return "MIN";
}
else if(getInDataType().getName().equals(DataTypeDefinition.DATETIME))
{
return "MIN";
}
else
{
return super.getRangeMin();
}
}
}

View File

@@ -0,0 +1,269 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.SearchLanguageConversion;
/**
* Property lucene builder for fixed value mapping (eg to null, true, etc)
*
* @author andyh
*/
public class FixedValueLuceneBuilder extends BaseLuceneBuilder
{
private Serializable value;
/**
* Construct
*
* @param value Serializable
*/
public FixedValueLuceneBuilder(Serializable value)
{
super();
this.value = value;
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
if (EqualsHelper.nullSafeEquals(value, value))
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E
{
if (not)
{
if (value == null)
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
else
{
if (value == null)
{
return lqpa.getMatchNoneQuery();
}
else
{
return lqpa.getMatchAllQuery();
}
}
}
@Override
@SuppressWarnings("unchecked")
public <Q, S, E extends Throwable> Q buildLuceneGreaterThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
if (value instanceof Comparable)
{
Comparable<Serializable> comparable = (Comparable<Serializable>) value;
if (comparable.compareTo(value) > 0)
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
@SuppressWarnings("unchecked")
public <Q, S, E extends Throwable> Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
if (value instanceof Comparable)
{
Comparable<Serializable> comparable = (Comparable<Serializable>) value;
if (comparable.compareTo(value) >= 0)
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneIn(LuceneQueryParserAdaptor<Q, S, E> lqpa, Collection<Serializable> values, Boolean not, PredicateMode mode) throws E
{
boolean in = false;
for (Serializable value : values)
{
if (EqualsHelper.nullSafeEquals(value, value))
{
in = true;
break;
}
}
if (in == !not)
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneInequality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
if (!EqualsHelper.nullSafeEquals(value, value))
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
@SuppressWarnings("unchecked")
public <Q, S, E extends Throwable> Q buildLuceneLessThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
if (value instanceof Comparable)
{
Comparable<Serializable> comparable = (Comparable<Serializable>) value;
if (comparable.compareTo(value) < 0)
{
return lqpa.getMatchAllQuery(); }
else
{
return lqpa.getMatchNoneQuery();
}
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
@SuppressWarnings("unchecked")
public <Q, S, E extends Throwable> Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
if (value instanceof Comparable)
{
Comparable<Serializable> comparable = (Comparable<Serializable>) value;
if (comparable.compareTo(value) <= 0)
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, Boolean not) throws E
{
if (value != null)
{
boolean matches = false;
Object converted = DefaultTypeConverter.INSTANCE.convert(value.getClass(), value);
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted);
String regExpression = SearchLanguageConversion.convertSQLLikeToRegex(asString);
Pattern pattern = Pattern.compile(regExpression);
String target = DefaultTypeConverter.INSTANCE.convert(String.class, value);
Matcher matcher = pattern.matcher(target);
if (matcher.matches())
{
matches = true;
}
if (matches == !not)
{
return lqpa.getMatchAllQuery();
}
else
{
return lqpa.getMatchNoneQuery();
}
}
else
{
return lqpa.getMatchNoneQuery();
}
}
@Override
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa)
{
throw new UnsupportedOperationException();
}
@Override
public String getLuceneFieldName()
{
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,42 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
/**
* Lucene Builder for properties which do not support query
*
* @author davidc
*/
public class NotSupportedLuceneBuilder extends BaseLuceneBuilder
{
/**
* Construct
*/
public NotSupportedLuceneBuilder()
{
}
}

View File

@@ -0,0 +1,168 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import java.util.ArrayList;
import org.alfresco.repo.search.adaptor.lucene.AnalysisMode;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
/**
* Lucene Builder for CMIS object id property.
*
* @author andyh
* @author dward
*/
public class ObjectIdLuceneBuilder extends BaseLuceneBuilder
{
private DictionaryService dictionaryService;
/**
* Construct
*
* @param dictionaryService DictionaryService
*/
public ObjectIdLuceneBuilder(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
@Override
public String getLuceneFieldName()
{
return "ID";
}
private <Q, S, E extends Throwable> StoreRef getStore(LuceneQueryParserAdaptor<Q, S, E> lqpa)
{
ArrayList<StoreRef> stores = lqpa.getSearchParameters().getStores();
if(stores.size() < 1)
{
// default
return StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
}
return stores.get(0);
}
private <Q, S, E extends Throwable> String getValueAsString(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value)
{
String nodeRefStr = null;
if(!NodeRef.isNodeRef((String)value))
{
// assume the object id is the node guid
StoreRef storeRef = getStore(lqpa);
nodeRefStr = storeRef.toString() + "/" + (String)value;
}
else
{
nodeRefStr = (String)value;
}
Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.NODE_REF), nodeRefStr);
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted);
return asString;
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(lqpa, value);
return lqpa.getIdentifierQuery(field, stringValue, AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E
{
if (not)
{
return lqpa.getMatchNoneQuery();
} else
{
return lqpa.getMatchAllQuery();
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID + " can not be used in a 'greater than' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID
+ " can not be used in a 'greater than or equals' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID + " can not be used in a 'less than' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID + " can not be used in a 'less than or equals' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, Boolean not) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(lqpa, value);
Q q = lqpa.getIdentifieLikeQuery(field, stringValue, AnalysisMode.IDENTIFIER);
if(not)
{
q = lqpa.getNegatedQuery(q);
}
return q;
}
@Override
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa)
{
return getLuceneFieldName();
}
}

View File

@@ -0,0 +1,154 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import org.alfresco.opencmis.dictionary.CMISDictionaryService;
import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper;
import org.alfresco.repo.search.adaptor.lucene.AnalysisMode;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
/**
* Lucene Builder for CMIS object type id property
*
* @author andyh
*/
public class ObjectTypeIdLuceneBuilder extends BaseLuceneBuilder
{
private CMISDictionaryService cmisDictionaryService;
/**
* Construct
*
* @param cmisDictionaryService CMISDictionaryService
*/
public ObjectTypeIdLuceneBuilder(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
@Override
public String getLuceneFieldName()
{
return "EXACTTYPE";
}
private String getValueAsString(Serializable value)
{
// Object converted =
// DefaultTypeConverter.INSTANCE.convert(getServiceRegistry().getDictionaryService().getDataType(DataTypeDefinition.QNAME),
// value);
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, value);
return asString;
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(value);
TypeDefinitionWrapper type = cmisDictionaryService.findType(stringValue);
return lqpa
.getFieldQuery(field, type.getAlfrescoClass().toString(), AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E
{
if (not)
{
return lqpa.getMatchNoneQuery();
} else
{
return lqpa.getMatchAllQuery();
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID + " can not be used in a 'greater than' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID
+ " can not be used in a 'greater than or equals' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneInequality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
return lqpa.getNegatedQuery(buildLuceneEquality(lqpa, value, mode, luceneFunction));
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID + " can not be used in a 'less than' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID + " can not be used in a 'less than or equals' comparison");
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, Boolean not) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(value);
TypeDefinitionWrapper type = cmisDictionaryService.findType(stringValue);
String typeQName = type.getAlfrescoClass().toString();
Q q = lqpa.getLikeQuery(field, typeQName, AnalysisMode.IDENTIFIER);
if (not)
{
q = lqpa.getNegatedQuery(q);
}
return q;
}
@Override
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa)
{
return getLuceneFieldName();
}
}

View File

@@ -0,0 +1,135 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.io.Serializable;
import java.util.ArrayList;
import org.alfresco.repo.search.adaptor.lucene.AnalysisMode;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
/**
* Lucene Builder for CMIS parent property
*
* @author andyh
*
*/
public class ParentLuceneBuilder extends BaseLuceneBuilder
{
private DictionaryService dictionaryService;
/**
* Construct
*
* @param dictionaryService DictionaryService
*/
public ParentLuceneBuilder(DictionaryService dictionaryService)
{
super();
this.dictionaryService = dictionaryService;
}
private <Q, S, E extends Throwable> StoreRef getStore(LuceneQueryParserAdaptor<Q, S, E> lqpa)
{
ArrayList<StoreRef> stores = lqpa.getSearchParameters().getStores();
if(stores.size() < 1)
{
// default
return StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
}
return stores.get(0);
}
@Override
public String getLuceneFieldName()
{
return "PARENT";
}
private <Q, S, E extends Throwable> String getValueAsString(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value)
{
String nodeRefStr = (String)value;
if(!NodeRef.isNodeRef((String)value))
{
// assume the value (object id) is the node guid
StoreRef storeRef = getStore(lqpa);
nodeRefStr = storeRef.toString() + "/" + (String)value;
}
Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.NODE_REF), nodeRefStr);
String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted);
return asString;
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, PredicateMode mode,
LuceneFunction luceneFunction) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(lqpa, value);
return lqpa.getFieldQuery(field, stringValue, AnalysisMode.IDENTIFIER, luceneFunction);
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, Boolean not) throws E
{
if (not)
{
return lqpa.getFieldQuery("ISROOT", "T", AnalysisMode.IDENTIFIER, LuceneFunction.FIELD);
} else
{
return lqpa.getNegatedQuery(lqpa.getFieldQuery("ISROOT", "T", AnalysisMode.IDENTIFIER, LuceneFunction.FIELD));
}
}
@Override
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, Serializable value, Boolean not) throws E
{
String field = getLuceneFieldName();
String stringValue = getValueAsString(lqpa, value);
Q q = lqpa.getLikeQuery(field, stringValue, AnalysisMode.IDENTIFIER);
if (not)
{
return lqpa.getNegatedQuery(q);
}
return q;
}
@Override
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa)
{
return getLuceneFieldName();
}
}

View File

@@ -0,0 +1,127 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.mapping;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.opencmis.dictionary.CMISDictionaryService;
import org.alfresco.opencmis.dictionary.CMISPropertyLuceneBuilder;
import org.alfresco.opencmis.dictionary.PropertyLuceneBuilderMapping;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.springframework.beans.factory.InitializingBean;
/**
* Lucene Builder mappings for built-in CMIS properties
*
* @author davidc
*/
public class RuntimePropertyLuceneBuilderMapping implements PropertyLuceneBuilderMapping, InitializingBean
{
private CMISDictionaryService cmisDictionaryService;
private DictionaryService dictionaryService;
private Map<String, CMISPropertyLuceneBuilder> luceneBuilders = new HashMap<String, CMISPropertyLuceneBuilder>();
/**
* @param cmisDictionaryService cmisDictionaryService
*/
public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
/**
* @param dictionaryService dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
@Override
public void afterPropertiesSet()
{
registerPropertyLuceneBuilder(PropertyIds.OBJECT_ID, new ObjectIdLuceneBuilder(dictionaryService));
registerPropertyLuceneBuilder(PropertyIds.OBJECT_TYPE_ID, new ObjectTypeIdLuceneBuilder(cmisDictionaryService));
registerPropertyLuceneBuilder(PropertyIds.BASE_TYPE_ID, new BaseTypeIdLuceneBuilder(cmisDictionaryService));
registerPropertyLuceneBuilder(PropertyIds.CREATED_BY, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_CREATOR));
registerPropertyLuceneBuilder(PropertyIds.CREATION_DATE, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_CREATED));
registerPropertyLuceneBuilder(PropertyIds.LAST_MODIFIED_BY, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_MODIFIER));
registerPropertyLuceneBuilder(PropertyIds.LAST_MODIFICATION_DATE, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_MODIFIED));
registerPropertyLuceneBuilder(PropertyIds.CHANGE_TOKEN, new FixedValueLuceneBuilder(null));
registerPropertyLuceneBuilder(PropertyIds.NAME, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_NAME));
registerPropertyLuceneBuilder(PropertyIds.DESCRIPTION, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_DESCRIPTION));
registerPropertyLuceneBuilder(PropertyIds.IS_IMMUTABLE, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.IS_LATEST_VERSION, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.IS_MAJOR_VERSION, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.IS_LATEST_MAJOR_VERSION, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.VERSION_LABEL, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.VERSION_SERIES_ID, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.CHECKIN_COMMENT, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_LENGTH, new ContentStreamLengthLuceneBuilder(dictionaryService));
registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_MIME_TYPE, new ContentStreamMimetypeLuceneBuilder(dictionaryService));
registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_ID, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_FILE_NAME, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_NAME));
registerPropertyLuceneBuilder(PropertyIds.PARENT_ID, new ParentLuceneBuilder(dictionaryService));
registerPropertyLuceneBuilder(PropertyIds.PATH, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.SOURCE_ID, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder(PropertyIds.TARGET_ID, new NotSupportedLuceneBuilder());
registerPropertyLuceneBuilder("alfcmis:nodeRef", new NotSupportedLuceneBuilder());
}
@Override
public CMISPropertyLuceneBuilder getPropertyLuceneBuilder(String propertyId)
{
return luceneBuilders.get(propertyId);
}
@Override
public CMISPropertyLuceneBuilder createDirectPropertyLuceneBuilder(QName propertyName)
{
return new DirectLuceneBuilder(dictionaryService, propertyName);
}
/**
* Register pre-defined Property Accessor
*
* @param name String
* @param luceneBuilder CMISPropertyLuceneBuilder
*/
private void registerPropertyLuceneBuilder(String name, CMISPropertyLuceneBuilder luceneBuilder)
{
luceneBuilders.put(name, luceneBuilder);
}
}

View File

@@ -0,0 +1,424 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.search;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.search.adaptor.lucene.AnalysisMode;
import org.alfresco.repo.search.impl.parsers.CMIS_FTSLexer;
import org.alfresco.repo.search.impl.parsers.CMIS_FTSParser;
import org.alfresco.repo.search.impl.parsers.FTSQueryException;
import org.alfresco.repo.search.impl.querymodel.Argument;
import org.alfresco.repo.search.impl.querymodel.Column;
import org.alfresco.repo.search.impl.querymodel.Constraint;
import org.alfresco.repo.search.impl.querymodel.Constraint.Occur;
import org.alfresco.repo.search.impl.querymodel.Function;
import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext;
import org.alfresco.repo.search.impl.querymodel.LiteralArgument;
import org.alfresco.repo.search.impl.querymodel.QueryModelFactory;
import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective;
import org.alfresco.repo.search.impl.querymodel.Selector;
import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPhrase;
import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSTerm;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;
public class CMISFTSQueryParser
{
@SuppressWarnings("unused")
static public Constraint buildFTS(String ftsExpression, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, Selector selector,
Map<String, Column> columnMap, String defaultField)
{
// TODO: Decode sql escape for '' should do in CMIS layer
// parse templates to trees ...
CMIS_FTSParser parser = null;
try
{
CharStream cs = new ANTLRStringStream(ftsExpression);
CMIS_FTSLexer lexer = new CMIS_FTSLexer(cs);
CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new CMIS_FTSParser(tokens);
CommonTree ftsNode = (CommonTree) parser.cmisFtsQuery().getTree();
return buildFTSConnective(ftsNode, factory, functionEvaluationContext, selector, columnMap, defaultField);
}
catch (RecognitionException e)
{
if (parser != null)
{
String[] tokenNames = parser.getTokenNames();
String hdr = parser.getErrorHeader(e);
String msg = parser.getErrorMessage(e, tokenNames);
throw new FTSQueryException(hdr + "\n" + msg, e);
}
return null;
}
}
static private Constraint buildFTSConnective(CommonTree node, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext,
Selector selector, Map<String, Column> columnMap, String defaultField)
{
Connective connective;
switch (node.getType())
{
case CMIS_FTSParser.DISJUNCTION:
connective = Connective.OR;
break;
case CMIS_FTSParser.CONJUNCTION:
connective = Connective.AND;
break;
default:
throw new FTSQueryException("Invalid connective ..." + node.getText());
}
List<Constraint> constraints = new ArrayList<Constraint>(node.getChildCount());
CommonTree testNode;
for (int i = 0; i < node.getChildCount(); i++)
{
CommonTree subNode = (CommonTree) node.getChild(i);
Constraint constraint;
switch (subNode.getType())
{
case CMIS_FTSParser.DISJUNCTION:
case CMIS_FTSParser.CONJUNCTION:
constraint = buildFTSConnective(subNode, factory, functionEvaluationContext, selector, columnMap, defaultField);
break;
case CMIS_FTSParser.DEFAULT:
testNode = (CommonTree) subNode.getChild(0);
constraint = buildFTSTest(testNode, factory, functionEvaluationContext, selector, columnMap, defaultField);
constraint.setOccur(Occur.DEFAULT);
break;
case CMIS_FTSParser.EXCLUDE:
testNode = (CommonTree) subNode.getChild(0);
constraint = buildFTSTest(testNode, factory, functionEvaluationContext, selector, columnMap, defaultField);
constraint.setOccur(Occur.EXCLUDE);
break;
default:
throw new FTSQueryException("Unsupported FTS option " + subNode.getText());
}
constraints.add(constraint);
}
if (constraints.size() == 1)
{
return constraints.get(0);
}
else
{
if (connective == Connective.OR)
{
return factory.createDisjunction(constraints);
}
else
{
return factory.createConjunction(constraints);
}
}
}
static private Constraint buildFTSTest(CommonTree argNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext,
Selector selector, Map<String, Column> columnMap, String defaultField)
{
CommonTree testNode = argNode;
switch (testNode.getType())
{
case CMIS_FTSParser.DISJUNCTION:
case CMIS_FTSParser.CONJUNCTION:
return buildFTSConnective(testNode, factory, functionEvaluationContext, selector, columnMap, defaultField);
case CMIS_FTSParser.TERM:
return buildTerm(testNode, factory, functionEvaluationContext, selector, columnMap);
case CMIS_FTSParser.PHRASE:
return buildPhrase(testNode, factory, functionEvaluationContext, selector, columnMap);
default:
throw new FTSQueryException("Unsupported FTS option " + testNode.getText());
}
}
static private Constraint buildPhrase(CommonTree testNode, QueryModelFactory factory,
FunctionEvaluationContext functionEvaluationContext, Selector selector, Map<String, Column> columnMap)
{
String functionName = FTSPhrase.NAME;
Function function = factory.getFunction(functionName);
Map<String, Argument> functionArguments = new LinkedHashMap<String, Argument>();
LiteralArgument larg = factory.createLiteralArgument(FTSPhrase.ARG_PHRASE, DataTypeDefinition.TEXT, getText(testNode.getChild(0)));
functionArguments.put(larg.getName(), larg);
larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT);
functionArguments.put(larg.getName(), larg);
return factory.createFunctionalConstraint(function, functionArguments);
}
static private Constraint buildTerm(CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext,
Selector selector, Map<String, Column> columnMap)
{
String functionName = FTSTerm.NAME;
Function function = factory.getFunction(functionName);
Map<String, Argument> functionArguments = new LinkedHashMap<String, Argument>();
LiteralArgument larg = factory.createLiteralArgument(FTSTerm.ARG_TERM, DataTypeDefinition.TEXT, getText(testNode.getChild(0)));
functionArguments.put(larg.getName(), larg);
larg = factory.createLiteralArgument(FTSTerm.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT);
functionArguments.put(larg.getName(), larg);
return factory.createFunctionalConstraint(function, functionArguments);
}
static class DisjunctionToken implements Token
{
public int getChannel()
{
return 0;
}
public int getCharPositionInLine()
{
return 0;
}
public CharStream getInputStream()
{
return null;
}
public int getLine()
{
return 0;
}
public String getText()
{
return null;
}
public int getTokenIndex()
{
return 0;
}
public int getType()
{
return CMIS_FTSParser.DISJUNCTION;
}
public void setChannel(int arg0)
{
}
public void setCharPositionInLine(int arg0)
{
}
public void setInputStream(CharStream arg0)
{
}
public void setLine(int arg0)
{
}
public void setText(String arg0)
{
}
public void setTokenIndex(int arg0)
{
}
public void setType(int arg0)
{
}
}
static class DefaultToken implements Token
{
public int getChannel()
{
return 0;
}
public int getCharPositionInLine()
{
return 0;
}
public CharStream getInputStream()
{
return null;
}
public int getLine()
{
return 0;
}
public String getText()
{
return null;
}
public int getTokenIndex()
{
return 0;
}
public int getType()
{
return CMIS_FTSParser.DEFAULT;
}
public void setChannel(int arg0)
{
}
public void setCharPositionInLine(int arg0)
{
}
public void setInputStream(CharStream arg0)
{
}
public void setLine(int arg0)
{
}
public void setText(String arg0)
{
}
public void setTokenIndex(int arg0)
{
}
public void setType(int arg0)
{
}
}
static private String getText(Tree node)
{
String text = node.getText();
int index;
switch (node.getType())
{
case CMIS_FTSParser.FTSWORD:
index = text.indexOf('\\');
if (index == -1)
{
return text;
}
else
{
return unescape(text);
}
case CMIS_FTSParser.FTSPHRASE:
String phrase = text.substring(1, text.length() - 1);
index = phrase.indexOf('\\');
if (index == -1)
{
return phrase;
}
else
{
return unescape(phrase);
}
default:
return text;
}
}
static private String unescape(String string)
{
StringBuilder builder = new StringBuilder(string.length());
boolean lastWasEscape = false;
for (int i = 0; i < string.length(); i++)
{
char c = string.charAt(i);
if (lastWasEscape)
{
if (c == 'u')
{
throw new UnsupportedOperationException(string);
}
else
{
builder.append(c);
}
lastWasEscape = false;
}
else
{
if (c == '\\')
{
lastWasEscape = true;
}
else
{
builder.append(c);
}
}
}
if (lastWasEscape)
{
throw new FTSQueryException("Escape character at end of string " + string);
}
return builder.toString();
}
}

View File

@@ -0,0 +1,203 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.search;
import java.util.Locale;
import org.alfresco.repo.search.impl.querymodel.QueryOptions;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* The options for a CMIS query
*
* @author andyh
*/
public class CMISQueryOptions extends QueryOptions
{
public enum CMISQueryMode
{
CMS_STRICT, CMS_WITH_ALFRESCO_EXTENSIONS;
}
private CMISQueryMode queryMode = CMISQueryMode.CMS_STRICT;
private CmisVersion cmisVersion = CmisVersion.CMIS_1_1;
public static CMISQueryOptions create(SearchParameters searchParameters)
{
String sql = searchParameters.getQuery();
CMISQueryOptions options = new CMISQueryOptions(sql, searchParameters.getStores().get(0));
options.setIncludeInTransactionData(!searchParameters.excludeDataInTheCurrentTransaction());
options.setDefaultFTSConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND);
options.setDefaultFTSFieldConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND);
options.setSkipCount(searchParameters.getSkipCount());
options.setMaxPermissionChecks(searchParameters.getMaxPermissionChecks());
options.setMaxPermissionCheckTimeMillis(searchParameters.getMaxPermissionCheckTimeMillis());
if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE)
{
options.setMaxItems(searchParameters.getLimit());
}
else
{
options.setMaxItems(searchParameters.getMaxItems());
}
options.setMlAnalaysisMode(searchParameters.getMlAnalaysisMode());
options.setLocales(searchParameters.getLocales());
options.setStores(searchParameters.getStores());
options.setUseInMemorySort(searchParameters.getUseInMemorySort());
options.setMaxRawResultSetSizeForInMemorySort(searchParameters.getMaxRawResultSetSizeForInMemorySort());
//options.setQuery(); Done on conbstruction
//options.setQueryMode(); Should set afterwards
options.setQueryParameterDefinitions(searchParameters.getQueryParameterDefinitions());
options.setDefaultFieldName(searchParameters.getDefaultFieldName());
options.setBulkFetchEnabled(searchParameters.isBulkFetchEnabled());
options.setExcludeTenantFilter(searchParameters.getExcludeTenantFilter());
options.setSinceTxId(searchParameters.getSinceTxId());
for(String name : searchParameters.getQueryTemplates().keySet())
{
String template = searchParameters.getQueryTemplates().get(name);
options.addQueryTemplate(name, template);
}
return options;
}
/**
* Create a CMISQueryOptions instance with the default options other than
* the query and store ref. The query will be run using the locale returned
* by I18NUtil.getLocale()
*
* @param query
* - the query to run
* @param storeRef
* - the store against which to run the query
*/
public CMISQueryOptions(String query, StoreRef storeRef)
{
this(query, storeRef, I18NUtil.getLocale());
}
/**
* Create a CMISQueryOptions instance with the default options other than
* the query, store ref and locale.
*
* @param query
* - the query to run
* @param storeRef
* - the store against which to run the query
*/
public CMISQueryOptions(String query, StoreRef storeRef, Locale locale)
{
super(query, storeRef, locale);
}
public CmisVersion getCmisVersion()
{
return cmisVersion;
}
public void setCmisVersion(CmisVersion cmisVersion)
{
this.cmisVersion = cmisVersion;
}
/**
* Get the query mode.
*
* @return the queryMode
*/
public CMISQueryMode getQueryMode()
{
return queryMode;
}
/**
* Set the query mode.
*
* @param queryMode
* the queryMode to set
*/
public void setQueryMode(CMISQueryMode queryMode)
{
this.queryMode = queryMode;
}
/**
* @return SearchParameters
*/
public SearchParameters getAsSearchParmeters()
{
SearchParameters searchParameters = new SearchParameters();
searchParameters.setDefaultFieldName(this.getDefaultFieldName());
searchParameters.setDefaultFTSFieldConnective(this.getDefaultFTSFieldConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND);
searchParameters.setDefaultFTSOperator(this.getDefaultFTSConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND);
searchParameters.setDefaultOperator(this.getDefaultFTSConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND);
searchParameters.setLanguage(SearchService.LANGUAGE_CMIS_ALFRESCO);
if(this.getMaxItems() > 0)
{
searchParameters.setLimit(this.getMaxItems());
searchParameters.setLimitBy(LimitBy.FINAL_SIZE);
searchParameters.setMaxItems(this.getMaxItems());
}
searchParameters.setMaxPermissionChecks(this.getMaxPermissionChecks());
searchParameters.setMaxPermissionCheckTimeMillis(this.getMaxPermissionCheckTimeMillis());
searchParameters.setMlAnalaysisMode(this.getMlAnalaysisMode());
//searchParameters.setNamespace() TODO: Fix
//searchParameters.setPermissionEvaluation()
searchParameters.setQuery(this.getQuery());
searchParameters.setSkipCount(this.getSkipCount());
//searchParameters.addAllAttribute()
for(Locale locale : this.getLocales())
{
searchParameters.addLocale(locale);
}
for(QueryParameterDefinition queryParameterDefinition: this.getQueryParameterDefinitions())
{
searchParameters.addQueryParameterDefinition(queryParameterDefinition);
}
//searchParameters.addQueryTemplate(name, template)
//searchParameters.addSort()
for(StoreRef storeRef : this.getStores())
{
searchParameters.addStore(storeRef);
}
//searchParameters.addTextAttribute()
searchParameters.setBulkFetchEnabled(isBulkFetchEnabled());
searchParameters.setQueryConsistency(this.getQueryConsistency());
searchParameters.setSinceTxId(getSinceTxId());
for(String name : getQueryTemplates().keySet())
{
String template = getQueryTemplates().get(name);
searchParameters.addQueryTemplate(name, template);
}
return searchParameters;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,554 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.opencmis.search;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import org.alfresco.opencmis.dictionary.CMISDictionaryService;
import org.alfresco.opencmis.dictionary.CMISNodeInfo;
import org.alfresco.opencmis.dictionary.PropertyDefinitionWrapper;
import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper;
import org.alfresco.repo.search.adaptor.lucene.LuceneFunction;
import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor;
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
import org.alfresco.repo.search.impl.querymodel.FunctionArgument;
import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext;
import org.alfresco.repo.search.impl.querymodel.PredicateMode;
import org.alfresco.repo.search.impl.querymodel.QueryModelException;
import org.alfresco.repo.search.impl.querymodel.Selector;
import org.alfresco.repo.search.impl.querymodel.impl.functions.Lower;
import org.alfresco.repo.search.impl.querymodel.impl.functions.Upper;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.Cardinality;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
/**
* @author andyh
*/
@SuppressWarnings("deprecation")
public class CmisFunctionEvaluationContext implements FunctionEvaluationContext
{
private static HashSet<String> EXPOSED_FIELDS = new HashSet<String>();
public static BaseTypeId[] STRICT_SCOPES = new BaseTypeId[] { BaseTypeId.CMIS_DOCUMENT, BaseTypeId.CMIS_FOLDER };
public static BaseTypeId[] ALFRESCO_SCOPES = new BaseTypeId[] { BaseTypeId.CMIS_DOCUMENT, BaseTypeId.CMIS_FOLDER,
BaseTypeId.CMIS_POLICY, BaseTypeId.CMIS_SECONDARY, BaseTypeId.CMIS_ITEM };
private Map<String, NodeRef> nodeRefs;
private Map<String, Float> scores;
private Map<NodeRef, CMISNodeInfo> nodeInfos;
private NodeService nodeService;
private CMISDictionaryService cmisDictionaryService;
private BaseTypeId[] validScopes;
private Float score;
static
{
EXPOSED_FIELDS.add(QueryConstants.FIELD_PATH);
EXPOSED_FIELDS.add(QueryConstants.FIELD_TEXT);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ID);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ISROOT);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNODE);
EXPOSED_FIELDS.add(QueryConstants.FIELD_TX);
EXPOSED_FIELDS.add(QueryConstants.FIELD_PARENT);
EXPOSED_FIELDS.add(QueryConstants.FIELD_PRIMARYPARENT);
EXPOSED_FIELDS.add(QueryConstants.FIELD_QNAME);
EXPOSED_FIELDS.add(QueryConstants.FIELD_CLASS);
EXPOSED_FIELDS.add(QueryConstants.FIELD_TYPE);
EXPOSED_FIELDS.add(QueryConstants.FIELD_EXACTTYPE);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ASPECT);
EXPOSED_FIELDS.add(QueryConstants.FIELD_EXACTASPECT);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ALL);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ISUNSET);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNULL);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNOTNULL);
EXPOSED_FIELDS.add(QueryConstants.FIELD_FTSSTATUS);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ASSOCTYPEQNAME);
EXPOSED_FIELDS.add(QueryConstants.FIELD_PRIMARYASSOCTYPEQNAME);
EXPOSED_FIELDS.add(QueryConstants.FIELD_DBID);
EXPOSED_FIELDS.add(QueryConstants.FIELD_TAG);
EXPOSED_FIELDS.add(QueryConstants.FIELD_TENANT);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ANCESTOR);
EXPOSED_FIELDS.add(QueryConstants.FIELD_SITE);
EXPOSED_FIELDS.add(QueryConstants.FIELD_TAG);
EXPOSED_FIELDS.add(QueryConstants.FIELD_PNAME);
EXPOSED_FIELDS.add(QueryConstants.FIELD_NPATH);
EXPOSED_FIELDS.add(QueryConstants.FIELD_ANAME);
EXPOSED_FIELDS.add(QueryConstants.FIELD_APATH);
EXPOSED_FIELDS.add(QueryConstants.FIELD_DOC_TYPE);
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.ANY.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.ASSOC_REF.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.BOOLEAN.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.CATEGORY.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.CHILD_ASSOC_REF.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.CONTENT.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.DATE.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.DATETIME.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.DOUBLE.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.FLOAT.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.INT.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.LOCALE.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.LONG.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.MLTEXT.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.NODE_REF.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.PATH.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.PERIOD.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.QNAME.getLocalName());
EXPOSED_FIELDS.add("d:"+DataTypeDefinition.TEXT.getLocalName());
}
/**
* @param nodeRefs
* the nodeRefs to set
*/
public void setNodeRefs(Map<String, NodeRef> nodeRefs)
{
this.nodeRefs = nodeRefs;
}
/**
* @param scores
* the scores to set
*/
public void setScores(Map<String, Float> scores)
{
this.scores = scores;
}
public void setNodeInfos(Map<NodeRef, CMISNodeInfo> nodeInfos) {
this.nodeInfos = nodeInfos;
}
/**
* @param nodeService
* the nodeService to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param cmisDictionaryService
* the cmisDictionaryService to set
*/
public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
/**
* @param validScopes
* the valid scopes to set
*/
public void setValidScopes(BaseTypeId[] validScopes)
{
this.validScopes = validScopes;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* getNodeRefs()
*/
public Map<String, NodeRef> getNodeRefs()
{
return nodeRefs;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* getNodeService()
*/
public NodeService getNodeService()
{
return nodeService;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* getProperty(org.alfresco.service.cmr.repository.NodeRef,
* org.alfresco.service.namespace.QName)
*/
public Serializable getProperty(NodeRef nodeRef, String propertyName)
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
CMISNodeInfo nodeInfo = nodeInfos.get(nodeRef);
if (nodeInfo == null)
{
nodeInfo = propertyDef.getPropertyAccessor().createNodeInfo(nodeRef);
nodeInfos.put(nodeRef, nodeInfo);
}
return propertyDef.getPropertyAccessor().getValue(nodeInfo);
}
/*
* (non-Javadoc)
*
* @see
* org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getScores
* ()
*/
public Map<String, Float> getScores()
{
return scores;
}
/**
* @return the score
*/
public Float getScore()
{
return score;
}
/**
* @param score
* the score to set
*/
public void setScore(Float score)
{
this.score = score;
}
public <Q, S, E extends Throwable> Q buildLuceneEquality(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Serializable value,
PredicateMode mode, LuceneFunction luceneFunction) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneEquality(lqpa, value, mode, luceneFunction);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneExists(org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.lang.Boolean)
*/
public <Q, S, E extends Throwable> Q buildLuceneExists(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Boolean not) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneExists(lqpa, not);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneGreaterThan
* (org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.io.Serializable,
* org.alfresco.repo.search.impl.querymodel.PredicateMode)
*/
public <Q, S, E extends Throwable> Q buildLuceneGreaterThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Serializable value,
PredicateMode mode, LuceneFunction luceneFunction) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneGreaterThan(lqpa, value, mode, luceneFunction);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneGreaterThanOrEquals
* (org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.io.Serializable,
* org.alfresco.repo.search.impl.querymodel.PredicateMode)
*/
public <Q, S, E extends Throwable> Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Serializable value,
PredicateMode mode, LuceneFunction luceneFunction) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneGreaterThanOrEquals(lqpa, value, mode, luceneFunction);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneIn(org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.util.Collection,
* java.lang.Boolean,
* org.alfresco.repo.search.impl.querymodel.PredicateMode)
*/
public <Q, S, E extends Throwable> Q buildLuceneIn(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Collection<Serializable> values,
Boolean not, PredicateMode mode) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneIn(lqpa, values, not, mode);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneInequality
* (org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.io.Serializable,
* org.alfresco.repo.search.impl.querymodel.PredicateMode)
*/
public <Q, S, E extends Throwable> Q buildLuceneInequality(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Serializable value,
PredicateMode mode, LuceneFunction luceneFunction) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneInequality(lqpa, value, mode, luceneFunction);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneLessThan
* (org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.io.Serializable,
* org.alfresco.repo.search.impl.querymodel.PredicateMode)
*/
public <Q, S, E extends Throwable> Q buildLuceneLessThan(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Serializable value,
PredicateMode mode, LuceneFunction luceneFunction) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneLessThan(lqpa, value, mode, luceneFunction);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneLessThanOrEquals
* (org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.io.Serializable,
* org.alfresco.repo.search.impl.querymodel.PredicateMode)
*/
public <Q, S, E extends Throwable> Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Serializable value,
PredicateMode mode, LuceneFunction luceneFunction) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneLessThanOrEquals(lqpa, value, mode, luceneFunction);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* buildLuceneLike(org.alfresco.repo.search.impl.lucene.LuceneQueryParser,
* org.alfresco.service.namespace.QName, java.io.Serializable,
* java.lang.Boolean)
*/
public <Q, S, E extends Throwable> Q buildLuceneLike(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName, Serializable value, Boolean not)
throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().buildLuceneLike(lqpa, value, not);
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* getLuceneSortField(org.alfresco.service.namespace.QName)
*/
public <Q, S, E extends Throwable> String getLuceneSortField(LuceneQueryParserAdaptor<Q, S, E> lqpa, String propertyName) throws E
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
return propertyDef.getPropertyLuceneBuilder().getLuceneSortField(lqpa);
}
public boolean isObjectId(String propertyName)
{
return PropertyIds.OBJECT_ID.equalsIgnoreCase(propertyName);
}
public boolean isOrderable(String fieldName)
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(fieldName);
if (propertyDef == null)
{
return false;
} else
{
return propertyDef.getPropertyDefinition().isOrderable();
}
}
public boolean isQueryable(String fieldName)
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(fieldName);
if (propertyDef == null)
{
return true;
} else
{
return propertyDef.getPropertyDefinition().isQueryable();
}
}
public String getLuceneFieldName(String propertyName)
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
if (propertyDef != null)
{
return propertyDef.getPropertyLuceneBuilder().getLuceneFieldName();
} else
{
// TODO: restrict to supported "special" fields
return propertyName;
}
}
public LuceneFunction getLuceneFunction(FunctionArgument functionArgument)
{
if (functionArgument == null)
{
return LuceneFunction.FIELD;
} else
{
String functionName = functionArgument.getFunction().getName();
if (functionName.equals(Upper.NAME))
{
return LuceneFunction.UPPER;
} else if (functionName.equals(Lower.NAME))
{
return LuceneFunction.LOWER;
} else
{
throw new QueryModelException("Unsupported function: " + functionName);
}
}
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* checkFieldApplies(org.alfresco.service.namespace.QName, java.lang.String)
*/
public void checkFieldApplies(Selector selector, String propertyName)
{
PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(propertyName);
if (propDef == null)
{
if (EXPOSED_FIELDS.contains(propertyName))
{
return;
}
else
{
throw new CmisInvalidArgumentException("Unknown column/property " + propertyName);
}
}
TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), validScopes);
if (typeDef == null)
{
throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + selector.getAlias());
}
// Check column/property applies to selector/type
if (typeDef.getPropertyById(propDef.getPropertyId()) == null)
{
throw new CmisInvalidArgumentException("Invalid column for "
+ typeDef.getTypeDefinition(false).getQueryName() + "." + propertyName);
}
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#
* isMultiValued(java.lang.String)
*/
public boolean isMultiValued(String propertyName)
{
PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(propertyName);
if (propDef == null)
{
throw new CmisInvalidArgumentException("Unknown column/property " + propertyName);
}
return propDef.getPropertyDefinition().getCardinality() == Cardinality.MULTI;
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getAlfrescoQName(org.alfresco.service.namespace.QName)
*/
@Override
public String getAlfrescoPropertyName(String propertyName)
{
PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName);
if(propertyDef != null)
{
return propertyDef.getPropertyLuceneBuilder().getLuceneFieldName().substring(1);
}
else
{
throw new CmisInvalidArgumentException("Unknown column/property " + propertyName);
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getAlfrescoTypeName(java.lang.String)
*/
@Override
public String getAlfrescoTypeName(String typeName)
{
TypeDefinitionWrapper typeDef = cmisDictionaryService.findType(typeName);
if(typeDef != null)
{
return typeDef.getAlfrescoClass().toString();
}
else
{
throw new CmisInvalidArgumentException("Unknown type " + typeName);
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.cache;
import java.io.Serializable;
/**
* Interface for caches that support value locking
*
* @author Derek Hulley
* @since 4.1.6
*/
public interface LockingCache<K extends Serializable, V extends Object> extends SimpleCache<K, V>
{
/**
* Determine if a value (addition, removal or update) has been locked for the remainer of the transaction
*
* @param key the cache key to check up on
* @return <tt>true</tt> if the value will not change for the remaineder of the transaction
*/
boolean isValueLocked(K key);
/**
* Prevent a key's value from being changed for the duriation of the transaction.
* By default, further attempts to modify the associated value will be ignored;
* this includes add a value back after removal.
*
* @param key the cache key that will be locked against change
*/
void lockValue(K key);
/**
* Cancel any previous lock applied to a key's value.
*
* @param key the cache key that will be unlocked, allowing changes
*/
void unlockValue(K key);
}

View File

@@ -0,0 +1,79 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.cache;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A cache backed by a simple <code>ConcurrentHashMap</code>.
* <p>
* <b>Note:</b> This cache is not transaction-safe. Use it for tests or wrap it appropriately.
*
* @author Derek Hulley
* @since 3.2
*/
public class MemoryCache<K extends Serializable, V extends Object> implements SimpleCache<K, V>
{
private Map<K, V> map;
public MemoryCache()
{
map = new ConcurrentHashMap<K, V>(15);
}
public boolean contains(K key)
{
return map.containsKey(key);
}
public Collection<K> getKeys()
{
return map.keySet();
}
public V get(K key)
{
return map.get(key);
}
public void put(K key, V value)
{
map.put(key, value);
}
public void remove(K key)
{
map.remove(key);
}
public void clear()
{
map.clear();
}
}

View File

@@ -0,0 +1,93 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.cache;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import org.alfresco.api.AlfrescoPublicApi;
/**
* Basic caching interface.
* <p>
* All implementations <b>must</b> be thread-safe. Additionally, the use of the
* <tt>Serializable</tt> for both keys and values ensures that the underlying
* cache implementations can support both clustered caches as well as persistent
* caches.
* <p>
* All implementations must support <tt>null</tt> values. It therefore follows
* that
* <pre>
* (simpleCache.contains(key) == true) does not imply (simpleCache.get(key) != null)
* </pre>
* but
* <pre>
* (simpleCache.contains(key) == false) implies (simpleCache.get(key) == null)
* </pre>
*
* @author Derek Hulley
*/
@AlfrescoPublicApi
public interface SimpleCache<K extends Serializable, V extends Object>
{
/**
* @param key the cache key to check up on
* @return Returns <tt>true</tt> if there is a cache entry,
* regardless of whether the value itself is <tt>null</tt>
*/
public boolean contains(K key);
public Collection<K> getKeys();
/**
* @param key K
* @return Returns the value associated with the key. It will be <tt>null</tt>
* if the value is <tt>null</tt> or if the cache doesn't have an entry.
*/
public V get(K key);
/**
* Set the value to store for a given key.
* <p/>
* Be sure to use {@link #remove(Serializable) remove} if cache entries need to be removed
* as the cache implementations must treat a <tt>null</tt> value as a first class object
* in exactly the same way as a {@link Map} will allow storage and retrieval of <tt>null</tt> values.
*
* @param key the key against which to store the value
* @param value the value to store. <tt>null</tt> is allowed.
*/
public void put(K key, V value);
/**
* Removes the cache entry whether or not the value stored against it is <tt>null</tt>.
*
* @param key the key value to remove
*/
public void remove(K key);
public void clear();
}

View File

@@ -0,0 +1,92 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import java.io.Serializable;
import org.alfresco.service.cmr.repository.ContentReader;
/**
* The location and lookup data for content. The very least data required to
* find content or assign a content writer is the content URL and any previous
* content that may have logically existed.
* <p>
* Although this class is doesn't enforce any conditions on the context,
* derived instances may have relationships that need to be maintained between
* various context values.
*
* @author Derek Hulley
*/
public class ContentContext implements Serializable
{
private static final long serialVersionUID = 6476617391229895125L;
/** An empty context. */
public static final ContentContext NULL_CONTEXT = new ContentContext(null, null);
private ContentReader existingContentReader;
private String contentUrl;
/**
* Construct the instance with the content URL.
*
* @param existingContentReader content with which to seed the new writer - may be <tt>null</tt>
* @param contentUrl the content URL - may be <tt>null</tt>
*/
public ContentContext(ContentReader existingContentReader, String contentUrl)
{
this.existingContentReader = existingContentReader;
this.contentUrl = contentUrl;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(128);
sb.append("ContentContext")
.append("[ contentUrl=").append(getContentUrl())
.append(", existing=").append((getExistingContentReader() == null ? false : true))
.append("]");
return sb.toString();
}
/**
* @return Returns the content to seed the writer with - may be <tt>null</tt>
*/
public ContentReader getExistingContentReader()
{
return existingContentReader;
}
/**
* @return Returns the content URL for the content's context - may be <tt>null</tt>
*/
public String getContentUrl()
{
return contentUrl;
}
}

View File

@@ -0,0 +1,238 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.cmr.repository.ContentAccessor;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentStreamListener;
import org.alfresco.service.cmr.repository.ContentWriter;
/**
* Provides low-level retrieval of content
* {@link org.alfresco.service.cmr.repository.ContentReader readers} and
* {@link org.alfresco.service.cmr.repository.ContentWriter writers}.
* <p>
* Implementations of this interface should be soley responsible for
* providing persistence and retrieval of the content against a
* <code>content URL</code>.
* <p>
* Content URLs must consist of a prefix or protocol followed by an
* implementation-specific identifier. See
* {@link org.alfresco.repo.content.filestore.TimeBasedFileContentUrlProvider TimeBasedFileContentUrlProvider} and
* {@link org.alfresco.repo.content.filestore.VolumeAwareContentUrlProvider VolumeAwareContentUrlProvider} implementations of
* {@link org.alfresco.repo.content.filestore.FileContentUrlProvider FileContentUrlProvider}
* For example, default content URL format
* for file stores is <b>store://year/month/day/hour/minute/GUID.bin</b> <br>
* <ul>
* <li> <b>store://</b>: prefix identifying an Alfresco content stores
* regardless of the persistence mechanism. </li>
* <li> <b>year</b>: year </li>
* <li> <b>month</b>: 1-based month of the year </li>
* <li> <b>day</b>: 1-based day of the month </li>
* <li> <b>hour</b>: 0-based hour of the day </li>
* <li> <b>minute</b>: 0-based minute of the hour </li>
* <li> <b>GUID</b>: A unique identifier </li>
* </ul>
* <p>
* Where the store cannot handle a particular content URL request, the
* {@code UnsupportedContentUrlException} must be generated. This will allow
* various implementations to provide fallback code to other stores where
* possible.
* <p>
* Where a store cannot serve a particular request because the functionality
* is just not available, the <code>UnsupportedOperationException</code> should
* be thrown. Once again, there may be fallback handling provided for these
* situations.
*
* @since 1.0
* @author Derek Hulley
*/
@AlfrescoPublicApi
public interface ContentStore
{
/**
* An empty content context used to retrieve completely new content.
*
* @see ContentStore#getWriter(ContentContext)
*/
public static final ContentContext NEW_CONTENT_CONTEXT = new ContentContext(null, null);
/**
* The delimiter that must be found in all URLS, i.e <b>://</b>
*/
public static final String PROTOCOL_DELIMITER = "://";
/**
* Check if the content URL format is supported by the store.
*
* @param contentUrl the content URL to check
* @return Returns <tt>true</tt> if none of the other methods on the store
* will throw an {@code UnsupportedContentUrlException} when given
* this URL.
*
* @since 2.1
*/
public boolean isContentUrlSupported(String contentUrl);
/**
* Check if the store supports write requests.
*
* @return Return true is the store supports write operations
*
* @since 2.1
*/
public boolean isWriteSupported();
/**
* Calculates the remaning <i>free</i> space in the underlying store.
* <p>
* <b>NOTE:</b> For efficiency, some implementations may provide a guess.
* <p>
* Implementations should focus on calculating a size value quickly, rather than accurately.
*
* @return
* Returns the total, possibly approximate, free space (in bytes) available to the store
* or <tt>-1</tt> if no size data is available.
*
* @since 3.3.3
*/
public long getSpaceFree();
/**
* Calculates the total storage space of the underlying store.
* <p>
* <b>NOTE:</b> For efficiency, some implementations may provide a guess.
* <p>
* Implementations should focus on calculating a size value quickly, rather than accurately.
*
* @return
* Returns the total, possibly approximate, size (in bytes) of the underlying store
* or <tt>-1</tt> if no size data is available.
*
* @since 3.3.3
*/
public long getSpaceTotal();
/**
* Get the location where the store is rooted. The format of the returned value will depend on the
* specific implementation of the store.
*
* @return Returns the store's root location or <b>.</b> if no information is available
*/
public String getRootLocation();
/**
* Check for the existence of content in the store.
* <p>
* The implementation of this may be more efficient than first getting a
* reader to {@link ContentReader#exists() check for existence}, although
* that check should also be performed.
*
* @param contentUrl
* the path to the content
* @return
* Returns true if the content exists, otherwise false if the content doesn't
* exist or <b>if the URL is not applicable to this store</b>.
* @throws org.alfresco.repo.content.UnsupportedContentUrlException
* if the content URL supplied is not supported by the store
* @throws ContentIOException
* if an IO error occurs
*
* @see ContentReader#exists()
*/
public boolean exists(String contentUrl);
/**
* Get the accessor with which to read from the content at the given URL.
* The reader is <b>stateful</b> and can <b>only be used once</b>.
*
* @param contentUrl the path to where the content is located
* @return Returns a read-only content accessor for the given URL. There may
* be no content at the given URL, but the reader must still be returned.
* @throws org.alfresco.repo.content.UnsupportedContentUrlException
* if the content URL supplied is not supported by the store
* @throws ContentIOException
* if an IO error occurs
*
* @see #exists(String)
* @see ContentReader#exists()
* @see org.alfresco.repo.content.EmptyContentReader
*/
public ContentReader getReader(String contentUrl);
/**
* Get an accessor with which to write content to a location
* within the store. The writer is <b>stateful</b> and can
* <b>only be used once</b>. The location may be specified but must, in that case,
* be a valid and unused URL.
* <p>
* The store will ensure that the {@link ContentAccessor#getContentUrl() new content URL} will
* be valid for all subsequent read attempts.
* <p>
* By supplying a reader to existing content, the store implementation may
* enable random access. The store implementation
* can enable this by copying the existing content into the new location
* before supplying a writer onto the new content.
*
* @param context
* the context of content.
* @return
* Returns a write-only content accessor
* @throws UnsupportedOperationException
* if the store is unable to provide the information
* @throws UnsupportedContentUrlException
* if the content URL supplied is not supported by the store
* @throws ContentExistsException
* if the content URL is already in use
* @throws ContentIOException
* if an IO error occurs
*
* @see ContentWriter#addListener(ContentStreamListener)
* @see ContentWriter#getContentUrl()
*/
public ContentWriter getWriter(ContentContext context);
/**
* Deletes the content at the given URL.
* <p>
* A delete cannot be forced since it is much better to have the
* file remain longer than desired rather than deleted prematurely.
*
* @param contentUrl
* the URL of the content to delete
* @return
* Returns <tt>true</tt> if the content was deleted (either by this or another operation),
* otherwise false. If the content no longer exists, then <tt>true</tt> is returned.
* @throws UnsupportedOperationException
* if the store is unable to perform the action
* @throws UnsupportedContentUrlException
* if the content URL supplied is not supported by the store
* @throws ContentIOException if an error occurs
* if an IO error occurs
*/
public boolean delete(String contentUrl);
}

View File

@@ -0,0 +1,59 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import org.alfresco.repo.tenant.TenantDeployer;
/**
* ContentStore capabilities. Allows us to avoid performing {@code instanceof} questions
* which can become a problem when certain proxies or subsystems are in use.
* <p>
* See ACE-2682 (tenant creation failure) for motivation.
*
* @author Matt Ward
*/
public interface ContentStoreCaps
{
/**
* Returns the ContentStore cast to a TenantRoutingContentStore if the underlying
* instance is of that type. Returns null otherwise.
* <p>
* Note, the actual return type is a TenantDeployer (supertype of TenantRoutingContentStore)
* since the data model has no knowledge of that subtype. This interface may
* need to move to a different project.
*
* @return TenantRoutingContentStore
*/
TenantDeployer getTenantRoutingContentStore();
/**
* Returns the ContentStore cast to a TenantDeployer if the underlying
* instance is of that type. Returns null otherwise.
*
* @return TenantDeployer
*/
TenantDeployer getTenantDeployer();
}

View File

@@ -0,0 +1,966 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.FileContentReader;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.detect.DefaultDetector;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigElement;
import org.springframework.extensions.config.ConfigLookupContext;
import org.springframework.extensions.config.ConfigService;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
/**
* Provides a bidirectional mapping between well-known mimetypes and the
* registered file extensions. All mimetypes and extensions are stored and
* handled as lowercase.
*
* @author Derek Hulley
*/
public class MimetypeMap implements MimetypeService
{
public static final String PREFIX_APPLICATION = "application/";
public static final String PREFIX_AUDIO = "audio/";
public static final String PREFIX_IMAGE = "image/";
public static final String PREFIX_MESSAGE = "message/";
public static final String PREFIX_MODEL = "model/";
public static final String PREFIX_MULTIPART = "multipart/";
public static final String PREFIX_TEXT = "text/";
public static final String PREFIX_VIDEO = "video/";
public static final String EXTENSION_BINARY = "bin";
public static final String MACOS_RESOURCE_FORK_FILE_NAME_PREFIX = "._";
public static final String MIMETYPE_MULTIPART_ALTERNATIVE = "multipart/alternative";
public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
public static final String MIMETYPE_TEXT_MEDIAWIKI = "text/mediawiki";
public static final String MIMETYPE_TEXT_CSS = "text/css";
public static final String MIMETYPE_TEXT_CSV = "text/csv";
public static final String MIMETYPE_TEXT_JAVASCRIPT = "text/javascript";
public static final String MIMETYPE_XML = "text/xml";
public static final String MIMETYPE_HTML = "text/html";
public static final String MIMETYPE_XHTML = "application/xhtml+xml";
public static final String MIMETYPE_PDF = "application/pdf";
public static final String MIMETYPE_JSON = "application/json";
public static final String MIMETYPE_WORD = "application/msword";
public static final String MIMETYPE_EXCEL = "application/vnd.ms-excel";
public static final String MIMETYPE_BINARY = "application/octet-stream";
public static final String MIMETYPE_PPT = "application/vnd.ms-powerpoint";
public static final String MIMETYPE_APP_DWG = "application/dwg";
public static final String MIMETYPE_IMG_DWG = "image/vnd.dwg";
public static final String MIMETYPE_VIDEO_AVI = "video/x-msvideo";
public static final String MIMETYPE_VIDEO_QUICKTIME = "video/quicktime";
public static final String MIMETYPE_VIDEO_WMV = "video/x-ms-wmv";
public static final String MIMETYPE_VIDEO_3GP = "video/3gpp";
public static final String MIMETYPE_VIDEO_3GP2 = "video/3gpp2";
public static final String MIMETYPE_DITA = "application/dita+xml";
// Flash
public static final String MIMETYPE_FLASH = "application/x-shockwave-flash";
public static final String MIMETYPE_VIDEO_FLV = "video/x-flv";
public static final String MIMETYPE_APPLICATION_FLA = "application/x-fla";
public static final String MIMETYPE_VIDEO_MPG = "video/mpeg";
public static final String MIMETYPE_VIDEO_MP4 = "video/mp4";
public static final String MIMETYPE_IMAGE_GIF = "image/gif";
public static final String MIMETYPE_IMAGE_JPEG = "image/jpeg";
public static final String MIMETYPE_IMAGE_RGB = "image/x-rgb";
public static final String MIMETYPE_IMAGE_SVG = "image/svg+xml";
public static final String MIMETYPE_IMAGE_PNG = "image/png";
public static final String MIMETYPE_IMAGE_TIFF = "image/tiff";
public static final String MIMETYPE_IMAGE_RAW_DNG = "image/x-raw-adobe";
public static final String MIMETYPE_IMAGE_RAW_3FR = "image/x-raw-hasselblad";
public static final String MIMETYPE_IMAGE_RAW_RAF = "image/x-raw-fuji";
public static final String MIMETYPE_IMAGE_RAW_CR2 = "image/x-raw-canon";
public static final String MIMETYPE_IMAGE_RAW_K25 = "image/x-raw-kodak";
public static final String MIMETYPE_IMAGE_RAW_MRW = "image/x-raw-minolta";
public static final String MIMETYPE_IMAGE_RAW_NEF = "image/x-raw-nikon";
public static final String MIMETYPE_IMAGE_RAW_ORF = "image/x-raw-olympus";
public static final String MIMETYPE_IMAGE_RAW_PEF = "image/x-raw-pentax";
public static final String MIMETYPE_IMAGE_RAW_ARW = "image/x-raw-sony";
public static final String MIMETYPE_IMAGE_RAW_X3F = "image/x-raw-sigma";
public static final String MIMETYPE_IMAGE_RAW_RW2 = "image/x-raw-panasonic";
public static final String MIMETYPE_IMAGE_RAW_RWL = "image/x-raw-leica";
public static final String MIMETYPE_IMAGE_RAW_R3D = "image/x-raw-red";
public static final String MIMETYPE_IMAGE_DWT = "image/x-dwt";
public static final String MIMETYPE_APPLICATION_EPS = "application/eps";
public static final String MIMETYPE_APPLICATION_PS = "application/postscript";
public static final String MIMETYPE_JAVASCRIPT = "application/x-javascript";
public static final String MIMETYPE_ZIP = "application/zip";
public static final String MIMETYPE_OPENSEARCH_DESCRIPTION = "application/opensearchdescription+xml";
public static final String MIMETYPE_ATOM = "application/atom+xml";
public static final String MIMETYPE_RSS = "application/rss+xml";
public static final String MIMETYPE_RFC822 = "message/rfc822";
public static final String MIMETYPE_OUTLOOK_MSG = "application/vnd.ms-outlook";
public static final String MIMETYPE_VISIO = "application/vnd.visio";
public static final String MIMETYPE_VISIO_2013 = "application/vnd.visio2013";
// Adobe
public static final String MIMETYPE_APPLICATION_ILLUSTRATOR = "application/illustrator";
public static final String MIMETYPE_APPLICATION_PHOTOSHOP = "image/vnd.adobe.photoshop";
//Encrypted office document
public static final String MIMETYPE_ENCRYPTED_OFFICE = "application/x-tika-ooxml-protected";
// Open Document
public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text";
public static final String MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE = "application/vnd.oasis.opendocument.text-template";
public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS = "application/vnd.oasis.opendocument.graphics";
public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS_TEMPLATE = "application/vnd.oasis.opendocument.graphics-template";
public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation";
public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION_TEMPLATE = "application/vnd.oasis.opendocument.presentation-template";
public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet";
public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET_TEMPLATE = "application/vnd.oasis.opendocument.spreadsheet-template";
public static final String MIMETYPE_OPENDOCUMENT_CHART = "application/vnd.oasis.opendocument.chart";
public static final String MIMETYPE_OPENDOCUMENT_CHART_TEMPLATE = "applicationvnd.oasis.opendocument.chart-template";
public static final String MIMETYPE_OPENDOCUMENT_IMAGE = "application/vnd.oasis.opendocument.image";
public static final String MIMETYPE_OPENDOCUMENT_IMAGE_TEMPLATE = "applicationvnd.oasis.opendocument.image-template";
public static final String MIMETYPE_OPENDOCUMENT_FORMULA = "application/vnd.oasis.opendocument.formula";
public static final String MIMETYPE_OPENDOCUMENT_FORMULA_TEMPLATE = "applicationvnd.oasis.opendocument.formula-template";
public static final String MIMETYPE_OPENDOCUMENT_TEXT_MASTER = "application/vnd.oasis.opendocument.text-master";
public static final String MIMETYPE_OPENDOCUMENT_TEXT_WEB = "application/vnd.oasis.opendocument.text-web";
public static final String MIMETYPE_OPENDOCUMENT_DATABASE = "application/vnd.oasis.opendocument.database";
// Open Office
public static final String MIMETYPE_OPENOFFICE1_WRITER = "application/vnd.sun.xml.writer";
public static final String MIMETYPE_OPENOFFICE1_CALC = "application/vnd.sun.xml.calc";
public static final String MIMETYPE_OPENOFFICE1_DRAW = "application/vnd.sun.xml.draw";
public static final String MIMETYPE_OPENOFFICE1_IMPRESS = "application/vnd.sun.xml.impress";
// Open XML
public static final String MIMETYPE_OPENXML_WORDPROCESSING = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
public static final String MIMETYPE_OPENXML_WORDPROCESSING_MACRO = "application/vnd.ms-word.document.macroenabled.12";
public static final String MIMETYPE_OPENXML_WORD_TEMPLATE = "application/vnd.openxmlformats-officedocument.wordprocessingml.template";
public static final String MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO = "application/vnd.ms-word.template.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
public static final String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE = "application/vnd.openxmlformats-officedocument.spreadsheetml.template";
public static final String MIMETYPE_OPENXML_SPREADSHEET_MACRO = "application/vnd.ms-excel.sheet.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO = "application/vnd.ms-excel.template.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO = "application/vnd.ms-excel.addin.macroenabled.12";
public static final String MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO = "application/vnd.ms-excel.sheet.binary.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
public static final String MIMETYPE_OPENXML_PRESENTATION_MACRO = "application/vnd.ms-powerpoint.presentation.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW = "application/vnd.openxmlformats-officedocument.presentationml.slideshow";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO = "application/vnd.ms-powerpoint.slideshow.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE = "application/vnd.openxmlformats-officedocument.presentationml.template";
public static final String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO = "application/vnd.ms-powerpoint.template.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_ADDIN = "application/vnd.ms-powerpoint.addin.macroenabled.12";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDE = "application/vnd.openxmlformats-officedocument.presentationml.slide";
public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO = "application/vnd.ms-powerpoint.slide.macroenabled.12";
// Star Office
public static final String MIMETYPE_STAROFFICE5_DRAW = "application/vnd.stardivision.draw";
public static final String MIMETYPE_STAROFFICE5_CALC = "application/vnd.stardivision.calc";
public static final String MIMETYPE_STAROFFICE5_IMPRESS = "application/vnd.stardivision.impress";
public static final String MIMETYPE_STAROFFICE5_IMPRESS_PACKED = "application/vnd.stardivision.impress-packed";
public static final String MIMETYPE_STAROFFICE5_CHART = "application/vnd.stardivision.chart";
public static final String MIMETYPE_STAROFFICE5_WRITER = "application/vnd.stardivision.writer";
public static final String MIMETYPE_STAROFFICE5_WRITER_GLOBAL = "application/vnd.stardivision.writer-global";
public static final String MIMETYPE_STAROFFICE5_MATH = "application/vnd.stardivision.math";
// Apple iWorks
public static final String MIMETYPE_IWORK_KEYNOTE = "application/vnd.apple.keynote";
public static final String MIMETYPE_IWORK_NUMBERS = "application/vnd.apple.numbers";
public static final String MIMETYPE_IWORK_PAGES = "application/vnd.apple.pages";
//MACOS
public static final String MIMETYPE_APPLEFILE = "application/applefile";
// WordPerfect
public static final String MIMETYPE_WORDPERFECT = "application/wordperfect";
// Audio
public static final String MIMETYPE_MP3 = "audio/mpeg";
public static final String MIMETYPE_AUDIO_MP4 = "audio/mp4";
public static final String MIMETYPE_VORBIS = "audio/vorbis";
public static final String MIMETYPE_FLAC = "audio/x-flac";
// Alfresco
public static final String MIMETYPE_ACP = "application/acp";
private static final String CONFIG_AREA = "mimetype-map";
private static final String CONFIG_CONDITION = "Mimetype Map";
private static final String ELEMENT_MIMETYPES = "mimetypes";
private static final String ATTR_MIMETYPE = "mimetype";
private static final String ATTR_DISPLAY = "display";
private static final String ATTR_DEFAULT = "default";
private static final String ATTR_TEXT = "text";
private static final Log logger = LogFactory.getLog(MimetypeMap.class);
private ConfigService configService;
private ContentCharsetFinder contentCharsetFinder;
private TikaConfig tikaConfig;
private Detector detector;
private List<String> mimetypes;
private Map<String, String> extensionsByMimetype;
private Map<String, String> mimetypesByExtension;
private Map<String, String> displaysByMimetype;
private Map<String, String> displaysByExtension;
private Set<String> textMimetypes;
/**
* Default constructor
*
* @since 2.1
*/
public MimetypeMap()
{
}
@Deprecated
public MimetypeMap(ConfigService configService)
{
logger.warn("MimetypeMap(ConfigService configService) has been deprecated. "
+ "Use the default constructor and property 'configService'");
this.configService = configService;
}
public ConfigService getConfigService()
{
return configService;
}
/**
* @param configService the config service to use to read mimetypes from
*/
public void setConfigService(ConfigService configService)
{
this.configService = configService;
}
/**
* {@inheritDoc}
*/
public ContentCharsetFinder getContentCharsetFinder()
{
return contentCharsetFinder;
}
/**
* Set the system default content characterset decoder
*/
public void setContentCharsetFinder(ContentCharsetFinder contentCharsetFinder)
{
this.contentCharsetFinder = contentCharsetFinder;
}
/**
* Injects the TikaConfig to use
*
* @param tikaConfig The Tika Config to use
*/
public void setTikaConfig(TikaConfig tikaConfig)
{
this.tikaConfig = tikaConfig;
}
/**
* Initialises the map using the configuration service provided
*/
public void init()
{
PropertyCheck.mandatory(this, "configService", configService);
PropertyCheck.mandatory(this, "contentCharsetFinder", contentCharsetFinder);
// TikaConfig should be given, but work around it if not
if (tikaConfig == null)
{
logger.warn("TikaConfig spring parameter not supplied, using default config");
setTikaConfig(TikaConfig.getDefaultConfig());
}
// Create our Tika mimetype detector up-front
// We can then be sure we only have the one, so it's quick (ALF-10813)
detector = new DefaultDetector(tikaConfig.getMimeRepository());
// Work out the mappings
this.mimetypes = new ArrayList<String>(40);
this.extensionsByMimetype = new HashMap<String, String>(59);
this.mimetypesByExtension = new HashMap<String, String>(59);
this.displaysByMimetype = new TreeMap<String, String>();
this.displaysByExtension = new HashMap<String, String>(59);
this.textMimetypes = new HashSet<String>(23);
Config config = configService.getConfig(CONFIG_CONDITION, new ConfigLookupContext(CONFIG_AREA));
ConfigElement mimetypesElement = config.getConfigElement(ELEMENT_MIMETYPES);
List<ConfigElement> mimetypes = mimetypesElement.getChildren();
int count = 0;
for (ConfigElement mimetypeElement : mimetypes)
{
count++;
// add to list of mimetypes
String mimetype = mimetypeElement.getAttribute(ATTR_MIMETYPE);
if (mimetype == null || mimetype.length() == 0)
{
logger.warn("Ignoring empty mimetype " + count);
continue;
}
// we store it as lowercase
mimetype = mimetype.toLowerCase();
boolean replacement = this.mimetypes.contains(mimetype);
if (!replacement)
{
this.mimetypes.add(mimetype);
}
// add to map of mimetype displays
String mimetypeDisplay = mimetypeElement.getAttribute(ATTR_DISPLAY);
if (mimetypeDisplay != null && mimetypeDisplay.length() > 0)
{
String prev = this.displaysByMimetype.put(mimetype, mimetypeDisplay);
if (replacement && prev != null && !mimetypeDisplay.equals(prev))
{
logger.warn("Replacing " + mimetype + " " + ATTR_DISPLAY + " value '" + prev + "' with '"
+ mimetypeDisplay + "'");
}
}
// Check if it is a text format
String isTextStr = mimetypeElement.getAttribute(ATTR_TEXT);
boolean isText = Boolean.parseBoolean(isTextStr) || mimetype.startsWith(PREFIX_TEXT);
boolean prevIsText = replacement ? this.textMimetypes.contains(mimetype) : !isText;
if (isText != prevIsText)
{
if (isText)
{
this.textMimetypes.add(mimetype);
}
else if (replacement)
{
this.textMimetypes.remove(mimetype);
}
if (replacement)
{
logger.warn("Replacing " + mimetype + " " + ATTR_TEXT + " value "
+ (prevIsText ? "'true' with 'false'" : "'false' with 'true'"));
}
}
// get all the extensions
List<ConfigElement> extensions = mimetypeElement.getChildren();
for (ConfigElement extensionElement : extensions)
{
// add to map of mimetypes by extension
String extension = extensionElement.getValue();
if (extension == null || extension.length() == 0)
{
logger.warn("Ignoring empty extension for mimetype: " + mimetype);
continue;
}
// put to lowercase
extension = extension.toLowerCase();
this.mimetypesByExtension.put(extension, mimetype);
// add to map of extension displays
String extensionDisplay = extensionElement.getAttribute(ATTR_DISPLAY);
String prev = this.displaysByExtension.get(extension);
// if no display defined for the extension - use the mimetype's
// display
if ((prev == null) && (extensionDisplay == null || extensionDisplay.length() == 0)
&& (mimetypeDisplay != null && mimetypeDisplay.length() > 0))
{
extensionDisplay = mimetypeDisplay;
}
if (extensionDisplay != null)
{
this.displaysByExtension.put(extension, extensionDisplay);
if (prev != null && !extensionDisplay.equals(prev))
{
logger.warn("Replacing " + mimetype + " extension " + ATTR_DISPLAY + " value '" + prev
+ "' with '" + extensionDisplay + "'");
}
}
// add to map of extensions by mimetype if it is the default or
// first extension (prevExtension == null)
String prevExtension = this.extensionsByMimetype.get(mimetype);
String isDefaultStr = extensionElement.getAttribute(ATTR_DEFAULT);
boolean isDefault = Boolean.parseBoolean(isDefaultStr) || prevExtension == null;
if (isDefault)
{
this.extensionsByMimetype.put(mimetype, extension);
if (prevExtension != null && !extension.equals(prevExtension))
{
logger.warn("Replacing " + mimetype + " default extension '" + prevExtension + "' with '"
+ extension + "'");
}
}
}
// check that there were extensions defined
if (extensions.size() == 0)
{
logger.warn("No extensions defined for mimetype: " + mimetype);
}
}
// make the collections read-only
this.mimetypes = Collections.unmodifiableList(this.mimetypes);
this.extensionsByMimetype = Collections.unmodifiableMap(this.extensionsByMimetype);
this.mimetypesByExtension = Collections.unmodifiableMap(this.mimetypesByExtension);
this.displaysByMimetype = Collections.unmodifiableMap(this.displaysByMimetype);
this.displaysByExtension = Collections.unmodifiableMap(this.displaysByExtension);
}
/**
* Get the file extension associated with the mimetype.
*
* @param mimetype a valid mimetype
* @return Returns the default extension for the mimetype. Returns the
* {@link #MIMETYPE_BINARY binary} mimetype extension.
*
* @see #MIMETYPE_BINARY
* @see #EXTENSION_BINARY
*/
public String getExtension(String mimetype)
{
String extension = extensionsByMimetype.get(mimetype);
return (extension == null ? EXTENSION_BINARY : extension);
}
/**
* Get the mimetype for the specified extension
*
* @param extension a valid file extension
* @return Returns a valid mimetype if found, or {@link #MIMETYPE_BINARY
* binary} as default.
*/
@Override
public String getMimetype(String extension)
{
return getMimetype(extension, MIMETYPE_BINARY);
}
/**
* Get the mimetype for the specified extension or returns the supplied default if unknown.
*/
private String getMimetype(String extension, String defaultMimetype)
{
String mimetype = null;
if (extension != null)
{
extension = extension.toLowerCase();
if (mimetypesByExtension.containsKey(extension))
{
mimetype = mimetypesByExtension.get(extension);
}
}
return mimetype == null ? defaultMimetype : mimetype;
}
public Map<String, String> getDisplaysByExtension()
{
return displaysByExtension;
}
public Map<String, String> getDisplaysByMimetype()
{
return displaysByMimetype;
}
public Map<String, String> getExtensionsByMimetype()
{
return extensionsByMimetype;
}
public List<String> getMimetypes()
{
return mimetypes;
}
public Map<String, String> getMimetypesByExtension()
{
return mimetypesByExtension;
}
public boolean isText(String mimetype)
{
return textMimetypes.contains(mimetype);
}
/**
* Use Apache Tika to try to guess the type of the file.
*
* @return The mimetype, or null if we can't tell.
*/
private MediaType detectType(String filename, ContentReader reader)
{
// Metadata metadata = new Metadata();
// if (filename != null)
// {
// metadata.add(Metadata.RESOURCE_NAME_KEY, filename);
// }
TikaInputStream inp = null;
try
{
if (reader != null)
{
if (reader instanceof FileContentReader)
{
try
{
inp = TikaInputStream.get(((FileContentReader) reader).getFile());
}
catch (FileNotFoundException e)
{
logger.warn("No backing file found for ContentReader " + e);
return null;
}
}
else
{
inp = TikaInputStream.get(reader.getContentInputStream());
}
}
return detectType(filename, inp);
}
finally
{
if (inp != null)
{
try
{
inp.close();
}
catch (IOException e)
{
logger.error("Error while closing TikaInputStream.", e);
}
}
}
}
private MediaType detectType(String filename, InputStream input)
{
TikaInputStream inp = null;
if (input != null)
{
inp = TikaInputStream.get(input);
}
return detectType(filename, inp);
}
/**
* Use Apache Tika to try to guess the type of the file.
*
* @return The mimetype, or null if we can't tell.
*/
private MediaType detectType(String filename, TikaInputStream input)
{
Metadata metadata = new Metadata();
if (filename != null)
{
metadata.add(Metadata.RESOURCE_NAME_KEY, filename);
}
InputStream inp = null;
if (input != null)
{
inp = TikaInputStream.get(input);
}
MediaType type;
try
{
type = detector.detect(inp, metadata);
type = typeBasedOnDetectedTypeAndExtension(type, filename);
logger.debug(input + " detected by Tika as being " + type.toString());
}
catch (Exception e)
{
logger.warn("Error identifying content type of problem document", e);
return null;
}
finally
{
if (inp != null)
{
try
{
inp.close();
}
catch (Exception e)
{
// noop
}
}
}
return type;
}
// We have a problem with .ai files, as Tika detects them as .pdf, but if we can use the filename
// we can correct that. Similar problem with .eps and .ps.
private MediaType typeBasedOnDetectedTypeAndExtension(MediaType type, String filename)
{
if (filename != null && type != null)
{
String[] detectedAndPossibleTypes = new String[]
{
MIMETYPE_PDF, MIMETYPE_APPLICATION_ILLUSTRATOR,
MIMETYPE_APPLICATION_PS, MIMETYPE_APPLICATION_EPS
};
for (int i=detectedAndPossibleTypes.length-1; i>=0; i-=2)
{
String detectedType = detectedAndPossibleTypes[i-1];
if (detectedType.equals(type.toString()))
{
String possibleType = detectedAndPossibleTypes[i];
String extension = getExtension(possibleType);
if (filename.endsWith("."+extension))
{
type = MediaType.parse(possibleType);
break;
}
}
}
}
return type;
}
/**
* Use Apache Tika to check if the mime type of the document really matches
* what it claims to be. This is typically used when a transformation or
* metadata extractions fails, and you want to know if someone has renamed a
* file and consequently it has the wrong mime type.
*
* @return Null if the mime type seems ok, otherwise the mime type it
* probably is
*/
public String getMimetypeIfNotMatches(ContentReader reader)
{
MediaType type = detectType(null, reader);
if (type == null)
{
// Tika doesn't know so we can't help, sorry...
return null;
}
// Is it a good match?
if (type.toString().equals(reader.getMimetype())) { return null; }
// Is it close?
MediaType claimed = MediaType.parse(reader.getMimetype());
if (tikaConfig.getMediaTypeRegistry().isSpecializationOf(claimed, type)
|| tikaConfig.getMediaTypeRegistry().isSpecializationOf(type, claimed))
{
// Probably close enough
return null;
}
// Check through known aliases of the type
SortedSet<MediaType> aliases = tikaConfig.getMediaTypeRegistry().getAliases(type);
for (MediaType alias : aliases)
{
String aliasType = alias.toString();
if (aliasType.equals(claimed.toString()))
{
return null;
}
}
// If we get here, then most likely the type is wrong
return type.toString();
}
/**
* Takes a guess at the mimetype based exclusively on the file extension,
* which can (and often is) wrong...
*
* @see #MIMETYPE_BINARY
*/
public String guessMimetype(String filename)
{
String mimetype = MIMETYPE_BINARY;
// Extract the extension
if (filename != null && filename.length() > 0)
{
int index = filename.lastIndexOf('.');
if (index > -1 && (index < filename.length() - 1))
{
String extension = filename.substring(index + 1).toLowerCase();
if (mimetypesByExtension.containsKey(extension))
{
mimetype = mimetypesByExtension.get(extension);
}
}
}
return mimetype;
}
/**
* Uses Tika to try to identify the mimetype of the file, falling back on
* {@link #guessMimetype(String)} for an extension based one if Tika can't
* help.
*/
public String guessMimetype(String filename, ContentReader reader)
{
// ALF-10813: MimetypeMap.guessMimetype consumes 30% of file upload time
// Let's only 'guess' if we need to
if (reader != null && reader.getMimetype() != null && !reader.getMimetype().equals(MimetypeMap.MIMETYPE_BINARY))
{
// It was set to something other than the default.
// Possibly someone used this method before (like the UI does) or
// they just
// know what their files are.
return reader.getMimetype();
}
InputStream input = (reader != null ? reader.getContentInputStream() : null);
return guessMimetype(filename, input);
}
/**
* Uses Tika to try to identify the mimetype of the file, falling back on
* {@link #guessMimetype(String)} for an extension based one if Tika can't
* help.
*/
public String guessMimetype(String filename, InputStream input)
{
MediaType type = detectType(filename, input);
String filenameGuess = guessMimetype(filename);
// If Tika doesn't know what the type is, or file is password protected, go with the filename one
if (type == null || MediaType.OCTET_STREAM.equals(type) || MIMETYPE_ENCRYPTED_OFFICE.equals(type.toString())) { return filenameGuess; }
// If Tika has supplied a very generic type, go with the filename one,
// as it's probably a custom Text or XML format known only to Alfresco
if ((MediaType.TEXT_PLAIN.equals(type) || MediaType.APPLICATION_XML.equals(type)) && (! filenameGuess.equals(MIMETYPE_BINARY)))
{
return filenameGuess;
}
// Alfresco doesn't support mimetype parameters
// Use the form of the mimetype without any
if (type.hasParameters())
{
type = type.getBaseType();
}
// Not all the mimetypes we use are the Tika Canonical one.
// So, detect when this happens and use ours in preference
String tikaType = type.toString();
if (mimetypes.contains(tikaType))
{
// Alfresco and Tika agree!
return tikaType;
}
// Check the aliases
SortedSet<MediaType> aliases = tikaConfig.getMediaTypeRegistry().getAliases(type);
for (MediaType alias : aliases)
{
String aliasType = alias.toString();
if (mimetypes.contains(aliasType)) { return aliasType; }
}
// If we get here, then Tika has identified something that
// Alfresco doesn't really know about. Just trust Tika on it
logger.info("Tika detected a type of " + tikaType + " for file " + filename
+ " which Alfresco doesn't know about. Consider " + " adding that type to your configuration");
return tikaType;
}
/**
* Returns a collection of mimetypes ordered by extension.
* @param extension to restrict the collection to one entry
*/
public Collection<String> getMimetypes(String extension)
{
Collection<String> sourceMimetypes;
if (extension == null)
{
sourceMimetypes = getMimetypes();
sourceMimetypes = sortMimetypesByExt(sourceMimetypes);
}
else
{
String mimetype = getMimetype(extension, null);
if (mimetype == null)
{
sourceMimetypes = Collections.emptySet();
}
else
{
sourceMimetypes = Collections.singleton(mimetype);
}
}
return sourceMimetypes;
}
/**
* Copies and sorts the supplied mimetypes by their file extensions
* @param mimetypes to be sorted
* @return a new List of sorted mimetypes
*/
private Collection<String> sortMimetypesByExt(Collection<String> mimetypes)
{
List<String> result = new ArrayList<String>(mimetypes);
for (int i=result.size()-1; i>= 0; i--)
{
result.set(i, getExtension(result.get(i)));
}
Collections.sort(result);
for (int i=result.size()-1; i>= 0; i--)
{
result.set(i, getMimetype(result.get(i)));
}
return result;
}
}

View File

@@ -0,0 +1,117 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.encoding;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.List;
import org.alfresco.encoding.CharactersetFinder;
import org.alfresco.service.cmr.repository.MimetypeService;
/**
* Utility bean to guess the charset given a stream and a mimetype.
*
* @since 2.1
* @author Derek Hulley
*/
public class ContentCharsetFinder
{
private Charset defaultCharset = Charset.defaultCharset();
private MimetypeService mimetypeService;
private List<CharactersetFinder> charactersetFinders;
/**
* Override the system default charset. Where the characterset cannot be determined for
* a mimetype and input stream, this mimetype will be used. The default is 'UTF-8'.
*
* @param defaultCharset the default characterset
*/
public void setDefaultCharset(String defaultCharset)
{
this.defaultCharset = Charset.forName(defaultCharset);
}
/**
* Set the mimetype service that will help determine if a particular mimetype can be
* treated as encoded text or not.
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
/**
* Set the list of characterset finder to execute, in order, for text based content.
* @param charactersetFinders a list of finders
*/
public void setCharactersetFinders(List<CharactersetFinder> charactersetFinders)
{
this.charactersetFinders = charactersetFinders;
}
/**
* Gets the characterset from the stream, if the mimetype is text and the text
* has enough information to give the encoding away. Otherwise, the default
* is returned.
*
* @param is a stream that will not be affected by the call, but must
* support marking
* @param mimetype the mimetype of the stream data - <tt>null</tt> if not known
* @return returns a characterset and never <tt>null</tt>
*/
public Charset getCharset(InputStream is, String mimetype)
{
if (mimetype == null)
{
return defaultCharset;
}
// Is it text?
if (!mimetypeService.isText(mimetype))
{
return defaultCharset;
}
// Try the finders
Charset charset = null;
for (CharactersetFinder finder : charactersetFinders)
{
charset = finder.detectCharset(is);
if (charset != null)
{
break;
}
}
// Done
if (charset == null)
{
return defaultCharset;
}
else
{
return charset;
}
}
}

View File

@@ -0,0 +1,726 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* @author sglover
*
*/
public abstract class AbstractDictionaryRegistry implements DictionaryRegistry
{
protected static final Log logger = LogFactory.getLog(AbstractDictionaryRegistry.class);
protected DictionaryDAO dictionaryDAO;
private Map<String, List<CompiledModel>> uriToModels = new ConcurrentHashMap<String, List<CompiledModel>>(0);
private Map<QName,CompiledModel> compiledModels = new ConcurrentHashMap<QName,CompiledModel>(0);
// namespaces
private ReadWriteLock urisCacheRWLock = new ReentrantReadWriteLock(true);
private List<String> urisCache = new ArrayList<String>(20);
private Map<String, String> prefixesCache = new ConcurrentHashMap<String, String>(0);
public AbstractDictionaryRegistry(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
@Override
public void clear()
{
setCompiledModels(new HashMap<QName,CompiledModel>());
setUriToModels(new HashMap<String, List<CompiledModel>>());
}
public Map<String, List<CompiledModel>> getUriToModels()
{
Map<String, List<CompiledModel>> ret = new HashMap<>();
ret.putAll(uriToModels); // copy
return ret;
}
private void setUriToModels(Map<String, List<CompiledModel>> uriToModels)
{
this.uriToModels = uriToModels;
}
@Override
public Map<QName, CompiledModel> getCompiledModels(boolean includeInherited)
{
return compiledModels;
}
private void setCompiledModels(Map<QName, CompiledModel> compiledModels)
{
this.compiledModels = compiledModels;
}
public List<CompiledModel> getModelsForUri(String uri)
{
return getModelsForUriImpl(uri);
}
@Override
public QName putModel(CompiledModel model)
{
return putModelImpl(model);
}
@Override
public CompiledModel getModel(QName modelName)
{
CompiledModel model = getModelImpl(modelName);
if(model == null)
{
throw new DictionaryException("d_dictionary.model.err.no_model", modelName);
}
return model;
}
@Override
public boolean modelExists(QName modelName)
{
CompiledModel model = getModelImpl(modelName);
return model != null;
}
@Override
public void removeModel(QName modelName)
{
removeModelImpl(modelName);
}
protected CompiledModel removeModelImpl(QName modelName)
{
CompiledModel compiledModel = compiledModels.get(modelName);
if (compiledModel != null)
{
// Remove the namespaces from the namespace service
M2Model model = compiledModel.getM2Model();
for (M2Namespace namespace : model.getNamespaces())
{
prefixesCache.remove(namespace.getPrefix());
urisCacheRWLock.writeLock().lock();
try
{
urisCache.remove(namespace.getUri());
}
finally
{
urisCacheRWLock.writeLock().unlock();
}
List<CompiledModel> models = uriToModels.get(namespace.getUri());
if(models != null)
{
models.remove(compiledModel);
}
}
compiledModels.remove(modelName);
}
return compiledModel;
}
protected CompiledModel getModelImpl(QName modelName)
{
CompiledModel model = compiledModels.get(modelName);
return model;
}
protected List<CompiledModel> getModelsForUriImpl(String uri)
{
List<CompiledModel> models = uriToModels.get(uri);
if(models == null)
{
models = Collections.emptyList();
}
// defensive copy
return new ArrayList<CompiledModel>(models);
}
protected void unmapUriToModel(String uri, CompiledModel model)
{
List<CompiledModel> models = uriToModels.get(uri);
if (models != null)
{
models.remove(model);
}
}
protected void mapUriToModel(String uri, CompiledModel model)
{
List<CompiledModel> models = uriToModels.get(uri);
if (models == null)
{
models = new ArrayList<CompiledModel>();
uriToModels.put(uri, models);
}
if (!models.contains(model))
{
models.add(model);
}
}
protected QName putModelImpl(CompiledModel model)
{
QName modelName = model.getModelDefinition().getName();
CompiledModel previousVersion = getModelImpl(modelName);
if (previousVersion != null)
{
for (M2Namespace namespace : previousVersion.getM2Model().getNamespaces())
{
prefixesCache.remove(namespace.getPrefix());
urisCacheRWLock.writeLock().lock();
try
{
urisCache.remove(namespace.getUri());
}
finally
{
urisCacheRWLock.writeLock().unlock();
}
unmapUriToModel(namespace.getUri(), previousVersion);
}
for (M2Namespace importNamespace : previousVersion.getM2Model().getImports())
{
unmapUriToModel(importNamespace.getUri(), previousVersion);
}
}
// Create namespace definitions for new model
M2Model m2Model = model.getM2Model();
for (M2Namespace namespace : m2Model.getNamespaces())
{
addURI(namespace.getUri());
addPrefix(namespace.getPrefix(), namespace.getUri());
mapUriToModel(namespace.getUri(), model);
}
for (M2Namespace importNamespace : m2Model.getImports())
{
mapUriToModel(importNamespace.getUri(), model);
}
compiledModels.put(modelName, model);
return modelName;
}
@Override
public AspectDefinition getAspect(QName aspectName)
{
return getAspectImpl(aspectName);
}
protected AspectDefinition getAspectImpl(QName aspectName)
{
AspectDefinition aspect = null;
if(aspectName != null)
{
List<CompiledModel> models = uriToModels.get(aspectName.getNamespaceURI());
if(models != null && models.size() > 0)
{
for (CompiledModel model : models)
{
aspect = model.getAspect(aspectName);
if(aspect != null)
{
break;
}
}
}
}
return aspect;
}
@Override
public AssociationDefinition getAssociation(QName assocName)
{
return getAssociationImpl(assocName);
}
protected AssociationDefinition getAssociationImpl(QName assocName)
{
AssociationDefinition assocDef = null;
List<CompiledModel> models = getModelsForUri(assocName.getNamespaceURI());
if(models != null && models.size() > 0)
{
for (CompiledModel model : models)
{
assocDef = model.getAssociation(assocName);
if(assocDef != null)
{
break;
}
}
}
return assocDef;
}
@Override
public ClassDefinition getClass(QName className)
{
return getClassImpl(className);
}
protected ClassDefinition getClassImpl(QName className)
{
ClassDefinition classDef = null;
List<CompiledModel> models = getModelsForUri(className.getNamespaceURI());
if(models != null && models.size() > 0)
{
for (CompiledModel model : models)
{
classDef = model.getClass(className);
if (classDef != null)
{
break;
}
}
}
return classDef;
}
@Override
public PropertyDefinition getProperty(QName propertyName)
{
return getPropertyImpl(propertyName);
}
protected PropertyDefinition getPropertyImpl(QName propertyName)
{
PropertyDefinition propDef = null;
List<CompiledModel> models = getModelsForUri(propertyName.getNamespaceURI());
if(models != null && models.size() > 0)
{
for (CompiledModel model : models)
{
propDef = model.getProperty(propertyName);
if(propDef != null)
{
break;
}
}
}
return propDef;
}
@Override
public TypeDefinition getType(QName typeName)
{
return getTypeImpl(typeName);
}
protected TypeDefinition getTypeImpl(QName typeName)
{
TypeDefinition typeDef = null;
if (typeName != null)
{
List<CompiledModel> models = getModelsForUri(typeName.getNamespaceURI());
if(models != null && models.size() > 0)
{
for (CompiledModel model : models)
{
typeDef = model.getType(typeName);
if(typeDef != null)
{
break;
}
}
}
}
return typeDef;
}
@Override
public ConstraintDefinition getConstraint(QName constraintQName)
{
return getConstraintImpl(constraintQName);
}
protected ConstraintDefinition getConstraintImpl(QName constraintQName)
{
ConstraintDefinition constraintDef = null;
List<CompiledModel> models = getModelsForUri(constraintQName.getNamespaceURI());
if(models != null && models.size() > 0)
{
for (CompiledModel model : models)
{
constraintDef = model.getConstraint(constraintQName);
if(constraintDef != null)
{
break;
}
}
}
return constraintDef;
}
@Override
public DataTypeDefinition getDataType(QName typeName)
{
return getDataTypeImp(typeName);
}
protected DataTypeDefinition getDataTypeImp(QName typeName)
{
DataTypeDefinition dataType = null;
if (typeName != null)
{
List<CompiledModel> models = getModelsForUri(typeName.getNamespaceURI());
if(models != null && models.size() > 0)
{
for (CompiledModel model : models)
{
dataType = model.getDataType(typeName);
if(dataType != null)
{
break;
}
}
}
}
return dataType;
}
@SuppressWarnings("rawtypes")
@Override
public DataTypeDefinition getDataType(Class javaClass)
{
return getDataTypeImpl(javaClass);
}
@SuppressWarnings("rawtypes")
protected DataTypeDefinition getDataTypeImpl(Class javaClass)
{
DataTypeDefinition dataTypeDef = null;
if (javaClass != null)
{
for (CompiledModel model : getCompiledModels(true).values())
{
dataTypeDef = model.getDataType(javaClass);
if(dataTypeDef != null)
{
break;
}
}
}
return dataTypeDef;
}
protected Map<String, String> getPrefixesCacheImpl()
{
return prefixesCache;
}
@Override
public Map<String, String> getPrefixesCache()
{
return getPrefixesCacheImpl();
}
@Override
public List<String> getUrisCache()
{
return getUrisCacheImpl();
}
protected List<String> getUrisCacheImpl()
{
urisCacheRWLock.readLock().lock();
try
{
return new ArrayList<String>(urisCache);
}
finally
{
urisCacheRWLock.readLock().unlock();
}
}
@Override
public Collection<String> getPrefixes(String URI)
{
return getPrefixesImpl(URI);
}
protected Collection<String> getPrefixesImpl(String URI)
{
Collection<String> prefixes = new ArrayList<String>();
for (String key : prefixesCache.keySet())
{
String uri = prefixesCache.get(key);
if ((uri != null) && (uri.equals(URI)))
{
prefixes.add(key);
}
}
return prefixes;
}
@Override
public void addURI(String uri)
{
addURIImpl(uri);
}
protected void addURIImpl(String uri)
{
if(hasURI(uri))
{
throw new NamespaceException("URI " + uri + " has already been defined");
}
urisCacheRWLock.writeLock().lock();
try
{
urisCache.add(uri);
}
finally
{
urisCacheRWLock.writeLock().unlock();
}
}
@Override
public boolean hasURI(String uri)
{
urisCacheRWLock.readLock().lock();
try
{
return urisCache.contains(uri);
}
finally
{
urisCacheRWLock.readLock().unlock();
}
}
@Override
public void addPrefix(String prefix, String uri)
{
addPrefixImpl(prefix, uri);
}
@Override
public boolean hasPrefix(String prefix)
{
return prefixesCache.containsKey(prefix);
}
protected void addPrefixImpl(String prefix, String uri)
{
urisCacheRWLock.readLock().lock();
try
{
if(!urisCache.contains(uri))
{
throw new NamespaceException("Namespace URI " + uri + " does not exist");
}
if (prefixesCache.containsKey(prefix))
{
throw new NamespaceException(
String.format("Namespace prefix '%s' is already in use for URI '%s' so cannot be registered for URI '%s'",
prefix,
prefixesCache.get(prefix),
uri));
}
prefixesCache.put(prefix, uri);
}
finally
{
urisCacheRWLock.readLock().unlock();
}
}
@Override
public void removeURI(String uri)
{
removeURIImpl(uri);
}
@Override
public void removePrefix(String prefix)
{
removePrefixImpl(prefix);
}
protected boolean removeURIImpl(String uri)
{
urisCacheRWLock.writeLock().lock();
try
{
return urisCache.remove(uri);
}
finally
{
urisCacheRWLock.writeLock().unlock();
}
}
protected boolean removePrefixImpl(String prefix)
{
return (prefixesCache.remove(prefix) != null);
}
@Override
public Collection<QName> getTypes(boolean includeInherited)
{
Collection<QName> types = new ArrayList<QName>(100);
for (QName model : getCompiledModels(includeInherited).keySet())
{
for(TypeDefinition typeDef : getModel(model).getTypes())
{
types.add(typeDef.getName());
}
}
return types;
}
@Override
public Collection<QName> getAssociations(boolean includeInherited)
{
Collection<QName> types = new ArrayList<QName>(100);
for (QName model : getCompiledModels(includeInherited).keySet())
{
for(AssociationDefinition assocDef : getModel(model).getAssociations())
{
types.add(assocDef.getName());
}
}
return types;
}
@Override
public Collection<QName> getAspects(boolean includeInherited)
{
Collection<QName> types = new ArrayList<QName>(100);
for (QName model : getCompiledModels(includeInherited).keySet())
{
for(AspectDefinition aspectDef : getModel(model).getAspects())
{
types.add(aspectDef.getName());
}
}
return types;
}
protected abstract void initImpl();
@Override
public void init()
{
initImpl();
}
protected abstract void removeImpl();
@Override
public void remove()
{
uriToModels.clear();
compiledModels.clear();
urisCacheRWLock.writeLock().lock();
try
{
urisCache.clear();
}
finally
{
urisCacheRWLock.writeLock().unlock();
}
prefixesCache.clear();
removeImpl();
}
@Override
public boolean isModelInherited(QName modelName)
{
CompiledModel model = compiledModels.get(modelName);
return (model != null);
}
@Override
public String getNamespaceURI(String prefix)
{
String namespaceURI = null;
if(prefix != null)
{
namespaceURI = getPrefixesCache().get(prefix);
}
return namespaceURI;
}
}

View File

@@ -0,0 +1,462 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import static org.alfresco.service.cmr.dictionary.DictionaryException.DuplicateDefinitionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.DynamicNamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Compiled representation of a model definition.
*
* In this case, compiled means that
* a) all references between model items have been resolved
* b) inheritence of class features have been flattened
* c) overridden class features have been resolved
*
* A compiled model also represents a valid model.
*
* @author David Caruana
*
*/
public class CompiledModel implements ModelQuery
{
// Logger
private static final Log logger = LogFactory.getLog(DictionaryDAOImpl.class);
private static final String ERR_COMPILE_MODEL_FAILURE = "d_dictionary.compiled_model.err.compile.failure";
private static final String ERR_DUPLICATE_PROPERTY_TYPE = "d_dictionary.compiled_model.err.duplicate_property_type";
private static final String ERR_DUPLICATE_TYPE = "d_dictionary.compiled_model.err.duplicate_type";
private static final String ERR_DUPLICATE_ASPECT = "d_dictionary.compiled_model.err.duplicate_aspect";
private static final String ERR_DUPLICATE_CONSTRAINT = "d_dictionary.compiled_model.err.duplicate_constraint";
private static final String ERR_CYCLIC_REFERENCE = "d_dictionary.compiled_model.err.cyclic_ref";
private M2Model model;
private ModelDefinition modelDefinition;
private Map<QName, DataTypeDefinition> dataTypes = new HashMap<QName, DataTypeDefinition>();
private Map<QName, ClassDefinition> classes = new HashMap<QName, ClassDefinition>();
private Map<QName, TypeDefinition> types = new HashMap<QName, TypeDefinition>();
private Map<QName, AspectDefinition> aspects = new HashMap<QName, AspectDefinition>();
private Map<QName, PropertyDefinition> properties = new HashMap<QName, PropertyDefinition>();
private Map<QName, AssociationDefinition> associations = new HashMap<QName, AssociationDefinition>();
private Map<QName, ConstraintDefinition> constraints = new HashMap<QName, ConstraintDefinition>();
/**
* Construct
*
* @param model model definition
* @param dictionaryDAO dictionary DAO
* @param namespaceDAO namespace DAO
*/
/*package*/ CompiledModel(M2Model model, DictionaryDAO dictionaryDAO, NamespaceDAO namespaceDAO, boolean enableConstraintClassLoading)
{
try
{
// Phase 1: Construct model definitions from model entries
// resolving qualified names
this.model = model;
constructDefinitions(model, namespaceDAO, dictionaryDAO);
// Phase 2: Resolve dependencies between model definitions
ModelQuery query = new DelegateModelQuery(this, dictionaryDAO);
resolveDependencies(query, namespaceDAO);
// Phase 3: Resolve inheritance of values within class hierachy
NamespacePrefixResolver localPrefixes = createLocalPrefixResolver(model, namespaceDAO);
resolveInheritance(query, localPrefixes, constraints);
// Phase 4: Resolve constraint dependencies
for (ConstraintDefinition def : constraints.values())
{
((M2ConstraintDefinition)def).resolveDependencies(query, enableConstraintClassLoading);
}
}
catch(Exception e)
{
if (logger.isDebugEnabled())
{
logger.debug("Failed to compile model: " + model.getName(), e);
}
throw new DictionaryException(ERR_COMPILE_MODEL_FAILURE, e, model.getName());
}
}
/**
* @return the model definition
*/
public M2Model getM2Model()
{
return model;
}
/**
* Construct compiled definitions
*
* @param model model definition
* @param namespaceDAO namespace DAO
*/
private void constructDefinitions(M2Model model, NamespaceDAO namespaceDAO, DictionaryDAO dictionaryDAO)
{
NamespacePrefixResolver localPrefixes = createLocalPrefixResolver(model, namespaceDAO);
// Construct Model Definition
modelDefinition = new M2ModelDefinition(model, localPrefixes, dictionaryDAO);
// Construct Property Types
for (M2DataType propType : model.getPropertyTypes())
{
M2DataTypeDefinition def = new M2DataTypeDefinition(modelDefinition, propType, localPrefixes);
if (dataTypes.containsKey(def.getName()))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_TYPE, propType.getName());
}
dataTypes.put(def.getName(), def);
}
// Construct Type Definitions
for (M2Type type : model.getTypes())
{
M2TypeDefinition def = new M2TypeDefinition(modelDefinition, type, localPrefixes, properties, associations);
if (classes.containsKey(def.getName()))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_TYPE, type.getName());
}
classes.put(def.getName(), def);
types.put(def.getName(), def);
}
// Construct Aspect Definitions
for (M2Aspect aspect : model.getAspects())
{
M2AspectDefinition def = new M2AspectDefinition(modelDefinition, aspect, localPrefixes, properties, associations);
if (classes.containsKey(def.getName()))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_ASPECT, aspect.getName());
}
classes.put(def.getName(), def);
aspects.put(def.getName(), def);
}
// Construct Constraint Definitions
for (M2Constraint constraint : model.getConstraints())
{
M2ConstraintDefinition def = new M2ConstraintDefinition(modelDefinition, null, constraint, localPrefixes);
QName qname = def.getName();
if (constraints.containsKey(qname))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_CONSTRAINT, constraint.getName());
}
constraints.put(qname, def);
}
}
/**
* Create a local namespace prefix resolver containing the namespaces defined and imported
* in the model
*
* @param model model definition
* @param namespaceDAO namespace DAO
* @return the local namespace prefix resolver
*/
private NamespacePrefixResolver createLocalPrefixResolver(M2Model model, NamespaceDAO namespaceDAO)
{
// Retrieve set of existing URIs for validation purposes
Collection<String> uris = namespaceDAO.getURIs();
// Create a namespace prefix resolver based on imported and defined
// namespaces within the model
DynamicNamespacePrefixResolver prefixResolver = new DynamicNamespacePrefixResolver(null);
for (M2Namespace imported : model.getImports())
{
String uri = imported.getUri();
if (!uris.contains(uri))
{
throw new NamespaceException("URI " + uri + " cannot be imported as it is not defined (with prefix " + imported.getPrefix());
}
if(model.getNamespace(uri) != null)
{
throw new NamespaceException("URI " + uri + " cannot be imported as it is already contained in the model's namespaces");
}
prefixResolver.registerNamespace(imported.getPrefix(), uri);
}
for (M2Namespace defined : model.getNamespaces())
{
prefixResolver.registerNamespace(defined.getPrefix(), defined.getUri());
}
return prefixResolver;
}
/**
* Resolve dependencies between model items
*
* @param query support for querying other items in model
*/
private void resolveDependencies(ModelQuery query, NamespaceDAO namespaceDAO)
{
NamespacePrefixResolver prefixResolver = createLocalPrefixResolver(model, namespaceDAO);
for (DataTypeDefinition def : dataTypes.values())
{
((M2DataTypeDefinition)def).resolveDependencies(query);
}
for (ClassDefinition def : classes.values())
{
((M2ClassDefinition)def).resolveDependencies(query, prefixResolver, constraints);
}
}
/**
* Resolve class feature inheritence
*
* @param query support for querying other items in model
*/
private void resolveInheritance(
ModelQuery query,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
// Calculate order of class processing (root to leaf)
Map<Integer,List<ClassDefinition>> order = new TreeMap<Integer,List<ClassDefinition>>();
for (ClassDefinition def : classes.values())
{
// Calculate class depth in hierarchy
int depth = 0;
QName parentName = def.getParentName();
Set<ClassDefinition> traversedNodes = new HashSet<ClassDefinition>();
traversedNodes.add(def);
while (parentName != null)
{
ClassDefinition parentClass = getClass(parentName);
if (parentClass == null)
{
break;
}
if (traversedNodes.contains(parentClass))
{
throw new DictionaryException(ERR_CYCLIC_REFERENCE, parentClass.getName(), model.getName());
}
depth = depth +1;
traversedNodes.add(parentClass);
parentName = parentClass.getParentName();
}
// Map class to depth
List<ClassDefinition> classes = order.get(depth);
if (classes == null)
{
classes = new ArrayList<ClassDefinition>();
order.put(depth, classes);
}
classes.add(def);
if (logger.isTraceEnabled())
{
logger.trace("Resolving inheritance: class " + def.getName() + " found at depth " + depth);
}
}
// Resolve inheritance of each class
for (int depth = 0; depth < order.size(); depth++)
{
for (ClassDefinition def : order.get(depth))
{
((M2ClassDefinition)def).resolveInheritance(query, prefixResolver, modelConstraints);
}
}
}
/**
* @return the compiled model definition
*/
public ModelDefinition getModelDefinition()
{
return modelDefinition;
}
/**
* @return the compiled property types
*/
public Collection<DataTypeDefinition> getDataTypes()
{
return dataTypes.values();
}
/**
* @return the compiled types
*/
public Collection<TypeDefinition> getTypes()
{
return types.values();
}
/**
* @return the compiled aspects
*/
public Collection<AspectDefinition> getAspects()
{
return aspects.values();
}
/**
*
* @return the compiled properties
*/
public Collection<PropertyDefinition> getProperties()
{
return properties.values();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getPropertyType(org.alfresco.repo.ref.QName)
*/
public DataTypeDefinition getDataType(QName name)
{
return dataTypes.get(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ModelQuery#getDataType(java.lang.Class)
*/
public DataTypeDefinition getDataType(Class javaClass)
{
for (DataTypeDefinition dataTypeDef : dataTypes.values())
{
if (dataTypeDef.getJavaClassName().equals(javaClass.getName()))
{
return dataTypeDef;
}
}
return null;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getType(org.alfresco.repo.ref.QName)
*/
public TypeDefinition getType(QName name)
{
return types.get(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getAspect(org.alfresco.repo.ref.QName)
*/
public AspectDefinition getAspect(QName name)
{
return aspects.get(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getClass(org.alfresco.repo.ref.QName)
*/
public ClassDefinition getClass(QName name)
{
return classes.get(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getProperty(org.alfresco.repo.ref.QName)
*/
public PropertyDefinition getProperty(QName name)
{
return properties.get(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getAssociation(org.alfresco.repo.ref.QName)
*/
public AssociationDefinition getAssociation(QName name)
{
return associations.get(name);
}
/**
* @return the compiled associations
*/
public Collection<AssociationDefinition> getAssociations()
{
return associations.values();
}
/**
* @return the compiled constraints
*/
public Collection<ConstraintDefinition> getConstraints()
{
return constraints.values();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getConstraint(QName)
*/
public ConstraintDefinition getConstraint(QName name)
{
return constraints.get(name);
}
}

View File

@@ -0,0 +1,154 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.util.cache.AbstractAsynchronouslyRefreshedCache;
import org.alfresco.util.cache.RefreshableCacheEvent;
import org.alfresco.util.cache.RefreshableCacheListener;
import org.alfresco.util.cache.RefreshableCacheRefreshedEvent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Asynchronously refreshed cache for dictionary models.
*/
public class CompiledModelsCache extends AbstractAsynchronouslyRefreshedCache<DictionaryRegistry>
{
private static Log logger = LogFactory.getLog(CompiledModelsCache.class);
private DictionaryDAOImpl dictionaryDAO;
private TenantService tenantService;
@Override
protected DictionaryRegistry buildCache(String tenantId)
{
if (tenantId == null)
{
tenantId = tenantService.getCurrentUserDomain();
}
final String finalTenant = tenantId;
return AuthenticationUtil.runAs(new RunAsWork<DictionaryRegistry>()
{
public DictionaryRegistry doWork() throws Exception
{
return dictionaryDAO.initDictionaryRegistry(finalTenant);
}
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantId));
}
/**
* @param tenantId the tenantId of cache that will be removed from live cache
* @return removed DictionaryRegistry
*/
public void remove(final String tenantId)
{
//TODO Should be reworked when ACE-2001 will be implemented
liveLock.writeLock().lock();
try
{
DictionaryRegistry dictionaryRegistry = live.get(tenantId);
if (dictionaryRegistry != null)
{
live.remove(tenantId);
dictionaryRegistry.remove();
if (logger.isDebugEnabled())
{
logger.debug("Removed dictionary register for tenant " + tenantId);
}
}
}
finally
{
liveLock.writeLock().unlock();
}
}
/**
* @param dictionaryDAO the dictionaryDAOImpl to set
*/
public void setDictionaryDAO(DictionaryDAOImpl dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
/**
* @param tenantService the tenantService to set
*/
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
@Override
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
// RefreshableCacheListener as anonymous class since CompileModelsCache already
// implements this interface, but expects to be invoked in different circumstances.
register(new RefreshableCacheListener()
{
@Override
public void onRefreshableCacheEvent(RefreshableCacheEvent event)
{
if (logger.isDebugEnabled())
{
logger.debug("Handling "+event.getClass().getSimpleName()+
", cache="+event.getCacheId()+
", key="+event.getKey());
}
if (event instanceof RefreshableCacheRefreshedEvent &&
event.getCacheId().equals(getCacheId()))
{
// notify registered listeners that dictionary has been initialised (population is complete).
// Note we do that here to ensure that the dictionary registry has been added to the cache,
// so that any dependencies (like the CMIS dictionary) will use the new dictionary.
for (DictionaryListener dictionaryListener : dictionaryDAO.getDictionaryListeners())
{
logger.debug("Calling afterDIctionaryInit ["+event.getClass().getSimpleName()+
", cache="+event.getCacheId()+
", key="+event.getKey()+
"] on "+
dictionaryListener.getClass().getSimpleName());
dictionaryListener.afterDictionaryInit();
}
}
}
@Override
public String getCacheId()
{
return CompiledModelsCache.this.getCacheId();
}
});
}
}

View File

@@ -0,0 +1,96 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.Map;
import org.alfresco.service.namespace.QName;
/**
* Core dictionary registry (holding core models initialised at bootstrap).
*
* @author sglover
*
*/
public class CoreDictionaryRegistryImpl extends AbstractDictionaryRegistry
{
public CoreDictionaryRegistryImpl(DictionaryDAO dictionaryDAO)
{
super(dictionaryDAO);
}
@Override
public String getTenantDomain()
{
return null;
}
@Override
protected void initImpl()
{
long startTime = System.currentTimeMillis();
// populate the dictionary based on registered sources (only for core registry)
for (DictionaryListener dictionaryDeployer : dictionaryDAO.getDictionaryListeners())
{
dictionaryDeployer.onDictionaryInit();
}
// Done
if (logger.isInfoEnabled())
{
Map<QName, CompiledModel> models = getCompiledModels(false);
logger.info("Init core dictionary: model count = "+(models != null ? models.size() : 0)
+" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"]");
}
}
@Override
public void remove()
{
for(DictionaryListener listener : dictionaryDAO.getDictionaryListeners())
{
listener.afterDictionaryDestroy();
}
}
@Override
protected QName putModelImpl(CompiledModel model)
{
// TODO disallow model overrides for the core dictionary
QName qname = super.putModelImpl(model);
return qname;
}
@Override
public void removeImpl()
{
for(DictionaryListener listener : dictionaryDAO.getDictionaryListeners())
{
listener.afterDictionaryDestroy();
}
}
}

View File

@@ -0,0 +1,215 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.CustomModelDefinition;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.QName;
/**
* Read-only definition of a Custom Model
*
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelDefinitionImpl implements CustomModelDefinition
{
private final ModelDefinition m2ModelDefinition;
private final boolean active;
private final MessageLookup messageLookup;
private final Collection<TypeDefinition> typeDefinitions;
private final Collection<AspectDefinition> aspectDefinitions;
private final Collection<ConstraintDefinition> modelDefinedConstraints;
/* package */CustomModelDefinitionImpl(CompiledModel compiledModel, boolean active, MessageLookup messageLookup)
{
this.m2ModelDefinition = compiledModel.getModelDefinition();
this.active = active;
this.messageLookup = messageLookup;
// compiledModel.getTypes(), getAspects and getConstraints are never null
this.typeDefinitions = new ArrayList<>(compiledModel.getTypes());
this.aspectDefinitions = new ArrayList<>(compiledModel.getAspects());
this.modelDefinedConstraints = removeInlineConstraints(compiledModel);
}
/**
* Removes the inline constraints (i.e. defined within the property) from
* all constraints. The result will be constraints that have been defined
* within the model (Top level) itself.
*
* @param compiledModel the compiled model
* @return list of model defined constraints
*/
public static List<ConstraintDefinition> removeInlineConstraints(CompiledModel compiledModel)
{
List<ConstraintDefinition> modelConstraints = new ArrayList<>();
Set<QName> propertyConstraints = new HashSet<>();
for(PropertyDefinition propDef : compiledModel.getProperties())
{
if (propDef.getConstraints().size() > 0)
{
for (ConstraintDefinition propConst : propDef.getConstraints())
{
propertyConstraints.add(propConst.getName());
}
}
}
for (ConstraintDefinition constraint : compiledModel.getConstraints())
{
if (!propertyConstraints.contains(constraint.getName()))
{
modelConstraints.add(constraint);
}
}
return modelConstraints;
}
@Override
public String getDescription()
{
return getDescription(messageLookup);
}
@Override
public boolean isActive()
{
return this.active;
}
@Override
public String getAnalyserResourceBundleName()
{
return m2ModelDefinition.getAnalyserResourceBundleName();
}
@Override
public String getAuthor()
{
return m2ModelDefinition.getAuthor();
}
@Override
public long getChecksum(XMLBindingType xmlbindingtype)
{
return m2ModelDefinition.getChecksum(xmlbindingtype);
}
@Override
public String getDescription(MessageLookup messagelookup)
{
return m2ModelDefinition.getDescription(messagelookup);
}
@Override
public DictionaryDAO getDictionaryDAO()
{
return m2ModelDefinition.getDictionaryDAO();
}
@Override
public Collection<NamespaceDefinition> getImportedNamespaces()
{
return m2ModelDefinition.getImportedNamespaces();
}
@Override
public QName getName()
{
return m2ModelDefinition.getName();
}
@Override
public Collection<NamespaceDefinition> getNamespaces()
{
return m2ModelDefinition.getNamespaces();
}
@Override
public Date getPublishedDate()
{
return m2ModelDefinition.getPublishedDate();
}
@Override
public String getVersion()
{
return m2ModelDefinition.getVersion();
}
@Override
public boolean isNamespaceDefined(String uri)
{
return m2ModelDefinition.isNamespaceDefined(uri);
}
@Override
public boolean isNamespaceImported(String uri)
{
return m2ModelDefinition.isNamespaceImported(uri);
}
@Override
public void toXML(XMLBindingType xmlbindingtype, OutputStream xml)
{
m2ModelDefinition.toXML(xmlbindingtype, xml);
}
@Override
public Collection<TypeDefinition> getTypeDefinitions()
{
return Collections.unmodifiableCollection(typeDefinitions);
}
@Override
public Collection<AspectDefinition> getAspectDefinitions()
{
return Collections.unmodifiableCollection(aspectDefinitions);
}
@Override
public Collection<ConstraintDefinition> getModelDefinedConstraints()
{
return Collections.unmodifiableCollection(modelDefinedConstraints);
}
}

View File

@@ -0,0 +1,69 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* A simple POJO to encapsulate the custom models' statistics information.
*
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelsInfo
{
private int numberOfActiveModels;
private int numberOfActiveTypes;
private int numberOfActiveAspects;
public int getNumberOfActiveModels()
{
return this.numberOfActiveModels;
}
public void setNumberOfActiveModels(int numberOfActiveModels)
{
this.numberOfActiveModels = numberOfActiveModels;
}
public int getNumberOfActiveTypes()
{
return this.numberOfActiveTypes;
}
public void setNumberOfActiveTypes(int numberOfActiveTypes)
{
this.numberOfActiveTypes = numberOfActiveTypes;
}
public int getNumberOfActiveAspects()
{
return this.numberOfActiveAspects;
}
public void setNumberOfActiveAspects(int numberOfActiveAspects)
{
this.numberOfActiveAspects = numberOfActiveAspects;
}
}

View File

@@ -0,0 +1,173 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
/**
* Model query that delegates its search if itself cannot find the model
* item required.
*
* @author David Caruana
*
*/
/*package*/ class DelegateModelQuery implements ModelQuery
{
private ModelQuery query;
private ModelQuery delegate;
/**
* Construct
*
* @param query ModelQuery
* @param delegate ModelQuery
*/
/*package*/ DelegateModelQuery(ModelQuery query, ModelQuery delegate)
{
this.query = query;
this.delegate = delegate;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getPropertyType(org.alfresco.repo.ref.QName)
*/
public DataTypeDefinition getDataType(QName name)
{
DataTypeDefinition def = query.getDataType(name);
if (def == null)
{
def = delegate.getDataType(name);
}
return def;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ModelQuery#getDataType(java.lang.Class)
*/
public DataTypeDefinition getDataType(Class javaClass)
{
DataTypeDefinition def = query.getDataType(javaClass);
if (def == null)
{
def = delegate.getDataType(javaClass);
}
return def;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getType(org.alfresco.repo.ref.QName)
*/
public TypeDefinition getType(QName name)
{
TypeDefinition def = query.getType(name);
if (def == null)
{
def = delegate.getType(name);
}
return def;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getAspect(org.alfresco.repo.ref.QName)
*/
public AspectDefinition getAspect(QName name)
{
AspectDefinition def = query.getAspect(name);
if (def == null)
{
def = delegate.getAspect(name);
}
return def;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getClass(org.alfresco.repo.ref.QName)
*/
public ClassDefinition getClass(QName name)
{
ClassDefinition def = query.getClass(name);
if (def == null)
{
def = delegate.getClass(name);
}
return def;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getProperty(org.alfresco.repo.ref.QName)
*/
public PropertyDefinition getProperty(QName name)
{
PropertyDefinition def = query.getProperty(name);
if (def == null)
{
def = delegate.getProperty(name);
}
return def;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.ModelQuery#getAssociation(org.alfresco.repo.ref.QName)
*/
public AssociationDefinition getAssociation(QName name)
{
AssociationDefinition def = query.getAssociation(name);
if (def == null)
{
def = delegate.getAssociation(name);
}
return def;
}
/* (non-Javadoc)
* @see ModelQuery#getConstraint(QName)
*/
public ConstraintDefinition getConstraint(QName name)
{
ConstraintDefinition def = query.getConstraint(name);
if (def == null)
{
def = delegate.getConstraint(name);
}
return def;
}
}

View File

@@ -0,0 +1,232 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Bootstrap Dictionary DAO with pre-defined models & message resources (from classpath)
*
* @author David Caruana, janv
*
*/
public class DictionaryBootstrap implements DictionaryListener
{
// The list of models to bootstrap with
private List<String> models = new ArrayList<String>();
// The list of model resource bundles to bootstrap with
private List<String> resourceBundles = new ArrayList<String>();
// Dictionary DAO
private DictionaryDAO dictionaryDAO = null;
// Tenant Service
private TenantService tenantService;
private Properties globalProperties;
// Logger
private static Log logger = LogFactory.getLog(DictionaryBootstrap.class);
/**
* Sets the Dictionary DAO
*
* @param dictionaryDAO DictionaryDAO
*/
public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
/**
* Sets the Tenant Service
*
* @param tenantService TenantService
*/
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
/**
* Sets the global properties
*
* @param globalProperties
*/
public void setGlobalProperties(Properties globalProperties)
{
this.globalProperties = globalProperties;
}
/**
* Sets the initial list of models to bootstrap with
*
* @param modelResources the model names
*/
public void setModels(List<String> modelResources)
{
this.models = modelResources;
}
/**
* Sets the initial list of models to bootstrap with
*
* @param labels the labels
*/
public void setLabels(List<String> labels)
{
this.resourceBundles = labels;
}
/**
* Bootstrap the Dictionary - register and populate
*
*/
public void bootstrap()
{
onDictionaryInit();
initStaticMessages();
register();
}
/**
* Register with the Dictionary
*/
private void register()
{
dictionaryDAO.registerListener(this);
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryListener#onInit()
*/
public void onDictionaryInit()
{
long startTime = System.currentTimeMillis();
if (logger.isTraceEnabled())
{
logger.trace("onDictionaryInit: ["+Thread.currentThread()+"]");
}
// note: on first bootstrap will init empty dictionary
Collection<QName> modelsBefore = dictionaryDAO.getModels(true); // note: on first bootstrap will init empty dictionary
int modelsBeforeCnt = (modelsBefore != null ? modelsBefore.size() : 0);
if ((tenantService == null) || (! tenantService.isTenantUser()))
{
// register models
for (String bootstrapModel : models)
{
InputStream modelStream = getClass().getClassLoader().getResourceAsStream(bootstrapModel);
if (modelStream == null)
{
throw new DictionaryException("d_dictionary.bootstrap.model_not_found", bootstrapModel);
}
try
{
M2Model model = M2Model.createModel(modelStream);
model.setConfigProperties(globalProperties);
if (logger.isDebugEnabled())
{
logger.debug("Loading model: "+model.getName()+" (from "+bootstrapModel+")");
}
dictionaryDAO.putModel(model);
}
catch(DictionaryException e)
{
throw new DictionaryException("d_dictionary.bootstrap.model_not_imported", e, bootstrapModel);
}
finally
{
try
{
modelStream.close();
}
catch (IOException ioe)
{
logger.warn("Failed to close model input stream for '"+bootstrapModel+"': "+ioe);
}
}
}
Collection<QName> modelsAfter = dictionaryDAO.getModels(true);
int modelsAfterCnt = (modelsAfter != null ? modelsAfter.size() : 0);
if (logger.isDebugEnabled())
{
logger.debug("Model count: before="+modelsBeforeCnt+", load="+models.size()+", after="+modelsAfterCnt+" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"]");
}
}
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryListener#afterInit()
*/
public void afterDictionaryInit()
{
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryListener#onDictionaryDestroy()
*/
public void afterDictionaryDestroy()
{
}
/**
* Register the static resource bundles
*/
private void initStaticMessages()
{
// register messages
for (String resourceBundle : resourceBundles)
{
I18NUtil.registerResourceBundle(resourceBundle);
}
}
}

View File

@@ -0,0 +1,548 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.alfresco.repo.tenant.TenantDeployer;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.ParameterCheck;
/**
* Data Dictionary Service Implementation
*
* @author David Caruana
* @author sglover
*/
public class DictionaryComponent implements DictionaryService, TenantDeployer
{
private DictionaryDAO dictionaryDAO;
private MessageLookup messageLookup;
// TODO: Check passed arguments are valid
/**
* Sets the Meta Model DAO
*
* @param dictionaryDAO dictionary DAO
*/
public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
/**
* Sets the message lookup service
*
* @param messageLookup
* the message lookup service
*/
public void setMessageLookup(MessageLookup messageLookup)
{
this.messageLookup = messageLookup;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAllModels()
*/
public Collection<QName> getAllModels()
{
return getAllModels(true);
}
public Collection<QName> getAllModels(boolean includeInherited)
{
return dictionaryDAO.getModels(includeInherited);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getModel(org.alfresco.repo.ref.QName)
*/
public ModelDefinition getModel(QName model)
{
return dictionaryDAO.getModel(model);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAllPropertyTypes()
*/
public Collection<QName> getAllDataTypes()
{
Collection<QName> propertyTypes = new ArrayList<QName>();
for (QName model : getAllModels())
{
propertyTypes.addAll(getDataTypes(model));
}
return propertyTypes;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getPropertyTypes(org.alfresco.repo.ref.QName)
*/
public Collection<QName> getDataTypes(QName model)
{
Collection<DataTypeDefinition> propertyTypes = dictionaryDAO.getDataTypes(model);
Collection<QName> qnames = new ArrayList<QName>(propertyTypes.size());
for (DataTypeDefinition def : propertyTypes)
{
qnames.add(def.getName());
}
return qnames;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAllTypes()
*/
public Collection<QName> getAllTypes()
{
return getAllTypes(true);
}
public Collection<QName> getAllTypes(boolean includeInherited)
{
return dictionaryDAO.getTypes(includeInherited);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getSubTypes(org.alfresco.service.namespace.QName, boolean)
*/
public Collection<QName> getSubTypes(QName superType, boolean follow)
{
return dictionaryDAO.getSubTypes(superType, follow);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getTypes(org.alfresco.repo.ref.QName)
*/
public Collection<QName> getTypes(QName model)
{
Collection<TypeDefinition> types = dictionaryDAO.getTypes(model);
Collection<QName> qnames = new ArrayList<QName>(types.size());
for (TypeDefinition def : types)
{
qnames.add(def.getName());
}
return qnames;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAllAspects()
*/
public Collection<QName> getAllAspects()
{
return getAllAspects(true);
}
public Collection<QName> getAllAspects(boolean includeInherited)
{
return dictionaryDAO.getAspects(includeInherited);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAllAssociations()
*/
public Collection<QName> getAllAssociations()
{
return getAllAssociations(true);
}
public Collection<QName> getAllAssociations(boolean includeInherited)
{
return dictionaryDAO.getAssociations(includeInherited);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getSubAspects(org.alfresco.service.namespace.QName, boolean)
*/
public Collection<QName> getSubAspects(QName superAspect, boolean follow)
{
return dictionaryDAO.getSubAspects(superAspect, follow);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAspects(org.alfresco.repo.ref.QName)
*/
public Collection<QName> getAspects(QName model)
{
Collection<AspectDefinition> aspects = dictionaryDAO.getAspects(model);
Collection<QName> qnames = new ArrayList<QName>(aspects.size());
for (AspectDefinition def : aspects)
{
qnames.add(def.getName());
}
return qnames;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAssociations(org.alfresco.repo.ref.QName)
*/
public Collection<QName> getAssociations(QName model)
{
Collection<AssociationDefinition> associations = dictionaryDAO.getAssociations(model);
Collection<QName> qnames = new ArrayList<QName>(associations.size());
for (AssociationDefinition def : associations)
{
qnames.add(def.getName());
}
return qnames;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#isSubClass(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName)
*/
public boolean isSubClass(QName className, QName ofClassName)
{
// Validate arguments
ParameterCheck.mandatory("className", className);
ParameterCheck.mandatory("ofClassName", ofClassName);
ClassDefinition classDef = getClass(className);
if (classDef == null)
{
return false;
}
ClassDefinition ofClassDef = getClass(ofClassName);
if (ofClassDef == null)
{
return false;
}
// Only check if both ends are either a type or an aspect
boolean subClassOf = false;
if (classDef.isAspect() == ofClassDef.isAspect())
{
while (classDef != null)
{
if (classDef.equals(ofClassDef))
{
subClassOf = true;
break;
}
// No match yet, so go to parent class
QName parentClassName = classDef.getParentName();
classDef = (parentClassName == null) ? null : getClass(parentClassName);
}
}
return subClassOf;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getPropertyType(org.alfresco.repo.ref.QName)
*/
public DataTypeDefinition getDataType(QName name)
{
return dictionaryDAO.getDataType(name);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getDataType(java.lang.Class)
*/
public DataTypeDefinition getDataType(Class<?> javaClass)
{
return dictionaryDAO.getDataType(javaClass);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getType(org.alfresco.repo.ref.QName)
*/
public TypeDefinition getType(QName name)
{
return dictionaryDAO.getType(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAspect(org.alfresco.repo.ref.QName)
*/
public AspectDefinition getAspect(QName name)
{
return dictionaryDAO.getAspect(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getClass(org.alfresco.repo.ref.QName)
*/
public ClassDefinition getClass(QName name)
{
return dictionaryDAO.getClass(name);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAnonymousType(org.alfresco.repo.ref.QName, java.util.Collection)
*/
public TypeDefinition getAnonymousType(QName type, Collection<QName> aspects)
{
return dictionaryDAO.getAnonymousType(type, aspects);
}
/**
*
* {@inheritDoc}
*/
public TypeDefinition getAnonymousType(QName name)
{
TypeDefinition typeDef = getType(name);
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
List<QName> aspectNames = new ArrayList<QName>(aspects.size());
getMandatoryAspects(typeDef, aspectNames);
return getAnonymousType(typeDef.getName(), aspectNames);
}
/**
* Gets a flattened list of all mandatory aspects for a given class
*
* @param classDef the class
* @param aspects a list to hold the mandatory aspects
*/
private void getMandatoryAspects(ClassDefinition classDef, List<QName> aspects)
{
for (AspectDefinition aspect : classDef.getDefaultAspects())
{
QName aspectName = aspect.getName();
if (!aspects.contains(aspectName))
{
aspects.add(aspect.getName());
getMandatoryAspects(aspect, aspects);
}
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getProperty(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName)
*/
public PropertyDefinition getProperty(QName className, QName propertyName)
{
PropertyDefinition propDef = null;
ClassDefinition classDef = dictionaryDAO.getClass(className);
if (classDef != null)
{
Map<QName,PropertyDefinition> propDefs = classDef.getProperties();
propDef = propDefs.get(propertyName);
}
return propDef;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getPropertyDefs(org.alfresco.service.namespace.QName)
*/
public Map<QName,PropertyDefinition> getPropertyDefs(QName className)
{
ClassDefinition classDef = dictionaryDAO.getClass(className);
if (classDef != null)
{
return classDef.getProperties();
}
return null;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getProperty(org.alfresco.repo.ref.QName)
*/
public PropertyDefinition getProperty(QName propertyName)
{
return dictionaryDAO.getProperty(propertyName);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryService#getAssociation(org.alfresco.repo.ref.QName)
*/
public AssociationDefinition getAssociation(QName associationName)
{
return dictionaryDAO.getAssociation(associationName);
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getAllProperties(org.alfresco.service.namespace.QName)
*/
public Collection<QName> getAllProperties(QName dataType)
{
Collection<QName> aspects = new HashSet<QName>(64);
for (QName model : getAllModels())
{
aspects.addAll(getProperties(model, dataType));
}
return aspects;
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getAllProperties(org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName)
*/
public Collection<QName> getProperties(QName model, QName dataType)
{
Collection<PropertyDefinition> propDefs = dictionaryDAO.getProperties(model, dataType);
HashSet<QName> props = new HashSet<QName>(propDefs.size());
for(PropertyDefinition def : propDefs)
{
props.add(def.getName());
}
return props;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getProperties(org.alfresco.service.namespace.QName)
*/
public Collection<QName> getProperties(QName model)
{
Collection<PropertyDefinition> propDefs = dictionaryDAO.getProperties(model);
HashSet<QName> props = new HashSet<QName>(propDefs.size());
for(PropertyDefinition def : propDefs)
{
props.add(def.getName());
}
return props;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getConstraint(org.alfresco.service.namespace.QName)
*/
public ConstraintDefinition getConstraint(QName constraintQName)
{
return dictionaryDAO.getConstraint(constraintQName);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getConstraints(org.alfresco.service.namespace.QName)
*/
public Collection<ConstraintDefinition> getConstraints(QName model)
{
return dictionaryDAO.getConstraints(model);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.DictionaryService#getConstraints(org.alfresco.service.namespace.QName, boolean)
*/
public Collection<ConstraintDefinition> getConstraints(QName model, boolean referenceableDefsOnly)
{
return dictionaryDAO.getConstraints(model, referenceableDefsOnly);
}
public void init()
{
dictionaryDAO.init();
}
public void destroy()
{
dictionaryDAO.destroy();
}
public void onEnableTenant()
{
dictionaryDAO.reset(); // to initialise empty dictionary and re-populate
}
public void onDisableTenant()
{
dictionaryDAO.destroy();
}
/* (non-Javadoc)
* @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String)
*/
@Override
public String getMessage(String messageKey)
{
return messageLookup.getMessage(messageKey);
}
/* (non-Javadoc)
* @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String, java.util.Locale)
*/
@Override
public String getMessage(String messageKey, Locale locale)
{
return messageLookup.getMessage(messageKey, locale);
}
/* (non-Javadoc)
* @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String, java.lang.Object[])
*/
@Override
public String getMessage(String messageKey, Object... params)
{
return messageLookup.getMessage(messageKey, params);
}
/* (non-Javadoc)
* @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String, java.util.Locale, java.lang.Object[])
*/
@Override
public String getMessage(String messageKey, Locale locale, Object... params)
{
return messageLookup.getMessage(messageKey, locale, params);
}
@Override
public ModelDefinition getModelByNamespaceUri(String uri)
{
for(QName modelQname : dictionaryDAO.getModels())
{
if(modelQname.getNamespaceURI().equals(uri))
{
return getModel(modelQname);
}
}
return null;
}
// @Override
// public Collection<QName> getCoreTypes()
// {
// return dictionaryDAO.getCoreTypes();
// }
//
// @Override
// public Collection<QName> getCoreAspects()
// {
// return dictionaryDAO.getCoreAspects();
// }
//
// @Override
// public Collection<QName> getCoreAssociations()
// {
// return dictionaryDAO.getCoreAssociations();
// }
}

View File

@@ -0,0 +1,297 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
/**
* Dictionary Data Access
*
* @author David Caruana, sglover
*/
public interface DictionaryDAO extends ModelQuery
{
/**
* get DictionaryListener registered by calls to registerListener
*
* @see org.alfresco.repo.dictionary.DictionaryListener
* @return read only list of dictionary listeners
*/
List<DictionaryListener> getDictionaryListeners();
DictionaryRegistry getDictionaryRegistry(String tenantDomain);
boolean isContextRefreshed();
/**
* @return the models known by the dictionary
*/
/**
* @return the models known by the dictionary
*/
Collection<QName> getModels();
Collection<QName> getModels(boolean includeInherited);
Collection<QName> getTypes(boolean includeInherited);
Collection<QName> getAssociations(boolean includeInherited);
Collection<QName> getAspects(boolean includeInherited);
/**
* @param name
* the model to retrieve
* @return the named model definition
*/
ModelDefinition getModel(QName name);
/**
* @param model
* the model to retrieve property types for
* @return the property types of the model
*/
Collection<DataTypeDefinition> getDataTypes(QName model);
/**
* @param model
* the model to retrieve types for
* @return the types of the model
*/
Collection<TypeDefinition> getTypes(QName model);
/**
* @param superType QName
* @param follow
* true => follow up the super-class hierarchy, false =>
* immediate sub types only
*/
Collection<QName> getSubTypes(QName superType, boolean follow);
/**
* @param model
* the model to retrieve aspects for
* @return the aspects of the model
*/
Collection<AspectDefinition> getAspects(QName model);
/**
* @param model
* the model to retrieve associations for
* @return the associations of the model
*/
Collection<AssociationDefinition> getAssociations(QName model);
/**
* @param superAspect QName
* @param follow
* true => follow up the super-class hierarchy, false =>
* immediate sub aspects only
*/
Collection<QName> getSubAspects(QName superAspect, boolean follow);
/**
* @param model
* the model for which to get properties for
* @return the properties of the model
*/
Collection<PropertyDefinition> getProperties(QName model);
/**
* Construct an anonymous type that combines a primary type definition and
* and one or more aspects
*
* @param type
* the primary type
* @param aspects
* the aspects to combine
* @return the anonymous type definition
*/
TypeDefinition getAnonymousType(QName type, Collection<QName> aspects);
/**
* Adds a model to the dictionary. The model is compiled and validated.
*
* @param model
* the model to add
* @return QName name of model
*/
QName putModel(M2Model model);
// QName putCustomModel(M2Model model);
/**
* Adds a model to the dictionary. The model is compiled and validated.
* Constraints are not loaded.
*
* This method should only be used to load models where the enforcement of
* constraints is never required. For example, SOLR read only use of the
* index where contraints are not required and thier definitions may not be
* available.
*
* @param model
* the model to add
* @return QName name of model
*/
QName putModelIgnoringConstraints(M2Model model);
/**
* Removes a model from the dictionary. The types and aspect in the model
* will no longer be available.
*
* @param model
* the qname of the model to remove
*/
void removeModel(QName model);
/**
* Get all properties for the model and that are of the given data type. If
* dataType is null then the all properties will be returned.
*
* @param modelName
* the name of the model
* @param dataType
* <tt>null</tt> to get all properties
* @return the properties associated with the model
*/
Collection<PropertyDefinition> getProperties(QName modelName, QName dataType);
/**
* Get all properties for all models of the given data type.
*
* @param dataType QName
*/
Collection<PropertyDefinition> getPropertiesOfDataType(QName dataType);
/**
* @param modelName
* the model to retrieve namespaces for
* @return the namespaces of the model
*/
Collection<NamespaceDefinition> getNamespaces(QName modelName);
/**
* @param model
* the model to retrieve constraint defs (including property
* constaint refs)
* @return the constraints of the model
*/
Collection<ConstraintDefinition> getConstraints(QName model);
/**
* @param model
* the model to retrieve constraint defs (optionally only
* referenceable constraints)
* @return the constraints of the model
*/
Collection<ConstraintDefinition> getConstraints(QName model,
boolean referenceableDefsOnly);
/**
* Return diffs between input model and model in the Dictionary.
*
* If the input model does not exist in the Dictionary then no diffs will be
* returned.
*
* @param model M2Model
* @return model diffs (if any)
*/
List<M2ModelDiff> diffModel(M2Model model);
List<M2ModelDiff> diffModelIgnoringConstraints(M2Model model);
/**
* Register listener with the Dictionary
* <p>
* This method is <b>deprecated</b>, use {@link #registerListener(DictionaryListener dictionaryListener)} instead.
* </p>
* @param dictionaryListener
*/
@Deprecated
void register(DictionaryListener dictionaryListener);
/**
*
* Register listener with the Dictionary
*
* @param dictionaryListener DictionaryListener
*/
void registerListener(DictionaryListener dictionaryListener);
/**
* Reset the Dictionary for the current tenant.
* The current dictionary will be discarded <b>and reloaded</b> before the method returns
* i.e. upon return the dictionary will be current.
*/
void reset();
/**
* Initialise a reload of the dictionary for the current tenant. The current version of
* the dictionary will be accessible during this call, however it will only return once
* the dictionary has undergone a reload for the current tenant.
*/
void init();
/**
* Destroy the Dictionary. After this call, there will be no dictionary available for the current
* tenant; reloading will be done lazily as required.
* <p>
* <strong>WARNING: </strong>This method can cause 'stutter' on user threads as they wait for
* the dictionary to reload. It is safer to call {@link #init()}, which will also rebuild the
* dictionary but will not destroy the old one, thereby allowing other threads to continue
* operating.
*/
void destroy();
// MT-specific
boolean isModelInherited(QName name);
/**
* @return String
*/
String getDefaultAnalyserResourceBundleName();
/**
* @return ClassLoader
*/
ClassLoader getResourceClassLoader();
/**
* @param resourceClassLoader ClassLoader
*/
void setResourceClassLoader(ClassLoader resourceClassLoader);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* Dictionary Listener interface.
* <p>
* This interface allows Dictionary Listeners to register with the DictionaryService.
*
*/
public interface DictionaryListener
{
/**
* Callback for (re-)initialising the Dictionary caches (executed in the current tenant context)
*/
void onDictionaryInit();
/**
* Callback once dictionary destroy is complete (executed in the current tenant context)
*/
void afterDictionaryDestroy();
/**
* Callback once dictionary initialisation is complete (executed in the current tenant context)
*/
void afterDictionaryInit();
}

View File

@@ -0,0 +1,111 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.Collection;
import org.alfresco.service.namespace.NamespaceService;
/**
* Data Dictionary Namespace Service Implementation
*
* @author David Caruana
*/
public class DictionaryNamespaceComponent implements NamespaceService
{
/**
* Namespace DAO
*/
private NamespaceDAO namespaceDAO;
/**
* Sets the Namespace DAO
*
* @param namespaceDAO namespace DAO
*/
public void setNamespaceDAO(NamespaceDAO namespaceDAO)
{
this.namespaceDAO = namespaceDAO;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.NamespaceService#getURIs()
*/
public Collection<String> getURIs()
{
return namespaceDAO.getURIs();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.NamespaceService#getPrefixes()
*/
public Collection<String> getPrefixes()
{
return namespaceDAO.getPrefixes();
}
/* (non-Javadoc)
* @see org.alfresco.repo.ref.NamespacePrefixResolver#getNamespaceURI(java.lang.String)
*/
public String getNamespaceURI(String prefix)
{
return namespaceDAO.getNamespaceURI(prefix);
}
/* (non-Javadoc)
* @see org.alfresco.repo.ref.NamespacePrefixResolver#getPrefixes(java.lang.String)
*/
public Collection<String> getPrefixes(String namespaceURI)
{
return namespaceDAO.getPrefixes(namespaceURI);
}
/* (non-Javadoc)
* @see org.alfresco.service.namespace.NamespaceService#registerNamespace(java.lang.String, java.lang.String)
*/
public void registerNamespace(String prefix, String uri)
{
// TODO:
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
* @see org.alfresco.service.namespace.NamespaceService#registerNamespace(java.lang.String, java.lang.String)
*/
public void unregisterNamespace(String prefix)
{
// TODO:
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,82 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
/**
*
* @author sglover
*
*/
public interface DictionaryRegistry
{
void init();
void remove();
CompiledModel getModel(QName name);
boolean modelExists(QName name);
Map<String, List<CompiledModel>> getUriToModels();
Map<QName, CompiledModel> getCompiledModels(boolean includeInherited);
QName putModel(CompiledModel model);
void removeModel(QName modelName);
String getTenantDomain();
void clear();
List<CompiledModel> getModelsForUri(String uri);
AspectDefinition getAspect(QName aspectName);
AssociationDefinition getAssociation(QName assocName);
ClassDefinition getClass(QName className);
PropertyDefinition getProperty(QName propertyName);
TypeDefinition getType(QName typeName);
ConstraintDefinition getConstraint(QName constraintQName);
DataTypeDefinition getDataType(QName typeName);
@SuppressWarnings("rawtypes")
DataTypeDefinition getDataType(Class javaClass);
boolean isModelInherited(QName modelName);
Map<String, String> getPrefixesCache();
List<String> getUrisCache();
Collection<String> getPrefixes(String URI);
void addURI(String uri);
boolean hasURI(String uri);
void addPrefix(String prefix, String uri);
boolean hasPrefix(String prefix);
void removeURI(String uri);
void removePrefix(String prefix);
Collection<QName> getTypes(boolean includeInherited);
Collection<QName> getAssociations(boolean includeInherited);
Collection<QName> getAspects(boolean includeInherited);
String getNamespaceURI(String prefix);
}

View File

@@ -0,0 +1,39 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* A dictionary listener that allows listeners to listen for models being added to
* the dictionary. Used by the OpenCMIS dictionary to refresh its registry when new models
* are added to the core dictionary.
*
* @author sglover
*
*/
public interface ExtendedDictionaryListener extends DictionaryListener
{
void modelAdded(CompiledModel model, String tenant);
}

View File

@@ -0,0 +1,67 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* How faceting is to be supported
*
* @author Andy
*
*/
public enum Facetable
{
/**
* TRUE - faceting is required and enhanced support for this is provided if possible
*/
TRUE,
/**
* UNSET - facet support is unset, standard support is assumed
*/
UNSET,
/**
* FALSE - feceting is not required and will not be supported
*/
FALSE;
public static String serializer(Facetable facetable) {
return facetable.toString();
}
public static Facetable deserializer(String value) {
if (value == null) {
return null;
} else if (value.equalsIgnoreCase(TRUE.toString())) {
return TRUE;
} else if (value.equalsIgnoreCase(FALSE.toString())) {
return FALSE;
} else if (value.equalsIgnoreCase(UNSET.toString())) {
return UNSET;
} else {
throw new IllegalArgumentException(
"Invalid facetable enum value: " + value);
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* How tokenisation is supported in the index.
*
*
* @author andyh
*
*/
public enum IndexTokenisationMode {
/**
* Tokenise the property. If the analyser supported ordering then the field
* supports ordering FTS is supported via analysis.
*/
TRUE,
/**
* Do not tokenise the property. The field supports ordering and pattern
* matching.
*/
FALSE,
/**
* There may be two indexes - one to support ordering and one to support
* search.
*/
BOTH;
public static String serializer(IndexTokenisationMode indexTokenisationMode) {
return indexTokenisationMode.toString();
}
public static IndexTokenisationMode deserializer(String value) {
if (value == null) {
return null;
} else if (value.equalsIgnoreCase(TRUE.toString())) {
return TRUE;
} else if (value.equalsIgnoreCase(FALSE.toString())) {
return FALSE;
} else if (value.equalsIgnoreCase(BOTH.toString())) {
return BOTH;
} else {
throw new IllegalArgumentException(
"Invalid IndexTokenisationMode: " + value);
}
}
}

View File

@@ -0,0 +1,255 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.i18n.StaticMessageLookup;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Compiled anonymous type definition.
*
* @author David Caruana
*
*/
/*package*/ class M2AnonymousTypeDefinition implements TypeDefinition
{
private TypeDefinition type;
private Map<QName,PropertyDefinition> properties = new HashMap<QName,PropertyDefinition>();
private Map<QName,AssociationDefinition> associations = new HashMap<QName,AssociationDefinition>();
private Map<QName,ChildAssociationDefinition> childassociations = new HashMap<QName,ChildAssociationDefinition>();
private transient MessageLookup staticMessageLookup = new StaticMessageLookup();
/**
* Construct
*
* @param type the primary type
* @param aspects the aspects to combine with the type
*/
/*package*/ M2AnonymousTypeDefinition(TypeDefinition type, Collection<AspectDefinition> aspects)
{
this.type = type;
// Combine features of type and aspects
properties.putAll(type.getProperties());
associations.putAll(type.getAssociations());
childassociations.putAll(type.getChildAssociations());
for (AspectDefinition aspect : aspects)
{
properties.putAll(aspect.getProperties());
associations.putAll(aspect.getAssociations());
childassociations.putAll(aspect.getChildAssociations());
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getModel()
*/
public ModelDefinition getModel()
{
return type.getModel();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.TypeDefinition#getDefaultAspects()
*/
public List<AspectDefinition> getDefaultAspects()
{
return type.getDefaultAspects();
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspects(boolean)
*/
public List<AspectDefinition> getDefaultAspects(boolean inherited)
{
return type.getDefaultAspects(inherited);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspectNames()
*/
public Set<QName> getDefaultAspectNames()
{
return type.getDefaultAspectNames();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getName()
*/
public QName getName()
{
return QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "anonymous#" + type.getName().getLocalName());
}
@Override
public String getDescription()
{
return getDescription(staticMessageLookup);
}
@Override
public String getTitle()
{
return getTitle(staticMessageLookup);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getTitle()
*/
public String getTitle(MessageLookup messageLookup)
{
return type.getTitle(messageLookup);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getDescription()
*/
public String getDescription(MessageLookup messageLookup)
{
return type.getDescription(messageLookup);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getParentName()
*/
public QName getParentName()
{
return type.getParentName();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#isAspect()
*/
public boolean isAspect()
{
return type.isAspect();
}
public Boolean getArchive()
{
return type.getArchive();
}
public Boolean getIncludedInSuperTypeQuery()
{
return type.getIncludedInSuperTypeQuery();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getProperties()
*/
public Map<QName, PropertyDefinition> getProperties()
{
return Collections.unmodifiableMap(properties);
}
/**
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultValues()
*/
public Map<QName, Serializable> getDefaultValues()
{
Map<QName, Serializable> result = new HashMap<QName, Serializable>(5);
for(Map.Entry<QName, PropertyDefinition> entry : properties.entrySet())
{
PropertyDefinition propertyDefinition = entry.getValue();
String defaultValue = propertyDefinition.getDefaultValue();
if (defaultValue != null)
{
result.put(entry.getKey(), defaultValue);
}
}
return Collections.unmodifiableMap(result);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getAssociations()
*/
public Map<QName, AssociationDefinition> getAssociations()
{
return Collections.unmodifiableMap(associations);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#isContainer()
*/
public boolean isContainer()
{
return !childassociations.isEmpty();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getChildAssociations()
*/
public Map<QName, ChildAssociationDefinition> getChildAssociations()
{
return Collections.unmodifiableMap(childassociations);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getAnalyserResourceBundleName()
*/
@Override
public String getAnalyserResourceBundleName()
{
return type.getAnalyserResourceBundleName();
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getParentClassDefinition()
*/
@Override
public ClassDefinition getParentClassDefinition()
{
return type.getParentClassDefinition();
}
}

View File

@@ -0,0 +1,41 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* Aspect definition.
*
* @author David Caruana
*/
public class M2Aspect extends M2Class
{
/*package*/ M2Aspect()
{
super();
}
}

View File

@@ -0,0 +1,80 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
/**
* Compiled Aspect Definition.
*
* @author David Caruana
*/
/*package*/ class M2AspectDefinition extends M2ClassDefinition
implements AspectDefinition
{
/*package*/ M2AspectDefinition(ModelDefinition model, M2Aspect m2Aspect, NamespacePrefixResolver resolver, Map<QName, PropertyDefinition> modelProperties, Map<QName, AssociationDefinition> modelAssociations)
{
super(model, m2Aspect, resolver, modelProperties, modelAssociations);
}
@Override
public String getDescription(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "aspect", name, "description");
// if we don't have a description call the super class
if (value == null)
{
value = super.getDescription(messageLookup);
}
return value;
}
@Override
public String getTitle(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "aspect", name, "title");
// if we don't have a title call the super class
if (value == null)
{
value = super.getTitle(messageLookup);
}
return value;
}
}

View File

@@ -0,0 +1,46 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* Association definition.
*
* @author David Caruana
*/
public class M2Association extends M2ClassAssociation
{
/*package*/ M2Association()
{
}
/*package*/ M2Association(String name)
{
super(name);
}
}

View File

@@ -0,0 +1,356 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.repo.i18n.StaticMessageLookup;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
/**
* Compiled Association Definition.
*
* @author David Caruana
*/
/*package*/ class M2AssociationDefinition implements AssociationDefinition
{
private ClassDefinition classDef;
private M2ClassAssociation assoc;
private QName name;
private QName targetClassName;
private ClassDefinition targetClass;
private QName sourceRoleName;
private QName targetRoleName;
private transient MessageLookup staticMessageLookup = new StaticMessageLookup();
/**
* Construct
*
* @param classDef ClassDefinition
* @param assoc M2ClassAssociation
* @param resolver NamespacePrefixResolver
*/
/*package*/ M2AssociationDefinition(ClassDefinition classDef, M2ClassAssociation assoc, NamespacePrefixResolver resolver)
{
this.classDef = classDef;
this.assoc = assoc;
// Resolve names
this.name = QName.createQName(assoc.getName(), resolver);
this.targetClassName = QName.createQName(assoc.getTargetClassName(), resolver);
this.sourceRoleName = QName.createQName(assoc.getSourceRoleName(), resolver);
this.targetRoleName = QName.createQName(assoc.getTargetRoleName(), resolver);
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(56);
sb.append("Association")
.append("[ class=").append(classDef)
.append(", name=").append(name)
.append(", target class=").append(targetClassName)
.append(", source role=").append(sourceRoleName)
.append(", target role=").append(targetRoleName)
.append("]");
return sb.toString();
}
/*package*/ M2ClassAssociation getM2Association()
{
return assoc;
}
/*package*/ void resolveDependencies(ModelQuery query)
{
if (targetClassName == null)
{
throw new DictionaryException("d_dictionary.association.target_class_not_specified", name.toPrefixString());
}
targetClass = query.getClass(targetClassName);
if (targetClass == null)
{
throw new DictionaryException("d_dictionary.association.target_class_not_found", targetClassName.toPrefixString(), name.toPrefixString());
}
}
@Override
public ModelDefinition getModel()
{
return classDef.getModel();
}
@Override
public QName getName()
{
return name;
}
@Override
public boolean isChild()
{
return (assoc instanceof M2ChildAssociation);
}
@Override
public String getTitle()
{
return getTitle(staticMessageLookup);
}
@Override
public String getDescription()
{
return getDescription(staticMessageLookup);
}
@Override
public String getTitle(MessageLookup messageLookup)
{
String value = M2Label.getLabel(classDef.getModel(), messageLookup, "association", name, "title");
if (value == null)
{
value = assoc.getTitle();
}
return value;
}
@Override
public String getDescription(MessageLookup messageLookup)
{
String value = M2Label.getLabel(classDef.getModel(), messageLookup, "association", name, "description");
if (value == null)
{
value = assoc.getDescription();
}
return value;
}
@Override
public boolean isProtected()
{
return assoc.isProtected();
}
@Override
public ClassDefinition getSourceClass()
{
return classDef;
}
@Override
public QName getSourceRoleName()
{
return sourceRoleName;
}
@Override
public boolean isSourceMandatory()
{
return assoc.isSourceMandatory();
}
@Override
public boolean isSourceMany()
{
return assoc.isSourceMany();
}
@Override
public ClassDefinition getTargetClass()
{
return targetClass;
}
@Override
public QName getTargetRoleName()
{
return targetRoleName;
}
@Override
public boolean isTargetMandatory()
{
return assoc.isTargetMandatory();
}
@Override
public boolean isTargetMandatoryEnforced()
{
return assoc.isTargetMandatoryEnforced();
}
@Override
public boolean isTargetMany()
{
return assoc.isTargetMany();
}
/* package */ M2ModelDiff diffAssoc(AssociationDefinition assocDef)
{
M2ModelDiff modelDiff = null;
boolean isUpdated = false;
boolean isUpdatedIncrementally = false;
if (this == assocDef)
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UNCHANGED);
return modelDiff;
}
// check name - cannot be null
if (! name.equals(assocDef.getName()))
{
isUpdated = true;
}
// check title
if (! EqualsHelper.nullSafeEquals(getTitle(null), assocDef.getTitle(null), false))
{
isUpdatedIncrementally = true;
}
// check description
if (! EqualsHelper.nullSafeEquals(getDescription(null), assocDef.getDescription(null), false))
{
isUpdatedIncrementally = true;
}
// check source class qname
if (! EqualsHelper.nullSafeEquals(getSourceClass().getName(), assocDef.getSourceClass().getName()))
{
isUpdated = true;
}
// check source role qname
if (! EqualsHelper.nullSafeEquals(getSourceRoleName(), assocDef.getSourceRoleName()))
{
isUpdated = true;
}
// check target class qname
if (! EqualsHelper.nullSafeEquals(getTargetClass().getName(), assocDef.getTargetClass().getName()))
{
isUpdated = true;
}
// check target role qname
if (! EqualsHelper.nullSafeEquals(getTargetRoleName(), assocDef.getTargetRoleName()))
{
isUpdated = true;
}
// TODO - additional checks - is... (x7)
if (isUpdated)
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UPDATED);
}
else if (isUpdatedIncrementally)
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UPDATED_INC);
}
else
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UNCHANGED);
}
return modelDiff;
}
/*package*/ static Collection<M2ModelDiff> diffAssocLists(Collection<AssociationDefinition> previousAssocs, Collection<AssociationDefinition> newAssocs)
{
List<M2ModelDiff> modelDiffs = new ArrayList<M2ModelDiff>();
for (AssociationDefinition previousAssoc : previousAssocs)
{
boolean found = false;
for (AssociationDefinition newAssoc : newAssocs)
{
if (newAssoc.getName().equals(previousAssoc.getName()))
{
modelDiffs.add(((M2AssociationDefinition)previousAssoc).diffAssoc(newAssoc));
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(previousAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_DELETED));
}
}
for (AssociationDefinition newAssoc : newAssocs)
{
boolean found = false;
for (AssociationDefinition previousAssoc : previousAssocs)
{
if (newAssoc.getName().equals(previousAssoc.getName()))
{
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(newAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_CREATED));
}
}
return modelDiffs;
}
}

View File

@@ -0,0 +1,85 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* Child Association definition.
*
* @author David Caruana
*
*/
public class M2ChildAssociation extends M2ClassAssociation
{
private String requiredChildName = null;
private Boolean allowDuplicateChildName = null;
private Boolean propagateTimestamps = null;
/*package*/ M2ChildAssociation()
{
}
/*package*/ M2ChildAssociation(String name)
{
super(name);
}
public String getRequiredChildName()
{
return requiredChildName;
}
public void setRequiredChildName(String requiredChildName)
{
this.requiredChildName = requiredChildName;
}
public boolean allowDuplicateChildName()
{
return allowDuplicateChildName == null ? true : allowDuplicateChildName;
}
public void setAllowDuplicateChildName(boolean allowDuplicateChildName)
{
this.allowDuplicateChildName = allowDuplicateChildName;
}
public boolean isPropagateTimestamps()
{
return propagateTimestamps == null ? false : propagateTimestamps;
}
public void setPropagateTimestamps(boolean propagateTimestamps)
{
this.propagateTimestamps = propagateTimestamps;
}
}

View File

@@ -0,0 +1,70 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.namespace.NamespacePrefixResolver;
/**
* Compiled Association Definition.
*
* @author David Caruana
*/
/*package*/ class M2ChildAssociationDefinition extends M2AssociationDefinition
implements ChildAssociationDefinition
{
/**
* Construct
* @param classDef class definition
* @param assoc child assocation
* @param resolver namespace resolver
*/
/*package*/ M2ChildAssociationDefinition(ClassDefinition classDef, M2ChildAssociation assoc, NamespacePrefixResolver resolver)
{
super(classDef, assoc, resolver);
}
public String getRequiredChildName()
{
return ((M2ChildAssociation)getM2Association()).getRequiredChildName();
}
public boolean getDuplicateChildNamesAllowed()
{
return ((M2ChildAssociation)getM2Association()).allowDuplicateChildName();
}
public boolean getPropagateTimestamps()
{
return ((M2ChildAssociation)getM2Association()).isPropagateTimestamps();
}
}

View File

@@ -0,0 +1,304 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;
/**
* Abstract Class Definition.
*
* @author David Caruana
*
*/
public abstract class M2Class
{
public static final Pattern PROPERTY_PLACEHOLDER = Pattern.compile("\\$\\{.*\\}\\|.*");
private String name = null;
private String title = null;
private String description = null;
private String parentName = null;
private Boolean archive = null;
private Boolean includedInSuperTypeQuery = null;
private String analyserResourceBundleName = null;
private List<M2Property> properties = new ArrayList<M2Property>();
private List<M2PropertyOverride> propertyOverrides = new ArrayList<M2PropertyOverride>();
private List<M2ClassAssociation> associations = new ArrayList<M2ClassAssociation>();
private List<String> mandatoryAspects = new ArrayList<String>();
/*package*/ M2Class()
{
}
public boolean isAspect()
{
return this instanceof M2Aspect;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public Boolean getArchive()
{
return archive;
}
public void setArchive(boolean archive)
{
this.archive = Boolean.valueOf(archive);
}
public Boolean getIncludedInSuperTypeQuery()
{
return includedInSuperTypeQuery;
}
public void setIncludedInSuperTypeQuery(boolean includedInSuperTypeQuery)
{
this.includedInSuperTypeQuery = Boolean.valueOf(includedInSuperTypeQuery);
}
public M2Property createProperty(String name)
{
M2Property property = new M2Property();
property.setName(name);
properties.add(property);
return property;
}
public void removeProperty(String name)
{
M2Property property = getProperty(name);
if (property != null)
{
properties.remove(property);
}
}
public List<M2Property> getProperties()
{
return Collections.unmodifiableList(properties);
}
public M2Property getProperty(String name)
{
for (M2Property candidate : properties)
{
if (candidate.getName().equals(name))
{
return candidate;
}
}
return null;
}
public M2Association createAssociation(String name)
{
M2Association association = new M2Association();
association.setName(name);
associations.add(association);
return association;
}
public M2ChildAssociation createChildAssociation(String name)
{
M2ChildAssociation association = new M2ChildAssociation();
association.setName(name);
associations.add(association);
return association;
}
public void removeAssociation(String name)
{
M2ClassAssociation association = getAssociation(name);
if (association != null)
{
associations.remove(association);
}
}
public List<M2ClassAssociation> getAssociations()
{
return Collections.unmodifiableList(associations);
}
public M2ClassAssociation getAssociation(String name)
{
for (M2ClassAssociation candidate : associations)
{
if (candidate.getName().equals(name))
{
return candidate;
}
}
return null;
}
public M2PropertyOverride createPropertyOverride(String name)
{
M2PropertyOverride property = new M2PropertyOverride();
property.setName(name);
propertyOverrides.add(property);
return property;
}
public void removePropertyOverride(String name)
{
M2PropertyOverride property = getPropertyOverride(name);
if (property != null)
{
propertyOverrides.remove(property);
}
}
public List<M2PropertyOverride> getPropertyOverrides()
{
return Collections.unmodifiableList(propertyOverrides);
}
public M2PropertyOverride getPropertyOverride(String name)
{
for (M2PropertyOverride candidate : propertyOverrides)
{
if (candidate.getName().equals(name))
{
return candidate;
}
}
return null;
}
public void addMandatoryAspect(String name)
{
mandatoryAspects.add(name);
}
public void removeMandatoryAspect(String name)
{
mandatoryAspects.remove(name);
}
public List<String> getMandatoryAspects()
{
return Collections.unmodifiableList(mandatoryAspects);
}
/**
* @return String
*/
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
public void setAnalyserResourceBundleName(String analyserResourceBundleName)
{
this.analyserResourceBundleName = analyserResourceBundleName;
}
public void setConfigProperties(Properties configProperties)
{
if (properties != null)
{
for (M2Property property : properties)
{
property.setConfigProperties(configProperties);
}
}
if (propertyOverrides != null)
{
for (M2PropertyOverride propertyOverride : propertyOverrides)
{
propertyOverride.setConfigProperties(configProperties);
}
}
}
}

View File

@@ -0,0 +1,219 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* Abstract Association Definition.
*
* @author David Caruana
*
*/
public abstract class M2ClassAssociation
{
private String name = null;
private Boolean isProtected = null;
private String title = null;
private String description = null;
private String sourceRoleName = null;
private Boolean isSourceMandatory = null;
private Boolean isSourceMany = null;
private String targetClassName = null;
private String targetRoleName = null;
private Boolean isTargetMandatory = null;
private Boolean isTargetMandatoryEnforced = null;
private Boolean isTargetMany = null;
/*package*/ M2ClassAssociation()
{
}
/*package*/ M2ClassAssociation(String name)
{
this.name = name;
}
public boolean isChild()
{
return this instanceof M2ChildAssociation;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public boolean isProtected()
{
return isProtected == null ? false : isProtected;
}
public void setProtected(boolean isProtected)
{
this.isProtected = isProtected;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getSourceRoleName()
{
return sourceRoleName;
}
public void setSourceRoleName(String name)
{
this.sourceRoleName = name;
}
public boolean isSourceMandatory()
{
return isSourceMandatory == null ? true : isSourceMandatory;
}
public void setSourceMandatory(boolean isSourceMandatory)
{
this.isSourceMandatory = isSourceMandatory;
}
public boolean isSourceMany()
{
return isSourceMany == null ? false : isSourceMany;
}
public void setSourceMany(boolean isSourceMany)
{
this.isSourceMany = isSourceMany;
}
public String getTargetClassName()
{
return targetClassName;
}
public void setTargetClassName(String targetClassName)
{
this.targetClassName = targetClassName;
}
public String getTargetRoleName()
{
return targetRoleName;
}
public void setTargetRoleName(String name)
{
this.targetRoleName = name;
}
public Boolean getTargetMandatory()
{
return isTargetMandatory();
}
public boolean isTargetMandatory()
{
return isTargetMandatory == null ? false : isTargetMandatory;
}
public void setTargetMandatory(boolean isTargetMandatory)
{
this.isTargetMandatory = isTargetMandatory;
}
public Boolean getTargetMandatoryEnforced()
{
return isTargetMandatoryEnforced();
}
public boolean isTargetMandatoryEnforced()
{
return isTargetMandatoryEnforced == null ? isTargetMandatory() : isTargetMandatoryEnforced;
}
public void setTargetMandatoryEnforced(boolean isTargetMandatoryEnforced)
{
this.isTargetMandatoryEnforced = isTargetMandatoryEnforced;
}
public boolean isTargetMany()
{
return isTargetMany == null ? true : isTargetMany;
}
public void setTargetMany(boolean isTargetMany)
{
this.isTargetMany = isTargetMany;
}
}

View File

@@ -0,0 +1,781 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import static org.alfresco.service.cmr.dictionary.DictionaryException.DuplicateDefinitionException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.i18n.StaticMessageLookup;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
/**
* Compiled Class Definition
*
* @author David Caruana
*/
/*package*/ class M2ClassDefinition implements ClassDefinition
{
private static final String ERR_CLASS_NOT_DEFINED_NAMESPACE = "d_dictionary.class_definition.class.namespace_not_defined";
private static final String ERR_PROPERTY_NOT_DEFINED_NAMESPACE = "d_dictionary.class_definition.property.namespace_not_defined";
private static final String ERR_DUPLICATE_PROPERTY_DEFINITION = "d_dictionary.class_definition.duplicate.property_definition";
private static final String ERR_DUPLICATE_PROPERTY_EXISTING_DEF = "d_dictionary.class_definition.duplicate.property_existing_def";
private static final String ERR_ASSOCIATION_NOT_DEFINED_NAMESPACE = "d_dictionary.class_definition.association.namespace_not_defined";
private static final String ERR_DUPLICATE_ASSOCIATION_DEFINITION = "d_dictionary.class_definition.duplicate.association_definition";
private static final String ERR_DUPLICATE_ASSOCIATION_EXISTING_DEF = "d_dictionary.class_definition.duplicate.association_existing_def";
private static final String ERR_DUPLICATE_PROPERTY_AND_PROPERTY_OVERRIDE = "d_dictionary.class_definition.duplicate.property_and_property_override";
private static final String ERR_DUPLICATE_PROPERTY_OVERRIDE = "d_dictionary.class_definition.duplicate.property_override_definition";
private static final String ERR_PARENT_NOT_FOUND = "d_dictionary.class_definition.class.parent_not_found";
private static final String ERR_PROPERTY_NOT_EXIST = "d_dictionary.class_definition.property_not_exist";
private static final String ERR_MANDATORY_ASPECT_NOT_FOUND = "d_dictionary.class_definition.mandatory_aspect_not_found";
private static final String ERR_DUPLICATE_PROPERTY_IN_CLASS_HIERARCHY = "d_dictionary.class_definition.duplicate.property_in_class_hierarchy";
private static final String ERR_DUPLICATE_ASSOCIATION_IN_CLASS_HIERARCHY = "d_dictionary.class_definition.duplicate.association_in_class_hierarchy";
protected ModelDefinition model;
protected M2Class m2Class;
protected QName name;
protected QName parentName = null;
protected ClassDefinition parentClassDefinition;
private Map<QName, M2PropertyOverride> propertyOverrides = new HashMap<QName, M2PropertyOverride>();
private Map<QName, PropertyDefinition> properties = new HashMap<QName, PropertyDefinition>();
private Map<QName, PropertyDefinition> inheritedProperties = new HashMap<QName, PropertyDefinition>();
private Map<QName, AssociationDefinition> associations = new HashMap<QName, AssociationDefinition>();
private Map<QName, AssociationDefinition> inheritedAssociations = new HashMap<QName, AssociationDefinition>();
private Map<QName, ChildAssociationDefinition> inheritedChildAssociations = new HashMap<QName, ChildAssociationDefinition>();
private List<AspectDefinition> defaultAspects = new ArrayList<AspectDefinition>();
private List<QName> defaultAspectNames = new ArrayList<QName>();
private List<AspectDefinition> inheritedDefaultAspects = new ArrayList<AspectDefinition>();
private Set<QName> inheritedDefaultAspectNames = new HashSet<QName>();
private Boolean archive = null;
private Boolean inheritedArchive = null;
private Boolean includedInSuperTypeQuery = null;
private Boolean inheritedIncludedInSuperTypeQuery = null;
private String analyserResourceBundleName;
private transient MessageLookup staticMessageLookup = new StaticMessageLookup();
/**
* Construct
*
* @param m2Class class definition
* @param resolver namepsace resolver
* @param modelProperties global list of model properties
* @param modelAssociations global list of model associations
*/
/*package*/ M2ClassDefinition(ModelDefinition model, M2Class m2Class, NamespacePrefixResolver resolver, Map<QName, PropertyDefinition> modelProperties, Map<QName, AssociationDefinition> modelAssociations)
{
this.model = model;
this.m2Class = m2Class;
// Resolve Names
this.name = QName.createQName(m2Class.getName(), resolver);
if (!model.isNamespaceDefined(name.getNamespaceURI()))
{
throw new DictionaryException(ERR_CLASS_NOT_DEFINED_NAMESPACE, name.toPrefixString(), name.getNamespaceURI(), model.getName().toPrefixString());
}
this.archive = m2Class.getArchive();
this.includedInSuperTypeQuery = m2Class.getIncludedInSuperTypeQuery();
if (m2Class.getParentName() != null && m2Class.getParentName().length() > 0)
{
this.parentName = QName.createQName(m2Class.getParentName(), resolver);
}
// Construct Properties
for (M2Property property : m2Class.getProperties())
{
PropertyDefinition def = new M2PropertyDefinition(this, property, resolver);
if (!model.isNamespaceDefined(def.getName().getNamespaceURI()) &&
!model.isNamespaceImported(def.getName().getNamespaceURI()))
{
throw new DictionaryException(ERR_PROPERTY_NOT_DEFINED_NAMESPACE, def.getName().toPrefixString(), def.getName().getNamespaceURI(), model.getName().toPrefixString());
}
if (properties.containsKey(def.getName()))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_DEFINITION, def.getName().toPrefixString(), name.toPrefixString());
}
// Check for existence of property elsewhere within the model
PropertyDefinition existingDef = modelProperties.get(def.getName());
if (existingDef != null)
{
// TODO: Consider sharing property, if property definitions are equal
throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_EXISTING_DEF, def.getName().toPrefixString(), name.toPrefixString(), existingDef.getContainerClass().getName().toPrefixString());
}
properties.put(def.getName(), def);
modelProperties.put(def.getName(), def);
}
// Construct Associations
for (M2ClassAssociation assoc : m2Class.getAssociations())
{
AssociationDefinition def;
if (assoc instanceof M2ChildAssociation)
{
def = new M2ChildAssociationDefinition(this, (M2ChildAssociation)assoc, resolver);
}
else
{
def = new M2AssociationDefinition(this, assoc, resolver);
}
if (!model.isNamespaceDefined(def.getName().getNamespaceURI()))
{
throw new DictionaryException(ERR_ASSOCIATION_NOT_DEFINED_NAMESPACE, def.getName().toPrefixString(), def.getName().getNamespaceURI(), model.getName().toPrefixString());
}
if (associations.containsKey(def.getName()))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_ASSOCIATION_DEFINITION, def.getName().toPrefixString(), name.toPrefixString());
}
// Check for existence of association elsewhere within the model
AssociationDefinition existingDef = modelAssociations.get(def.getName());
if (existingDef != null)
{
// TODO: Consider sharing association, if association definitions are equal
throw new DuplicateDefinitionException(ERR_DUPLICATE_ASSOCIATION_EXISTING_DEF, def.getName().toPrefixString(), name.toPrefixString(), existingDef.getSourceClass().getName().toPrefixString());
}
associations.put(def.getName(), def);
modelAssociations.put(def.getName(), def);
}
// Construct Property overrides
for (M2PropertyOverride override : m2Class.getPropertyOverrides())
{
QName overrideName = QName.createQName(override.getName(), resolver);
if (properties.containsKey(overrideName))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_AND_PROPERTY_OVERRIDE, overrideName.toPrefixString(), name.toPrefixString());
}
if (propertyOverrides.containsKey(overrideName))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_OVERRIDE, overrideName.toPrefixString(), name.toPrefixString());
}
propertyOverrides.put(overrideName, override);
}
// Resolve qualified names
for (String aspectName : m2Class.getMandatoryAspects())
{
QName name = QName.createQName(aspectName, resolver);
if (!defaultAspectNames.contains(name))
{
defaultAspectNames.add(name);
}
}
this.analyserResourceBundleName = m2Class.getAnalyserResourceBundleName();
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(120);
sb.append("ClassDef")
.append("[name=").append(name)
.append("]");
return sb.toString();
}
/*package*/ void resolveDependencies(
ModelQuery query,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
if (parentName != null)
{
ClassDefinition parent = query.getClass(parentName);
if (parent == null)
{
throw new DictionaryException(ERR_PARENT_NOT_FOUND, parentName.toPrefixString(), name.toPrefixString());
}
parentClassDefinition = parent;
}
for (PropertyDefinition def : properties.values())
{
((M2PropertyDefinition)def).resolveDependencies(query, prefixResolver, modelConstraints);
}
for (AssociationDefinition def : associations.values())
{
((M2AssociationDefinition)def).resolveDependencies(query);
}
for (Map.Entry<QName, M2PropertyOverride> override : propertyOverrides.entrySet())
{
PropertyDefinition propDef = query.getProperty(override.getKey());
if (propDef == null)
{
throw new DictionaryException(ERR_PROPERTY_NOT_EXIST, name.toPrefixString(), override.getKey().toPrefixString());
}
}
for (QName aspectName : defaultAspectNames)
{
AspectDefinition aspect = query.getAspect(aspectName);
if (aspect == null)
{
throw new DictionaryException(ERR_MANDATORY_ASPECT_NOT_FOUND, aspectName.toPrefixString(), name.toPrefixString());
}
defaultAspects.add(aspect);
}
}
/*package*/ void resolveInheritance(
ModelQuery query,
NamespacePrefixResolver prefixResolver,
Map<QName, ConstraintDefinition> modelConstraints)
{
// Retrieve parent class
ClassDefinition parentClass = (parentName == null) ? null : query.getClass(parentName);
// Build list of inherited properties (and process overridden values)
if (parentClass != null)
{
for (PropertyDefinition def : parentClass.getProperties().values())
{
M2PropertyOverride override = propertyOverrides.get(def.getName());
if (override == null)
{
inheritedProperties.put(def.getName(), def);
}
else
{
inheritedProperties.put(
def.getName(),
new M2PropertyDefinition(this, def, override, prefixResolver, modelConstraints));
}
}
}
// Append list of defined properties
for (PropertyDefinition def : properties.values())
{
if (inheritedProperties.containsKey(def.getName()))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_IN_CLASS_HIERARCHY, def.getName().toPrefixString(), name.toPrefixString());
}
inheritedProperties.put(def.getName(), def);
}
// Build list of inherited associations
if (parentClass != null)
{
inheritedAssociations.putAll(parentClass.getAssociations());
}
// Append list of defined associations
for (AssociationDefinition def : associations.values())
{
if (inheritedAssociations.containsKey(def.getName()))
{
throw new DuplicateDefinitionException(ERR_DUPLICATE_ASSOCIATION_IN_CLASS_HIERARCHY, def.getName().toPrefixString(), name.toPrefixString());
}
inheritedAssociations.put(def.getName(), def);
}
// Derive Child Associations
for (AssociationDefinition def : inheritedAssociations.values())
{
if (def instanceof ChildAssociationDefinition)
{
inheritedChildAssociations.put(def.getName(), (ChildAssociationDefinition)def);
}
}
// Build list of inherited default aspects
if (parentClass != null)
{
inheritedDefaultAspects.addAll(parentClass.getDefaultAspects());
}
// Append list of defined default aspects
for (AspectDefinition def : defaultAspects)
{
if (!inheritedDefaultAspects.contains(def))
{
inheritedDefaultAspects.add(def);
}
}
// Convert to set of names
for (AspectDefinition aspDef : inheritedDefaultAspects)
{
inheritedDefaultAspectNames.add(aspDef.getName());
}
// resolve archive inheritance
if (parentClass != null && archive == null)
{
// archive not explicitly set on this class and there is a parent class
inheritedArchive = ((M2ClassDefinition)parentClass).getArchive();
}
// resolve includedInSuperTypeQuery inheritance
if (parentClass != null && includedInSuperTypeQuery == null)
{
// archive not explicitly set on this class and there is a parent class
inheritedIncludedInSuperTypeQuery = ((M2ClassDefinition)parentClass).getIncludedInSuperTypeQuery();
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getModel()
*/
public ModelDefinition getModel()
{
return model;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getName()
*/
public QName getName()
{
return name;
}
@Override
public String getDescription()
{
return getDescription(staticMessageLookup);
}
@Override
public String getTitle()
{
return getTitle(staticMessageLookup);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getTitle()
*/
public String getTitle(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "class", name, "title");
if (value == null)
{
value = m2Class.getTitle();
}
return value;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getDescription()
*/
public String getDescription(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "class", name, "description");
if (value == null)
{
value = m2Class.getDescription();
}
return value;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getParentName()
*/
public QName getParentName()
{
return parentName;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#isAspect()
*/
public boolean isAspect()
{
return (m2Class instanceof M2Aspect);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getArchive()
*/
public Boolean getArchive()
{
return archive == null ? inheritedArchive : archive;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#includedInSuperTypeQuery()
*/
public Boolean getIncludedInSuperTypeQuery()
{
if(includedInSuperTypeQuery != null)
{
return includedInSuperTypeQuery;
}
if(inheritedIncludedInSuperTypeQuery != null)
{
return inheritedIncludedInSuperTypeQuery;
}
return Boolean.TRUE;
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getProperties()
*/
public Map<QName, PropertyDefinition> getProperties()
{
return Collections.unmodifiableMap(inheritedProperties);
}
/**
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultValues()
*/
public Map<QName, Serializable> getDefaultValues()
{
Map<QName, Serializable> result = new HashMap<QName, Serializable>(5);
for(Map.Entry<QName, PropertyDefinition> entry : inheritedProperties.entrySet())
{
PropertyDefinition propertyDefinition = entry.getValue();
String defaultValue = propertyDefinition.getDefaultValue();
if (defaultValue != null)
{
result.put(entry.getKey(), defaultValue);
}
}
return Collections.unmodifiableMap(result);
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getAssociations()
*/
public Map<QName, AssociationDefinition> getAssociations()
{
return Collections.unmodifiableMap(inheritedAssociations);
}
/**
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspects()
*/
public List<AspectDefinition> getDefaultAspects()
{
return inheritedDefaultAspects;
}
/**
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspects(boolean)
*/
public List<AspectDefinition> getDefaultAspects(boolean inherited)
{
return inherited ? getDefaultAspects() : defaultAspects;
}
/**
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspectNames()
*/
public Set<QName> getDefaultAspectNames()
{
return inheritedDefaultAspectNames;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#isContainer()
*/
public boolean isContainer()
{
return !inheritedChildAssociations.isEmpty();
}
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.ClassDefinition#getChildAssociations()
*/
public Map<QName, ChildAssociationDefinition> getChildAssociations()
{
return Collections.unmodifiableMap(inheritedChildAssociations);
}
@Override
public int hashCode()
{
return name.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (!(obj instanceof M2ClassDefinition))
{
return false;
}
return name.equals(((M2ClassDefinition)obj).name);
}
/**
* return differences in class definition
*
* note:
* - checks properties for incremental updates, but does not include the diffs
* - checks assocs & child assocs for incremental updates, but does not include the diffs
* - incremental updates include changes in title/description, property default value, etc
*/
/* package */ List<M2ModelDiff> diffClass(ClassDefinition classDef)
{
List<M2ModelDiff> modelDiffs = new ArrayList<M2ModelDiff>();
boolean isUpdated = false;
boolean isUpdatedIncrementally = false;
if (this == classDef)
{
return modelDiffs;
}
// check name - cannot be null
if (! getName().equals(classDef.getName()))
{
isUpdated = true;
}
// check title
if (! EqualsHelper.nullSafeEquals(getTitle(null), classDef.getTitle(null), false))
{
isUpdatedIncrementally = true;
}
// check description
if (! EqualsHelper.nullSafeEquals(getDescription(null), classDef.getDescription(null), false))
{
isUpdatedIncrementally = true;
}
// check parent name
if (getParentName() != null)
{
if (! getParentName().equals(classDef.getParentName()))
{
isUpdated = true;
}
}
else if (classDef.getParentName() != null)
{
isUpdated = true;
}
// check if aspect (or type)
if (isAspect() != classDef.isAspect())
{
isUpdated = true;
}
// check if container
if (isContainer() != classDef.isContainer())
{
if (isContainer())
{
// updated (non-incrementally) if class was a container and now is not a container - ie. all child associations removed
isUpdated = true;
}
if (classDef.isContainer())
{
// updated incrementally if class was not a container and now is a container - ie. some child associations added
isUpdatedIncrementally = true;
}
}
// check all properties (including inherited properties)
Collection<M2ModelDiff> propertyDiffs = M2PropertyDefinition.diffPropertyLists(getProperties().values(), classDef.getProperties().values());
modelDiffs.addAll(propertyDiffs);
// check all associations (including inherited associations, child associations and inherited child associations)
Collection<M2ModelDiff> assocDiffs = M2AssociationDefinition.diffAssocLists(getAssociations().values(), classDef.getAssociations().values());
modelDiffs.addAll(assocDiffs);
// check default/mandatory aspects
for (AspectDefinition newAspect : classDef.getDefaultAspects(false))
{
boolean found = false;
for (AspectDefinition previousAspect : getDefaultAspects(false))
{
if (newAspect.getName().equals(previousAspect.getName()))
{
found = true;
break;
}
}
if (! found)
{
// mandatory aspect added (to aspect or type)
isUpdated = true;
}
}
// check archive/inheritedArchive
if (getArchive() == null)
{
if (classDef.getArchive() != null)
{
isUpdatedIncrementally = true;
}
}
else
{
Boolean classArchive = classDef.getArchive();
if (classArchive == null || classArchive.booleanValue() != getArchive().booleanValue())
{
isUpdatedIncrementally = true;
}
}
// check includedInSuperTypeQuery/inheritedIncludedInSuperTypeQuery
if (getIncludedInSuperTypeQuery() == null)
{
// belts-and-braces (currently does not return null)
if (classDef.getIncludedInSuperTypeQuery() != null)
{
isUpdatedIncrementally = true;
}
}
else
{
Boolean classIncludedInSuperTypeQuery = classDef.getIncludedInSuperTypeQuery();
if (classIncludedInSuperTypeQuery == null || classIncludedInSuperTypeQuery.booleanValue() != getIncludedInSuperTypeQuery().booleanValue())
{
isUpdatedIncrementally = true;
}
}
String modelDiffType;
if (isAspect())
{
modelDiffType = M2ModelDiff.TYPE_ASPECT;
}
else
{
modelDiffType = M2ModelDiff.TYPE_TYPE;
}
if (isUpdated)
{
modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UPDATED));
}
else if (isUpdatedIncrementally)
{
modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UPDATED_INC));
}
else
{
modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UNCHANGED));
}
return modelDiffs;
}
/**
* return differences in class definition lists
*
*/
/*package*/ static List<M2ModelDiff> diffClassLists(Collection<ClassDefinition> previousClasses, Collection<ClassDefinition> newClasses, String M2ModelDiffType)
{
List<M2ModelDiff> modelDiffs = new ArrayList<M2ModelDiff>();
for (ClassDefinition previousClass : previousClasses)
{
boolean found = false;
for (ClassDefinition newClass : newClasses)
{
if (newClass.getName().equals(previousClass.getName()))
{
modelDiffs.addAll(((M2ClassDefinition)previousClass).diffClass(newClass));
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(previousClass.getName(), M2ModelDiffType, M2ModelDiff.DIFF_DELETED));
}
}
for (ClassDefinition newClass : newClasses)
{
boolean found = false;
for (ClassDefinition previousClass : previousClasses)
{
if (newClass.getName().equals(previousClass.getName()))
{
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(newClass.getName(), M2ModelDiffType, M2ModelDiff.DIFF_CREATED));
}
}
return modelDiffs;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getAnalyserResourceBundleName()
*/
@Override
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.dictionary.ClassDefinition#getParentClassDefinition()
*/
@Override
public ClassDefinition getParentClassDefinition()
{
return parentClassDefinition;
}
}

View File

@@ -0,0 +1,139 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract Property Constraint.
*
* @author Derek Hulley
*/
public class M2Constraint
{
private String name;
private String ref;
private String type;
private String title;
private String description;
private List<M2NamedValue> parameters = new ArrayList<M2NamedValue>(2);
/*package*/ M2Constraint()
{
}
@Override
public String toString()
{
return this.name;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getRef()
{
return ref;
}
public void setRef(String refName)
{
this.ref = refName;
}
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public List<M2NamedValue> getParameters()
{
return parameters;
}
public M2NamedValue createParameter(String name, String simpleValue)
{
M2NamedValue param = new M2NamedValue();
param.setName(name);
param.setSimpleValue(simpleValue);
parameters.add(param);
return param;
}
public M2NamedValue createParameter(String name, List<String> listValue)
{
M2NamedValue param = new M2NamedValue();
param.setName(name);
param.setListValue(listValue);
parameters.add(param);
return param;
}
public void removeParameter(String name)
{
List<M2NamedValue> params = new ArrayList<M2NamedValue>(getParameters());
for (M2NamedValue param : params)
{
if (param.getName().equals(name))
{
parameters.remove(param);
}
}
}
}

View File

@@ -0,0 +1,523 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint;
import org.alfresco.repo.dictionary.constraint.RegexConstraint;
import org.alfresco.repo.dictionary.constraint.RegisteredConstraint;
import org.alfresco.repo.dictionary.constraint.StringLengthConstraint;
import org.alfresco.repo.i18n.StaticMessageLookup;
import org.alfresco.service.cmr.dictionary.Constraint;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.PropertyAccessException;
/**
* Compiled Property Constraint
*
* @author Derek Hulley. janv
*/
/* package */class M2ConstraintDefinition implements ConstraintDefinition
{
private static final String PROP_SHORT_NAME = "shortName";
private static final String PROP_TITLE = "title";
private static final String PROP_DESCRIPTION = "description";
public static final String ERR_CYCLIC_REF = "d_dictionary.constraint.err.cyclic_ref";
public static final String ERR_TYPE_AND_REF = "d_dictionary.constraint.err.type_and_ref";
public static final String ERR_TYPE_OR_REF = "d_dictionary.constraint.err.type_or_ref";
public static final String ERR_REF_NOT_FOUND = "d_dictionary.constraint.err.ref_not_found";
public static final String ERR_ANON_NEEDS_PROPERTY = "d_dictionary.constraint.err.anon_needs_property";
public static final String ERR_INVALID_TYPE = "d_dictionary.constraint.err.invalid_type";
public static final String ERR_SIMPLE_AND_LIST = "d_dictionary.constraint.err.property_simple_and_list";
public static final String ERR_CONSTRUCT_FAILURE = "d_dictionary.constraint.err.construct_failure";
public static final String ERR_PROPERTY_MISMATCH = "d_dictionary.constraint.err.property_mismatch";
public static final String ERR_RESERVED_PROPERTY = "d_dictionary.constraint.err.reserved_property";
public static final String ERR_NAMESPACE_NOT_DEFINED = "d_dictionary.constraint.err.namespace_not_defined";
private static int anonPropCount = 0;
private ModelDefinition model;
private NamespacePrefixResolver prefixResolver;
private M2Constraint m2Constraint;
private QName name;
private Constraint constraint;
private boolean resolving;
private transient MessageLookup staticMessageLookup = new StaticMessageLookup();
/* package */M2ConstraintDefinition(M2PropertyDefinition m2PropertyDef, M2Constraint m2Constraint,
NamespacePrefixResolver prefixResolver)
{
this(m2PropertyDef.getModel(), m2PropertyDef, m2Constraint, prefixResolver);
}
/* package */M2ConstraintDefinition(ModelDefinition modelDefinition, M2PropertyDefinition m2PropertyDef,
M2Constraint m2Constraint, NamespacePrefixResolver prefixResolver)
{
this.model = modelDefinition;
this.m2Constraint = m2Constraint;
this.prefixResolver = prefixResolver;
String constraintName = m2Constraint.getName();
if (constraintName == null)
{
// the constraint is anonymous, so it has to be defined within the context of a property
if (m2PropertyDef == null)
{
throw new DictionaryException(ERR_ANON_NEEDS_PROPERTY);
}
// pick the name up from the property and some anonymous value
String localName = m2PropertyDef.getName().getLocalName() + "_anon_" + (++anonPropCount);
this.name = QName.createQName(m2PropertyDef.getName().getNamespaceURI(), localName);
m2Constraint.setName(this.name.getPrefixedQName(prefixResolver).toPrefixString());
}
else
{
this.name = QName.createQName(m2Constraint.getName(), prefixResolver);
if (!model.isNamespaceDefined(name.getNamespaceURI()))
{
throw new DictionaryException(ERR_NAMESPACE_NOT_DEFINED, name.toPrefixString(), name.getNamespaceURI(), model.getName().toPrefixString());
}
}
}
/* package */synchronized void resolveDependencies(ModelQuery query, boolean enableConstraintClassLoading)
{
if (resolving)
{
throw new DictionaryException(ERR_CYCLIC_REF, name.toPrefixString());
}
// prevent circular references
try
{
resolving = true;
resolveInternal(query, enableConstraintClassLoading);
}
finally
{
resolving = false;
}
}
private synchronized void resolveInternal(ModelQuery query, boolean enableConstraintClassLoading)
{
if (constraint != null)
{
// already been resolved
return;
}
String shortName = name.toPrefixString();
String ref = m2Constraint.getRef();
String type = m2Constraint.getType();
String title = m2Constraint.getTitle();
String description = m2Constraint.getDescription();
if (ref != null && type != null)
{
throw new DictionaryException(ERR_TYPE_AND_REF, shortName);
}
else if (ref == null && type == null)
{
throw new DictionaryException(ERR_TYPE_OR_REF, shortName);
}
else if (ref != null)
{
// resolve the reference name
QName qnameRef = QName.createQName(ref, prefixResolver);
// ensure that the reference exists in the model
M2ConstraintDefinition constraintDef = (M2ConstraintDefinition) query.getConstraint(qnameRef);
if (constraintDef == null)
{
throw new DictionaryException(ERR_REF_NOT_FOUND, ref, shortName);
}
// make sure that the constraint definition has itself been resolved
constraintDef.resolveDependencies(query, enableConstraintClassLoading);
// just use the constraint provided by the referenced definition
this.constraint = constraintDef.getConstraint();
//use real constraint name instead of anonymous name
//TODO Fix backed out - breaks DictionaryDAOTest
//this.name = constraintDef.getName();
if (m2Constraint.getTitle() == null)
{
m2Constraint.setTitle(constraintDef.getTitle(null));
}
if (m2Constraint.getDescription() == null)
{
m2Constraint.setDescription(constraintDef.getDescription(null));
}
}
else
{
// we have to build the constraint from the type
try
{
ConstraintType constraintType = ConstraintType.valueOf(type);
constraint = constraintType.newInstance();
}
catch (IllegalArgumentException e)
{
// try to establish it as a class
try
{
if(enableConstraintClassLoading)
{
@SuppressWarnings("unchecked")
Class clazz = Class.forName(type);
constraint = (Constraint) clazz.newInstance();
}
}
catch (ClassNotFoundException ee)
{
throw new DictionaryException(ERR_INVALID_TYPE, type, shortName);
}
catch (ClassCastException ee)
{
throw new DictionaryException(ERR_INVALID_TYPE, type, shortName);
}
catch (Exception ee)
{
throw new DictionaryException(ERR_CONSTRUCT_FAILURE, type, shortName);
}
}
if(constraint != null)
{
// property setters
BeanWrapper beanWrapper = new BeanWrapperImpl(constraint);
List<M2NamedValue> constraintNamedValues = m2Constraint.getParameters();
if (constraintNamedValues != null)
{
for (M2NamedValue namedValue : constraintNamedValues)
{
String namedValueName = namedValue.getName();
// Check for reserved properties
if (namedValueName.equals(PROP_SHORT_NAME))
{
throw new DictionaryException(ERR_RESERVED_PROPERTY, PROP_SHORT_NAME, namedValueName);
}
Object value = null;
if (namedValue.getSimpleValue() != null && namedValue.getListValue() != null)
{
throw new DictionaryException(ERR_SIMPLE_AND_LIST, shortName, namedValue.getName());
}
else if (namedValue.getSimpleValue() != null)
{
value = namedValue.getSimpleValue();
}
else if (namedValue.getListValue() != null)
{
value = namedValue.getListValue();
}
try
{
beanWrapper.setPropertyValue(namedValueName, value);
}
catch (PropertyAccessException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName);
}
catch (InvalidPropertyException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName);
}
}
// Pass in the short name as a special property, if it is available
if (beanWrapper.isWritableProperty(PROP_SHORT_NAME))
{
try
{
beanWrapper.setPropertyValue(PROP_SHORT_NAME, shortName);
}
catch (PropertyAccessException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName);
}
catch (InvalidPropertyException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName);
}
}
if ((title != null) && (beanWrapper.isWritableProperty(PROP_TITLE)))
{
beanWrapper.setPropertyValue(PROP_TITLE, title);
}
if ((title != null) && (beanWrapper.isWritableProperty(PROP_DESCRIPTION)))
{
beanWrapper.setPropertyValue(PROP_DESCRIPTION, description);
}
}
// now initialize
constraint.initialize();
}
}
}
/**
* @see #getName()
*/
@Override
public String toString()
{
return getName().toString();
}
@Override
public ModelDefinition getModel()
{
return model;
}
@Override
public QName getName()
{
return name;
}
@Override
public String getTitle()
{
return getTitle(staticMessageLookup);
}
@Override
public String getDescription()
{
return getDescription(staticMessageLookup);
}
@Override
public String getTitle(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "constraint", name, "title");
if (value == null)
{
value = m2Constraint.getTitle();
}
return value;
}
@Override
public String getDescription(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "constraint", name, "description");
if (value == null)
{
value = m2Constraint.getDescription();
}
return value;
}
@Override
public Constraint getConstraint()
{
return constraint;
}
@Override
public QName getRef()
{
QName refQName = null;
String ref = m2Constraint.getRef();
if (ref != null)
{
refQName = QName.createQName(ref, prefixResolver);
}
return refQName;
}
/**
* Well-known constraint types
*/
public static enum ConstraintType
{
REGISTERED
{
@Override
protected Constraint newInstance()
{
return new RegisteredConstraint();
}
},
REGEX
{
@Override
protected Constraint newInstance()
{
return new RegexConstraint();
}
},
MINMAX
{
@Override
protected Constraint newInstance()
{
return new NumericRangeConstraint();
}
},
LENGTH
{
@Override
protected Constraint newInstance()
{
return new StringLengthConstraint();
}
},
LIST
{
@Override
protected Constraint newInstance()
{
return new ListOfValuesConstraint();
}
};
/**
* @return Returns the constraint implementation
*/
protected abstract Constraint newInstance();
}
/* package */ M2ModelDiff diffConstraint(ConstraintDefinition conDef)
{
M2ModelDiff modelDiff = null;
boolean isUpdated = false;
boolean isUpdatedIncrementally = false;
if (this == conDef)
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UNCHANGED);
return modelDiff;
}
// check name - cannot be null
if (! name.equals(conDef.getName()))
{
isUpdated = true;
}
// check title
if (! EqualsHelper.nullSafeEquals(getTitle(null), conDef.getTitle(null), false))
{
isUpdatedIncrementally = true;
}
// check description
if (! EqualsHelper.nullSafeEquals(getDescription(null), conDef.getDescription(null), false))
{
isUpdatedIncrementally = true;
}
// check type string
if (! EqualsHelper.nullSafeEquals(getConstraint().getType(), conDef.getConstraint().getType()))
{
isUpdated = true;
}
if (isUpdated)
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UPDATED);
}
else if (isUpdatedIncrementally)
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UPDATED_INC);
}
else
{
modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UNCHANGED);
}
return modelDiff;
}
/*package*/ static Collection<M2ModelDiff> diffConstraintLists(Collection<ConstraintDefinition> previousConstraints, Collection<ConstraintDefinition> newConstraints)
{
List<M2ModelDiff> modelDiffs = new ArrayList<M2ModelDiff>();
for (ConstraintDefinition previousConstraint : previousConstraints)
{
boolean found = false;
for (ConstraintDefinition newConstraint : newConstraints)
{
if (newConstraint.getName().equals(previousConstraint.getName()))
{
modelDiffs.add(((M2ConstraintDefinition)previousConstraint).diffConstraint(previousConstraint));
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(previousConstraint.getName(), M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_DELETED));
}
}
for (ConstraintDefinition newConstraint : newConstraints)
{
boolean found = false;
for (ConstraintDefinition previousConstraint : previousConstraints)
{
if (newConstraint.getName().equals(previousConstraint.getName()))
{
found = true;
break;
}
}
if (! found)
{
modelDiffs.add(new M2ModelDiff(newConstraint.getName(), M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_CREATED));
}
}
return modelDiffs;
}
}

View File

@@ -0,0 +1,125 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
/**
* Property Type Definition
*
* @author David Caruana
*
*/
public class M2DataType
{
private String name = null;
private String title = null;
private String description = null;
private String defaultAnalyserClassName = null;
private String javaClassName = null;
private String analyserResourceBundleName = null;
/*package*/ M2DataType()
{
super();
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getDefaultAnalyserClassName()
{
return defaultAnalyserClassName;
}
public void setDefaultAnalyserClassName(String defaultAnalyserClassName)
{
this.defaultAnalyserClassName = defaultAnalyserClassName;;
}
public String getJavaClassName()
{
return javaClassName;
}
public void setJavaClassName(String javaClassName)
{
this.javaClassName = javaClassName;;
}
/**
* @return String
*/
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
public void setAnalyserResourceBundleName(String analyserResourceBundleName)
{
this.analyserResourceBundleName = analyserResourceBundleName;
}
}

View File

@@ -0,0 +1,253 @@
/*
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.dictionary;
import java.util.Locale;
import java.util.ResourceBundle;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.util.StringUtils;
import org.alfresco.repo.i18n.StaticMessageLookup;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.ModelDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
/**
* Compiled Property Type Definition
*
* @author David Caruana
*
*/
/*package*/ class M2DataTypeDefinition implements DataTypeDefinition
{
private static final String ERR_NOT_DEFINED_NAMESPACE = "d_dictionary.data_type.namespace_not_defined";
private static final String ERR_JAVA_CLASS_NOT_SPECIFIED = "d_dictionary.data_type.java_class_not_specified";
private static final String ERR_JAVA_CLASS_INVALID = "d_dictionary.data_type.java_class_invalid";
private ModelDefinition model;
private QName name;
private M2DataType dataType;
private String analyserResourceBundleName;
private transient MessageLookup staticMessageLookup = new StaticMessageLookup();
/*package*/ M2DataTypeDefinition(ModelDefinition model, M2DataType propertyType, NamespacePrefixResolver resolver)
{
this.model = model;
this.name = QName.createQName(propertyType.getName(), resolver);
if (!model.isNamespaceDefined(name.getNamespaceURI()))
{
throw new DictionaryException(ERR_NOT_DEFINED_NAMESPACE, name.toPrefixString(), name.getNamespaceURI(), model.getName().toPrefixString());
}
this.dataType = propertyType;
this.analyserResourceBundleName = dataType.getAnalyserResourceBundleName();
}
/*package*/ void resolveDependencies(ModelQuery query)
{
// Ensure java class has been specified
String javaClass = dataType.getJavaClassName();
if (javaClass == null)
{
throw new DictionaryException(ERR_JAVA_CLASS_NOT_SPECIFIED, name.toPrefixString());
}
// Ensure java class is valid and referenceable
try
{
Class.forName(javaClass);
}
catch (ClassNotFoundException e)
{
throw new DictionaryException(ERR_JAVA_CLASS_INVALID, javaClass, name.toPrefixString(), e);
}
}
/**
* @see #getName()
*/
@Override
public String toString()
{
return getName().toString();
}
@Override
public ModelDefinition getModel()
{
return model;
}
@Override
public QName getName()
{
return name;
}
@Override
public String getTitle()
{
return getTitle(staticMessageLookup);
}
@Override
public String getDescription()
{
return getDescription(staticMessageLookup);
}
@Override
public String getTitle(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "datatype", name, "title");
if (value == null)
{
value = dataType.getTitle();
}
return value;
}
@Override
public String getDescription(MessageLookup messageLookup)
{
String value = M2Label.getLabel(model, messageLookup, "datatype", name, "description");
if (value == null)
{
value = dataType.getDescription();
}
return value;
}
@Override
public String getDefaultAnalyserClassName()
{
return dataType.getDefaultAnalyserClassName();
}
@Override
public String getJavaClassName()
{
return dataType.getJavaClassName();
}
@Override
public String getAnalyserResourceBundleName()
{
return analyserResourceBundleName;
}
@Override
public String resolveAnalyserClassName()
{
return resolveAnalyserClassName(I18NUtil.getLocale());
}
/**
* @param locale Locale
* @return String
*/
@Override
public String resolveAnalyserClassName(Locale locale)
{
ClassLoader resourceBundleClassLoader = getModel().getDictionaryDAO().getResourceClassLoader();
if(resourceBundleClassLoader == null)
{
resourceBundleClassLoader = this.getClass().getClassLoader();
}
StringBuilder keyBuilder = new StringBuilder(64);
keyBuilder.append(getModel().getName().toPrefixString());
keyBuilder.append(".datatype");
keyBuilder.append(".").append(getName().toPrefixString());
keyBuilder.append(".analyzer");
String key = StringUtils.replace(keyBuilder.toString(), ":", "_");
String analyserClassName = null;
String defaultAnalyserResourceBundleName = this.getModel().getDictionaryDAO().getDefaultAnalyserResourceBundleName();
if(defaultAnalyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(defaultAnalyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
String analyserResourceBundleName;
if(analyserClassName == null)
{
analyserResourceBundleName = dataType.getAnalyserResourceBundleName();
if(analyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
}
if(analyserClassName == null)
{
analyserResourceBundleName = getModel().getAnalyserResourceBundleName();
if(analyserResourceBundleName != null)
{
ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader);
if(bundle.containsKey(key))
{
analyserClassName = bundle.getString(key);
}
}
}
if(analyserClassName == null)
{
// MLTEXT should fall back to TEXT for analysis
if(name.equals(DataTypeDefinition.MLTEXT))
{
analyserClassName = model.getDictionaryDAO().getDataType(DataTypeDefinition.TEXT).resolveAnalyserClassName(locale);
if(analyserClassName == null)
{
analyserClassName = dataType.getDefaultAnalyserClassName();
}
}
else
{
analyserClassName = dataType.getDefaultAnalyserClassName();
}
}
return analyserClassName;
}
}

Some files were not shown because too many files have changed in this diff Show More