// Copyright (c) 2006 by Leif Frenzel <himself@leiffrenzel.de>
// All rights reserved.
// Copyright (c) 2011 by Alejandro Serrano
package net.sf.eclipsefp.haskell.core.cabalmodel;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import net.sf.eclipsefp.haskell.buildwrapper.types.Component;
import net.sf.eclipsefp.haskell.buildwrapper.types.Component.ComponentType;
/** <p>The root of the package description model, represents the contents of a
* <code>.cabal</code> file.</p>
*
* @author Leif Frenzel
* @author Alejandro Serrano
*/
public class PackageDescription {
private final List<PackageDescriptionStanza> stanzas;
PackageDescription() {
stanzas = new ArrayList<>();
}
public PackageDescription(final String name){
this();
PackageDescriptionStanza pds = new PackagePropertiesStanza(this, 0 );
stanzas.add( pds );
pds.update( CabalSyntax.FIELD_NAME, name );
}
public List<PackageDescriptionStanza> getStanzas() {
return stanzas;
}
public PackageDescriptionStanza getPackageStanza() {
if (getStanzas().size()>0 && getStanzas().get(0) instanceof PackagePropertiesStanza){
return getStanzas().get(0);
}
return null;
}
public PackageDescriptionStanza getLibraryStanza() {
return getComponentStanza( new Component( ComponentType.LIBRARY, null, null, true ) );
}
public List<PackageDescriptionStanza> getExecutableStanzas() {
Vector<PackageDescriptionStanza> result = new Vector<>();
for (PackageDescriptionStanza stanza : getStanzas()) {
if (stanza.getType() == CabalSyntax.SECTION_EXECUTABLE) {
result.add( stanza );
}
}
return result;
}
public List<PackageDescriptionStanza> getTestSuiteStanzas() {
Vector<PackageDescriptionStanza> result = new Vector<>();
for (PackageDescriptionStanza stanza : getStanzas()) {
if (stanza.getType() == CabalSyntax.SECTION_TESTSUITE) {
result.add( stanza );
}
}
return result;
}
public List<PackageDescriptionStanza> getBenchmarkStanzas() {
Vector<PackageDescriptionStanza> result = new Vector<>();
for (PackageDescriptionStanza stanza : getStanzas()) {
if (stanza.getType() == CabalSyntax.SECTION_BENCHMARK) {
result.add( stanza );
}
}
return result;
}
public PackageDescriptionStanza addStanza(final CabalSyntax type,final String name){
int startLine=stanzas.get(stanzas.size()-1).getEndLine()+1;
PackageDescriptionStanza pds=new PackageDescriptionStanza(this, type, name, startLine );
pds.setEndLine( startLine+1 );
stanzas.add( pds );
return pds;
}
/**
* add the existing stanza from another description to this description
* @param pds
*/
public void addStanza(final PackageDescriptionStanza pds){
pds.move( this );
}
public void removeStanza(final PackageDescriptionStanza stanza) {
boolean found = false;
int diff = 0;
for (PackageDescriptionStanza st : getStanzas()) {
if (st == stanza) {
diff = - (st.getEndLine() - st.getStartLine() + 1);
found = true;
continue;
}
if (found) {
st.diffLine( diff );
}
}
this.stanzas.remove( stanza );
}
public Map<String, List<PackageDescriptionStanza>> getStanzasBySourceDir(){
Map<String, List<PackageDescriptionStanza>> ret=new HashMap<>();
for (PackageDescriptionStanza pds:stanzas){
Collection<String> sds=pds.getSourceDirs();
for (String t:sds){
if (t.length()>0){
List<PackageDescriptionStanza> pdss=ret.get( t );
if (pdss==null){
pdss=new LinkedList<>();
ret.put( t, pdss );
}
pdss.add(pds);
}
}
}
return ret;
}
public Collection<String> getAllSourceDirs() {
HashSet<String> result = new HashSet<>();
for (PackageDescriptionStanza pds:stanzas){
Collection<String> sds=pds.getSourceDirs();
result.addAll( sds );
}
return result;
}
public Collection<String> getAllNonHaskellFiles() {
HashSet<String> result = new HashSet<>();
for (PackageDescriptionStanza pds:stanzas){
Collection<String> sds=pds.getNonHaskellFiles();
result.addAll( sds );
}
return result;
}
public void dump(final Writer w) throws IOException {
for (PackageDescriptionStanza pds:stanzas){
pds.dump( w, 0 );
}
}
public String dump(){
StringWriter sw=new StringWriter();
try {
dump( sw );
String s=sw.toString();
return s;
} catch (IOException ioe){
// cannot happen
}
return null;
}
public PackageDescriptionStanza getComponentStanza(final Component c){
for (PackageDescriptionStanza pds:stanzas){
if (CabalSyntax.SECTION_LIBRARY.equals( pds.getType()) && c.getType().equals( ComponentType.LIBRARY )){
return pds;
}
if (CabalSyntax.SECTION_EXECUTABLE.equals(pds.getType()) && c.getType().equals( ComponentType.EXECUTABLE ) && pds.getName().equals(c.getName())){
return pds;
}
if (CabalSyntax.SECTION_TESTSUITE.equals(pds.getType()) && c.getType().equals( ComponentType.TESTSUITE ) && pds.getName().equals(c.getName())){
return pds;
}
if (CabalSyntax.SECTION_BENCHMARK.equals(pds.getType()) && c.getType().equals( ComponentType.BENCHMARK ) && pds.getName().equals(c.getName())){
return pds;
}
}
return null;
}
public PackageDescriptionStanza getSameStanza(final PackageDescriptionStanza p){
for (PackageDescriptionStanza pds:stanzas){
if (pds.getType()==null && p.getType()==null){
return pds;
}
if (CabalSyntax.SECTION_LIBRARY.equals( pds.getType()) && CabalSyntax.SECTION_LIBRARY.equals( p.getType())){
return pds;
}
if (CabalSyntax.SECTION_EXECUTABLE.equals(pds.getType()) && CabalSyntax.SECTION_EXECUTABLE.equals(p.getType() ) && pds.getName().equals(p.getName())){
return pds;
}
if (CabalSyntax.SECTION_TESTSUITE.equals(pds.getType()) && CabalSyntax.SECTION_TESTSUITE.equals(p.getType() ) && pds.getName().equals(p.getName())){
return pds;
}
if (CabalSyntax.SECTION_BENCHMARK.equals(pds.getType()) && CabalSyntax.SECTION_BENCHMARK.equals(p.getType() ) && pds.getName().equals(p.getName())){
return pds;
}
}
return null;
}
}