All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ro.isdc.wro.extensions.model.factory.SmartWroModelFactory Maven / Gradle / Ivy

/**
 * Copyright@2011 wro4j
 */
package ro.isdc.wro.extensions.model.factory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ro.isdc.wro.WroRuntimeException;
import ro.isdc.wro.manager.factory.standalone.StandaloneContext;
import ro.isdc.wro.model.WroModel;
import ro.isdc.wro.model.factory.AbstractWroModelFactory;
import ro.isdc.wro.model.factory.WroModelFactory;
import ro.isdc.wro.model.factory.XmlModelFactory;
import ro.isdc.wro.model.group.Inject;
import ro.isdc.wro.model.group.processor.Injector;


/**
 * When used, this factory will make it possible to migrate easily from xml to groovy (or json) DSL seamlessly.
 *
 * @author Alex Objelean
 * @created 6 Aug 2011
 * @since 1.4.0
 */
public class SmartWroModelFactory extends AbstractWroModelFactory {
  private static final Logger LOG = LoggerFactory.getLogger(SmartWroModelFactory.class);
  /**
   * The default location of the wro model file.
   */
  private static final String DEFAULT_WRO_FILE = "/src/main/webapp/WEB-INF/wro.xml";
  @Inject
  private Injector injector;
  private List factoryList;
  /**
   * The exact file where the model is located.
   */
  private File wroFile;
  /**
   * flag indicating if the wroFile should be auto detected.
   */
  private boolean autoDetectWroFile = true;


  /**
   * Use this factory method when you want to use the {@link SmartWroModelFactory} in standalone (maven plugin) context.
   * The autoDetect flag is set to true if the wroFile path is the same as the default wro file name.
   */
  public static SmartWroModelFactory createFromStandaloneContext(final StandaloneContext context) {
    Validate.notNull(context);
    final boolean autoDetectWroFile = FilenameUtils.normalize(context.getWroFile().getPath()).contains(
      FilenameUtils.normalize(DEFAULT_WRO_FILE));
    if (!autoDetectWroFile) {
      LOG.debug("autoDetect is " + autoDetectWroFile + " because wroFile: " + context.getWroFile()
        + " is not the same as the default one: " + DEFAULT_WRO_FILE);
    }
    return new SmartWroModelFactory().setWroFile(context.getWroFile()).setAutoDetectWroFile(autoDetectWroFile);
  }


  /**
   * The file to use for creating model. It is not required to set this field, but if you set, do not set a null object.
   *
   * @param wroFile the wroFile to set
   */
  public SmartWroModelFactory setWroFile(final File wroFile) {
    Validate.notNull(wroFile);
    this.wroFile = wroFile;
    return this;
  }


  /**
   * @return default list of factories to be used by {@link SmartWroModelFactory}.
   */
  protected List newWroModelFactoryFactoryList() {
    final List factoryList = new ArrayList();
    LOG.debug("auto detect wroFile: {}", autoDetectWroFile);
    factoryList.add(newXmlModelFactory());
    factoryList.add(newGroovyModelFactory());
    factoryList.add(newJsonModelFactory());
    return factoryList;
  }


  private XmlModelFactory newXmlModelFactory() {
    return new XmlModelFactory() {
      @Override
      protected InputStream getModelResourceAsStream()
        throws IOException {
        if (wroFile == null) {
          return super.getModelResourceAsStream();
        }
        return createAutoDetectedStream(getDefaultModelFilename());
      }
    };
  }


  private GroovyModelFactory newGroovyModelFactory() {
    return new GroovyModelFactory() {
      @Override
      protected InputStream getModelResourceAsStream()
        throws IOException {
        if (wroFile == null) {
          return super.getModelResourceAsStream();
        }
        return createAutoDetectedStream(getDefaultModelFilename());
      }
    };
  }


  private JsonModelFactory newJsonModelFactory() {
    return new JsonModelFactory() {
      @Override
      protected InputStream getModelResourceAsStream()
        throws IOException {
        if (wroFile == null) {
          return super.getModelResourceAsStream();
        }
        return createAutoDetectedStream(getDefaultModelFilename());
      }
    };
  }


  /**
   * Handles the resource model auto detection.
   */
  private InputStream createAutoDetectedStream(final String defaultFileName)
    throws IOException {
    try {
      Validate.notNull(wroFile, "Cannot call this method if wroFile is null!");
      if (autoDetectWroFile) {
        final File file = new File(wroFile.getParentFile(), defaultFileName);
        LOG.debug("\tloading autodetected wro file: " + file);
        return new FileInputStream(file);
      }
      LOG.debug("loading wroFile: " + wroFile);
      return new FileInputStream(wroFile);
    } catch (final FileNotFoundException e) {
      // When auto detect is turned on, do not skip trying.. because the auto detection assume that the wro file name
      // can be wrong.
      if (autoDetectWroFile) {
        throw e;
      }
      throw new WroRuntimeException("The wroFile doesn't exist. Skip trying with other wro model factories", e);
    }
  }


  /**
   * {@inheritDoc}
   */
  @Override
  public WroModel create() {
    if (factoryList == null) {
      factoryList = newWroModelFactoryFactoryList();
    }
    if (factoryList != null) {
      // Holds the details about model creation which are logged only when no model can be created
      final StringBuffer logMessageBuffer = new StringBuffer();
      for (final WroModelFactory factory : factoryList) {
        try {
          //use injector for aggregated modelFactories
          injector.inject(factory);
          final Class factoryClass = factory.getClass().asSubclass(WroModelFactory.class);
          logMessageBuffer.append(" Using " + getClassName(factoryClass) + " for model creation..\n");
          return factory.create();
        } catch (final WroRuntimeException e) {
          LOG.debug("[FAIL] creating model... will try another factory");
          logMessageBuffer.append("[FAIL] Model creation using " + getClassName(factory.getClass())
            + " failed. Trying another ...\n");
          logMessageBuffer.append("[FAIL] Exception occured while building the model using: "
            + getClassName(factory.getClass()) + " " + e.getMessage());
          // stop trying with other factories if the reason is IOException
          if (!autoDetectWroFile && e.getCause() instanceof IOException) {
            throw e;
          }
        }
      }
      LOG.error(logMessageBuffer.toString());
    }
    throw new WroRuntimeException("Cannot create model using any of provided factories");
  }


  /**
   * @return string representation of the factory name.
   */
  protected String getClassName(final Class factoryClass) {
    final String className = factoryClass.isAnonymousClass()
      ? factoryClass.getSuperclass().getSimpleName()
      : factoryClass.getSimpleName();
    return className;
  }


  /**
   * @param factoryList the factoryList to set
   */
  public SmartWroModelFactory setFactoryList(final List factoryList) {
    Validate.notNull(factoryList);
    this.factoryList = factoryList;
    return this;
  }


  /**
   * In order to keep backward compatibility for building the model . The idea is if this field is false, then the exact
   * file will be used to create the model, otherwise, wro model file is auto-detected based on the parent folder where
   * the wroFile is located.
   *
   * @param autoDetectWroFile the autoDetectWroFile to set
   */
  public SmartWroModelFactory setAutoDetectWroFile(final boolean autoDetectWroFile) {
    this.autoDetectWroFile = autoDetectWroFile;
    return this;
  }


  /**
   * {@inheritDoc}
   */
  @Override
  protected String getDefaultModelFilename() {
    return DEFAULT_WRO_FILE;
  }


  /**
   * {@inheritDoc}
   */
  @Override
  protected InputStream getModelResourceAsStream()
    throws IOException {
    throw new IllegalStateException("This method should never be called!");
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy