package com.microsoft.bingads.v10.bulk.entities; import com.microsoft.bingads.v10.bulk.entities.BulkTargetIdentifier; import com.microsoft.bingads.InternalException; import com.microsoft.bingads.v10.internal.bulk.BulkObjectWriter; import com.microsoft.bingads.v10.internal.bulk.entities.MultiRecordBulkEntity; import com.microsoft.bingads.internal.functionalinterfaces.Consumer; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * This abstract base class provides properties that are shared by all bulk sub target classes. * * @param <TBid> see {@link BulkTargetBid} */ abstract class BulkSubTarget<TBid extends BulkTargetBid> extends MultiRecordBulkEntity { private Status status; private Long targetId; private Long entityId; private String entityName; private String parentEntityName; private boolean hasDeleteAllRow; private final List<TBid> bids = new ArrayList<TBid>(); private final Class<TBid> classOfTBid; boolean isBeingWrittenAsPartOfParentTarget; public BulkSubTarget(Class<TBid> classOfTBid) { this.classOfTBid = classOfTBid; } /** * Gets the list of target bids corresponding the this sub target type. */ public List<TBid> getBids() { return Collections.unmodifiableList(bids); } /** * Sets the list of target bids corresponding the this sub target type. */ void setBids(List<TBid> bids) { for (TBid bid : bids) { this.bids.add(bid); } reconstructSubTargets(); setStatus(bids.size() > 0 ? Status.ACTIVE : Status.DELETED); } void setIdentifier(BulkTargetIdentifier identifier) { if (identifier.getTargetBidType() != classOfTBid) { throw new InternalException(new IllegalArgumentException("Invalid identifier type")); } hasDeleteAllRow = identifier.isDeleteRow(); setEntityId(identifier.getEntityId()); setTargetId(identifier.getTargetId()); setEntityName(identifier.getEntityName()); setParentEntityName(identifier.getParentEntityName()); } @Override public void writeToStream(BulkObjectWriter rowWriter, boolean excludeReadonlyData) throws IOException { // If the sub-target (for example BulkAgeTarget) is being written as part of BulkTarget, // AgeTarget may be null, which means no Age bids should be written. // Otherwise, if BulkAgeTarget is written individually, AgeTarget must be set. // Also, if target is being deleted, don't require SubTarget API properties to be set if (!isBeingWrittenAsPartOfParentTarget && getStatus() != Status.DELETED) { validatePropertiesNotNull(); } // In any case, for non-empty targets Bids list need to be validated. API doesn't allow passing null or empty list of bids, so shouldn't SDK validateBidsNotNullOrEmpty(); BulkTargetIdentifier identifier = createBid().getIdentifier(); identifier.setStatus(Status.DELETED); identifier.setTargetId(getTargetId()); identifier.setEntityId(getEntityId()); identifier.setEntityName(getEntityName()); identifier.setParentEntityName(getParentEntityName()); identifier.writeToStream(rowWriter, excludeReadonlyData); if (getStatus() == Status.DELETED) { return; } for (TBid bid : convertApiToBulkBids()) { bid.writeToStream(rowWriter, excludeReadonlyData); } } abstract void reconstructSubTargets(); void validatePropertiesNotNull() { // To be implemented by specific target types } void validateBidsNotNullOrEmpty() { // To be implemented by specific target types } abstract TBid createBid(); abstract List<TBid> convertApiToBulkBids(); TBid createAndPopulateBid(Consumer<TBid> setAdditionalProperties) { TBid bid = createBid(); bid.setStatus(getStatus()); bid.setTargetId(getTargetId()); bid.setEntityId(getEntityId()); bid.setEntityName(getEntityName()); bid.setParentEntityName(getParentEntityName()); setAdditionalProperties.accept(bid); return bid; } @Override public List<? extends BulkEntity> getChildEntities() { return getBids(); } @Override public boolean allChildrenPresent() { return hasDeleteAllRow; } /** * Gets the status of the target. * * <p> * The value is Active if the target is available in the customer's shared library. * The value is Deleted if the target is deleted from the customer's shared library, * or should be deleted in a subsequent upload operation. * Corresponds to the 'Status' field in the bulk file. * </p> */ public Status getStatus() { return status; } /** * Sets the status of the target. * * <p> * The value is Active if the target is available in the customer's shared library. * The value is Deleted if the target is deleted from the customer's shared library, * or should be deleted in a subsequent upload operation. * Corresponds to the 'Status' field in the bulk file. * </p> */ public void setStatus(Status status) { this.status = status; } /** * Gets the identifier of the target. */ public Long getTargetId() { return targetId; } /** * Sets the identifier of the target. */ public void setTargetId(Long targetId) { this.targetId = targetId; } /** * Reserved for internal use. */ Long getEntityId() { return entityId; } /** * Reserved for internal use. */ void setEntityId(Long entityId) { this.entityId = entityId; } /** * Reserved for internal use. */ String getEntityName() { return entityName; } /** * Reserved for internal use. */ void setEntityName(String entityName) { this.entityName = entityName; } /** * Reserved for internal use. */ String getParentEntityName() { return parentEntityName; } /** * Reserved for internal use. */ void setParentEntityName(String parentEntityName) { this.parentEntityName = parentEntityName; } }