国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Rumah Java javaTutorial Menukar entiti JPA kepada Mendix

Menukar entiti JPA kepada Mendix

Jan 13, 2025 pm 06:04 PM

Baru-baru ini semasa menerokai Mendix, saya dapati mereka mempunyai Platform SDK yang membolehkan anda berinteraksi dengan model aplikasi mendix melalui API.

Ini memberi saya idea untuk meneroka sama ada ia boleh digunakan untuk mencipta model domain kami. Khususnya, untuk mencipta model domain berdasarkan aplikasi tradisional sedia ada.

Jika digeneralisasikan lagi, ini boleh digunakan untuk menukar mana-mana aplikasi sedia ada kepada Mendix dan meneruskan pembangunan dari sana.

Menukar aplikasi web Java/Spring kepada Mendix

Jadi, saya mencipta aplikasi web Java/Spring yang kecil dengan API dan lapisan pangkalan data yang mudah. Ia menggunakan pangkalan data H2 terbenam untuk kesederhanaan.

Dalam siaran ini, kami hanya akan menukar entiti JPA. Jom tengok mereka:

@Entity
@Table(name = "CAT")
class Cat {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    private int age;
    private String color;

    @OneToOne
    private Human humanPuppet;

    ... constructor ...
    ... getters ...
}

@Entity
@Table(name = "HUMAN")
public class Human {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    ... constructor ...
    ... getters ...
}

Seperti yang anda lihat, ia agak mudah: Kucing dengan nama, umur, warna dan boneka Manusianya, kerana kucing memerintah dunia seperti yang kita tahu.

Kedua-duanya mempunyai medan ID yang dijana secara automatik. Kucing mempunyai perkaitan satu sama lain dengan Manusia supaya ia boleh memanggil manusianya pada bila-bila masa ia mahu. (Jika ia bukan entiti JPA, saya akan meletakkan kaedah meow() tetapi biarkan itu untuk masa hadapan).

Apl berfungsi sepenuhnya tetapi sekarang kami hanya berminat dengan lapisan data.

Mengekstrak metadata Entiti dalam json

Ini boleh dilakukan dalam beberapa cara berbeza:

  1. Dengan menganalisis entiti secara statik dalam pakej mereka.
  2. Dengan menggunakan refleksi untuk membaca entiti tersebut pada masa jalan.

Saya telah memilih pilihan 2 kerana ia lebih cepat dan saya tidak dapat mencari perpustakaan yang boleh melakukan pilihan 1 dengan mudah.

Seterusnya, kita perlu memutuskan cara untuk mendedahkan json sebaik sahaja kita membinanya. Untuk memudahkan, kami hanya akan menulisnya ke dalam fail. Beberapa cara alternatif boleh jadi:

  • Mendedahkannya melalui api. Ini lebih rumit kerana anda juga perlu memastikan titik akhir terjamin dengan baik kerana kami tidak boleh mendedahkan metadata kami secara terbuka.
  • Mendedahkannya melalui beberapa alat pengurusan, seperti penggerak but spring atau jmx. Ia lebih selamat, tetapi masih memerlukan masa untuk menyediakan.

Mari kita lihat kod sebenar:

public class MendixExporter {
    public static void exportEntitiesTo(String filePath) throws IOException {
        AnnotatedTypeScanner typeScanner = new AnnotatedTypeScanner(false, Entity.class);

        Set<Class<?>> entityClasses = typeScanner.findTypes(JavaToMendixApplication.class.getPackageName());
        log.info("Entity classes are: {}", entityClasses);

        List<MendixEntity> mendixEntities = new ArrayList<>();

        for (Class<?> entityClass : entityClasses) {
            List<MendixAttribute> attributes = new ArrayList<>();
            for (Field field : entityClass.getDeclaredFields()) {

                AttributeType attributeType = determineAttributeType(field);
                AssociationType associationType = determineAssociationType(field, attributeType);
                String associationEntityType = determineAssociationEntityType(field, attributeType);

                attributes.add(
                        new MendixAttribute(field.getName(), attributeType, associationType, associationEntityType));
            }
            MendixEntity newEntity = new MendixEntity(entityClass.getSimpleName(), attributes);
            mendixEntities.add(newEntity);
        }

        writeToJsonFile(filePath, mendixEntities);
    }
    ...
}

Kami bermula dengan mencari semua kelas dalam apl kami yang ditandakan dengan anotasi @Entity JPA.
Kemudian, untuk setiap kelas, kami:

  1. Dapatkan medan yang diisytiharkan dengan entityClass.getDeclaredFields().
  2. Gelung setiap medan kelas itu.

Untuk setiap medan, kami:

  1. Tentukan jenis atribut:

    private static final Map<Class<?>, AttributeType> JAVA_TO_MENDIX_TYPE = Map.ofEntries(
            Map.entry(String.class, AttributeType.STRING),
            Map.entry(Integer.class, AttributeType.INTEGER),
            ...
            );
    // we return AttributeType.ENTITY if we cannot map to anything else
    

    Pada asasnya kami hanya memadankan jenis java dengan nilai enum tersuai kami dengan mencarinya dalam peta JAVA_TO_MENDIX_TYPE.

  2. Seterusnya, kami menyemak sama ada atribut ini sebenarnya adalah perkaitan (menunjuk kepada @Entity lain). Jika ya, kami menentukan jenis persatuan itu: satu-dengan-satu, satu-ke-banyak, banyak-ke-banyak:

    @Entity
    @Table(name = "CAT")
    class Cat {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        private String name;
        private int age;
        private String color;
    
        @OneToOne
        private Human humanPuppet;
    
        ... constructor ...
        ... getters ...
    }
    
    @Entity
    @Table(name = "HUMAN")
    public class Human {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        private String name;
    
        ... constructor ...
        ... getters ...
    }
    

    Untuk berbuat demikian, kami hanya menyemak jenis atribut yang dipetakan sebelum ini. Sekiranya ia adalah Entiti, yang bermaksud bahawa dalam langkah sebelum ini kami tidak dapat memetakannya kepada mana-mana jenis java primitif, String atau Enum.
    Kemudian kita juga perlu memutuskan jenis persatuan itu. Semakannya mudah: jika ia adalah jenis Senarai, maka ia adalah satu-ke-banyak, sebaliknya satu-dengan-satu (belum melaksanakan 'banyak-ke-banyak' lagi).

  3. Kami kemudian mencipta objek MendixAttribute untuk setiap medan yang ditemui.

Setelah itu selesai, kami hanya mencipta objek MendixEntity untuk entiti dengan senarai atribut yang diberikan.
MendixEntity dan MendixAttribute ialah kelas yang akan kami gunakan untuk memetakan ke json nanti:

public class MendixExporter {
    public static void exportEntitiesTo(String filePath) throws IOException {
        AnnotatedTypeScanner typeScanner = new AnnotatedTypeScanner(false, Entity.class);

        Set<Class<?>> entityClasses = typeScanner.findTypes(JavaToMendixApplication.class.getPackageName());
        log.info("Entity classes are: {}", entityClasses);

        List<MendixEntity> mendixEntities = new ArrayList<>();

        for (Class<?> entityClass : entityClasses) {
            List<MendixAttribute> attributes = new ArrayList<>();
            for (Field field : entityClass.getDeclaredFields()) {

                AttributeType attributeType = determineAttributeType(field);
                AssociationType associationType = determineAssociationType(field, attributeType);
                String associationEntityType = determineAssociationEntityType(field, attributeType);

                attributes.add(
                        new MendixAttribute(field.getName(), attributeType, associationType, associationEntityType));
            }
            MendixEntity newEntity = new MendixEntity(entityClass.getSimpleName(), attributes);
            mendixEntities.add(newEntity);
        }

        writeToJsonFile(filePath, mendixEntities);
    }
    ...
}

Akhir sekali, kami menyimpan Senarai ke fail json menggunakan jackson.

Mengimport entiti ke dalam Mendix

Inilah bahagian yang menyeronokkan, bagaimana kita membaca fail json yang kita hasilkan di atas dan mencipta entiti mendix daripadanya?

SDK Platform Mendix mempunyai API Typescript untuk berinteraksi dengannya.
Mula-mula kita akan mencipta objek untuk mewakili entiti dan atribut kita, serta enum untuk jenis perkaitan dan atribut:

private static final Map<Class<?>, AttributeType> JAVA_TO_MENDIX_TYPE = Map.ofEntries(
        Map.entry(String.class, AttributeType.STRING),
        Map.entry(Integer.class, AttributeType.INTEGER),
        ...
        );
// we return AttributeType.ENTITY if we cannot map to anything else

Seterusnya, kami perlu mendapatkan apl kami dengan appId, membuat salinan kerja sementara, membuka model dan mencari model domain yang kami minati:

private static AssociationType determineAssociationType(Field field, AttributeType attributeType) {
    if (!attributeType.equals(AttributeType.ENTITY))
        return null;
    if (field.getType().equals(List.class)) {
        return AssociationType.ONE_TO_MANY;
    } else {
        return AssociationType.ONE_TO_ONE;
    }
}

SDK sebenarnya akan menarik apl mendix kami daripada git dan mengusahakannya.

Selepas membaca daripada fail json, kami akan menggelungkan entiti:

public record MendixEntity(
        String name,
        List<MendixAttribute> attributes) {
}

public record MendixAttribute(
        String name,
        AttributeType type,
        AssociationType associationType,
        String entityType) {

    public enum AttributeType {
        STRING,
        INTEGER,
        DECIMAL,
        AUTO_NUMBER,
        BOOLEAN,
        ENUM,
        ENTITY;
    }

    public enum AssociationType {
        ONE_TO_ONE,
        ONE_TO_MANY
    }
}

Di sini kami menggunakan domainmodels.Entity.createIn(domainModel); untuk mencipta entiti baharu dalam model domain kami dan memberikan nama kepadanya. Kami boleh menetapkan lebih banyak sifat, seperti dokumentasi, indeks, malah lokasi tempat entiti akan dipaparkan dalam model domain.

Kami memproses atribut dalam fungsi berasingan:

interface ImportedEntity {
    name: string;
    generalization: string;
    attributes: ImportedAttribute[];
}

interface ImportedAttribute {
    name: string;
    type: ImportedAttributeType;
    entityType: string;
    associationType: ImportedAssociationType;
}

enum ImportedAssociationType {
    ONE_TO_ONE = "ONE_TO_ONE",
    ONE_TO_MANY = "ONE_TO_MANY"
}

enum ImportedAttributeType {
    INTEGER = "INTEGER",
    STRING = "STRING",
    DECIMAL = "DECIMAL",
    AUTO_NUMBER = "AUTO_NUMBER",
    BOOLEAN = "BOOLEAN",
    ENUM = "ENUM",
    ENTITY = "ENTITY"
}

Satu-satunya perkara di sini yang perlu kita lakukan ialah memetakan jenis atribut kepada jenis mendix yang sah.

Seterusnya kami memproses persatuan. Pertama, memandangkan dalam entiti Java kami persatuan telah diisytiharkan oleh medan, kami perlu membezakan medan mana yang merupakan atribut mudah, dan mana yang merupakan persatuan. Untuk melakukannya, kita hanya perlu menyemak sama ada ia jenis ENTITI atau jenis primitif:

const client = new MendixPlatformClient();
const app = await client.getApp(appId);
const workingCopy = await app.createTemporaryWorkingCopy("main");
const model = await workingCopy.openModel();
const domainModelInterface = model.allDomainModels().filter(dm => dm.containerAsModule.name === MyFirstModule")[0];
const domainModel = await domainModelInterface.load();

Mari kita wujudkan persatuan:

function createMendixEntities(domainModel: domainmodels.DomainModel, entitiesInJson: any) {
    const importedEntities: ImportedEntity[] = JSON.parse(entitiesInJson);

    importedEntities.forEach((importedEntity, i) => {
        const mendixEntity = domainmodels.Entity.createIn(domainModel);
        mendixEntity.name = importedEntity.name;

        processAttributes(importedEntity, mendixEntity);
    });

    importedEntities.forEach(importedEntity => {
        const mendixParentEntity = domainModel.entities.find(e => e.name === importedEntity.name) as domainmodels.Entity;
        processAssociations(importedEntity, domainModel, mendixParentEntity);
    });
}

Kami ada 4 sifat penting untuk ditetapkan, selain nama:

  1. Entiti induk. Ini ialah entiti semasa.
  2. Entiti kanak-kanak. Dalam langkah terakhir, kami mencipta entiti mendix untuk setiap entiti java. Sekarang kita hanya perlu mencari entiti yang sepadan berdasarkan jenis medan java dalam entiti kita:

    function processAttributes(importedEntity: ImportedEntity, mendixEntity: domainmodels.Entity) {
        importedEntity.attributes.filter(a => a.type !== ImportedAttributeType.ENTITY).forEach(a => {
            const mendixAttribute = domainmodels.Attribute.createIn(mendixEntity);
            mendixAttribute.name = capitalize(getAttributeName(a.name, importedEntity));
            mendixAttribute.type = assignAttributeType(a.type, mendixAttribute);
        });
    }
    
  3. Jenis persatuan. Jika ia satu-dengan-satu, ia memetakan kepada Rujukan. Jika ia satu-ke-banyak, ia memetakan kepada Set Rujukan. Kami akan melangkau banyak-ke-banyak buat masa ini.

  4. Pemilik persatuan. Kedua-dua persatuan satu-dengan-satu dan banyak-ke-banyak mempunyai jenis pemilik yang sama: Kedua-duanya. Untuk satu sama satu, jenis pemilik mestilah Lalai.

SDK Platform Mendix akan mencipta entiti dalam salinan kerja tempatan aplikasi mendix kami. Sekarang kita hanya perlu memberitahunya untuk melakukan perubahan:

@Entity
@Table(name = "CAT")
class Cat {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    private int age;
    private String color;

    @OneToOne
    private Human humanPuppet;

    ... constructor ...
    ... getters ...
}

@Entity
@Table(name = "HUMAN")
public class Human {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    ... constructor ...
    ... getters ...
}

Selepas beberapa saat, anda boleh membuka apl dalam Mendix Studio Pro dan mengesahkan keputusan:
Converting JPA entities to Mendix

Begitulah: entiti Kucing dan Manusia dengan perkaitan satu dengan satu di antara mereka.

Jika anda ingin mencuba sendiri atau melihat kod penuh, pergi ke repo ini.

Idea untuk masa hadapan

  1. Dalam contoh ini saya telah menggunakan aplikasi Java/Spring untuk menukar daripadanya kerana saya paling mahir dalam penggunaannya tetapi sebarang aplikasi boleh digunakan. Cukup sekadar dapat membaca data jenis (secara statik atau semasa masa jalan) untuk mengekstrak nama kelas dan medan.
  2. Saya ingin tahu untuk mencuba membaca dan mengeksport beberapa logik java ke aliran mikro Mendix. Kita mungkin tidak benar-benar boleh menukar logik perniagaan itu sendiri tetapi kita sepatutnya boleh mendapatkan strukturnya (sekurang-kurangnya tandatangan kaedah perniagaan?).
  3. Kod daripada artikel ini boleh digeneralisasikan dan dijadikan perpustakaan: format json boleh kekal sama, dan mungkin terdapat satu perpustakaan untuk mengeksport jenis java dan satu lagi untuk mengimport entiti mendix.
  4. Kita boleh menggunakan pendekatan yang sama untuk melakukan sebaliknya: menukar mendix kepada bahasa lain.

Kesimpulan

Mendix Platform SDK ialah ciri berkuasa yang membolehkan anda berinteraksi dengan apl mendix secara pengaturcaraan. Mereka menyenaraikan beberapa contoh kes penggunaan seperti mengimport/mengeksport kod, menganalisis kerumitan apl.
Sila lihat mereka sekiranya anda berminat.
Untuk artikel ini, anda boleh mendapatkan kod penuh di sini.

Atas ialah kandungan terperinci Menukar entiti JPA kepada Mendix. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Perbezaan antara hashmap dan hashtable? Perbezaan antara hashmap dan hashtable? Jun 24, 2025 pm 09:41 PM

Perbezaan antara hashmap dan hashtable terutamanya dicerminkan dalam keselamatan benang, sokongan nilai null dan prestasi. 1. Dari segi keselamatan benang, hashtable adalah benang selamat, dan kaedahnya kebanyakannya kaedah segerak, sementara hashmap tidak melakukan pemprosesan penyegerakan, yang bukan benang-selamat; 2. Dari segi sokongan nilai null, hashmap membolehkan satu kunci null dan nilai null berbilang, manakala hashtable tidak membenarkan kekunci atau nilai null, jika tidak, nullPointerException akan dibuang; 3. Dari segi prestasi, hashmap lebih cekap kerana tidak ada mekanisme penyegerakan, dan Hashtable mempunyai prestasi penguncian yang rendah untuk setiap operasi. Adalah disyorkan untuk menggunakan ConcurrentHashMap sebaliknya.

Mengapa kita memerlukan kelas pembalut? Mengapa kita memerlukan kelas pembalut? Jun 28, 2025 am 01:01 AM

Java menggunakan kelas pembalut kerana jenis data asas tidak dapat mengambil bahagian secara langsung dalam operasi berorientasikan objek, dan bentuk objek sering diperlukan dalam keperluan sebenar; 1. Kelas koleksi hanya boleh menyimpan objek, seperti senarai menggunakan tinju automatik untuk menyimpan nilai berangka; 2. Generik tidak menyokong jenis asas, dan kelas pembungkusan mesti digunakan sebagai parameter jenis; 3. Kelas pembungkusan boleh mewakili nilai null untuk membezakan data yang tidak tersendiri atau hilang; 4. Kelas pembungkusan menyediakan kaedah praktikal seperti penukaran rentetan untuk memudahkan parsing dan pemprosesan data, jadi dalam senario di mana ciri -ciri ini diperlukan, kelas pembungkusan sangat diperlukan.

Apakah kaedah statik dalam antara muka? Apakah kaedah statik dalam antara muka? Jun 24, 2025 pm 10:57 PM

Staticmethodsininterfaceswereintroducedinjava8toallowutilityfunctionswithintheintheinterfaceitself.beforjava8, SuchfunctionsRequiredseparateHelpereHelperes, LeadingTodisorgaganizedCode.Now, staticmethodethreeKeybeeMeKeBeReSes, staticmethodeDethreeKeybeeMeKeBeReSes, staticmethodethreeKeybeeMeKeKeBeReSes, staticmethodeDethreeKeybeeMeKeKeBeReKeNey

Bagaimanakah pengkompil JIT mengoptimumkan kod? Bagaimanakah pengkompil JIT mengoptimumkan kod? Jun 24, 2025 pm 10:45 PM

Penyusun JIT mengoptimumkan kod melalui empat kaedah: kaedah dalam talian, pengesanan tempat panas dan penyusunan, spekulasi jenis dan devirtualisasi, dan penghapusan operasi yang berlebihan. 1. Kaedah sebaris mengurangkan panggilan overhead dan memasukkan kaedah kecil yang sering dipanggil terus ke dalam panggilan; 2. Pengesanan tempat panas dan pelaksanaan kod frekuensi tinggi dan mengoptimumkannya untuk menjimatkan sumber; 3. Jenis spekulasi mengumpul maklumat jenis runtime untuk mencapai panggilan devirtualisasi, meningkatkan kecekapan; 4. Operasi berlebihan menghapuskan pengiraan dan pemeriksaan yang tidak berguna berdasarkan penghapusan data operasi, meningkatkan prestasi.

Apakah blok inisialisasi contoh? Apakah blok inisialisasi contoh? Jun 25, 2025 pm 12:21 PM

Blok permulaan contoh digunakan dalam Java untuk menjalankan logik inisialisasi apabila membuat objek, yang dilaksanakan sebelum pembina. Ia sesuai untuk senario di mana beberapa pembina berkongsi kod inisialisasi, permulaan medan kompleks, atau senario permulaan kelas tanpa nama. Tidak seperti blok inisialisasi statik, ia dilaksanakan setiap kali ia ditegaskan, manakala blok permulaan statik hanya dijalankan sekali apabila kelas dimuatkan.

Apakah kata kunci `akhir` untuk pembolehubah? Apakah kata kunci `akhir` untuk pembolehubah? Jun 24, 2025 pm 07:29 PM

Injava, thefinalkeywordpreventsavariable'svaluefrombeingchangedafterassignment, butitsbehaviordiffersforprimitivesandobjectreferences.forprimitiveVariables, finalmakesthevalueconstant, asinfinalintmax_speed = 100;

Apakah corak kilang? Apakah corak kilang? Jun 24, 2025 pm 11:29 PM

Mod kilang digunakan untuk merangkum logik penciptaan objek, menjadikan kod lebih fleksibel, mudah dikekalkan, dan ditambah longgar. Jawapan teras adalah: dengan mengurus logik penciptaan objek secara berpusat, menyembunyikan butiran pelaksanaan, dan menyokong penciptaan pelbagai objek yang berkaitan. Keterangan khusus adalah seperti berikut: Mod Kilang menyerahkan penciptaan objek ke kelas kilang khas atau kaedah untuk diproses, mengelakkan penggunaan Newclass () secara langsung; Ia sesuai untuk senario di mana pelbagai jenis objek yang berkaitan dicipta, logik penciptaan boleh berubah, dan butiran pelaksanaan perlu disembunyikan; Sebagai contoh, dalam pemproses pembayaran, jalur, paypal dan contoh lain dicipta melalui kilang -kilang; Pelaksanaannya termasuk objek yang dikembalikan oleh kelas kilang berdasarkan parameter input, dan semua objek menyedari antara muka yang sama; Varian biasa termasuk kilang -kilang mudah, kaedah kilang dan kilang abstrak, yang sesuai untuk kerumitan yang berbeza.

Apakah jenis pemutus? Apakah jenis pemutus? Jun 24, 2025 pm 11:09 PM

Terdapat dua jenis penukaran: tersirat dan eksplisit. 1. Penukaran tersirat berlaku secara automatik, seperti menukar int untuk berganda; 2. Penukaran eksplisit memerlukan operasi manual, seperti menggunakan (int) mydouble. Kes di mana penukaran jenis diperlukan termasuk memproses input pengguna, operasi matematik, atau lulus pelbagai jenis nilai antara fungsi. Isu-isu yang perlu diperhatikan adalah: Mengubah nombor terapung ke dalam bilangan bulat akan memotong bahagian pecahan, mengubah jenis besar menjadi jenis kecil boleh menyebabkan kehilangan data, dan beberapa bahasa tidak membenarkan penukaran langsung jenis tertentu. Pemahaman yang betul tentang peraturan penukaran bahasa membantu mengelakkan kesilapan.

See all articles