001/*
002 * file SimpleCreateQuery.java
003 *
004 * Licensed Materials - Property of IBM
005 * Restricted Materials of IBM - you are allowed to copy, modify and 
006 * redistribute this file as part of any program that interfaces with 
007 * IBM Rational CM API.
008 *
009 * com.ibm.rational.stp.client.samples.SimpleCreateQuery
010 *
011 * (C) Copyright IBM Corporation 2004, 2008.  All Rights Reserved.
012 * Note to U.S. Government Users Restricted Rights:  Use, duplication or 
013 * disclosure restricted by GSA ADP  Schedule Contract with IBM Corp.
014 */
015
016package com.ibm.rational.stp.client.samples;
017
018import static javax.swing.JOptionPane.showInputDialog;
019
020import java.util.ArrayList;
021import java.util.List;
022
023import javax.swing.JOptionPane;
024import javax.wvcm.ProviderFactory;
025import javax.wvcm.WvcmException;
026import javax.wvcm.PropertyRequestItem.PropertyRequest;
027
028import com.ibm.rational.wvcm.stp.StpLocation;
029import com.ibm.rational.wvcm.stp.StpProvider;
030import com.ibm.rational.wvcm.stp.StpResource;
031import com.ibm.rational.wvcm.stp.StpProvider.Domain;
032import com.ibm.rational.wvcm.stp.cc.CcProvider;
033import com.ibm.rational.wvcm.stp.cq.CqFieldDefinition;
034import com.ibm.rational.wvcm.stp.cq.CqProvider;
035import com.ibm.rational.wvcm.stp.cq.CqQuery;
036import com.ibm.rational.wvcm.stp.cq.CqRecordType;
037import com.ibm.rational.wvcm.stp.cq.CqResultSet;
038import com.ibm.rational.wvcm.stp.cq.CqQuery.DisplayField;
039import com.ibm.rational.wvcm.stp.cq.CqQuery.Filter;
040import com.ibm.rational.wvcm.stp.cq.CqQuery.Filter.Operation;
041import com.ibm.rational.wvcm.stp.cq.CqQuery.FilterLeaf.TargetType;
042
043/**
044 * @author trw
045 * 
046 */
047public class SimpleCreateQuery
048{
049
050    public static void main(String[] args) throws Exception
051    {
052        g_provider = (CqProvider) ProviderFactory
053                .createProvider(CqProvider.CQ_ONLY_PROVIDER_CLASS, g_callback);
054
055        // Get the location for the new query from the user
056        StpLocation location = g_provider.stpLocation
057                    (showInputDialog("Where do you want to create the query?",
058                                     "cq.query:<query path>@<dbset>/<userdb>"));
059        
060        // Get a proxy for the record type the query will target
061        CqRecordType rt = g_provider.buildProxy(CqRecordType.class, 
062                                                "cq.record:Defect@" 
063                                                    + location.getRepo());
064        
065        // Construct display field array and filter expression for the query
066        DisplayField[] fields =
067            new DisplayField[] {
068                buildColumn(rt, "id"), 
069                buildColumn(rt, "headline"),
070                buildColumn(rt, "customer.name"),
071                buildColumn(rt, "project.name"), 
072                buildColumn(rt, "description") };
073        Filter filter =
074            g_provider.buildFilterLeaf(buildPath(rt, "Owner.login_name"),
075                                       Operation.IS_EQUAL,
076                                       TargetType.CONSTANT,
077                                       "engineer"); 
078        
079        // Create a permanent version of this query
080        CqQuery query = g_provider.cqQuery(location);
081
082        query.setPrimaryRecordType(rt);
083        query.setDisplayFields(fields);
084        query.setFiltering(filter);
085        
086        query.doCreateQuery(null);
087
088        // Execute the query and print the results (optional)
089        CqResultSet results = query.doExecute(1, Integer.MAX_VALUE, null);
090    
091        while (results.hasNext()) {
092            String[] row = results.next().getStrings();
093            System.out.println(row[0] + ": (from " + row[2] + ") " + row[1]);
094        }
095    
096        results.release();
097        
098        // Clean up (present only for a repeatable demonstration)
099        query.doUnbindAll(null);
100    }
101
102    static DisplayField buildColumn(CqRecordType rt,
103                                       String path) throws WvcmException
104    {
105        return rt.cqProvider().buildDisplayField(buildPath(rt, path), true);
106    }
107
108    static CqFieldDefinition[] buildPath(CqRecordType rt,
109                                            String path) throws WvcmException
110    {
111        List<CqFieldDefinition> result = new ArrayList<CqFieldDefinition>();
112        if (rt.lookupProperty(CqRecordType.FIELD_DEFINITIONS) instanceof Exception)
113            rt = (CqRecordType) rt.doReadProperties(QUERY_RECORD_TYPE_PROPS);
114        for (String name : path.split("\\.")) {
115            if (rt == null)
116                throw new IllegalArgumentException("Field preceeding " + name
117                    + " does not reference a record");
118            CqFieldDefinition def = find(rt, name);
119            result.add(def);
120            rt = null;
121            switch (def.getFieldType()) {
122            case RESOURCE:
123            case RESOURCE_LIST:
124                rt =
125                    (CqRecordType) def.getReferencedRecordType()
126                        .doReadProperties(QUERY_RECORD_TYPE_PROPS);
127            }
128        }
129        return result.toArray(new CqFieldDefinition[result.size()]);
130    }
131
132    static CqFieldDefinition find(CqRecordType rt,
133                                   String name) throws WvcmException
134    {
135        for (CqFieldDefinition fieldDef : rt.getFieldDefinitions())
136            if (fieldDef.getDisplayName().compareToIgnoreCase(name) == 0)
137                return fieldDef;
138        throw new IllegalArgumentException("'" + name + "' is not a field ");
139    }
140
141    private static final PropertyRequest FIELD_DEFN_PROPS = new PropertyRequest(StpResource.DISPLAY_NAME, CqFieldDefinition.VALUE_TYPE, CqFieldDefinition.FIELD_TYPE, CqFieldDefinition.REFERENCED_RECORD_TYPE);
142
143    private static final PropertyRequest QUERY_RECORD_TYPE_PROPS = new PropertyRequest(StpResource.DISPLAY_NAME, CqRecordType.FIELD_DEFINITIONS.nest(FIELD_DEFN_PROPS));
144
145    static StpProvider.StpCallback g_callback = new StpProvider.StpCallback()
146    {
147        public Authentication getAuthenticationEx(Domain domain,
148                                                  String realm,
149                                                  int retryCount,
150                                                  StpProvider provider,
151                                                  WvcmException failure) throws WvcmException
152        {
153            if (m_unpw != null && retryCount == 0)
154                return m_unpw;
155            String title = "Enter " + domain + " Username '+' Password for " + realm + " [" + retryCount + "]";
156            if (failure != null)
157                title = "Login failed: " + failure + "\n" + title;
158            String unpw = JOptionPane.showInputDialog(title, "admin+");
159            if (unpw == null || unpw.length() == 0)
160                throw new IllegalAccessError("User canceled request");
161            return m_unpw = unpw.equals("anonymous")? null : new UnPw(unpw);
162        }
163
164        public Authentication getAuthentication(String r,
165                                                int c)
166        {
167            return null;
168        }
169
170        private UnPw m_unpw;
171    };
172
173    /**
174     * A simple Authentication object in which the username and password
175     * obtained from the user is cached for use by the CM API.
176     */
177    static class UnPw implements CcProvider.CcAuthentication {
178        /**
179         * Constructs an Authentication object
180         * 
181         * @param unpw A String containing username+password.
182         */
183        UnPw(String unpw) {  m_data = unpw.split("\\+", -2); }
184
185        public String loginName() { return m_data[0]; }
186        public String password() { return m_data.length > 1 ? m_data[1] : ""; };
187        public String getPrimaryGroupName() {  return m_data.length > 2 ? m_data[2] : ""; }
188
189        /* (non-Javadoc)
190         * @see com.ibm.rational.wvcm.stp.cc.CcProvider.CcAuthentication#getGroupList()
191         */
192        public List<String> getGroupList()
193        {
194            return null;
195        }
196
197        /** The cached credentials */
198        private String[] m_data;
199
200    }
201
202    static CqProvider g_provider;
203}