Obsah
Postup nastavení importu Windchill
Nastavení přepínačů
Administrace > Nástroje administrátora > Objekty systému > Řízené objekty
Vyhledat KonstrKusImport
Záložka Přepínače
Vyhledat přepínač KonstrKusImportSchvalTransformuj
Záložka Firemní
Založit
Vybrat z poptextu Schválení a transformace
Uložit
Podobně přepínač varianta
Vyhledat přepínač KonstrKusImportVarianta
Záložka Firemní
Založit
Zapsat Deprag
Uložit
Nastavení parametrů příchozích souborů
Založit agendu AXA
Administrace > MSK - Webové služby > Agendy komunikace
Agenda - WINDCHILL
Cílový systém - OR-SYSTEM
Odkaz na úlohu - 58 CSTANDKUS_IMPORT (předpokládá se, že bude řešena logika třídou cz.orcz.mskws.CStandKusImport)
Založit parametr příchozích souborů Fmp
Administrace > MSK - Webové služby > Příchozí/odchozí soubory > Parametry příchozích/odchozích souborů
Vstup/Výstup - Import s podporou Groovy do OR-SYSTEM Open (vybrat z poptextu - hodnotu „w“
Adresář pro uložení - libovolný např import-g - založit na serveru relativně k datovému adresáři, tedy např. /dlf1/oropen/cvicna/import-g
Adresář protokolu - libovolný např import-g/protokoly - založit podobně jako předchozí bod na serveru
Založit agendu souborů Fma
Administrace > MSK - Webové služby > Příchozí/odchozí soubory > Agendy souborů
Vstupní/Výstupní - vybrat parametr z předchozího kroku - Import s podporou Groovy maker do OR-SYSTEM Open
Priorita - střední (jakákoliv kromě okamžité)
Jméno adresáře příchozího -URL cesta /dlf1/importopen/cvicna/windchill (Obvykle se jedná o adresář z NAS serveru připojený k aplikačnímu serveru)
Jméno souboru příchozího: *.xml
Agenda WINDCHILL
Založit naplánovanou úlohu
Administrace > Parametry > Plánovač úloh > Plánovač úloh
Plán spouštění - dle potřeby. Např. denně každou hodinu.
Úloha - OxSpustDav
Název úlohy - Import Windchill
Příkazový řádek - AutoImport runBatch WINDCHILL
Nastavení konverzní tabulky
Pomocí konverzní tabulky lze naplnit atributy entit CPolozka(ts) a CPolozkaRozmer(tsr).
Lze nastavit způsob jaký se konvertují atributy konstrukčního kusovníku do výše uvedených entit.
A to z hlavičky CKonstrKusHlav, tak řádků CKonstrKusKomp
Konverzní tabulku je možné založit ručně.
A to pro tyto části:
- DepragTsKonstrKusHlavImp
- DepragTsrKonstrKusHlavImp
- DepragTsKonstrKusKompImp
- DepragTsrKonstrKusKompImp
V řádcích se potom nastaví plnění konstant nebo plnění z Importovaných podkladů přímo nebo s konverzí.
Existuje také varianta naimportování předpřipraveného souboru.
Administrace > MSK - Webové služby > Konverzní tabulka
Další nabídka > Import záznamů.
Vybrat export_wkh_Deprag.json
Popřípadě založit ručně:
Založit hlavičku konverzní tabulky Wkh
Zapsat postupně 4 entity výše uvedené.
Příklad pro vyplnění názvu tsZn z atributu nazev konstrukčního kusovníku.
Název tabulky v OR vybrat z poptextu - Ts
Název atributu v OR např. tsZn
Název atributu v konstrukčním kusovníku - nazev
Příklad pro vyplnění konstanty „J“ do tsStJn
Název tabulky v OR vybrat z poptextu - Ts
Název atributu v OR např. tsStJn
Název atributu v konstrukčním kusovníku - ponechat prázdný
Značka K jako konstanta
Konstanta J
Obecně je potřeba prověřit plnění měrné jednotky a doplnit konstanty.
Vytvoření Groovy makra
Makro provádí konverzi XML souboru do Importovaných podkladů konstrukčního kusovníku.
Založit makro
Administrace > Nástroje administrátora > Správa vlastních zdrojů aplikace > Groovy makra
Druh: Skupinové
Kód WINDCHILL (dle agendy)
Název WINDCHILL (dle agendy)
Třída definice cz.ortex.common.o0.mailTemplateTypes.GroovyType
Předmět Import kusovníku Windchill
záložka „Programování“
(Groovy makrem je možné modifikovat funkčnost importu)
varianta makra pro verzi OR-SYSTEM Open do 25.10.2023
varianta makra pro verzi OR-SYSTEM Open od 26.10.2023
Testování importu Windchill
Nakopírovat cvičné xml soubory do adresáře dle Fmp.
Např. /dlf1/importopen/cvicna/windchill/6018980B.xml
V naplánovaných úlohách přes pravý klik provést spuštění.
Výsledek se zobrazí v záložce historie, popřípadě vyběhne chyba na popředí.
Princip importu spočívá v procházení adresáře importu. Pro každý XML soubor se vygeneruje úloha do fronty Axz.
Varianta makra OR-SYSTEM do verze z 25.10.2023
import cz.orcz.orfmodel.CKonstrKusHlavWsImp; import cz.orcz.orfmodel.CPolozka; import cz.orcz.orfmodel.CKonstrKusKompImp; import cz.orcz.orfmodel.Axz; import cz.orcz.mskws.ws.KonstrKusImport; import javax.xml.bind.*; import javax.xml.bind.annotation.*; import javax.xml.transform.stream.StreamSource; import java.io.File; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import cz.ortex.util.o0.O0Session; import javax.swing.JOptionPane; import org.hibernate.Session; import org.hibernate.Transaction; import static cz.ortex.implutil.o0.HibernateUtil.getSessionFactory; import java.io.FileOutputStream; import java.io.PrintStream; import cz.ortex.implutil.o0.O0CfgSrv; import cz.ortex.implutil.o0.O0CfgSrvPar; import cz.ortex.impldao.o0.admin.O0logDaoImpl; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import cz.ortex.impllogic.o0.task.O0taskDemonUtil; import cz.ortex.impllogic.o0.task.OxSpustDavTaskRun; protected static void autoImport(String urlCesta, O0Session o0Session,Axz axz) { CKonstrKusKompImp lastKusKompImp; int lastLevel; // Create a Random object Random random = new Random(); // Generate a random integer between 0 (inclusive) and an upper bound (exclusive) int randomInt = random.nextInt(100); // Change 100 to your desired upper bound if (axz == null){ axz = new Axz(); axz.setAxzId=randomInt; } try { //Adresář protokolu obecný String adrProtokol = O0CfgSrv.get(O0CfgSrvPar.ADR_PROTOKOLY); // Zadejte cestu k souboru, kam chcete přesměrovat výstup String soubor = adrProtokol + "axz_"+axz.axzId+".log"; axz.axzHlaseni = soubor; // Vytvořte nový výstupní proud pro soubor FileOutputStream fileOutputStream = new FileOutputStream(soubor); // Vytvořte PrintStream pro nový výstupní proud PrintStream printStream = new PrintStream(fileOutputStream); // Uložte stávající System.out do záložního PrintStreamu PrintStream systemOutBackup = System.out; // Nastavte nový PrintStream jako System.out System.setOut(printStream); // Nyní vše, co je vypsáno na System.out, bude přesměrováno do souboru // Vytvoření JAXB kontextu pro CKonstrKusHlavWsImp a CKonstrKusKompImp třídy JAXBContext context = JAXBContext.newInstance(CKonstrKusHlavWsImp.class, CKonstrKusKompImp.class,SearchResults.class,SearchObject.class); // Vytvoření unmarshalleru Unmarshaller unmarshaller = context.createUnmarshaller(); // Nastavení validace XML (volitelné) unmarshaller.setSchema(null); // null znamená, že se validace neprovádí // Načtení XML ze souboru File xmlFile = new File(urlCesta); JAXBElement<SearchResults> rootElement = unmarshaller.unmarshal(new StreamSource(xmlFile), SearchResults.class); // Získání načtených dat SearchResults searchResults = rootElement.getValue(); List<SearchObject> objects = searchResults.getObjects(); // Vytvoření seznamu CKonstrKusHlavWsImp objektů List<CKonstrKusHlavWsImp> kusHlavImpList = new ArrayList<>(); //JOptionPane.showMessageDialog(null, "CKonstrKusHlavWsImp: zacatek"); // Mapa pro uchování předchozích úrovní Map<Integer, CKonstrKusHlavWsImp> previousLevels = new HashMap<>(); Session s2 = getSessionFactory().getCurrentSession();//udelam novou String autor = o0Session.getLoginName(); // Procházení načtených objektů for (SearchObject searchObject : objects) { List<String> attributes = searchObject.getAttributes(); int level = Integer.parseInt(attributes.get(0)); if (level == 0) { CKonstrKusHlavWsImp kusHlavImp = new CKonstrKusHlavWsImp(); kusHlavImp.setIdentPol(attributes.get(2)); kusHlavImp.setIdCSyst(String.valueOf(level)); kusHlavImp.setVykres(attributes.get(2)); kusHlavImp.setNazev(attributes.get(3)); kusHlavImp.setStatus((short) 200); kusHlavImp.setEdat(new Date()); kusHlavImp.setEname(autor); kusHlavImp.setRevize("00"); CPolozka cPolozka=s2.get(CPolozka.class,kusHlavImp.getIdentPol()); if (cPolozka != null){ kusHlavImp.setTypPol(cPolozka.getBs()); } else { kusHlavImp.setTypPol((short) 0); } kusHlavImpList.add(kusHlavImp); // Přidání CKonstrKusHlavWsImp do mapy předchozích úrovní previousLevels.put(level, kusHlavImp); } else { CKonstrKusHlavWsImp parentHlavImp = previousLevels.get(level - 1); if (parentHlavImp == null) { CKonstrKusHlavWsImp kusHlavImp = new CKonstrKusHlavWsImp(); kusHlavImp.setIdentPol(lastKusKompImp.getIdentPol()); kusHlavImp.setVykres(lastKusKompImp.getIdentPol()); kusHlavImp.setNazev(lastKusKompImp.getNazev()); previousLevels.put(level - 1, kusHlavImp); kusHlavImp.setIdCSyst(String.valueOf(level - 1)); kusHlavImpList.add(kusHlavImp); kusHlavImp.setStatus((short) 200); kusHlavImp.setEdat(new Date()); kusHlavImp.setEname(autor); kusHlavImp.setRevize("00"); CPolozka cPolozka=s2.get(CPolozka.class,kusHlavImp.getIdentPol()); if (cPolozka != null){ kusHlavImp.setTypPol(cPolozka.getBs()); } else { kusHlavImp.setTypPol((short) 0); } parentHlavImp = previousLevels.get(level - 1); } if (parentHlavImp != null) { CKonstrKusKompImp kusKompImp = new CKonstrKusKompImp(); kusKompImp.setIdentPol(attributes.get(2)); kusKompImp.setIdCSyst(attributes.get(2)); kusKompImp.setVykres(attributes.get(2)); kusKompImp.setNazev(attributes.get(3)); kusKompImp.setMnoz(new BigDecimal(attributes.get(1))); kusKompImp.setcKonstrKusHlavImp(parentHlavImp); parentHlavImp.getcKonstrKusKompImps().add(kusKompImp); if (lastLevel > level){ previousLevels.remove(level); } kusKompImp.setRevize("00"); CPolozka cPolozka=s2.get(CPolozka.class,kusKompImp.getIdentPol()); if (cPolozka != null){ kusKompImp.setTypPol(cPolozka.getBs()); } else { kusKompImp.setTypPol((short) 0); } kusKompImp.setEdat(new Date()); kusKompImp.setEname(autor); lastKusKompImp=kusKompImp; lastLevel=level; } else{ } } } // Výpis naimportovaných dat for (CKonstrKusHlavWsImp kusHlavImp : kusHlavImpList) { System.out.println("CKonstrKusHlavWsImp: identPol=" + kusHlavImp.getIdentPol() + "level "+kusHlavImp.getIdCSyst()); for (CKonstrKusKompImp kusKompImp : kusHlavImp.getcKonstrKusKompImps()) { System.out.println(" CKonstrKusKompImp: identPol=" + kusKompImp.getIdentPol() + ", mnozstvi=" + kusKompImp.getMnoz()); } //JOptionPane.showMessageDialog(null, "CKonstrKusHlavWsImp: identPol=" + kusHlavImp.getIdentPol() + "level "+kusHlavImp.getIdCSyst()); Session s = getSessionFactory().openSession();//udelam novou Transaction tx = s.getTransaction(); tx.begin(); s.save(kusHlavImp); s.update(axz); tx.commit(); KonstrKusImport i = new KonstrKusImport(o0Session); i.transformuj(kusHlavImp); } // Obnovte původní System.out System.setOut(systemOutBackup); // Zavřete souborový výstup printStream.close(); String obsahLogu = new String(Files.readAllBytes(Paths.get(axz.axzHlaseni))); O0logDaoImpl o0logDaoImpl; o0logDaoImpl = new O0logDaoImpl(); o0logDaoImpl.setOrsoftSession(o0Session); Character v='V'; Character g='G'; try { o0logDaoImpl.zapisLog("WINDCHILL axz:"+axz.axzId, obsahLogu, null, null, null, null, null, null, null, v,g); } catch (Exception e){ //JOptionPane.showMessageDialog(null, e.getMessage()); System.out.println(" vyjimka " + e.getMessage()); } try { if (O0taskDemonUtil.getOrsoftSessionRun() != null) { OxSpustDavTaskRun.zapisVysledek(obsahLogu); } } catch (Exception e){ //JOptionPane.showMessageDialog(null, e.getMessage()); System.out.println(" vyjimka " + e.getMessage()); } } catch (JAXBException e) { e.printStackTrace(); } } @XmlRootElement(name = "SearchResults") @XmlAccessorType(XmlAccessType.FIELD) public class SearchResults { @XmlElement(name = "Object") private List<SearchObject> objects; // Gettery a settery pro objects public List<SearchObject> getObjects() { return objects; } public void setObjects(List<SearchObject> objects) { this.objects = objects; } } @XmlAccessorType(XmlAccessType.FIELD) public class SearchObject { @XmlElement(name = "Attribute") private List<String> attributes; // Gettery a settery pro attributes public List<String> getAttributes() { return attributes; } public void setAttributes(List<String> attributes) { this.attributes = attributes; } }
Varianta makra OR-SYSTEM od verze z 26.10.2023
import cz.orcz.orfmodel.CKonstrKusHlavWsImp; import cz.orcz.orfmodel.CPolozka; import cz.orcz.orfmodel.CKonstrKusKompImp; import cz.orcz.orfmodel.Axz; import cz.orcz.mskws.ws.KonstrKusImport; import javax.xml.bind.*; import javax.xml.bind.annotation.*; import javax.xml.transform.stream.StreamSource; import java.io.File; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import cz.ortex.util.o0.O0Session; import javax.swing.JOptionPane; import org.hibernate.Session; import org.hibernate.Transaction; import static cz.ortex.implutil.o0.HibernateUtil.getSessionFactory; import java.io.FileOutputStream; import java.io.PrintStream; import cz.ortex.implutil.o0.O0CfgSrv; import cz.ortex.implutil.o0.O0CfgSrvPar; import cz.ortex.impldao.o0.admin.O0logDaoImpl; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import cz.ortex.impllogic.o0.task.O0taskDemonUtil; import cz.ortex.impllogic.o0.task.OxSpustDavTaskRun; import cz.ortex.util.o0.O0StringUtil; protected static void autoImport(String urlCesta, O0Session o0Session,Axz axz) { CKonstrKusKompImp lastKusKompImp; int lastLevel; // Create a Random object Random random = new Random(); // Generate a random integer between 0 (inclusive) and an upper bound (exclusive) int randomInt = random.nextInt(100); // Change 100 to your desired upper bound if (axz == null){ axz = new Axz(); axz.setAxzId=randomInt; } try { //Adresář protokolu obecný String adrProtokol = O0CfgSrv.get(O0CfgSrvPar.ADR_PROTOKOLY); // Zadejte cestu k souboru, kam chcete přesměrovat výstup String soubor = adrProtokol + "axz_"+axz.axzId+".log"; axz.axzHlaseni = soubor; // Vytvořte nový výstupní proud pro soubor FileOutputStream fileOutputStream = new FileOutputStream(soubor); // Vytvořte PrintStream pro nový výstupní proud PrintStream printStream = new PrintStream(fileOutputStream); // Uložte stávající System.out do záložního PrintStreamu PrintStream systemOutBackup = System.out; // Nastavte nový PrintStream jako System.out System.setOut(printStream); // Nyní vše, co je vypsáno na System.out, bude přesměrováno do souboru // Vytvoření JAXB kontextu pro CKonstrKusHlavWsImp a CKonstrKusKompImp třídy JAXBContext context = JAXBContext.newInstance(CKonstrKusHlavWsImp.class, CKonstrKusKompImp.class,SearchResults.class,SearchObject.class); // Vytvoření unmarshalleru Unmarshaller unmarshaller = context.createUnmarshaller(); // Nastavení validace XML (volitelné) unmarshaller.setSchema(null); // null znamená, že se validace neprovádí // Načtení XML ze souboru File xmlFile = new File(urlCesta); JAXBElement<SearchResults> rootElement = unmarshaller.unmarshal(new StreamSource(xmlFile), SearchResults.class); // Získání načtených dat SearchResults searchResults = rootElement.getValue(); List<SearchObject> objects = searchResults.getObjects(); // Vytvoření seznamu CKonstrKusHlavWsImp objektů List<CKonstrKusHlavWsImp> kusHlavImpList = new ArrayList<>(); //JOptionPane.showMessageDialog(null, "CKonstrKusHlavWsImp: zacatek"); // Mapa pro uchování předchozích úrovní Map<Integer, CKonstrKusHlavWsImp> previousLevels = new HashMap<>(); Session s2 = getSessionFactory().getCurrentSession();//udelam novou String autor = o0Session.getLoginName(); // Procházení načtených objektů for (SearchObject searchObject : objects) { List<String> attributes = searchObject.getAttributes(); int level = Integer.parseInt(attributes.get(0)); if (level == 0) { CKonstrKusHlavWsImp kusHlavImp = new CKonstrKusHlavWsImp(); kusHlavImp.setIdentPol(attributes.get(2)); kusHlavImp.setIdCSyst(String.valueOf(level)); kusHlavImp.setVykres(attributes.get(2)); kusHlavImp.setNazev(attributes.get(3)); kusHlavImp.setAtrAn05(O0StringUtil.substring(attributes.get(4),0,40)); kusHlavImp.setAtrAn06(O0StringUtil.substring(attributes.get(5),0,40)); kusHlavImp.setStatus((short) 200); kusHlavImp.setEdat(new Date()); kusHlavImp.setEname(autor); kusHlavImp.setRevize("00"); CPolozka cPolozka=s2.get(CPolozka.class,kusHlavImp.getIdentPol()); if (cPolozka != null){ kusHlavImp.setTypPol(cPolozka.getBs()); } else { kusHlavImp.setTypPol((short) 0); } kusHlavImpList.add(kusHlavImp); // Přidání CKonstrKusHlavWsImp do mapy předchozích úrovní previousLevels.put(level, kusHlavImp); } else { CKonstrKusHlavWsImp parentHlavImp = previousLevels.get(level - 1); if (parentHlavImp == null) { CKonstrKusHlavWsImp kusHlavImp = new CKonstrKusHlavWsImp(); kusHlavImp.setIdentPol(lastKusKompImp.getIdentPol()); kusHlavImp.setVykres(lastKusKompImp.getIdentPol()); kusHlavImp.setNazev(lastKusKompImp.getNazev()); kusHlavImp.setAtrAn05(O0StringUtil.substring(lastKusKompImp.getAtrAn05(),0,40)); kusHlavImp.setAtrAn06(O0StringUtil.substring(lastKusKompImp.getAtrAn06(),0,40)); previousLevels.put(level - 1, kusHlavImp); kusHlavImp.setIdCSyst(String.valueOf(level - 1)); kusHlavImpList.add(kusHlavImp); kusHlavImp.setStatus((short) 200); kusHlavImp.setEdat(new Date()); kusHlavImp.setEname(autor); kusHlavImp.setRevize("00"); CPolozka cPolozka=s2.get(CPolozka.class,kusHlavImp.getIdentPol()); if (cPolozka != null){ kusHlavImp.setTypPol(cPolozka.getBs()); } else { kusHlavImp.setTypPol((short) 0); } parentHlavImp = previousLevels.get(level - 1); } if (parentHlavImp != null) { CKonstrKusKompImp kusKompImp = new CKonstrKusKompImp(); kusKompImp.setIdentPol(attributes.get(2)); kusKompImp.setIdCSyst(attributes.get(2)); kusKompImp.setVykres(attributes.get(2)); kusKompImp.setNazev(attributes.get(3)); kusKompImp.setAtrAn05(O0StringUtil.substring(attributes.get(4),0,40)); kusKompImp.setAtrAn06(O0StringUtil.substring(attributes.get(5),0,40)); kusKompImp.setMnoz(new BigDecimal(attributes.get(1))); kusKompImp.setcKonstrKusHlavImp(parentHlavImp); parentHlavImp.getcKonstrKusKompImps().add(kusKompImp); if (lastLevel > level){ previousLevels.remove(level); } kusKompImp.setRevize("00"); CPolozka cPolozka=s2.get(CPolozka.class,kusKompImp.getIdentPol()); if (cPolozka != null){ kusKompImp.setTypPol(cPolozka.getBs()); } else { kusKompImp.setTypPol((short) 0); } kusKompImp.setEdat(new Date()); kusKompImp.setEname(autor); lastKusKompImp=kusKompImp; lastLevel=level; } else{ } } } // Výpis naimportovaných dat for (CKonstrKusHlavWsImp kusHlavImp : kusHlavImpList) { System.out.println("KusHlavWsImp: identPol=" + kusHlavImp.getIdentPol() + "level "+kusHlavImp.getIdCSyst()); for (CKonstrKusKompImp kusKompImp : kusHlavImp.getcKonstrKusKompImps()) { System.out.println(" KusKompImp: identPol=" + kusKompImp.getIdentPol() + ", mnozstvi=" + kusKompImp.getMnoz()); } //JOptionPane.showMessageDialog(null, "CKonstrKusHlavWsImp: identPol=" + kusHlavImp.getIdentPol() + "level "+kusHlavImp.getIdCSyst()); Session s = getSessionFactory().openSession();//udelam novou Transaction tx = s.getTransaction(); tx.begin(); s.save(kusHlavImp); s.update(axz); tx.commit(); KonstrKusImport i = new KonstrKusImport(o0Session); i.transformuj(kusHlavImp); } // Obnovte původní System.out System.setOut(systemOutBackup); // Zavřete souborový výstup printStream.close(); String obsahLogu = new String(Files.readAllBytes(Paths.get(axz.axzHlaseni))); O0logDaoImpl o0logDaoImpl; o0logDaoImpl = new O0logDaoImpl(); o0logDaoImpl.setOrsoftSession(o0Session); Character v='V'; Character g='G'; try { o0logDaoImpl.zapisLog("WINDCHILL axz:"+axz.axzId, obsahLogu, null, null, null, null, null, null, null, v,g); } catch (Exception e){ //JOptionPane.showMessageDialog(null, e.getMessage()); System.out.println(" vyjimka " + e.getMessage()); } try { if (O0taskDemonUtil.getOrsoftSessionRun() != null) { if (obsahLogu != null && obsahLogu.length() > 2550) { obsahLogu =obsahLogu.substring(0, 2550); } OxSpustDavTaskRun.zapisVysledek(obsahLogu); } } catch (Exception e){ //JOptionPane.showMessageDialog(null, e.getMessage()); System.out.println(" vyjimka " + e.getMessage()); } } catch (JAXBException e) { e.printStackTrace(); } } @XmlRootElement(name = "SearchResults") @XmlAccessorType(XmlAccessType.FIELD) public class SearchResults { @XmlElement(name = "Object") private List<SearchObject> objects; // Gettery a settery pro objects public List<SearchObject> getObjects() { return objects; } public void setObjects(List<SearchObject> objects) { this.objects = objects; } } @XmlAccessorType(XmlAccessType.FIELD) public class SearchObject { @XmlElement(name = "Attribute") private List<String> attributes; // Gettery a settery pro attributes public List<String> getAttributes() { return attributes; } public void setAttributes(List<String> attributes) { this.attributes = attributes; } }