/* * This program 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 3 of the License, or * (at your option) any later version. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * PropertyPath.java * Copyright (C) 2006-2012 University of Waikato, Hamilton, New Zealand package weka.core; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.StringTokenizer; import java.util.Vector; *//** * A helper class for accessing properties in nested objects, e.g., accessing the "getRidge" method of a LinearRegression classifier part of MultipleClassifierCombiner, e.g., Vote. For doing so, one needs to supply the object to work on and a property path. The property path is a dot delimited path of property names ("getFoo()" and "setFoo(int)" have "foo" as property name), indices of arrays are 0-based. E.g.: * <p/> * * <code>getPropertyDescriptor(vote, "classifiers[1].ridge")</code> will return the second classifier (which should be our LinearRegression) of the given Vote meta-classifier and there the property descriptor of the "ridge" property. <code>getValue(...)</code> will return the actual value of the ridge parameter and <code>setValue(...)</code> will set it. * * @author fracpete (fracpete at waikato dot ac dot nz) * @version $Revision: 8034 $ */ /* public class PropertyPath implements RevisionHandler { *//** * Represents a single element of a property path * * @author fracpete (fracpete at waikato dot ac dot nz) * @version $Revision: 8034 $ */ /* public static class PathElement implements Cloneable, RevisionHandler { *//** the property */ /* protected String m_Name; *//** the index of the array (-1 for none) */ /* protected int m_Index; *//** * initializes the path element with the given property * * @param property * the property to initialize with */ /* public PathElement(String property) { super(); if (property.indexOf("[") > -1) { m_Name = property.replaceAll("\\[.*$", ""); m_Index = Integer.parseInt(property.replaceAll(".*\\[", "").replaceAll("\\].*", "")); } else { m_Name = property; m_Index = -1; } } *//** * returns a clone of the current object * * @return the clone of the current state */ /* public Object clone() { return new PathElement(this.toString()); } *//** * returns the name of the property * * @return the name of the property */ /* public String getName() { return m_Name; } *//** * returns whether the property is an index-based one * * @return true if the property has an index */ /* public boolean hasIndex() { return (getIndex() > -1); } *//** * returns the index of the property, -1 if the property is not an index-based one * * @return the index of the property */ /* public int getIndex() { return m_Index; } *//** * returns the element once again as string * * @return the property as string */ /* public String toString() { String result; result = getName(); if (hasIndex()) result += "[" + getIndex() + "]"; return result; } *//** * Returns the revision string. * * @return the revision */ /* public String getRevision() { return RevisionUtils.extract("$Revision: 8034 $"); } } *//** * Contains a (property) path structure * * @author fracpete (fracpete at waikato dot ac dot nz) * @version $Revision: 8034 $ */ /* public static class Path implements RevisionHandler { *//** the structure */ /* protected Vector<PathElement> m_Elements; *//** * default constructor, only used internally */ /* protected Path() { super(); m_Elements = new Vector<PathElement>(); } *//** * uses the given dot-path * * @param path * path in dot-notation */ /* public Path(String path) { this(); m_Elements = breakUp(path); } *//** * uses the vector with PathElement objects to initialize with * * @param elements * the PathElements to use */ /* public Path(Vector<PathElement> elements) { this(); for (int i = 0; i < elements.size(); i++) m_Elements.add((PathElement) elements.get(i).clone()); } *//** * uses the given array as elements for the path * * @param elements * the path elements to use */ /* public Path(String[] elements) { this(); for (int i = 0; i < elements.length; i++) m_Elements.add(new PathElement(elements[i])); } *//** * breaks up the given path and returns it as vector * * @param path * the path to break up * @return the single elements of the path */ /* protected Vector<PathElement> breakUp(String path) { Vector<PathElement> result; StringTokenizer tok; result = new Vector<PathElement>(); tok = new StringTokenizer(path, "."); while (tok.hasMoreTokens()) result.add(new PathElement(tok.nextToken())); return result; } *//** * returns the element at the given index * * @param index * the index of the element to return * @return the specified element */ /* public PathElement get(int index) { return (PathElement) m_Elements.get(index); } *//** * returns the number of path elements of this structure * * @return the number of path elements */ /* public int size() { return m_Elements.size(); } *//** * returns a path object based on the given path string * * @param path * path to work on * @return the path structure */ /* public static Path parsePath(String path) { return new Path(path); } *//** * returns a subpath of the current structure, starting with the specified element index up to the end * * @param startIndex * the first element of the subpath * @return the new subpath */ /* public Path subpath(int startIndex) { return subpath(startIndex, size()); } *//** * returns a subpath of the current structure, starting with the specified element index up. The endIndex specifies the element that is not part of the new subpath. In other words, the new path contains the elements from "startIndex" up to "(endIndex-1)". * * @param startIndex * the first element of the subpath * @param endIndex * the element that is after the last added element * @return the new subpath */ /* public Path subpath(int startIndex, int endIndex) { Vector<PathElement> list; int i; list = new Vector<PathElement>(); for (i = startIndex; i < endIndex; i++) list.add(get(i)); return new Path(list); } *//** * returns the structure again as a dot-path * * @return the path structure as dot-path */ /* public String toString() { String result; int i; result = ""; for (i = 0; i < m_Elements.size(); i++) { if (i > 0) result += "."; result += m_Elements.get(i); } return result; } *//** * Returns the revision string. * * @return the revision */ /* public String getRevision() { return RevisionUtils.extract("$Revision: 8034 $"); } } *//** * A helper class that stores Object and PropertyDescriptor together. * * @author fracpete (fracpete at waikato dot ac dot nz) * @version $Revision: 8034 $ */ /* protected static class PropertyContainer implements RevisionHandler { *//** the descriptor */ /* //protected PropertyDescriptor m_Descriptor; *//** the associated object */ /* protected Object m_Object; *//** * initializes the container * * @param desc * the property descriptor * @param obj * the associated object */ /* public PropertyContainer(PropertyDescriptor desc, Object obj) { super(); m_Descriptor = desc; m_Object = obj; } *//** * returns the stored descriptor * * @return the stored descriptor */ /* public PropertyDescriptor getDescriptor() { return m_Descriptor; } *//** * returns the stored object * * @return the stored object */ /* public Object getObject() { return m_Object; } *//** * Returns the revision string. * * @return the revision */ /* public String getRevision() { return RevisionUtils.extract("$Revision: 8034 $"); } } *//** * returns the property and object associated with the given path, null if a problem occurred. * * @param src * the object to start from * @param path * the path to follow * @return not null, if the property could be found */ /* public static PropertyContainer find(Object src, Path path) { PropertyContainer result; //PropertyDescriptor desc; Object newSrc; PathElement part; Method method; Object methodResult; // get descriptor part = path.get(0); try { desc = new PropertyDescriptor(part.getName(), src.getClass()); } catch (Exception e) { desc = null; e.printStackTrace(); } // problem occurred? -> stop if (desc == null) return null; // end of path reached? if (path.size() == 1) { //result = new PropertyContainer(desc, src); } // recurse further else { try { //method = desc.getReadMethod(); methodResult = method.invoke(src, (Object[]) null); if (part.hasIndex()) newSrc = Array.get(methodResult, part.getIndex()); else newSrc = methodResult; result = find(newSrc, path.subpath(1)); } catch (Exception e) { result = null; e.printStackTrace(); } } return result; } *//** * returns the property associated with the given path, null if a problem occurred. * * @param src * the object to start from * @param path * the path to follow * @return not null, if the property could be found */ /* public static PropertyDescriptor getPropertyDescriptor(Object src, Path path) { PropertyContainer cont; cont = find(src, path); if (cont == null) return null; else return cont.getDescriptor(); } *//** * returns the property associated with the given path * * @param src * the object to start from * @param path * the path to follow * @return not null, if the property could be found */ /* public static PropertyDescriptor getPropertyDescriptor(Object src, String path) { return getPropertyDescriptor(src, new Path(path)); } *//** * returns the value specified by the given path from the object * * @param src * the object to work on * @param path * the retrieval path * @return the value, null if an error occurred */ /* public static Object getValue(Object src, Path path) { Object result; PropertyContainer cont; Method method; Object methodResult; PathElement part; result = null; cont = find(src, path); // problem? if (cont == null) return null; // retrieve the value try { part = path.get(path.size() - 1); method = cont.getDescriptor().getReadMethod(); methodResult = method.invoke(cont.getObject(), (Object[]) null); if (part.hasIndex()) result = Array.get(methodResult, part.getIndex()); else result = methodResult; } catch (Exception e) { result = null; e.printStackTrace(); } return result; } *//** * returns the value specified by the given path from the object * * @param src * the object to work on * @param path * the retrieval path * @return the value, null if an error occurred */ /* public static Object getValue(Object src, String path) { return getValue(src, new Path(path)); } *//** * set the given value specified by the given path in the object * * @param src * the object to work on * @param path * the retrieval path * @param value * the value to set * @return true if the value could be set */ /* public static boolean setValue(Object src, Path path, Object value) { boolean result; PropertyContainer cont; Method methodRead; Method methodWrite; Object methodResult; PathElement part; result = false; cont = find(src, path); // problem? if (cont == null) return result; // set the value try { part = path.get(path.size() - 1); methodRead = cont.getDescriptor().getReadMethod(); methodWrite = cont.getDescriptor().getWriteMethod(); if (part.hasIndex()) { methodResult = methodRead.invoke(cont.getObject(), (Object[]) null); Array.set(methodResult, part.getIndex(), value); methodWrite.invoke(cont.getObject(), new Object[] { methodResult }); } else { methodWrite.invoke(cont.getObject(), new Object[] { value }); } result = true; } catch (Exception e) { result = false; e.printStackTrace(); } return result; } *//** * set the given value specified by the given path in the object * * @param src * the object to work on * @param path * the retrieval path * @param value * the value to set */ /* public static void setValue(Object src, String path, Object value) { setValue(src, new Path(path), value); } *//** * Returns the revision string. * * @return the revision */ /* public String getRevision() { return RevisionUtils.extract("$Revision: 8034 $"); } *//** * for testing only * * @param args * the commandline options - ignored * @throws Exception * if something goes wrong */ /* public static void main(String[] args) throws Exception { // Path Path path = new Path("hello.world[2].nothing"); System.out.println("Path: " + path); System.out.println(" -size: " + path.size()); System.out.println(" -elements:"); for (int i = 0; i < path.size(); i++) System.out.println(" " + i + ". " + path.get(i).getName() + " -> " + path.get(i).getIndex()); // retrieving ridge with path weka.classifiers.meta.Vote vote = new weka.classifiers.meta.Vote(); vote.setClassifiers( new weka.classifiers.Classifier[]{ new weka.classifiers.trees.J48(), new weka.classifiers.functions.LinearRegression()}); path = new Path("classifiers[1].ridge"); System.out.println("path: " + path + " -> " + getValue(vote, path)); // setting ridge with path and retrieving it again setValue(vote, path.toString(), new Double(0.1)); System.out.println("path: " + path + " -> " + getValue(vote, path)); } } */