// Path: src/main/java/com/rolfje/anonimatron/synonyms/NumberSynonym.java
// public class NumberSynonym implements Synonym {
// 	private String type;
// 	private Number from;
// 	private Number to;
// 	private boolean shortLived = false;
// 
// 	public NumberSynonym() {
// 	}
// 
// 	public NumberSynonym(String type, Number from, Number to, boolean shortLived) {
// 		this.type = type;
// 		this.from = from;
// 		this.to = to;
// 		this.shortLived = shortLived;
// 	}
// 
// 	@Override
// 	public boolean isShortLived() {
// 		return shortLived;
// 	}
// 
// 	@Override
// 	public String getType() {
// 		return type;
// 	}
// 
// 	@Override
// 	public Number getFrom() {
// 		return from;
// 	}
// 
// 	@Override
// 	public Number getTo() {
// 		return to;
// 	}
// 
// 
// 	public void setType(String type) {
// 		this.type = type;
// 	}
// 
// 	public void setTo(Number to) {
// 		this.to = to;
// 	}
// 
// 	public void setFrom(Number from) {
// 		this.from = from;
// 	}
// 
// 	public void setShortLived(boolean shortLived) {
// 		this.shortLived = shortLived;
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (obj == null || getClass() != obj.getClass())
// 			return false;
// 		return this.hashCode() == obj.hashCode();
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return from.hashCode() + to.hashCode() + type.hashCode();
// 	}
// }
// 
// Path: src/main/java/com/rolfje/anonimatron/synonyms/StringSynonym.java
// public class StringSynonym implements Synonym {
//     private String type;
//     private String from;
//     private String to;
//     private boolean shortlived = false;
// 
//     public StringSynonym() {
//     }
// 
//     public StringSynonym(String type, String from, String to, boolean shortlived) {
//         this.type = type;
//         this.from = from;
//         this.to = to;
//         this.shortlived = shortlived;
//     }
// 
//     @Override
//     public String getType() {
//         return type;
//     }
// 
//     @Override
//     public Object getFrom() {
//         return from;
//     }
// 
//     @Override
//     public Object getTo() {
//         return to;
//     }
// 
//     public void setType(String type) {
//         this.type = type;
//     }
// 
//     public void setFrom(String from) {
//         this.from = from;
//     }
// 
//     public void setTo(String to) {
//         this.to = to;
//     }
// 
//     public void setShortlived(boolean shortlived) {
//         this.shortlived = shortlived;
//     }
// 
//     @Override
//     public boolean isShortLived() {
//         return shortlived;
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         return (obj != null) && (this.getClass() == obj.getClass()) && (this.hashCode() == obj.hashCode());
//     }
// 
//     @Override
//     public int hashCode() {
//         return from.hashCode() + to.hashCode() + type.hashCode();
//     }
// }
// 
// Path: src/main/java/com/rolfje/anonimatron/synonyms/Synonym.java
// public interface Synonym {
// 
// 	/**
// 	 * Indicates if this Synonym is short-lived or transient, meaning that
//      * it should not be stored in the synonyms file. Transient Synonyms
//      * are not stored, need to be calculated each run time.
// 	 *
// 	 * Transient synonyms are:
// 	 *
// 	 * <ol>
// 	 *     <li>Not stored in memory.</li>
// 	 *     <li>Not stored in the synonym file.</li>
// 	 * </ol>
// 	 *
// 	 * @return <code>true</code> if the synonym should be thrown away
// 	 * after use (not stored in the synonym file).
// 	 */
// 	boolean isShortLived();
// 
// 	/**
// 	 * @return The semantic data type of this Synonym, usually something
// 	 *         descriptive as "NAME" or "STREET".
// 	 */
// 	String getType();
// 
// 	/**
// 	 * @return The data which was in the original database for this Synonym
// 	 */
// 	Object getFrom();
// 
// 	/**
// 	 * 
// 	 * @return The data with which the original data in the database will be or
// 	 *         is replaced when the Anonymizer runs.
// 	 */
// 	Object getTo();
// }


import com.rolfje.anonimatron.synonyms.NumberSynonym;
import com.rolfje.anonimatron.synonyms.StringSynonym;
import com.rolfje.anonimatron.synonyms.Synonym;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
package com.rolfje.anonimatron.anonymizer;



/**
 * Generates valid Dutch "Burger Service Nummer" or "SOFI Nummer", a social
 * security number uniquely identifying civilians to the governement.
 * <p>
 * A BSN Number is 9 digits long, can not start with 3 zeroes, the first digit
 * must be less than 4, and the whole number passes the "11 proof"
 * <p>
 * See https://nl.wikipedia.org/wiki/Burgerservicenummer
 */
public class DutchBSNAnononymizer extends AbstractElevenProofAnonymizer {
    private static final int LENGTH = 9;

    @Override
    public String getType() {
        return "BURGERSERVICENUMMER";
    }

    @Override
    public Synonym anonymize(Object from, int size, boolean isShortLived) {
        if (size < LENGTH) {
            throw new UnsupportedOperationException(
                    "Cannot generate a BSN that fits in a " + size + " character string. Must be " + LENGTH
                            + " characters or more.");
        }

        String newBSN = generateNonIdenticalBSN(from);

        if (from instanceof Number) {
// Path: src/main/java/com/rolfje/anonimatron/synonyms/NumberSynonym.java
// public class NumberSynonym implements Synonym {
// 	private String type;
// 	private Number from;
// 	private Number to;
// 	private boolean shortLived = false;
// 
// 	public NumberSynonym() {
// 	}
// 
// 	public NumberSynonym(String type, Number from, Number to, boolean shortLived) {
// 		this.type = type;
// 		this.from = from;
// 		this.to = to;
// 		this.shortLived = shortLived;
// 	}
// 
// 	@Override
// 	public boolean isShortLived() {
// 		return shortLived;
// 	}
// 
// 	@Override
// 	public String getType() {
// 		return type;
// 	}
// 
// 	@Override
// 	public Number getFrom() {
// 		return from;
// 	}
// 
// 	@Override
// 	public Number getTo() {
// 		return to;
// 	}
// 
// 
// 	public void setType(String type) {
// 		this.type = type;
// 	}
// 
// 	public void setTo(Number to) {
// 		this.to = to;
// 	}
// 
// 	public void setFrom(Number from) {
// 		this.from = from;
// 	}
// 
// 	public void setShortLived(boolean shortLived) {
// 		this.shortLived = shortLived;
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (obj == null || getClass() != obj.getClass())
// 			return false;
// 		return this.hashCode() == obj.hashCode();
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		return from.hashCode() + to.hashCode() + type.hashCode();
// 	}
// }
// 
// Path: src/main/java/com/rolfje/anonimatron/synonyms/StringSynonym.java
// public class StringSynonym implements Synonym {
//     private String type;
//     private String from;
//     private String to;
//     private boolean shortlived = false;
// 
//     public StringSynonym() {
//     }
// 
//     public StringSynonym(String type, String from, String to, boolean shortlived) {
//         this.type = type;
//         this.from = from;
//         this.to = to;
//         this.shortlived = shortlived;
//     }
// 
//     @Override
//     public String getType() {
//         return type;
//     }
// 
//     @Override
//     public Object getFrom() {
//         return from;
//     }
// 
//     @Override
//     public Object getTo() {
//         return to;
//     }
// 
//     public void setType(String type) {
//         this.type = type;
//     }
// 
//     public void setFrom(String from) {
//         this.from = from;
//     }
// 
//     public void setTo(String to) {
//         this.to = to;
//     }
// 
//     public void setShortlived(boolean shortlived) {
//         this.shortlived = shortlived;
//     }
// 
//     @Override
//     public boolean isShortLived() {
//         return shortlived;
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         return (obj != null) && (this.getClass() == obj.getClass()) && (this.hashCode() == obj.hashCode());
//     }
// 
//     @Override
//     public int hashCode() {
//         return from.hashCode() + to.hashCode() + type.hashCode();
//     }
// }
// 
// Path: src/main/java/com/rolfje/anonimatron/synonyms/Synonym.java
// public interface Synonym {
// 
// 	/**
// 	 * Indicates if this Synonym is short-lived or transient, meaning that
//      * it should not be stored in the synonyms file. Transient Synonyms
//      * are not stored, need to be calculated each run time.
// 	 *
// 	 * Transient synonyms are:
// 	 *
// 	 * <ol>
// 	 *     <li>Not stored in memory.</li>
// 	 *     <li>Not stored in the synonym file.</li>
// 	 * </ol>
// 	 *
// 	 * @return <code>true</code> if the synonym should be thrown away
// 	 * after use (not stored in the synonym file).
// 	 */
// 	boolean isShortLived();
// 
// 	/**
// 	 * @return The semantic data type of this Synonym, usually something
// 	 *         descriptive as "NAME" or "STREET".
// 	 */
// 	String getType();
// 
// 	/**
// 	 * @return The data which was in the original database for this Synonym
// 	 */
// 	Object getFrom();
// 
// 	/**
// 	 * 
// 	 * @return The data with which the original data in the database will be or
// 	 *         is replaced when the Anonymizer runs.
// 	 */
// 	Object getTo();
// }


// Path: src/main/java/com/rolfje/anonimatron/anonymizer/DutchBSNAnononymizer.java
import com.rolfje.anonimatron.synonyms.NumberSynonym;
import com.rolfje.anonimatron.synonyms.StringSynonym;
import com.rolfje.anonimatron.synonyms.Synonym;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.math.BigInteger;

package com.rolfje.anonimatron.anonymizer;



/**
 * Generates valid Dutch "Burger Service Nummer" or "SOFI Nummer", a social
 * security number uniquely identifying civilians to the governement.
 * <p>
 * A BSN Number is 9 digits long, can not start with 3 zeroes, the first digit
 * must be less than 4, and the whole number passes the "11 proof"
 * <p>
 * See https://nl.wikipedia.org/wiki/Burgerservicenummer
 */
public class DutchBSNAnononymizer extends AbstractElevenProofAnonymizer {
    private static final int LENGTH = 9;

    @Override
    public String getType() {
        return "BURGERSERVICENUMMER";
    }

    @Override
    public Synonym anonymize(Object from, int size, boolean isShortLived) {
        if (size < LENGTH) {
            throw new UnsupportedOperationException(
                    "Cannot generate a BSN that fits in a " + size + " character string. Must be " + LENGTH
                            + " characters or more.");
        }

        String newBSN = generateNonIdenticalBSN(from);

        if (from instanceof Number) {
            return new NumberSynonym(