package org.osbp.mysmartshop.dtos;

import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import javax.validation.Valid;
import org.eclipse.osbp.dsl.common.datatypes.IDto;
import org.eclipse.osbp.runtime.common.annotations.Dispose;
import org.eclipse.osbp.runtime.common.annotations.DomainReference;
import org.eclipse.osbp.runtime.common.annotations.FilterDepth;
import org.osbp.mysmartshop.dtos.BaseUUIDDto;
import org.osbp.mysmartshop.dtos.DtoTestBeanDto;
import org.osbp.mysmartshop.dtos.DtoTestChildContainmentDto;
import org.osbp.mysmartshop.dtos.DtoTestChildCrossRefDto;

@SuppressWarnings("all")
public class DtoTestParentDto extends BaseUUIDDto implements IDto, Serializable, PropertyChangeListener {
  private String string;
  
  @DomainReference
  @Valid
  @FilterDepth(depth = 0)
  private List<DtoTestChildContainmentDto> containmentChilds;
  
  @DomainReference
  @FilterDepth(depth = 0)
  private List<DtoTestChildCrossRefDto> crossRefChilds;
  
  @DomainReference
  @FilterDepth(depth = 0)
  private DtoTestChildCrossRefDto crossRefChild;
  
  @Valid
  private DtoTestBeanDto beanx;
  
  public DtoTestParentDto() {
    installLazyCollections();
  }
  
  /**
   * Installs lazy collection resolving for entity {@link DtoTestParent} to the dto {@link DtoTestParentDto}.
   * 
   */
  protected void installLazyCollections() {
    super.installLazyCollections();
    containmentChilds = new org.eclipse.osbp.dsl.dto.lib.OppositeContainmentDtoList<>(
    				org.eclipse.osbp.dsl.dto.lib.MappingContext.getCurrent(),
    				DtoTestChildContainmentDto.class, this, "container.id",
    				(java.util.function.Supplier<Object> & Serializable) () -> this.getId(), this);
    crossRefChilds = new org.eclipse.osbp.dsl.dto.lib.OppositeDtoList<>(
    				org.eclipse.osbp.dsl.dto.lib.MappingContext.getCurrent(),
    				DtoTestChildCrossRefDto.class, "container.id",
    				(java.util.function.Supplier<Object> & Serializable) () -> this.getId(), this);
  }
  
  /**
   * Checks whether the object is disposed.
   * @throws RuntimeException if the object is disposed.
   */
  private void checkDisposed() {
    if (isDisposed()) {
      throw new RuntimeException("Object already disposed: " + this);
    }
  }
  
  /**
   * Calling dispose will destroy that instance. The internal state will be 
   * set to 'disposed' and methods of that object must not be used anymore. 
   * Each call will result in runtime exceptions.<br/>
   * If this object keeps composition containments, these will be disposed too. 
   * So the whole composition containment tree will be disposed on calling this method.
   */
  @Dispose
  public void dispose() {
    if (isDisposed()) {
      return;
    }
    try {
      // Dispose all the composition references.
      if (this.containmentChilds != null) {
        for (DtoTestChildContainmentDto dtoTestChildContainmentDto : this.containmentChilds) {
          dtoTestChildContainmentDto.dispose();
        }
        this.containmentChilds = null;
      }
      
    }
    finally {
      super.dispose();
    }
    
  }
  
  /**
   * Returns the string property or <code>null</code> if not present.
   */
  public String getString() {
    return this.string;
  }
  
  /**
   * Sets the <code>string</code> property to this instance.
   * 
   * @param string - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setString(final String string) {
    firePropertyChange("string", this.string, this.string = string );
  }
  
  /**
   * Returns an unmodifiable list of containmentChilds.
   */
  public List<DtoTestChildContainmentDto> getContainmentChilds() {
    return Collections.unmodifiableList(internalGetContainmentChilds());
  }
  
  /**
   * Returns the list of <code>DtoTestChildContainmentDto</code>s thereby lazy initializing it. For internal use only!
   * 
   * @return list - the resulting list
   * 
   */
  public List<DtoTestChildContainmentDto> internalGetContainmentChilds() {
    if (this.containmentChilds == null) {
      this.containmentChilds = new java.util.ArrayList<DtoTestChildContainmentDto>();
    }
    return this.containmentChilds;
  }
  
  /**
   * Adds the given dtoTestChildContainmentDto to this object. <p>
   * Since the reference is a composition reference, the opposite reference <code>DtoTestChildContainmentDto#container</code> of the <code>dtoTestChildContainmentDto</code> will be handled automatically and no further coding is required to keep them in sync.<p>
   * See {@link DtoTestChildContainmentDto#setContainer(DtoTestChildContainmentDto)}.
   * 
   * @param dtoTestChildContainmentDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void addToContainmentChilds(final DtoTestChildContainmentDto dtoTestChildContainmentDto) {
    checkDisposed();
    
    dtoTestChildContainmentDto.setContainer(this);
  }
  
  /**
   * Removes the given dtoTestChildContainmentDto from this object. <p>
   * 
   * @param dtoTestChildContainmentDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void removeFromContainmentChilds(final DtoTestChildContainmentDto dtoTestChildContainmentDto) {
    checkDisposed();
    
    dtoTestChildContainmentDto.setContainer(null);
  }
  
  /**
   * For internal use only!
   */
  public void internalAddToContainmentChilds(final DtoTestChildContainmentDto dtoTestChildContainmentDto) {
    
    if(!internalGetContainmentChilds().contains(dtoTestChildContainmentDto)) {
    	if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    		// collections will become resolved! We need to send a delta notification.
    		List<DtoTestChildContainmentDto> oldList = new java.util.ArrayList<>(internalGetContainmentChilds());
    		internalGetContainmentChilds().add(dtoTestChildContainmentDto);
    		firePropertyChange("containmentChilds", oldList, internalGetContainmentChilds());
    	} else {
    		// in mapping mode, we do NOT resolve any collection
    		internalGetContainmentChilds().add(dtoTestChildContainmentDto);
    	}
    }
  }
  
  /**
   * For internal use only!
   */
  public void internalRemoveFromContainmentChilds(final DtoTestChildContainmentDto dtoTestChildContainmentDto) {
    if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    	// collections will become resolved! We need to send a delta notification.
    	List<DtoTestChildContainmentDto> oldList = new java.util.ArrayList<>(internalGetContainmentChilds());
    	internalGetContainmentChilds().remove(dtoTestChildContainmentDto);
    	firePropertyChange("containmentChilds", oldList, internalGetContainmentChilds());	
    }else{
    	// in mapping mode, we do NOT resolve any collection
    	internalGetContainmentChilds().remove(dtoTestChildContainmentDto);
    }
  }
  
  /**
   * Sets the <code>containmentChilds</code> property to this instance.
   * Since the reference has an opposite reference, the opposite <code>DtoTestChildContainmentDto#
   * container</code> of the <code>containmentChilds</code> will be handled automatically and no 
   * further coding is required to keep them in sync.<p>
   * See {@link DtoTestChildContainmentDto#setContainer(DtoTestChildContainmentDto)
   * 
   * @param containmentChilds - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setContainmentChilds(final List<DtoTestChildContainmentDto> containmentChilds) {
    checkDisposed();
    for (DtoTestChildContainmentDto dto : internalGetContainmentChilds().toArray(new DtoTestChildContainmentDto[this.containmentChilds.size()])) {
    	removeFromContainmentChilds(dto);
    }
    
    if(containmentChilds == null) {
    	return;
    }
    
    for (DtoTestChildContainmentDto dto : containmentChilds) {
    	addToContainmentChilds(dto);
    }
  }
  
  /**
   * Returns an unmodifiable list of crossRefChilds.
   */
  public List<DtoTestChildCrossRefDto> getCrossRefChilds() {
    return Collections.unmodifiableList(internalGetCrossRefChilds());
  }
  
  /**
   * Returns the list of <code>DtoTestChildCrossRefDto</code>s thereby lazy initializing it. For internal use only!
   * 
   * @return list - the resulting list
   * 
   */
  public List<DtoTestChildCrossRefDto> internalGetCrossRefChilds() {
    if (this.crossRefChilds == null) {
      this.crossRefChilds = new java.util.ArrayList<DtoTestChildCrossRefDto>();
    }
    return this.crossRefChilds;
  }
  
  /**
   * Adds the given dtoTestChildCrossRefDto to this object. <p>
   * Since the reference is a composition reference, the opposite reference <code>DtoTestChildCrossRefDto#container</code> of the <code>dtoTestChildCrossRefDto</code> will be handled automatically and no further coding is required to keep them in sync.<p>
   * See {@link DtoTestChildCrossRefDto#setContainer(DtoTestChildCrossRefDto)}.
   * 
   * @param dtoTestChildCrossRefDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void addToCrossRefChilds(final DtoTestChildCrossRefDto dtoTestChildCrossRefDto) {
    checkDisposed();
    
    dtoTestChildCrossRefDto.setContainer(this);
  }
  
  /**
   * Removes the given dtoTestChildCrossRefDto from this object. <p>
   * 
   * @param dtoTestChildCrossRefDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void removeFromCrossRefChilds(final DtoTestChildCrossRefDto dtoTestChildCrossRefDto) {
    checkDisposed();
    
    dtoTestChildCrossRefDto.setContainer(null);
  }
  
  /**
   * For internal use only!
   */
  public void internalAddToCrossRefChilds(final DtoTestChildCrossRefDto dtoTestChildCrossRefDto) {
    
    if(!internalGetCrossRefChilds().contains(dtoTestChildCrossRefDto)) {
    	if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    		// collections will become resolved! We need to send a delta notification.
    		List<DtoTestChildCrossRefDto> oldList = new java.util.ArrayList<>(internalGetCrossRefChilds());
    		internalGetCrossRefChilds().add(dtoTestChildCrossRefDto);
    		firePropertyChange("crossRefChilds", oldList, internalGetCrossRefChilds());
    	} else {
    		// in mapping mode, we do NOT resolve any collection
    		internalGetCrossRefChilds().add(dtoTestChildCrossRefDto);
    	}
    }
  }
  
  /**
   * For internal use only!
   */
  public void internalRemoveFromCrossRefChilds(final DtoTestChildCrossRefDto dtoTestChildCrossRefDto) {
    if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    	// collections will become resolved! We need to send a delta notification.
    	List<DtoTestChildCrossRefDto> oldList = new java.util.ArrayList<>(internalGetCrossRefChilds());
    	internalGetCrossRefChilds().remove(dtoTestChildCrossRefDto);
    	firePropertyChange("crossRefChilds", oldList, internalGetCrossRefChilds());	
    }else{
    	// in mapping mode, we do NOT resolve any collection
    	internalGetCrossRefChilds().remove(dtoTestChildCrossRefDto);
    }
  }
  
  /**
   * Sets the <code>crossRefChilds</code> property to this instance.
   * Since the reference has an opposite reference, the opposite <code>DtoTestChildCrossRefDto#
   * container</code> of the <code>crossRefChilds</code> will be handled automatically and no 
   * further coding is required to keep them in sync.<p>
   * See {@link DtoTestChildCrossRefDto#setContainer(DtoTestChildCrossRefDto)
   * 
   * @param crossRefChilds - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setCrossRefChilds(final List<DtoTestChildCrossRefDto> crossRefChilds) {
    checkDisposed();
    for (DtoTestChildCrossRefDto dto : internalGetCrossRefChilds().toArray(new DtoTestChildCrossRefDto[this.crossRefChilds.size()])) {
    	removeFromCrossRefChilds(dto);
    }
    
    if(crossRefChilds == null) {
    	return;
    }
    
    for (DtoTestChildCrossRefDto dto : crossRefChilds) {
    	addToCrossRefChilds(dto);
    }
  }
  
  /**
   * Returns the crossRefChild property or <code>null</code> if not present.
   */
  public DtoTestChildCrossRefDto getCrossRefChild() {
    return this.crossRefChild;
  }
  
  /**
   * Sets the <code>crossRefChild</code> property to this instance.
   * 
   * @param crossRefChild - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setCrossRefChild(final DtoTestChildCrossRefDto crossRefChild) {
    checkDisposed();
    firePropertyChange("crossRefChild", this.crossRefChild, this.crossRefChild = crossRefChild);
  }
  
  /**
   * Returns the beanx property.
   */
  public DtoTestBeanDto getBeanx() {
    if(this.beanx== null){
      this.beanx = new DtoTestBeanDto();
    }
    return this.beanx;
  }
  
  /**
   * Sets the <code>beanx</code> property to this instance.
   * 
   * @param beanx - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setBeanx(final DtoTestBeanDto beanx) {
    // ensure that embedded beans will notify their parent about changes
    // so their dirty state can be handled properly
    if (this.beanx != null) {
    	this.beanx.removePropertyChangeListener(this);
    }
    
    firePropertyChange("beanx", this.beanx, this.beanx = beanx );
    
    if (this.beanx != null) {
    	this.beanx.addPropertyChangeListener(this);
    }
  }
  
  public String foo() {
    String _xifexpression = null;
    if ((this.beanx != null)) {
      _xifexpression = "X";
    } else {
      _xifexpression = "Y";
    }
    return _xifexpression;
  }
  
  public void foo2() {
    this.setString("xxyy");
  }
  
  public void propertyChange(final java.beans.PropertyChangeEvent event) {
    Object source = event.getSource();
    
    // forward the event from embeddable beans to all listeners. So the parent of the embeddable
    // bean will become notified and its dirty state can be handled properly
    
    
    	if(source == beanx){
    		firePropertyChange("beanx" + "_" + event.getPropertyName(), event.getOldValue(), event.getNewValue());
    	} else 
    { 
    	super.propertyChange(event);
    }
  }
}
