All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.ssc.parser.ParserInformatString Maven / Gradle / Ivy

Go to download

This is a JSR331 interface for SSC (Software for the Calculation of the Simplex) is a java library for solving linear programming problems v. 3.0.1. SSC was designed and developed by Stefano Scarioli.

The newest version!
package it.ssc.parser;

import it.ssc.log.SscLevel;
import it.ssc.log.SscLogger;
import it.ssc.parser.exception.InvalidInformatStringException;

import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * I nomi dei campi possono iniziare solo con caratteri alfabetici e contenere solo
 * caratteri alfanumerici e "_" (undescore). 
 * 

* * Il formato di lettura e' costituito dal nome del campo e dal tipo. * Tipo consentiti (byte, char , int, long, float, double, boolean , string(lunghezza) * varstring , Date(informat input ). Le date saranno lette come da formato * ma memorizzate in un campo long che esprime in millisecondi l'intervallo di tempo * dal 1970. *

* * Ogni valore sul file di input e' separato da un separatore che sara' impostato nel ref *

* * * Nei diversi formati (libero o a colonna) i valori missing (null sul dataset) sono * caricati tramite l'opzione setMissingValue() e con il valore corrispondente sui dati * che poi viene appunto convertito sulk pdv in null. * Si puo poi, nel caso in qui il campo sia di tipo string o char, scegliere se convertire * questo missing in una seguenza di spazi : aggiungendo {space} si dichiara di mettere * lo spazio al posto del null in fase di scrittura, di default mette null. *

* E' possibile, se i dati caricati sono di tipo string o char , fare in moodo che se il * carattere caricato e' una stringa vuota o costituita di soli spazi, di convertire * questro "blank" in null. Aggiungendo {null} si converte la stringa costituita di * caratteri di tipo spaziatore con null sul dataset di output. * * *

* * Formato libero , esempio : * cognome: string(158), nome: string(256), eta: int ,sposato: boolean, giorno_matrimonio: * date(gg/mm/aa) *
* Il valore booleano puo essere rappresentato sul file con ("true","false") o ("f","t"), * indipendentemente dall'essere maiuscolo o minuscolo. Nel caso di campo String , tra * parentesi tonde, si definisce la lunghezza massima del campo che verra scritto sul * dataset di output, per cui se il record recuperato e' piu' lungo verra' troncato poco * prima di essere salvato sul dataset, anche se nel passo di data mantiene la sua lunghezza. * Nel caso di formato libero si puo impostare il separatore, ovvero il carattere o sequenza * di caratteri che verrra utilizzata per separare i dati in input. *
Verificare con attenzione caratteri come \t etc. * * *
*
* * Formato a colonna : * cognome: string[1-13]{SPACE}, nome: string(5)[14-20], eta:int[21-30] ,sposato:boolean[34], * giorno_matrimonio:date(gg/mm/aa)[35-45] * *
* I valori tra perentesi quadre rappresentano il range di colonne che viene letto. Nel caso * che in una colonna di tipo string non si trovi nessun valore ma uno spazio o al contrario * il valore di missing value (.), verra caricato rispettivamente il valore di " " o null. * Se si vuole cambiare impostazione nella memorizzazione dei null, occorre aggiungere l'istruzione * di non valorizzazione dei null : {SPACE}; Se invece ci sono dei blank e si vuole metterli a null * in fase di scrittura del dataset si imposta {NULL}. Questo solo per stringhe e character *
* Nel caso del secondo string, il valore viene letto dalle colonne 14 alla 20 comprese, pero * poi il valore viene memorizzato sul dataset in un campo di lunghezza 5, anche se durante il passo * di data la sua lunghezza e' sempre di lunghezza 7. * *
*
* * Formato misto : * cognome: string, nome: string[14-20], eta:int ,sposato:boolean[34], giorno_matrimonio:date(gg/mm/aa)[35-45] * * * Nel formato misto , dopo ogni campo letto, il cursore di lettura si pone immediatamente dopo il campo * precedentemente letto, a quel punto il campo successivo viene letto a formato libero o no, a seconda del * tipo di dichiarazione. * *
*
* * * Il formato gestisce i salti record o salto campi o leggere lo stesso record logico presente su piu righe : *
a) @@ fa leggere sullo stesso pdv i dati della righa successiva del file. Naturalmente * non ha senso metterlo alla fine dell'istruzioni di importazione. In quanto non ci sarebbero piu' * campi da leggere. * @@ equivale a #1 *
b) @n fa puntare il cursore alla colonna n sul riga fisica attualmente caricata dal file. * *
c) #n fa puntare alla n-esima successiva riga del file di input. Puo essere messo in mezzo alla istruzione * di importazione andando avanti nelle operazioni di lettura sullo stesso pdv; se invece messo alla * fine fa puntare alla n-esima riga successiva e poi inizia un altro record. Se metto ad esempio alla * fine dell'istruzione di importazione #1, punta alla riga successsiva, ma poi inizia il record successivo alla riga in quanto * l'istruzione di input essendo terminata passa al record successivo. * Puo essere messo in mezzo o alla fine. *
d) ## riservato *
e) @ blocco del record in caso di successive letture (condizionali) *
f) # riservato * *
E' opzionale combinare , in una seguenza successiva, solo una sola istruzione che inizia * per cancelletto, con una che inizia per chiocciola. Ad esempio : *
* cognome: string, nome: string[14-20], @@, @34, eta:int ,sposato:boolean *
* un istruzione del genere non ha effetto :
* cognome: string, nome: string[14-20],#34,@@ , eta:int ,sposato:boolean
* in quanto fa puntare il cursore alla colonna 34 , ma poi va alla righa successiva per continuare * a leggere lo stesso record su una nuova riga * * *

* * * @author Stefano Scarioli * @version 1.0 * @since version 1.0 */ public class ParserInformatString extends GenericParser { private static final Logger logger=SscLogger.getLogger(); /** * L'operazione di parser della stringa deve dare luogo a due tipi di informazioni. * Una e' data dal tipo di campi letti, l'altra sono le azioni che deve eventualmente * effettuare nelle operazioni di lettura (direttive @ / # ). Simuliamo : * * Effettuo la separazione dei token con la virgola, */ public void parser(String informat_string) throws InvalidInformatStringException { this.list_input_step=new ArrayList(); //imposto come delimitatore la virgola per separare gli input step Scanner scanner = new Scanner(informat_string).useDelimiter(","); while (scanner.hasNext()) { //prendo il valore e verifico se e' relativo alla dichiarazione //di una variabile o a un'istruzione @ o # String input_step = scanner.next().trim(); //pattern per la dichiarazione di variabili Pattern pattern_dich_var = Pattern.compile("(\\p{Alpha}\\w*\\s*):(.+)"); Matcher matcher_dich_var = pattern_dich_var.matcher(input_step); //pattern per le istruzioni @ o # Pattern pattern_azioni = Pattern.compile("(#{1,2}|@{1,2})|([@#]\\d+)"); Matcher matcher_azioni = pattern_azioni.matcher(input_step); //pattern per i gruppi di variabili Pattern pattern_group_var = Pattern.compile("((\\p{Alpha}+)(\\d+)\\s*\\-\\s*(\\p{Alpha}+)(\\d+)\\s*):(.+)"); Matcher matcher_group_var = pattern_group_var.matcher(input_step); if (matcher_dich_var.matches()) { String nome_variabile =matcher_dich_var.group(1).trim(); if(!nome_variabile.matches("[A-Z_0-9]+")) { logger.log(SscLevel.WARNING,"Il nome della variabile '"+nome_variabile +"' non e' in maiuscolo."); logger.log(SscLevel.NOTE,"Per uniformita' tutte le variabili devono essere maiuscole: il nome verra'"+ " convertito in '"+nome_variabile.toUpperCase()+"'"); } nome_variabile=nome_variabile.toUpperCase(); if(existNameDichiarationVar(nome_variabile)) { throw new InvalidInformatStringException("Variabile "+nome_variabile+" gia dichiarata."); } InputSubDichiarationVar single_input_dich_var=new InputSubDichiarationVar(); single_input_dich_var.setNameVar(nome_variabile); String type_variabile = matcher_dich_var.group(2).trim(); parseType(type_variabile,single_input_dich_var); this.list_input_step.add(single_input_dich_var); } else if (matcher_group_var.matches()) { String nome_variabile_da =matcher_group_var.group(2).trim(); String nome_variabile_a =matcher_group_var.group(4).trim(); String num_da =matcher_group_var.group(3).trim(); String num_a =matcher_group_var.group(5).trim(); String type_variabile = matcher_group_var.group(6).trim(); /* for(int a=0;a<=matcher_group_var.groupCount();a++) { System.out.println("KKKKK>>>>>" + matcher_group_var.group(a) + "<-:"+a); } */ if(!nome_variabile_da.equals(nome_variabile_a)) { throw new InvalidInformatStringException("Range variabili da "+nome_variabile_da+num_da+" a "+nome_variabile_a+num_a+" devono avere lo stesso prefisso alfabetico."); } int num_var_da=Integer.parseInt(num_da); int num_var_a=Integer.parseInt(num_a); if(num_var_da >= num_var_a) { throw new InvalidInformatStringException("Range variabili da "+nome_variabile_da+num_da+" a "+nome_variabile_a+num_a+" deve partire da un numero intero minore ad un numero intero maggiore."); } if(!nome_variabile_da.matches("[A-Z_0-9]+")) { logger.log(SscLevel.WARNING,"Il nome del range di variabili '"+nome_variabile_da +"' non e' in maiuscolo."); logger.log(SscLevel.NOTE,"Per uniformita' tutte le variabili devono essere maiuscole: il nome verra'"+ " convertito in '"+nome_variabile_da.toUpperCase()+"'"); } nome_variabile_da=nome_variabile_da.toUpperCase(); for(int a=num_var_da;a<=num_var_a;a++) { String single_var_n=nome_variabile_da+a; if(existNameDichiarationVar(single_var_n)) { throw new InvalidInformatStringException("Variabile "+single_var_n+" gia dichiarata."); } InputSubDichiarationVar single_input_dich_var=new InputSubDichiarationVar(); single_input_dich_var.setNameVar(single_var_n); parseType(type_variabile,single_input_dich_var); this.list_input_step.add(single_input_dich_var); } } else if (matcher_azioni.matches()) { InputSubDichiarationAction single_input_dic_act=new InputSubDichiarationAction(); parseAction(input_step,single_input_dic_act); this.list_input_step.add(single_input_dic_act); } else { throw new InvalidInformatStringException("ERRORE. Errato formato di input o uso di caratteri non consentiti" +informat_string ); } } scanner.close(); } private void parseAction(String string_to_parse, InputSubDichiarationAction single_input_step) throws InvalidInformatStringException { Pattern pattern_azioni = Pattern.compile("((#{1,2})|(@{1,2}))|(([@#])(\\d+))"); Matcher matcher_azioni = pattern_azioni.matcher(string_to_parse); if (matcher_azioni.matches()) { for(int a=0;a<=matcher_azioni.groupCount();a++) { //System.out.println("KKKKK>>>>>" + matcher_azioni.group(a) + "<-:"+a); } if(matcher_azioni.group(3)!=null) { single_input_step.setReadLineNext(true); } if(matcher_azioni.group(4)!=null) { if(matcher_azioni.group(5).equals("@")) { int colonna = Integer.parseInt(matcher_azioni.group(6)); if(colonna==0) throw new InvalidInformatStringException("L'indice di colonna deve essere maggiore di zero"); single_input_step.setPointColumn(colonna); } else if(matcher_azioni.group(5).equals("#")) { int row = Integer.parseInt(matcher_azioni.group(6)); if(row==0) throw new InvalidInformatStringException("L'indice di riga deve essere maggiore di zero"); single_input_step.setPointRow(row); } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy