001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.kernel.api;
019
020import static com.google.common.collect.ImmutableSet.of;
021import static org.apache.jena.rdf.model.ResourceFactory.createProperty;
022import static org.apache.jena.rdf.model.ResourceFactory.createResource;
023
024import java.util.Set;
025import java.util.function.Predicate;
026import java.util.stream.Collectors;
027
028import org.apache.jena.rdf.model.Property;
029import org.apache.jena.rdf.model.Resource;
030
031import com.google.common.collect.ImmutableSet;
032
033/**
034 * A lexicon of the RDF properties that the fcrepo kernel (or close-to-core modules) use
035 *
036 * @author ajs6f
037 */
038public final class RdfLexicon {
039
040    /**
041     * Repository namespace "fedora"
042    **/
043    public static final String REPOSITORY_NAMESPACE = "http://fedora.info/definitions/v4/repository#";
044
045    public static final String FCREPO_API_NAMESPACE = "http://fedora.info/definitions/fcrepo#";
046
047    public static final String ACTIVITY_STREAMS_NAMESPACE = "https://www.w3.org/ns/activitystreams#";
048
049    public static final String EBUCORE_NAMESPACE = "http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#";
050
051    public static final String OA_NAMESPACE = "http://www.w3.org/ns/oa#";
052
053    public static final String PROV_NAMESPACE = "http://www.w3.org/ns/prov#";
054
055    public static final String PREMIS_NAMESPACE = "http://www.loc.gov/premis/rdf/v1#";
056
057    public static final String MEMENTO_NAMESPACE = "http://mementoweb.org/ns#";
058
059    public static final String RDF_NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
060
061    /**
062     * Namespace for the W3C WebAC vocabulary.
063     */
064    public static final String WEBAC_NAMESPACE_VALUE = "http://www.w3.org/ns/auth/acl#";
065
066    /**
067     * Fedora configuration namespace "fedora-config", used for user-settable
068     * configuration properties.
069     **/
070    // TODO from UCDetector: Constant "RdfLexicon.FEDORA_CONFIG_NAMESPACE" has 0 references
071    // should be referenced again when versioning is back in REST api
072    public static final String FEDORA_CONFIG_NAMESPACE = // NO_UCD (unused code)
073            "info:fedoraconfig/";
074
075    /**
076     * Linked Data Platform namespace.
077     */
078    public static final String LDP_NAMESPACE = "http://www.w3.org/ns/ldp#";
079
080    /**
081     * Is this namespace one that the repository manages?
082     */
083    public static final Predicate<String> isManagedNamespace = p -> p.equals(REPOSITORY_NAMESPACE) ||
084            p.equals(LDP_NAMESPACE) || p.equals(MEMENTO_NAMESPACE);
085
086    // FIXITY
087
088    public static final Resource FIXITY_TYPE = createResource(PREMIS_NAMESPACE + "Fixity");
089
090    public static final Property HAS_MESSAGE_DIGEST_ALGORITHM =
091            createProperty(PREMIS_NAMESPACE + "hasMessageDigestAlgorithm");
092
093    public static final Property HAS_MESSAGE_DIGEST =
094            createProperty(PREMIS_NAMESPACE + "hasMessageDigest");
095
096    public static final Property HAS_SIZE =
097        createProperty(PREMIS_NAMESPACE + "hasSize");
098    public static final Property HAS_FIXITY_RESULT =
099        createProperty(PREMIS_NAMESPACE + "hasFixity");
100
101    private static final Set<Property> fixityProperties = of(
102            HAS_FIXITY_RESULT, HAS_MESSAGE_DIGEST);
103
104    public static final Resource EVENT_OUTCOME_INFORMATION = createResource(PREMIS_NAMESPACE + "EventOutcomeDetail");
105
106    public static final Property HAS_FIXITY_STATE =
107            createProperty(PREMIS_NAMESPACE + "hasEventOutcome");
108
109    public static final Property WRITABLE =
110            createProperty(REPOSITORY_NAMESPACE + "writable");
111
112    public static final String FEDORA_NON_RDF_SOURCE_DESCRIPTION_URI = REPOSITORY_NAMESPACE +
113            "NonRdfSourceDescription";
114
115    // Server managed properties
116    public static final Property CREATED_DATE =
117            createProperty(REPOSITORY_NAMESPACE + "created");
118    public static final Property CREATED_BY =
119            createProperty(REPOSITORY_NAMESPACE + "createdBy");
120    public static final Property LAST_MODIFIED_DATE =
121            createProperty(REPOSITORY_NAMESPACE + "lastModified");
122    public static final Property LAST_MODIFIED_BY =
123            createProperty(REPOSITORY_NAMESPACE + "lastModifiedBy");
124
125    public static final Resource FEDORA_CONTAINER =
126            createResource(REPOSITORY_NAMESPACE + "Container");
127    public static final Resource FEDORA_BINARY =
128            createResource(REPOSITORY_NAMESPACE + "Binary");
129    public static final Resource FEDORA_RESOURCE =
130            createResource(REPOSITORY_NAMESPACE + "Resource");
131
132    // Linked Data Platform
133    public static final Property PAGE =
134        createProperty(LDP_NAMESPACE + "Page");
135    public static final Resource CONTAINER =
136            createResource(LDP_NAMESPACE + "Container");
137    public static final Resource BASIC_CONTAINER =
138            createResource(LDP_NAMESPACE + "BasicContainer");
139    public static final Resource DIRECT_CONTAINER =
140            createResource(LDP_NAMESPACE + "DirectContainer");
141    public static final Resource INDIRECT_CONTAINER =
142            createResource(LDP_NAMESPACE + "IndirectContainer");
143    public static final Property MEMBERSHIP_RESOURCE =
144            createProperty(LDP_NAMESPACE + "membershipResource");
145    public static final Property HAS_MEMBER_RELATION =
146            createProperty(LDP_NAMESPACE + "hasMemberRelation");
147    public static final Property INSERTED_CONTENT_RELATION =
148            createProperty(LDP_NAMESPACE + "insertedContentRelation");
149    public static final Property CONTAINS =
150        createProperty(LDP_NAMESPACE + "contains");
151    public static final Property LDP_MEMBER =
152            createProperty(LDP_NAMESPACE + "member");
153    public static final Resource RESOURCE =
154            createResource(LDP_NAMESPACE + "Resource");
155    public static final Resource RDF_SOURCE =
156            createResource(LDP_NAMESPACE + "RDFSource");
157    public static final Resource NON_RDF_SOURCE =
158        createResource(LDP_NAMESPACE + "NonRDFSource");
159    public static final Property CONSTRAINED_BY =
160            createProperty(LDP_NAMESPACE + "constrainedBy");
161    public static final Property MEMBER_SUBJECT =
162            createProperty(LDP_NAMESPACE + "MemberSubject");
163
164    private static final Set<Property> ldpManagedProperties = of(CONTAINS);
165
166    // REPOSITORY INFORMATION
167    public static final Property HAS_TRANSACTION_SERVICE =
168            createProperty(REPOSITORY_NAMESPACE + "hasTransactionProvider");
169
170    // OTHER SERVICES
171    public static final Property HAS_FIXITY_SERVICE =
172            createProperty(REPOSITORY_NAMESPACE + "hasFixityService");
173
174    // BINARY DESCRIPTIONS
175    public static final Property DESCRIBES =
176            createProperty("http://www.iana.org/assignments/relation/describes");
177    public static final Property DESCRIBED_BY =
178            createProperty("http://www.iana.org/assignments/relation/describedby");
179
180    public static final Resource INACCESSIBLE_RESOURCE =
181            createResource(REPOSITORY_NAMESPACE + "inaccessibleResource");
182    public static final Property HAS_MIME_TYPE =
183            createProperty(EBUCORE_NAMESPACE + "hasMimeType");
184    public static final Property HAS_ORIGINAL_NAME =
185            createProperty(EBUCORE_NAMESPACE + "filename");
186
187    // EXTERNAL CONTENT
188    public static final Property EXTERNAL_CONTENT = createProperty(FCREPO_API_NAMESPACE + "ExternalContent");
189    public static final Property PROXY_FOR = createProperty(REPOSITORY_NAMESPACE + "proxyFor");
190    public static final Property REDIRECTS_TO = createProperty(REPOSITORY_NAMESPACE + "redirectsTo");
191
192    // RDF EXTRACTION
193    public static final Property INBOUND_REFERENCES = createProperty(FCREPO_API_NAMESPACE + "PreferInboundReferences");
194    public static final Property PREFER_SERVER_MANAGED = createProperty(REPOSITORY_NAMESPACE + "ServerManaged");
195
196    public static final Property EMBED_CONTAINED = createProperty(OA_NAMESPACE + "PreferContainedDescriptions");
197
198
199    // WEBAC
200    public static final String WEBAC_ACCESS_CONTROL_VALUE = WEBAC_NAMESPACE_VALUE + "accessControl";
201
202    public static final String SERVER_MANAGED_PROPERTIES_MODE = "fcrepo.properties.management";
203
204    // Properties which are managed by the server but are not from managed namespaces
205    private static final Set<Property> serverManagedProperties;
206    static {
207        final ImmutableSet.Builder<Property> b = ImmutableSet.builder();
208        b.addAll(fixityProperties).addAll(ldpManagedProperties);
209        serverManagedProperties = b.build();
210    }
211
212    private static final Predicate<Property> hasFedoraNamespace =
213        p -> !p.isAnon() && p.getNameSpace().startsWith(REPOSITORY_NAMESPACE);
214
215    private static Predicate<Property> hasMementoNamespace =
216        p -> !p.isAnon() && p.getNameSpace().startsWith(MEMENTO_NAMESPACE);
217
218    // Server managed properties which may be overridden by clients when the server is in "relaxed" mode
219    private static final Set<Property> relaxableProperties = of(LAST_MODIFIED_BY, LAST_MODIFIED_DATE, CREATED_BY,
220            CREATED_DATE);
221
222    // Detects if a server managed property is allowed to be updated in "relaxed" mode
223    public static final Predicate<Property> isRelaxed =
224            p -> relaxableProperties.contains(p)
225                    && ("relaxed".equals(System.getProperty(SERVER_MANAGED_PROPERTIES_MODE)));
226
227    /**
228     * Detects whether an RDF property is managed by the repository.
229     */
230    public static final Predicate<Property> isManagedPredicate =
231            hasFedoraNamespace.or(hasMementoNamespace).or(p -> serverManagedProperties.contains(p));
232
233    /**
234     * Fedora defined JCR node type with supertype of nt:file with two nt:folder named fedora:timemap and
235     * fedora:binaryTimemap inside.
236     */
237    public static final String NT_VERSION_FILE = "nt:versionFile";
238
239    /**
240     * Fedora defined JCR node type which can have no children except optionally a timemap
241     */
242    public static final String NT_LEAF_NODE = "nt:leafNode";
243
244    /**
245     * Fedora defined node path for a binary description.
246     */
247    public static final String FEDORA_DESCRIPTION = "fedora:description";
248
249    /**
250     * Fedora defined node path for a timemap
251     */
252    public static final String LDPCV_TIME_MAP = "fedora:timemap";
253
254    // VERSIONING
255    /**
256     * Memento TimeMap type.
257     */
258    public static final String VERSIONING_TIMEMAP_TYPE = MEMENTO_NAMESPACE + "TimeMap";
259
260    /**
261     * Memento TimeGate type.
262     */
263    public static final String VERSIONING_TIMEGATE_TYPE = MEMENTO_NAMESPACE + "TimeGate";
264
265    /**
266     * Type for memento objects.
267     */
268    public static final String MEMENTO_TYPE = MEMENTO_NAMESPACE + "Memento";
269
270    /**
271     * This is an internal RDF type for versionable resources, this may be replaced by a Memento type.
272     */
273    public static final Resource VERSIONED_RESOURCE =
274        createResource(MEMENTO_NAMESPACE + "OriginalResource");
275
276    /*
277     * Interaction Models.
278     */
279    public static final Set<Resource> INTERACTION_MODEL_RESOURCES = of(
280            BASIC_CONTAINER, INDIRECT_CONTAINER, DIRECT_CONTAINER, NON_RDF_SOURCE);
281
282    public static final Set<String> INTERACTION_MODELS = INTERACTION_MODEL_RESOURCES.stream()
283            .map(m -> m.getURI().replace(LDP_NAMESPACE, "ldp:"))
284            .collect(Collectors.toSet());
285
286    private RdfLexicon() {
287
288    }
289}