Zapis i odczyt dokumentu

Zakładamy, że utworzony programowo dokument został zapisany w postaci pliku HTML. Co jednak, gdybyśmy chcieli mieć możliwość zapisu i późniejszego odczytu zawartości dokumentu?

Jednym z wygodnych rozwiązań jest zastosowanie JAXB (Java Architecture for XML Binding), biblioteki pozwalającej na zapis złożonej struktury obiektów w pamięci w formacie XML (ang. marshal) i późniejsze odtworzenie struktury obiektów z dokumentu XML (ang. unmarshal​). ​

Aby zapis i odczyt był mozliwy musi być spełnionych kilka warunków:

  • musimy oznaczyć elementy, które chcemy zapisać (można też wymusić użycie specyficznych tagów lub atrybutów XML). Czyli raczej ​oznaczamy​ niż ​programujemy,​ ale oszczędzamy bardzo dużo czasu!
  • ponieważ przy odczycie tworzone są nowe puste obiekty na podstawie tagów, może być wymagane dodanie standardowych konstruktorów (tam gdzie są obecne konstruktory z parametrami).

Dla przypomnienia <​to:​jest:​tag att=“a to jest atrybut”>​ a tag zamykający wygląda tak </​to:​jest:​tag>​.

Adnotacje

Biblioteka JAXB używa specyficznego mechanizmu języka - adnotacji (ang. annotations​) [który chyba nie będzie omawiany na wykładzie ???]

Adnotacje mają postać ​@Identifier​ lub ​@Identifier(key=value[,​otherkey=othervalue])​ i są umieszczane w kodzie programu, zazwyczaj przed definicją klasy, deklaracją atrybutu lub definicją metody.

Na przykład:

<code java>

  @Override	 
  public String toString(){	 
      return "";​	 
  }	 

</​code>​

Adnotacje nie mają bezpośredniego wpływu na wykonanie kodu, ale mogą być wykorzystywane przez zewnętrzne narzędzia przetwarzające kod (zarówno źródłowy,​ jak i skompilowany): ​

  • kompilator
  • biblioteki, które na podstawie adnotacji dowiadują się, w jaki sposób przetwarzać obiekty, na przykład:
    • wypełniać ich atrybuty danymi zapisanymi w zewnętrznych źródłach (dokumentach,​ bazach danych)
    • zapisywać obiekty w specyficznych formatach
    • wybierać specyficzne elementy, np. funkcje służące do testowania ​@org.junit.Test
    • wiązać wywołania metod i ich parametry z interfejsem sieciowym

Formalnie, adnotacje deklaruje się jak interfejsy i umieszcza w pakietach

:!: Dodając adnotacje zadbaj, aby importować elementy z pakietu ​javax.xml.bind.annotation

Metody do zapisu i odczytu

Dodaj w klasie ​Document​ metody do zapisu i odczytu

<code java>

  public void write(String fileName){	 
      try {	 
          JAXBContext jc = JAXBContext.newInstance(Document.class);​	 
          Marshaller m = jc.createMarshaller();​	 
          m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,​ Boolean.TRUE);​	 
          FileWriter writer= new FileWriter(fileName);;​	 
          m.marshal(this,​ writer);	 
      } catch (JAXBException ex) {	 
          ex.printStackTrace();​	 
      }	 
      catch (IOException ex) {	 
          ex.printStackTrace();​	 
      }	 
 
  }	 
  public static Document read(String fileName){	 
      try {	 
          JAXBContext jc = JAXBContext.newInstance(Document.class);​	 
          Unmarshaller m = jc.createUnmarshaller();​	 
          FileReader reader = new FileReader(fileName);​	 
          return (Document) m.unmarshal(reader);​	 
      } catch (JAXBException ex) {	 
          ex.printStackTrace();​	 
      } catch (FileNotFoundException ex) {	 
          ex.printStackTrace();​	 
      }	 
      return null;	 
  }	 
 

</​code>​

Dodaj także w funkcji ​main()​ kod, który zapisuje (i odczytuje) dokument

<code java>

      cv.write("​cv.xml"​);​	 
      //Document cv2 = Document.read("​cv.xml"​);​	 
      //​cv2.writeHTML(System.out);​	 

</​code>​

Dla użytkowników Java 9 (zazwyczaj na laptopach)

Java SE 9 nie widzi części modułów Java EE, w tym JAXB.

1. W IntelliJ w dialogu Project Structure - ustaw Project language Level : 8 - lambdas, type annotations ​

2. Zalecanym obejściem (w https://​blog.codefx.org/​java/​java-9-migration-guide/​) jest dodanie opcji uruchamiania programu

<​code>​ –add-modules java.se.ee </​code>​

W IntelliJ nalezy je wpisac w oknie Run → Edit Configurations → pole VM options

Dodajemy adnotacje

W następnych etapach będziemy modyfikowali kod (dodawali adnotacje) i sprawdzali, co zmienia się w pliku ​cv.xml

Najczęściej używane będą następujące adnotacje

  • ​@XmlRootElement​ - oznaczenie klasy będącej korzeniem drzewa XML
  • ​@XmlElement​ - oznaczenie, że atrybut ma zostać zapisany jako element XML (jako nazwa znacznika XML zostanie użyta nazwa atrybutu)
  • ​@XmlElement(name=“​xyz”​)​ - podana jest nazwa znacznika ​xyz
  • ​XmlAttribute​ atrybut (pole klasy) zostanie zapisany jako atrybut XML

Oznacz Document jako XMLRootElement

<code java> @XmlRootElement public class Document { … } </​code>​

Zobacz, co zostało zapisane do pliku ​cv.xml

Oznacz atrybuty klasy Document ​

<code java>

  @XmlElement	 
  String title;	 
  @XmlElement	 
  List<​Section>​ sections = new ArrayList<>​();​	 
  @XmlElement	 
  Photo photo;	 

</​code>​

Wykonaj program i spróbuj zidentyfikować i naprawić błąd…

Photo

Pole ​url​ odwzorujemy w atrybut

<code java>

  @XmlAttribute	 
  String url;	 

</​code>​

Section ​

Tytuł jest zapewne krótki - odwzorujemy go w atrybut, natomiast listę akapitów (​paragraphs​) w XmlElement

Poprawiamy nazwy znaczników XML

Zastąp ​ w odpowiednim miejscu ​@XmlElement​ przez ​@XmlElement(name=“​section”​)​ i ​@XmlElement(name=“​paragraph”​)​.

Nie widać listy w cv.xml? ​

1. Uzupełnijmy więc znaczniki w ​ParagraphWithList,​ UnorderedList oraz ​ListItem

Prawdopodobnie dalej lista w ​cv.xml​ nie będzie widoczna…

2. Poinformuj, JAXB o klasach potomnych ​Paragraph

<code java> @XmlSeeAlso({ParagraphWithList.class}) public class Paragraph { </​code>​

… i usuń ewentualne błędy.

3. Możesz przyjrzeć się znacznikom i poprawić nazwy według uznania

po/lab4_old.txt · Last modified: 2018/10/28 14:58 by pszwed
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0