/*
* 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.jena.assembler.assemblers;
import java.util.*;
import java.util.function.Function;
import org.apache.jena.assembler.* ;
import org.apache.jena.assembler.exceptions.* ;
import org.apache.jena.rdf.model.* ;
import org.apache.jena.shared.* ;
import org.apache.jena.vocabulary.RDF ;
public abstract class ModelAssembler extends AssemblerBase implements Assembler
{
protected abstract Model openEmptyModel( Assembler a, Resource root, Mode mode );
protected Model openModel( Assembler a, Resource root, Content initial, Mode mode )
{
Model m = openEmptyModel( a, root, mode );
if (!initial.isEmpty()) addContent( root, m, initial );
return m;
}
@Override public Object open( Assembler a, Resource root, Mode mode )
{
Model m = openModel( a, root, getInitialContent( a, root ), mode );
addContent( root, m, getContent( a, root ) );
m.setNsPrefixes( getPrefixMapping( a, root ) );
return m;
}
protected void addContent( Resource root, Model m, Content c )
{
if (m.supportsTransactions())
{
m.begin();
try { c.fill( m ); m.commit(); }
catch (Throwable t) { m.abort(); throw new TransactionAbortedException( root, t ); }
}
else
c.fill( m );
}
private PrefixMapping getPrefixMapping( Assembler a, Resource root )
{
return PrefixMappingAssembler.getPrefixes
( a, root, PrefixMapping.Factory.create() );
}
@Override public Model openModel( Resource root, Mode mode )
{ return (Model) open( this, root, mode ); }
protected Content getInitialContent( Assembler a, Resource root )
{
Model partial = ModelFactory.createDefaultModel();
Resource combined = partial.createResource();
for (StmtIterator it = root.listProperties( JA.initialContent ); it.hasNext();)
transferContentProperties( partial, it.nextStatement().getResource(), combined );
return contentFromModel( a, root, partial, combined );
}
private Content contentFromModel( Assembler a, Resource root, Model partial, Resource combined )
{
return partial.isEmpty()
? Content.empty
: (Content) a.open( completedClone( root, combined, partial ) )
;
}
protected Content getContent( Assembler a, Resource root )
{
final Resource newRoot = oneLevelClone( root );
final Model fragment = newRoot.getModel();
return fragment.isEmpty() ? Content.empty : (Content) a.open( a, completedClone( root, newRoot, fragment ) );
}
private Resource completedClone( Resource root, Resource newRoot, Model fragment )
{
Model typed = fragment.add( newRoot, RDF.type, JA.Content );
return newRoot.inModel( ModelFactory.createUnion( root.getModel(), typed ) );
}
private Resource oneLevelClone( Resource root )
{
Model partialCopy = ModelFactory.createDefaultModel();
Resource newRoot = partialCopy.createResource();
transferContentProperties( partialCopy, root, newRoot );
return newRoot;
}
private void transferContentProperties( Model partial, Resource someInitial, Resource combined )
{
for ( Property contentProperty : ContentAssembler.contentProperties )
{
partial.add( copyProperties( someInitial, replaceSubjectMap( partial, combined ), contentProperty ) );
}
}
private List<Statement> copyProperties( Resource root, Function<Statement, Statement> replace, Property property )
{ return root.listProperties( property ).mapWith( replace ).toList(); }
private Function<Statement, Statement> replaceSubjectMap( final Model inModel, final Resource newSubject ) {
return s -> inModel.createStatement(newSubject, s.getPredicate(), s.getObject());
}
}