/*
* Copyright 2011 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.core.rebind.crossdevice;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.cruxframework.crux.core.client.screen.DeviceAdaptive.Device;
import org.cruxframework.crux.core.client.screen.DeviceAdaptive.Template;
import org.cruxframework.crux.core.client.screen.DeviceAdaptive.Templates;
import org.cruxframework.crux.core.client.utils.StringUtils;
import org.cruxframework.crux.core.rebind.context.RebindContext;
import org.cruxframework.crux.core.rebind.screen.View;
import org.cruxframework.crux.core.rebind.screen.ViewFactory;
import org.w3c.dom.Document;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JPackage;
import com.google.gwt.dev.resource.Resource;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class CrossDevicesTemplateParser
{
private ViewFactory viewFactory;
private JClassType baseIntf;
private RebindContext context;
private Device device;
private static DocumentBuilder documentBuilder;
private static Lock builderLock = new ReentrantLock();
public CrossDevicesTemplateParser(RebindContext context, JClassType baseIntf, Device device)
{
this.context = context;
this.baseIntf = baseIntf;
this.device = device;
this.viewFactory = new ViewFactory(context);
initializeDocumentBuilder();
}
private static void initializeDocumentBuilder()
{
if (documentBuilder == null)
{
builderLock.lock();
try
{
if (documentBuilder == null)
{
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
}
}
catch (ParserConfigurationException e)
{
throw new CrossDevicesException("Error creating XML Parser.", e);
}
finally
{
builderLock.unlock();
}
}
}
/**
*
* @return
*/
public String getTemplateController(View view, String deviceAdaptive, Device device)
{
Iterator<String> controllers = view.iterateControllers();
String controllerName = null;
if (controllers.hasNext())
{
controllerName = controllers.next();
if (controllers.hasNext())
{
throw new CrossDevicesException("Cross device templates can not define more than one controller. Cross device widget["+deviceAdaptive+"]. Device ["+device.toString()+"]");
}
}
if (StringUtils.isEmpty(controllerName))
{
throw new CrossDevicesException("Can not find the controller attribute for deviceAdaptive widget ["+deviceAdaptive+"]. Device ["+device.toString()+"]");
}
return controllerName;
}
/**
*
* @param template
* @param lastModified
* @param qualifiedSourceName
* @param device
* @return
*/
public View getTemplateView(Document template, String deviceAdaptive, long lastModified, Device device)
{
try
{
return viewFactory.getView(deviceAdaptive, device.toString(), template, lastModified, false);
}
catch (Exception e)
{
throw new CrossDevicesException("Error retrieving metadata from template associated with the deviceAdaptive widget ["+deviceAdaptive+"]. Device ["+device.toString()+"]", e);
}
}
public Resource getDeviceAdaptiveTemplateResource()
{
Templates templates = baseIntf.getAnnotation(Templates.class);
Template template = getTemplateForDevice(templates);
if (template != null)
{
JPackage adaptiveDevicePackage = baseIntf.getPackage();
String templateResource = (adaptiveDevicePackage!=null?adaptiveDevicePackage.getName().replaceAll("\\.", "/"):"")+"/"+template.name()+".xdevice.xml";
return context.getGeneratorContext().getResourcesOracle().getResource(templateResource);
}
return null;
}
public Document getDeviceAdaptiveTemplate(Resource resource)
{
if (resource != null)
{
try
{
InputStream stream = resource.openContents();
try
{
return documentBuilder.parse(stream);
}
finally
{
if (stream != null)
{
try
{
stream.close();
}
catch (IOException e)
{
// do nothing
}
}
}
}
catch (Exception e)
{
return null;
}
}
return null;
}
private Template getTemplateForDevice(Templates templates)
{
Template defaultTemplate = null;
for (Template template : templates.value())
{
if (template.device().equals(device))
{
return template;
}
}
return defaultTemplate;
}
}