2009-06-25 12 views
6

Sto costruendo uno strumento di traduzione di dati generici per uso aziendale interno, utilizzando Java 5. I vari reparti utilizzano formati diversi per informazioni sulle coordinate (latitudini/longitudini) e desiderano visualizzare i dati nel loro formato. Ad esempio, le coordinate della Casa Bianca in formato DMS sonoUn mezzo per specificare stringhe di pattern che guidano l'analisi e la formattazione per oggetti arbitrari?

38 ° 53' 55.133" N, 77 ° 02' 15.691" W

Ma possono anche essere espressi come:

385355,133/- 0770215.691

Voglio rappresentare il modello richiesto da ogni sistema come una stringa, e quindi utilizzare quei modelli per analizzare i dati di istanza dal sistema di input e anche utilizzare tale modello quando si formatta una stringa per il consumo dal sistema di output.

Quindi non è diverso da un problema di formattazione di data/ora, per il quale JDK fornisce java.text.SimpleDateFormat che consente di convertire tra diversi modelli di data/ora, definiti da stringhe come "AAAA-MM-GG "o" MM/GG/AA ".

La mia domanda è, devo creare questa cosa di CoordinateFormat completamente da zero, oppure c'è un buon strumento generale o un approccio ben definito che posso usare per guidarmi in questa impresa?

+0

Nizza domanda, mi piace particolarmente che titolo per il caso generale. – BCS

+0

Grazie a tutti coloro che hanno offerto suggerimenti. Ho finito con una specie di combinatore parser unico. Non è il più elegante, ma ha il compito. La stringa di formato per 38 ° 53 '55.133 "N, 77 ° 02' 15.691" W (ovvero DMS, o gradi minuti secondi) ha finito con $ lat {$ d {} ° $ m {} '$ s {places = 3} "$ h}, $ lon {$ d {} ° $ m {} '$ s {places = 3}" "$ h}. La stringa per 38.898648, -77.037692 (ovvero DD o formato decimale in sei posizioni) $ long {$ dd {places = 6 ~ showNegativeSign = true}}, $ lon {$ dd {places = 6 ~ showNegativeSign = true}} E ovviamente sono possibili una miriade di altre combinazioni, che è quello che cercavo. –

risposta

1

Se ho letto bene, stai parlando del problema affrontato dal pattern Interpreter, ma una sorta di andare in entrambe le direzioni.

Ci sono alcuni modi semplici per ottenere delle belle interfacce generiche, in modo da poter far funzionare il resto della cosa. La mia raccomandazione su che è qualcosa di simile:

public interface Interpreter<OutputType> { 
public void setCode(String coding); 
public OutputType decode(String formattedData); 
public String encode(OutputType rawData); } 

Tuttavia, ci sono un paio di ostacoli con implementazioni concrete. Per il tuo esempio di data, potresti dover gestire "9/9/09", "9 settembre 09", "9 settembre 2009". Il primo "tipo" di data è semplice: numeri e simboli di divisori, ma uno degli altri due è piuttosto cattivo. Onestamente, fare qualcosa di totalmente generico (che potrebbe già essere in scatola) probabilmente non è ragionevole, quindi consiglio quanto segue.

Lo attaccherei su due livelli, il primo dei quali è piuttosto semplice con espressioni regolari e stringa di formato: inserire la stringa di dati nelle cose che diventeranno dati non elaborati. Forniresti qualcosa come "D */M */YY" (o "M */D *") per il primo, "D * MMM YY" per il secondo e "Mm + D * e *, YYYY" per l'ultimo, in cui hai definito nei tuoi dati alcuni simboli riservati (D, M, Y, interpretazioni ovvie) e per tutti i tipi di dati (* più caratteri possibili, + "pieno", e caratteri estranei definiti) - questi simboli ovviamente essendo specifico per la tua applicazione. Quindi le tue regex roomp formeranno la stringa, alimentando tutto ciò che è associato a ciascun carattere riservato ai singoli campi di dati e salvando la parte di decorazione (virgole, ecc.) In una stringa di formattazione.

Questo primo livello può essere abbastanza generico: ogni tipo di dati (ad es. Data, coordinate, indirizzo) ha simboli riservati (che non si sovrappongono a nessun carattere di formattazione) e tutti i tipi di dati hanno alcuni simboli condivisi. Forse l'interfaccia Interpreter avrebbe anche i metodi public List<Character> reservedSymbols() e public void splitCode(List<String> splitcodes), o forse i campi garantiti, in modo da poter rendere il divisore una classe esterna e passare i risultati.

Il secondo livello è meno facile, perché raggiunge la parte che non può essere generica. In base al formato dei simboli riservati, i singoli campi devono sapere come presentarsi. Per l'esempio della data, MM direbbe al mese di stampare come (01, 02, ... 12), M * come (1, 2, ... 12), MMM come (JAN, FEB, ... DEC) , Mmm come (Jan, Feb, ... Dec), ecc. Se la tua azienda è stata un po 'coerente o non si avventura troppo lontano dalle rappresentazioni standard di cose, allora la codifica manuale di ciascuna di queste non dovrebbe essere troppo brutta (e infatti, ci sono probabilmente modi intelligenti all'interno di ogni tipo di dati per ridurre il codice replicato). Ma non penso che sia pratico generare tutto questo - voglio dire, praticamente rappresentare quel qualcosa che può essere presentato come un numero o caratteri (come mesi) o interi dati che possono essere dedotti da dati parziali (ad esempio, secolo dall'anno) o come ottenere rappresentazioni troncate dai dati (ad esempio, il troncamento per l'anno è per le ultime due cifre, i numeri più normali che troncano a due cifre iniziali) probabilmente prenderà il tempo necessario per scrivere a mano quei casi, anche se credo di poter Immagina casi della tua applicazione che il trade-off potrebbe valerne la pena. La data è davvero un esempio complicato, ma posso certamente vedere cose ugualmente insidiose in arrivo per altri tipi di dati.

Sommario:

-C'è un volto generico semplice si può mettere sul vostro problema, in modo che il resto della vostra applicazione può essere codificato intorno ad esso.

-questo è un analizzatore di primo passaggio abbastanza semplice e generico, con simboli universali riservati e simboli riservati per ciascun tipo di dati; assicurarsi che questi non si scontrano con i simboli che compariranno nella formattazione

-C'è una fase un po 'noioso finale di codifica per i singoli bit di dati

+0

Risposta molto accurata. Non lontano da quello che ho finito. Vedi il commento sopra. –

0

un'occhiata al JScience, soprattutto this class

+0

Grazie, ma sto cercando una soluzione più generale al problema più generale, dal momento che ci sono altre bestie oltre a date e coordinate che avranno anche diversi formati tra cui questo strumento deve tradurre. –

0

# 1. Penserei che definire un formato interno comune sarebbe utile. Dovresti convertire dal formato di input a quello interno e in qualsiasi numero di formati, come richiesto dall'output. # 2. RegEx sarebbe la mia scelta per implementare il convertitore.

+0

Non sono sicuro che regex è fino a il compito ... Penso a questo problema come a un altro caso del problema di formattazione della data: voglio una stringa del modello molto simile a "mm/gg/aaaa" tranne che sarà qualcosa come "ddmmss.sss". non codificare qualcosa che è così specifico per le coordinate, lo sono re per uno strumento o un approccio generale che risolve questo problema per tutti i tipi di oggetti arbitrari che hanno una rappresentazione di stringa. Voglio una soluzione al problema più generale, di cui la formattazione della data e la formattazione delle coordinate sono solo esempi specifici. –

0

Una soluzione sarebbe quella di definire un sistema di specifiche da cui sia possibile ricavare sia la regex di input (o qualsiasi altra cosa) sia la stringa di formato di output. Se si dispone di un sistema regex che consente i gruppi di acquisizione denominati e un sistema di formattazione che consente argomenti non sequenziali, ciò potrebbe essere semplice come ricodificare l'escape e l'indicizzazione di uno nell'altro. Non conosco la Java di Java, quindi lascerò i dettagli al lettore.

0

Per me, sembra che si stia esaminando una struttura più ampia per la soluzione.

Il problema principale che vedo è che stai cercando un proiettile d'argento per eliminare qualsiasi tipo di dati. Ma come dice java, il modo più coerente è avvolgere l'espressione regolare. Ogni tipo di oggetto avrà bisogno di un elenco di stringhe che definiscono i formati accettati. Quindi la data potrebbe avere molti, coordinate hanno 2, ecc

Queste stringhe possono essere sia espressione regolare (doloroso, ma coerente e accettato) o si può scrivere il proprio libreria di conversione di andare o meno così:

Converter c = nuovo convertitore();
FormatString format = new FormatString ("ddmmss.sss");
format.AddRegexEquivalent ("d", "\\ d");
format.AddRegexEquivalent ("m", "\\ d");
format.AddRegexEquivalent ("s", "\\ d");
c.AddFormatString (formato);

se (c.ConvertString ("385.355,133")) {

    System.out.println (c.GetData ("d"));
    System.out.println (c.GetData ("m"));
    System.out.println (c.GetData ("s"));
}


uscita:
55,133

Sarà dura, ma penso che è più quello che stai cercando. Il convertitore deve tradurre le lettere indicate in equivalenti di regex. (come inizio si può sostituire la massa) e quindi concatenare tutti i valori per ogni lettera. Vorrei restituire una stringa da GetData e quindi utilizzare un *** Parse da lì, più facile da gestire.

0

La classe TextTemplate in wicket genera una stringa interpolando una stringa "modello" con una mappa di coppie chiave-valore. È possibile utilizzare la stringa del modello di output come base, con una variabile da interpolare dalla mappa per ciascun valore (gradi di longitudine, minuti, qualunque sia). Questo non farà la conversione a due vie, ma potresti dare un'occhiata e vedere se ti aiuta.

http://wicketstuff.org/wicket13doc/org/apache/wicket/util/template/TextTemplate.html

Ecco la fonte, dalla loro svn:

http://svn.apache.org/repos/asf/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/template/TextTemplate.java

Problemi correlati