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

org.openmdx.portal.servlet.AbstractApiController Maven / Gradle / Ivy

The newest version!
/*
 * ====================================================================
 * Project:     openMDX/Portal, http://www.openmdx.org/
 * Description: AbstractApiController
 * Owner:       the original authors.
 * ====================================================================
 *
 * This software is published under the BSD license
 * as listed below.
 * 
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 * 
 * * Neither the name of the openMDX team nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * ------------------
 * 
 * This product includes software developed by other organizations as
 * listed in the NOTICE file.
 */
package org.openmdx.portal.servlet;

import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.jdo.PersistenceManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.openmdx.base.accessor.jmi.cci.RefObject_1_0;
import org.openmdx.base.exception.ServiceException;
import org.openmdx.base.naming.Path;
import org.openmdx.kernel.exception.BasicException;
import org.openmdx.kernel.log.SysLog;

/**
 * AbstractApiController
 *
 */
public abstract class AbstractApiController {

	public static class ObjectReferenceBean {

		/**
		 * @return the title
		 */
		public String getTitle() {
			return title;
		}
		/**
		 * @param title the title to set
		 */
		public void setTitle(String title) {
			this.title = title;
		}
		/**
		 * @return the xri
		 */
		public String getXri() {
			return xri;
		}
		/**
		 * @param xri the xri to set
		 */
		public void setXri(String xri) {
			this.xri = xri;
		}
		
		private String title;
		private String xri;
	}

	public static class QueryBean {
	
		/**
		 * @return the position
		 */
		public Integer getPosition() {
			return position;
		}
		/**
		 * @param position the position to set
		 */
		public void setPosition(Integer position) {
			this.position = position;
		}
		/**
		 * @return the size
		 */
		public Integer getSize() {
			return size;
		}
		/**
		 * @param size the size to set
		 */
		public void setSize(Integer size) {
			this.size = size;
		}
		/**
		 * @return the query
		 */
		public String getQuery() {
			return query;
		}
		/**
		 * @param query the query to set
		 */
		public void setQuery(String query) {
			this.query = query;
		}
		
		private Integer position;
		private Integer size;
		private String query;
	}
	
	public static class OptionBean {
		
		/**
		 * @return the value
		 */
		public Short getValue() {
			return value;
		}
		/**
		 * @param value the value to set
		 */
		public void setValue(Short value) {
			this.value = value;
		}
		/**
		 * @return the title
		 */
		public String getTitle() {
			return title;
		}
		/**
		 * @param title the title to set
		 */
		public void setTitle(String title) {
			this.title = title;
		}
		
		private Short value;
		private String title;
	}

	/**
	 * VoidBean
	 *
	 */
	public static class VoidBean {
		
	}

	/**
	 * Constructor 
	 *
	 */
	public AbstractApiController(
	) {
	}
	
	/**
	 * Init request dispatcher.
	 * 
	 * @param request
	 * @param assertRequestId
	 * @param assertObjectXri
	 */
	public boolean init(
		HttpServletRequest request,
		String encoding
	) {
		try {
			request.setCharacterEncoding(encoding);
		} catch(Exception ignore) {
			SysLog.trace("Exception ignored", ignore);
		}
		this.request = request;
		this.session = request.getSession();
		this.app = (ApplicationContext)this.session.getAttribute(WebKeys.APPLICATION_KEY);
		this.parameterMap = this.request.getParameterMap();
		this.requestId = this.getFirstParameterValue(
			this.parameterMap, 
			Action.PARAMETER_REQUEST_ID
		);
		this.pm = this.app.getNewPmData();
		this.texts = this.app.getTexts();
		this.codes = this.app.getCodes();
		return true;
	}

	/**
	 * Invoked by handle() before command-specific method is called.
	 * 
	 * @return
	 * @throws ServiceException
	 */
	protected boolean prepare(
	) throws ServiceException {
		return true;
	}

	/**
	 * Get first value of given parameter.
	 * 
	 * @param parameterMap
	 * @param parameterName
	 * @return
	 */
	protected String getFirstParameterValue(
		Map parameterMap,
		String parameterName
	) {
		String[] parameterValues = this.getParameterValues(parameterMap, parameterName);
		return parameterValues == null || parameterValues.length == 0
			? null 
			: parameterValues[0];
	}
	
	/**
	 * Get values of given parameter.
	 * 
	 * @param parameterMap
	 * @param parameterName
	 * @return
	 */
	protected String[] getParameterValues(
		Map parameterMap,
		String parameterName
	) {
		return parameterMap.get(parameterName) == null || parameterMap.get(parameterName).length == 0
			? null
			: parameterMap.get(parameterName);		
	}
	
	/**
	 * Get element label.
	 * 
	 * @param qualifiedElementName
	 * @return
	 * @throws ServiceException
	 */
	protected String getLabel(
		String qualifiedElementName
	) throws ServiceException {
		ApplicationContext app = this.getApp();
		List labels = app.getUiElementDefinition(qualifiedElementName).getLabel();
		return app.getCurrentLocaleAsIndex() < labels.size()
			? labels.get(app.getCurrentLocaleAsIndex())
			: labels.get(0);
	}

	/**
	 * Get element tool tips.
	 * 
	 * @param qualifiedElementName
	 * @return
	 * @throws ServiceException
	 */
	protected String getToolTip(
		String qualifiedElementName
	) throws ServiceException {
		ApplicationContext app = this.getApp();
		List toolTips = app.getUiElementDefinition(qualifiedElementName).getToolTip();
		return app.getCurrentLocaleAsIndex() < toolTips.size()
			? toolTips.get(app.getCurrentLocaleAsIndex())
			: toolTips.get(0);
	}

	/**
	 * Get options for given code container.
	 * 
	 * @param name
	 * @param locale
	 * @param includeAll
	 * @return
	 * @throws ServiceException
	 */
	protected List getOptions(
		String name,
		short locale,
		boolean includeAll
	) throws ServiceException {
		Map codeEntries = codes.getLongTextByCode(name, locale, includeAll);		
		List options = new ArrayList();
		for(Map.Entry codeEntry: codeEntries.entrySet()) {
			AbstractApiController.OptionBean optionBean = new AbstractApiController.OptionBean();
			optionBean.setValue(codeEntry.getKey());
			optionBean.setTitle(codeEntry.getValue());
			options.add(optionBean);
		}
		return options;
	}

	/**
	 * Get object reference bean for given object.
	 * 
	 * @param obj
	 * @return
	 */
	protected ObjectReferenceBean newObjectReferenceBean(
		RefObject_1_0 obj
	) {
		ApplicationContext app = this.getApp();
		ObjectReferenceBean objRef = new ObjectReferenceBean();
		objRef.setXri(obj.refGetPath().toXRI());
		objRef.setTitle(
			app.getPortalExtension().getTitle(
				obj, 
				app.getCurrentLocaleAsIndex(), 
				app.getCurrentLocaleAsString(), 
				false, // asShortTitle, 
				app
			)
		);
		return objRef;
	}

	/**
	 * Invoke the method corresponding to the command.
	 * 
	 * @param command
	 * @param position
	 * @param size
	 * @param reader
	 * @return
	 * @throws ServiceException
	 */
	protected Object forward(
		String command,
		Path xri,
		Reader reader
	) throws ServiceException {
		if(!this.prepare()) {
			return false;
		}
		this.command = command;
		String methodName = command;
		Method method = null;
		for(Method m: this.getClass().getDeclaredMethods()) {
			if(m.getName().equals(methodName)) {
				method = m;
				break;
			}
		}
		// No action method found in declaring class. Check super types.
		if(method == null) {
			for(Method m: this.getClass().getMethods()) {
				if(m.getName().equals(methodName)) {
					method = m;
					break;
				}
			}		
		}
		if(method != null) {
			Class[] parameterTypes = method.getParameterTypes();
			// get...(path)
			if(
				parameterTypes.length == 1 &&
				command.startsWith("get") &&
				parameterTypes[0] == Path.class
			) {
				try {
					return method.invoke(
						this, 
						xri 
					);
				} catch(InvocationTargetException e) {
		        	ServiceException e0 = new ServiceException(
	                	BasicException.toStackedException(
	                		e.getTargetException(),
	                		e,
	    	                BasicException.Code.DEFAULT_DOMAIN,
	    	                BasicException.Code.SYSTEM_EXCEPTION,
	    	                "Error invoking method " + command
	                	));
		        	throw e0;
				} catch(Exception e) {
					throw new ServiceException(e);
				}
			} else if(
				parameterTypes.length == 2 &&
				parameterTypes[0] == Path.class
			) {
				try {
					return method.invoke(
						this, 
						xri,
						this.fromJson(reader, parameterTypes[1])
					);
				} catch(InvocationTargetException e) {
		        	ServiceException e0 = new ServiceException(
	                	BasicException.toStackedException(
	                		e.getTargetException(),
	                		e,
	    	                BasicException.Code.DEFAULT_DOMAIN,
	    	                BasicException.Code.SYSTEM_EXCEPTION,
	    	                "Error invoking method " + command
	                	));
		        	throw e0;
				} catch(Exception e) {
					throw new ServiceException(e);
				}
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	/**
	 * Read Json and map to bean.
	 * 
	 * @param reader
	 * @param clazz
	 * @return
	 * @throws ServiceException
	 */
	public abstract Object fromJson(
		Reader reader,
		Class clazz
	) throws ServiceException;

	/**
	 * Stringify object as Json.
	 * 
	 * @param object
	 * @return
	 * @throws ServiceException
	 */
	public abstract String toJson(
		Object object
	) throws ServiceException;

	/**
	 * Handle the requested command. Invoke the method corresponding to the command.
	 * 
	 * @param command
	 * @return
	 * @throws ServiceException
	 */
	public Object handle(
	) throws ServiceException {
		Path xri = new Path(this.getFirstParameterValue(this.parameterMap, "xri"));
		// PUT|POST
		if("PUT".equalsIgnoreCase(this.request.getMethod()) || "POST".equalsIgnoreCase(this.request.getMethod())) {
			SysLog.detail("PUT {0}", xri.toXRI());
			Reader reader;
			try {
				reader = new InputStreamReader(this.request.getInputStream(), "UTF-8");
			} catch(Exception ignore) {
				reader = null;
			}
			String command = xri.getLastSegment().toClassicRepresentation();
			return this.forward(
				command,
				xri,
				reader
			);
		} else {
			SysLog.detail("GET {0}", xri.toXRI());
			String command = xri.getLastSegment().toClassicRepresentation();
			return this.forward(
				command,
				xri,
				null
			);
		}
	}

	/**
	 * Close controller and associated resources.
	 * 
	 * @throws ServiceException
	 */
	public void close(
	) throws ServiceException {
		if(this.pm != null) {
			try {
				this.pm.close();
			} catch(Exception ignore) {}
		}
	}
	
	/**
	 * Retrieve app.
	 *
	 * @return Returns the app.
	 */
	public ApplicationContext getApp(
	) {
		return this.app;
	}

	/**
	 * Set app.
	 * 
	 * @param app The app to set.
	 */
	public void setApp(
		ApplicationContext app
	) {
		this.app = app;
	}

	/**
	 * Retrieve pm.
	 *
	 * @return Returns the pm.
	 */
	public PersistenceManager getPm(
	) {
		return this.pm;
	}

	/**
	 * Set pm.
	 * 
	 * @param pm The pm to set.
	 */
	public void setPm(
		PersistenceManager pm
	) {
		this.pm = pm;
	}

	/**
	 * Retrieve texts.
	 *
	 * @return Returns the texts.
	 */
	public Texts_1_0 getTexts(
	) {
		return this.texts;
	}

	/**
	 * Set texts.
	 * 
	 * @param texts The texts to set.
	 */
	public void setTexts(
		Texts_1_0 texts
	) {
		this.texts = texts;
	}

	/**
	 * Retrieve codes.
	 *
	 * @return Returns the codes.
	 */
	public Codes getCodes(
	) {
		return this.codes;
	}

	/**
	 * Set codes.
	 * 
	 * @param codes The codes to set.
	 */
	public void setCodes(
		Codes codes
	) {
		this.codes = codes;
	}

	/**
	 * Retrieve request.
	 *
	 * @return Returns the request.
	 */
	public HttpServletRequest getRequest(
	) {
		return this.request;
	}

	/**
	 * Set request.
	 * 
	 * @param request The request to set.
	 */
	public void setRequest(
		HttpServletRequest request
	) {
		this.request = request;
	}
		
	/**
	 * Retrieve session.
	 *
	 * @return Returns the session.
	 */
	public HttpSession getSession(
	) {
		return this.session;
	}

	/**
	 * Set session.
	 * 
	 * @param session The session to set.
	 */
	public void setSession(
		HttpSession session
	) {
		this.session = session;
	}

	/**
	 * Retrieve requestId.
	 *
	 * @return Returns the requestId.
	 */
	public String getRequestId(
	) {
		return this.requestId;
	}

	/**
	 * Set requestId.
	 * 
	 * @param requestId The requestId to set.
	 */
	public void setRequestId(
		String requestId
	) {
		this.requestId = requestId;
	}

	/**
	 * @return the command
	 */
	public String getCommand() {
		return command;
	}

	/**
	 * @param command the command to set
	 */
	public void setCommand(String command) {
		this.command = command;
	}

	/**
	 * @return the parameterMap
	 */
	public Map getParameterMap() {
		return parameterMap;
	}

	/**
	 * @param parameterMap the parameterMap to set
	 */
	public void setParameterMap(Map parameterMap) {
		this.parameterMap = parameterMap;
	}	
	
	//-----------------------------------------------------------------------
	// Members
	//-----------------------------------------------------------------------
	private HttpServletRequest request;
	private String command;	
	private String requestId;
	private HttpSession session;
	private ApplicationContext app;
	private PersistenceManager pm;
	private Texts_1_0 texts;
	private Codes codes;
	private Map parameterMap = null;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy