package org.korsakow.ide.ui.controller.action.snu;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.dsrg.soenea.domain.MapperException;
import org.korsakow.domain.RuleFactory;
import org.korsakow.domain.Settings;
import org.korsakow.domain.Snu;
import org.korsakow.domain.command.Request;
import org.korsakow.domain.command.UpdateSnuCommand;
import org.korsakow.domain.interf.IEvent;
import org.korsakow.domain.interf.IInterface;
import org.korsakow.domain.interf.IMedia;
import org.korsakow.domain.interf.IPredicate;
import org.korsakow.domain.interf.IProject;
import org.korsakow.domain.interf.IRule;
import org.korsakow.domain.interf.ISettings;
import org.korsakow.domain.interf.ISnu;
import org.korsakow.domain.interf.ISound;
import org.korsakow.domain.interf.ITrigger;
import org.korsakow.domain.interf.ISnu.BackgroundSoundMode;
import org.korsakow.domain.mapper.input.InterfaceInputMapper;
import org.korsakow.domain.mapper.input.MediaInputMapper;
import org.korsakow.domain.mapper.input.ProjectInputMapper;
import org.korsakow.domain.mapper.input.SettingsInputMapper;
import org.korsakow.domain.mapper.input.SoundInputMapper;
import org.korsakow.ide.code.RuleParserException;
import org.korsakow.ide.code.k5.K5Code;
import org.korsakow.ide.code.k5.K5CodeGenerator;
import org.korsakow.ide.code.k5.K5Lexeme;
import org.korsakow.ide.code.k5.K5RuleParser;
import org.korsakow.ide.code.k5.K5Symbol;
import org.korsakow.ide.resources.PredicateType;
import org.korsakow.ide.resources.TriggerType;
import org.korsakow.ide.rules.RuleType;
import org.korsakow.ide.ui.components.code.CodeTableModel;
import org.korsakow.ide.ui.controller.helper.ViewHelper;
import org.korsakow.ide.ui.model.EventModel;
import org.korsakow.ide.ui.model.PredicateModel;
import org.korsakow.ide.ui.model.RuleModel;
import org.korsakow.ide.ui.model.TriggerModel;
import org.korsakow.ide.ui.resources.SnuResourceView;
public class SnuHelper {
public static Request createRequest(SnuResourceView view, Long id)
{
Request request = new Request();
request.set(UpdateSnuCommand.ID, id);
request.set(UpdateSnuCommand.NAME, view.getNameFieldText().trim());
request.set(UpdateSnuCommand.KEYWORDS, view.getKeywords());
request.set(UpdateSnuCommand.MAIN_MEDIA_ID, view.getMainMediaId());
if ( view.getMainMediaCustomDuration() != null )
request.set(UpdateSnuCommand.MAIN_MEDIA_CUSTOM_DURATION, view.getMainMediaCustomDuration() );
request.set(UpdateSnuCommand.RATING, view.getRating());
switch (view.getBackgroundSoundMode())
{
case CLEAR:
case KEEP:
request.set(UpdateSnuCommand.BACKGROUND_SOUND_ID, null);
break;
case SET:
request.set(UpdateSnuCommand.BACKGROUND_SOUND_ID, view.getBackgroundSoundId());
break;
}
request.set(UpdateSnuCommand.BACKGROUND_SOUND_MODE, view.getBackgroundSoundMode());
request.set(UpdateSnuCommand.BACKGROUND_SOUND_VOLUME, 1.0f);
request.set(UpdateSnuCommand.BACKGROUND_SOUND_LOOPING, view.getBackgroundSoundLooping());
request.set(UpdateSnuCommand.LIVES, view.getLives());
request.set(UpdateSnuCommand.INTERFACE_ID, view.getInterfaceId());
request.set(UpdateSnuCommand.MAX_LINKS, view.getMaxLinks());
request.set(UpdateSnuCommand.LOOPING, view.getLooping());
request.set(UpdateSnuCommand.STARTER, view.getStarter());
request.set(UpdateSnuCommand.ENDER, view.getEnder());
request.set(UpdateSnuCommand.PREVIEW_MEDIA_ID, view.getPreviewMediaId());
request.set(UpdateSnuCommand.PREVIEW_TEXT, view.getPreviewText());
request.set(UpdateSnuCommand.INSERT_TEXT, view.getInsertText());
// TODO: remove reference to Rule objects
List<IRule> searchRules = getSearchRules(view);
List<IRule> rules = (List<IRule>)view.getCachedRules();
if (rules == null)
rules = new ArrayList<IRule>();
rules.addAll(searchRules);
ViewHelper.addRulesToRequest(request, rules);
return request;
}
public static List<IRule> getSearchRules(SnuResourceView resourceView)
{
K5RuleParser parser = new K5RuleParser();
List<IRule> rules = new ArrayList<IRule>();
CodeTableModel codeModel = resourceView.getCodeTable().getModel();
boolean isFirstTime = true;
for (int i = 0; i < codeModel.getRowCount(); ++i)
{
Long time = codeModel.getTimeAt(i);
if (time == null) {
// not sure what we should do... for now we just ignore them
continue;
}
Long maxLinks = codeModel.getMaxLinksAt(i);
K5Code code = codeModel.getCodeAt(i);
List<IRule> subRules = Collections.EMPTY_LIST;
try {
List<K5Lexeme> lexemes = parser.tokenize(code.getRawCode());
subRules = parser.createRules(lexemes);
// handle special cases
boolean clearorkeepIsExplicitlyStated = false;
K5Lexeme firstLexeme = lexemes.isEmpty()?null:lexemes.get(0);
if (firstLexeme != null)
{
switch (firstLexeme.getOpType())
{
case CLEAR_PREVIOUS_LINKS:
case KEEP_PREVIOUS_LINKS:
clearorkeepIsExplicitlyStated = true;
break;
}
}
if (!clearorkeepIsExplicitlyStated)
{
if (isFirstTime) {
subRules.add(0, RuleFactory.createClearScoresRule());
}
// else do nothing since there is no (and no need for) a KeepScoresRule
}
} catch (RuleParserException e) {
// just omit these
// its okay since the code editor identifies erroneous entries
continue;
}
IRule searchRule = RuleFactory.createSearchRule(subRules);
searchRule.setTriggerTime(time);
searchRule.setDynamicProperty("maxLinks", maxLinks);
rules.add(searchRule);
isFirstTime = false;
}
return rules;
}
public static void initView(SnuResourceView view, String name, IMedia mainMedia) throws MapperException
{
ISettings settings = SettingsInputMapper.find();
final String similarName = settings.getBoolean(Settings.PutSimilarResourcesAtTop)?mainMedia.getName():null;
final IProject project = ProjectInputMapper.find();
view.setNameFieldText(name);
view.setMainMedia(mainMedia);
view.setRating(1.0f);
view.setPreviewMediaChoices(ViewHelper.sort(MediaInputMapper.findAll(), IMedia.class, similarName));
view.setPreviewMedia(mainMedia);
List<IInterface> interfaces = InterfaceInputMapper.findAll();
view.setInterfaceChoices(ViewHelper.sort(interfaces, IInterface.class, similarName));
if (project.getDefaultInterface() != null)
view.setInterface(project.getDefaultInterface());
else if (!interfaces.isEmpty())
view.setInterface(interfaces.get(0));
view.setBackgroundSoundChoices(ViewHelper.sort(SoundInputMapper.findAll(), ISound.class, similarName));
view.setBackgroundSound(Snu.DEFAULT_BACKGROUNDSOUNDMODE);
view.repaint();
view.revalidate();
}
public static void initView(SnuResourceView view, ISnu snu) throws MapperException
{
ISettings settings = SettingsInputMapper.find();
final String similarName = settings.getBoolean(Settings.PutSimilarResourcesAtTop)?snu.getMainMedia().getName():null;
view.setResourceId(snu.getId());
view.setNameFieldText(snu.getName());
view.setKeywords(snu.getKeywords());
view.setMainMedia(snu.getMainMedia());
view.setRating(snu.getRating());
view.setBackgroundSoundChoices(ViewHelper.sort(SoundInputMapper.findAll(), ISound.class, similarName));
if (snu.getBackgroundSoundMode() == BackgroundSoundMode.SET)
view.setBackgroundSound(snu.getBackgroundSound());
else
view.setBackgroundSound(snu.getBackgroundSoundMode());
view.setBackgroundSoundLoop(snu.getBackgroundSoundLooping());
view.setInterfaceChoices(ViewHelper.sort(InterfaceInputMapper.findAll(), IInterface.class, similarName));
view.setInterface(snu.getInterface());
view.setLives(snu.getLives());
view.setMaxLinks(snu.getMaxLinks());
view.setLooping(snu.getLooping());
view.setStarter(snu.getStarter());
view.setEnder(snu.getEnder());
view.setPreviewMediaChoices(ViewHelper.sort(MediaInputMapper.findAll(), IMedia.class, similarName));
view.setPreviewMedia(snu.getPreviewMedia());
view.setPreviewText(snu.getPreviewText());
view.setInsertText(snu.getInsertText());
List<IRule> allRules = new ArrayList<IRule>(snu.getRules());
List<IRule> searchRules = getSearchRules(allRules);
allRules.removeAll(searchRules);
setSearchRules(view, searchRules);
view.setCachedRules(new ArrayList<IRule>(allRules));
view.repaint();
view.revalidate();
}
private static TriggerModel getTriggerModel(ITrigger trigger)
{
TriggerType triggerType = TriggerType.forId(trigger.getTriggerType());
TriggerModel model = new TriggerModel(triggerType);
for (String id : trigger.getDynamicPropertyIds())
model.addProperty(id, trigger.getDynamicProperty(id));
List<TriggerModel> children = new ArrayList<TriggerModel>();
return model;
}
private static PredicateModel getPredicateModel(IPredicate predicate)
{
PredicateType predicateType = PredicateType.forId(predicate.getPredicateType());
PredicateModel model = new PredicateModel(predicateType);
for (String id : predicate.getDynamicPropertyIds())
model.addProperty(id, predicate.getDynamicProperty(id));
List<PredicateModel> children = new ArrayList<PredicateModel>();
for (IPredicate child : predicate.getPredicates())
children.add(getPredicateModel(child));
model.setPredicates(children);
return model;
}
private static RuleModel getRuleModel(IRule rule)
{
RuleType ruleType = RuleType.forId(rule.getRuleType());
RuleModel model = new RuleModel(ruleType);
for (String id : rule.getDynamicPropertyIds())
model.setProperty(id, rule.getDynamicProperty(id));
List<RuleModel> children = new ArrayList<RuleModel>();
for (IRule child : rule.getRules())
children.add(getRuleModel(child));
model.setRules(children);
return model;
}
private static Collection<EventModel> createEventModels(Collection<IEvent> events)
{
Collection<EventModel> eventModels = new ArrayList<EventModel>();
for (IEvent event : events) {
TriggerModel triggerModel = getTriggerModel(event.getTrigger());
PredicateModel predicateModel = getPredicateModel(event.getPredicate());
RuleModel ruleModel = getRuleModel(event.getRule());
EventModel model = new EventModel(triggerModel, predicateModel, ruleModel);
eventModels.add(model);
}
return eventModels;
}
private static List<IRule> getSearchRules(List<IRule> snuRules)
{
List<IRule> searchRules = new ArrayList<IRule>();
for (IRule rule : snuRules)
if (RuleType.Search.getId().equals(rule.getRuleType()))
searchRules.add(rule);
return searchRules;
}
private static void setSearchRules(SnuResourceView resourceView, List<IRule> searchRules)
{
K5CodeGenerator gen = new K5CodeGenerator();
CodeTableModel codeModel = new CodeTableModel();
boolean isFirstTime = true;
for (IRule searchRule : searchRules) {
List<IRule> rules = searchRule.getRules();
// this is the default behavior and is not shown in the ui
// if (isFirstTime && !rules.isEmpty() && rules.get(0).getRuleType() == RuleType.ClearScores)
// rules.remove(0);
// this is the default behavior and is not shown in the ui
// if (!isFirstTime && !rules.isEmpty() && rules.get(0).getRuleType() != RuleType.ClearScores)
// rules.remove(0);
K5Code code = gen.createK5CodeOmitUnsupported(rules, isFirstTime);
if (isFirstTime && (rules.isEmpty() || !RuleType.ClearScores.getId().equals(rules.get(0).getRuleType()))) {
code.setRawCode(K5Symbol.KEEP_PREVIOUS_LINKS + K5Symbol.DEFAULT_STATEMENT_SEPARATOR_STRING + code.getRawCode());
}
int row = codeModel.addRow(searchRule.getTriggerTime(), code);
Long maxLinks;
try {
maxLinks = Long.parseLong(""+searchRule.getDynamicProperty("maxLinks"));
} catch (Exception e) {
maxLinks = null;
}
codeModel.setMaxLinks(maxLinks, row);
isFirstTime = false;
}
resourceView.getCodeTable().setModel(codeModel);
}
}