AbstractGraphElement.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.ostrichemulators.semtool.om;
import com.ostrichemulators.semtool.util.RDFDatatypeTools;
import com.ostrichemulators.semtool.util.Constants;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.LiteralImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.model.vocabulary.XMLSchema;
/**
*
* @author ryan
*/
public abstract class AbstractGraphElement
implements GraphElement, Comparable<AbstractGraphElement> {
private static final Set<URI> COUNTABLES = new HashSet<>();
private final transient List<PropertyChangeListener> listeners = new ArrayList<>();
private final transient Map<URI, Value> properties = new HashMap<>();
private URI graphid;
private Map<String, Object> propHash = new HashMap<>(); //this is sent to the js (ChartIt)
static {
COUNTABLES.add( XMLSchema.INT );
COUNTABLES.add( XMLSchema.INTEGER );
COUNTABLES.add( XMLSchema.FLOAT );
COUNTABLES.add( XMLSchema.DOUBLE );
COUNTABLES.add( XMLSchema.DECIMAL );
COUNTABLES.add( XMLSchema.DATE );
COUNTABLES.add( XMLSchema.DATETIME );
COUNTABLES.add( XMLSchema.TIME );
COUNTABLES.add( XMLSchema.LONG );
COUNTABLES.add( XMLSchema.SHORT );
}
public AbstractGraphElement( URI id ) {
this( id, null, id.getLocalName() );
}
public AbstractGraphElement( URI id, URI type, String label ) {
properties.put( RDF.SUBJECT, id );
properties.put( RDFS.LABEL, new LiteralImpl( label ) );
properties.put( RDF.TYPE, null == type ? Constants.ANYNODE : type );
graphid = id;
}
@Override
public void addPropertyChangeListener( PropertyChangeListener pcl ) {
listeners.add( pcl );
}
@Override
public void removePropertyChangeListener( PropertyChangeListener pcl ) {
listeners.remove( pcl );
}
@Override
public Collection<PropertyChangeListener> getPropertyChangeListeners() {
return new ArrayList<>( listeners );
}
protected void fireIfPropertyChanged( String prop, Object oldval, Object newval ) {
// we only want to fire if we need to, so check that something has
// actually changed
boolean oldNull = ( null == oldval );
boolean newNull = ( null == newval );
if ( oldNull && newNull ) {
return;
}
if ( !Objects.equals( oldval, newval ) ) {
PropertyChangeEvent pce
= new PropertyChangeEvent( this, prop, oldval, newval );
for ( PropertyChangeListener pcl : listeners ) {
pcl.propertyChange( pce );
}
}
}
/**
* Sets a new label for this vertex. This function is a convenience to null
* null null null null null {@link #setValue(org.openrdf.model.URI, org.openrdf.model.Value)
* }
* Any name is acceptable. We can always rename a vertex or edge.
*
* @param label the new label to set
*/
@Override
public void setLabel( String label ) {
setValue( RDFS.LABEL, RDFDatatypeTools.getValueFromObject( label ) );
}
@Override
public Set<URI> getPropertyKeys() {
return new HashSet<>( properties.keySet() );
}
@Override
public String getLabel() {
return ( properties.containsKey( RDFS.LABEL )
? properties.get( RDFS.LABEL ).stringValue() : "" );
}
@Override
public void setValue( URI prop, Value val ) {
Value oldval = properties.get( prop );
properties.put( prop, val );
fireIfPropertyChanged( prop.toString(), oldval, val );
}
public void setPropHash( Map<String, Object> _propHash ) {
propHash = _propHash;
}
public Map<String, Object> getPropHash() {
return propHash;
}
@Override
public Value getValue( URI prop ) {
return properties.get( prop );
}
@Override
public Map<URI, Value> getValues() {
return properties;
}
@Override
public boolean hasProperty( URI prop ) {
return properties.containsKey( prop );
}
@Override
public void setURI( URI uri ) {
setValue( RDF.SUBJECT, uri );
}
@Override
public URI getURI() {
return URI.class.cast( getValue( RDF.SUBJECT ) );
}
@Override
public URI getType() {
return URI.class.cast( getValue( RDF.TYPE ) );
}
@Override
public void setType( URI type ) {
setValue( RDF.TYPE, type );
}
@Override
public void removeProperty( URI prop ) {
properties.remove( prop );
}
/**
* Gets the datatype for the value that would be returned for the given
* property from a call to {@link #getValue(org.openrdf.model.URI) }
*
* @param prop the property to find
* @return the datatype, or {@link XMLSchema#ANYURI} if the value is a URI, or
* {@link XMLSchema#ENTITY} for a BNode.
*/
public URI getDataType( URI prop ) {
if ( properties.containsKey( prop ) ) {
Value data = properties.get( prop );
return RDFDatatypeTools.getDatatype( data );
}
return null;
}
@Override
public URI getGraphId() {
return graphid;
}
@Override
public void setGraphId( URI graphid ) {
this.graphid = graphid;
}
@Override
public int hashCode() {
int hash = 7;
hash = 41 * hash + Objects.hashCode( this.getGraphId() );
return hash;
}
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
final AbstractGraphElement other = (AbstractGraphElement) obj;
return Objects.equals( this.getGraphId(), other.getGraphId() );
}
@Override
public String toString() {
return getURI() + "; " + getType().getLocalName() + "; " + getLabel();
}
@Override
public int compareTo( AbstractGraphElement o ) {
return toString().compareTo( o.toString() );
}
/**
* Gets all the property keys that have "countable" values (int, double, date)
*
* @param age
* @return
*/
public static List<URI> getCountablePropertyKeys( GraphElement age ) {
List<URI> keys = new ArrayList<>();
for ( Map.Entry<URI, Value> en : age.getValues().entrySet() ) {
Value val = en.getValue();
if ( val instanceof Literal ) {
Literal lit = Literal.class.cast( val );
URI dt = lit.getDatatype();
if ( COUNTABLES.contains( dt ) ) {
keys.add( en.getKey() );
}
}
}
return keys;
}
}