Sfondo
Un progetto comporta la conversione di una mappa di espressioni relazionali ( rxm ) in un'istruzione XML / SQL. La mappa è simile a:
root > people, # "root" keyword starts the document
person > person, # maps table context to a node
.first_name > first, # maps a column to a node
.last_name > name/last, # maps a column to an ancestor node
.age > @age, # @ maps a column to an attribute node
account.person_id +> person.person_id, # +> performs an INNER JOIN
account > account, # context is now "account" node
.id > @id, # account id attribute
^, # pop stack to previous context
address > address, # switch context to "address" node
.*, # .* globs all columns
account.person_id -> company.person_id, # -> performs an OUTER JOIN
; # Starts the optional WHERE clause
Il rxm viene convertito in classi Java usando ANTLR.
Camminando attraverso AST utilizza un pattern Visitor che chiama i metodi per entrare e uscire da varie parti dell'albero. Ad esempio:
@Override
public void enterRoot( QueryParser.RootContext context ) {
System.out.println( "Root: " + context.getChild(2).getText() );
}
@Override
public void exitRoot( QueryParser.RootContext context ) {
System.out.println( "<< root" );
}
Problema
Il codice deve generare un'istruzione XML / SQL sulla falsariga di:
XMLROOT (
XMLELEMENT (
NAME people,
XMLELEMENT (
NAME person,
XMLATTRIBUTE( ... )
)
),
VERSION ’1.0’,
STANDALONE YES
)
Nel momento in cui vengono chiamati enterRoot
o exitRoot
, non è noto se ci sarà un'altra linea mappata usando rxm . Idealmente, mi piacerebbe scrivere:
@Override
public void enterRoot( QueryParser.RootContext context ) {
String root = context.getChild(2).getText();
getStack().push( "SELECT XMLROOT( XMLELEMENT( NAME " + root );
getStack().push( "VERSION '1.0', STANDALONE YES )" );
}
Domanda
L'utilizzo di uno stack sembra essere un buon modo per generare la query in base al modello di visitatore.
Quale struttura dati useresti per convertire una mappa lineare in una query gerarchica?
Sarebbe possibile, ad esempio, inserire semplicemente l'ultimo elemento dallo stack (ad esempio, la riga contenente la parentesi di chiusura), archiviarlo localmente, quindi reinserirlo in seguito?