Package factOrFiction.model

Source Code of factOrFiction.model.CardPool

package factOrFiction.model;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;

import factOrFiction.Activator;
import factOrFiction.core.CardTemplate;
import factOrFiction.extension.ExtensionHandler;
import factOrFiction.extension.IExtensionCallback;
import factOrFiction.utils.CardNameUtil;
import factOrFiction.utils.FileUtils;

/**
* Manage two disparate set of card list:
*  + tournament legal cards as given by external plugin
*  + all registered cards from released editions as defined by plugins
* @author  E0420300
*/
public class CardPool extends Observable implements ICardFinder {
 
  private static final String FACT_OR_FICTION_EDITION_EXTENSION = "factOrFiction.core.edition";

  // moniker file to identify version of index
  private static final String INDEX_VERSION = "version-1.5";
 
  // sortable indeces in Lucene
  public static final String SORT_ON_EDITION = "sort-on-edition";
  public static final String SORT_ON_TYPE = "sort-on-type";
  public static final String SORT_ON_NAME = "sort-on-name";

  // Untokenized fields in Lucene
  public static final String ID = "id";
  public static final String PLUGIN = "ed";
  public static final String CLASS = "class";
 
  // Searchable fields in Lucene
  public static final String NAME = "name";
  public static final String TYPE = "type";
  public static final String TEXT = "text";
  public static final String EDITION = "edition";
  public static final String ARTIST = "artist";
  public static final String FLAVOR = "flavor";
  public static final String META = "meta";
  public static final String COLOR = "color";

  // Lucene needs known fixed value to do a 'find all', this is the value :)
  public static final String LUCENE_DEFAULT = "qbert";

  // Lucene stuff
  private RAMDirectory idx = null;
  private IndexSearcher idxSearcher = null;

  // keeps a (normalized) name to CardTemplate mapping
  // cached from queries to the registered plugins
  private HashMap<String, CardTemplate> cachedMap = null;
  private ExtensionHandler<CardTemplate> editionPluginHandler = null;

  // we're the one
  private static CardPool theInstance = new CardPool();

  private CardPool() {
    editionPluginHandler  = new ExtensionHandler<CardTemplate>(FACT_OR_FICTION_EDITION_EXTENSION);
    cachedMap = new HashMap<String, CardTemplate>(2048);
  }
 
  public static CardPool instance() {
    return theInstance;
  }
 
  // access to the Lucene store
  public IndexSearcher getIndexSearcher() {
    return idxSearcher;
  }


  public boolean lookupMetaInfo(String name, String meta) {
    if(idxSearcher != null) {
      Query idQuery = new TermQuery(new Term(ID, CardNameUtil.getNormalizedName(name)));
      Query metaQuery = new TermQuery(new Term(META, meta.toLowerCase()));
      BooleanQuery query = new BooleanQuery();
      query.add(idQuery, BooleanClause.Occur.MUST);
      query.add(metaQuery, BooleanClause.Occur.MUST);
     
      try {
        Hits hits = idxSearcher.search(query);
        return hits.length() > 0;
      } catch (IOException e) {
        e.getMessage();
      }
     
    }
    return false;
  }

  public CardTemplate lookup(Document doc) {
    String id = doc.getField(CardPool.ID).stringValue();
    String ed = doc.getField(CardPool.PLUGIN).stringValue();
    String classname = doc.getField(CardPool.CLASS).stringValue();
    return lookup(ed, classname, id);
  }

  public CardTemplate lookup(String symbolicBundleName, String className, String name) {
    String normName = CardNameUtil.getNormalizedName(name);
   
    CardTemplate card = cachedMap.get( normName  );
     
    if(card == null) {
      // check if deep search is needed
      if( "".equals(className) || "".equals(symbolicBundleName))
        return lookup(name);
     
      card = editionPluginHandler.createExecutableFromBundle(symbolicBundleName, className);
     
      if(card != null) {
        CardTemplateAdapter adapter = new CardTemplateAdapter(card);
        cachedMap.put(normName , adapter);
      }
    }
   
    return card;
  }

  public CardTemplate lookup(String name) {
    final String normName = CardNameUtil.getNormalizedName(name);
   
    CardTemplate card = cachedMap.get( normName  );
     
    if(card == null) {
      editionPluginHandler.scan(null, "name", new IExtensionCallback<CardTemplate> () {
        public boolean created(String extension, String name, CardTemplate clazz) {
          // cache data for later lookups
          if(!cachedMap.containsKey(name)) {
            CardTemplateAdapter adapter = new CardTemplateAdapter(clazz);
            cachedMap.put(name , adapter);
          }
         
          if( normName.equals(name) )
            return true;
           
          // don't abort
          return false;
        }
      });
    }
   
    // and try again, if found should be in the map by now
    return cachedMap.get( normName  );
  }

  public void initFromPlugins(IProgressMonitor monitor, boolean force) {
    monitor.beginTask("Reading Cardpool", 6);

    // check for stored Lucene index
    File indexPath = Activator.getDefault().getStateLocation().append(".index").toFile();
    File indexVersion = new File(indexPath, INDEX_VERSION);
        System.out.println("IndexPath:" + indexPath.getAbsolutePath());
        System.out.println("IndexVersion:" + indexVersion.getAbsolutePath());

    if( force || !indexPath.exists() || !indexVersion.exists() ) {
      // create path
      indexPath.mkdirs();
     
      // clear out directory
      FileUtils.deleteDirectoryContents(indexPath);
     
          try {
            Directory tempIdx = FSDirectory.getDirectory(indexPath, true);
           
            // gather all MetaInfo Provider
        ExtensionHandler<IMetaEnhancer> tournamentFormatPluginhandler = new ExtensionHandler<IMetaEnhancer>("factOrFiction.tournamentformat");
        final List<IMetaEnhancer> enhancer = tournamentFormatPluginhandler.createExecutables();
       
        if(enhancer != null) {
              for (IMetaEnhancer metaEnhancer : enhancer) {
                metaEnhancer.restore();
              }
        }
              // Make an writer to create the index
            final IndexWriter writer = new IndexWriter(tempIdx, new StandardAnalyzer(), true);
       
        SubProgressMonitor sub = new SubProgressMonitor(monitor, 3);
        editionPluginHandler.scan(sub, NAME, new IExtensionCallback<CardTemplate>() {
          public boolean created(String plugin, String name, CardTemplate clazz) {
                try {
                  String classname = clazz.getClass().getName();
             
                  Document doc = new Document();
     
                  // Add the title as an unindexed field...
              // This way we can retrieve it from the HashMap.
              // I would like to store something else than this string reference
              // but Lucene only allows for strings to be stored!?!?
                  doc.add( new Field(ID, name, Field.Store.YES, Field.Index.UN_TOKENIZED) );
                  doc.add( new Field(PLUGIN, plugin, Field.Store.YES, Field.Index.UN_TOKENIZED) );
                  doc.add( new Field(CLASS, classname, Field.Store.YES, Field.Index.UN_TOKENIZED) );
                 
                  // ...and the content as an indexed field. Note that indexed
                  doc.add(new Field(NAME, clazz.getName(), Field.Store.NO, Field.Index.TOKENIZED));
                  doc.add(new Field(TEXT, clazz.getText(), Field.Store.NO, Field.Index.TOKENIZED));
                  doc.add(new Field(TYPE, clazz.getType(), Field.Store.NO, Field.Index.TOKENIZED));
                  doc.add(new Field(FLAVOR, clazz.getFlavor(), Field.Store.NO, Field.Index.TOKENIZED));
                  doc.add(new Field(ARTIST, clazz.getArtist(), Field.Store.NO, Field.Index.TOKENIZED));
                  doc.add(new Field(EDITION, clazz.getEdition(), Field.Store.NO, Field.Index.TOKENIZED));
               
                  // build meta info, add known key
                  StringBuffer meta = new StringBuffer(LUCENE_DEFAULT);
                  for (IMetaEnhancer metaEnhancer : enhancer) {
                    String addOnMeta = metaEnhancer.getMetaInfo(clazz.getName());
                   
                    if(addOnMeta != null) {
                      meta.append(' ');
                  meta.append( addOnMeta );
                    }
              }
                  // Meta info such as tournament legality for filtering, searching
                  doc.add( new Field(META, meta.toString(), Field.Store.NO, Field.Index.TOKENIZED) );
                 
                  // TODO add direct info on color, hybrid
                  // build meta info, add known key
                  StringBuffer color = new StringBuffer();
              if(clazz.isWhite())
                    color.append(" white");
              if(clazz.isBlue())
                    color.append(" blue");
              if(clazz.isBlack())
                    color.append(" black");
              if(clazz.isRed())
                    color.append(" red");
              if(clazz.isGreen())
                    color.append(" green");
              if(clazz.isHybrid())
                    color.append(" hybrid");
              if(clazz.isLand())
                    color.append(" land");
                  doc.add( new Field(COLOR, color.toString(), Field.Store.NO, Field.Index.TOKENIZED) );
                 
                  // Sortable index on the title field
                  doc.add(new Field(SORT_ON_NAME, clazz.getName(), Field.Store.YES, Field.Index.UN_TOKENIZED));
                  doc.add(new Field(SORT_ON_TYPE, clazz.getType(), Field.Store.YES, Field.Index.UN_TOKENIZED));
                  doc.add(new Field(SORT_ON_EDITION, clazz.getEdition(), Field.Store.YES, Field.Index.UN_TOKENIZED));
 
                  writer.addDocument(doc);
            } catch (IOException e) {
              e.printStackTrace();
            }
            return false;
          }
        });

        // clean-up created index
        writer.optimize();
            writer.close();
            tempIdx.close();

            // create index version moniker
            indexVersion.createNewFile();
           
        monitor.worked(1);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
   
    try {
      // initialize our Lucene in memory storage (could be from existing index!)
      idx = new RAMDirectory(indexPath);
      monitor.worked(1);
         
      // setup an index searcher
      idxSearcher = new IndexSearcher(idx);
      monitor.worked(1);
     
      // notify everybody about changes
      setChanged();
      notifyObservers(idxSearcher);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
TOP

Related Classes of factOrFiction.model.CardPool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.