/*
* � Copyright IBM Corp. 2013
*
* 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 com.ibm.xsp.extlib.device.impl;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Map;
import com.ibm.commons.util.StringUtil;
import com.ibm.xsp.FacesExceptionEx;
import com.ibm.xsp.designer.context.XSPUserAgent;
import com.ibm.xsp.extlib.device.Device;
import com.ibm.xsp.extlib.device.DeviceService;
import com.ibm.xsp.extlib.social.impl.ResourceImpl;
public class DeviceImpl extends ResourceImpl implements Device {
private static final long serialVersionUID = 1L;
public static final int PHONE = 1;
public static final int TABLET = 2;
public static final int OTHER = 4; //for example an iPod
public static final int GOOGLE = 8;
public static final int APPLE = 16;
public static final int MICROSOFT = 32;
public static final int BLACKBERRY = 64;
private int m_type = 0;
private Method[] methods = this.getClass().getMethods();
private static String[] PREFIXES = {"is","get"}; // $NON-NLS-1$ $NON-NLS-2$
private Map m_versions;
private XSPUserAgent _xspUserAgent;
public DeviceImpl(DeviceService service, String userAgent) {
super(service,userAgent);
userAgent = StringUtil.getNonNullString(userAgent);
parseBrowser(userAgent.toLowerCase());
}
@Override
public DeviceService getService() {
return (DeviceService)super.getService();
}
private Method retrieveMethod(String name)
{
for(String prefix:PREFIXES)
{
for(Method method:methods)
{
if(method.getName().equalsIgnoreCase(prefix+(String)name))
{
Class[] parameters = method.getParameterTypes();
// this avoids to call mehod with same name but with parameters, at the moment we don't support parameters
if(parameters.length == 0)
{
Object[] params = new Object[] {};
return method;
}
}
}
}
return null;
}
@Override
public Object getField(String key) {
// Look at the different providers
DeviceDataProvider[] dataProviders = (DeviceDataProvider[])getService().getResourceDataProviders();
for(int i=0; i<dataProviders.length; i++) {
DeviceDataProvider pd = dataProviders[i];
if(pd instanceof AbstractDeviceDataProvider) {
Object value = ((AbstractDeviceDataProvider)pd).getValue(this, key);
if(value!=null) {
return value;
}
}
}
Method met = retrieveMethod(key);
if(met != null)
{
try {
Object[] params = new Object[] {};
return met.invoke(this, params);
}
catch (Exception e) {
//Ignore exception
}
}
return super.getField(key);
}
/**
* This is mostly for dump/debug capability
* @param key
* @return
*/
@Override
public Object getFieldByProvider(String provider, String key) {
DeviceDataProvider[] dataProviders = (DeviceDataProvider[])getService().getResourceDataProviders();
for(int i=0; i<dataProviders.length; i++) {
DeviceDataProvider pd = dataProviders[i];
if(StringUtil.equals(pd.getName(),provider)) {
if(pd instanceof AbstractDeviceDataProvider) {
Object value = ((AbstractDeviceDataProvider)pd).getValue(this, key);
return value;
}
}
}
return null;
}
@Override
public void setField(String key, Object value) {
throw new FacesExceptionEx("\"Device\" objects cannot be modified."); // $NLX-DeviceImpl.TheDeviceImplobjectisreadonlyUset-1$
}
@Override
public Class<?> getType(Object key) {
DeviceDataProvider[] dataProviders = (DeviceDataProvider[])getService().getResourceDataProviders();
// Look at the different providers
for(int i=0; i<dataProviders.length; i++) {
DeviceDataProvider pd = dataProviders[i];
if(pd instanceof AbstractDeviceDataProvider) {
Class<?> type = ((AbstractDeviceDataProvider)pd).getType(this, key);
if(type!=null) {
return type;
}
}
}
if(key instanceof String)
{
Method met = retrieveMethod((String)key);
if(met != null)
{
return met.getReturnType();
}
}
return super.getType(key);
}
public boolean isAndroid()
{
return (m_type & GOOGLE) == GOOGLE;
}
public boolean isApple()
{
return (m_type & APPLE) == APPLE;
}
public boolean isBlackberry()
{
return (m_type & BLACKBERRY) == BLACKBERRY;
}
public boolean isWindows()
{
return (m_type & MICROSOFT) == MICROSOFT;
}
public boolean isMobile()
{
return (m_type & PHONE) == PHONE;
}
public boolean isTablet()
{
return (m_type & TABLET) == TABLET ;
}
public boolean isOther()
{
return (m_type & OTHER) == OTHER ;
}
public boolean isIphone()
{
return isApple() && isMobile() && !isOther();
}
public boolean isIpad()
{
return isApple() && isTablet();
}
public boolean isIpod()
{
return isApple() && isMobile() && isOther();
}
public Map getVersion()
{
return m_versions;
}
private String getVersion(String key)
{
if(_xspUserAgent == null)
{
_xspUserAgent = new XSPUserAgent(getId().toLowerCase());
}
return _xspUserAgent.getVersion(key);
}
protected void parseBrowser(String userAgentLC) {
if(m_type == 0)
{
m_versions = new Hashtable();
if(userAgentLC.contains("mobi")) // $NON-NLS-1$
{
m_type += PHONE;
}
if(userAgentLC.contains("tablet")) // $NON-NLS-1$
{
m_type += TABLET;
}
if(userAgentLC.contains("android")) // $NON-NLS-1$
{
m_type += GOOGLE;
if((m_type & PHONE) == 0)
{
m_type += TABLET;
}
m_versions.put("android", getVersion("android")); // $NON-NLS-1$ $NON-NLS-2$
}
else if(userAgentLC.contains("blackberry")) // $NON-NLS-1$
{
m_type += BLACKBERRY;
if((m_type & TABLET) == 0)
{
m_type += PHONE;
}
m_versions.put("blackberry",getVersion("blackberry")); // $NON-NLS-1$ $NON-NLS-2$
}
else if(userAgentLC.contains("windows")) // $NON-NLS-1$
{
String winVer = getVersion("windows phone"); // $NON-NLS-1$
if(StringUtil.isEmpty(winVer))
{
winVer = getVersion("windows phone os"); // $NON-NLS-1$
}
m_versions.put("windows",winVer); // $NON-NLS-1$
if(!StringUtil.isEmpty(winVer))
{
m_type += MICROSOFT;
}
}
else if(userAgentLC.contains("mac os")) // $NON-NLS-1$
{
m_type += APPLE;
String iDev = "iphone"; // $NON-NLS-1$
if(userAgentLC.contains("ipad")) // $NON-NLS-1$
{
m_type += TABLET;
if((m_type & PHONE) == PHONE)
{
m_type -= PHONE;
}
if((m_type & OTHER) == OTHER)
{
m_type -= OTHER;
}
iDev = "ipad"; // $NON-NLS-1$
}
else if(userAgentLC.contains("ipod")) // $NON-NLS-1$
{
if((m_type & PHONE) != PHONE)
{
m_type += PHONE;
}
if((m_type & OTHER) != OTHER)
{
m_type += OTHER;
}
iDev = "ipod"; // $NON-NLS-1$
}
String devVer = getVersion("iphone os");// $NON-NLS-1$
if(StringUtil.isEmpty(devVer))
{
devVer = getVersion("cpu os"); // $NON-NLS-1$
}
m_versions.put(iDev,devVer);
}
}
}
}