sascha@982: package de.intevation.flys.artifacts.datacage;
sascha@982: 
sascha@990: import java.util.Collection;
sascha@991: import java.util.List;
sascha@1024: import java.util.Date;
sascha@990: 
sascha@984: import java.sql.SQLException;
sascha@991: import java.sql.PreparedStatement;
sascha@990: import java.sql.Types;
sascha@1025: import java.sql.Timestamp;
sascha@984: 
sascha@982: import de.intevation.artifacts.GlobalContext;
sascha@999: import de.intevation.artifacts.ArtifactCollection;
sascha@999: import de.intevation.artifacts.User;
sascha@982: 
sascha@983: import de.intevation.artifactdatabase.db.SQL;
sascha@983: import de.intevation.artifactdatabase.db.SQLExecutor;
sascha@983: 
sascha@982: import de.intevation.artifactdatabase.LifetimeListener;
sascha@999: import de.intevation.artifactdatabase.Backend;
sascha@982: 
sascha@990: import de.intevation.artifactdatabase.data.StateData;
sascha@990: 
sascha@991: import de.intevation.artifactdatabase.state.Output;
sascha@992: import de.intevation.artifactdatabase.state.Facet;
sascha@991: 
sascha@984: import de.intevation.artifacts.Artifact;
sascha@984: import de.intevation.artifacts.ArtifactDatabase;
sascha@984: import de.intevation.artifacts.ArtifactDatabaseException;
sascha@984: 
sascha@984: import de.intevation.flys.artifacts.FLYSArtifact;
sascha@984: 
sascha@984: import de.intevation.artifacts.common.utils.LRUCache;
sascha@984: 
sascha@982: import org.apache.log4j.Logger;
sascha@982: 
sascha@982: import org.w3c.dom.Document;
sascha@982: 
sascha@982: public class Datacage
sascha@1002: implements   LifetimeListener
sascha@982: {
sascha@982:     private static Logger log = Logger.getLogger(Datacage.class);
sascha@982: 
sascha@999:     public static final String DATACAGE_KEY =
sascha@999:         "global.datacage.instance";
sascha@999: 
sascha@984:     public static final String ARTEFACT_DATABASE_KEY =
sascha@984:         "global.artifact.database";
sascha@984: 
sascha@987:     private String SQL_DELETE_ALL_USERS      = "delete.all.users";
sascha@996:     private String SQL_DELETE_ALL_ARTIFACTS  = "delete.all.artifacts";
sascha@987:     private String SQL_USER_ID_NEXTVAL       = "user.id.nextval";
sascha@987:     private String SQL_USER_BY_GID           = "user.by.gid";
sascha@987:     private String SQL_INSERT_USER           = "insert.user";
sascha@987:     private String SQL_COLLECTION_BY_GID     = "collection.by.gid";
sascha@987:     private String SQL_COLLECTION_ID_NEXTVAL = "collection.id.nextval";
sascha@987:     private String SQL_INSERT_COLLECTION     = "insert.collection";
sascha@988:     private String SQL_ARTIFACT_BY_GID       = "artifact.by.gid";
sascha@988:     private String SQL_COLLECTION_ITEM_ID_NEXTVAL =
sascha@988:         "collection.item.id.nextval";
sascha@988:     private String SQL_INSERT_COLLECTION_ITEM = "insert.collection.item";
sascha@989:     private String SQL_ARTIFACT_ID_NEXTVAL    = "artifact.id.nextval";
sascha@989:     private String SQL_INSERT_ARTIFACT        = "insert.artifact";
sascha@991:     private String SQL_ARTIFACT_DATA_ID_NEXTVAL = "artifact.data.id.nextval";
sascha@990:     private String SQL_INSERT_ARTIFACT_DATA   = "insert.artifact.data";
sascha@991:     private String SQL_OUT_ID_NEXTVALUE       = "out.id.nextval";
sascha@991:     private String SQL_INSERT_OUT             = "insert.out";
sascha@992:     private String SQL_FACET_ID_NEXTVAL       = "facet.id.nextval";
sascha@992:     private String SQL_INSERT_FACET           = "insert.facet";
sascha@1003:     private String SQL_UPDATE_COLLECTION_NAME = "update.collection.name";
sascha@1003:     private String SQL_DELETE_ARTIFACT_FROM_COLLECTION =
sascha@1003:         "delete.artifact.from.collection";
sascha@1004:     private String SQL_DELETE_COLLECTION_BY_GID =
sascha@1004:         "delete.collection.by.gid";
sascha@1004:     private String SQL_DELETE_USER_BY_GID = "delete.user.by.gid";
sascha@1004:     private String SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID =
sascha@1004:         "delete.artifact.data.by.artifact.id";
sascha@1004:     private String SQL_DELETE_OUTS_BY_ARTIFACT_ID =
sascha@1004:         "delete.outs.by.artifact.id";
sascha@1004:     private String SQL_DELETE_FACETS_BY_ARTIFACT_ID =
sascha@1008:         "delete.facets.by.artifact.id";
sascha@1006:     private String SQL_DELETE_ARTIFACT_BY_GID =
sascha@1006:         "delete.artifact.by.gid";
sascha@984: 
sascha@983:     protected SQLExecutor sqlExecutor;
sascha@983: 
sascha@984:     public class InitialScan 
sascha@984:     implements   ArtifactDatabase.ArtifactLoadedCallback
sascha@984:     {
sascha@984:         protected LRUCache<String, Integer> users;
sascha@986:         protected LRUCache<String, Integer> collections;
sascha@988:         protected LRUCache<String, Integer> artifacts;
sascha@984: 
sascha@991:         protected GlobalContext context;
sascha@991: 
sascha@984:         public InitialScan() {
sascha@986:             users       = new LRUCache<String, Integer>();
sascha@986:             collections = new LRUCache<String, Integer>();
sascha@988:             artifacts   = new LRUCache<String, Integer>();
sascha@984:         }
sascha@984: 
sascha@991:         public InitialScan(GlobalContext context) {
sascha@991:             this();
sascha@991:             this.context = context;
sascha@991:         }
sascha@991: 
sascha@984:         @Override
sascha@984:         public void artifactLoaded(
sascha@984:             String   userId,
sascha@984:             String   collectionId,
sascha@1009:             String   collectionName,
sascha@1024:             Date     collectionCreated,
sascha@984:             String   artifactId,
sascha@1024:             Date     artifactCreated,
sascha@984:             Artifact artifact
sascha@984:         ) {
sascha@984:             if (!(artifact instanceof FLYSArtifact)) {
sascha@984:                 log.warn("ignoring none FLYS artifacts");
sascha@984:                 return;
sascha@984:             }
sascha@984: 
sascha@984:             FLYSArtifact flysArtifact = (FLYSArtifact)artifact;
sascha@986: 
sascha@986:             Integer uId = getUserId(userId);
sascha@1025:             Integer cId = getCollectionId(
sascha@1025:                 collectionId, uId, collectionName, collectionCreated);
sascha@987: 
sascha@1025:             storeArtifact(artifactId, cId, flysArtifact, artifactCreated);
sascha@984:         }
sascha@984: 
sascha@987:         protected Integer getId(
sascha@987:             LRUCache<String, Integer> cache,
sascha@987:             final String              idString,
sascha@987:             final String              selectById
sascha@987:         ) {
sascha@987:             Integer id = cache.get(idString);
sascha@987:             if (id != null) {
sascha@987:                 return id;
sascha@986:             }
sascha@986: 
sascha@986:             final Integer [] res = new Integer[1];
sascha@986: 
sascha@986:             SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@986:                 @Override
sascha@986:                 public boolean doIt() throws SQLException {
sascha@987:                     prepareStatement(selectById);
sascha@987:                     stmnt.setString(1, idString);
sascha@986:                     result = stmnt.executeQuery();
sascha@986:                     if (!result.next()) {
sascha@986:                         return false;
sascha@986:                     }
sascha@986:                     res[0] = result.getInt(1);
sascha@986:                     return true;
sascha@986:                 }
sascha@986:             };
sascha@986: 
sascha@986:             if (exec.runRead()) {
sascha@987:                 cache.put(idString, res[0]);
sascha@986:                 return res[0];
sascha@986:             }
sascha@986: 
sascha@987:             return null;
sascha@987:         }
sascha@987: 
sascha@988:         protected void storeArtifact(
sascha@989:             final String       artifactId,
sascha@989:             Integer            collectionId,
sascha@1025:             final FLYSArtifact artifact,
sascha@1025:             final Date         artifactCreated
sascha@988:         ) {
sascha@988:             Integer aId = getId(artifacts, artifactId, SQL_ARTIFACT_BY_GID);
sascha@988: 
sascha@988:             if (aId != null) {
sascha@988:                 // We've already stored it. Just create the collection item.
sascha@988:                 storeCollectionItem(collectionId, aId);
sascha@988:                 return;
sascha@988:             }
sascha@988:             // We need to write it to database
sascha@989: 
sascha@989:             final Integer [] res = new Integer[1];
sascha@989: 
sascha@989:             SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@989:                 @Override
sascha@989:                 public boolean doIt() throws SQLException {
sascha@989:                     prepareStatement(SQL_ARTIFACT_ID_NEXTVAL);
sascha@989:                     result = stmnt.executeQuery();
sascha@989:                     if (!result.next()) {
sascha@989:                         return false;
sascha@989:                     }
sascha@989:                     res[0] = result.getInt(1);
sascha@989:                     reset();
sascha@989:                     prepareStatement(SQL_INSERT_ARTIFACT);
sascha@989:                     stmnt.setInt   (1, res[0]);
sascha@989:                     stmnt.setString(2, artifactId);
sascha@989:                     stmnt.setString(3, artifact.getCurrentStateId());
sascha@1025:                     Timestamp timestamp = new Timestamp(artifactCreated != null
sascha@1025:                         ? artifactCreated.getTime()
sascha@1025:                         : System.currentTimeMillis());
sascha@1025:                     stmnt.setTimestamp(4, timestamp);
sascha@989:                     stmnt.execute();
sascha@990:                     conn.commit();
sascha@989:                     return true;
sascha@989:                 }
sascha@989:             };
sascha@989: 
sascha@989:             if (!exec.runWrite()) {
sascha@989:                 log.error("storing of artifact failed.");
sascha@989:                 return;
sascha@989:             }
sascha@989: 
sascha@989:             artifacts.put(artifactId, aId = res[0]);
sascha@989: 
sascha@989:             storeCollectionItem(collectionId, aId);
sascha@989: 
sascha@990:             storeData(aId, artifact);
sascha@990: 
sascha@1002:             storeOuts(aId, artifact, context);
sascha@991:         }
sascha@991: 
sascha@990: 
sascha@988:         protected void storeCollectionItem(
sascha@988:             final Integer collectionId,
sascha@988:             final Integer artifactId
sascha@988:         ) {
sascha@988:             SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@988:                 @Override
sascha@988:                 public boolean doIt() throws SQLException {
sascha@988:                     prepareStatement(SQL_COLLECTION_ITEM_ID_NEXTVAL);
sascha@988:                     result = stmnt.executeQuery();
sascha@988:                     if (!result.next()) {
sascha@988:                         return false;
sascha@988:                     }
sascha@988:                     int ciId = result.getInt(1);
sascha@988:                     reset();
sascha@988:                     prepareStatement(SQL_INSERT_COLLECTION_ITEM);
sascha@988:                     stmnt.setInt(1, ciId);
sascha@988:                     stmnt.setInt(2, collectionId);
sascha@988:                     stmnt.setInt(3, artifactId);
sascha@988:                     stmnt.execute();
sascha@990:                     conn.commit();
sascha@988:                     return true;
sascha@988:                 }
sascha@988:             };
sascha@988: 
sascha@988:             if (!exec.runWrite()) {
sascha@988:                 log.error("storing of collection item failed.");
sascha@988:             }
sascha@988:         }
sascha@987: 
sascha@987:         protected Integer getCollectionId(
sascha@987:             final String  collectionId,
sascha@987:             final Integer ownerId,
sascha@1025:             final String  collectionName,
sascha@1025:             final Date    collectionCreated
sascha@987:         ) {
sascha@987:             Integer c = getId(collections, collectionId, SQL_COLLECTION_BY_GID);
sascha@987: 
sascha@987:             if (c != null) {
sascha@987:                 return c;
sascha@987:             }
sascha@987: 
sascha@987:             final Integer [] res = new Integer[1];
sascha@987: 
sascha@987:             SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@987:                 @Override
sascha@987:                 public boolean doIt() throws SQLException {
sascha@987:                     prepareStatement(SQL_COLLECTION_ID_NEXTVAL);
sascha@987:                     result = stmnt.executeQuery();
sascha@987:                     if (!result.next()) {
sascha@987:                         return false;
sascha@987:                     }
sascha@987:                     res[0] = result.getInt(1);
sascha@987:                     reset();
sascha@987:                     prepareStatement(SQL_INSERT_COLLECTION);
sascha@987:                     stmnt.setInt   (1, res[0]);
sascha@987:                     stmnt.setString(2, collectionId);
sascha@987:                     stmnt.setInt   (3, ownerId);
sascha@1009:                     setString(stmnt, 4, collectionName);
sascha@1025:                     Timestamp timestamp = new Timestamp(collectionCreated != null
sascha@1025:                         ? collectionCreated.getTime()
sascha@1025:                         : System.currentTimeMillis());
sascha@1025:                     stmnt.setTimestamp(5, timestamp);
sascha@987:                     stmnt.execute();
sascha@990:                     conn.commit();
sascha@987:                     return true;
sascha@987:                 }
sascha@987:             };
sascha@987: 
sascha@987:             if (exec.runWrite()) {
sascha@987:                 collections.put(collectionId, res[0]);
sascha@987:                 return res[0];
sascha@987:             }
sascha@987: 
sascha@987:             return null;
sascha@987:         }
sascha@987: 
sascha@987:         protected Integer getUserId(final String userId) {
sascha@987: 
sascha@987:             Integer u = getId(users, userId, SQL_USER_BY_GID);
sascha@987: 
sascha@987:             if (u != null) {
sascha@987:                 return u;
sascha@987:             }
sascha@987: 
sascha@987:             final Integer [] res = new Integer[1];
sascha@987: 
sascha@987:             SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@986:                 @Override
sascha@986:                 public boolean doIt() throws SQLException {
sascha@986:                     prepareStatement(SQL_USER_ID_NEXTVAL);
sascha@986:                     result = stmnt.executeQuery();
sascha@986:                     if (!result.next()) {
sascha@986:                         return false;
sascha@986:                     }
sascha@986:                     res[0] = result.getInt(1);
sascha@986:                     reset();
sascha@986:                     prepareStatement(SQL_INSERT_USER);
sascha@986:                     stmnt.setInt   (1, res[0]);
sascha@986:                     stmnt.setString(2, userId);
sascha@986:                     stmnt.execute();
sascha@990:                     conn.commit();
sascha@986:                     return true;
sascha@986:                 }
sascha@986:             };
sascha@986: 
sascha@986:             if (exec.runWrite()) {
sascha@986:                 users.put(userId, res[0]);
sascha@986:                 return res[0];
sascha@986:             }
sascha@986: 
sascha@986:             return null;
sascha@986:         }
sascha@986: 
sascha@984:         public boolean scan(ArtifactDatabase adb) {
sascha@993:             log.debug("scan");
sascha@984:             try {
sascha@984:                 adb.loadAllArtifacts(this);
sascha@984:             }
sascha@984:             catch (ArtifactDatabaseException ade) {
sascha@984:                 log.error(ade);
sascha@984:                 return false;
sascha@984:             }
sascha@984:             return true;
sascha@984:         }
sascha@984:     } // class InitialScan
sascha@984: 
sascha@984: 
sascha@982:     public Datacage() {
sascha@982:     }
sascha@982: 
sascha@982:     @Override
sascha@982:     public void setup(Document document) {
sascha@982:         log.debug("setup");
sascha@983:         DBConfig config = DBConfig.getInstance();
sascha@983:         setupSQL(config.getSQL());
sascha@983:         sqlExecutor = new SQLExecutor(config.getDBConnection());
sascha@983:     }
sascha@983: 
sascha@983:     protected void setupSQL(SQL sql) {
sascha@987:         SQL_DELETE_ALL_USERS      = sql.get(SQL_DELETE_ALL_USERS);
sascha@996:         SQL_DELETE_ALL_ARTIFACTS  = sql.get(SQL_DELETE_ALL_ARTIFACTS);
sascha@987:         SQL_USER_ID_NEXTVAL       = sql.get(SQL_USER_ID_NEXTVAL);
sascha@987:         SQL_USER_BY_GID           = sql.get(SQL_USER_BY_GID);
sascha@987:         SQL_INSERT_USER           = sql.get(SQL_INSERT_USER);
sascha@987:         SQL_COLLECTION_BY_GID     = sql.get(SQL_COLLECTION_BY_GID);
sascha@987:         SQL_COLLECTION_ID_NEXTVAL = sql.get(SQL_COLLECTION_ID_NEXTVAL);
sascha@987:         SQL_INSERT_COLLECTION     = sql.get(SQL_INSERT_COLLECTION);
sascha@988:         SQL_ARTIFACT_BY_GID       = sql.get(SQL_ARTIFACT_BY_GID);
sascha@988:         SQL_COLLECTION_ITEM_ID_NEXTVAL =
sascha@988:             sql.get(SQL_COLLECTION_ITEM_ID_NEXTVAL);
sascha@988:         SQL_INSERT_COLLECTION_ITEM =
sascha@988:             sql.get(SQL_INSERT_COLLECTION_ITEM);
sascha@989:         SQL_ARTIFACT_ID_NEXTVAL = sql.get(SQL_ARTIFACT_ID_NEXTVAL);
sascha@989:         SQL_INSERT_ARTIFACT     = sql.get(SQL_INSERT_ARTIFACT);
sascha@991:         SQL_ARTIFACT_DATA_ID_NEXTVAL = sql.get(SQL_ARTIFACT_DATA_ID_NEXTVAL);
sascha@990:         SQL_INSERT_ARTIFACT_DATA = sql.get(SQL_INSERT_ARTIFACT_DATA);
sascha@991:         SQL_OUT_ID_NEXTVALUE     = sql.get(SQL_OUT_ID_NEXTVALUE);
sascha@991:         SQL_INSERT_OUT           = sql.get(SQL_INSERT_OUT);
sascha@992:         SQL_FACET_ID_NEXTVAL     = sql.get(SQL_FACET_ID_NEXTVAL);
sascha@992:         SQL_INSERT_FACET         = sql.get(SQL_INSERT_FACET);
sascha@1003:         SQL_UPDATE_COLLECTION_NAME = sql.get(SQL_UPDATE_COLLECTION_NAME);
sascha@1003:         SQL_DELETE_ARTIFACT_FROM_COLLECTION =
sascha@1003:             sql.get(SQL_DELETE_ARTIFACT_FROM_COLLECTION);
sascha@1004:         SQL_DELETE_COLLECTION_BY_GID = sql.get(SQL_DELETE_COLLECTION_BY_GID);
sascha@1004:         SQL_DELETE_USER_BY_GID       = sql.get(SQL_DELETE_USER_BY_GID);
sascha@1004:         SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID =
sascha@1004:             sql.get(SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID);
sascha@1004:         SQL_DELETE_OUTS_BY_ARTIFACT_ID =
sascha@1004:             sql.get(SQL_DELETE_OUTS_BY_ARTIFACT_ID);
sascha@1004:         SQL_DELETE_FACETS_BY_ARTIFACT_ID =
sascha@1004:             sql.get(SQL_DELETE_FACETS_BY_ARTIFACT_ID);
sascha@1010:         SQL_DELETE_ARTIFACT_BY_GID =
sascha@1010:             sql.get(SQL_DELETE_ARTIFACT_BY_GID);
sascha@991:     }
sascha@991: 
sascha@992:     protected static final int numFacets(List<Output> outs) {
sascha@992:         int sum = 0;
sascha@992:         for (Output out: outs) {
sascha@992:             sum += out.getFacets().size();
sascha@992:         }
sascha@992:         return sum;
sascha@992:     }
sascha@992: 
sascha@992:     protected static final void setString(
sascha@991:         PreparedStatement stmnt, 
sascha@991:         int               index,
sascha@991:         Object            value
sascha@991:     ) 
sascha@991:     throws SQLException
sascha@991:     {
sascha@991:         if (value == null) {
sascha@991:             stmnt.setNull(index, Types.VARCHAR);
sascha@991:         }
sascha@991:         else {
sascha@991:             stmnt.setString(index, value.toString());
sascha@991:         }
sascha@982:     }
sascha@982: 
sascha@982:     @Override
sascha@982:     public void systemUp(GlobalContext context) {
sascha@993:         log.debug("systemUp entered");
sascha@984:         initialScan(context);
sascha@999:         context.put(DATACAGE_KEY, this);
sascha@993:         log.debug("systemUp leaved");
sascha@982:     }
sascha@982: 
sascha@984:     protected void initialScan(GlobalContext context) {
sascha@984:         log.debug("initialScan");
sascha@984: 
sascha@984:         Object adbObject = context.get(ARTEFACT_DATABASE_KEY);
sascha@984: 
sascha@984:         if (!(adbObject instanceof ArtifactDatabase)) {
sascha@984:             log.error("missing artefact database. Cannot scan");
sascha@984:             return;
sascha@984:         }
sascha@984: 
sascha@984:         ArtifactDatabase adb = (ArtifactDatabase)adbObject;
sascha@984: 
sascha@984:         if (!cleanDatabase()) {
sascha@984:             log.error("cleaning database failed");
sascha@984:             return;
sascha@984:         }
sascha@984: 
sascha@991:         InitialScan is = new InitialScan(context);
sascha@984: 
sascha@984:         if (!is.scan(adb)) {
sascha@984:             log.error("initial scan failed");
sascha@984:             return;
sascha@984:         }
sascha@984: 
sascha@984:     }
sascha@984: 
sascha@984:     protected boolean cleanDatabase() {
sascha@984: 
sascha@993:         log.debug("cleanDatabase");
sascha@993: 
sascha@993:         boolean success = sqlExecutor.new Instance() {
sascha@984:             @Override
sascha@984:             public boolean doIt() throws SQLException {
sascha@984:                 prepareStatement(SQL_DELETE_ALL_USERS);
sascha@984:                 stmnt.execute();
sascha@996:                 prepareStatement(SQL_DELETE_ALL_ARTIFACTS);
sascha@996:                 stmnt.execute();
sascha@990:                 conn.commit();
sascha@984:                 return true;
sascha@984:             }
sascha@984:         }.runWrite();
sascha@993: 
sascha@993:         log.debug("after runWrite(): " + success);
sascha@993: 
sascha@993:         return success;
sascha@984:     }
sascha@984: 
sascha@984: 
sascha@982:     @Override
sascha@982:     public void systemDown(GlobalContext context) {
sascha@982:         log.debug("systemDown");
sascha@982:     }
sascha@999: 
sascha@999:     public void setup(GlobalContext globalContext) {
sascha@999:         log.debug("setup");
sascha@999:     }
sascha@999: 
sascha@1002:     public void createdArtifact(
sascha@1002:         Artifact      artifact, 
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@1002:     ) {
sascha@999:         log.debug("createdArtifact");
sascha@1002: 
felix@1624:         if (artifact == null) {
felix@1624:             log.warn("artifact to create is null");
felix@1624:             return;
felix@1624:         }
felix@1624: 
sascha@1002:         if (!(artifact instanceof FLYSArtifact)) {
felix@1624:             log.warn("need FLYSArtifact here (have " + artifact.getClass() + ")");
sascha@1002:             return;
sascha@1002:         }
sascha@1002: 
sascha@1002:         final FLYSArtifact flys = (FLYSArtifact)artifact;
sascha@1002: 
sascha@1002:         final int [] res = new int[1];
sascha@1002: 
sascha@1002:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1002:             @Override
sascha@1002:             public boolean doIt() throws SQLException {
sascha@1002:                 prepareStatement(SQL_ARTIFACT_ID_NEXTVAL);
sascha@1002:                 result = stmnt.executeQuery();
sascha@1002:                 if (!result.next()) {
sascha@1004:                     log.error("id generation for artifact failed");
sascha@1002:                     return false;
sascha@1002:                 }
sascha@1002:                 res[0] = result.getInt(1);
sascha@1002:                 reset();
sascha@1002:                 prepareStatement(SQL_INSERT_ARTIFACT);
sascha@1025:                 stmnt.setInt      (1, res[0]);
sascha@1025:                 stmnt.setString   (2, flys.identifier());
sascha@1025:                 stmnt.setString   (3, flys.getCurrentStateId());
sascha@1025:                 stmnt.setTimestamp(4,
sascha@1025:                     new Timestamp(System.currentTimeMillis()));
sascha@1002:                 stmnt.execute();
sascha@1002:                 conn.commit();
sascha@1002:                 return true;
sascha@1002:             }
sascha@1002:         };
sascha@1002: 
sascha@1002:         if (!exec.runWrite()) {
sascha@1002:             log.error("storing of artifact failed.");
sascha@1002:             return;
sascha@1002:         }
sascha@1002: 
sascha@1002:         storeData(res[0], flys);
sascha@1002:         storeOuts(res[0], flys, context);
sascha@999:     }
sascha@999: 
sascha@1002:     public void storedArtifact(
sascha@1002:         Artifact      artifact,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@1002:     ) {
sascha@999:         log.debug("storedArtifact");
sascha@1004:         if (!(artifact instanceof FLYSArtifact)) {
felix@1624:             log.warn("need FLYSArtifact here but have a " + artifact.getClass());
sascha@1004:             return;
sascha@1004:         }
sascha@1004: 
sascha@1004:         final FLYSArtifact flys = (FLYSArtifact)artifact;
sascha@1004: 
sascha@1004:         final Integer [] res = new Integer[1];
sascha@1004: 
sascha@1004:         // check first if artifact already exists
sascha@1004:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1004:             @Override
sascha@1004:             public boolean doIt() throws SQLException {
sascha@1004:                 prepareStatement(SQL_ARTIFACT_BY_GID);
sascha@1007:                 stmnt.setString(1, flys.identifier());
sascha@1004:                 result = stmnt.executeQuery();
sascha@1004:                 if (!result.next()) {
sascha@1004:                     // new artifact
sascha@1004:                     return true;
sascha@1004:                 }
sascha@1004:                 res[0] = result.getInt(1);
sascha@1004:                 return true;
sascha@1004:             }
sascha@1004:         };
sascha@1004: 
sascha@1004:         if (!exec.runRead()) {
sascha@1004:             log.error("querying artifact failed");
sascha@1004:             return;
sascha@1004:         }
sascha@1004: 
sascha@1004:         if (res[0] == null) { // new artifact
sascha@1004:             createdArtifact(artifact, backend, context);
sascha@1004:             return;
sascha@1004:         }
sascha@1004: 
sascha@1004:         // artifact already exists -> delete old data
sascha@1004:         exec = sqlExecutor.new Instance() {
sascha@1004:             @Override
sascha@1004:             public boolean doIt() throws SQLException {
sascha@1004:                 prepareStatement(SQL_DELETE_ARTIFACT_DATA_BY_ARTIFACT_ID);
sascha@1004:                 stmnt.setInt(1, res[0]);
sascha@1004:                 stmnt.execute();
sascha@1004:                 prepareStatement(SQL_DELETE_FACETS_BY_ARTIFACT_ID);
sascha@1004:                 stmnt.setInt(1, res[0]);
sascha@1004:                 stmnt.execute();
sascha@1004:                 prepareStatement(SQL_DELETE_OUTS_BY_ARTIFACT_ID);
sascha@1004:                 stmnt.setInt(1, res[0]);
sascha@1004:                 stmnt.execute();
sascha@1004:                 conn.commit();
sascha@1004:                 return true;
sascha@1004:             }
sascha@1004:         };
sascha@1004: 
sascha@1004:         if (!exec.runWrite()) {
sascha@1004:             log.error("deleting old artifact data failed");
sascha@1004:             return;
sascha@1004:         }
sascha@1004: 
sascha@1004:         // write new data
sascha@1004:         storeData(res[0], flys);
sascha@1004:         storeOuts(res[0], flys, context);
sascha@999:     }
sascha@999: 
sascha@1002:     public void createdUser(
sascha@1004:         final User    user,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@1002:     ) {
sascha@999:         log.debug("createdUser");
sascha@1004:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1004:             @Override
sascha@1004:             public boolean doIt() throws SQLException {
sascha@1004:                 prepareStatement(SQL_USER_ID_NEXTVAL);
sascha@1004:                 result = stmnt.executeQuery();
sascha@1004:                 if (!result.next()) {
sascha@1004:                     log.error("id generation for user failed");
sascha@1004:                     return false;
sascha@1004:                 }
sascha@1004:                 int uId = result.getInt(1);
sascha@1004:                 reset();
sascha@1004:                 prepareStatement(SQL_INSERT_USER);
sascha@1004:                 stmnt.setInt(1, uId);
sascha@1004:                 stmnt.setString(2, user.identifier());
sascha@1004:                 stmnt.execute();
sascha@1004:                 conn.commit();
sascha@1004:                 return true;
sascha@1004:             }
sascha@1004:         };
sascha@1004: 
sascha@1004:         if (!exec.runWrite()) {
sascha@1004:             log.error("create user failed");
sascha@1004:         }
sascha@999:     }
sascha@999: 
sascha@1002:     public void deletedUser(
sascha@1004:         final String  identifier,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@1002:     ) {
sascha@999:         log.debug("deletedUser");
sascha@1004:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1004:             @Override
sascha@1004:             public boolean doIt() throws SQLException {
sascha@1004:                 prepareStatement(SQL_DELETE_USER_BY_GID);
sascha@1004:                 stmnt.setString(1, identifier);
sascha@1004:                 stmnt.execute();
sascha@1004:                 conn.commit();
sascha@1004:                 return true;
sascha@1004:             }
sascha@1004:         };
sascha@1004: 
sascha@1004:         if (!exec.runWrite()) {
sascha@1004:             log.error("delete user failed");
sascha@1004:         }
sascha@999:     }
sascha@999: 
sascha@999:     public void createdCollection(
sascha@1004:         final ArtifactCollection collection,
sascha@1004:         Backend                  backend,
sascha@1004:         GlobalContext            context
sascha@999:     ) {
sascha@999:         log.debug("createdCollection");
sascha@1004:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1004:             @Override
sascha@1004:             public boolean doIt() throws SQLException {
sascha@1004:                 String userId = collection.getUser().identifier();
sascha@1004:                 prepareStatement(SQL_USER_BY_GID);
sascha@1004:                 stmnt.setString(1, userId);
sascha@1004:                 result = stmnt.executeQuery();
sascha@1004:                 int uId;
sascha@1004:                 if (result.next()) {
sascha@1004:                     uId = result.getInt(1);
sascha@1004:                     reset();
sascha@1004:                 }
sascha@1004:                 else {
sascha@1004:                     // need to create user first
sascha@1004:                     reset();
sascha@1004:                     prepareStatement(SQL_USER_ID_NEXTVAL);
sascha@1004:                     result = stmnt.executeQuery();
sascha@1004:                     if (!result.next()) {
sascha@1004:                         log.error("id generation for user failed");
sascha@1004:                         return false;
sascha@1004:                     }
sascha@1004:                     uId = result.getInt(1);
sascha@1004:                     reset();
sascha@1004:                     prepareStatement(SQL_INSERT_USER);
sascha@1004:                     stmnt.setInt(1, uId);
sascha@1004:                     stmnt.setString(2, userId);
sascha@1004:                     stmnt.execute();
sascha@1004:                     conn.commit();
sascha@1004:                     reset();
sascha@1004:                 }
sascha@1004: 
sascha@1004:                 prepareStatement(SQL_COLLECTION_ID_NEXTVAL);
sascha@1004:                 result = stmnt.executeQuery();
sascha@1004:                 if (!result.next()) {
sascha@1004:                     log.error("id generation for collection failed");
sascha@1004:                     return false;
sascha@1004:                 }
sascha@1004:                 int cId = result.getInt(1);
sascha@1004:                 reset();
sascha@1004: 
sascha@1004:                 String identifier = collection.identifier();
sascha@1004:                 String name       = collection.getName();
sascha@1004: 
sascha@1004:                 prepareStatement(SQL_INSERT_COLLECTION);
sascha@1004:                 stmnt.setInt(1, cId);
sascha@1004:                 stmnt.setString(2, identifier);
sascha@1004:                 stmnt.setInt(3, uId);
sascha@1004:                 setString(stmnt, 4, name);
sascha@1025:                 stmnt.setTimestamp(5,
sascha@1025:                     new Timestamp(System.currentTimeMillis()));
sascha@1004:                 stmnt.execute();
sascha@1004: 
sascha@1004:                 conn.commit();
sascha@1004:                 return true;
sascha@1004:             }
sascha@1004:         };
sascha@1004: 
sascha@1004:         if (!exec.runWrite()) {
sascha@1004:             log.error("create collection failed");
sascha@1004:         }
sascha@999:     }
sascha@999: 
sascha@1002:     public void deletedCollection(
sascha@1004:         final String  identifier,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@1002:     ) {
sascha@999:         log.debug("deletedCollection");
sascha@1004:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1004:             @Override
sascha@1004:             public boolean doIt() throws SQLException {
sascha@1004:                 prepareStatement(SQL_DELETE_COLLECTION_BY_GID);
sascha@1004:                 stmnt.setString(1, identifier);
sascha@1004:                 stmnt.execute();
sascha@1004:                 conn.commit();
sascha@1004:                 return true;
sascha@1004:             }
sascha@1004:         };
sascha@1004: 
sascha@1004:         if (!exec.runWrite()) {
sascha@1004:             log.error("delete collection failed");
sascha@1004:         }
sascha@999:     }
sascha@999: 
sascha@999:     public void changedCollectionAttribute(
sascha@1002:         String        identifier,
sascha@1002:         Document      document,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@999:     ) {
sascha@999:         log.debug("changedCollectionAttribute");
sascha@999:     }
sascha@999: 
sascha@999:     public void changedCollectionItemAttribute(
sascha@1002:         String        collectionId,
sascha@1002:         String        artifactId,
sascha@1002:         Document      document,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@999:     ) {
sascha@999:         log.debug("changedCollectionItemAttribute");
sascha@999:     }
sascha@999: 
sascha@999:     public void addedArtifactToCollection(
sascha@1004:         final String  artifactId,
sascha@1004:         final String  collectionId,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@999:     ) {
sascha@999:         log.debug("addedArtifactToCollection");
sascha@1004:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1004:             @Override
sascha@1004:             public boolean doIt() throws SQLException {
sascha@1004:                 prepareStatement(SQL_ARTIFACT_BY_GID);
sascha@1004:                 stmnt.setString(1, artifactId);
sascha@1004:                 result = stmnt.executeQuery();
sascha@1004:                 if (!result.next()) {
sascha@1004:                     return false;
sascha@1004:                 }
sascha@1004:                 int aId = result.getInt(1);
sascha@1004:                 reset();
sascha@1004: 
sascha@1004:                 prepareStatement(SQL_COLLECTION_BY_GID);
sascha@1004:                 stmnt.setString(1, collectionId);
sascha@1004:                 result = stmnt.executeQuery();
sascha@1004:                 if (!result.next()) {
sascha@1004:                     return false;
sascha@1004:                 }
sascha@1004:                 int cId = result.getInt(1);
sascha@1004:                 reset();
sascha@1004: 
sascha@1004:                 prepareStatement(SQL_COLLECTION_ITEM_ID_NEXTVAL);
sascha@1004:                 result = stmnt.executeQuery();
sascha@1004:                 if (!result.next()) {
sascha@1004:                     return false;
sascha@1004:                 }
sascha@1004:                 int ciId = result.getInt(1);
sascha@1004:                 reset();
sascha@1004: 
sascha@1004:                 prepareStatement(SQL_INSERT_COLLECTION_ITEM);
sascha@1004:                 stmnt.setInt(1, ciId);
sascha@1004:                 stmnt.setInt(2, cId);
sascha@1004:                 stmnt.setInt(3, aId);
sascha@1004:                 stmnt.execute();
sascha@1004: 
sascha@1004:                 conn.commit();
sascha@1004:                 return true;
sascha@1004:             }
sascha@1004:         };
sascha@1004:         if (!exec.runWrite()) {
sascha@1004:             log.error("added artifact to collection failed");
sascha@1004:         }
sascha@999:     }
sascha@999: 
sascha@999:     public void removedArtifactFromCollection(
sascha@1003:         final String  artifactId,
sascha@1003:         final String  collectionId,
sascha@1002:         Backend       backend,
sascha@1002:         GlobalContext context
sascha@999:     ) {
sascha@999:         log.debug("removedArtifactFromCollection");
sascha@1003:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1003:             @Override
sascha@1003:             public boolean doIt() throws SQLException {
sascha@1003:                 prepareStatement(SQL_ARTIFACT_BY_GID);
sascha@1003:                 stmnt.setString(1, artifactId);
sascha@1003:                 result = stmnt.executeQuery();
sascha@1003:                 if (!result.next()) {
sascha@1003:                     return false;
sascha@1003:                 }
sascha@1003:                 int aId = result.getInt(1);
sascha@1003:                 reset();
sascha@1003:                 prepareStatement(SQL_COLLECTION_BY_GID);
sascha@1003:                 stmnt.setString(1, collectionId);
sascha@1003:                 result = stmnt.executeQuery();
sascha@1003:                 if (!result.next()) {
sascha@1003:                     return false;
sascha@1003:                 }
sascha@1003:                 int cId = result.getInt(1);
sascha@1003:                 reset();
sascha@1003:                 prepareStatement(SQL_DELETE_ARTIFACT_FROM_COLLECTION);
sascha@1003:                 stmnt.setInt(1, cId);
sascha@1003:                 stmnt.setInt(2, aId);
sascha@1003:                 stmnt.execute();
sascha@1003:                 conn.commit();
sascha@1003:                 return true;
sascha@1003:             }
sascha@1003:         };
sascha@1003:         if (!exec.runWrite()) {
sascha@1003:             log.error("removing artifact from collection failed");
sascha@1003:         }
sascha@999:     }
sascha@999: 
sascha@999:     public void setCollectionName(
sascha@1003:         final String  collectionId,
sascha@1003:         final String  name,
sascha@1002:         GlobalContext context
sascha@999:     ) {
sascha@999:         log.debug("setCollectionName");
sascha@1003:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1003:             @Override
sascha@1003:             public boolean doIt() throws SQLException {
sascha@1003:                 prepareStatement(SQL_UPDATE_COLLECTION_NAME);
sascha@1003:                 stmnt.setString(1, name);
sascha@1003:                 stmnt.setString(2, collectionId);
sascha@1003:                 stmnt.execute();
sascha@1003:                 conn.commit();
sascha@1003:                 return true;
sascha@1003:             }
sascha@1003:         };
sascha@1003:         if (!exec.runWrite()) {
sascha@1003:             log.error("changing name failed");
sascha@1003:         }
sascha@999:     }
sascha@1002: 
sascha@1002:     protected void storeData(
sascha@1002:         final int     artifactId,
sascha@1002:         FLYSArtifact  artifact
sascha@1002:     ) {
sascha@1002:         final Collection<StateData> data = artifact.getAllData();
sascha@1002: 
sascha@1002:         if (data.isEmpty()) {
sascha@1002:             return;
sascha@1002:         }
sascha@1002: 
sascha@1002:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1002:             @Override
sascha@1002:             public boolean doIt() throws SQLException {
sascha@1002:                 int [] ids = new int[data.size()];
sascha@1002:                 prepareStatement(SQL_ARTIFACT_DATA_ID_NEXTVAL);
sascha@1002: 
sascha@1002:                 for (int i = 0; i < ids.length; ++i) {
sascha@1002:                     result = stmnt.executeQuery();
sascha@1002:                     if (!result.next()) {
sascha@1002:                         log.error("generating id for artifact data failed");
sascha@1002:                         return false;
sascha@1002:                     }
sascha@1002:                     ids[i] = result.getInt(1);
sascha@1002:                     result.close(); result = null;
sascha@1002:                 }
sascha@1002:                 reset();
sascha@1002:                 prepareStatement(SQL_INSERT_ARTIFACT_DATA);
sascha@1002: 
sascha@1002:                 int i = 0;
sascha@1002:                 for (StateData sd: data) {
sascha@1002:                     int id = ids[i++];
sascha@1002:                     stmnt.setInt(1, id);
sascha@1002:                     stmnt.setInt(2, artifactId);
sascha@1002:                     // XXX: Where come the nulls from?
sascha@1002:                     String type = sd.getType();
sascha@1002:                     if (type == null) type = "String";
sascha@1002:                     stmnt.setString(3, type);
sascha@1002:                     stmnt.setString(4, sd.getName());
sascha@1002:                     setString(stmnt, 5, sd.getValue());
sascha@1002:                     stmnt.execute();
sascha@1002:                 }
sascha@1002: 
sascha@1002:                 conn.commit();
sascha@1002:                 return true;
sascha@1002:             }
sascha@1002:         };
sascha@1002: 
sascha@1002:         if (!exec.runWrite()) {
sascha@1002:             log.error("storing artifact data failed");
sascha@1002:         }
sascha@1002:     }
sascha@1002: 
sascha@1002:     protected void storeOuts(
sascha@1002:         final int          artifactId,
sascha@1002:         final FLYSArtifact artifact,
sascha@1002:         GlobalContext      context
sascha@1002:     ) {
sascha@1050:         final List<Output> outs = artifact.getOutputs(context);
sascha@1002: 
sascha@1002:         if (outs.isEmpty()) {
sascha@1002:             return;
sascha@1002:         }
sascha@1002: 
sascha@1002:         final int [] outIds = new int[outs.size()];
sascha@1002: 
sascha@1002:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1002:             @Override
sascha@1002:             public boolean doIt() throws SQLException {
sascha@1002:                 prepareStatement(SQL_OUT_ID_NEXTVALUE);
sascha@1002:                 for (int i = 0; i < outIds.length; ++i) {
sascha@1002:                     result = stmnt.executeQuery();
sascha@1002:                     if (!result.next()) {
sascha@1002:                         log.error("generation of out ids failed");
sascha@1002:                         return false;
sascha@1002:                     }
sascha@1002:                     outIds[i] = result.getInt(1);
sascha@1002:                     result.close(); result = null;
sascha@1002:                 }
sascha@1002:                 reset();
sascha@1002:                 prepareStatement(SQL_INSERT_OUT);
sascha@1002:                 for (int i = 0; i < outIds.length; ++i) {
sascha@1002:                     Output out = outs.get(i);
sascha@1002:                     stmnt.setInt(1, outIds[i]);
sascha@1002:                     stmnt.setInt(2, artifactId);
sascha@1002:                     stmnt.setString(3, out.getName());
sascha@1002:                     setString(stmnt, 4, out.getDescription());
sascha@1002:                     setString(stmnt, 5, out.getType());
sascha@1002:                     stmnt.execute();
sascha@1002:                 }
sascha@1002:                 conn.commit();
sascha@1002:                 return true;
sascha@1002:             }
sascha@1002:         };
sascha@1002: 
sascha@1002:         if (!exec.runWrite()) {
sascha@1002:             log.error("storing artifact outs failed");
sascha@1002:             return;
sascha@1002:         }
sascha@1002: 
sascha@1002:         final int FACETS = numFacets(outs);
sascha@1002: 
sascha@1002:         if (FACETS == 0) {
sascha@1002:             return;
sascha@1002:         }
sascha@1002: 
sascha@1002:         exec = sqlExecutor.new Instance() {
sascha@1002:             @Override
sascha@1002:             public boolean doIt() throws SQLException {
sascha@1002:                 int [] facetIds = new int[FACETS];
sascha@1002:                 prepareStatement(SQL_FACET_ID_NEXTVAL);
sascha@1002:                 for (int i = 0; i < facetIds.length; ++i) {
sascha@1002:                     result = stmnt.executeQuery();
sascha@1002:                     if (!result.next()) {
sascha@1002:                         log.error("generation of facet ids failed");
sascha@1002:                         return false;
sascha@1002:                     }
sascha@1002:                     facetIds[i] = result.getInt(1);
sascha@1002:                     result.close(); result = null;
sascha@1002:                 }
sascha@1002:                 reset();
sascha@1002:                 prepareStatement(SQL_INSERT_FACET);
sascha@1002:                 int index = 0;
sascha@1002:                 for (int i = 0, N = outs.size(); i < N; ++i) {
sascha@1002:                     Output out = outs.get(i);
sascha@1002:                     int outId = outIds[i];
sascha@1002:                     for (Facet facet: out.getFacets()) {
sascha@1002:                         stmnt.setInt(1, facetIds[index]);
sascha@1002:                         stmnt.setInt(2, outId);
sascha@1002:                         stmnt.setString(3, facet.getName());
sascha@1002:                         stmnt.setInt(4, facet.getIndex());
sascha@1002:                         stmnt.setString(5, "XXX"); // TODO: handle states
sascha@1002:                         setString(stmnt, 6, facet.getDescription());
sascha@1002:                         stmnt.execute();
sascha@1002:                         ++index;
sascha@1002:                     }
sascha@1002:                 }
sascha@1002:                 conn.commit();
sascha@1002:                 return true;
sascha@1002:             }
sascha@1002:         };
sascha@1002: 
sascha@1002:         if (!exec.runWrite()) {
sascha@1002:             log.error("storing facets failed");
sascha@1002:         }
sascha@1002:     }
sascha@1006: 
sascha@1006:     public void killedCollections(
sascha@1006:         final List<String> identifiers,
sascha@1006:         GlobalContext      context
sascha@1006:     ) {
sascha@1006:         log.debug("killedCollections");
sascha@1006: 
sascha@1006:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1006:             @Override
sascha@1006:             public boolean doIt() throws SQLException {
sascha@1006:                 prepareStatement(SQL_DELETE_COLLECTION_BY_GID);
sascha@1006:                 for (String identifier: identifiers) {
sascha@1006:                     stmnt.setString(1, identifier);
sascha@1006:                     stmnt.execute();
sascha@1006:                 }
sascha@1006:                 conn.commit();
sascha@1006:                 return true;
sascha@1006:             }
sascha@1006:         };
sascha@1006: 
sascha@1006:         if (!exec.runWrite()) {
sascha@1006:             log.error("killing collections failed");
sascha@1006:         }
sascha@1006:     }
sascha@1006: 
sascha@1006:     public void killedArtifacts(
sascha@1006:         final List<String> identifiers,
sascha@1006:         GlobalContext      context
sascha@1006:     ) {
sascha@1006:         log.debug("killedArtifacts");
sascha@1006: 
sascha@1006:         SQLExecutor.Instance exec = sqlExecutor.new Instance() {
sascha@1006:             @Override
sascha@1006:             public boolean doIt() throws SQLException {
sascha@1006:                 prepareStatement(SQL_DELETE_ARTIFACT_BY_GID);
sascha@1006:                 for (String identifier: identifiers) {
sascha@1006:                     stmnt.setString(1, identifier);
sascha@1006:                     stmnt.execute();
sascha@1006:                 }
sascha@1006:                 conn.commit();
sascha@1006:                 return true;
sascha@1006:             }
sascha@1006:         };
sascha@1006: 
sascha@1006:         if (!exec.runWrite()) {
sascha@1006:             log.error("killing artifacts failed");
sascha@1006:         }
sascha@1006:     }
sascha@982: }
sascha@982: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :