package org.xenei.jdbc4sparql.impl.rdf; import java.sql.DatabaseMetaData; import java.util.ArrayList; import java.util.List; import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.xenei.jdbc4sparql.iface.Catalog; import org.xenei.jdbc4sparql.iface.Column; import org.xenei.jdbc4sparql.iface.ColumnDef; import org.xenei.jdbc4sparql.iface.Schema; import org.xenei.jdbc4sparql.iface.Table; import org.xenei.jdbc4sparql.iface.name.ColumnName; import org.xenei.jdbc4sparql.impl.NameUtils; import org.xenei.jena.entities.EntityManager; import org.xenei.jena.entities.EntityManagerFactory; import org.xenei.jena.entities.EntityManagerRequiredException; import org.xenei.jena.entities.MissingAnnotation; import org.xenei.jena.entities.ResourceWrapper; import org.xenei.jena.entities.annotations.Predicate; import org.xenei.jena.entities.annotations.Subject; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.shared.Lock; import com.hp.hpl.jena.vocabulary.RDFS; @Subject(namespace = "http://org.xenei.jdbc4sparql/entity/Column#") public class RdfColumn extends RdfNamespacedObject implements Column, ResourceWrapper { public static class Builder implements Column { public static RdfColumn fixupTable(final RdfTable table, final RdfColumn column) { column.table = table; return column; } private ColumnDef columnDef; private Table table; private String name; private final Class<? extends RdfColumn> typeClass = RdfColumn.class; private String remarks = null; private final List<String> querySegments = new ArrayList<String>(); /** * Add a query segment where %1$s = tableVar, and %2$s=columnVar * * @param querySegment * @return */ public Builder addQuerySegment(final String querySegment) { querySegments.add(querySegment); return this; } public RdfColumn build(final Model model) { checkBuildState(); final ResourceBuilder builder = new ResourceBuilder(model); Resource column = null; if (builder.hasResource(getFQName())) { column = builder.getResource(getFQName(), typeClass); } else { column = builder.getResource(getFQName(), typeClass); column.addLiteral(RDFS.label, name); column.addLiteral(builder.getProperty(typeClass, "remarks"), StringUtils.defaultString(remarks)); column.addProperty(builder.getProperty(typeClass, "columnDef"), ((ResourceWrapper) columnDef).getResource()); } if (!querySegments.isEmpty()) { final String eol = System.getProperty("line.separator"); final StringBuilder sb = new StringBuilder(); for (final String seg : querySegments) { sb.append(seg).append(eol); } final Property querySegmentProp = builder.getProperty( typeClass, "querySegmentFmt"); column.addLiteral(querySegmentProp, getQuerySegmentFmt()); querySegments.clear(); } final EntityManager entityManager = EntityManagerFactory .getEntityManager(); try { final RdfColumn retval = entityManager.read(column, typeClass); RdfTable tbl = null; if (table instanceof RdfTable.Builder) { tbl = ((RdfTable.Builder) table).build(model); } else if (table instanceof RdfTable) { tbl = (RdfTable) table; } else { throw new IllegalArgumentException( "table not an rdf table or builder"); } // table is now a real RdfTable so add it as a property column.addProperty(builder.getProperty(typeClass, "table"), tbl.getResource()); return Builder.fixupTable(tbl, retval); } catch (final MissingAnnotation e) { throw new RuntimeException(e); } } protected void checkBuildState() { if (columnDef == null) { throw new IllegalStateException("columnDef must be set"); } if (!(columnDef instanceof ResourceWrapper)) { throw new IllegalStateException( "columnDef must implement ResourceWrapper"); } if (table == null) { throw new IllegalStateException("table must be set"); } if (StringUtils.isBlank(name)) { throw new IllegalStateException("Name must be set"); } if (querySegments.size() == 0) { querySegments.add("# no query segments provided"); } } @Override public Catalog getCatalog() { return table.getSchema().getCatalog(); } @Override public ColumnDef getColumnDef() { return columnDef; } public String getFQName() { final ResourceWrapper rw = (ResourceWrapper) getColumnDef(); final StringBuilder sb = new StringBuilder() .append(rw.getResource().getURI()).append(" ").append(name) .append(" ").append(getQuerySegmentFmt()); return String.format("%s/instance/UUID-%s", ResourceBuilder.getFQName(RdfColumn.class), UUID.nameUUIDFromBytes(sb.toString().getBytes())); } @Override public ColumnName getName() { return table.getName().getColumnName(name); } @Override public String getQuerySegmentFmt() { final String eol = System.getProperty("line.separator"); final StringBuilder sb = new StringBuilder(); if (!querySegments.isEmpty()) { for (final String seg : querySegments) { sb.append(seg).append(eol); } } else { sb.append("# no segment provided").append(eol); } return sb.toString(); } @Override public String getRemarks() { return remarks; } @Override public Schema getSchema() { return table.getSchema(); } @Override public String getSPARQLName() { return NameUtils.getSPARQLName(this); } @Override public String getSQLName() { return NameUtils.getDBName(this); } @Override public Table getTable() { return table; } @Override public boolean hasQuerySegments() { return querySegments.size() > 0; } @Override public boolean isOptional() { return getColumnDef().getNullable() != DatabaseMetaData.columnNoNulls; } public Builder setColumnDef(final ColumnDef columnDef) { if (columnDef instanceof ResourceWrapper) { this.columnDef = columnDef; } return this; } public Builder setName(final String name) { this.name = name; return this; } public Builder setRemarks(final String remarks) { this.remarks = remarks; return this; } public Builder setTable(final Table table) { this.table = table; return this; } } private RdfTable table; private ColumnName columnName; public void delete() { final Model model = getResource().getModel(); final Resource r = getResource(); model.enterCriticalSection(Lock.WRITE); try { model.remove(null, null, r); model.remove(r, null, null); } finally { model.leaveCriticalSection(); } } @Override public RdfCatalog getCatalog() { return getSchema().getCatalog(); } @Override @Predicate(impl = true) public RdfColumnDef getColumnDef() { throw new EntityManagerRequiredException(); } @Override public ColumnName getName() { if (columnName == null) { columnName = getTable().getName().getColumnName(getSimpleName()); } return columnName; } @Override @Predicate(impl = true) public String getQuerySegmentFmt() { throw new EntityManagerRequiredException(); } @Override @Predicate(impl = true) public String getRemarks() { throw new EntityManagerRequiredException(); } @Override @Predicate(impl = true) public Resource getResource() { throw new EntityManagerRequiredException(); } @Override public RdfSchema getSchema() { return getTable().getSchema(); } @Predicate(impl = true, namespace = "http://www.w3.org/2000/01/rdf-schema#", name = "label") public String getSimpleName() { throw new EntityManagerRequiredException(); } @Override public String getSPARQLName() { return NameUtils.getSPARQLName(this); } @Override public String getSQLName() { return NameUtils.getDBName(this); } @Override public RdfTable getTable() { return table; } @Override public boolean hasQuerySegments() { return true; } @Override public boolean isOptional() { return getColumnDef().getNullable() != DatabaseMetaData.columnNoNulls; } @Override public String toString() { return getName().toString(); } }