/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2004 Bull S.A.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: AbsArchiveModifier.java 15428 2008-10-07 11:20:29Z sauthieg $
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.generators.genclientstub.modifier;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.ow2.jonas.generators.genbase.GenBaseException;
import org.ow2.jonas.generators.genbase.archive.Archive;
import org.ow2.jonas.generators.genbase.archive.J2EEArchive;
import org.ow2.jonas.generators.genbase.archive.WebApp;
import org.ow2.jonas.generators.genbase.generator.Config;
import org.ow2.jonas.generators.genbase.modifier.ArchiveModifier;
import org.ow2.jonas.generators.genclientstub.ClientStubGenException;
import org.ow2.jonas.generators.genclientstub.generator.Generator;


/**
 * Defines common methods used by all modifier
 */
public abstract class AbsArchiveModifier extends ArchiveModifier {

    /**
     * Constructor
     * @param archive the j2ee archive
     */
    public AbsArchiveModifier(J2EEArchive archive) {
        super(archive);
    }

    /**
    * Modify the current archive and return a modified archive.
     * @return a modified archive.
     * @throws GenBaseException When Client Generation or storing phase fails.
     */
    public abstract Archive modify() throws GenBaseException;

    /**
     * Generates stub/tie classes for a given archive with its config
     * @param config configuration to use for the generator
     * @param archive the file containing the remote class
     * @throws ClientStubGenException if the generation fails
     */
    protected void generateFoundStubs(Config config, Archive archive) throws ClientStubGenException {

        // List of classes on which generate stubs
        List classesStub = new ArrayList();
        try {
            List files = archive.getContainedFiles();

            for (Iterator itFiles = files.iterator(); itFiles.hasNext();) {
                String clName = (String) itFiles.next();
                if (clName.endsWith("_Stub.class") || clName.endsWith("_Tie.class")) {
                    // Extract classname from stub and add entry in the list
                    if (archive instanceof WebApp) {
                        if (clName.startsWith("WEB-INF/classes/")) {
                            classesStub.add(clName.substring("WEB-INF/classes/".length()));
                        }
                    } else {
                        classesStub.add(clName);
                    }
                }
            }

            // launch generation for all classes found
            for (Iterator itClass = classesStub.iterator(); itClass.hasNext();) {
                String clName = (String) itClass.next();

                // Remove stub name
                int removeStubIdx = 0;
                if (clName.endsWith("_Stub.class")) {
                    removeStubIdx = clName.length() - "_Stub.class".length();
                } else if (clName.endsWith("_Tie.class")) {
                    removeStubIdx = clName.length() - "_Tie.class".length();
                } else {
                    continue;
                }
                clName = clName.substring(0, removeStubIdx);

                // Remove the _ from the className
                int idx = clName.lastIndexOf('/') + 1;
                if (clName.charAt(idx) == '_') {
                    String pkgName = clName.substring(0, idx);
                    clName = pkgName + clName.substring(idx + 1, clName.length());
                }

                // Translate / into . (/ is in jar entry, classname should contain .)
                clName = clName.replaceAll("/", ".");

                // javax object and existing omg stubs
                if (clName.indexOf("javax.") != -1 || clName.indexOf("org.omg.stub") != -1) {
                    continue;
                }


                // Doesn't take into account Home and Remote
                if (clName.indexOf("Home") != -1 || clName.indexOf("Remote") != -1) {
                    continue;
                }

                Generator g = new Generator(config, null, clName, archive);
                try {
                    g.generate();
                    g.compile();
                } catch (ClientStubGenException cstge) {
                    continue;
                }
                // add files in archive
                g.addFiles(archive);
            }
        } catch (Exception e) {
            throw new ClientStubGenException("Cannot find/build stubs from the file " + archive.getRootFile(), e);
        }

    }

}