code: package com.taxonic.carml.model.impl;
  
  import com.taxonic.carml.model.Resource;
  import com.taxonic.carml.rdf_mapper.annotations.RdfProperty;
  import com.taxonic.carml.rdf_mapper.annotations.RdfResourceName;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.stream.Collectors;
  
  import com.taxonic.carml.util.RdfUtil;
  import org.eclipse.rdf4j.model.Model;
  import org.eclipse.rdf4j.model.ValueFactory;
  import org.eclipse.rdf4j.model.impl.LinkedHashModel;
  import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
  import org.eclipse.rdf4j.model.util.ModelBuilder;
  import org.eclipse.rdf4j.model.vocabulary.RDFS;
  
  public abstract class CarmlResource implements Resource {
  
  	private static final ValueFactory VF = SimpleValueFactory.getInstance();
  
  	String id;
  	String label;
  	private Map<Resource, Model> modelCache = new HashMap<>();
  
  	@Override
  	@RdfResourceName
  	public String getId() {
  		return id;
  	}
  
  	public void setId(String id) {
  		this.id = id;
  	}
  
  	@Override
  	@RdfProperty("http://www.w3.org/2000/01/rdf-schema#label")
  	public String getLabel() {
  		return label;
  	}
  
  	public void setLabel(String label) {
  		this.label = label;
  	}
  
  	public org.eclipse.rdf4j.model.Resource getAsResource() {
  
  		if (id == null) {
  			return VF.createBNode();
  		}
  
  		if (RdfUtil.isValidIri(id)) {
  			return VF.createIRI(id);
  		}
  
  		return VF.createBNode(id);
  	}
  
  	private void cacheModel(Model model) {
  		modelCache = new HashMap<>();
  		modelCache.put(this, model);
  	}
  
  	public Model asRdf() {
  
  		if (modelCache.containsKey(this)) {
  			Model cachedModel = modelCache.get(this);
  			if (!cachedModel.isEmpty()) {
  				return cachedModel;
  			}
  		}
  
  		ModelBuilder builder = new ModelBuilder();
  		addTriples(builder);
  		if (label != null) {
  			builder.add(RDFS.LABEL, label);
  		}
  		Model model = builder.build();
  
  		Model nestedModel = getReferencedResources().stream()
  				.flatMap(resource -> resource.asRdf().stream())
  				.collect(Collectors.toCollection(LinkedHashModel::new));
  
  		model.addAll(nestedModel);
  
  		cacheModel(model);
  
  		return model;
  	}
  
  }
  