Mar 262018
 

Ci troviamo nel mondo Spring dove possiamo far creare e far gestire le singole entità attraverso Spring Data.

Durante la fase di analisi è stato ipotizzato correttamente che abbiamo 3 Oggetti Java che possono estendere una Classe Astratta di riferimento. Se volessimo utilizzare questa rappresentazione avremmo una situazione in cui la classe astratta rappresenterebbe anche delle Entity (le classi che la estendono). Purtroppo questa situazione è tanto semplice nella realizzazione quanto complessa nell’utilizzo, ma di seguito ripoto un esempio che potrebbe illuminare un caso d’uso.

Il problema delle Survey

Supponiamo di voler realizzare un sistema che gestisca delle Survey (sia domande che risposte da parte degli utenti) come quell che ci propone Google Drive quando ci permette di realizzare delle Form.

Dobbiamo definire il nostro elemento base (rappresentazione delle singole domande) e successivamente andremo a definire più nello specifico i singoli tipi di domanda. Di seguito uno schema che potrebbe rappresentare il sistema nel modo migliore:

       SimpleQuestion (Abstract Class)
                     |
    +----------------+----------------+
    |                |                |
    |                |                |
Paragraph     MultipleChoice     LinearScale

Cosa rappresentano i singoli elementi sopra riportati?

  • SimpleQuestion: rappresentazione della domanda, ovvero quella parte di codiche che ha come property la domanda (il testo della domanda)
  • Paragraph: Rappresentazione della domanda a risposta aperta
  • MultipleChoise: Rappresentazione della domanda a risposta multipla (sia in checkbox che in radio button)
  • LinearScale: Rappresentazione della domanda che ha come risposta un valore (tipicamente una valutazione)

Ecco come verrà scritto il codice:

@Entity
@Inheritance
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes({
        @Type(value = Paragraph.class),
        @Type(value = MultipleChoice.class),
        @Type(value = LinearScale.class),
})
public abstract class SimpleQuestion implements Serializable {
 
    @javax.persistence.Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    @NotNull
    private String question;
 
    public SimpleQuestion() {
 
    }
 
    public SimpleQuestion(Long id, String question) {
        this.id = id;
        this.question = question;
    }
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getQuestion() {
        return question;
    }
 
    public void setQuestion(String question) {
        this.question = question;
    }
}

Rappresentazione delle domande a risposta aperta

@Entity
public class Paragraph extends SimpleQuestion {
    public Paragraph(){}
    @JsonCreator
    public Paragraph(@JsonProperty("id")Long id, @JsonProperty("question")String question) {
        // JSON Rappresentation
        super(id, question);
    }
}

Rappresentazione delle domande a risposta multipla

@Entity
public class MultipleChoice extends SimpleQuestion {
 
    @NotNull
    private String mcType;
 
    @OneToMany(cascade = CascadeType.ALL)
    private Set options;
 
    public MultipleChoice(){}
 
    @JsonCreator
    public MultipleChoice(@JsonProperty("id")Long id, @JsonProperty("question")String question,
                          @JsonProperty("mcType")String mcType, @JsonProperty("options")Set options) {
        // JSON Rappresentation
        super(id, question);
        this.mcType = mcType; //tipo di risposta, se radio o check
        this.options = options; //elenco delle risposte
    }
 
    public String getMcType() {
        return mcType;
    }
 
    public void setMcType(String mcType) {
        this.mcType = mcType;
    }
 
    public Set getOptions() {
        return options;
    }
 
    public void setOptions(Set options) {
        this.options = options;
    }
}
@Entity
public class Option {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    @NotNull
    private String response; // singola risposta della MultipleChoise
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getResponse() {
        return response;
    }
 
    public void setResponse(String response) {
        this.response = response;
    }
 
}

Rappresentazione delle domande per una valutazione

@Entity
public class LinearScale extends SimpleQuestion {
 
    @NotNull
    private Integer maxValue; //massimo valore che può avere la scala per la valutazione
 
    public LinearScale(){}
 
    @JsonCreator
    public LinearScale(@JsonProperty("id")Long id, @JsonProperty("question")String question,
                          @JsonProperty("maxValue")Integer maxValue) {
        // JSON Rappresentation
        super(id, question);
        this.maxValue = maxValue;
    }
 
    public Integer getMaxValue() {
        return maxValue;
    }
 
    public void setMaxValue(Integer maxValue) {
        this.maxValue = maxValue;
    }
 
}

Da notare il valore type nella SimpleQuestion, questa property serve a definire la tipologia di domanda quando viene eseguita una POST per creare una survey. Infatti il servizio rest da realizzare con la metodologia Spring dovrà essere chiamato come segue

curl -i -X POST -H "Content-Type": "application/json" http://localhost:8080/survey-spring-rest-module/api/survey/save
{
  "simpleQuestions": [
    {
      "type" : "Paragraph",
      "question": "metti il tuo nome"
    },
    {
      "type" : "MultipleChoice",
      "question": "Quale colore preferisci?",
      "mcType": "radio",
      "options": [
        {
          "response": "Rosso"
        },
        {
          "response": "Giallo"
        },
        {
          "response": "Blue"
        }
      ]
    },
    {
      "type" : "LinearScale",
      "maxValue": 10,
      "question": "Come valuti questa survey?"
    },
    {
      "type" : "MultipleChoice",
      "question": "Quali parole ti identificano?",
      "mcType": "checkbox",
      "options": [
        {
          "response": "Ingegnere"
        },
        {
          "response": "Sviluppattore"
        },
        {
          "response": "Spazzino"
        }
      ]
    }
  ],
  "title": "questa è una survey"
}

Conclusioni

In questo modo siamo riusciti a rappresentare una survey in manire dinamica, dove il type definisce il tipo di domanda e la parte frontend sarà in grado di visualizzare la pagina dedicata alle survey.

 

Edit per gestire i dtype

Potete notare che come informazione utilizzando le ricerche tramite Spring Data ritorni un valore chiamato type (sarebbe il valore nel Data Base che corrisponde all’attributo dtype).

Utilizando una custom query in Spring Data potrebbe non ritornare tale informazione a meno che non impostiate tale informazione come segue:

@Column(insertable = false, updatable = false)
 
private String dtype;
Dec 052017
 

Sviluppando applicazioni iPhone può capitare che la metodologia di mettere a disposizione nuove applicazioni di test tramite Testflight non sia la strada percorribile. Può capitare che sia necessario inoltrare il file my_iphone_application.ipa e farla installare direttamente sul device.

L’ultima versione di iTunes non permette di gestire il proprio iPhone come prima, infatti non è più possibile gestire le schermate e le varie applicazioni installate. E’ possibile, sempre tramite iTunes, installare la nostra applicazione di test ne seguente modo:

  1. Disinstallare dal proprio iPhone l’applicazione se già presente
  2. Collegare il proprio iPhone al nostro Mac e visualizzarlo tramite iTunes
  3. Trascinare la nuova applicazione, my_iphone_application.ipa, sopra il device visibile nel menù di sinistra di iTunes

Con questa procedura avete installato la vostra applicazione direttamente sul vostro iPhone.

 

Buon lavoro a tutti

iPad