/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.stanbol.enhancer.servicesapi.impl; import java.io.IOException; import java.io.InputStream; import java.util.Map; import org.apache.clerezza.commons.rdf.Graph; import org.apache.clerezza.commons.rdf.Triple; import org.apache.clerezza.commons.rdf.IRI; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.ConfigurationPolicy; import org.apache.felix.scr.annotations.Service; import org.apache.stanbol.enhancer.servicesapi.Blob; import org.apache.stanbol.enhancer.servicesapi.ContentItem; import org.apache.stanbol.enhancer.servicesapi.ContentItemFactory; import org.apache.stanbol.enhancer.servicesapi.ContentReference; import org.apache.stanbol.enhancer.servicesapi.ContentSink; import org.apache.stanbol.enhancer.servicesapi.ContentSource; import org.apache.stanbol.enhancer.servicesapi.helper.ContentItemHelper; /** * Abstract implementation of the {@link ContentItemFactory} that requires only * the three abstract methods <ul> * <li> {@link #createBlob(ContentSource)} * <li> {@link #createContentItem(String, Blob, Graph)} * <li> {@link #createContentItem(IRI, Blob, Graph)} * </ul> to be overridden.<p> * Implementers should NOTE that {@link #createBlob(ContentSource)} will be * called to create the main {@link Blob} instance for a contentItem before * the {@link ContentItem} itself is instantiated. If this is a problem, than * this abstract super class can not be used. * * @author Rupert Westenthaler * @since 0.9.1-incubating */ @Component(componentAbstract=true,immediate=true,policy=ConfigurationPolicy.OPTIONAL) @Service(value=ContentItemFactory.class) public abstract class AbstractContentItemFactory implements ContentItemFactory { /** * State if {@link LazyDereferencingBlob}s are used for {@link Blob}s * created for {@link ContentReference}s */ private final boolean lazyLoadingBlobsEnabled; /** * Default constructor setting {@link #isLazyDereferenceing()} to <code>false</code> */ protected AbstractContentItemFactory(){ this(false); } /** * Creates a AbstractContentItemFactory and sets the state for the usage * of {@link LazyDereferencingBlob}s. * @param enableLazyDereferencingBlobs if {@link Blob}s generated for * {@link ContentReference}s should dereference the content during the * construction or lazily on the first access to the content. */ protected AbstractContentItemFactory(boolean enableLazyDereferencingBlobs){ this.lazyLoadingBlobsEnabled = enableLazyDereferencingBlobs; } @Override public final ContentItem createContentItem(ContentSource source) throws IOException { return createContentItem((IRI)null, source, null); } @Override public final ContentItem createContentItem(String prefix, ContentSource source) throws IOException { return createContentItem(prefix,source,null); } @Override public final ContentItem createContentItem(IRI id, ContentSource source) throws IOException { return createContentItem(id, source, null); } @Override public final ContentItem createContentItem(ContentReference reference) throws IOException { return createContentItem(reference, null); } @Override public final ContentItem createContentItem(ContentReference reference, Graph metadata) throws IOException { if(reference == null){ throw new IllegalArgumentException("The parsed ContentReference MUST NOT be NULL!"); } return createContentItem(new IRI(reference.getReference()),createBlob(reference),metadata); } @Override public final ContentItem createContentItem(String prefix, ContentSource source,Graph metadata) throws IOException { if(prefix == null){ throw new IllegalArgumentException("The parsed prefix MUST NOT be NULL!"); } if(source == null){ throw new IllegalArgumentException("The parsed ContentSource MUST NOT be NULL!"); } return createContentItem(prefix, createBlob(source), metadata); } @Override public final ContentItem createContentItem(IRI id, ContentSource source, Graph metadata) throws IOException { if(source == null){ throw new IllegalArgumentException("The parsed ContentSource MUST NOT be NULL!"); } return createContentItem(id, createBlob(source), metadata); } /** * Creates a ContentItem for the parsed parameters * @param id the ID or <code>null</code>. Implementors might want to use * {@link ContentItemHelper#streamDigest(InputStream, java.io.OutputStream, String) * for generating an ID while reading the data from the ContentSource * @param blob the Blob * @param metadata the metadata or <code>null</code> if none. Implementation * are free to use the passed instance or to generate a new one. However * they MUST ensure that all {@link Triple}s contained by the passed graph * are also added to the {@link ContentItem#getMetadata() metadata} of the * returned ContentItem. * @return the created content item */ protected abstract ContentItem createContentItem(IRI id, Blob blob, Graph metadata); /** * Creates a ContentItem for the parsed parameters * @param prefix the prefix for the ID of the contentItem. Guaranteed to be * NOT <code>null</code>. Implementors might want to use * {@link ContentItemHelper#streamDigest(InputStream, java.io.OutputStream, String) * for generating an ID while reading the data from the ContentSource * @param blob the Blob * @param metadata the metadata or <code>null</code> if none. Implementation * are free to use the passed instance or to generate a new one. However * they MUST ensure that all {@link Triple}s contained by the passed graph * are also added to the {@link ContentItem#getMetadata() metadata} of the * returned ContentItem. * @return the created content item */ protected abstract ContentItem createContentItem(String prefix, Blob blob, Graph metadata); @Override public abstract Blob createBlob(ContentSource source) throws IOException; @Override public abstract ContentSink createContentSink(String mediaType) throws IOException; /** * Getter for the state if the content from {@link ContentReference} used * to create {@link ContentItem}s and Blobs is dereferenced immediately or * - lazily - on the first usage. * @return the lazy dereferencing state. */ public boolean isLazyDereferenceing(){ return lazyLoadingBlobsEnabled; } @Override public final Blob createBlob(ContentReference reference) throws IOException { if(reference == null){ throw new IllegalArgumentException("The passed ContentReference MUST NOT be NULL!"); } if(lazyLoadingBlobsEnabled){ return new LazyDereferencingBlob(reference); } else { return createBlob(reference.dereference()); } } /** * If {@link AbstractContentItemFactory#isLazyDereferenceing} * @author westei * */ protected class LazyDereferencingBlob implements Blob { private final ContentReference contentReference; private Blob _blob; protected LazyDereferencingBlob(ContentReference contentReference){ this.contentReference = contentReference; } @Override public String getMimeType() { return getLazy().getMimeType(); } @Override public InputStream getStream() { return getLazy().getStream(); } @Override public Map<String,String> getParameter() { return getLazy().getParameter(); } @Override public long getContentLength() { if(_blob == null){ //do not dereference for calls on getContentLength return -1; } else { return _blob.getContentLength(); } } public Blob getLazy() { if(_blob == null){ try { _blob = createBlob(contentReference.dereference()); } catch (IOException e) { throw new IllegalStateException("Unable to derefernece content reference '" + contentReference.getReference()+" (Message: "+e.getMessage()+")!",e); } } return _blob; } } }