001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.kernel.modeshape.rdf.impl;
017
018import static com.google.common.collect.ImmutableSet.builder;
019import static com.hp.hpl.jena.graph.NodeFactory.createLiteral;
020import static com.hp.hpl.jena.graph.NodeFactory.createURI;
021import static com.hp.hpl.jena.graph.Triple.create;
022import static com.hp.hpl.jena.rdf.model.ResourceFactory.createTypedLiteral;
023import static java.util.Arrays.stream;
024import static java.util.stream.Collectors.joining;
025import static org.fcrepo.kernel.api.FedoraJcrTypes.ROOT;
026import static org.fcrepo.kernel.api.RdfLexicon.HAS_FIXITY_CHECK_COUNT;
027import static org.fcrepo.kernel.api.RdfLexicon.HAS_FIXITY_ERROR_COUNT;
028import static org.fcrepo.kernel.api.RdfLexicon.HAS_FIXITY_REPAIRED_COUNT;
029import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
030import static org.slf4j.LoggerFactory.getLogger;
031
032import com.hp.hpl.jena.rdf.model.Resource;
033import org.apache.commons.lang3.StringUtils;
034import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
035import org.fcrepo.kernel.api.models.FedoraResource;
036import org.fcrepo.metrics.RegistryService;
037
038import java.util.Map;
039import javax.jcr.Repository;
040import org.fcrepo.kernel.modeshape.services.functions.GetClusterConfiguration;
041import org.modeshape.jcr.JcrRepository;
042import org.slf4j.Logger;
043
044import com.codahale.metrics.Counter;
045import com.google.common.collect.ImmutableSet;
046import com.hp.hpl.jena.graph.Triple;
047
048/**
049 * Assemble {@link Triple}s derived from the root of a repository.
050 *
051 * @author ajs6f
052 * @since Oct 18, 2013
053 */
054public class RootRdfContext extends NodeRdfContext {
055
056    private static final String PREFIX = "org.fcrepo.services.";
057    private static final String FIXITY_REPAIRED_COUNTER = "LowLevelStorageService.fixity-repaired-counter";
058    private static final String FIXITY_ERROR_COUNTER = "LowLevelStorageService.fixity-error-counter";
059    private static final String FIXITY_CHECK_COUNTER = "LowLevelStorageService.fixity-check-counter";
060    private static final Logger LOGGER = getLogger(RootRdfContext.class);
061    static final RegistryService registryService = RegistryService.getInstance();
062
063    /**
064     * Ordinary constructor.
065     *
066     * @param resource the resource
067     * @param idTranslator the id translator
068     */
069    public RootRdfContext(final FedoraResource resource,
070                          final IdentifierConverter<Resource, FedoraResource> idTranslator) {
071        super(resource, idTranslator);
072
073        if (resource().hasType(ROOT)) {
074            concatRepositoryTriples();
075        }
076    }
077
078    private void concatRepositoryTriples() {
079        LOGGER.trace("Creating RDF triples for repository description");
080        final Repository repository = session().getRepository();
081
082        final ImmutableSet.Builder<Triple> b = builder();
083        stream(repository.getDescriptorKeys()).forEach(key -> {
084            final String descriptor = repository.getDescriptor(key);
085            if (descriptor != null) {
086                // Create a URI from the jcr.Repository constant values,
087                // converting them from dot notation (identifier.stability)
088                // to the camel case that is more common in RDF properties.
089                final String uri = stream(key.split("\\."))
090                        .map(StringUtils::capitalize).collect(joining("", REPOSITORY_NAMESPACE + "repository", ""));
091                b.add(create(subject(), createURI(uri), createLiteral(descriptor)));
092            }
093        });
094
095        /*
096            FIXME: removing due to performance problems, esp. w/ many files on federated filesystem
097            see: https://www.pivotaltracker.com/story/show/78647248
098
099            b.add(create(subject(), HAS_OBJECT_COUNT.asNode(), createLiteral(String
100                    .valueOf(getRepositoryCount(repository)))));
101            b.add(create(subject(), HAS_OBJECT_SIZE.asNode(), createLiteral(String
102                    .valueOf(getRepositorySize(repository)))));
103        */
104
105        // Get the cluster configuration, if available
106        // this ugly test checks to see whether this is an ordinary JCR
107        // repository or a ModeShape repo, which will possess the extra info
108        if (JcrRepository.class.isAssignableFrom(repository.getClass())) {
109            final Map<String, String> config = new GetClusterConfiguration().apply(repository);
110            assert (config != null);
111            config.forEach((k, v) -> b.add(create(subject(), createURI(REPOSITORY_NAMESPACE + k), createLiteral(v))));
112        }
113
114        // retrieve the metrics from the service
115        final Map<String, Counter> counters = registryService.getMetrics().getCounters();
116        // and add the repository metrics to the RDF model
117        if (counters.containsKey(FIXITY_CHECK_COUNTER)) {
118            b.add(create(subject(), HAS_FIXITY_CHECK_COUNT.asNode(),
119                    createTypedLiteral(counters.get(PREFIX + FIXITY_CHECK_COUNTER).getCount()).asNode()));
120        }
121
122        if (counters.containsKey(FIXITY_ERROR_COUNTER)) {
123            b.add(create(subject(), HAS_FIXITY_ERROR_COUNT.asNode(),
124                    createTypedLiteral(counters.get(PREFIX + FIXITY_ERROR_COUNTER).getCount()).asNode()));
125        }
126
127        if (counters.containsKey(FIXITY_REPAIRED_COUNTER)) {
128            b.add(create(subject(), HAS_FIXITY_REPAIRED_COUNT.asNode(),
129                    createTypedLiteral(counters.get(PREFIX + FIXITY_REPAIRED_COUNTER).getCount()).asNode()));
130        }
131
132        // offer all these accumulated triples
133        concat(b.build());
134    }
135}