/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package datasource.explorer; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.logging.Logger; import ilog.cpl.datasource.IlpDefaultDataSource; import ilog.cpl.datasource.structure.IlpChild; import ilog.cpl.datasource.structure.IlpContainer; import ilog.cpl.model.IlpObject; /** * JTGO data source explorer sample 2 using a custom IlpClass. See * <A href="../../../index.html">index.html</A> for a description of this * sample. */ public class FileDataSource extends IlpDefaultDataSource { Logger log; /** * Constructor. */ public FileDataSource(Logger log) { // call the constructor of IlpDefaultDataSource super(); this.log = log; // loads the roots into the data source File[] rootdirs = File.listRoots(); addFiles(rootdirs); } /** * Adds files to the data source. * * @param files * The java.io.Files to be wrapped by FileObject. */ protected synchronized void addFiles(File[] files) { // Here we avoid calling IlpDefaultDataSource.addObject, as in this case // object would be inserted one by one. It would result in very low // performance, as each inserted object will result in one notification, // and each notification would result in a redrawing (in the tree for // example). So here the IlpObjects are stored in a list before calling // the addObjects method which will result in only one notification List<IlpObject> filesAsIlpObjects = new ArrayList<IlpObject>(files.length); for (int i = 0; i < files.length; i++) { // use the file itself as the object identifier File id = files[i]; try { if (id.canRead()) { if (getObject(id) == null) { IlpObject ilpObject = new FileObject(files[i]); filesAsIlpObjects.add(ilpObject); } } } catch (Exception e) { // just ignore entry } } if (filesAsIlpObjects.size() != 0) addObjects(filesAsIlpObjects); } /** * This method in conjunction with the two previous classes realizes * load-on-demand in the data source. */ Override public synchronized IlpContainer getContainerInterface(Object idOrIlpObject) { // retrieve the object from the id or the object IlpObject object = idOrIlpObject instanceof IlpObject ? (IlpObject) idOrIlpObject : getObject(idOrIlpObject); // if we retrieved the object and it is an instance of // FileObject.GetIlpClass() if (object != null && FileObject.GetIlpClass().isAssignableFrom(object.getIlpClass())) { // retrieve the file, and test if it is a directory, if not, return null. Boolean isDirectory = (Boolean) object.getAttributeValue(FileObject.DIRECTORY); if (isDirectory.booleanValue()) return DIRECTORY_LOADER; else return null; } // for all other classes than FileObject.GetIlpClass(), use the regular // implementation, // So the FileDataSource can behave like an ordinary IlpDefaultDataSource // for // all other classes. return super.getContainerInterface(idOrIlpObject); } /** * Container interface for file objects. This interface uses the listFiles * method to get the list of children. It tries to add them to the data source * content, doing the loading on demand, and then returns the list of * identifiers. */ IlpContainer DIRECTORY_LOADER = new IlpContainer() { Override public Collection<Object> getChildren(IlpObject object) { // the file is supposed to be a directory File directory = (File) object.getIdentifier(); File[] files = directory.listFiles(); if (files == null) return Collections.emptyList(); List<Object> filesIds = new ArrayList<Object>(files.length); for (int i = 0; i < files.length; i++) { // 1st get all the identifiers filesIds.add(files[i]); } // then add the files addFiles(files); return filesIds; } }; /** * This method in conjunction with the two previous classes realizes * load-on-demand in the data source. */ Override public synchronized IlpChild getChildInterface(Object idOrIlpObject) { // retrieve the object from the id or the object IlpObject object = idOrIlpObject instanceof IlpObject ? (IlpObject) idOrIlpObject : getObject(idOrIlpObject); // if the object is an instance of FileObject.GetIlpClass() if (object != null && FileObject.GetIlpClass().isAssignableFrom(object.getIlpClass())) { // retrieve the file it contains and returns it (see FILE_PARENT below). File file = (File) object.getIdentifier(); File parentFile = file.getParentFile(); if (parentFile != null) { return FILE_PARENT; } else { return null; } } return super.getChildInterface(idOrIlpObject); } /** * Child interface for file objects. This interface uses the getParentFile * method to get the parent. */ IlpChild FILE_PARENT = new IlpChild() { Override public Object getParent(IlpObject object) { File file = (File) object.getIdentifier(); File parentFile = file.getParentFile(); return parentFile; } }; }