Created
July 27, 2012 16:55
-
-
Save digulla/3189139 to your computer and use it in GitHub Desktop.
Xml model factory for Wro4j which can reference imports (see https://code.google.com/p/wro4j/issues/detail?id=423)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2008. All rights reserved. | |
*/ | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.HashMap; | |
import java.util.Map; | |
import javax.xml.parsers.DocumentBuilderFactory; | |
import org.apache.commons.lang3.StringUtils; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import org.w3c.dom.Document; | |
import org.w3c.dom.Element; | |
import org.w3c.dom.NodeList; | |
import ro.isdc.wro.WroRuntimeException; | |
import ro.isdc.wro.model.WroModel; | |
import ro.isdc.wro.model.factory.AbstractWroModelFactory; | |
import ro.isdc.wro.model.group.Group; | |
import ro.isdc.wro.model.group.Inject; | |
import ro.isdc.wro.model.resource.Resource; | |
import ro.isdc.wro.model.resource.ResourceType; | |
import ro.isdc.wro.model.resource.locator.factory.UriLocatorFactory; | |
import ro.isdc.wro.util.StopWatch; | |
/** | |
* Model factory implementation. Creates a WroModel object, based on an xml. This xml contains the description of all | |
* groups. | |
* <p/> | |
* This class is thread-safe (the create method is synchronized). | |
* | |
* @author Alex Objelean | |
* @created Created on Nov 3, 2008 | |
*/ | |
public class XmlModelFactory | |
extends AbstractWroModelFactory { | |
/** | |
* Logger for this class. | |
*/ | |
private static final Logger LOG = LoggerFactory.getLogger(XmlModelFactory.class); | |
/** | |
* Default xml filename. | |
*/ | |
private static final String DEFAULT_FILE_NAME = "wro.xml"; | |
/** | |
* Group tag used in xml. | |
*/ | |
private static final String TAG_GROUP = "group"; | |
/** | |
* Groups tag used in xml. | |
*/ | |
private static final String TAG_GROUPS = "groups"; | |
/** | |
* Import tag used in xml. | |
*/ | |
private static final String TAG_IMPORT = "import"; | |
/** | |
* CSS tag used in xml. | |
*/ | |
private static final String TAG_CSS = "css"; | |
/** | |
* JS tag used in xml. | |
*/ | |
private static final String TAG_JS = "js"; | |
/** | |
* GroupRef tag used in xml. | |
*/ | |
private static final String TAG_GROUP_REF = "group-ref"; | |
/** | |
* Group name attribute used in xml. | |
*/ | |
private static final String ATTR_GROUP_NAME = "name"; | |
/** | |
* Minimize attribute specified on resource level, used to turn on/off minimization on this particular resource during | |
* pre processing. | |
*/ | |
private static final String ATTR_MINIMIZE = "minimize"; | |
/** | |
* Used to locate imports; | |
*/ | |
@Inject | |
private UriLocatorFactory uriLocatorFactory; | |
/** | |
* {@inheritDoc} | |
*/ | |
@Override | |
public synchronized WroModel create() { | |
// TODO cache model based on application Mode (DEPLOYMENT, DEVELOPMENT) | |
final StopWatch stopWatch = new StopWatch("Create Wro Model from XML"); | |
try { | |
stopWatch.start("createDocument"); | |
final Document document = createDocument(); | |
final WroModel model = createModel(); | |
parseElement( model, document.getDocumentElement() ); | |
return model; | |
} finally { | |
//clear the processed imports even when the model creation fails. | |
stopWatch.stop(); | |
LOG.debug(stopWatch.prettyPrint()); | |
} | |
} | |
private void parseElement( WroModel model, Element element ) { | |
final String tagName = element.getTagName(); | |
if (TAG_JS.equals(tagName)) { | |
parseJS( model, element ); | |
} else if( TAG_CSS.equals(tagName)) { | |
parseCSS( model, element ); | |
} else if( TAG_GROUP.equals(tagName)) { | |
parseGroup( model, element ); | |
} else if( TAG_GROUP_REF.equals(tagName)) { | |
parseGroupRef( model, element ); | |
} else if( TAG_IMPORT.equals(tagName)) { | |
parseImport( model, element ); | |
} else if( TAG_GROUPS.equals(tagName)) { | |
parseChildren( model, element ); | |
} | |
} | |
private void parseImport( WroModel model, Element element ) { | |
final String uri = element.getTextContent().trim(); | |
LOG.debug( "processing import: {}", uri ); | |
final XmlModelFactory importedModelFactory = new XmlModelFactory() { | |
@Override | |
protected InputStream getModelResourceAsStream() | |
throws IOException { | |
LOG.debug( "build model from import: {}", uri ); | |
LOG.debug( "uriLocatorFactory: {}", uriLocatorFactory ); | |
return uriLocatorFactory.locate( uri ); | |
}; | |
}; | |
WroModel other = importedModelFactory.create(); | |
for( Group g : other.getGroups() ) { | |
addGroup( g ); | |
model.addGroup( g ); | |
} | |
} | |
private void parseGroupRef( WroModel model, Element element ) { | |
String ref = element.getTextContent().trim(); | |
Group other = groups.get( ref ); | |
if( null == other ) { | |
throw new WroRuntimeException( "Missing group [" + ref + "]" ); | |
} | |
for( Resource r : other.getResources() ) { | |
currentGroup.addResource( r ); | |
} | |
} | |
private Map<String, Group> groups = new HashMap<String, Group>(); | |
private void parseGroup( WroModel model, Element element ) { | |
final String name = element.getAttribute(ATTR_GROUP_NAME); | |
Group group = new Group( name ); | |
addGroup( group ); | |
final Group parentGroup = currentGroup; | |
currentGroup = group; | |
parseChildren( model, element ); | |
model.addGroup( group ); | |
currentGroup = parentGroup; | |
} | |
void addGroup( final Group group ) { | |
final Group old = groups.put( group.getName(), group ); | |
if( null != old ) { | |
throw new WroRuntimeException( "Found two groups with the name [" + group.getName() + "]" ); | |
} | |
} | |
private void parseCSS( WroModel model, Element element ) { | |
Resource resource = createResoure( ResourceType.CSS, element ); | |
currentGroup.addResource( resource ); | |
} | |
private Group currentGroup; | |
private void parseJS( WroModel model, Element element ) { | |
Resource resource = createResoure( ResourceType.JS, element ); | |
currentGroup.addResource( resource ); | |
} | |
private Resource createResoure( ResourceType type, Element element ) { | |
final String minimizeAsString = element.getAttribute(ATTR_MINIMIZE); | |
final boolean minimize = StringUtils.isEmpty(minimizeAsString) | |
? true | |
: Boolean.valueOf(element.getAttribute(ATTR_MINIMIZE)); | |
String text = element.getTextContent(); | |
final Resource resource = Resource.create(text, type); | |
resource.setMinimize(minimize); | |
return resource; | |
} | |
private void parseChildren( WroModel model, Element element ) { | |
NodeList children = element.getChildNodes(); | |
for (int i = 0; i < children.getLength(); i++) { | |
if( Element.ELEMENT_NODE != children.item(i).getNodeType() ) { | |
continue; | |
} | |
final Element child = (Element)children.item(i); | |
parseElement( model, child ); | |
} | |
} | |
/** | |
* @return valid {@link Document} of the xml containing model representation. | |
*/ | |
private Document createDocument() { | |
try { | |
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | |
factory.setNamespaceAware(true); | |
final Document document = factory.newDocumentBuilder().parse(getModelResourceAsStream()); | |
document.getDocumentElement().normalize(); | |
return document; | |
} catch (final Exception e) { | |
throw new WroRuntimeException("Cannot build model from XML", e); | |
} | |
} | |
/** | |
* Parse the document and creates the model. | |
* | |
* @param document to parse. | |
* @return {@link WroModel} object. | |
*/ | |
private WroModel createModel() { | |
final WroModel model = new WroModel(); | |
return model; | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
@Override | |
protected String getDefaultModelFilename() { | |
return DEFAULT_FILE_NAME; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment