Search in sources :

Example 31 with Attribute

use of org.jdom2.Attribute in project JMRI by JMRI.

the class SwitchboardEditorXml method load.

/**
     * Create a SwitchboardEditor object, then register and fill it, then pop it in a
     * JFrame
     *
     * @param shared Top level Element to unpack.
     * @return true if successful
     */
@Override
public boolean load(Element shared, Element perNode) {
    boolean result = true;
    // find coordinates
    int x = 0;
    int y = 0;
    int height = 400;
    int width = 300;
    int rangemin = 1;
    int rangemax = 32;
    int columns = 4;
    String type = "T";
    String connection = "I";
    String shape = "key";
    String name;
    try {
        x = shared.getAttribute("x").getIntValue();
        y = shared.getAttribute("y").getIntValue();
        height = shared.getAttribute("height").getIntValue();
        width = shared.getAttribute("width").getIntValue();
    } catch (org.jdom2.DataConversionException e) {
        log.error("failed to convert Switchboard's attribute");
        result = false;
    }
    // find the name
    // this will be replaced by the name as stored NOI18N
    name = "Switchboard";
    if (shared.getAttribute("name") != null) {
        name = shared.getAttribute("name").getValue();
    }
    // confirm that panel hasn't already been loaded
    if (jmri.jmrit.display.PanelMenu.instance().isPanelNameUsed(name)) {
        log.warn("File contains a panel with the same name (" + name + ") as an existing panel");
        result = false;
    }
    SwitchboardEditor panel = new SwitchboardEditor(name);
    //panel.makeFrame(name);
    jmri.jmrit.display.PanelMenu.instance().addEditorPanel(panel);
    panel.getTargetFrame().setLocation(x, y);
    panel.getTargetFrame().setSize(width, height);
    panel.setTitle();
    // Load editor option flags. This has to be done before the content
    // items are loaded, to preserve the individual item settings.
    Attribute a;
    boolean value = true;
    if ((a = shared.getAttribute("editable")) != null && a.getValue().equals("no")) {
        value = false;
    }
    panel.setAllEditable(value);
    value = true;
    if ((a = shared.getAttribute("showtooltips")) != null && a.getValue().equals("no")) {
        value = false;
    }
    panel.setAllShowTooltip(value);
    value = true;
    if ((a = shared.getAttribute("controlling")) != null && a.getValue().equals("no")) {
        value = false;
    }
    panel.setAllControlling(value);
    value = false;
    if ((a = shared.getAttribute("hide")) != null && a.getValue().equals("yes")) {
        value = true;
    }
    panel.setShowHidden(value);
    value = true;
    if ((a = shared.getAttribute("panelmenu")) != null && a.getValue().equals("no")) {
        value = false;
    }
    panel.setPanelMenuVisible(value);
    String state = "both";
    if ((a = shared.getAttribute("scrollable")) != null) {
        state = a.getValue();
    }
    panel.setScroll(state);
    value = false;
    if ((a = shared.getAttribute("hideunconnected")) != null && a.getValue().equals("yes")) {
        value = true;
    }
    panel.setHideUnconnected(value);
    try {
        rangemin = shared.getAttribute("rangemin").getIntValue();
        rangemax = shared.getAttribute("rangemax").getIntValue();
    } catch (org.jdom2.DataConversionException e) {
        log.error("failed to convert Switchboard's range");
        result = false;
    }
    panel.setPanelMenuRangeMin(rangemin);
    panel.setPanelMenuRangeMax(rangemax);
    type = shared.getAttribute("type").getValue();
    panel.setSwitchType(type);
    connection = shared.getAttribute("connection").getValue();
    panel.setSwitchManu(connection);
    shape = shared.getAttribute("shape").getValue();
    panel.setSwitchShape(shape);
    try {
        columns = shared.getAttribute("columns").getIntValue();
    } catch (org.jdom2.DataConversionException e) {
        log.error("failed to convert Switchboard's column count");
        result = false;
    }
    panel.setColumns(columns);
    String defaultTextColor = "black";
    if (shared.getAttribute("defaulttextcolor") != null) {
        defaultTextColor = shared.getAttribute("defaulttextcolor").getValue();
    }
    panel.setDefaultTextColor(defaultTextColor);
    // set color if needed
    try {
        int red = shared.getAttribute("redBackground").getIntValue();
        int blue = shared.getAttribute("blueBackground").getIntValue();
        int green = shared.getAttribute("greenBackground").getIntValue();
        //panel.setBackground(new Color(red, green, blue));
        panel.setDefaultBackgroundColor(new Color(red, green, blue));
    } catch (org.jdom2.DataConversionException e) {
        log.warn("Could not parse color attributes!");
    } catch (NullPointerException e) {
    // considered normal if the attributes are not present
    }
    //set the (global) editor display widgets to their flag settings
    panel.initView();
    // load the contents with their individual option settings
    List<Element> items = shared.getChildren();
    for (int i = 0; i < items.size(); i++) {
        // get the class, hence the adapter object to do loading
        Element item = items.get(i);
        String adapterName = item.getAttribute("class").getValue();
        log.debug("load via " + adapterName);
        try {
            XmlAdapter adapter = (XmlAdapter) Class.forName(adapterName).newInstance();
            // and do it
            adapter.load(item, panel);
            if (!panel.loadOK()) {
                result = false;
            }
        } catch (Exception e) {
            log.error("Exception while loading " + item.getName() + ":" + e);
            result = false;
            e.printStackTrace();
        }
    }
    // dispose of url correction data
    panel.disposeLoadData();
    // display the results, with the editor in back
    panel.pack();
    panel.setAllEditable(panel.isEditable());
    // we don't pack the target frame here, because size was specified
    // TODO: Work out why, when calling this method, panel size is increased
    // vertically (at least on MS Windows)
    // always show the panel
    panel.getTargetFrame().setVisible(true);
    // register the resulting panel for later configuration
    ConfigureManager cm = InstanceManager.getNullableDefault(jmri.ConfigureManager.class);
    if (cm != null) {
        cm.registerUser(panel);
    }
    // reset the size and position, in case the display caused it to change
    panel.getTargetFrame().setLocation(x, y);
    panel.getTargetFrame().setSize(width, height);
    panel.updatePressed();
    return result;
}
Also used : Attribute(org.jdom2.Attribute) Color(java.awt.Color) Element(org.jdom2.Element) Point(java.awt.Point) SwitchboardEditor(jmri.jmrit.display.switchboardEditor.SwitchboardEditor) ConfigureManager(jmri.ConfigureManager) AbstractXmlAdapter(jmri.configurexml.AbstractXmlAdapter) XmlAdapter(jmri.configurexml.XmlAdapter)

Example 32 with Attribute

use of org.jdom2.Attribute in project JMRI by JMRI.

the class WarrantPreferences method loadSpeedMap.

// Avoid firePropertyChange until SignalSpeedMap is completely loaded
private boolean loadSpeedMap(Element child) {
    if (child == null) {
        return false;
    }
    Element rampParms = child.getChild(STEP_INCREMENTS);
    if (rampParms == null) {
        return false;
    }
    Attribute a;
    if ((a = rampParms.getAttribute(TIME_INCREMENT)) != null) {
        try {
            this._msIncrTime = a.getIntValue();
        } catch (DataConversionException ex) {
            this._msIncrTime = 500;
            log.error("Unable to read ramp time increment. Setting to default value (500ms).", ex);
        }
    }
    if ((a = rampParms.getAttribute(RAMP_INCREMENT)) != null) {
        try {
            this._throttleIncr = a.getFloatValue();
        } catch (DataConversionException ex) {
            this._throttleIncr = 0.03f;
            log.error("Unable to read ramp throttle increment. Setting to default value (0.03).", ex);
        }
    }
    if ((a = rampParms.getAttribute(THROTTLE_SCALE)) != null) {
        try {
            _throttleScale = a.getFloatValue();
        } catch (DataConversionException ex) {
            _throttleScale = .90f;
            log.error("Unable to read throttle scale. Setting to default value (0.90f).", ex);
        }
    }
    rampParms = child.getChild(SPEED_NAME_PREFS);
    if (rampParms == null) {
        return false;
    }
    if ((a = rampParms.getAttribute("percentNormal")) != null) {
        if (a.getValue().equals("yes")) {
            _interpretation = 1;
        } else {
            _interpretation = 2;
        }
    }
    if ((a = rampParms.getAttribute(INTERPRETATION)) != null) {
        try {
            _interpretation = a.getIntValue();
        } catch (DataConversionException ex) {
            _interpretation = 1;
            log.error("Unable to read interpetation of Speed Map. Setting to default value % normal.", ex);
        }
    }
    HashMap<String, Float> map = new LinkedHashMap<>();
    List<Element> list = rampParms.getChildren();
    for (int i = 0; i < list.size(); i++) {
        String name = list.get(i).getName();
        Float speed = 0f;
        try {
            speed = Float.valueOf(list.get(i).getText());
        } catch (NumberFormatException nfe) {
            log.error("Speed names has invalid content for {} = ", name, list.get(i).getText());
        }
        log.debug("Add {}, {} to AspectSpeed Table", name, speed);
        map.put(name, speed);
    }
    // no firePropertyChange
    this.setSpeedNames(map);
    rampParms = child.getChild(APPEARANCE_PREFS);
    if (rampParms == null) {
        return false;
    }
    LinkedHashMap<String, String> heads = new LinkedHashMap<>();
    list = rampParms.getChildren();
    for (int i = 0; i < list.size(); i++) {
        String name = Bundle.getMessage(list.get(i).getName());
        String speed = list.get(i).getText();
        heads.put(name, speed);
    }
    // no firePropertyChange
    this.setAppearances(heads);
    // Now set SignalSpeedMap members.
    SignalSpeedMap speedMap = jmri.InstanceManager.getDefault(SignalSpeedMap.class);
    speedMap.setRampParams(_msIncrTime, _msIncrTime);
    speedMap.setDefaultThrottleFactor(_throttleScale);
    speedMap.setLayoutScale(_scale);
    speedMap.setAspects(new HashMap<>(this._speedNames), _interpretation);
    speedMap.setAppearances(new HashMap<>(this._headAppearances));
    return true;
}
Also used : Attribute(org.jdom2.Attribute) Element(org.jdom2.Element) LinkedHashMap(java.util.LinkedHashMap) SignalSpeedMap(jmri.implementation.SignalSpeedMap) DataConversionException(org.jdom2.DataConversionException)

Example 33 with Attribute

use of org.jdom2.Attribute in project JMRI by JMRI.

the class TrainSwitchListText method load.

public static void load(Element e) {
    Element emts = e.getChild(Xml.SWITCH_LIST_TEXT_STRINGS);
    if (emts == null) {
        return;
    }
    Attribute a;
    if (emts.getChild(Xml.SWICH_LIST_FOR) != null) {
        if ((a = emts.getChild(Xml.SWICH_LIST_FOR).getAttribute(Xml.TEXT)) != null) {
            setStringSwitchListFor(a.getValue());
        }
    }
    if (emts.getChild(Xml.SCHEDULED_WORK_TRAIN) != null) {
        if ((a = emts.getChild(Xml.SCHEDULED_WORK_TRAIN).getAttribute(Xml.TEXT)) != null) {
            setStringScheduledWork(a.getValue());
        }
    }
    if (emts.getChild(Xml.DEPARTS_AT) != null) {
        if ((a = emts.getChild(Xml.DEPARTS_AT).getAttribute(Xml.TEXT)) != null) {
            setStringDepartsAt(a.getValue());
        }
    }
    if (emts.getChild(Xml.DEPARTS_EXPECTED_ARRIVAL) != null) {
        if ((a = emts.getChild(Xml.DEPARTS_EXPECTED_ARRIVAL).getAttribute(Xml.TEXT)) != null) {
            setStringDepartsAtExpectedArrival(a.getValue());
        }
    }
    if (emts.getChild(Xml.DEPARTED_EXPECTED) != null) {
        if ((a = emts.getChild(Xml.DEPARTED_EXPECTED).getAttribute(Xml.TEXT)) != null) {
            setStringDepartedExpected(a.getValue());
        }
    }
    if (emts.getChild(Xml.VISIT_NUMBER) != null) {
        if ((a = emts.getChild(Xml.VISIT_NUMBER).getAttribute(Xml.TEXT)) != null) {
            setStringVisitNumber(a.getValue());
        }
    }
    if (emts.getChild(Xml.VISIT_NUMBER_DEPARTED) != null) {
        if ((a = emts.getChild(Xml.VISIT_NUMBER_DEPARTED).getAttribute(Xml.TEXT)) != null) {
            setStringVisitNumberDeparted(a.getValue());
        }
    }
    if (emts.getChild(Xml.VISIT_NUMBER_TERMINATES) != null) {
        if ((a = emts.getChild(Xml.VISIT_NUMBER_TERMINATES).getAttribute(Xml.TEXT)) != null) {
            setStringVisitNumberTerminates(a.getValue());
        }
    }
    if (emts.getChild(Xml.VISIT_NUMBER_TERMINATES_DEPARTED) != null) {
        if ((a = emts.getChild(Xml.VISIT_NUMBER_TERMINATES_DEPARTED).getAttribute(Xml.TEXT)) != null) {
            setStringVisitNumberTerminatesDeparted(a.getValue());
        }
    }
    if (emts.getChild(Xml.VISIT_NUMBER_DONE) != null) {
        if ((a = emts.getChild(Xml.VISIT_NUMBER_DONE).getAttribute(Xml.TEXT)) != null) {
            setStringVisitNumberDone(a.getValue());
        }
    }
    if (emts.getChild(Xml.TRAIN_DIRECTION_CHANGE) != null) {
        if ((a = emts.getChild(Xml.TRAIN_DIRECTION_CHANGE).getAttribute(Xml.TEXT)) != null) {
            setStringTrainDirectionChange(a.getValue());
        }
    }
    if (emts.getChild(Xml.NO_CAR_PICK_UPS) != null) {
        if ((a = emts.getChild(Xml.NO_CAR_PICK_UPS).getAttribute(Xml.TEXT)) != null) {
            setStringNoCarPickUps(a.getValue());
        }
    }
    if (emts.getChild(Xml.NO_CAR_SET_OUTS) != null) {
        if ((a = emts.getChild(Xml.NO_CAR_SET_OUTS).getAttribute(Xml.TEXT)) != null) {
            setStringNoCarDrops(a.getValue());
        }
    }
    if (emts.getChild(Xml.TRAIN_DONE) != null) {
        if ((a = emts.getChild(Xml.TRAIN_DONE).getAttribute(Xml.TEXT)) != null) {
            setStringTrainDone(a.getValue());
        }
    }
    if (emts.getChild(Xml.TRAIN_DEPARTS_CARS) != null) {
        if ((a = emts.getChild(Xml.TRAIN_DEPARTS_CARS).getAttribute(Xml.TEXT)) != null) {
            setStringTrainDepartsCars(a.getValue());
        }
    }
    if (emts.getChild(Xml.TRAIN_DEPARTS_LOADS) != null) {
        if ((a = emts.getChild(Xml.TRAIN_DEPARTS_LOADS).getAttribute(Xml.TEXT)) != null) {
            setStringTrainDepartsLoads(a.getValue());
        }
    }
    if (emts.getChild(Xml.SWITCH_LIST_TRACK) != null) {
        if ((a = emts.getChild(Xml.SWITCH_LIST_TRACK).getAttribute(Xml.TEXT)) != null) {
            setStringSwitchListByTrack(a.getValue());
        }
    }
    if (emts.getChild(Xml.HOLD_CAR) != null) {
        if ((a = emts.getChild(Xml.HOLD_CAR).getAttribute(Xml.TEXT)) != null) {
            setStringHoldCar(a.getValue());
        }
    }
}
Also used : Attribute(org.jdom2.Attribute) Element(org.jdom2.Element)

Example 34 with Attribute

use of org.jdom2.Attribute in project JMRI by JMRI.

the class SymbolicProgFrame method writeFile.

// dead class doesn't need this fixed right now
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION")
void writeFile() {
    log.warn("SymbolicProgFrame writeFile invoked - is this still right, or should the LocoFile method be used?");
    log.warn("Note use of VersionID attribute...");
    try {
        // get the file
        int retVal = fco.showSaveDialog(this);
        // handle selection or cancel
        if (retVal != JFileChooser.APPROVE_OPTION) {
            // leave early
            return;
        }
        File file = fco.getSelectedFile();
        // This is taken in large part from "Java and XML" page 368
        // create root element
        Element root = new Element("locomotive-config");
        Document doc = jmri.jmrit.XmlFile.newDocument(root, jmri.jmrit.XmlFile.getDefaultDtdLocation() + "locomotive-config.dtd");
        // add XSLT processing instruction
        // <?xml-stylesheet type="text/xsl" href="XSLT/locomotive.xsl"?>
        java.util.Map<String, String> m = new java.util.HashMap<String, String>();
        m.put("type", "text/xsl");
        m.put("href", jmri.jmrit.XmlFile.xsltLocation + "locomotive.xsl");
        ProcessingInstruction p = new ProcessingInstruction("xml-stylesheet", m);
        doc.addContent(0, p);
        // add top-level elements
        Element values;
        root.addContent(// locomotive values are first item
        new Element("locomotive").setAttribute("roadNumber", locoRoadNumber.getText()).setAttribute("roadName", locoRoadName.getText()).setAttribute("mfg", locoMfg.getText()).setAttribute("model", locoModel.getText()).addContent(new Element("decoder").setAttribute("model", decoderModel.getText()).setAttribute("mfg", decoderMfg.getText()).setAttribute("versionID", "").setAttribute("mfgID", "")).addContent(values = new Element("values")));
        // Append a decoderDef element to values
        Element decoderDef;
        values.addContent(decoderDef = new Element("decoderDef"));
        // add the variable values to the decoderDef Element
        for (int i = 0; i < variableModel.getRowCount(); i++) {
            decoderDef.addContent(new Element("varValue").setAttribute("item", variableModel.getLabel(i)).setAttribute("value", variableModel.getValString(i)));
        }
        // add the CV values to the values Element
        for (int i = 0; i < cvModel.getRowCount(); i++) {
            values.addContent(new Element("CVvalue").setAttribute("name", cvModel.getName(i)).setAttribute("value", cvModel.getValString(i)));
        }
        // write the result to selected file
        java.io.FileOutputStream o = new java.io.FileOutputStream(file);
        try {
            XMLOutputter fmt = new XMLOutputter();
            fmt.setFormat(Format.getPrettyFormat().setLineSeparator(System.getProperty("line.separator")).setTextMode(Format.TextMode.PRESERVE));
            fmt.output(doc, o);
        } finally {
            o.close();
        }
        // mark file as OK
        variableModel.setFileDirty(false);
    } catch (Exception e) {
        log.error(e.getLocalizedMessage(), e);
    }
}
Also used : XMLOutputter(org.jdom2.output.XMLOutputter) Element(org.jdom2.Element) Document(org.jdom2.Document) DecoderFile(jmri.jmrit.decoderdefn.DecoderFile) File(java.io.File) ProcessingInstruction(org.jdom2.ProcessingInstruction) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings)

Example 35 with Attribute

use of org.jdom2.Attribute in project JMRI by JMRI.

the class SymbolicProgFrame method processLocoFile.

void processLocoFile(Element loco) {
    // load the name et al
    locoRoadName.setText(loco.getAttributeValue("roadName"));
    locoRoadNumber.setText(loco.getAttributeValue("roadNumber"));
    locoMfg.setText(loco.getAttributeValue("mfg"));
    locoModel.setText(loco.getAttributeValue("model"));
    // load the variable definitions for the decoder
    Element decoder = loco.getChild("decoder");
    if (decoder != null) {
        // get the file name
        String mfg = decoder.getAttribute("mfg").getValue();
        String model = decoder.getAttribute("model").getValue();
        String filename = "xml" + File.separator + mfg + "_" + model + ".xml";
        if (log.isDebugEnabled()) {
            log.debug("will read decoder info from " + filename);
        }
        readAndParseConfigFile(new File(filename));
        if (log.isDebugEnabled()) {
            log.debug("finished processing decoder file for loco file");
        }
    } else {
        log.error("No decoder element found in config file");
    }
    // get the CVs and load
    Element values = loco.getChild("values");
    if (values != null) {
        // get the CV values and load
        List<Element> varList = values.getChildren("CVvalue");
        if (log.isDebugEnabled()) {
            log.debug("Found " + varList.size() + " CVvalues");
        }
        for (int i = 0; i < varList.size(); i++) {
            // locate the row
            if (((varList.get(i))).getAttribute("name") == null) {
                if (log.isDebugEnabled()) {
                    log.debug("unexpected null in name " + ((varList.get(i))) + " " + ((varList.get(i))).getAttributes());
                }
                break;
            }
            if (((varList.get(i))).getAttribute("value") == null) {
                if (log.isDebugEnabled()) {
                    log.debug("unexpected null in value " + ((varList.get(i))) + " " + ((varList.get(i))).getAttributes());
                }
                break;
            }
            String name = ((varList.get(i))).getAttribute("name").getValue();
            String value = ((varList.get(i))).getAttribute("value").getValue();
            if (log.isDebugEnabled()) {
                log.debug("CV: " + i + "th entry, CV number " + name + " has value: " + value);
            }
            CvValue cvObject = cvModel.allCvMap().get(name);
            cvObject.setValue(Integer.valueOf(value).intValue());
            cvObject.setState(CvValue.FROMFILE);
        }
        variableModel.configDone();
    } else {
        log.error("no values element found in config file; CVs not configured");
        return;
    }
    // get the variable values and load
    Element decoderDef = values.getChild("decoderDef");
    if (decoderDef != null) {
        List<Element> varList = decoderDef.getChildren("varValue");
        if (log.isDebugEnabled()) {
            log.debug("Found " + varList.size() + " varValues");
        }
        for (int i = 0; i < varList.size(); i++) {
            // locate the row
            Attribute itemAttr = null;
            if ((itemAttr = varList.get(i).getAttribute("item")) == null) {
                if (log.isDebugEnabled()) {
                    log.debug("unexpected null in item " + varList.get(i));
                }
                break;
            }
            if ((itemAttr = varList.get(i).getAttribute("name")) == null) {
                if (log.isDebugEnabled()) {
                    log.debug("unexpected null in name " + varList.get(i));
                }
                break;
            }
            String item = itemAttr.getValue();
            if (((varList.get(i))).getAttribute("value") == null) {
                if (log.isDebugEnabled()) {
                    log.debug("unexpected null in value " + ((varList.get(i))));
                }
                break;
            }
            String value = ((varList.get(i))).getAttribute("value").getValue();
            if (log.isDebugEnabled()) {
                log.debug("Variable " + i + " is " + item + " value: " + value);
            }
            int row;
            for (row = 0; row < variableModel.getRowCount(); row++) {
                if (variableModel.getLabel(row).equals(item)) {
                    break;
                }
            }
            if (log.isDebugEnabled()) {
                log.debug("Variable " + item + " is row " + row);
            }
            if (!value.equals("")) {
                // don't set if no value was stored
                variableModel.setIntValue(row, Integer.valueOf(value).intValue());
            }
            variableModel.setState(row, VariableValue.FROMFILE);
        }
        variableModel.configDone();
    } else {
        log.error("no decoderDef element found in config file");
    }
    // the act of loading values marks as dirty, but we're actually in synch
    variableModel.setFileDirty(false);
}
Also used : Attribute(org.jdom2.Attribute) Element(org.jdom2.Element) CvValue(jmri.jmrit.symbolicprog.CvValue) DecoderFile(jmri.jmrit.decoderdefn.DecoderFile) File(java.io.File)

Aggregations

Attribute (org.jdom2.Attribute)104 Element (org.jdom2.Element)96 DataConversionException (org.jdom2.DataConversionException)17 Editor (jmri.jmrit.display.Editor)15 ArrayList (java.util.ArrayList)13 NamedIcon (jmri.jmrit.catalog.NamedIcon)13 IOException (java.io.IOException)12 LayoutEditor (jmri.jmrit.display.layoutEditor.LayoutEditor)10 File (java.io.File)8 Color (java.awt.Color)7 List (java.util.List)7 HashMap (java.util.HashMap)6 Asn1Integer (com.android.hotspot2.asn1.Asn1Integer)5 Asn1Object (com.android.hotspot2.asn1.Asn1Object)5 Asn1Oid (com.android.hotspot2.asn1.Asn1Oid)5 OidMappings (com.android.hotspot2.asn1.OidMappings)5 ASN1Encodable (com.android.org.bouncycastle.asn1.ASN1Encodable)5 ASN1EncodableVector (com.android.org.bouncycastle.asn1.ASN1EncodableVector)5 ASN1Set (com.android.org.bouncycastle.asn1.ASN1Set)5 DERBitString (com.android.org.bouncycastle.asn1.DERBitString)5