Index: /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoCharset.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoCharset.java	(revision 33642)
+++ /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoCharset.java	(revision 33642)
@@ -0,0 +1,42 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fr.cadastre.edigeo;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+
+/**
+ * Partial list of Edigeo charsets according to NF Z 52000 Annex C, table C.1.
+ * ISO 6937 (JEC) is not supported by Java.
+ */
+enum EdigeoCharset {
+    ISO_646_IRV("IRV", StandardCharsets.US_ASCII),
+    ISO_646_FRANCE("646-FRANCE", StandardCharsets.ISO_8859_1),
+    ISO_8859_1("8859-1", StandardCharsets.ISO_8859_1),
+    ISO_8859_2("8859-2", Charset.forName("ISO-8859-2")),
+    ISO_8859_3("8859-3", Charset.forName("ISO-8859-3")),
+    ISO_8859_4("8859-4", Charset.forName("ISO-8859-4")),
+    ISO_8859_5("8859-5", Charset.forName("ISO-8859-5")),
+    ISO_8859_6("8859-6", Charset.forName("ISO-8859-6")),
+    ISO_8859_7("8859-7", Charset.forName("ISO-8859-7")),
+    ISO_8859_8("8859-8", Charset.forName("ISO-8859-8")),
+    ISO_8859_9("8859-9", Charset.forName("ISO-8859-9"));
+    //ISO_6937_JEC("JEC");
+
+    final String zv;
+    final Charset cs;
+
+    EdigeoCharset(String zv, Charset cs) {
+        this.zv = Objects.requireNonNull(zv, "zv");
+        this.cs = Objects.requireNonNull(cs, "cs");
+    }
+
+    static EdigeoCharset of(String zv) {
+        for (EdigeoCharset e : values()) {
+            if (e.zv.equals(zv)) {
+                return e;
+            }
+        }
+        throw new IllegalArgumentException(zv);
+    }
+}
Index: /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoFile.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoFile.java	(revision 33642)
+++ /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoFile.java	(revision 33642)
@@ -0,0 +1,143 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fr.cadastre.edigeo;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.Objects;
+
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Superclass of all Edigeo files.
+ */
+abstract class EdigeoFile {
+
+    private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+
+    /**
+     * Block descriptor.
+     */
+    static class Block {
+        /** RTY */ final String type;
+        /** RID */ String identifier;
+
+        Block(String type) {
+            this.type = Objects.requireNonNull(type, "type");
+        }
+
+        public final String getType() {
+            return type;
+        }
+
+        public final String getIdentifier() {
+            return identifier;
+        }
+
+        void processRecord(EdigeoRecord r) {
+            if ("RID".equals(r.name)) {
+                identifier = safeGetAndLog(r, tr("Identifier"));
+            } else {
+                throw new IllegalArgumentException(r.toString());
+            }
+        }
+    }
+
+    private boolean bomFound;
+    private boolean eomFound;
+    EdigeoCharset charset;
+    private Block currentBlock;
+
+    EdigeoFile(Path path) throws IOException {
+        try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.ISO_8859_1)) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                if (!line.isEmpty()) {
+                    // Read record
+                    EdigeoRecord r = new EdigeoRecord(line);
+                    // Process begin of file
+                    if (!bomFound) {
+                        bomFound = "BOM".equals(r.name);
+                        if (!bomFound) {
+                            throw new IOException("Unexpected first record: " + r);
+                        } else {
+                            assert r.length == 12 && r.values.size() == 1 : r;
+                            continue;
+                        }
+                    }
+                    // Process charset
+                    if (charset == null) {
+                        if (!"CSE".equals(r.name)) {
+                            throw new IOException("Unexpected record instead of charset: " + r);
+                        } else {
+                            assert r.values.size() == 1 : r;
+                            charset = EdigeoCharset.of(r.values.get(0));
+                            continue;
+                        }
+                    }
+                    // Process other records & end of file
+                    if (eomFound) {
+                        throw new IOException("Unexpected record after end of file: " + r);
+                    }
+                    eomFound = "EOM".equals(r.name);
+                    if (!eomFound) {
+                        processRecord(r);
+                    } else {
+                        assert r.length == 0 && r.values.isEmpty() : r;
+                    }
+                }
+            }
+        }
+    }
+
+    protected abstract Block createBlock(String type);
+
+    private void processRecord(EdigeoRecord r) {
+        if ("RTY".equals(r.name)) {
+            currentBlock = createBlock(r.values.get(0));
+            return;
+        }
+
+        if (currentBlock == null) {
+            throw new IllegalStateException(r.toString());
+        }
+
+        currentBlock.processRecord(r);
+    }
+
+    protected static String safeGet(EdigeoRecord r) {
+        return r.length > 0 ? r.values.get(0) : null;
+    }
+
+    protected static int safeGetInt(EdigeoRecord r) {
+        return r.length > 0 ? Integer.parseInt(r.values.get(0)) : 0;
+    }
+
+    protected static LocalDate safeGetDate(EdigeoRecord r) {
+        return r.length > 0 ? LocalDate.parse(r.values.get(0), dateFormatter) : null;
+    }
+
+    protected static String safeGetAndLog(EdigeoRecord r, String msg) {
+        if (r.length > 0) {
+            String v = r.values.get(0);
+            Logging.info(msg + ": " + v);
+            return v;
+        }
+        return null;
+    }
+
+    protected static LocalDate safeGetDateAndLog(EdigeoRecord r, String msg) {
+        if (r.length > 0) {
+            LocalDate v = LocalDate.parse(r.values.get(0), dateFormatter);
+            Logging.info(msg + ": " + v);
+            return v;
+        }
+        return null;
+    }
+}
Index: /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoFileTHF.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoFileTHF.java	(revision 33642)
+++ /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoFileTHF.java	(revision 33642)
@@ -0,0 +1,275 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fr.cadastre.edigeo;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Edigeo THF file.
+ */
+public class EdigeoFileTHF extends EdigeoFile {
+
+    /**
+     * Support descriptor.
+     */
+    public static class Support extends Block {
+
+        enum SecurityClassification {
+            MILITARY_SECRECY(1),
+            INDUSTRIAL_SECRECY(2),
+            CONFIDENTIAL(3),
+            MILITARY_CONFIDENTIAL(4),
+            INDUSTRIAL_CONFIDENTIAL(5),
+            RESTRICTED_DIFFUSION(6),
+            NOT_PROTECTED(7);
+
+            final int level;
+            SecurityClassification(int level) {
+                this.level = level;
+            }
+
+            public static SecurityClassification of(int level) {
+                for (SecurityClassification s : values()) {
+                    if (s.level == level) {
+                        return s;
+                    }
+                }
+                throw new IllegalArgumentException(Integer.toString(level));
+            }
+        }
+
+        /** AUT */ String author;
+        /** ADR */ String recipient;
+        /** LOC */ int nLots;
+        /** VOC */ int nVolumes;
+        /** SEC */ SecurityClassification security;
+        /** RDI */ String diffusionRestriction;
+        /** VER */ String edigeoVersion;
+        /** VDA */ LocalDate edigeoDate;
+        /** TRL */ String transmissionName;
+        /** EDN */ int transmissionEdition;
+        /** TDA */ LocalDate transmissionDate;
+        /** INF */ String transmissionInformation;
+
+        Support(String type) {
+            super(type);
+        }
+
+        /**
+         * Returns author.
+         * @return author
+         */
+        public final String getAuthor() {
+            return author;
+        }
+
+        /**
+         * Returns recipient.
+         * @return recipient
+         */
+        public final String getRecipient() {
+            return recipient;
+        }
+
+        /**
+         * Returns number of geographic lots.
+         * @return number of geographic lots
+         */
+        public final int getnLots() {
+            return nLots;
+        }
+
+        /**
+         * Returns number of volumes.
+         * @return number of volumes
+         */
+        public final int getnVolumes() {
+            return nVolumes;
+        }
+
+        /**
+         * Returns security classification.
+         * @return security classification
+         */
+        public final SecurityClassification getSecurity() {
+            return security;
+        }
+
+        /**
+         * Returns diffusion restriction.
+         * @return diffusion restriction
+         */
+        public final String getDiffusionRestriction() {
+            return diffusionRestriction;
+        }
+
+        /**
+         * Returns Edigeo version.
+         * @return Edigeo version
+         */
+        public final String getEdigeoVersion() {
+            return edigeoVersion;
+        }
+
+        /**
+         * Returns Edigeo date.
+         * @return Edigeo date
+         */
+        public final LocalDate getEdigeoDate() {
+            return edigeoDate;
+        }
+
+        /**
+         * Returns name of transmission.
+         * @return name of transmission
+         */
+        public final String getTransmissionName() {
+            return transmissionName;
+        }
+
+        /**
+         * Returns edition number of transmission.
+         * @return edition number of transmission
+         */
+        public final int getTransmissionEdition() {
+            return transmissionEdition;
+        }
+
+        /**
+         * Returns date of transmission.
+         * @return date of transmission
+         */
+        public final LocalDate getTransmissionDate() {
+            return transmissionDate;
+        }
+
+        /**
+         * Returns general information about transmission.
+         * @return general information about transmission
+         */
+        public final String getTransmissionInformation() {
+            return transmissionInformation;
+        }
+
+        @Override
+        void processRecord(EdigeoRecord r) {
+            switch (r.name) {
+            case "AUT": author = safeGetAndLog(r, tr("Author")); break;
+            case "ADR": recipient = safeGetAndLog(r, tr("Recipient")); break;
+            case "LOC": nLots = safeGetInt(r); break;
+            case "VOC": nVolumes = safeGetInt(r); break;
+            case "SEC": security = SecurityClassification.of(safeGetInt(r)); break;
+            case "RDI": diffusionRestriction = safeGetAndLog(r, tr("Diffusion restriction")); break;
+            case "VER": edigeoVersion = safeGet(r); break;
+            case "VDA": edigeoDate = safeGetDate(r); break;
+            case "TRL": transmissionName = safeGet(r); break;
+            case "EDN": transmissionEdition = safeGetInt(r); break;
+            case "TDA": transmissionDate = safeGetDateAndLog(r, tr("Date")); break;
+            case "INF": transmissionInformation = safeGetAndLog(r, tr("Information")); break;
+            default:
+                super.processRecord(r);
+            }
+        }
+    }
+
+    /**
+     * Geographic lot descriptor.
+     */
+    public static class Lot extends Block {
+
+        /** LON */ String name;
+        /** INF */ String information;
+        /** GNN */ String genDataName;
+        /** GNI */ String genDataId;
+        /** GON */ String coorRefName;
+        /** GOI */ String coorRefId;
+        /** QAN */ String qualityName;
+        /** QAI */ String qualityId;
+        /** DIN */ String dictName;
+        /** DII */ String dictId;
+        /** SCN */ String scdName;
+        /** SCI */ String scdId;
+        /** GDC */ int nGeoData;
+        /** GDN */ final List<String> geoDataName = new ArrayList<>();
+        /** GDI */ final List<String> geoDataId = new ArrayList<>();
+
+        Lot(String type) {
+            super(type);
+        }
+
+        @Override
+        void processRecord(EdigeoRecord r) {
+            switch (r.name) {
+            case "LON": name = safeGetAndLog(r, tr("Name")); break;
+            case "INF": information = safeGetAndLog(r, tr("Information")); break;
+            case "GNN": genDataName = safeGet(r); break;
+            case "GNI": genDataId = safeGet(r); break;
+            case "GON": coorRefName = safeGet(r); break;
+            case "GOI": coorRefId = safeGet(r); break;
+            case "QAN": qualityName = safeGet(r); break;
+            case "QAI": qualityId = safeGet(r); break;
+            case "DIN": dictName = safeGet(r); break;
+            case "DII": dictId = safeGet(r); break;
+            case "SCN": scdName = safeGet(r); break;
+            case "SCI": scdId = safeGet(r); break;
+            case "GDC": nGeoData = safeGetInt(r); break;
+            case "GDN": geoDataName.add(safeGet(r)); break;
+            case "GDI": geoDataId.add(safeGet(r)); break;
+            default:
+                super.processRecord(r);
+            }
+        }
+    }
+
+    Support support;
+    List<Lot> lots;
+
+    /**
+     * Constructs a new {@code EdigeoFileTHF}.
+     * @param path path to THF file
+     * @throws IOException if any I/O error occurs
+     */
+    public EdigeoFileTHF(Path path) throws IOException {
+        super(path);
+    }
+
+    /**
+     * Returns the support descriptor.
+     * @return the support descriptor
+     */
+    public Support getSupport() {
+        return support;
+    }
+
+    /**
+     * Returns the list of geographic lot descriptors.
+     * @return the list of geographic lot descriptors
+     */
+    public List<Lot> getLots() {
+        return Collections.unmodifiableList(lots);
+    }
+
+    @Override
+    protected Block createBlock(String type) {
+        switch (type) {
+            case "GTS":
+                support = new Support(type);
+                return support;
+            case "GTL":
+                if (lots == null) {
+                    lots = new ArrayList<>();
+                }
+                Lot lot = new Lot(type);
+                lots.add(lot);
+                return lot;
+            default:
+                throw new IllegalArgumentException(type);
+        }
+    }
+}
Index: /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoRecord.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoRecord.java	(revision 33642)
+++ /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoRecord.java	(revision 33642)
@@ -0,0 +1,108 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fr.cadastre.edigeo;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Edigeo record.
+ */
+class EdigeoRecord {
+
+    enum Nature {
+        RESERVED('T'),
+        SIMPLE('S'),
+        COMPOSED('C');
+
+        final char code;
+        Nature(char code) {
+            this.code = code;
+        }
+
+        static Nature of(char c) {
+            for (Nature n : values()) {
+                if (c == n.code) {
+                    return n;
+                }
+            }
+            throw new IllegalArgumentException("Unknown code: " + c);
+        }
+    }
+
+    enum Format {
+        STRING('A'),
+        COORDINATES('C'),
+        DATE('D'),
+        REAL_WITH_EXP('E'),
+        SIGNED('I'),
+        UNSIGNED('N'),
+        DESCRIPTOR_REF('P'),
+        REAL_WITHOUT_EXP('R'),
+        TEXT('T'),
+        RESERVED(' ');
+
+        final char code;
+        Format(char code) {
+            this.code = code;
+        }
+
+        static Format of(char c) {
+            for (Format f : values()) {
+                if (c == f.code) {
+                    return f;
+                }
+            }
+            throw new IllegalArgumentException("Unknown code: " + c);
+        }
+    }
+
+    final String name;
+    final Nature nature;
+    final Format format;
+    final int length;
+    final List<String> values;
+
+    EdigeoRecord(String line) {
+        name = line.substring(0, 3);
+        assert 'A' <= name.charAt(0) && name.charAt(0) <= 'Z' : line;
+        nature = Nature.of(line.charAt(3));
+        format = Format.of(line.charAt(4));
+        assert nature != Nature.RESERVED || format == Format.RESERVED : line;
+        length = Integer.parseUnsignedInt(line.substring(5, 7));
+        assert line.charAt(7) == ':' : line;
+        if (line.length() > 8) {
+            assert line.length() <= 80;
+            values = Arrays.asList(line.substring(8).split(";"));
+            assert (nature == Nature.SIMPLE && values.size() == 1) || (nature == Nature.COMPOSED && values.size() > 1) : line;
+        } else {
+            values = Collections.emptyList();
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(format, length, nature, name, values);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        EdigeoRecord other = (EdigeoRecord) obj;
+        return format == other.format
+            && length == other.length
+            && nature == other.nature
+            && Objects.equals(name, other.name)
+            && Objects.equals(values, other.values);
+    }
+
+    @Override
+    public String toString() {
+        return "EdigeoRecord [name=" + name + ", nature=" + nature + ", format=" + format + ", length=" + length
+                + ", values=" + values + ']';
+    }
+}
Index: /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/pci/EdigeoPciImporter.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/pci/EdigeoPciImporter.java	(revision 33642)
+++ /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/pci/EdigeoPciImporter.java	(revision 33642)
@@ -0,0 +1,67 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fr.cadastre.edigeo.pci;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.io.importexport.OsmImporter;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.IllegalDataException;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Importer for French Cadastre - Edigéo files.
+ */
+public class EdigeoPciImporter extends OsmImporter {
+
+    static final ExtensionFileFilter EDIGEO_FILE_FILTER = new ExtensionFileFilter(
+            "thf", "thf", tr("Cadastre Edigeo files") + " (*.thf)");
+
+    protected File file;
+
+    /**
+     * Constructs a new {@code EdigeoImporter}.
+     */
+    public EdigeoPciImporter() {
+        super(EDIGEO_FILE_FILTER);
+    }
+
+    @Override
+    public void importData(File file, ProgressMonitor progressMonitor)
+            throws IOException, IllegalDataException {
+        if (file != null) {
+            this.file = file;
+        }
+        // Do not call super.importData because Compression.getUncompressedFileInputStream skips the first entry
+        try (InputStream in = new FileInputStream(file)) {
+            importData(in, file, progressMonitor);
+        } catch (FileNotFoundException e) {
+            Logging.error(e);
+            throw new IOException(tr("File ''{0}'' does not exist.", file.getName()), e);
+        }
+    }
+
+    @Override
+    protected DataSet parseDataSet(InputStream in, ProgressMonitor instance) throws IllegalDataException {
+        try {
+            return EdigeoPciReader.parseDataSet(in, file, instance);
+        } catch (IOException e) {
+            throw new IllegalDataException(e);
+        }
+    }
+
+    @Override
+    protected OsmDataLayer createLayer(DataSet dataSet, File associatedFile, String layerName) {
+        // FIXME: mapping pci => osm
+        //DataSetUpdater.updateDataSet(dataSet, handler, associatedFile);
+        return new OsmDataLayer(dataSet, layerName, associatedFile);
+    }
+}
Index: /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/pci/EdigeoPciReader.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/pci/EdigeoPciReader.java	(revision 33642)
+++ /applications/editors/josm/plugins/cadastre-fr/src/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/pci/EdigeoPciReader.java	(revision 33642)
@@ -0,0 +1,53 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fr.cadastre.edigeo.pci;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.DataSet.UploadPolicy;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.AbstractReader;
+import org.openstreetmap.josm.io.IllegalDataException;
+import org.openstreetmap.josm.plugins.fr.cadastre.edigeo.EdigeoFileTHF;
+
+/**
+ * Reader for French Cadastre - Edigéo files.
+ */
+public class EdigeoPciReader extends AbstractReader {
+
+    /**
+     * Constructs a new {@code EdigeoReader}.
+     */
+    public EdigeoPciReader() {
+    }
+
+    static DataSet parseDataSet(InputStream in, File file, ProgressMonitor instance) throws IOException {
+        if (in != null) {
+            in.close();
+        }
+        try {
+            return new EdigeoPciReader().parse(file.toPath(), instance);
+        } catch (IOException e) {
+            throw e;
+        } catch (Throwable t) {
+            throw new IOException(t);
+        }
+    }
+
+    DataSet parse(Path path, ProgressMonitor instance) throws IOException {
+        // Read THF file
+        EdigeoFileTHF thf = new EdigeoFileTHF(path);
+        DataSet ds = new DataSet();
+        ds.setName(thf.getSupport().getIdentifier());
+        ds.setUploadPolicy(UploadPolicy.DISCOURAGED);
+        return ds;
+    }
+
+    @Override
+    protected DataSet doParseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
+        return null;
+    }
+}
Index: /applications/editors/josm/plugins/cadastre-fr/test/unit/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoRecordTest.java
===================================================================
--- /applications/editors/josm/plugins/cadastre-fr/test/unit/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoRecordTest.java	(revision 33642)
+++ /applications/editors/josm/plugins/cadastre-fr/test/unit/org/openstreetmap/josm/plugins/fr/cadastre/edigeo/EdigeoRecordTest.java	(revision 33642)
@@ -0,0 +1,40 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fr.cadastre.edigeo;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.openstreetmap.josm.plugins.fr.cadastre.edigeo.EdigeoRecord.Format;
+import org.openstreetmap.josm.plugins.fr.cadastre.edigeo.EdigeoRecord.Nature;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+/**
+ * Unit test of {@link EdigeoRecord}.
+ */
+public class EdigeoRecordTest {
+
+    /**
+     * Unit test of {@link EdigeoRecord#EdigeoRecord}.
+     */
+    @Test
+    public void testEdigeoRecord() {
+        EdigeoRecord r = new EdigeoRecord("SCPCP27:TEST01;SeSD;OBJ;PARCELLE_id");
+        assertEquals("SCP", r.name);
+        assertEquals(Nature.COMPOSED, r.nature);
+        assertEquals(Format.DESCRIPTOR_REF, r.format);
+        assertEquals(27, r.length);
+        assertEquals(Arrays.asList("TEST01", "SeSD", "OBJ", "PARCELLE_id"), r.values);
+    }
+
+    /**
+     * Unit test of methods {@link EdigeoRecord#equals} and {@link EdigeoRecord#hashCode}.
+     */
+    @Test
+    public void testEqualsContract() {
+        EqualsVerifier.forClass(EdigeoRecord.class).usingGetClass()
+            .verify();
+    }
+}
