Täydentävä projektin koontitoiminto on objekti, joka käsittelee projektin resursseja tietyllä tavalla. Täydentäviä projektien koontitoimintoja käytetään usein resurssin muunnossa, jonka tuloksena on toisenlainen resurssi tai artefakti. Koontitoiminnon luomat resurssit on yleensä merkitty johdetuiksi resursseiksi.
Lisäosat lisäävät ympäristöön täydentäviä projektin koontitoimintoja, jotta ne voivat toteuttaa erityisiä resurssien muuntoja. Esimerkiksi JDT (Java development tools) määrittää täydentävän projektin koontitoiminnon, joka kääntää Java-lähdetiedoston luokkatiedostoksi aina, kun tiedosto lisätään tai sitä muokataan Java-projektissa. Se myös seuraa alisteisia tiedostoja ja kokoaa ne uudelleen tarvittaessa.
Ohjelmointirajapinnan näkökulmasta ympäristö määrittää kaksi koontien peruslajia:
Täydentävät koonnit täytetään resurssin muutosten deltan avulla. Delta kuvaa kaikkien projektissa tapahtuneiden muutosten yhteisvaikutusta projektin edellisen koonnin jälkeen. Tämä delta on samankaltainen kuin se, jota käytetään resurssien muutostapahtumien sisällä.
Käyttäjä voi säännöllisin väliajoin puhdistaa projektit pakottaakseen koko projektin koonnin uudelleen, kun täydentävä koonti seuraavan kerran ajetaan projektissa. Projektin puhdistus poistaa koontitiedot, kuten ongelmamerkinnät ja luokkatiedostot.
Koontitoiminnot on helpointa selittää esimerkin avulla. JDT Java -kääntäjää ohjaa täydentävä Java-projektinkoontitoiminto, joka kääntää tiedostot uudelleen projektissa, johon on tullut muutoksia. Kun täydellinen koonti liipaistaan (tai täydentävä koonti puhdistuksen jälkeen), projektin kaikki .java-tiedostot käännetään. Käännökseen liittyvät ongelmat lisätään ongelmamerkintöinä asianmukaisiin .java-tiedostoihin. Kun täydentävä koonti liipaistaan, koontitoiminto kääntää valikoivasti uudelleen lisätyt, muutetut tai muutoin vaikutuksen kohteena olleet .java-tiedostot, jotka on kuvattu resurssien deltassa, ja päivittää ongelmamerkinnät tarpeen mukaan. Kaikki .class-tiedostot tai merkinnät, jotka eivät enää ole tarpeen, poistetaan.
Täydentävällä koonnilla on ilmeisiä etuja projekteissa, joissa on satoja tai tuhansia resursseja, joista suurin osa ei muutu millään tavalla.
Täydentävän koonnin tekninen haasteellisuus on sen määrittämisessä, mitkä kohteet on koottava uudelleen. Esimerkiksi Java-koontitoiminnon ylläpitämään sisäiseen tilaan sisältyy riippuvuuskaavion ja raportoitujen käännösongelmien luettelon kaltaisia asioita. Näitä tietoja käytetään täydentävässä luonnissa yksilöimään, mitkä luokat on käännettävä uudelleen Java-resurssin muutosten seurauksena.
Vaikka koonnin perusrakenne on määritetty ympäristössä, todellisen työn tekee koontitoiminnon koodi. Monimutkaisten täydentävien koontitoimintojen mallien esittely ei ole mahdollista tämän esityksen yhteydessä, koska toteutus määräytyy kunkin koontitoiminnon rakenteen mukaan.
Koontitoimintoa voi kutsua suoraan seuraavilla kahdella tavalla:
Käytännössä työympäristön käyttäjä liipaisee koonnin valitsemalla vastaavat komennot resurssien navigaattorinäkymän valikossa.
Ympäristö voi kutsua täydentäviä projektin koontitoimintoja epäsuorasti automaattisen koonnin aikana. Jos tämä ominaisuus on käytössä, automaattinen koonti ajetaan aina kun työtilaa muutetaan.
Laajennuspisteen org.eclipse.core.resources.builders avulla voit lisätä täydentävän projektin koontitoiminnon määrityksen. Seuraava merkintä osoittaa, kuinka kuvitteellinen lisäosa com.example.builders voi lisätä täydentävän projektin koontitoiminnon.
<extension id="mybuilder" name="My Sample Builder" point="org.eclipse.core.resources.builders"> <builder <run class="com.example.builders.BuilderExample"> <parameter name="optimize" value="true" /> <parameter name="comment" value="Builder comment" /> </run> </builder> </extension>
Laajennuspisteessä yksilöidyn luokan on laajennettava ympäristön luokkaa IncrementalProjectBuilder.
public class BuilderExample extends IncrementalProjectBuilder { IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { // lisää koontilogiikka tähän return null; } protected void startupOnInitialize() { // lisää koontitoiminnon alustuslogiikka tähän } protected void clean(IProgressMonitor monitor) { // lisää koontitoiminnon puhdistuslogiikka tähän } }
Koonnin käsittely alkaa build()-metodin avulla, jossa on tietoja pyydetystä koonnista. Koonnilla on jokin seuraavista arvoista:
Jos täydentävää koontia on pyydetty, annetaan resurssin delta, joka kuvaa edellisen koonnin jälkeen resursseissa tapahtuneet muutokset. Seuraavassa katkelmassa tarkennetaan build()-metodia.
protected IProject[] build(int kind, Map args, IProgressMonitor monitor throws CoreException { if (kind == IncrementalProjectBuilder.FULL_BUILD) { fullBuild(monitor); } else { IResourceDelta delta = getDelta(getProject()); if (delta == null) { fullBuild(monitor); } else { incrementalBuild(delta, monitor); } } return null; }
Joskus käy niin, että projektin "X," koonnin yhteydessä koontitoiminto tarvitsee tietoja muutoksista, toisessa projektissa "Y." (Esimerkiksi jos projektin X Java-luokka toteuttaa projektin Y toimittaman rajapinnan.) Projektin X koonnin yhteydessä projektin Y deltan saa käyttöön kutsumalla metodia getDelta(Y). Jotta voidaan varmistaa, että ympäristö pystyy toimittamaan tällaiset deltat, projektin X koontitoiminnon täytyy esitellä projektien X ja Y välinen riippuvuus palauttamalla taulukko, joka sisältää projektin Y aiemmasta build()-kutsusta. Jos koontitoiminnolla ei ole riippuvuuksia, se palauttaa tyhjäarvon. Lisätietoja on kohdassa IncrementalProjectBuilder.
Täydellisen koonnin pyynnön käsittelyn edellyttämä logiikka on lisäosakohtainen. Se voi tarkoittaa projektin jokaisen resurssin läpikäyntiä tai jopa sen selvittämistä, onko projektin ja muiden projektien välillä riippuvuuksia. Seuraava katkelma on ehdotus täydellisen koonnin toteutuksesta.
protected void fullBuild(final IProgressMonitor monitor) throws CoreException { try { getProject().accept(new MyBuildVisitor()); } catch (CoreException e) { } }
Koonnin läpikäyntitoiminto toteuttaa tietyn resurssin koonnin (ja vastaa true jatkaakseen kaikkien aliresurssien läpikäyntiä).
class MyBuildVisitor implements IResourceVisitor { public boolean visit(IResource res) { //kokoa määritetty resurssi. //jatka aliobjektien läpikäyntiä palauttamalla arvo true. return true; } }
Läpikäynti jatkuu, kunnes koko resurssirakenne on käyty läpi.
Kun toteutat täydentävän koonnin, koontitoiminto käsittelee resurssien muutosten deltaa eikä koko resurssirakennetta.
protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException { // läpikäyntitoiminto tekee työn. delta.accept(new MyBuildDeltaVisitor()); }
Läpikäynti jatkuu, kunnes koko resurssien muutosten deltan rakenne on käyty läpi. Muutosten tarkka luonne on samankaltainen kuin kohdassa Resurssien muutosten kuuntelutoiminnon toteutus on kuvattu. Yksi tärkeä ero kuitenkin on. Täydentävät projektien koontitoiminnot nimittäin käsittelevät tiettyyn projektiin perustuvaa resurssien deltaa, eivät koko työtilaa.
Työympäristössä käyttäjät voivat puhdistaa projektin tai projektijoukon ennen koonnin aloitusta. Tämän ominaisuuden avulla käyttäjä voi pakottaa koonnin uudelleen alusta alkaen tiettyihin projekteihin. Koontitoimintojen on toteutettava tämä metodi, jos projektista on tarkoitus puhdistaa ongelmamerkinnät ja johdetut resurssit.
Jos haluat saattaa koontitoiminnon tietyn projektin käyttöön, se on sisällytettävä projektin koontimäärityksiin. Projektin koontimääritys on luettelo projektin koonnin yhteydessä ajettavista komennoista ja niiden järjestyksestä. Kussakin komennossa nimetään yksi täydentävä projektin koontitoiminto.
HUOMAUTUS: Koontikomennossa oleva koontitoiminnon nimi on koontitoiminnon laajennuksen tarkka tunnus. Laajennuksen tarkka tunnus luodaan yhdistämällä lisäosan tunnus yksinkertaiseen laajennustunnukseen plugin.xml-tiedostossa. Esimerkiksi koontitoiminto, jolla on yksinkertainen laajennustunnus "mybuilder" lisäosassa "com.example.builders", saa nimen "com.example.builders.mybuilder".
Seuraavassa katkelmassa lisätään uusi koontitoiminto aiemman koontitoimintoluettelon ensimmäiseksi koontitoiminnoksi.
final String BUILDER_ID = "com.example.builders.mybuilder"; IProjectDescription desc = project.getDescription(); ICommand[] commands = desc.getBuildSpec(); boolean found = false; for (int i = 0; i < commands.length; ++i) { if (commands[i].getBuilderName().equals(BUILDER_ID)) { found = true; break; } } if (!found) { //lisää koontitoiminto projektiin ICommand command = desc.newCommand(); command.setBuilderName(BUILDER_ID); ICommand[] newCommands = new ICommand[commands.length + 1]; // Lisää se ennen muita koontitoimintoja. System.arraycopy(commands, 0, newCommands, 1, commands.length); newCommands[0] = command; desc.setBuildSpec(newCommands); project.setDescription(desc, null); }
Projektin koontitoiminnon kokoonpanon määritys tehdään vain kerran, yleensä projektin luonnin yhteydessä. Yleinen tapa liittää koontitoiminto projektiin on määrittää projektiluonne.