/* Copyright 2006 VPAC * * This file is part of qc. * qc is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * qc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with qc; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.vpac.qc.model.query; import java.util.ArrayList; import org.jdom.Element; import org.jdom.JDOMException; import org.vpac.qc.model.clients.GenericClient; /** * This class is the default implementation of the abstract {@link Query}. A * class extending {@link UserInput} is needed to be able to retrieve user * input. * <p> * For more information read the documentation of {@link Query}. * * @author Markus Binsteiner * */ public class UserInputQuery extends Query { private ArrayList<QueryArgument> defaults = null; private ArrayList<QueryArgument> preselection = null; private ArrayList<QueryArgument> userInput = null; private ArrayList<QueryArgument> inputDependant = null; private ArrayList<QueryArgument> userNeeded = null; private ArrayList<Object> userNeededValues = null; private UserInput ui = null; public UserInputQuery(String name, GenericClient client, String context) { super(name, client, context); } public void init() throws JDOMException, ArgumentsException { defaults = new ArrayList<QueryArgument>(); preselection = new ArrayList<QueryArgument>(); userInput = new ArrayList<QueryArgument>(); inputDependant = new ArrayList<QueryArgument>(); userNeeded = new ArrayList<QueryArgument>(); userNeededValues = new ArrayList<Object>(); super.init(); } protected void setArguments(String[] argNames) throws JDOMException, ArgumentsException { this.arguments = new QueryArgument[argNames.length]; for (int i = 0; i < arguments.length; i++) { this.arguments[i] = QueryArgument .argumentFactory(this, argNames[i]); String typeString = this.arguments[i].getType().getAttributeValue( "name"); if (ArgumentType.DEFAULT.equals(typeString)) defaults.add(this.arguments[i]); else if (ArgumentType.INPUT_DEPENDANT.equals(typeString)) { inputDependant.add(this.arguments[i]); } else if (ArgumentType.PRESELECTION.equals(typeString)) { preselection.add(this.arguments[i]); userNeeded.add(this.arguments[i]); } else if (ArgumentType.USERINPUT.equals(typeString)) { userInput.add(this.arguments[i]); userNeeded.add(this.arguments[i]); } else throw new JDOMException("Could not get type of argument: " + this.arguments[i].name); } } public void fillPreselections() throws ArgumentsException { for (QueryArgument arg : preselection) { try { arg.retrieveValue(); } catch (Throwable e) { arg.changeType(ArgumentType.USERINPUT); } if (arg.getValue() == null) { arg.changeType(ArgumentType.USERINPUT); } } } public void fillUserInputWithDefaults() throws ArgumentsException { for (QueryArgument arg : userInput) { try { arg.retrieveValue(); } catch (Throwable e) { arg.setValue(new Object[] {}); } if (arg.getValue() == null) { arg.setValue(new Object[] {}); } } } public void fillDefaults() throws ArgumentsException { for (QueryArgument arg : defaults) { try { arg.retrieveValue(); } catch (Throwable e) { myLogger.warn("Could not fill argument \"" + arg.getName() + "\"with default value. Cause: " + e.getMessage()); arg.changeType(ArgumentType.USERINPUT); } if (arg.getValue() == null) { arg.changeType(ArgumentType.USERINPUT); } } } // public Element getRootElement() { // return rootElement; // } // public static void main (String[] args){ // // try { // // GenericClient client = new // VomrsClient({""},/home/markus/workspace/voc/queries.xml); // // UserInputQuery userInputQuery = new UserInputQuery("testQuery", new // File("/home/markus/workspace/voc/queries.xml"), // new String[]{ "test21", "test10", "test1009", "test50", "representatives" // }); // //new String[]{ "default1", "default2", "testprop", "testprop_list", // "testprop_compbined", "test21", "test10", "test1009", "test50" }, new // File("/home/markus/workspace/voc/queries.xml")); // // userInputQuery.fillDefaults(); // userInputQuery.fillPreselections(); // // for ( QueryArgument qarg : userInputQuery.getArguments() ){ // // System.out.println("Argument: "+qarg.getName()); // try { // for ( Object obj : (Object[])qarg.getValue() ){ // System.out.println("Object: "+obj+"\tClass: "+obj.getClass().toString()); // } // } catch (ClassCastException e) { // System.out.println("Single object: "+qarg.getValue()+"\tClass: // "+qarg.getValue().getClass().toString()); // } // System.out.println(); // // } // // } catch (Exception e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // // } /** * This class returns all the QueryArguments that need user interaction * (userinput and preselection). They are converted into * UserInterfaceArguments. The main difference to QueryArguments is that the * preselection is filtered. The userinterface gives back an array of * Objects in the same order than the userNeeded Array in this * (UserInputQuery) class. * * @return an array of UserInterfaceArguments */ public ArrayList<UserInterfaceArgument> getUserNeededArguments() { ArrayList<UserInterfaceArgument> result = new ArrayList<UserInterfaceArgument>(); for (QueryArgument arg : userNeeded) { boolean isPreselection = false; ArrayList<Object> presel_new = null; if (ArgumentType.PRESELECTION.equals(arg.getType() .getAttributeValue("name"))) { isPreselection = true; } if (arg.getValue() == null || arg.getValue().length == 0) { result.add(new UserInterfaceArgument(arg.getName(), arg .getPrettyName(), arg.getDescription(), null, false)); } else { Object[] presel = null; try { presel = (Object[]) arg.getValue(); } catch (ClassCastException e) { presel = new Object[] { arg.getValue() }; } presel_new = new ArrayList<Object>(); String filter = arg.getType().getChild("method") .getAttributeValue("filter"); int start = 0; int increment = 1; if ("even".equals(filter)) { start = 0; increment = 2; } else if ("uneven".equals(filter)) { start = 1; increment = 2; } for (int i = start; i < presel.length; i = i + increment) { presel_new.add(presel[i]); } result.add(new UserInterfaceArgument(arg.getName(), arg .getPrettyName(), arg.getDescription(), presel_new, isPreselection)); } } return result; } public void connect(UserInput ui) { this.ui = ui; } public void fillUserInput() throws ArgumentsException { Object[] values = ui.getUserInput(); if (values.length != userNeeded.size()) { throw new ArgumentsException( "The lengths of QueryArgument array and values array differ."); } // fill input dependent values now, because the value field is not // overwritten yet fillInputDependent(values); // TODO check user input for (int i = 0; i < userNeeded.size(); i++) { userNeeded.get(i).setValue(new Object[] { values[i] }); } } private void fillInputDependent(Object[] values) throws ArgumentsException { for (int i = 0; i < inputDependant.size(); i++) { Element method = inputDependant.get(i).getType().getChild("method"); String otherArgument = method.getAttributeValue("object"); int index = -1; QueryArgument other = null; // find the other argument for (index = 0; index < userNeeded.size(); index++) { if (otherArgument.equals(userNeeded.get(index).getName())) break; } other = arguments[index]; String property = method.getAttributeValue("object_property"); Object new_value = processInputDependentValue(other, values[index], property); if (new_value == null) { throw new ArgumentsException( "Could not get user dependant value for QueryArgument: " + inputDependant.get(i).getName()); } inputDependant.get(i).setValue(new Object[] { new_value }); } } // this is all a bit dodgy. private Object processInputDependentValue(QueryArgument otherArg, Object other, String filter) { int relative = Integer.MIN_VALUE; try { relative = new Integer(filter); } catch (NumberFormatException e) { // TODO implement other filters here return null; } // find the position of the other result. we can assume that the other // arg has an object[] as value int index = -1; Object[] values = ((Object[]) (otherArg.getValue())); for (index = 0; index < values.length; index++) { if (other.equals(values[index])) { break; } } return values[index + relative]; } private void setUserNeededValues(ArrayList<Object> userNeededValues) { this.userNeededValues = userNeededValues; } public void prepare() throws ArgumentsException { this.fillDefaults(); this.fillPreselections(); this.fillUserInputWithDefaults(); } }