Cria, revisa e padroniza XML do dicionário de dados Sankhya (`datadictionary/<TABELA>.xml`) — `<table>`, `<treeTable>`, `<nativeTable>`, `<instance>`, `<fields>`, `<filters>`, `<menu>`, `<dynamicForm>`, `<dynamicTreeView>`, `dataType` (TEXTO/INTEIRO/DECIMAL/DATA/DATA_HORA/HORA/CHECKBOX/LISTA/PESQUISA), `<expression>`, `calculated`, lookups e relacionamentos. Use ao criar, alterar, revisar, auditar ou padronizar arquivos em `datadictionary/`, ao receber spec de tabela/entidade hierárquica, ao definir metadados/UI de uma tabela, ao mapear tipos, ou ao tocar em XML com tag raiz `<metadados>` ou tags `<table>`/`<treeTable>`.
Cria, revisa e padroniza XML do dicionário de dados Sankhya (`datadictionary/<TABELA>.xml`) — `<table>`, `<treeTable>`, `<nativeTable>`, `<instance>`, `<fields>`, `<filters>`, `<menu>`, `<dynamicForm>`, `<dynamicTreeView>`, `dataType` (TEXTO/INTEIRO/DECIMAL/DATA/DATA_HORA/HORA/CHECKBOX/LISTA/PESQUISA), `<expression>`, `calculated`, lookups e relacionamentos. Use ao criar, alterar, revisar, auditar ou padronizar arquivos em `datadictionary/`, ao receber spec de tabela/entidade hierárquica, ao definir metadados/UI de uma tabela, ao mapear tipos, ou ao tocar em XML com tag raiz `<metadados>` ou tags `<table>`/`<treeTable>`.
Dicionario de Dados (Data Dictionary) - Addon Studio 2.0
Dicionario de Dados define estrutura dados aplicacao — tabelas, campos, instancias, extensoes entidades nativas — declarativo via XML em datadictionary/.
Entidade Java (@JapeEntity) = classe dominio limpa — so @Column(name = "..."), @JoinColumn(name, referencedColumnName), anotacoes relacionamento (@OneToMany, @OneToOne, @ManyToOne). Toda metadata UI, tipos, descricoes, comportamento vive so nos XMLs.
Regra fundamental:@Column so atributo name. @JoinColumn so name e referencedColumnName. Nao use @Expression, @GeneratedValue, @Option, @Property nem outro atributo extra. Tudo no XML.
PARTE 1 - CRIANDO O DICIONARIO DE DADOS
1.1 Estrutura de Arquivos
Um XML por tabela/entidade em datadictionary/.
Convencao: nome arquivo = nome tabela. Ex: TDCXYZCAD.xml pra tabela TDCXYZCAD.
1.2 Esqueleto XML Base
<?xml version="1.0" encoding="ISO-8859-1" ?><metadadosxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../.gradle/metadados.xsd"><!-- <table> ou <nativeTable> aqui --></metadados>
1.3 Tags Raiz
Tag XML
Quando usar
<table />
Tabela nova criada pelo add-on.
<treeTable />
Tabela hierarquica (pai/filho) — cadastros tipo centro de custo, categorias de produto, organogramas. Framework gera UI tree + campos CODIGOPAI/ANALITICO/GRAU. Detalhes em references/tree-table.md.
<nativeTable />
Extensao tabela nativa Sankhya Om (adiciona campos/instancia).
<nativeFolder />
Container para <pastaNativa> — encaixe em pasta nativa Sankhya (Configuracoes / Cadastros / Consulta / Rotina / Relatorio). Detalhes em references/menu.md.
<menu />
Estrutura de menu/navegacao do add-on. Container para <folder>, <dynamicForm>, <dynamicTreeView>, <ui>, <dashboard>. Detalhes em references/menu.md.
<dynamicForm />
Tela CRUD declarativa (sem JS/HTML) gerada a partir de uma <instance> da tabela. Vai dentro de <menu>/<folder>. Detalhes em references/dynamic-form.md.
<filters />
Filtros de busca em telas geradas por <dynamicForm>/<dynamicTreeView>. Filho de <table>/<treeTable>. Detalhes em references/filters.md.
1.4 Tag <table> - Tabela nova
Atributos obrigatorios
Atributo
Descricao
name
Nome tabela no banco.
sequenceType
"A" (automatico) ou "M" (manual).
sequenceField
Coluna PK que recebe sequencia. Obrigatorio com sequenceType="A"; omitir com sequenceType="M".
Elemento filho obrigatorio: <description>
<table> exige <description> propria — registrada em TDDTAB.DESCRTAB (NOT NULL). Distinta da <description> da <instance>: a do <table> descreve a tabela fisica, a da <instance> descreve a entidade JAPE. Costumam ser iguais, mas as duas precisam estar presentes.
Define entidade (instancia JAPE) da tabela. Existem duas tags possiveis dentro de <instances>:
Tag
Quando usar
<instance>
Instancia nova, criada pelo addon. Permitida em <table> e em <nativeTable>.
<nativeInstance>
Instancia nativa do Sankhya (ex.: CabecalhoNota, Parceiro, Produto). Somente dentro de <nativeTable>.
<!-- Instancia nova do addon --><instances><instancename="TdcXyzProduto"><description>Produtos</description></instance></instances>
<!-- Instancia nativa Sankhya (so dentro de <nativeTable>) --><instances><nativeInstancename="CabecalhoNota"><relationShip><!-- relacoes opcionais com entidades do addon --></relationShip></nativeInstance></instances>
Atributos de <instance> / <nativeInstance>
Atributo
Obrigatorio
Descricao
name
Sim
Nome logico da entidade (bate com @JapeEntity(entity = "...")).
resourceId
Nao
Identificador do recurso da instancia no Sankhya. Formato br.com.sankhya.<projeto>.<idtela>.
parentInstance
Nao
resourceId da instancia nativa da qual esta deriva. Declara a instancia como alias/derivada da nativa.
parentInstance — alias de instancia nativa. Use quando o addon cria uma instancia propria sobre uma tabela nativa mas quer herdar o vinculo com a instancia nativa correspondente (telas, permissoes, comportamento). O valor e o resourceId da nativa, nao o name:
<nativeTablename="<TABELA_NATIVA>"><instances><instancename="<Prx><Mod><Ctx>"resourceId="br.com.sankhya.<projeto>.<idtela>"parentInstance="<resourceId da instancia nativa alvo>"><description>...</description></instance></instances></nativeTable>
O resourceId da instancia nativa alvo nao e adivinhavel — confira no dicionario do ambiente (TDDINS) ou no metadata nativo. Nunca invente o valor a partir do nome da instancia.
Sem parentInstance, a instancia nasce solta — perde o vinculo com a nativa. Omitir o atributo na geracao dropa a informacao silenciosamente (o XSD nao exige).
Por que <nativeInstance> ao inves de <instance>: ambas as tags geram a mesma entidade no runtime, mas <nativeInstance> sinaliza para o builder que a instancia ja existe no Sankhya nativo e nao deve ser regravada no metadata.xml final. Se uma instancia nativa for declarada como <instance>, o deploy do addon re-mapeia o owner da instancia para o addon e quebra regras de negocio, validacoes e telas nativas que dependem dela. Pareie sempre com isNativeInstance = true no @JapeEntity correspondente (ver entity secao 1.2).
Convencao de nomes (parametrizada por projeto)
Padrao parametrizado por <PRX> (prefixo) + <MOD3> (modulo). Ver database secao "Descobrir convencao do projeto" antes de criar tabela nova.
Atributo
Padrao
Exemplo (PRX=TDC, MOD3=XYZ)
<table name="...">
<PRX><MOD3><CTX> (UPPER)
TDCXYZCAB
<instance name="..."> (em <table>)
<Prx><Mod><Ctx> (PascalCase)
TdcXyzCabecalho
<instance name="..."> (em <nativeTable>, instancia nova)
<Prx><Mod><Ctx> (PascalCase)
TdcXyzDefensivos
<nativeInstance name="..."> (em <nativeTable>)
Nome exato da instancia nativa Sankhya
CabecalhoNota, Parceiro, ItemNota
Componentes do prefixo addon:
<Prx> / <PRX>: prefixo fixo do projeto, 3-4 caracteres (ex.: Tdc/TDC, App/APP, Cst/CST)
Prefixo <Prx><Mod> no <instance> evita colisao com outros contextos do ERP. Bate com @JapeEntity(entity = "...") correspondente. <nativeInstance>nunca leva prefixo addon — o nome tem que ser identico ao da instancia nativa Sankhya.
NOTA: exemplos seguintes usam TDC como prefixo ilustrativo. Substituir pelo <PRX> real do projeto.
1.7 Relacionamentos (<relationShip>)
Entidade com relacao (@OneToMany, @OneToOne) declara <relationShip> dentro <instance>/<nativeInstance>.
Atributos do <relation>
Atributo XML
Obrigatorio
Default
Significado
entityName
Sim
-
Nome da instancia relacionada.
relation
Nao
OneToOne
Tipo: OneToOne, OneToMany, ManyToOne, ManyToMany. Default e OneToOne — informar sempre em relacao 1:N.
insert
Nao
-
"S"/"N". So com OneToOne: inclui a entidade relacionada que tenha merge-on-root.
update
Nao
-
"S"/"N". So com OneToOne: atualiza a entidade relacionada que tenha merge-on-root.
removeCascade
Nao
-
"S"/"N". So com OneToMany: exclui os dados relacionados (equivale a delete on cascade).
Filhos: <expression> (opcional) e <fields> (obrigatorio). Cada <field> do <fields> tem localName (coluna da tabela atual) e targetName (coluna da relacionada).
Configura o relacionamento e/ou filtra a entidade destino. Aceita tres formatos (combinaveis no mesmo <expression>):
1) @ref-param[...] — configuracao do relacionamento (reflete no dynaform)
Opcao
Efeito
description=
Descricao da aba no dynaform (ex.: description=Contatos).
force-one-to-one=true
Forca entidade com chave dupla por data a aparecer como pesquisa em vez de aba. Ex.: TipoOperacao, TipoNegociacao.
result-only-analytic=true
Exibe so registros analiticos da entidade hierarquica destino.
show-on-ui=false
Com dynaform, a aba nao aparece na tela.
auto-search=true
Busca automatica da relacionada.
merge-on-root=true
Junta as 2 entidades na tela — o usuario ve uma coisa so. Pareia com insert/update no <relation>.
merge-to-find=true
Junta as entidades na busca.
APP_PROFILE=P:(...)
Exibe so se o cliente tiver os modulos da chave. Formato P:(<CHAVE>{<CODMOD>},...) — chave e codigo saem do modulo licenciado, nao invente.
2) @form-filter[...] — filtro de formulario
Pode depender de campo dos dois formularios. Alias form. = formulario de origem; alias this. = formulario de destino.
3) Filtro simples — depende so da entidade destino. Alias this..
<!-- 1) @ref-param: aba nomeada, forcada como pesquisa --><relationentityName="TdcXyzTipo"relation="OneToOne"><expression><![CDATA[@ref-param[description=Tipo, force-one-to-one=true]]]></expression><fields><fieldlocalName="CODTIPO"targetName="CODTIPO"/></fields></relation><!-- 2) @form-filter: cruza campo do form de origem (form.) com o destino (this.) --><relationentityName="TdcXyzVinculo"relation="OneToMany"><expression><![CDATA[@form-filter[EXISTS (SELECT 1 FROM TDCXYZCTR C WHERE C.CODEMP = form.CODEMP AND this.CODVINCULO = C.CODVINCULO)]]]></expression><fields><fieldlocalName="CODPRODUTO"targetName="CODPRODUTO"/></fields></relation><!-- 3) Filtro simples: so a entidade destino --><relationentityName="TdcXyzVinculo"relation="OneToMany"><expression><![CDATA[this.ATIVO='S']]></expression><fields><fieldlocalName="CODPRODUTO"targetName="CODPRODUTO"/></fields></relation>
force-one-to-one decide OneToOne vs aba no dynaform; description= nomeia a aba. Omitir <expression> na geracao perde cardinalidade correta, filtro e nome de aba — o XSD nao exige, entao a falta e silenciosa.
nullable vs required:nullable="N" restringe o dado (campo nao aceita nulo); required="S" restringe a UI (dynaform exige preenchimento). Nao sao sinonimos — campo obrigatorio na tela pode aceitar nulo no banco (registro gravado por integracao/listener) e vice-versa.
targetType em PESQUISA aceita: TEXTO, INTEIRO, DECIMAL, DATA, DATA_HORA, HORA.
Sub-tag <description> (obrigatoria)
Todo <field> tem <description>preenchida com texto descritivo (nao vazia, sem so espacos). Acentos permitidos — a skill encoding converte o arquivo para ISO-8859-1 depois.
Variaveis de contexto BeanShell (em <expression> BeanShell):
Expressao
Uso
$ctx_usuario_logado
Codigo usuario logado
$ctx_dh_atual
Data/hora atual servidor
$col_<COLUNA>
Valor atual coluna
Quando <expression> contiver SQL (nao BeanShell), envolva o conteudo com #type.sql# e use as macros SQL Sankhya (dbDate(), nullValue(), truncMonth(), etc.) para portabilidade Oracle/MSSQL. Ver macros.
<expression> vs atributo calculated — semantica completa:
<expression> define a logica do campo (BeanShell ou SQL via #type.sql#). O comportamento depende de o campo ter ou nao a flag calculated="S":
Cenario
<expression> roda
Coluna no banco
@Column na entity Java
<expression>semcalculated (default N)
So em INSERT/UPDATE
Sim — valor persiste na coluna fisica
Sim — @Column normal
<expression>comcalculated="S"
A cada leitura do registro
Nao — sem DDL para esse campo
Sim — @Column normal (framework le via expression)
Pontos criticos:
calculated="S"exige<expression> presente (obrigatorio).
calculated="S" afeta somente o DDL (sem coluna fisica). Nao afeta @Column da @JapeEntity — campo calculado continua acessivel pela entity Java normalmente.
Use calculated="S" quando precisar de informacao variavel atualizada em tempo real (ex.: status derivado de outras tabelas, agregacao).
Custo alto, especialmente SQL: se carregar 1000 registros, o framework dispara 1 query por registro para cada coluna calculada. Sem calculated, a <expression> roda 1 vez no INSERT/UPDATE e o valor fica persistido — leitura barata.
Sub-tag <fieldOptions> (opcional)
Opcoes pra campo lista (dropdown). Cada <option> tem value (armazenado) e texto (label).
Estende tabelas Sankhya Om. Sem<primaryKey> nem sequenceType.
Declare todos campos usados pela entidade (nativos + custom).
Prefixo exclusivo add-on (ex: XYZ_) nos custom pra evitar conflito.
Dentro de <nativeTable> ha dois cenarios para a tag de instancia, conforme a entidade alvo seja nativa ou nova (ver tabela completa em 1.6):
Cenario A — Instancia nativa Sankhya: <nativeInstance>
Use quando a entidade ja existe no Sankhya nativo (CabecalhoNota, Parceiro, ItemNota, TipoOperacao, Produto, etc.). Combine sempre com isNativeTable = trueeisNativeInstance = true no @JapeEntity.
<nativeInstance> aceita apenas <relationShip> opcional — sem <description>, sem campos adicionais. Os campos vao no <fields> da <nativeTable>.
Cenario B — Instancia nova do addon em tabela nativa: <instance>
Use quando o addon cria uma instancia logica nova sobre uma tabela nativa (ex.: DefensivosAgricolas sobre TGFDFAGR). Combine com isNativeTable = true no @JapeEntity, semisNativeInstance.
Campos pra entidades com correspondencia em sistemas externos. Inclui ID origem (retornado pela plataforma pos-sync) + campo indicando qual plataforma gerou registro. Inclua bloco Auditoria junto:
<fieldname="IDORIGEM"dataType="TEXTO"size="100"readOnly="S"order="2"allowSearch="N"visibleOnSearch="N"><description>Id Origem</description></field><fieldname="PLATAFORMA"dataType="LISTA"size="10"readOnly="S"UITabName="__main"order="3"allowSearch="N"visibleOnSearch="N"><description>Plataforma</description><fieldOptions><optionvalue="A">Plataforma A</option><optionvalue="B">Plataforma B</option></fieldOptions></field><!-- + bloco de Auditoria completo acima -->
1.12 Exemplos Completos
Exemplos completos de XML — tabela com sequência AUTO/MANUAL, PK simples e composta, nativeTable + nativeInstance, nativeTable + instance (addon cria instância lógica em tabela nativa), e exemplo XML→Java integrado — em references/examples.md.
2. Geração XML a partir de @JapeEntity (Java → XML)
Workflow para gerar XML do dicionário a partir de uma @JapeEntity Java existente — fluxo, mapeamento @JapeEntity → tag raiz/instância, mapeamento PK e sequência, mapeamento @Column → <field>, limpeza da entidade Java pós-geração — em references/java-to-xml.md.
3. Geração @JapeEntity a partir de XML (XML → Java)
Workflow para gerar entidade @JapeEntity Java a partir do XML do dicionário — fluxo, mapeamento de tag raiz/instância, PK simples e composta, <field> → @Column, <relationShip> → @OneToMany, PESQUISA com navegação → @OneToOne/@JoinColumn, edge cases (FK que referencia campo não-PK), campos que não vão para Java, anotações Lombok padrão — em references/xml-to-java.md. Exemplo completo XML→Java em references/examples.md.
4.1 Checklist: Criando XML do zero (solicitacao do usuario)
Criar <NOME_TABELA>.xml em datadictionary/.
<table> pra novas ou <nativeTable> pra nativas. Em <nativeTable>, escolher <instance> (instancia nova do addon) ou <nativeInstance> (instancia nativa Sankhya — nome reusa entidade do ERP).
Definir sequenceType e sequenceField conforme estrategia.
Declarar <description> da <table> (vai pra TDDTAB.DESCRTAB, NOT NULL).
Declarar <primaryKey> com campos PK.
Declarar <instance> com nome entidade + <description> propria da instancia. Instancia derivada de nativa? Informar parentInstance (+ resourceId).
Declarar <relationShip> pra cada relacao. Informar relation (default e OneToOne — 1:N exige relation="OneToMany") e <expression> quando houver filtro, force-one-to-one ou nome de aba.
Declarar todos campos + atributos.
Informar allowSearch e visibleOnSearch em todos.
Nomes corretos: UITabName, UIGroupName, nuCasasDecimais, required="S"/"N".
Incluir <expression> pra calculados.
Incluir <fieldOptions> so em LISTA.
Usar dataType="PESQUISA" + targetInstance/targetField/targetType pra lookups.
<description> preenchida em todos <field> (nao vazia). Acentos permitidos — skill encoding ajusta o charset depois.
4.2 Checklist: Gerando XML a partir de entidade Java existente
Pra cada <field> da <primaryKey>, mapear como @Id + @Column(name).
PK composta? Criar @Embeddable com campos, usar @Id no embeddable.
Pra cada <field> dos <fields>, criar campo Java com @Column(name) + tipo inferido.
Pra cada <relation>, criar @OneToMany com @Relationship.
PESQUISA com navegacao: adicionar @OneToOne + @JoinColumn(name, referencedColumnName).
Nao adicionar @Expression, @GeneratedValue, @Option, @Property nem extras.
4.4 Erros Comuns
Erro
Correcao
Usar uiTabName no XML
Sempre UITabName (Pascal Case, UI maiusculo).
Usar precision no XML
Sempre nuCasasDecimais.
Usar required="true" no XML
Sempre required="S" ou required="N".
Omitir allowSearch/visibleOnSearch
Sempre informar, mesmo "N".
Omitir <fieldOptions> em campo lista
Gerar <fieldOptions> com <option> pra cada opcao.
Usar <fieldOptions> em campo CHECKBOX
Remover <fieldOptions>, manter so dataType="CHECKBOX".
<description> vazia ou ausente em <field>
Preencher <description> obrigatorio.
Omitir <description> filha de <table> (so na <instance>)
Adicionar <description> propria de <table>. Sem ela, deploy falha com DESCRTAB NULL em TDDTAB.
Omitir sequenceType na tag <table>
Sempre informar sequenceType (+ sequenceField se AUTO).
Omitir relation em <relation> de uma relacao 1:N
Informar relation="OneToMany". O default do XSD e OneToOne — omitir gera cardinalidade errada sem erro de validacao.
Atributos extras no @Column Java
Manter soname — resto no XML.
Usar @Expression ou @GeneratedValue no Java
Remover — vao pra <expression> e sequenceType no XML.
@JoinColumn com name e referencedColumnName invertidos
name = campo local (na tabela com @JoinColumn). referencedColumnName = campo na referenciada. Ver references/xml-to-java.md, seção "FK que referencia campo nao-PK".
Usar <instance> para instancia nativa Sankhya em <nativeTable>
Usar <nativeInstance>. <instance> faz o builder regravar a entrada no metadata.xml; durante o deploy a instancia e re-mapeada para o owner do addon e quebra regras/validacoes nativas.
Esquecer <nativeInstance> quando o entity Java reusa nome nativo (CabecalhoNota, Parceiro, Produto, etc.)
Trocar <instance> por <nativeInstance> no XML e adicionar isNativeInstance = true no @JapeEntity.
Skills relacionadas
entity — classe Java @JapeEntity que mapeia a tabela definida neste XML
database — dbscript que materializa a tabela no banco
macros — macros do MacroTranslator para SQL portável Oracle/MSSQL no campo <expression>