Sisällys
Tarjouskonfiguraattori (TAHKO) on Sonera Oyj:n myyjille tuotettava tarjousdokumenttien generointiohjelmisto. Ohjelmisto toteutetaan Helsingin yliopiston tietojenkäsittelytieteen laitoksen ohjelmistotuotantoprojektina. Ohjelmistolla generoidaan tarjousdokumentteja käyttäjän antamien tietojen pohjalta. Ohjelman tarkoituksena on helpottaa myyjien työtä ja saada tarjouksista ulkoasultaan yhteneviä.
Ohjelmistoa käytetään www-selaimen avulla ja se vaatii käynnistyäkseen hyväksyttävän tunnuksen ja salasanan. Tarjousta tehtäessä valitaan asiakas ja tuotteet, joita asiakkaalle aiotaan tarjota. Käyttäjä voi muokata tuotteiden hintoja määrätyissä rajoissa. Asiakas ja tuotetiedot tulevat tietokannasta. Lisäksi tietokannassa säilytetään tarjousdokumenttien ulkoasun määrääviä tiedostoja. Annettujen tietojen perusteella TAHKO generoi halutun muotoisia tarjousdokumentteja. Dokumentit voidaan tulostaa erilaisissa formaateissa (esim. PDF) ja ne voidaan tallentaa tietokantaan XML-muodossa, josta ne saadaan uudelleen muokattaviksi ja tulostettaviksi.
Tahkossa on kuusi osajärjestelmää (kuva 2.1): WWW-käyttöliittymä, Filteri, ApacheWrapper, Tietokanta, Servlet ja Profile. Www-käyttöliittymällä tarkoitetaan käyttäjän www-selaimessa näkyvää TAHKO:n osaa. Servlet on www-palvelimella ajettava Java-ohjelma, joka toimii välittäjänä käyttöliittymän ja muun TAHKO:n välillä. Tietokantaoperaatiot hoidetaan TAHKO:ssa JDBC:tä käyttävän Tietokanta-osajärjestelmän avulla, joka toimii yksinkertaistettuna Java-rajapintana relaatiotietokantaan. ApacheWrapper on yksinkertaistettu rajapinta Apachen XML- ja JSP-työkaluille. Filter-osajärjestelmä suodattaa tietokannasta tulevaa tietoa tuotteiden väliset riippuvuussuhteet huomioivaksi. Profiili-osajärjestelmä huolehtii sessionhalinnasta käyttäjän tehdessä tarjousta TAHKO:lla. Profiili-osajärjestelmä tallettaa käyttäjän tekemät asiakas- ja tuotevalinnat xml-muodossa käyttösession ajaksi. Tarkemmat kuvaukset kunkin osajärjestelmän suunnitelmista on kuvattu seuraavissa luvuissa (luvut 3-8).
Ohjelman käyttäjälle näkyvä käyttöliittymä on toteutettu XML:llä sisäänkirjautumista lukuunottamatta. Seuraavissa aliluvuissa on kuvattu käyttöliittymän eri vaiheet ja niihin liittyvä XML.
Sisäänkirjautumisikkunassa (kuva 3.1) käyttäjä antaa käyttäjätunnuksen ja salasanan päästäkseen järjestelmään. Sivulta lähtevät parametrit ovat käsittelevän sivun id (page=0), käyttäjätunnus (user_login) ja salasana (user_password). Onnistuneen sisäänkirjautumisen tuloksena siirrytään asiakkaan hakuun (kuva 3.2). JSP:ltä saadaan seuraavat asiat:
Vasenkehys:
Hakukentän luontiin tarvittava XML.
Tämänhetkinen tarjouksen tilanne. Käyttäjän tiedot selvillä.
Virheellinen salasana tai käyttäjätunnus palauttaa käyttäjän takaisin sisäänkirjautumissivulle (kuva 3.1).
Asiakkaan haku ikkunassa (kuva 3.2) käyttäjä voi hakea asiakkaita yrityksen tai yhteyshenkilön mukaan. Sivulta lähtevät parametrit ovat käsittelevän sivun id (page=1), hakusana (search) ja hakukategoria (category). Haku palauttaa listan kaikista hakuehdon täyttävistä asiakkaista (kuva 3.3). JSP:ltä saadaan seuraavat asiat:
Vasen kehys:
Hakukentän luontiin tarvittava XML ja suoritetun haun tulos.
Asiakashaun tuloksena saadusta listasta (kuva 3.3) valitaan haluttu asiakas painamalla Valitse-linkkiä. Jos haussa ei löytänyt yhtään asiakasta se kerrotaan käyttäjälle (kuva 3.4). Sivulta lähtevät parametrit ovat käsittelevän sivun id (page=2) ja asiakas id (customer_id). Kun asiakas on valittu siirrytään tuotteiden valinta sivulle (kuva 3.5) JSP:ltä saadaan seuraavat asiat:
Vasen kehys:
Tuotteiden hakukenttä.
Tuotteen haku ikkunassa (kuva 3.5) käyttäjä voi hakea tuotteita niiden nimen tai id:n mukaan. Sivulta lähtevät parametrit ovat käsittelevän sivun id (page=3), hakusana (search) ja hakukategoria (category). Haku palauttaa listan kaikista hakuehdon täyttävistä tuotteista (kuva 3.6). JSP:ltä saadaan seuraavat asiat:
Vasen kehys:
Hakukentän luontiin tarvittava XML ja haun tulos
Tuotehaun tuloksena saadusta listasta (kuva 3.6) valitaan haluttu tuote painamalla Valitse-linkkiä. Linkin painamisesta seuraa myös vasemman kehyksen uudelleenlataus. Jos haussa ei löytänyt yhtään tuotetta se kerrotaan käyttäjälle (kuva 3.7). Sivulta lähtevä parametrit ovat käsittelevän sivun id (page=4) tuote id (product_id). JSP:ltä saadaan seuraavat asiat:
Vasen kehys:
Hakukenttä
Tuotteiden hinnoittelu tapahtuu siten, että valittujen tuotteiden listassa (kuva 3.8) määritellään tuotteiden kappalemäärä ja yksikköhinta. Lisäksi käyttäjä voi määritellä alennusprosentin tarjoukselle. Jotta tuotteille määritellyt hinnat saadaan pysymään tallessa, pitää ne saada tallennettua sessioon aina silloin kun tarjoukseen lisätään tai poistetaan tuotteita tai vaihdetaan asiakasta.
Käyttäjä voi kirjoittaa tarjoukseen vapaamuotoista tekstiä. Tämän tekstin tarkoituksena on antaa käyttäjälle mahdollisuus kertoa lisää tarjoukseen liittyvistä yksityiskohdista (kuva 3.8).
Uusi tarjous luodaan painamalla Luo uusi tarjous -linkkiä sivun yläreunassa. Tämän jälkeen tarjouksen tiedot nollataan (paitsi myyjä). Sivulta lähtevä parametri on käsittelevän sivun id (page=5). Tilanne palautuu Asiakkaan haku -kohtaan (kuva 3.2).
Tallennettu tarjous avataan painamalla Avaa vanha tarjous -linkkiä, jolloin siirrytään tallennetun tarjouksen hakusivulle (kuva 3.9). Lähteväksi parametriksi asetetaan käsittelevän sivun id (page=6). Tarjousta etsitään asiakkaan nimen avulla ja mahdollisesti määritellään, kuinka uusi haettavan tarjouksen on oltava. Haussa lähtevät parametrit ovat käsittelevän sivun id (page=7), asiakkaan nimi (customer_name) ja aikaväli (how_old).
Tarjoushaun tuloksena saadusta listasta valitaan haluttu tuote painamalla
Valitse-linkkiä (kuva 3.6). Jos haussa ei löytänyt yhtään tuotetta, se kerrotaan
käyttäjälle. Haluttu tarjous avataan painamalla Avaa-linkkiä. Lähtevät
parametrit ovat käsittelevän sivun id (page=8) ja tarjouksen id (offer_id).
JSP:ltä saadaan seuraavat asiat:
Oikea kehys: Hakukentän luontiin tarvittava XML ja haun tulos.
Asiakasta vaihdetaan painamalla Vaihda asiakas -linkkiä. Lähtevät parametrit ovat käsittelevän sivun id (page=9), poistettavan asiakkaan id ja kaikki tarjouksen sen hetkiset tiedot. Oikean kehyksen tilanne palautuu kohtaan asiakkaan valinta (kuva 3.2).
Tuote poistetaan listasta painamalla Poista-linkkiä. Lähtevä parametri on käsittelevän sivun id (page=10), poistettavan tuoteen id ja kaikki tarjouksen sen hetkiset tiedot. Saatava XML on muuten sama kuin ennen, mutta siitä puuttuu kyseinen tuote (kuva 3.5 Tuotteen valinta).
Filtteri-osajärjestelmä huolehtii tietokannasta haetun 'raakatiedon' prosessoimisesta sopivaan XML-muotoon. Varsinaisia filttereitä ovat XMLFilter ja DependencyFilter. Muut osajärjestelmään kuuluvat luokat ovat näiden käyttämiä apuluokkia (kuva 4.1).
Osajärjestelmän ulospäinnäkyvät luokat ovat DependencyFilter ja XMLFilter (kuva 4.1). DependencyFilter käyttää sisäluokkiaan ProductFactorya ja DependencyFactorya muuntamaan saamansa syötteet ProductItem- ja DependencyRule-olioksi, jotka se antaa DependencyCore-luokan käsiteltäväksi. DependencyCore käyttää apunaan sisäluokkaansa ItemNode:a.
Osajärjestelmää käytetään XMLFilter- ja DependencyFilter-luokkien filter-metodeilla. Ne ottavat parametreina tietoa mm. DBResult-olioina ja tuottavat XML:ää.
Prosessoi tietokannasta haettua tuotelistausta asiakkaan profiilin ja tuoteriippuvuuksien perusteella. Tuotetusta XML:ästä ilmenee, mitä tuotteita ei voida myydä asiakkaalle ja mitkä vaativat joitain toisia tuotteita. Apuna käytetään DependencyCore-luokkaa, joka selvittää riippuvuudet.
ProductItem on DebendecyFilterin sisäluokka, jota käytetään tuotetietoja sisältävänä Item-toteutuksena.
ProductFactory on DependencyFilterin sisäluokka. Se muuttaa tuotetietoja sisältävän DBResult-olion ProductItem-taulukoksi.
Muuttaa riippuvuustietoja sisältävän DBResult-olion DependencyRule-taulukoksi. DependencyFilterin sisäluokka.
Item on rajapintaluokka, joka määrittelee DependencyCore:lla käsiteltävien olioiden rajapinnan.
DependencyRule kuvaa kahden tuotteen välistä riippuvuutta. Riippuvuus voi olla joko poissulkeva (exclude), tai vaativuus (include).
Luokka merkitsee annetun Item-taulukon alkiot annettujen tuoteriippuvuuksien ja asiakkaan profiilin perusteella. Item:in tila voi olla joko YES (voi valita), NO (ei voi valita) tai MORE (vaatii lisäksi muita). Mikäli tilaksi asetetaan NO, myös kaikkien niiden Item:ien, jotka vaativat sen tilaksi asetetaan NO.
Luokka on DependencyCoren käyttämä apuluokka, joka sisältää Itemin sekä viittaukset niihin Itemeihin, jotka tarvitsevat tätä. Näin muodostuu verkko, jonka avulla voidaan helposti asettaa rekursiivisesti Itemien tilaksi NO, kun niiden väliset (include-) riippuvuussuhteet ovat ensin tiedossa.
DBSlave on TaHKo:n osajärjestelmä, joka huolehtii tietokannan käsittelystä. Tähän kuuluu tiedon haku, jossain määrin sen talletus, sekä käyttäjien autentikointi. Osajärjestelmä sisältää kirjastoluokan DBSlave ja DBResult-luokan, jota käytetään palauttaessa tietokantahakujen tuloksia. Virhetilanteissa tuotetaan DBException tai jokin sen alaluokista.
DBSlave-luokka on yhteydessä tietokantaan ja tarjoaa tietokantapalveluja muille TaHKo:n osajärjestelmille. DBResult-luokka toimii tietovarastona hakutuloksia palautettaessa. Sillä voi kysellä tiedot yksitellen tai pyytä ne XML- tai DOM-muodossa (kuva 5.1).
Muut osajärjestelmät käyttävät tietokanta-osajärjestelmää DBSlave-luokan julkisten metodien avulla. DBSlave palauttaa tuloksensa joko XML-muodossa (Stringinä) tai DBResult-oliona, jolloin sen sisältämiin tietoihin pääsee käsiksi DBResult-luokan julkisilla metodeilla.
Tietokannan käsittelyyn käytetään JDBC-rajapintaa.
Tietokannan käsittely tapahtuu kutsumalla luokan DBSlave metodeja. Vapaamuotoisia hakuja suorittava getFromDatabase-metodi palauttaa haun tulokset DBResult-oliona, jolta tiedot voidaan kysellä stringeinä, kokonaislukuina, doubleina tai objekteina tai koko tulos voidaan muuntaa XML-muotoon.
DBSlave on staattinen kirjastoluokka. Ennenkuin tietokantatoimintoja voidaan käyttää, luokka täytyy alustaa kutsumalla metodia setDBServer, joka asettaa tarvittavat parameterit yhteyden saamiseksi tietokantaan.
Tämä osajärjestelmä huolehtii yhteydenpidosta TAHKO:n käyttäjien www-selaimiin. Osajärjestelmä sisältää vain yhden luokan: TahkoServlet, joka on HttpServletin aliluokka. Osajärjestelmä on nimensä mukaisesti servletti; se ladataan Tomcatiin, ja Tomcat kutsuu sen metodeja käyttäjän selaimestaan lähettämien http-requestien perusteella.
Servlet-osajärjestelmän metodeja käyttää ainostaan Tomcat. Sen sijaan Servlet itse kutsuu Db- ja ApacheWrapper -osajärjestelmien metodeja.
Tämä on servlet-osajärjestelmän ainoa luokka. Se on periytetty javax.servlet.HttpServlet:stä.
public void init(ServletConfig config) throws ServletException
Tämä on kuormitettu versio HttpServetin vastaavannimisestä funktiosta, joka käsittelee servletille annettavat, komentoriviparametrejä vastaavat alustusparametrit.
parametri: config servletille annettavat alustusparametrit. Tomcatia käytettäessä nämä annetaan web.xml -tiedostossa.
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
Tämä on kuormitettu versio HttpServetin vastaavannimisestä funktiosta, joka käsittelee käyttäjän www-selaimelta tulevan http get -pyynnön.
Tämä on kuormitettu versio HttpServetin vastaavannimisestä funktiosta, joka käsittelee käyttäjän www-selaimelta tulevan http post -pyynnön.
ApacheWrapper on osajärjestelmä, jonka tehtävänä on kapseloida Apachen (www.apache.org) työkalut. Tässä dokumentoidut luokat ja metodit ovat kaikki julkisia, ja muodostavat siten rajapinnan muihin osajärjestelmiin (kuva 7.1).
Tämä työkaluluokka kapseloi Apachen Fop PDF-generaattorin.
Tämä työkaluluokka kapseloi Apachen Xalan XML-prosessoijan.
Tämä työkaluluokka kapseloi Apachen Tomcat jsp-koneen.
Tämä osajärjestelmä huolehtii sessionhalinnasta käyttäjän tehdessä tarjousta TAHKO:lla. Profiili-osajärjestelmä tallettaa käyttäjän tekemät asiakas- ja tuotevalinnat xml-muodossa käyttösession ajaksi. Lopussa profiili-osajärjestelmään kootusta XML:stä tehdään lopullinen PDF-tarjous. Profiili-osajärjestelmää käytetään JSP-sivuilta käsin sekä Servletistä.
Profile on rajapintaluokka, joka määrittelee sessionhallinnassa käytettävän profiilin rajapinnan.
Tämä rajapintaluokka on periytetty Item-rajapinnasta. Se sisältää kaksi uutta metodia, jotka sopivat profiilielementtien käsittelyyn.
Tämä luokka toteuttaa ItemElement-rajapinnan. Se tallettaa elementin kentät Javan TreeMap -olioon.
Joissain kohdissa suunnittelua hidasteena tai haittana tarkalle suunnittelulle ilmeni kokemuksen puute vastaavista järjestelmistä ja niiden suunnittelusta. Kaiken kaikkiaan suunnittelu eteni kuitenkin hyvin, sillä porukasta löytyi ainakin yksi, joka hallitsi asian ja siten toteutus pysynee melko suoraviivaisena ja dokumentin pitäisi olla kattava.