code: package com.taxonic.carml.model.impl;
  
  import com.google.common.collect.ImmutableSet;
  import com.taxonic.carml.model.LogicalSource;
  import com.taxonic.carml.model.PredicateObjectMap;
  import com.taxonic.carml.model.Resource;
  import com.taxonic.carml.model.SubjectMap;
  import com.taxonic.carml.model.TriplesMap;
  import com.taxonic.carml.rdf_mapper.annotations.RdfProperty;
  import com.taxonic.carml.rdf_mapper.annotations.RdfType;
  import com.taxonic.carml.vocab.Rdf;
  import com.taxonic.carml.vocab.Rml;
  import com.taxonic.carml.vocab.Rr;
  import java.util.LinkedHashSet;
  import java.util.Objects;
  import java.util.Set;
  import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;
  import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
  import org.apache.commons.lang3.builder.ToStringStyle;
  import org.eclipse.rdf4j.model.util.ModelBuilder;
  import org.eclipse.rdf4j.model.vocabulary.RDF;
  
  public class CarmlTriplesMap extends CarmlResource implements TriplesMap{
  
  	private LogicalSource logicalSource;
  	private SubjectMap subjectMap;
  	private Set<PredicateObjectMap> predicateObjectMaps;
  
  	public CarmlTriplesMap() {
  		// Empty constructor for object mapper
  	}
  
  	public CarmlTriplesMap(
  		LogicalSource logicalSource,
  		SubjectMap subjectMap,
  		Set<PredicateObjectMap> predicateObjectMaps
  	) {
  		this.logicalSource = logicalSource;
  		this.subjectMap = subjectMap;
  		this.predicateObjectMaps = predicateObjectMaps;
  	}
  
  	@RdfProperty(Rml.logicalSource)
  	@RdfType(CarmlLogicalSource.class)
  	@Override
  	public LogicalSource getLogicalSource() {
  		return logicalSource;
  	}
  
  	@RdfProperty(Rr.subjectMap)
  	@RdfType(CarmlSubjectMap.class)
  	@Override
  	public SubjectMap getSubjectMap() {
  		return subjectMap;
  	}
  
  	@RdfProperty(Rr.predicateObjectMap)
  	@RdfType(CarmlPredicateObjectMap.class)
  	@Override
  	public Set<PredicateObjectMap> getPredicateObjectMaps() {
  		return predicateObjectMaps;
  	}
  
  	public void setLogicalSource(LogicalSource logicalSource) {
  		this.logicalSource = logicalSource;
  	}
  
  	public void setSubjectMap(SubjectMap subjectMap) {
  		this.subjectMap = subjectMap;
  	}
  
  	public void setPredicateObjectMaps(Set<PredicateObjectMap> predicateObjectMaps) {
  		this.predicateObjectMaps = predicateObjectMaps;
  	}
  
  	@Override
  	public String toString() {
  		ToStringStyle style = new MultilineRecursiveToStringStyle();
  		StringBuffer buffer = new StringBuffer();
  		buffer.append(String.format("%s %s:%n ", getClass().getSimpleName(), getResourceName()));
  		return new ReflectionToStringBuilder(this, style, buffer).toString();
  	}
  
  	@Override
  	public int hashCode() {
  		return Objects.hash(logicalSource, subjectMap, predicateObjectMaps);
  	}
  
  	@Override
  	public boolean equals(Object obj) {
  		if (this == obj) {
  			return true;
  		}
  		if (obj == null) {
  			return false;
  		}
  		if (getClass() != obj.getClass()) {
  			return false;
  		}
  		CarmlTriplesMap other = (CarmlTriplesMap) obj;
  		return Objects.equals(logicalSource, other.logicalSource) &&
  				Objects.equals(subjectMap, other.subjectMap) &&
  				Objects.equals(predicateObjectMaps, other.predicateObjectMaps);
  	}
  
  	@Override
  	public Set<Resource> getReferencedResources() {
  		ImmutableSet.Builder<Resource> builder = ImmutableSet.<Resource>builder();
  		if (logicalSource != null) {
  			builder.add(logicalSource);
  		}
  		if (subjectMap != null) {
  			builder.add(subjectMap);
  		}
  		return builder.addAll(predicateObjectMaps)
  				.build();
  	}
  
  	@Override
  	public void addTriples(ModelBuilder modelBuilder) {
  		modelBuilder.subject(getAsResource())
  				.add(RDF.TYPE, Rdf.Rr.TriplesMap);
  		if (logicalSource != null) {
  			modelBuilder.add(Rml.logicalSource, logicalSource.getAsResource());
  		}
  		if (subjectMap != null) {
  			modelBuilder.add(Rr.subjectMap, subjectMap.getAsResource());
  		}
  		predicateObjectMaps.forEach(pom -> modelBuilder.add(Rr.predicateObjectMap, pom.getAsResource()));
  	}
  
  	public static Builder newBuilder() {
  		return new Builder();
  	}
  
  	public static class Builder {
  
  		private LogicalSource logicalSource;
  		private SubjectMap subjectMap;
  		private Set<PredicateObjectMap> predicateObjectMaps = new LinkedHashSet<>();
  
  		public Builder logicalSource(LogicalSource logicalSource) {
  			this.logicalSource = logicalSource;
  			return this;
  		}
  
  		public Builder subjectMap(SubjectMap subjectMap) {
  			this.subjectMap = subjectMap;
  			return this;
  		}
  
  		public Builder predicateObjectMap(PredicateObjectMap predicateObjectMap) {
  			predicateObjectMaps.add(predicateObjectMap);
  			return this;
  		}
  
  		public CarmlTriplesMap build() {
  			return new CarmlTriplesMap(
  				logicalSource,
  				subjectMap,
  				predicateObjectMaps
  			);
  		}
  	}
  
  }
  