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 org.fcrepo.kernel.api.FedoraJcrTypes.ROOT;
024import static org.fcrepo.kernel.api.RdfLexicon.HAS_FIXITY_CHECK_COUNT;
025import static org.fcrepo.kernel.api.RdfLexicon.HAS_FIXITY_ERROR_COUNT;
026import static org.fcrepo.kernel.api.RdfLexicon.HAS_FIXITY_REPAIRED_COUNT;
027import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
028import static org.slf4j.LoggerFactory.getLogger;
029
030import com.hp.hpl.jena.rdf.model.Resource;
031import org.apache.commons.lang.StringUtils;
032import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
033import org.fcrepo.kernel.api.models.FedoraResource;
034import org.fcrepo.metrics.RegistryService;
035
036import java.util.Map;
037import java.util.SortedMap;
038
039import javax.jcr.Repository;
040import javax.jcr.RepositoryException;
041
042import org.fcrepo.kernel.modeshape.services.functions.GetClusterConfiguration;
043import org.modeshape.jcr.JcrRepository;
044import org.slf4j.Logger;
045
046import com.codahale.metrics.Counter;
047import com.google.common.collect.ImmutableSet;
048import com.hp.hpl.jena.graph.Triple;
049
050/**
051 * Assemble {@link Triple}s derived from the root of a repository.
052 *
053 * @author ajs6f
054 * @since Oct 18, 2013
055 */
056public class RootRdfContext extends NodeRdfContext {
057
058    private static final Logger LOGGER = getLogger(RootRdfContext.class);
059    static final RegistryService registryService = RegistryService.getInstance();
060
061    /**
062     * Ordinary constructor.
063     *
064     * @param resource the resource
065     * @param idTranslator the id translator
066     * @throws RepositoryException if repository exception occurred
067     */
068    public RootRdfContext(final FedoraResource resource,
069                          final IdentifierConverter<Resource, FedoraResource> idTranslator)
070            throws RepositoryException {
071        super(resource, idTranslator);
072
073        if (resource().hasType(ROOT)) {
074            concatRepositoryTriples();
075        }
076    }
077
078    private void concatRepositoryTriples() throws RepositoryException {
079        LOGGER.trace("Creating RDF triples for repository description");
080        final Repository repository = resource().getNode().getSession().getRepository();
081
082        final ImmutableSet.Builder<Triple> b = builder();
083
084        for (final String key : repository.getDescriptorKeys()) {
085            final String descriptor = repository.getDescriptor(key);
086            if (descriptor != null) {
087                // Create a URI from the jcr.Repository constant values,
088                // converting them from dot notation (identifier.stability)
089                // to the camel case that is more common in RDF properties.
090                final StringBuilder uri = new StringBuilder(REPOSITORY_NAMESPACE);
091                uri.append("repository");
092                for (final String segment : key.split("\\.")) {
093                    uri.append(StringUtils.capitalize(segment));
094                }
095                b.add(create(subject(), createURI(uri.toString()),
096                        createLiteral(descriptor)));
097            }
098        }
099
100        /*
101            FIXME: removing due to performance problems, esp. w/ many files on federated filesystem
102            see: https://www.pivotaltracker.com/story/show/78647248
103
104            b.add(create(subject(), HAS_OBJECT_COUNT.asNode(), createLiteral(String
105                    .valueOf(getRepositoryCount(repository)))));
106            b.add(create(subject(), HAS_OBJECT_SIZE.asNode(), createLiteral(String
107                    .valueOf(getRepositorySize(repository)))));
108        */
109
110        // Get the cluster configuration, if available
111        // this ugly test checks to see whether this is an ordinary JCR
112        // repository or a ModeShape repo, which will possess the extra info
113        if (JcrRepository.class.isAssignableFrom(repository.getClass())) {
114            final Map<String, String> config =
115                new GetClusterConfiguration().apply(repository);
116            assert (config != null);
117
118            for (final Map.Entry<String, String> entry : config.entrySet()) {
119                b.add(create(subject(), createURI(REPOSITORY_NAMESPACE + entry.getKey()),
120                        createLiteral(entry.getValue())));
121            }
122        }
123
124        // retrieve the metrics from the service
125        final SortedMap<String, Counter> counters = registryService.getMetrics().getCounters();
126        // and add the repository metrics to the RDF model
127        if (counters.containsKey("LowLevelStorageService.fixity-check-counter")) {
128            b.add(create(subject(), HAS_FIXITY_CHECK_COUNT.asNode(),
129                    createTypedLiteral(
130                            counters.get(
131                                    "org.fcrepo.services."
132                                            + "LowLevelStorageService."
133                                            + "fixity-check-counter")
134                                    .getCount()).asNode()));
135        }
136
137        if (counters.containsKey("LowLevelStorageService.fixity-error-counter")) {
138            b.add(create(subject(), HAS_FIXITY_ERROR_COUNT.asNode(),
139                    createTypedLiteral(
140                            counters.get(
141                                    "org.fcrepo.services."
142                                            + "LowLevelStorageService."
143                                            + "fixity-error-counter")
144                                    .getCount()).asNode()));
145        }
146
147        if (counters
148                .containsKey("LowLevelStorageService.fixity-repaired-counter")) {
149            b.add(create(subject(), HAS_FIXITY_REPAIRED_COUNT.asNode(),
150                    createTypedLiteral(
151                            counters.get(
152                                    "org.fcrepo.services."
153                                            + "LowLevelStorageService."
154                                            + "fixity-repaired-counter")
155                                    .getCount()).asNode()));
156        }
157
158        // offer all these accumulated triples
159        concat(b.build());
160    }
161
162}