<commit_before>package name.abuchen.portfolio.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import name.abuchen.portfolio.Messages;

public class Client
{
    /* package */static final int CURRENT_VERSION = 13;

    private transient PropertyChangeSupport propertyChangeSupport;

    private int version = CURRENT_VERSION;

    private List<Security> securities = new ArrayList<Security>();
    private List<Watchlist> watchlists;
    private List<ConsumerPriceIndex> consumerPriceIndeces;

    private List<Account> accounts = new ArrayList<Account>();
    private List<Portfolio> portfolios = new ArrayList<Portfolio>();
    private List<InvestmentPlan> plans;
    private Category rootCategory = new Category(Messages.LabelPortfolio, 100);

    private Map<String, String> properties; // old versions!

    private String industryTaxonomyId;

    public Client()
    {
        doPostLoadInitialization();
    }

    /* package */final void doPostLoadInitialization()
    {
        // when loading the Client from XML, attributes that are not (yet)
        // persisted in that version are not initialized

        if (watchlists == null)
            watchlists = new ArrayList<Watchlist>();

        if (consumerPriceIndeces == null)
            consumerPriceIndeces = new ArrayList<ConsumerPriceIndex>();

        if (properties == null)
            properties = new HashMap<String, String>();

        if (propertyChangeSupport == null)
            propertyChangeSupport = new PropertyChangeSupport(this);

        if (plans == null)
            plans = new ArrayList<InvestmentPlan>();
    }

    public int getVersion()
    {
        return version;
    }

    public void setVersion(int version)
    {
        this.version = version;
    }

    public List<InvestmentPlan> getPlans()
    {
        return plans;
    }

    public void addPlan(InvestmentPlan plan)
    {
        plans.add(plan);
    }

    public void removePlan(InvestmentPlan plan)
    {
        plans.remove(plan);
    }

    public List<Security> getSecurities()
    {
        return securities;
    }

    public void addSecurity(Security security)
    {
        securities.add(security);
    }

    public void addSecurities(Collection<Security> sec)
    {
        securities.addAll(sec);
    }

    public void removeSecurity(Security security)
    {
        securities.remove(security);
        for (Watchlist w : watchlists)
            w.getSecurities().remove(security);
        // FIXME possibly remove transactions and category assignments as well
    }

    public List<Watchlist> getWatchlists()
    {
        return watchlists;
    }

    public List<ConsumerPriceIndex> getConsumerPriceIndeces()
    {
        return consumerPriceIndeces;
    }

    public void setConsumerPriceIndeces(List<ConsumerPriceIndex> prices)
    {
        this.consumerPriceIndeces = prices;
        Collections.sort(this.consumerPriceIndeces);
    }

    public void addConsumerPriceIndex(ConsumerPriceIndex record)
    {
        consumerPriceIndeces.add(record);
    }

    public void addAccount(Account account)
    {
        accounts.add(account);
    }

    public void removeAccount(Account account)
    {
        deleteCrossEntries(account.getTransactions());
        accounts.remove(account);
    }

    public List<Account> getAccounts()
    {
        return accounts;
    }

    public void addPortfolio(Portfolio portfolio)
    {
        portfolios.add(portfolio);
    }

    public void removePortfolio(Portfolio portfolio)
    {
        deleteCrossEntries(portfolio.getTransactions());
        portfolios.remove(portfolio);
    }

    public List<Portfolio> getPortfolios()
    {
        return portfolios;
    }

    public void setRootCategory(Category root)
    {
        this.rootCategory = root;
    }

    public Category getRootCategory()
    {
        return this.rootCategory;
    }

    public void setIndustryTaxonomy(IndustryClassification taxonomy)
    {
        this.industryTaxonomyId = taxonomy != null ? taxonomy.getIdentifier() : null;
    }

    public IndustryClassification getIndustryTaxonomy()
    {
        return IndustryClassification.lookup(industryTaxonomyId);
    }

    public void setProperty(String key, String value)
    {
        String oldValue = properties.put(key, value);
        propertyChangeSupport.firePropertyChange("properties", oldValue, value); //$NON-NLS-1$
    }

    public void removeProperity(String key)
    {
        String oldValue = properties.remove(key);
        propertyChangeSupport.firePropertyChange("properties", oldValue, null); //$NON-NLS-1$
    }

    public String getProperty(String key)
    {
        return properties.get(key);
    }

    private void deleteCrossEntries(List<? extends Transaction> transactions)
    {
        // crossEntry.delete modifies list
        for (Transaction t : new ArrayList<Transaction>(transactions))
        {
            if (t.getCrossEntry() != null)
                t.getCrossEntry().delete();
        }
    }

    public void addPropertyChangeListener(PropertyChangeListener listener)
    {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
    {
        propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener)
    {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }<commit_msg>Delete investment plan when deleting associated portfolio and account<commit_after>package name.abuchen.portfolio.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import name.abuchen.portfolio.Messages;

public class Client
{
    /* package */static final int CURRENT_VERSION = 13;

    private transient PropertyChangeSupport propertyChangeSupport;

    private int version = CURRENT_VERSION;

    private List<Security> securities = new ArrayList<Security>();
    private List<Watchlist> watchlists;
    private List<ConsumerPriceIndex> consumerPriceIndeces;

    private List<Account> accounts = new ArrayList<Account>();
    private List<Portfolio> portfolios = new ArrayList<Portfolio>();
    private List<InvestmentPlan> plans;
    private Category rootCategory = new Category(Messages.LabelPortfolio, 100);

    private Map<String, String> properties; // old versions!

    private String industryTaxonomyId;

    public Client()
    {
        doPostLoadInitialization();
    }

    /* package */final void doPostLoadInitialization()
    {
        // when loading the Client from XML, attributes that are not (yet)
        // persisted in that version are not initialized

        if (watchlists == null)
            watchlists = new ArrayList<Watchlist>();

        if (consumerPriceIndeces == null)
            consumerPriceIndeces = new ArrayList<ConsumerPriceIndex>();

        if (properties == null)
            properties = new HashMap<String, String>();

        if (propertyChangeSupport == null)
            propertyChangeSupport = new PropertyChangeSupport(this);

        if (plans == null)
            plans = new ArrayList<InvestmentPlan>();
    }

    public int getVersion()
    {
        return version;
    }

    public void setVersion(int version)
    {
        this.version = version;
    }

    public List<InvestmentPlan> getPlans()
    {
        return plans;
    }

    public void addPlan(InvestmentPlan plan)
    {
        plans.add(plan);
    }

    public void removePlan(InvestmentPlan plan)
    {
        plans.remove(plan);
    }

    public List<Security> getSecurities()
    {
        return securities;
    }

    public void addSecurity(Security security)
    {
        securities.add(security);
    }

    public void addSecurities(Collection<Security> sec)
    {
        securities.addAll(sec);
    }

    public void removeSecurity(Security security)
    {
        securities.remove(security);
        for (Watchlist w : watchlists)
            w.getSecurities().remove(security);
        deleteInvestmentPlans(security);
        // FIXME possibly remove transactions and category assignments as well
    }

    public List<Watchlist> getWatchlists()
    {
        return watchlists;
    }

    public List<ConsumerPriceIndex> getConsumerPriceIndeces()
    {
        return consumerPriceIndeces;
    }

    public void setConsumerPriceIndeces(List<ConsumerPriceIndex> prices)
    {
        this.consumerPriceIndeces = prices;
        Collections.sort(this.consumerPriceIndeces);
    }

    public void addConsumerPriceIndex(ConsumerPriceIndex record)
    {
        consumerPriceIndeces.add(record);
    }

    public void addAccount(Account account)
    {
        accounts.add(account);
    }

    public void removeAccount(Account account)
    {
        deleteCrossEntries(account.getTransactions());
        deleteInvestmentPlans(account);
        accounts.remove(account);
    }

    public List<Account> getAccounts()
    {
        return accounts;
    }

    public void addPortfolio(Portfolio portfolio)
    {
        portfolios.add(portfolio);
    }

    public void removePortfolio(Portfolio portfolio)
    {
        deleteCrossEntries(portfolio.getTransactions());
        deleteInvestmentPlans(portfolio);
        portfolios.remove(portfolio);
    }

    public List<Portfolio> getPortfolios()
    {
        return portfolios;
    }

    public void setRootCategory(Category root)
    {
        this.rootCategory = root;
    }

    public Category getRootCategory()
    {
        return this.rootCategory;
    }

    public void setIndustryTaxonomy(IndustryClassification taxonomy)
    {
        this.industryTaxonomyId = taxonomy != null ? taxonomy.getIdentifier() : null;
    }

    public IndustryClassification getIndustryTaxonomy()
    {
        return IndustryClassification.lookup(industryTaxonomyId);
    }

    public void setProperty(String key, String value)
    {
        String oldValue = properties.put(key, value);
        propertyChangeSupport.firePropertyChange("properties", oldValue, value); //$NON-NLS-1$
    }

    public void removeProperity(String key)
    {
        String oldValue = properties.remove(key);
        propertyChangeSupport.firePropertyChange("properties", oldValue, null); //$NON-NLS-1$
    }

    public String getProperty(String key)
    {
        return properties.get(key);
    }

    private void deleteCrossEntries(List<? extends Transaction> transactions)
    {
        // crossEntry.delete modifies list
        for (Transaction t : new ArrayList<Transaction>(transactions))
        {
            if (t.getCrossEntry() != null)
                t.getCrossEntry().delete();
        }
    }

    private void deleteInvestmentPlans(Portfolio portfolio)
    {
        for (InvestmentPlan plan : plans)
        {
            if (plan.getPortfolio().equals(portfolio))
                removePlan(plan);
        }
    }

    private void deleteInvestmentPlans(Account account)
    {
        for (InvestmentPlan plan : plans)
        {
            if (plan.getAccount().equals(account))
                removePlan(plan);
        }
    }

    private void deleteInvestmentPlans(Security security)
    {
        for (InvestmentPlan plan : plans)
        {
            if (plan.getSecurity().equals(security))
                removePlan(plan);
        }
    }

    public void addPropertyChangeListener(PropertyChangeListener listener)
    {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
    {
        propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener)
    {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }
{'fraction_non_alphanumeric': 0.08496945010183299, 'fraction_numerical': 0.0011405295315682282, 'mean_word_length': 2.7807206652294427, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3956749', 'n_tokens_mistral': 3301, 'n_tokens_neox': 3157, 'n_words': 720}