Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
      Copyright (c) 2013 zuendorf 
   
      Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
      and associated documentation files (the "Software"), to deal in the Software without restriction, 
      including without limitation the rights to use, copy, modify, merge, publish, distribute, 
      sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
      furnished to do so, subject to the following conditions: 
   
     The above copyright notice and this permission notice shall be included in all copies or 
     substantial portions of the Software. 
  
     The Software shall be used for Good, not Evil. 
  
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
     BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
     DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
   */
  
  package org.sdmlib.models.transformations;
  
  
  import org.sdmlib.CGUtil;
  
  
  public class Template implements PropertyChangeInterface
  {
     // ==========================================================================
  
     protected PropertyChangeSupport listeners = new PropertyChangeSupport(this);
  
     @Override
     {
        return ;
     }
  
     public void addPropertyChangeListener(PropertyChangeListener listener)
     {
     }
  
     // ==========================================================================
  
     public void removeYou()
     {
        setChooser(null);
        withoutMatches(this.getMatches().toArray(new Match[this.getMatches().size()]));
        withoutParents(this.getParents().toArray(new PlaceHolderDescription[this.getParents().size()]));
        getPropertyChangeSupport().firePropertyChange("REMOVE_YOU"thisnull);
     }
  
     // ==========================================================================
  
     public static final String PROPERTY_TEMPLATETEXT = "templateText";
  
     private String templateText = "";
  
     public String getTemplateText()
     {
        return this.;
     }
  
     public void setTemplateText(String value)
     {
        if (!StrUtil.stringEquals(this.value))
        {
           String oldValue = this.;
           this. = value;
           getPropertyChangeSupport().firePropertyChange(oldValuevalue);
        }
     }
  
     public Template withTemplateText(String value)
     {
        setTemplateText(value);
        return this;
     }
  
    @Override
    public String toString()
    {
       StringBuilder s = new StringBuilder();
 
       s.append(" ").append(this.getTemplateText());
       s.append(" ").append(this.getModelClassName());
       s.append(" ").append(this.getExpandedText());
       s.append(" ").append(this.getListStart());
       s.append(" ").append(this.getListSeparator());
       s.append(" ").append(this.getListEnd());
       s.append(" ").append(this.getName());
       return s.substring(1);
    }
 
    public Template withSimple(String propertyName)
    {
       return with("_""_"propertyName);
    }
 
    public Template withReplacements(String... placeholderAttrNamePairs)
    {
       for (int i = 0; i + 2 <= placeholderAttrNamePairs.lengthi += 2)
       {
          this.createPlaceholders().withTextFragment(placeholderAttrNamePairs[i]).withAttrName(placeholderAttrNamePairs[i + 1]);
       }
 
       return this;
    }
 
    public Template with(String templateTextString... placeholderAttrNamePairs)
    {
       this.setTemplateText(templateText);
 
       this.withReplacements(placeholderAttrNamePairs);
 
       return this;
    }
 
    public Template withList(String startString separatorString end)
    {
       this.setListStart(start);
       this.setListSeparator(separator);
       this.setListEnd(end);
 
       return this;
    }
 
    // ==========================================================================
 
    public static final String PROPERTY_MODELOBJECT = "modelObject";
 
    private Object modelObject;
 
    public Object getModelObject()
    {
       return this.;
    }
 
    public void setModelObject(Object value)
    {
       if (this. != value)
       {
          Object oldValue = this.;
          this. = value;
          getPropertyChangeSupport().firePropertyChange(oldValuevalue);
       }
    }
 
    public Template withModelObject(Object value)
    {
       setModelObject(value);
       return this;
    }
 
    // ==========================================================================
 
    public static final String PROPERTY_MODELCLASSNAME = "modelClassName";
 
    private String modelClassName;
 
    public String getModelClassName()
    {
       return this.;
    }
 
    public void setModelClassName(String value)
    {
       if (!StrUtil.stringEquals(this.value))
       {
          String oldValue = this.;
          this. = value;
       }
    }
 
    public Template withModelClassName(String value)
    {
       setModelClassName(value);
       return this;
    }
 
    {
       PlaceHolderDescription placeholder = this.createPlaceholders();
 
       Template subTemplate = placeholder.createSubTemplate();
 
       return subTemplate;
    }
 
    // ==========================================================================
 
    public static final String PROPERTY_EXPANDEDTEXT = "expandedText";
 
    private String expandedText;
 
    protected JsonIdMap idMap;
 
    public String getExpandedText()
    {
       return this.;
    }
 
    public void setExpandedText(String value)
    {
       if (!StrUtil.stringEquals(this.value))
       {
          String oldValue = this.;
          this. = value;
          getPropertyChangeSupport().firePropertyChange(oldValuevalue);
       }
    }
 
    public Template withExpandedText(String value)
    {
       setExpandedText(value);
       return this;
    }
 
    protected int currentPosInExpandedText = 0;
 
 
    public int getValueStartPos()
    {
       return ;
    }
 
    public Template withValueStartPos(int valueStartPos)
    {
       this. = valueStartPos;
       return this;
    }
 
    public Match parseOnceNew()
    {
       this. = 0;
       return parseOnce();
    }
 
    public MatchSet parse()
    {
       MatchSet result = new MatchSet();
       if (!isList())
       {
          Match subMatch = parseOnce();
 
          if (subMatch != null)
          {
             result.add(subMatch);
          }
       }
       else
       {
          int oldValueStartPos = 0;
 
          // look for list start
          int listStartPos = this.getExpandedText().indexOf(this.getListStart(), );
 
          if (listStartPos >= 0)
          {
 
             LinkedHashSet<ObjectmodelObjectSet = new LinkedHashSet<Object>();
 
             oldValueStartPos = ;
             Match subMatch = parseOnce();
 
             while (subMatch != null)
             {
                // add to results
                modelObjectSet.add(this.getModelObject());
                result.add(subMatch);
 
                // skip list separator
                int listSeperatorPos = this.getExpandedText().indexOf(this.getListSeparator(), );
                int behindListSeparatorPos = listSeperatorPos + this.getListSeparator().length();
                int listEndPos = this.getExpandedText().indexOf(this.getListEnd(), );
 
                if (" ".equals(this.getListSeparator()))
                {
                   int length = this.getExpandedText().length();
                   boolean startFound = false;
                   for (int i = i < lengthi++)
                   {
                      char charAt = .charAt(i);
                      if (!startFound && Character.isWhitespace(charAt))
                      {
                         startFound = true;
                         listSeperatorPos = i;
                         behindListSeparatorPos = i + 1;
                      }
                      else if (startFound)
                      {
                         if (Character.isWhitespace(charAt))
                         {
                            behindListSeparatorPos = i + 1;
                         }
                         else
                         {
                            break;
                         }
                      }
                   }
                }
 
                if ("".equals(this.getListEnd()))
                {
                   // there is no good list end symbol use constFragment behind
                   // list placeholder instead
                   listEndPos = this.getExpandedText().indexOf(this.);
                }
 
                boolean found = listSeperatorPos ==  && listSeperatorPos <= listEndPos;
 
                if (found)
                {
                   // more to come
                   oldValueStartPos = ;
 
                    = behindListSeparatorPos;
 
                   subMatch = parseOnce();
                }
                else
                {
                   subMatch = null;
                   oldValueStartPos = ;
                }
             }
 
              = oldValueStartPos;
 
             // skip list end
             int listEndPos = this.getExpandedText().indexOf(this.getListEnd(), );
 
             if (listEndPos == )
             {
                 =  + getListEnd().length();
             }
 
             this.setModelObject(modelObjectSet);
          }
       }
 
       return result;
    }
 
    public static int logStartPos = 8331;
 
    public Match parseOnce()
    {
       // the templateText contains placeholders and constant text fragments.
       // Match the constant fragments in the expanded text.
       // Assign the content in between to the placeholders
 
       int placeHolderPosInTemplateText = 0;
       int currentPosInTemplateText = 0;
 
       // int constantStartPosInExpandedText = 0;
 
       int matchStartPos = ;
 
       Match templateMatch = new Match()
          .withFullText(this.getExpandedText())
          .withStartPos(matchStartPos);
 
       PlaceHolderDescription previousPlaceHolder;
 
       // split template text into fragments and identify fragments in expanded
       // text
       Iterator<PlaceHolderDescriptioniterator = this.getPlaceholders().iterator();
       if (iterator.hasNext())
       {
          PlaceHolderDescription placeholder = iterator.next();
 
          // find constant fragment before placeholder
          placeHolderPosInTemplateText = this.getTemplateText().indexOf(placeholder.getTextFragment(), currentPosInTemplateText);
 
          String constfragment = this.getTemplateText().substring(currentPosInTemplateTextplaceHolderPosInTemplateText);
 
          currentPosInTemplateText = placeHolderPosInTemplateText + placeholder.getTextFragment().length();
 
          // find fragment in expanded text
          int endOfMatchInExpandedText = matchConstantFragmentToExpandedText(constfragment);
 
          // constantStartPosInExpandedText =
          // this.getExpandedText().indexOf(constfragment,
          // currentPosInExpandedText);
 
          if ( !=  || endOfMatchInExpandedText < )
          {
             return null;
          }
 
           = endOfMatchInExpandedText;
 
          SendableEntityCreator creator = this.getIdMap().getCreator(this.getModelClassName(), true);
 
          boolean first = true;
 
          while (true)
          {
             if ( >= )
             {
                ..print("Parsing at " +  + ": "
                   + getExpandedText().substring(, Math.min( + 50, getExpandedText().length())));
                ..println();
             }
 
             previousPlaceHolder = placeholder;
 
             if (iterator.hasNext())
             {
                placeholder = iterator.next();
             }
             else
             {
                placeholder = null;
             }
 
             // find constant fragment before placeholder
             if (placeholder != null)
             {
                placeHolderPosInTemplateText = this.getTemplateText().indexOf(placeholder.getTextFragment(), currentPosInTemplateText);
             }
             else
             {
                placeHolderPosInTemplateText = this.getTemplateText().length();
             }
 
             constfragment = this.getTemplateText().substring(currentPosInTemplateTextplaceHolderPosInTemplateText);
 
             if (placeholder != null)
             {
                currentPosInTemplateText = placeHolderPosInTemplateText + placeholder.getTextFragment().length();
             }
 
             Template subTemplate = previousPlaceHolder.getSubTemplate();
             if (subTemplate != null)
             {
                // ask subtemplate to parse
                MatchSet subMatches = subTemplate.withExpandedText(this.getExpandedText()).withValueStartPos()
                   .withIdMap().withConstFragmentFollowingAfterList(constfragment)
                   .parse();
 
                if (!subMatches.isEmpty())
                {
                   // create placeholderMatch
                   Match placeholderMatch = new Match()
                      .withPlaceholder(previousPlaceHolder)
                      .withModelObject(this.getModelObject())
                      .withFullText(this.getExpandedText())
                      .withStartPos()
                      .withEndPos(subTemplate.getValueStartPos() - 1)
                      .withParentMatch(templateMatch)
                      .withSubMatches(subMatches.toArray(new Match[]
                      {}));
 
                }
 
                this. = subTemplate.getValueStartPos();
 
                // now the constant fragment should follow
                endOfMatchInExpandedText = matchConstantFragmentToExpandedText(constfragment);
 
                // constantStartPosInExpandedText =
                // this.getExpandedText().indexOf(constfragment,
                // currentPosInExpandedText);
 
                if (endOfMatchInExpandedText < 0)
                {
                   return null;
                }
 
                 = endOfMatchInExpandedText;
             }
             else
             {
                // find fragment in expanded text
                endOfMatchInExpandedText = matchConstantFragmentToExpandedText(constfragment);
 
                if (endOfMatchInExpandedText < 0)
                {
                   return null;
                }
 
                if (constfragment.equals(""))
                {
                   // empty constfragment, look for list separator
                   int listSeparatorPos = this.getExpandedText().indexOf(this.getListSeparator(), );
                   int listEndPos = this.getExpandedText().indexOf(this.getListEnd(), );
 
                   if ("".equals(this.getListEnd()))
                   {
                      // there is no good list end symbol use constFragment
                      // behind list placeholder instead
                      listEndPos = this.getExpandedText().indexOf(this.);
                   }
 
                   if (!"".equals(this.getListSeparator()) && listSeparatorPos >= 0 && listSeparatorPos < listEndPos)
                   {
                       = listSeparatorPos;
                      endOfMatchInExpandedText = listSeparatorPos;
                   }
                   else if (listEndPos >= 0)
                   {
                       = listEndPos;
                      endOfMatchInExpandedText = listEndPos;
                   }
                   else
                   {
                      return null;
                   }
                }
 
                String value = this.getExpandedText().substring();
 
                int valueStartPos = ;
 
                 = endOfMatchInExpandedText;
 
                if (first)
                {
                   first = false;
 
                   // look for object in idMap
                   String key = getModelClassName() + "_" + value;
                   Object object = .getObject(key);
 
                   if (object != null && this. == false)
                   {
                      ..println("Warning: two objects with id: " + key);
                   }
 
                   if (object == null || this. == false)
                   {
                      // create object and assign attribute
                      object = creator.getSendableInstance(false);
                   }
 
                   .put(keyobject);
 
                   this.setModelObject(object);
                }
                creator.setValue(this.getModelObject(), previousPlaceHolder.getAttrName(), value"update");
 
                // create placeholderMatch
                Match placeholderMatch = new Match()
                   .withPlaceholder(previousPlaceHolder)
                   .withModelObject(this.getModelObject())
                   .withFullText(this.getExpandedText())
                   .withStartPos(valueStartPos)
                   .withEndPos(endOfMatchInExpandedText - 1)
                   .withParentMatch(templateMatch);
             }
 
             if (placeholder == null)
             {
                break;
             }
          }
       }
 
       // found a match, protocol it
       templateMatch.withEndPos( - 1)
          .withTemplate(this)
          .withModelObject(this.getModelObject());
 
       return templateMatch;
    }
 
    private int startOfMatch = -1;
 
    private int matchConstantFragmentToExpandedText(String constfragmentint currentPosInExpandedText)
    {
       int currentPosInConstFragment = 0;
 
       int blankPos = constfragment.indexOf(' ');
 
       if (blankPos <= 0)
       {
          // no blank, take it all
          blankPos = constfragment.length();
       }
 
       // search for real prefix in text
       currentPosInExpandedText = this..indexOf(constfragment.substring(0, blankPos), currentPosInExpandedText);
 
       if (currentPosInExpandedText < 0)
       {
          return -1;
       }
 
        = currentPosInExpandedText;
 
       while (currentPosInConstFragment < constfragment.length())
       {
          char constFragmentChar = constfragment.charAt(currentPosInConstFragment);
 
          if (constFragmentChar == ' ')
          {
             char nextFragmentChar = .;
             if (currentPosInConstFragment + 1 < constfragment.length())
             {
                nextFragmentChar = constfragment.charAt(currentPosInConstFragment + 1);
             }
 
             while (currentPosInExpandedText < .length()
                && Character.isWhitespace(.charAt(currentPosInExpandedText))
                && .charAt(currentPosInExpandedText) != nextFragmentChar)
             {
                currentPosInExpandedText++;
             }
 
             currentPosInConstFragment++;
          }
          else
          {
             if (.charAt(currentPosInExpandedText) != constFragmentChar)
             {
                return -1;
             }
             currentPosInConstFragment++;
             currentPosInExpandedText++;
          }
       }
 
       return currentPosInExpandedText;
    }
 
    protected Template withConstFragmentFollowingAfterList(String constfragment)
    {
       this. = constfragment;
       return this;
    }
 
    private IdMap getIdMap()
    {
       if (this. == null)
       {
          this. = new GenericIdMap();
       }
       return ;
    }
 
    private boolean isList()
    {
       return !"".equals(this.getListStart() + this.getListSeparator() + this.getListEnd());
    }
 
    protected Template withIdMap(JsonIdMap idMap2)
    {
       this. = idMap2;
 
       return this;
    }
 
    public static int expansionStep = 0;
 
    public void generate()
    {
       // expand all placeholder descriptions
       StringBuilder result = new StringBuilder();
 
       provideIdMap();
 
       LinkedHashSet<ObjectrootObjects = new LinkedHashSet<Object>();
 
       if ( == null)
       {
          this.setExpandedText("");
          return;
       }
 
       if ( instanceof Collection)
       {
          Collection<?> collection = (Collection<?>) ;
          if (!collection.isEmpty())
          {
             Object elem = collection.iterator().next();
 
             if ("Double Integer String".indexOf(CGUtil.shortClassName(elem.getClass().getName())) >= 0)
             {
                rootObjects.add();
             }
             else
             {
                rootObjects.addAll((Collection<?>) );
             }
          }
       }
       else
       {
          rootObjects.add();
       }
 
       result.append(this.getListStart());
 
       boolean first = true;
 
       for (Object root : rootObjects)
       {
          if (first)
          {
             first = false;
             this.setModelClassName(root.getClass().getName());
          }
          else
          {
             result.append(this.getListSeparator());
          }
 
          int searchPos = 0;
 
          // expand template
          for (PlaceHolderDescription placeholder : this.getPlaceholders())
          {
             // find textFragment in template text
             int foundPos = this.getTemplateText().indexOf(placeholder.getTextFragment(), searchPos);
 
             if (foundPos >= 0)
             {
                // copy initial template fragment to result
                result.append(this.getTemplateText().substring(searchPosfoundPos));
 
                // read attribute and append to result
                Object attrValue = getValue(placeholderroot);
 
                Template subTemplate = placeholder.getSubTemplate();
                if (subTemplate == null)
                {
                   // use value direct
                   ++;
                   if ( >= )
                   {
                      ..print("Expansion step " +  + ": " + this + " " + attrValue);
                      ..println();
                   }
                   result.append(attrValue);
                }
                else
                {
                   // use subtemplate
                   ++;
                   if ( >= )
                   {
                      ..print("Expansion step " +  + ": " + subTemplate + " " + attrValue);
                      ..println();
                   }
                   subTemplate.withModelObject(attrValue)
                      .generate();
 
                   result.append(subTemplate.getExpandedText());
                }
 
                // update positions
                searchPos = foundPos + placeholder.getTextFragment().length();
             }
          }
 
          // append closing text fragment
          result.append(this.getTemplateText().substring(searchPos));
       }
 
       result.append(this.getListEnd());
 
       this.setExpandedText(result.toString());
    }
 
    public static int logStartStep = 453;
 
    private Object getValue(PlaceHolderDescription placeholderObject root)
    {
       SendableEntityCreator creator;
 
       String[] split = placeholder.getAttrName().split("\\.");
 
       Object currentObject = root;
 
       for (String attrName : split)
       {
          Integer index = null;
 
          try
          {
             index = Integer.valueOf(attrName);
          }
          catch (NumberFormatException e)
          {
             // do nothing
          }
 
          if (index != null)
          {
             // look up the element with this index
             Object[] array = ((Collection<?>) currentObject).toArray(new Object[((Collection<?>) currentObject).size()]);
 
             currentObject = array[index];
          }
          else if (currentObject instanceof ArrayList)
          {
             ArrayList<?> arrayList = (ArrayList<?>) currentObject;
             currentObject = arrayList.get(Integer.valueOf(attrName));
          }
          else
          {
             creator = .getCreatorClass(currentObject);
             if (creator == null)
             {
                creator = new GenericCreator().withClassName(currentObject
                   .getClass().getName());
             }
             currentObject = creator.getValue(currentObjectattrName);
          }
       }
 
       return currentObject;
    }
 
    private void provideIdMap()
    {
       try
       {
          if ( == null)
          {
             String className = .getClass().getName();
             String packageName = CGUtil.packageName(className) + ".util";
             className = packageName + "." + CGUtil.shortClassName(className) + "Creator";
 
              = new GenericIdMap();
 
             Class<?> creatorClass = Class.forName(className);
             Method method = creatorClass.getDeclaredMethod("createIdMap"String.class);
 
             JsonIdMap newIdMap = (JsonIdMapmethod.invoke(null"debug");
 
             .withCreator(newIdMap);
          }
       }
       catch (Exception e)
       {
 
       }
 
    }
 
    // ==========================================================================
 
    public static final String PROPERTY_LISTSTART = "listStart";
 
    private String listStart = "";
 
    public String getListStart()
    {
       return this.;
    }
 
    public void setListStart(String value)
    {
       if (!StrUtil.stringEquals(this.value))
       {
          String oldValue = this.;
          this. = value;
          getPropertyChangeSupport().firePropertyChange(oldValuevalue);
       }
    }
 
    public Template withListStart(String value)
    {
       setListStart(value);
       return this;
    }
 
    // ==========================================================================
 
    public static final String PROPERTY_LISTSEPARATOR = "listSeparator";
 
    private String listSeparator = "";
 
    public String getListSeparator()
    {
       return this.;
    }
 
    public void setListSeparator(String value)
    {
       if (!StrUtil.stringEquals(this.value))
       {
          String oldValue = this.;
          this. = value;
          getPropertyChangeSupport().firePropertyChange(oldValuevalue);
       }
    }
 
    public Template withListSeparator(String value)
    {
       setListSeparator(value);
       return this;
    }
 
    // ==========================================================================
 
    public static final String PROPERTY_LISTEND = "listEnd";
 
    private String listEnd = "";
 
    public String getListEnd()
    {
       return this.;
    }
 
    public void setListEnd(String value)
    {
       if (!StrUtil.stringEquals(this.value))
       {
          String oldValue = this.;
          this. = value;
          getPropertyChangeSupport().firePropertyChange(oldValuevalue);
       }
    }
 
    public Template withListEnd(String value)
    {
       setListEnd(value);
       return this;
    }
 
    public Template withParent(String textFragmentString attrName)
    {
       this.getParents().first().withTextFragment(textFragment).withAttrName(attrName);
 
       return this;
    }
 
    public static final TemplateSet EMPTY_SET = new TemplateSet();

   
              many                       many
 Template ----------------------------------- PlaceHolderDescription
              owners                   placeholders
 
 
 
    public static final String PROPERTY_PLACEHOLDERS = "placeholders";
 
    private PlaceHolderDescriptionSet placeholders = null;
 
    {
       if (this. == null)
       {
          return .;
       }
 
       return this.;
    }
 
    public boolean addToPlaceholders(PlaceHolderDescription value)
    {
       boolean changed = false;
 
       if (value != null)
       {
          if (this. == null)
          {
             this. = new PlaceHolderDescriptionSet();
          }
 
          changed = this..add(value);
 
          if (changed)
          {
             value.withOwners(this);
             getPropertyChangeSupport().firePropertyChange(nullvalue);
          }
       }
 
      return changed;
   }
   public boolean removeFromPlaceholders(PlaceHolderDescription value)
   {
      boolean changed = false;
      if ((this. != null) && (value != null))
      {
         changed = this..remove(value);
         if (changed)
         {
            value.withoutOwners(this);
            getPropertyChangeSupport().firePropertyChange(valuenull);
         }
      }
      return changed;
   }
   {
      for (PlaceHolderDescription item : value)
      {
         addToPlaceholders(item);
      }
      return this;
   }
   {
      for (PlaceHolderDescription item : value)
      {
         removeFromPlaceholders(item);
      }
      return this;
   }
   public void removeAllFromPlaceholders()
   {
      for (PlaceHolderDescription value : tmpSet)
      {
         this.removeFromPlaceholders(value);
      }
   }
   {
      PlaceHolderDescription value = new PlaceHolderDescription();
      withPlaceholders(value);
      return value;
   }

   
              many                       one
 Template ----------------------------------- ChoiceTemplate
              choices                   chooser
 
   public static final String PROPERTY_CHOOSER = "chooser";
   private ChoiceTemplate chooser = null;
   {
      return this.;
   }
   public boolean setChooser(ChoiceTemplate value)
   {
      boolean changed = false;
      if (this. != value)
      {
         ChoiceTemplate oldValue = this.;
         if (this. != null)
         {
            this. = null;
            oldValue.withoutChoices(this);
         }
         this. = value;
         if (value != null)
         {
            value.withChoices(this);
         }
         getPropertyChangeSupport().firePropertyChange(oldValuevalue);
         changed = true;
      }
      return changed;
   }
   public Template withChooser(ChoiceTemplate value)
   {
      setChooser(value);
      return this;
   }
   {
      ChoiceTemplate value = new ChoiceTemplate();
      withChooser(value);
      return value;
   }

   
              one                       many
 Template ----------------------------------- Match
              template                   matches
 
   public static final String PROPERTY_MATCHES = "matches";
   private MatchSet matches = null;
   public MatchSet getMatches()
   {
      if (this. == null)
      {
         return .;
      }
      return this.;
   }
   public boolean addToMatches(Match value)
   {
      boolean changed = false;
      if (value != null)
      {
         if (this. == null)
         {
            this. = new MatchSet();
         }
         changed = this..add(value);
         if (changed)
         {
            value.withTemplate(this);
            getPropertyChangeSupport().firePropertyChange(nullvalue);
         }
      }
      return changed;
   }
   public boolean removeFromMatches(Match value)
   {
      boolean changed = false;
      if ((this. != null) && (value != null))
      {
         changed = this..remove(value);