package org.osbp.mysmartshop.dtos;

import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import org.eclipse.osbp.dsl.common.datatypes.IDto;
import org.eclipse.osbp.runtime.common.annotations.Dispose;
import org.eclipse.osbp.runtime.common.annotations.DomainKey;
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.CompanyDto;

@SuppressWarnings("all")
public class CompanyGroupDto extends BaseUUIDDto implements IDto, Serializable, PropertyChangeListener {
  @DomainKey
  private String name;
  
  private String description;
  
  @DomainReference
  @FilterDepth(depth = 0)
  private CompanyDto main_company;
  
  @DomainReference
  @FilterDepth(depth = 0)
  private List<CompanyDto> companies;
  
  public CompanyGroupDto() {
    installLazyCollections();
  }
  
  /**
   * Installs lazy collection resolving for entity {@link CompanyGroup} to the dto {@link CompanyGroupDto}.
   * 
   */
  protected void installLazyCollections() {
    super.installLazyCollections();
    companies = new org.eclipse.osbp.dsl.dto.lib.OppositeDtoList<>(
    				org.eclipse.osbp.dsl.dto.lib.MappingContext.getCurrent(),
    				CompanyDto.class, "company_group.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;
    }
    super.dispose();
  }
  
  /**
   * Returns the name property or <code>null</code> if not present.
   */
  public String getName() {
    return this.name;
  }
  
  /**
   * Sets the <code>name</code> property to this instance.
   * 
   * @param name - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setName(final String name) {
    firePropertyChange("name", this.name, this.name = name );
  }
  
  /**
   * Returns the description property or <code>null</code> if not present.
   */
  public String getDescription() {
    return this.description;
  }
  
  /**
   * Sets the <code>description</code> property to this instance.
   * 
   * @param description - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setDescription(final String description) {
    firePropertyChange("description", this.description, this.description = description );
  }
  
  /**
   * Returns the main_company property or <code>null</code> if not present.
   */
  public CompanyDto getMain_company() {
    return this.main_company;
  }
  
  /**
   * Sets the <code>main_company</code> property to this instance.
   * 
   * @param main_company - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setMain_company(final CompanyDto main_company) {
    checkDisposed();
    firePropertyChange("main_company", this.main_company, this.main_company = main_company);
  }
  
  /**
   * Returns an unmodifiable list of companies.
   */
  public List<CompanyDto> getCompanies() {
    return Collections.unmodifiableList(internalGetCompanies());
  }
  
  /**
   * Returns the list of <code>CompanyDto</code>s thereby lazy initializing it. For internal use only!
   * 
   * @return list - the resulting list
   * 
   */
  public List<CompanyDto> internalGetCompanies() {
    if (this.companies == null) {
      this.companies = new java.util.ArrayList<CompanyDto>();
    }
    return this.companies;
  }
  
  /**
   * Adds the given companyDto to this object. <p>
   * Since the reference is a composition reference, the opposite reference <code>CompanyDto#company_group</code> of the <code>companyDto</code> will be handled automatically and no further coding is required to keep them in sync.<p>
   * See {@link CompanyDto#setCompany_group(CompanyDto)}.
   * 
   * @param companyDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void addToCompanies(final CompanyDto companyDto) {
    checkDisposed();
    
    companyDto.setCompany_group(this);
  }
  
  /**
   * Removes the given companyDto from this object. <p>
   * 
   * @param companyDto - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void removeFromCompanies(final CompanyDto companyDto) {
    checkDisposed();
    
    companyDto.setCompany_group(null);
  }
  
  /**
   * For internal use only!
   */
  public void internalAddToCompanies(final CompanyDto companyDto) {
    
    if(!internalGetCompanies().contains(companyDto)) {
    	if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    		List<CompanyDto> oldList = null;
    		if(internalGetCompanies() instanceof org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) {
    			oldList = ((org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) internalGetCompanies()).copy();
    		} else {
    			oldList = new java.util.ArrayList<>(internalGetCompanies());
    		}
    		internalGetCompanies().add(companyDto);
    		firePropertyChange("companies", oldList, internalGetCompanies());
    	} else {
    		// in mapping mode, we do NOT resolve any collection
    		internalGetCompanies().add(companyDto);
    	}
    }
  }
  
  /**
   * For internal use only!
   */
  public void internalRemoveFromCompanies(final CompanyDto companyDto) {
    if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) {
    	List<CompanyDto> oldList = null;
    	if(internalGetCompanies() instanceof org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) {
    		oldList = ((org.eclipse.osbp.dsl.dto.lib.AbstractOppositeDtoList) internalGetCompanies()).copy();
    	} else {
    		oldList = new java.util.ArrayList<>(internalGetCompanies());
    	}
    	internalGetCompanies().remove(companyDto);
    	firePropertyChange("companies", oldList, internalGetCompanies());	
    }else{
    	// in mapping mode, we do NOT resolve any collection
    	internalGetCompanies().remove(companyDto);
    }
  }
  
  /**
   * Sets the <code>companies</code> property to this instance.
   * Since the reference has an opposite reference, the opposite <code>CompanyDto#
   * company_group</code> of the <code>companies</code> will be handled automatically and no 
   * further coding is required to keep them in sync.<p>
   * See {@link CompanyDto#setCompany_group(CompanyDto)
   * 
   * @param companies - the property
   * @throws RuntimeException if instance is <code>disposed</code>
   * 
   */
  public void setCompanies(final List<CompanyDto> companies) {
    checkDisposed();
    for (CompanyDto dto : internalGetCompanies().toArray(new CompanyDto[this.companies.size()])) {
    	removeFromCompanies(dto);
    }
    
    if(companies == null) {
    	return;
    }
    
    for (CompanyDto dto : companies) {
    	addToCompanies(dto);
    }
  }
  
  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
    { 
    	super.propertyChange(event);
    }
  }
}
