code: package com.taxonic.carml.model.impl;
  
  import com.google.common.collect.ImmutableSet;
  import com.taxonic.carml.model.BaseObjectMap;
  import com.taxonic.carml.model.GraphMap;
  import com.taxonic.carml.model.PredicateMap;
  import com.taxonic.carml.model.PredicateObjectMap;
  import com.taxonic.carml.model.Resource;
  import com.taxonic.carml.rdf_mapper.annotations.RdfProperty;
  import com.taxonic.carml.rdf_mapper.annotations.RdfType;
  import com.taxonic.carml.rdf_mapper.annotations.RdfTypeDecider;
  import com.taxonic.carml.vocab.Rdf;
  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.eclipse.rdf4j.model.util.ModelBuilder;
  import org.eclipse.rdf4j.model.vocabulary.RDF;
  
  public class CarmlPredicateObjectMap extends CarmlResource implements PredicateObjectMap {
  
  	private Set<PredicateMap> predicateMaps;
  	private Set<BaseObjectMap> objectMaps;
  	private Set<GraphMap> graphMaps;
  
  	public CarmlPredicateObjectMap() {
  		// Empty constructor for object mapper
  	}
  
  	public CarmlPredicateObjectMap(
  		Set<PredicateMap> predicateMaps,
  		Set<BaseObjectMap> objectMaps,
  		Set<GraphMap> graphMaps
  	) {
  		this.predicateMaps = predicateMaps;
  		this.objectMaps = objectMaps;
  		this.graphMaps = graphMaps;
  	}
  
  	@RdfProperty(Rr.predicateMap)
  	@RdfType(CarmlPredicateMap.class)
  	@Override
  	public Set<PredicateMap> getPredicateMaps() {
  		return predicateMaps;
  	}
  
  	@RdfProperty(Rr.objectMap)
  	@RdfTypeDecider(ObjectMapTypeDecider.class)
  	@Override
  	public Set<BaseObjectMap> getObjectMaps() {
  		return objectMaps;
  	}
  
  	@RdfProperty(Rr.graphMap)
  	@RdfType(CarmlGraphMap.class)
  	@Override
  	public Set<GraphMap> getGraphMaps() {
  		return graphMaps;
  	}
  
  	public void setPredicateMaps(Set<PredicateMap> predicateMaps) {
  		this.predicateMaps = predicateMaps;
  	}
  
  	public void setObjectMaps(Set<BaseObjectMap> objectMaps) {
  		this.objectMaps = objectMaps;
  	}
  
  	public void setGraphMaps(Set<GraphMap> graphMaps) {
  		this.graphMaps = graphMaps;
  	}
  
  	@Override
  	public String toString() {
  		return new ReflectionToStringBuilder(this, new MultilineRecursiveToStringStyle()).toString();
  	}
  
  	@Override
  	public int hashCode() {
  		return Objects.hash(predicateMaps, objectMaps, graphMaps);
  	}
  
  	@Override
  	public boolean equals(Object obj) {
  		if (this == obj) {
  			return true;
  		}
  		if (obj == null) {
  			return false;
  		}
  		if (getClass() != obj.getClass()) {
  			return false;
  		}
  		CarmlPredicateObjectMap other = (CarmlPredicateObjectMap) obj;
  		return Objects.equals(predicateMaps, other.predicateMaps) &&
  				Objects.equals(objectMaps, other.objectMaps) &&
  				Objects.equals(graphMaps, other.graphMaps);
  	}
  
  	@Override
  	public Set<Resource> getReferencedResources() {
  		return ImmutableSet.<Resource>builder()
  				.addAll(predicateMaps)
  				.addAll(objectMaps)
  				.addAll(graphMaps)
  				.build();
  	}
  
  	@Override
  	public void addTriples(ModelBuilder modelBuilder) {
  		modelBuilder.subject(getAsResource())
  				.add(RDF.TYPE, Rdf.Rr.PredicateObjectMap);
  
  		predicateMaps.forEach(pm -> modelBuilder.add(Rr.predicateMap, pm.getAsResource()));
  		objectMaps.forEach(om -> modelBuilder.add(Rr.objectMap, om.getAsResource()));
  		graphMaps.forEach(gm -> modelBuilder.add(Rr.graphMap, gm.getAsResource()));
  	}
  
  	public static Builder newBuilder() {
  		return new Builder();
  	}
  
  	public static class Builder {
  
  		private Set<PredicateMap> predicateMaps = new LinkedHashSet<>();
  		private Set<BaseObjectMap> objectMaps = new LinkedHashSet<>();
  		private Set<GraphMap> graphMaps = new LinkedHashSet<>();
  
  		public Builder predicateMap(PredicateMap predicateMap) {
  			predicateMaps.add(predicateMap);
  			return this;
  		}
  
  		public Builder objectMap(BaseObjectMap objectMap) {
  			objectMaps.add(objectMap);
  			return this;
  		}
  
  		public Builder graphMap(CarmlGraphMap carmlGraphMap) {
  			graphMaps.add(carmlGraphMap);
  			return this;
  		}
  
  		public Builder graphMaps(Set<GraphMap> graphMaps) {
  			this.graphMaps= graphMaps;
  			return this;
  		}
  
  		public CarmlPredicateObjectMap build() {
  			return new CarmlPredicateObjectMap(
  				predicateMaps,
  				objectMaps,
  				graphMaps
  			);
  		}
  	}
  }
  