2009-06-25 4 views
6

Je construis un outil de traduction de données à usage général pour l'entreprise en utilisant Java 5. Les différents départements utilisent des formats différents pour les informations de coordonnées (latitudes/longitudes), et ils veulent voir les données dans leur propre format. Par exemple, les coordonnées de la Maison Blanche au format DMS sontUn moyen de spécifier des chaînes de modèle qui gèrent l'analyse et la mise en forme pour des objets arbitraires?

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

Mais peuvent aussi être exprimés en:

385355,133/- Je souhaite représenter le modèle requis par chaque système sous la forme d'une chaîne, puis utiliser ces modèles pour analyser les données d'instance du système d'entrée et également utiliser ce modèle lors du formatage d'une chaîne pour consommation par le système de sortie. Il ressemble donc à un problème de formatage date/heure, pour lequel le JDK fournit java.text.SimpleDateFormat qui vous permet de convertir parmi différents modèles de date/heure, qui sont définis par des chaînes telles que "AAAA-MM-JJ" "ou" MM/JJ/AA ". Ma question est la suivante: est-ce que je dois construire complètement ce système de coordonnées à partir de zéro, ou y a-t-il un bon outil général ou une approche bien définie que je peux utiliser pour me guider dans cette entreprise?

+0

question Nice, je aime particulièrement que vous le titre pour le cas général. – BCS

+0

Merci à tous ceux qui ont offert des suggestions. Je me suis retrouvé avec une sorte de combinateur parser unique. Pas le plus élégant mais il fait le travail. La chaîne de format pour 38 ° 53 '55.133 "N, 77 ° 02' 15.691" W (aka DMS, ou degrés minutes secondes) a fini par $ lat {$ d {} ° $ m {} '$ s {places = 3} "$ h}, $ lon {$ d {} ° $ m {} '$ s {places = 3}" "$ h}. La chaîne pour 38.898648, -77.037692 (alias DD, ou degrés décimaux format à six endroits) fini $ lat {$ dd {places = 6 ~ showNegativeSign = true}}, $ lon {$ dd {places = 6 ~ showNegativeSign = true}} Et bien sûr, une myriade d'autres combinaisons sont possibles, ce que je recherchais. –

Répondre

1

Si je lis correctement, vous parlez du problème posé par le motif Interpreter, mais sorte d'aller dans les deux directions.

Il existe des moyens simples d'obtenir de jolies interfaces génériques, pour que le reste du système fonctionne. Ma recommandation sur c'est quelque chose comme:

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

Cependant, il y a quelques obstacles avec des applications concrètes. Pour votre exemple de date, vous devrez peut-être traiter avec "09/09/09", "9 septembre 09", "Septembre 9th, 2009". Le premier "genre" de date est simple - les nombres et les symboles de séparation, mais l'un ou l'autre des deux autres est assez méchant. Honnêtement, faire quelque chose de totalement générique (qui pourrait déjà être mis en boîte) n'est probablement pas raisonnable, donc je recommande ce qui suit. Je l'attaquerais sur deux niveaux, dont le premier est assez simple avec regex et la chaîne de format: hacher la chaîne de données dans les choses qui vont devenir des données brutes. Vous fournissez quelque chose comme "D */M */YY" (ou "M */D *") pour le premier, "D * MMM YY" pour le second, et "Mm + D * e *, YYYY" pour le dernier, où vous avez défini dans vos données certains symboles réservés (D, M, Y, interprétations évidentes) et pour tous les types de données (* caractères multiples possibles, + sortie "pleine", e caractères étrangers définis) - ces symboles évidemment être spécifique à votre application. Ensuite, votre substance regex écraserait la chaîne, tout ce qui est associé à chaque caractère réservé dans les champs de données individuels, et enregistrerait la partie de la décoration (virgules, etc) dans une chaîne de mise en forme. Ce premier niveau peut être assez générique - chaque type de données (par exemple, date, coordonnée, adresse) a des symboles réservés (qui ne chevauchent aucun caractère de formatage), et tous les types de données ont des symboles partagés. Peut-être que l'interface interpréteur aurait également des méthodes public List<Character> reservedSymbols() et , ou des champs peut-être garantis, de sorte que vous pouvez faire du diviseur une classe externe et transmettre les résultats.

Le deuxième niveau est moins facile, car il arrive à la partie qui ne peut pas être générique. Basé sur le format des symboles réservés, les champs individuels doivent savoir comment se présenter. À l'exemple de date, MM indiquerait le mois à imprimer comme (01, 02, ... 12), M * comme (1, 2, ... 12), MMM comme (JAN, FEB, ... DEC) , Mmm as (Jan, Fév, ... Dec), etc. Si votre entreprise a été quelque peu cohérente ou ne s'aventure pas trop loin des représentations standard, alors le codage à la main de chacune d'entre elles ne devrait pas être trop mauvais (et en fait, il y a probablement des moyens intelligents dans chaque type de données pour réduire le code répliqué). Mais je ne pense pas qu'il soit pratique de généraliser tout cela - je veux dire, représenter pratiquement quelque chose qui peut être présenté comme un nombre ou des caractères (comme des mois) ou des données entières qui peuvent être déduites à partir de données partielles.) ou comment obtenir des représentations tronquées à partir des données (par exemple, la troncature pour l'année est aux deux derniers chiffres vice et la plupart des nombres normaux tronquer à deux chiffres principaux) va probablement prendre aussi longtemps que l'écriture de ces cas, mais je suppose Imaginez des cas de votre application, le compromis pourrait en valoir la peine. La date est vraiment un exemple difficile, mais je peux certainement voir des choses tout aussi délicates à venir pour d'autres sortes de données.

Résumé:

est un visage -Il générique facile, vous pouvez mettre sur votre problème, de sorte que le reste de votre application peut être codé autour d'elle.

-il y a une analyse de premier passage assez simple et générique, avec des symboles réservés universels, puis des symboles réservés pour chaque type de données; assurez-vous que ceux-ci ne sont pas en collision avec des symboles qui apparaîtront dans le formatage

est une étape -Il y codage final un peu fastidieux pour des bits de données

+0

Réponse très complète. Pas loin de ce que j'ai fini avec. Voir le commentaire ci-dessus. –

0

un coup d'oeil à JScience, en particulier this class

+0

Merci, mais je suis à la recherche d'une solution plus générale au problème plus général, car il y a d'autres bêtes que les dates et les coordonnées qui auront aussi différents formats parmi lesquels cet outil doit traduire –

0

# 1. Je pense que la définition d'un format interne commun serait utile. Vous convertissez à partir du format d'entrée à interne et à un certain nombre de formats requis par la sortie. # 2. RegEx serait mon choix pour implémenter le convertisseur.

+0

Je ne suis pas sûr que regex est à la hauteur la tâche ... Je pense à ce problème comme un autre cas de problème de mise en forme de date.Je veux une chaîne de modèle un peu comme "mm/jj/aaaa" sauf que ce sera quelque chose comme "ddmmss.sss." Et je préfère ne code pas quelque chose qui est si spécifique aux coordonnées, je suis loo roi pour un outil général ou une approche qui résout ce problème pour toutes sortes d'objets arbitraires qui ont une représentation de chaîne. Je veux une solution au problème plus général, dont le formatage des dates et le formatage des coordonnées ne sont que des exemples spécifiques. –

0

Une solution consisterait à définir un système de spécification à partir duquel l'expression regex d'entrée (ou autre) et la chaîne de format de sortie peuvent être dérivées. Si vous avez un système regex qui permet des groupes de capture nommés et un système de formatage qui permet des arguments non séquentiels, cela peut être aussi simple que de recoder l'échappement et l'indexation de l'un dans l'autre. Je ne connais pas Java, donc je vais laisser les détails au lecteur.

0

Pour moi, il semble que vous envisagiez un cadre plus large pour votre solution.

Le problème principal que je vois est que vous cherchez une balle d'argent pour assommer n'importe quel type de données. Mais comme Java va la manière la plus cohérente est d'envelopper regex. Chaque type d'objet va avoir besoin d'une liste de chaînes définissant les formats acceptés. Ainsi, la date pourrait avoir beaucoup, les coordonnées ont 2, etc.

Ces chaînes peuvent être regex soit (douloureuse mais cohérente et acceptée) ou vous pouvez écrire votre propre bibliothèque de conversion pour aller quelque chose comme ceci:

Converter c = nouveau convertisseur();
Format Format Format = new FormatString ("ddmmss.sss");
format.AddRegexEquivalent ("d", "\\ d");
format.AddRegexEquivalent ("m", "\\ d");
format.AddRegexEquivalent ("s", "\\ d");
c.AddFormatString (format);

si (c.ConvertString ("385355,133")) {

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


sortie:
55,133

Ce sera difficile, mais je pense que c'est plus ce que vous cherchez. Le convertisseur doit traduire les lettres données en équivalents regex. (pour commencer, vous pouvez simplement remplacer en masse), puis concaténer toutes les valeurs pour chaque lettre. Je voudrais retourner une chaîne de GetData, puis utiliser un Parse *** à partir de là, plus facile à gérer.

0

La classe TextTemplate dans wicket génère une chaîne en interpolant une chaîne "template" avec une carte de paires clé-valeur. Vous pouvez utiliser la chaîne de modèle de sortie comme base, avec une variable à interpoler à partir de la carte pour chaque valeur (longitude degrés, minutes, peu importe). Cela ne fera pas de conversion bidirectionnelle, mais vous pourriez jeter un coup d'œil et voir si cela vous aide.

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

est ici la source, de leur svn:

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

Questions connexes