Конвертация моделей данных из формата XSD ПИР в формат Sencha Ext JS Model
Инсталяция для пользователя
Установить SWI-Prolog 7.4.2 for Microsoft Windows (64 bit)
http://www.swi-prolog.org/download/stable
Добавить в PATH
строку C:\Program Files\swipl\bin
.
После этого в командной строке должна быть доступна команда swipl
.
Установить зависимости
npm install
Создать пустой пакет (здесь он называется pir-model
), где будут размещаться сгененированные модели.
В файле package.json
вашего проекта прописать скрипт (здесь он называется pir-model
):
"scripts":
В корне пакета pir-model создать файл preparer.config.js со следующим содержимым:
const extend = ;const prepareClasses = ; moduleexports = dirs: input: '<путь до WSDL-файлов>' output: result: 'src' namespace: 'Pir.model' extend: extend prepareClasses: prepareClasses ;
Здесь namespace укажите для своего проекта.
Создайте файл \packages\local\pir-model\preparer\extend.js со следующим содержимым:
/** * Вычисление опции extend для каждой модели. */module { const m = model bt = modelbaseType; return modelbaseType ? `..` : `.Base`;};
Создайте файл \packages\local\pir-model\preparer\prepareClasses.js со следующим содержимым:
const fs = ;const path = ;const _ = ;const senchaExtjsGenerator = ; const ModelClass = senchaExtjsGeneratorModelClass;const Config = senchaExtjsGeneratorConfig; /** * Изменение классов перед их сохранением в пакете pir-model. */module { const common = modelClassManager; /** * Создание дополнительных классов. */ const creators = fs; creators; /** * Переопределение имеющихся классов Override. * Этим добавляется дополнительный функционал в имеющиеся модели данных. */ const overrides = fs; overrides; };
Создайте файл \packages\local\pir-model\preparer\common.js со следующим содержимым:
const camelcase = ;const pascalcase = ;const Config: ExtjsConfig ModelClass: ExtjsModelClass = ; /** * Общие функции. */module { { return modelClassManager; } /** * Функция для удобной обработки одного класса. * В качестве контекста this для функции prepareFn выступает сам класс. */ { const cls = modelClassManager; if !cls console; if cls prepareFncls; } /** * Функция для создания классов, предназначенных для создания хранилищ * под результаты разных методов АПИ сервера. * Добавляет название метода сервиса и имя поля, где хранятся массив записей. * @return */ { const baseClass = modelClassManager; const infoClass = baseClass; infoClassnamevalue = name; infoClassextendvalue = baseClassnamelocalName; infoClassproxyvalue = name: 'serviceMethod' value: serviceMethod name: 'reader' value: name: 'rootProperty' value: `result.` ; // Внимание, после добавления класса в менеджер классов добавьте очистку полей: // infoClass.fields.clear(); // Очистку полей можно делать ТОЛЬКО после добавления класса в менеджер классов. return infoClass; } /** * Вычисление baseClassName и rootProperty для классов информационных моделей. * На выходе готовый конфиг для метода createInfoClass. * @param * @param * @param * @param * @return */ { let rootProperty baseClassName; // Имя сервиса в WSDL (точнее имена файлов *.wsdl) отличаются от именования сервисов в клиенте. const serviceFolderName = information: 'debtorInformation' operations: 'debtorOperations' administration: 'debtorAdministration' serviceName; if !serviceFolderName throw `Неизвестный сервис ''.`; // Ищем класс ответа для данного метода сервера. const responseClassName = `.Response`; const responseClass = modelClassManager; if !responseClass throw `Не найден класс ''.`; if !responseClass throw `В классе ответа сервера '' нет hasOne с role==result.`; // В классе ответа ищем поле result в разделе hasOne. const resultAssociation = responseClasshasOnevalue; // В поле result ищем type. Это будет класс результатов в ответе сервера. const resultClassName = resultAssociationvalue; const resultClass = modelClassManager; if !resultClass throw `Не найден класс ''.`; // В классе результата ищем hasMany. // Для проверки надо убедится что он есть и в нем только одна запись, иначе ошибка. if !resultClass throw `В классе результата '' нет hasMany.`; if resultClasshasManyvaluelength > 1 throw `В hasMany класса результата '' больше одной связи.`; // Также можно проверить наличие totalRecordCount в fields, иначе ошибка. if !resultClass throw `В классе '' нет полей модели.`; if !resultClassfieldsvalue throw `В классе '' не найдено поле totalRecordCount.`; // Из hasMany следует вытащить role и сделать его PascalCase. rootProperty = ; baseClassName = resultClasshasManyvalue0value; return baseClassName name serviceMethod rootProperty serviceName ; } /** * Создание класса модели для словарей. * Все классы наследуются от класса результата ответа сервера на метод getDictionaryDetailsBySearchParams * На данный момент этим классом является Pir.model.baseModel.type.TBaseDictionary. * Также в extraParams.DictionaryCode включен код словаря dictionaryCode. */ { const serviceMethod = 'getDictionaryDetailsBySearchParams'; const baseClassName rootProperty = ; const dictionaryDetailClass = `dictionary.` name: 'proxy' value: name: 'serviceMethod' value: serviceMethod name: 'reader' value: name: 'rootProperty' value: rootProperty name: 'extraParams' value: name: 'DictionaryCode' value: dictionaryCode ; dictionaryDetailClassextendvalue = baseClassName; return dictionaryDetailClass; } return prepareClass createInfoClass createInfoClassConfig createDictionaryDetailClass ; }
Создайте каталоги:
\packages\local\pir-model\preparer\create
\packages\local\pir-model\preparer\override
с содержимым аналогичным как в проекте w_pir_client_v2
.
Собственно кодогенерацию следует настраивать путем создания скриптов в этих двух директориях.
В директории create создаются скрипты для создания новых моделей.
В директории override создаются оверрайды для существующих.
Запуск кодогенерации
npm run pir-model
Если все было сделано верно, сгенерированные модели будут размещены в директории \packages\local\pir-model\src
.