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;
023import static org.apache.jena.vocabulary.RDF.type;
024
025import java.util.Set;
026import java.util.function.Predicate;
027import java.util.stream.Collectors;
028
029import org.apache.jena.graph.Triple;
030import org.apache.jena.rdf.model.Property;
031import org.apache.jena.rdf.model.Resource;
032
033import com.google.common.collect.ImmutableSet;
034
035/**
036 * A lexicon of the RDF properties that the fcrepo kernel (or close-to-core modules) use
037 *
038 * @author ajs6f
039 */
040public final class RdfLexicon {
041
042    /**
043     * Repository namespace "fedora"
044    **/
045    public static final String REPOSITORY_NAMESPACE = "http://fedora.info/definitions/v4/repository#";
046
047    public static final String REPOSITORY_WEBAC_NAMESPACE = "http://fedora.info/definitions/v4/webac#";
048
049    public static final String FCREPO_API_NAMESPACE = "http://fedora.info/definitions/fcrepo#";
050
051    public static final String ACTIVITY_STREAMS_NAMESPACE = "https://www.w3.org/ns/activitystreams#";
052
053    public static final String EBUCORE_NAMESPACE = "http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#";
054
055    public static final String OA_NAMESPACE = "http://www.w3.org/ns/oa#";
056
057    public static final String PROV_NAMESPACE = "http://www.w3.org/ns/prov#";
058
059    public static final String PREMIS_NAMESPACE = "http://www.loc.gov/premis/rdf/v1#";
060
061    public static final String MEMENTO_NAMESPACE = "http://mementoweb.org/ns#";
062
063    public static final String RDF_NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
064
065
066    /**
067     * Namespace for the W3C WebAC vocabulary.
068     */
069    public static final String WEBAC_NAMESPACE_VALUE = "http://www.w3.org/ns/auth/acl#";
070
071    /**
072     * Linked Data Platform namespace.
073     */
074    public static final String LDP_NAMESPACE = "http://www.w3.org/ns/ldp#";
075
076    /**
077     * Is this namespace one that the repository manages?
078     */
079    public static final Predicate<String> isManagedNamespace = p -> p.equals(REPOSITORY_NAMESPACE) ||
080            p.equals(LDP_NAMESPACE) || p.equals(MEMENTO_NAMESPACE);
081
082    /**
083     * Tests if the triple has a predicate of rdf:type and an object with a managed namespace.
084     * @see RdfLexicon#isManagedNamespace
085     */
086    public static final Predicate<Triple> restrictedType = s -> s.getPredicate().equals(type.asNode()) &&
087            (s.getObject().isURI() && isManagedNamespace.test(s.getObject().getNameSpace()));
088
089    // FIXITY
090    public static final Property HAS_MESSAGE_DIGEST =
091            createProperty(PREMIS_NAMESPACE + "hasMessageDigest");
092
093    public static final Property HAS_SIZE =
094        createProperty(PREMIS_NAMESPACE + "hasSize");
095    public static final Property HAS_FIXITY_RESULT =
096        createProperty(PREMIS_NAMESPACE + "hasFixity");
097
098    private static final Set<Property> fixityProperties = of(
099            HAS_FIXITY_RESULT, HAS_MESSAGE_DIGEST);
100
101    public static final Property HAS_FIXITY_STATE =
102            createProperty(PREMIS_NAMESPACE + "hasEventOutcome");
103
104    public static final Property WRITABLE =
105            createProperty(REPOSITORY_NAMESPACE + "writable");
106
107    public static final String FEDORA_NON_RDF_SOURCE_DESCRIPTION_URI = REPOSITORY_NAMESPACE +
108            "NonRdfSourceDescription";
109
110    // Server managed properties
111    public static final Property CREATED_DATE =
112            createProperty(REPOSITORY_NAMESPACE + "created");
113    public static final Property CREATED_BY =
114            createProperty(REPOSITORY_NAMESPACE + "createdBy");
115    public static final Property LAST_MODIFIED_DATE =
116            createProperty(REPOSITORY_NAMESPACE + "lastModified");
117    public static final Property LAST_MODIFIED_BY =
118            createProperty(REPOSITORY_NAMESPACE + "lastModifiedBy");
119
120    public static final Resource FEDORA_CONTAINER =
121            createResource(REPOSITORY_NAMESPACE + "Container");
122    public static final Resource FEDORA_BINARY =
123            createResource(REPOSITORY_NAMESPACE + "Binary");
124    public static final Resource FEDORA_RESOURCE =
125            createResource(REPOSITORY_NAMESPACE + "Resource");
126    public static final Resource FEDORA_PAIR_TREE =
127            createResource(REPOSITORY_NAMESPACE + "Pairtree");
128    public static final Resource ARCHIVAL_GROUP =
129            createResource(REPOSITORY_NAMESPACE + "ArchivalGroup");
130    public static final Resource TIME_MAP =
131            createResource(REPOSITORY_NAMESPACE + "TimeMap");
132
133    // Linked Data Platform
134    public static final Property PAGE =
135        createProperty(LDP_NAMESPACE + "Page");
136    public static final Resource CONTAINER =
137            createResource(LDP_NAMESPACE + "Container");
138    public static final Resource BASIC_CONTAINER =
139            createResource(LDP_NAMESPACE + "BasicContainer");
140    public static final Resource DIRECT_CONTAINER =
141            createResource(LDP_NAMESPACE + "DirectContainer");
142    public static final Resource INDIRECT_CONTAINER =
143            createResource(LDP_NAMESPACE + "IndirectContainer");
144    public static final Property MEMBERSHIP_RESOURCE =
145            createProperty(LDP_NAMESPACE + "membershipResource");
146    public static final Property HAS_MEMBER_RELATION =
147            createProperty(LDP_NAMESPACE + "hasMemberRelation");
148    public static final Property INSERTED_CONTENT_RELATION =
149            createProperty(LDP_NAMESPACE + "insertedContentRelation");
150    public static final Property IS_MEMBER_OF_RELATION =
151            createProperty(LDP_NAMESPACE + "isMemberOfRelation");
152    public static final Property CONTAINS =
153        createProperty(LDP_NAMESPACE + "contains");
154    public static final Property LDP_MEMBER =
155            createProperty(LDP_NAMESPACE + "member");
156    public static final Resource RESOURCE =
157            createResource(LDP_NAMESPACE + "Resource");
158    public static final Resource RDF_SOURCE =
159            createResource(LDP_NAMESPACE + "RDFSource");
160    public static final Resource NON_RDF_SOURCE =
161        createResource(LDP_NAMESPACE + "NonRDFSource");
162    public static final Property CONSTRAINED_BY =
163            createProperty(LDP_NAMESPACE + "constrainedBy");
164    public static final Property MEMBER_SUBJECT =
165            createProperty(LDP_NAMESPACE + "MemberSubject");
166
167    private static final Set<Property> ldpManagedProperties = of(CONTAINS);
168
169    // REPOSITORY INFORMATION
170    public static final Property HAS_TRANSACTION_SERVICE =
171            createProperty(REPOSITORY_NAMESPACE + "hasTransactionProvider");
172    public static final Resource REPOSITORY_ROOT =
173            createResource(REPOSITORY_NAMESPACE + "RepositoryRoot");
174
175    // OTHER SERVICES
176    public static final Property HAS_FIXITY_SERVICE =
177            createProperty(REPOSITORY_NAMESPACE + "hasFixityService");
178
179    public static final Property HAS_MIME_TYPE =
180            createProperty(EBUCORE_NAMESPACE + "hasMimeType");
181    public static final Property HAS_ORIGINAL_NAME =
182            createProperty(EBUCORE_NAMESPACE + "filename");
183
184    // EXTERNAL CONTENT
185    public static final Property EXTERNAL_CONTENT = createProperty(FCREPO_API_NAMESPACE + "ExternalContent");
186    public static final Property PROXY_FOR = createProperty(REPOSITORY_NAMESPACE + "proxyFor");
187    public static final Property REDIRECTS_TO = createProperty(REPOSITORY_NAMESPACE + "redirectsTo");
188
189    // RDF EXTRACTION
190    public static final Property INBOUND_REFERENCES = createProperty(FCREPO_API_NAMESPACE + "PreferInboundReferences");
191    public static final Property PREFER_SERVER_MANAGED = createProperty(REPOSITORY_NAMESPACE + "ServerManaged");
192    public static final Property PREFER_MINIMAL_CONTAINER = createProperty(LDP_NAMESPACE +
193            "PreferMinimalContainer");
194    public static final Property PREFER_CONTAINMENT = createProperty(LDP_NAMESPACE + "PreferContainment");
195    public static final Property PREFER_MEMBERSHIP = createProperty(LDP_NAMESPACE + "PreferMembership");
196
197
198    public static final Property EMBED_CONTAINED = createProperty(OA_NAMESPACE + "PreferContainedDescriptions");
199
200
201    // WEBAC
202    public static final String WEBAC_ACCESS_CONTROL_VALUE = WEBAC_NAMESPACE_VALUE + "accessControl";
203
204    public static final String SERVER_MANAGED_PROPERTIES_MODE = "fcrepo.properties.management";
205
206    public static final String WEBAC_ACCESS_TO = WEBAC_NAMESPACE_VALUE + "accessTo";
207
208    public static final String WEBAC_ACCESS_TO_CLASS = WEBAC_NAMESPACE_VALUE + "accessToClass";
209
210    public static final Property WEBAC_ACCESS_TO_PROPERTY = createProperty(WEBAC_ACCESS_TO);
211
212    public static final String FEDORA_WEBAC_ACL_URI = REPOSITORY_WEBAC_NAMESPACE + "Acl";
213
214    // Properties which are managed by the server but are not from managed namespaces
215    private static final Set<Property> serverManagedProperties;
216    static {
217        final ImmutableSet.Builder<Property> b = ImmutableSet.builder();
218        b.addAll(fixityProperties).addAll(ldpManagedProperties);
219        serverManagedProperties = b.build();
220    }
221
222    private static final Predicate<Property> hasFedoraNamespace =
223        p -> !p.isAnon() && p.getNameSpace().startsWith(REPOSITORY_NAMESPACE);
224
225    private static Predicate<Property> hasMementoNamespace =
226        p -> !p.isAnon() && p.getNameSpace().startsWith(MEMENTO_NAMESPACE);
227
228    // Server managed properties which may be overridden by clients when the server is in "relaxed" mode
229    private static final Set<Property> relaxableProperties = of(LAST_MODIFIED_BY, LAST_MODIFIED_DATE, CREATED_BY,
230            CREATED_DATE);
231
232    // Detects if a server managed property is allowed to be updated in "relaxed" mode
233    public static final Predicate<Property> isRelaxed =
234            p -> relaxableProperties.contains(p)
235                    && ("relaxed".equals(System.getProperty(SERVER_MANAGED_PROPERTIES_MODE)));
236
237    /**
238     * Detects whether an RDF property is managed by the repository.
239     */
240    public static final Predicate<Property> isManagedPredicate =
241            hasFedoraNamespace.or(hasMementoNamespace).or(p -> serverManagedProperties.contains(p));
242
243    // VERSIONING
244    /**
245     * Memento TimeMap type.
246     */
247    public static final String VERSIONING_TIMEMAP_TYPE = MEMENTO_NAMESPACE + "TimeMap";
248    public static final Resource VERSIONING_TIMEMAP = createResource(VERSIONING_TIMEMAP_TYPE);
249
250    /**
251     * Memento TimeGate type.
252     */
253    public static final String VERSIONING_TIMEGATE_TYPE = MEMENTO_NAMESPACE + "TimeGate";
254
255    /**
256     * Type for memento objects.
257     */
258    public static final String MEMENTO_TYPE = MEMENTO_NAMESPACE + "Memento";
259
260    /**
261     * This is an internal RDF type for versionable resources, this may be replaced by a Memento type.
262     */
263    public static final Resource VERSIONED_RESOURCE =
264        createResource(MEMENTO_NAMESPACE + "OriginalResource");
265
266    public static final Property MEMENTO_ORIGINAL_RESOURCE =
267        createProperty(MEMENTO_NAMESPACE + "original");
268
269    /*
270     * Interaction Models.
271     */
272    public static final Set<Resource> INTERACTION_MODEL_RESOURCES = of(
273            BASIC_CONTAINER, INDIRECT_CONTAINER, DIRECT_CONTAINER, NON_RDF_SOURCE);
274
275    /**
276     * String set of valid interaction models with full LDP URI.
277     */
278    public static final Set<String> INTERACTION_MODELS_FULL = INTERACTION_MODEL_RESOURCES.stream().map(Resource::getURI)
279            .collect(Collectors.toSet());
280
281    /**
282     * This defines what we assume if you don't specify.
283     */
284    public static final Resource DEFAULT_INTERACTION_MODEL = BASIC_CONTAINER;
285
286    private RdfLexicon() {
287        // This constructor left intentionally blank.
288    }
289}