webForumDet fria alternativet

Sätta this till ett inladdat obj

7 svar · 270 visningar · startad av niels

nielsMedlem sedan juli 2000212 inlägg
#1

Har problem med följande kodsnutt i load(). Efter jag har laddat in chache så vill jag sätta this = "det CurrencyTable objectet som jag har laddat in" men så lätt går det så klart inte att göra. Ngn som vet hur man gör?

tack!
/Niels

package mobigear.currency;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import java.util.HashMap;
import java.util.Date;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.io.*;
import java.text.SimpleDateFormat;

public class CurrencyTable extends HashMap implements Serializable {

    private String lastUpdated;

    public CurrencyTable() {
        super();
    }

    public void load() throws CurrencyException {

        //Current date:
        String today = (new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        File cache = new File(Config.CACHE_PATH+today+".dat");

        if(cache.exists()) {
            try {
                final ObjectInputStream in = new ObjectInputStream(
                    new FileInputStream(cache)
                );
                CurrencyTable tbl = (CurrencyTable) in.readObject();
                //...how to set this to this??

                in.close();
                return;
            } catch (IOException e) {
            } catch (ClassNotFoundException e) {;}
        }

        URL url = null;
        try {
            url = new URL(Config.XML_URL);
        } catch (MalformedURLException e) {
            throw new CurrencyException("load(): "+e.getMessage());
        }

        URLConnection conn =  null;
        try {
            conn = url.openConnection();
        } catch (java.io.IOException e) {
            throw new CurrencyException("load: "+e.getMessage());
        }

        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = docBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new CurrencyException("load(): "+e.getMessage());
        }

        Document doc = null;
        try {
            doc = docBuilder.parse(conn.getInputStream());
        } catch (SAXException e) {

        } catch (IOException e) {
            throw new CurrencyException("laod: "+e.getMessage());
        }

        doc.getDocumentElement().normalize();

        Element cube = (Element)doc.getDocumentElement().getChildNodes().item(5).getChildNodes().item(1);
        lastUpdated = cube.getAttribute("time");

        NodeList lst = cube.getChildNodes();

        for(int i=0;i<lst.getLength();i++) {
            Node node = lst.item(i);
            if(node.getNodeType() == Node.ELEMENT_NODE) {
                Element currency = (Element)node;
                this.put(currency.getAttribute("currency"),new Double(Double.parseDouble(currency.getAttribute("rate"))));
            }
        }
        this.put(Config.DEFAULT_CURRENCY, new Double(1));

        //Save cache:
        try {
            final ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream(cache)
            );
            out.writeObject(this);
            out.close();
        } catch (IOException e) {
            //throw new CurrencyException("load(): unable to save cache: "+e.getMessage());
        }

    }

    public double lookupRate(String key) {
        return ((Double)this.get(key)).doubleValue();
    }

    public String getLastUpdated() {
        return lastUpdated;
    }

}
LimeMedlem sedan sep. 2001961 inlägg
#2

Nä, det är helt korrekt att du inte sätta om självreferensen this till något annat innifrån den instans som this representerar.

Jag skulle göra på en av följade sätt.

1. Om vi använder din kod lite:

 if(cache.exists()) {
            try {
                final ObjectInputStream in = new ObjectInputStream(
                    new FileInputStream(cache)
                );
                CurrencyTable tbl = (CurrencyTable) in.readObject();
                this.putAll(tbl);
                this.lastupdated = tbl.getLastUpdated();

                in.close();
                return;
            } catch (IOException e) {
            } catch (ClassNotFoundException e) {;}
        }

2. Bryt ut själva uppläsningen av objektet i en klassmetod och ladda sedan in xml-en.

package mobigear.currency;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import java.util.HashMap;
import java.util.Date;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.io.*;
import java.text.SimpleDateFormat;

public class CurrencyTable extends HashMap implements Serializable {

    private String lastUpdated;

    public CurrencyTable() {
        super();
    }

    public static CurrencyTable getCachedCurrencyTable()
    {
         CurrencyTable tbl = null;
        //Current date:
        String today = (new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        File cache = new File(Config.CACHE_PATH+today+".dat");

        if(cache.exists()) {
            try {
                final ObjectInputStream in = new ObjectInputStream(
                    new FileInputStream(cache)
                );
                tbl = (CurrencyTable) in.readObject();
                in.close();
                return;
            } catch (IOException e) {
            } catch (ClassNotFoundException e) {;}
        }
        return tbl;
    }
 
    public void load() throws CurrencyException {

        URL url = null;
        try {
            url = new URL(Config.XML_URL);
        } catch (MalformedURLException e) {
            throw new CurrencyException("load(): "+e.getMessage());
        }

        URLConnection conn =  null;
        try {
            conn = url.openConnection();
        } catch (java.io.IOException e) {
            throw new CurrencyException("load: "+e.getMessage());
        }

        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
        try {
            docBuilder = docBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new CurrencyException("load(): "+e.getMessage());
        }

        Document doc = null;
        try {
            doc = docBuilder.parse(conn.getInputStream());
        } catch (SAXException e) {

        } catch (IOException e) {
            throw new CurrencyException("laod: "+e.getMessage());
        }

        doc.getDocumentElement().normalize();

        Element cube = (Element)doc.getDocumentElement().getChildNodes().item(5).getChildNodes().item(1);
        lastUpdated = cube.getAttribute("time");

        NodeList lst = cube.getChildNodes();

        for(int i=0;i<lst.getLength();i++) {
            Node node = lst.item(i);
            if(node.getNodeType() == Node.ELEMENT_NODE) {
                Element currency = (Element)node;
                this.put(currency.getAttribute("currency"),new Double(Double.parseDouble(currency.getAttribute("rate"))));
            }
        }
        this.put(Config.DEFAULT_CURRENCY, new Double(1));

        //Save cache:
        try {
            final ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream(cache)
            );
            out.writeObject(this);
            out.close();
        } catch (IOException e) {
            //throw new CurrencyException("load(): unable to save cache: "+e.getMessage());
        }

    }
}

Jag antar att du nu anropar CurrencyTable såhär:

CurrencyTable ct = new CurrencyTable();
ct.load();

Nu blir det istället såhär:

CurrencyTable ct = CurrencyTable.getCachedCurrencyTable();
if(ct !=  null)
    ct.load();
nielsMedlem sedan juli 2000212 inlägg
#3

tack, men jah hade hoppats på att kunda packetera allt snyggt i CurrencyTable classen... även logiken för load().
Men jag antar att jag får designa om...

LimeMedlem sedan sep. 2001961 inlägg
#4

Det kan du ju...

Men det finns inget sätt att säga till en instans av ett objekt att sätta om sig själv till en instans av ett annat objekt. Det strider mot objektorienteringens ideér. Framför allt går det inte att mitt i en metod sätta om sig själv till en annan instans av klassen. I vilken instans och vilken metod skall man fortsätta körningen?

Däremot KAN du göra det på det sätt som jag gjort.

Själv skulle jag ha gjort det som en Factory och hämtat instanser av CurrencyTable från denna. Sparandet av cachad CurrencyTable skulle jag gjort i denna factoryklass och trådat.

nielsMedlem sedan juli 2000212 inlägg
#5

Har inte använt den pattern (som jag antar att det är) förr... har du lust att visa ett litet exempel på hur det funkar?

LimeMedlem sedan sep. 2001961 inlägg
#6

Inser när jag tänker efter att en Factory inte är korrekt. Jag tänkte på att man skulle skicka in en valutakod och få tillbaka en CurrencyTabell-subklass som representerar den valutan. Då är en factory bra. För lite om Factory se http://www.allapplabs.com/java_design_patterns/factory_pattern.htm.

Behöver applikationen egna CurrencyTable-objekt förresten? Annars kanske en Singelton skulle funka.

nielsMedlem sedan juli 2000212 inlägg
#7

Jag har en klass som heter CurrencyConverter som skapar en instans av en CurrenyTable men jag har hoppats på att CurrencyTable kunde packas i hop snyggt med all logik i en klass.

nielsMedlem sedan juli 2000212 inlägg
#8

Jag la koden för att ladda en CurrenTable från cache'n i CurrencyConverter så jag får nöja mig med det... tack för hjälpen Lime

134 ms totalt · 3 externa anrop · v20260731065814-full.beb2e261
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
131 ms — hämta tråd, inlägg och bilagor (db)